From 7f83f0700b3e66468308bef739e826546af97585 Mon Sep 17 00:00:00 2001 From: Phantom Date: Wed, 22 Oct 2025 17:34:23 +0800 Subject: [PATCH] chore: migrate from openai to @cherrystudio/openai package (#10802) * build: replace openai package with @cherrystudio/openai Update all imports from 'openai' to '@cherrystudio/openai' and remove the yarn patch * refactor(OpenAIResponseAPIClient): simplify token estimation logic for function call output Consolidate token estimation by first concatenating all output parts into a single string before counting tokens. This improves maintainability and handles additional output types consistently. --- .../openai-npm-5.12.2-30b075401c.patch | Bin 22280 -> 0 bytes package.json | 6 +-- scripts/auto-translate-i18n.ts | 2 +- scripts/update-i18n.ts | 2 +- src/main/apiServer/routes/chat.ts | 2 +- .../apiServer/services/chat-completion.ts | 4 +- src/main/services/remotefile/OpenAIService.ts | 2 +- .../clients/cherryai/CherryAiAPIClient.ts | 2 +- .../legacy/clients/openai/OpenAIApiClient.ts | 8 +++- .../legacy/clients/openai/OpenAIBaseClient.ts | 2 +- .../clients/openai/OpenAIResponseAPIClient.ts | 26 +++++++++++-- .../aiCore/legacy/clients/ovms/OVMSClient.ts | 2 +- .../legacy/clients/ppio/PPIOAPIClient.ts | 2 +- .../src/aiCore/legacy/clients/types.ts | 2 +- .../legacy/clients/zhipu/ZhipuAPIClient.ts | 2 +- .../feat/ImageGenerationMiddleware.ts | 4 +- .../src/aiCore/prepareParams/fileProcessor.ts | 2 +- src/renderer/src/config/models/utils.ts | 2 +- src/renderer/src/config/tools.ts | 2 +- .../src/services/ModelMessageService.ts | 2 +- .../src/services/SpanManagerService.ts | 2 +- .../src/services/__tests__/ApiService.test.ts | 4 +- .../__tests__/ModelMessageService.test.ts | 2 +- src/renderer/src/store/messageBlock.ts | 2 +- .../src/trace/dataHandler/StreamHandler.ts | 4 +- src/renderer/src/types/file.ts | 2 +- src/renderer/src/types/index.ts | 2 +- src/renderer/src/types/newMessage.ts | 2 +- src/renderer/src/types/sdk.ts | 6 +-- src/renderer/src/utils/mcp-tools.ts | 14 +++---- yarn.lock | 36 +++++++++--------- 31 files changed, 88 insertions(+), 64 deletions(-) delete mode 100644 .yarn/patches/openai-npm-5.12.2-30b075401c.patch diff --git a/.yarn/patches/openai-npm-5.12.2-30b075401c.patch b/.yarn/patches/openai-npm-5.12.2-30b075401c.patch deleted file mode 100644 index 29b92dcc7be2609f9044c4e170da87ab111c71f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22280 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 ({ diff --git a/src/renderer/src/services/__tests__/ModelMessageService.test.ts b/src/renderer/src/services/__tests__/ModelMessageService.test.ts index 0527e0c3cb..4017f028ce 100644 --- a/src/renderer/src/services/__tests__/ModelMessageService.test.ts +++ b/src/renderer/src/services/__tests__/ModelMessageService.test.ts @@ -1,5 +1,5 @@ +import { ChatCompletionMessageParam } from '@cherrystudio/openai/resources' import type { Model } from '@renderer/types' -import { ChatCompletionMessageParam } from 'openai/resources' import { describe, expect, it } from 'vitest' import { processReqMessages } from '../ModelMessageService' diff --git a/src/renderer/src/store/messageBlock.ts b/src/renderer/src/store/messageBlock.ts index 458956e38c..cddb8dcd68 100644 --- a/src/renderer/src/store/messageBlock.ts +++ b/src/renderer/src/store/messageBlock.ts @@ -1,10 +1,10 @@ import { WebSearchResultBlock } from '@anthropic-ai/sdk/resources' +import type OpenAI from '@cherrystudio/openai' import type { GroundingMetadata } from '@google/genai' import { createEntityAdapter, createSelector, createSlice, type PayloadAction } from '@reduxjs/toolkit' import { AISDKWebSearchResult, Citation, WebSearchProviderResponse, WebSearchSource } from '@renderer/types' import type { CitationMessageBlock, MessageBlock } from '@renderer/types/newMessage' import { MessageBlockType } from '@renderer/types/newMessage' -import type OpenAI from 'openai' import type { RootState } from './index' // 确认 RootState 从 store/index.ts 导出 diff --git a/src/renderer/src/trace/dataHandler/StreamHandler.ts b/src/renderer/src/trace/dataHandler/StreamHandler.ts index 5d6fb01c55..c071bdacde 100644 --- a/src/renderer/src/trace/dataHandler/StreamHandler.ts +++ b/src/renderer/src/trace/dataHandler/StreamHandler.ts @@ -1,8 +1,8 @@ +import { OpenAI } from '@cherrystudio/openai' +import { Stream } from '@cherrystudio/openai/streaming' import { TokenUsage } from '@mcp-trace/trace-core' import { Span } from '@opentelemetry/api' import { endSpan } from '@renderer/services/SpanManagerService' -import { OpenAI } from 'openai' -import { Stream } from 'openai/streaming' export class StreamHandler { private topicId: string diff --git a/src/renderer/src/types/file.ts b/src/renderer/src/types/file.ts index 76d1c0df14..8591c18119 100644 --- a/src/renderer/src/types/file.ts +++ b/src/renderer/src/types/file.ts @@ -1,6 +1,6 @@ +import type OpenAI from '@cherrystudio/openai' import type { File } from '@google/genai' import type { FileSchema } from '@mistralai/mistralai/models/components' -import type OpenAI from 'openai' export type RemoteFile = | { diff --git a/src/renderer/src/types/index.ts b/src/renderer/src/types/index.ts index ac57f9d89a..e8a8d333fd 100644 --- a/src/renderer/src/types/index.ts +++ b/src/renderer/src/types/index.ts @@ -1,7 +1,7 @@ import type { LanguageModelV2Source } from '@ai-sdk/provider' import type { WebSearchResultBlock } from '@anthropic-ai/sdk/resources' +import type OpenAI from '@cherrystudio/openai' import type { GenerateImagesConfig, GroundingMetadata, PersonGeneration } from '@google/genai' -import type OpenAI from 'openai' import type { CSSProperties } from 'react' export * from './file' diff --git a/src/renderer/src/types/newMessage.ts b/src/renderer/src/types/newMessage.ts index a24462b19f..4d0aa72f50 100644 --- a/src/renderer/src/types/newMessage.ts +++ b/src/renderer/src/types/newMessage.ts @@ -1,5 +1,5 @@ +import type { CompletionUsage } from '@cherrystudio/openai/resources' import type { ProviderMetadata } from 'ai' -import type { CompletionUsage } from 'openai/resources' import type { Assistant, diff --git a/src/renderer/src/types/sdk.ts b/src/renderer/src/types/sdk.ts index e18891f2bf..996d725cb7 100644 --- a/src/renderer/src/types/sdk.ts +++ b/src/renderer/src/types/sdk.ts @@ -11,6 +11,9 @@ import { MessageStream } from '@anthropic-ai/sdk/resources/messages/messages' import AnthropicVertex from '@anthropic-ai/vertex-sdk' import type { BedrockClient } from '@aws-sdk/client-bedrock' import type { BedrockRuntimeClient } from '@aws-sdk/client-bedrock-runtime' +import OpenAI, { AzureOpenAI } from '@cherrystudio/openai' +import { ChatCompletionContentPartImage } from '@cherrystudio/openai/resources' +import { Stream } from '@cherrystudio/openai/streaming' import { Content, CreateChatParameters, @@ -21,9 +24,6 @@ import { SendMessageParameters, Tool } from '@google/genai' -import OpenAI, { AzureOpenAI } from 'openai' -import { ChatCompletionContentPartImage } from 'openai/resources' -import { Stream } from 'openai/streaming' import { EndpointType } from './index' diff --git a/src/renderer/src/utils/mcp-tools.ts b/src/renderer/src/utils/mcp-tools.ts index 6914868d48..934d4d8824 100644 --- a/src/renderer/src/utils/mcp-tools.ts +++ b/src/renderer/src/utils/mcp-tools.ts @@ -1,4 +1,11 @@ import { ContentBlockParam, MessageParam, ToolUnion, ToolUseBlock } from '@anthropic-ai/sdk/resources' +import OpenAI from '@cherrystudio/openai' +import { + ChatCompletionContentPart, + ChatCompletionMessageParam, + ChatCompletionMessageToolCall, + ChatCompletionTool +} from '@cherrystudio/openai/resources' import { Content, FunctionCall, Part, Tool, Type as GeminiSchemaType } from '@google/genai' import { loggerService } from '@logger' import { isFunctionCallingModel, isVisionModel } from '@renderer/config/models' @@ -21,13 +28,6 @@ import { ChunkType } from '@renderer/types/chunk' import { AwsBedrockSdkMessageParam, AwsBedrockSdkTool, AwsBedrockSdkToolCall } from '@renderer/types/sdk' import { t } from 'i18next' import { nanoid } from 'nanoid' -import OpenAI from 'openai' -import { - ChatCompletionContentPart, - ChatCompletionMessageParam, - ChatCompletionMessageToolCall, - ChatCompletionTool -} from 'openai/resources' import { isToolUseModeFunction } from './assistant' import { convertBase64ImageToAwsBedrockFormat } from './aws-bedrock-utils' diff --git a/yarn.lock b/yarn.lock index a634e71da1..672c4af35f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2677,6 +2677,23 @@ __metadata: languageName: unknown linkType: soft +"@cherrystudio/openai@npm:^6.5.0, openai@npm:@cherrystudio/openai@6.5.0": + version: 6.5.0 + resolution: "@cherrystudio/openai@npm:6.5.0" + peerDependencies: + ws: ^8.18.0 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + ws: + optional: true + zod: + optional: true + bin: + openai: bin/cli + checksum: 10c0/0f6cafb97aec17037d5ddcccc88e4b4a9c8de77a989a35bab2394b682a1a69e8a9343e8ee5eb8107d5c495970dbf3567642f154c033f7afc3bf078078666a92e + languageName: node + linkType: hard + "@chevrotain/cst-dts-gen@npm:11.0.3": version: 11.0.3 resolution: "@chevrotain/cst-dts-gen@npm:11.0.3" @@ -13860,6 +13877,7 @@ __metadata: "@cherrystudio/embedjs-ollama": "npm:^0.1.31" "@cherrystudio/embedjs-openai": "npm:^0.1.31" "@cherrystudio/extension-table-plus": "workspace:^" + "@cherrystudio/openai": "npm:^6.5.0" "@dnd-kit/core": "npm:^6.3.1" "@dnd-kit/modifiers": "npm:^9.0.0" "@dnd-kit/sortable": "npm:^10.0.0" @@ -14041,7 +14059,6 @@ __metadata: notion-helper: "npm:^1.3.22" npx-scope-finder: "npm:^1.2.0" officeparser: "npm:^4.2.0" - openai: "patch:openai@npm%3A5.12.2#~/.yarn/patches/openai-npm-5.12.2-30b075401c.patch" os-proxy-config: "npm:^1.1.2" oxlint: "npm:^1.22.0" oxlint-tsgolint: "npm:^0.2.0" @@ -23907,23 +23924,6 @@ __metadata: languageName: node linkType: hard -"openai@patch:openai@npm%3A5.12.2#~/.yarn/patches/openai-npm-5.12.2-30b075401c.patch": - version: 5.12.2 - resolution: "openai@patch:openai@npm%3A5.12.2#~/.yarn/patches/openai-npm-5.12.2-30b075401c.patch::version=5.12.2&hash=ad5d10" - peerDependencies: - ws: ^8.18.0 - zod: ^3.23.8 - peerDependenciesMeta: - ws: - optional: true - zod: - optional: true - bin: - openai: bin/cli - checksum: 10c0/2964a1c88a98cf169c9b73e8cd6776c03c8f3103fee30961c6953e5d995ad57a697e2179615999356809349186df6496abae105928ff7ce0229e5016dec87cb3 - languageName: node - linkType: hard - "openapi-types@npm:^12.1.3": version: 12.1.3 resolution: "openapi-types@npm:12.1.3"