From 523633b5d6d6ec08751ef68f3627538274deb4a6 Mon Sep 17 00:00:00 2001 From: echoVic <137844255@qq.com> Date: Sat, 14 Mar 2026 09:31:25 +0800 Subject: [PATCH] feat(cli): add native openai provider support --- packages/cli/package.json | 1 + packages/cli/src/config/types.ts | 1 + .../cli/src/services/VercelAIChatService.ts | 10 ++++++ .../unit/context/ContextAssembler.test.ts | 17 +++++---- pnpm-lock.yaml | 36 +++++++++++++++++++ 5 files changed, 56 insertions(+), 9 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 299e3d1f..02298f60 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -62,6 +62,7 @@ "@ai-sdk/azure": "^3.0.5", "@ai-sdk/deepseek": "^2.0.4", "@ai-sdk/google": "^3.0.4", + "@ai-sdk/openai": "^3.0.26", "@ai-sdk/openai-compatible": "^2.0.4", "@inkjs/ui": "^2.0.0", "@modelcontextprotocol/sdk": "^1.17.4", diff --git a/packages/cli/src/config/types.ts b/packages/cli/src/config/types.ts index dd1e4d81..70ce5447 100644 --- a/packages/cli/src/config/types.ts +++ b/packages/cli/src/config/types.ts @@ -4,6 +4,7 @@ */ export type ProviderType = + | 'openai' | 'openai-compatible' | 'anthropic' | 'gemini' diff --git a/packages/cli/src/services/VercelAIChatService.ts b/packages/cli/src/services/VercelAIChatService.ts index c67d64e1..d76a7c42 100644 --- a/packages/cli/src/services/VercelAIChatService.ts +++ b/packages/cli/src/services/VercelAIChatService.ts @@ -2,6 +2,7 @@ import { createAnthropic } from '@ai-sdk/anthropic'; import { createAzure } from '@ai-sdk/azure'; import { createDeepSeek } from '@ai-sdk/deepseek'; import { createGoogleGenerativeAI } from '@ai-sdk/google'; +import { createOpenAI } from '@ai-sdk/openai'; import { createOpenAICompatible } from '@ai-sdk/openai-compatible'; import { generateText, jsonSchema, type LanguageModel, streamText } from 'ai'; import type { ChatCompletionMessageToolCall } from 'openai/resources/chat'; @@ -90,6 +91,15 @@ export class VercelAIChatService implements IChatService { const { provider, apiKey, baseUrl, model, customHeaders, providerId, apiVersion } = config; switch (provider) { + case 'openai': { + const openai = createOpenAI({ + apiKey, + baseURL: baseUrl || undefined, + headers: customHeaders, + }); + return openai(model); + } + case 'anthropic': { const anthropic = createAnthropic({ apiKey, diff --git a/packages/cli/tests/unit/context/ContextAssembler.test.ts b/packages/cli/tests/unit/context/ContextAssembler.test.ts index d9c26ce7..f5d5b5b2 100644 --- a/packages/cli/tests/unit/context/ContextAssembler.test.ts +++ b/packages/cli/tests/unit/context/ContextAssembler.test.ts @@ -8,16 +8,15 @@ import type { SessionEvent } from '../../../src/context/types.js'; // Helper: 创建基础事件字段 const base = ( - type: string, - sessionId = 'sess-1', - timestamp = '2026-02-21T10:00:00.000Z' + type: string, + sessionId = 'sess-1', + timestamp = '2026-02-21T10:00:00.000Z' ): Omit => ({ - id: `evt-${Math.random().toString(36).slice(2, 8)}`, - sessionId, - timestamp, - type: type as any, - cwd: '/tmp/test', - version: '1.0.0', + id: `evt-${Math.random().toString(36).slice(2, 8)}`, + sessionId, + timestamp, + cwd: '/tmp/test', + version: '1.0.0', }); function sessionCreatedEvent(sessionId = 'sess-1', ts = '2026-02-21T10:00:00.000Z'): SessionEvent { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1204da55..967912af 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,9 @@ importers: '@ai-sdk/google': specifier: ^3.0.4 version: 3.0.4(zod@3.25.76) + '@ai-sdk/openai': + specifier: ^3.0.26 + version: 3.0.41(zod@3.25.76) '@ai-sdk/openai-compatible': specifier: ^2.0.4 version: 2.0.4(zod@3.25.76) @@ -368,12 +371,24 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/openai@3.0.41': + resolution: {integrity: sha512-IZ42A+FO+vuEQCVNqlnAPYQnnUpUfdJIwn1BEDOBywiEHa23fw7PahxVtlX9zm3/zMvTW4JKPzWyvAgDu+SQ2A==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/openai@3.0.5': resolution: {integrity: sha512-tMdpwI+kV9gZ/USSN8PaHQItaq5B80cq8iwV8ulG3juaQ35ksTHMH5oDbf3vKVRFQwY9024iO2MsV+7bau3u3w==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/provider-utils@4.0.19': + resolution: {integrity: sha512-3eG55CrSWCu2SXlqq2QCsFjo3+E7+Gmg7i/oRVoSZzIodTuDSfLb3MRje67xE9RFea73Zao7Lm4mADIfUETKGg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/provider-utils@4.0.4': resolution: {integrity: sha512-VxhX0B/dWGbpNHxrKCWUAJKXIXV015J4e7qYjdIU9lLWeptk0KMLGcqkB4wFxff5Njqur8dt8wRi1MN9lZtDqg==} engines: {node: '>=18'} @@ -394,6 +409,10 @@ packages: resolution: {integrity: sha512-5KXyBOSEX+l67elrEa+wqo/LSsSTtrPj9Uoh3zMbe/ceQX4ucHI3b9nUEfNkGF3Ry1svv90widAt+aiKdIJasQ==} engines: {node: '>=18'} + '@ai-sdk/provider@3.0.8': + resolution: {integrity: sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ==} + engines: {node: '>=18'} + '@alcalzone/ansi-tokenize@0.2.2': resolution: {integrity: sha512-mkOh+Wwawzuf5wa30bvc4nA+Qb6DIrGWgBhRR/Pw4T9nsgYait8izvXkNyU78D6Wcu3Z+KUdwCmLCxlWjEotYA==} engines: {node: '>=18'} @@ -4559,12 +4578,25 @@ snapshots: '@ai-sdk/provider-utils': 4.0.4(zod@3.25.76) zod: 3.25.76 + '@ai-sdk/openai@3.0.41(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 3.0.8 + '@ai-sdk/provider-utils': 4.0.19(zod@3.25.76) + zod: 3.25.76 + '@ai-sdk/openai@3.0.5(zod@3.25.76)': dependencies: '@ai-sdk/provider': 3.0.2 '@ai-sdk/provider-utils': 4.0.4(zod@3.25.76) zod: 3.25.76 + '@ai-sdk/provider-utils@4.0.19(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 3.0.8 + '@standard-schema/spec': 1.1.0 + eventsource-parser: 3.0.6 + zod: 3.25.76 + '@ai-sdk/provider-utils@4.0.4(zod@3.25.76)': dependencies: '@ai-sdk/provider': 3.0.2 @@ -4587,6 +4619,10 @@ snapshots: dependencies: json-schema: 0.4.0 + '@ai-sdk/provider@3.0.8': + dependencies: + json-schema: 0.4.0 + '@alcalzone/ansi-tokenize@0.2.2': dependencies: ansi-styles: 6.2.3