From 83d415c0b843839badc1d2181c3505fded7a0da8 Mon Sep 17 00:00:00 2001 From: Boyuan Gao Date: Tue, 29 Jul 2025 16:39:33 +0800 Subject: [PATCH 1/4] fix: i18n --- packages/types/src/codebase-index.ts | 1 + packages/types/src/provider-settings.ts | 8 ++ packages/types/src/providers/doubao.ts | 44 +++++++++ packages/types/src/providers/index.ts | 1 + src/api/index.ts | 3 + src/api/providers/doubao.ts | 93 +++++++++++++++++++ src/api/providers/index.ts | 1 + src/services/code-index/constants/index.ts | 3 + src/services/code-index/embedders/doubao.ts | 76 +++++++++++++++ src/services/code-index/embedders/index.ts | 6 ++ .../code-index/interfaces/embedder.ts | 2 +- src/shared/embeddingModels.ts | 2 +- .../src/components/settings/ApiOptions.tsx | 7 ++ .../src/components/settings/constants.ts | 3 + .../components/settings/providers/Doubao.tsx | 52 +++++++++++ .../components/settings/providers/index.ts | 1 + .../components/ui/hooks/useSelectedModel.ts | 7 ++ .../src/context/ExtensionStateContext.tsx | 4 +- webview-ui/src/i18n/locales/ca/settings.json | 2 + webview-ui/src/i18n/locales/de/settings.json | 2 + webview-ui/src/i18n/locales/en/settings.json | 2 + webview-ui/src/i18n/locales/es/settings.json | 2 + webview-ui/src/i18n/locales/fr/settings.json | 2 + webview-ui/src/i18n/locales/hi/settings.json | 2 + webview-ui/src/i18n/locales/id/settings.json | 2 + webview-ui/src/i18n/locales/it/settings.json | 2 + webview-ui/src/i18n/locales/ja/settings.json | 2 + webview-ui/src/i18n/locales/ko/settings.json | 2 + webview-ui/src/i18n/locales/nl/settings.json | 2 + webview-ui/src/i18n/locales/pl/settings.json | 2 + .../src/i18n/locales/pt-BR/settings.json | 2 + webview-ui/src/i18n/locales/ru/settings.json | 2 + webview-ui/src/i18n/locales/tr/settings.json | 2 + webview-ui/src/i18n/locales/vi/settings.json | 2 + .../src/i18n/locales/zh-CN/settings.json | 2 + .../src/i18n/locales/zh-TW/settings.json | 2 + 36 files changed, 346 insertions(+), 4 deletions(-) create mode 100644 packages/types/src/providers/doubao.ts create mode 100644 src/api/providers/doubao.ts create mode 100644 src/services/code-index/embedders/doubao.ts create mode 100644 src/services/code-index/embedders/index.ts create mode 100644 webview-ui/src/components/settings/providers/Doubao.tsx diff --git a/packages/types/src/codebase-index.ts b/packages/types/src/codebase-index.ts index 89d5b168d78..a2aa863cd3a 100644 --- a/packages/types/src/codebase-index.ts +++ b/packages/types/src/codebase-index.ts @@ -48,6 +48,7 @@ export const codebaseIndexModelsSchema = z.object({ "openai-compatible": z.record(z.string(), z.object({ dimension: z.number() })).optional(), gemini: z.record(z.string(), z.object({ dimension: z.number() })).optional(), mistral: z.record(z.string(), z.object({ dimension: z.number() })).optional(), + doubao: z.record(z.string(), z.object({ dimension: z.number() })).optional(), }) export type CodebaseIndexModels = z.infer diff --git a/packages/types/src/provider-settings.ts b/packages/types/src/provider-settings.ts index 23cbd711d29..e13dc9d6397 100644 --- a/packages/types/src/provider-settings.ts +++ b/packages/types/src/provider-settings.ts @@ -24,6 +24,7 @@ export const providerNames = [ "mistral", "moonshot", "deepseek", + "doubao", "unbound", "requesty", "human-relay", @@ -194,6 +195,11 @@ const deepSeekSchema = apiModelIdProviderModelSchema.extend({ deepSeekApiKey: z.string().optional(), }) +const doubaoSchema = apiModelIdProviderModelSchema.extend({ + doubaoBaseUrl: z.string().optional(), + doubaoApiKey: z.string().optional(), +}) + const moonshotSchema = apiModelIdProviderModelSchema.extend({ moonshotBaseUrl: z .union([z.literal("https://api.moonshot.ai/v1"), z.literal("https://api.moonshot.cn/v1")]) @@ -266,6 +272,7 @@ export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProv openAiNativeSchema.merge(z.object({ apiProvider: z.literal("openai-native") })), mistralSchema.merge(z.object({ apiProvider: z.literal("mistral") })), deepSeekSchema.merge(z.object({ apiProvider: z.literal("deepseek") })), + doubaoSchema.merge(z.object({ apiProvider: z.literal("doubao") })), moonshotSchema.merge(z.object({ apiProvider: z.literal("moonshot") })), unboundSchema.merge(z.object({ apiProvider: z.literal("unbound") })), requestySchema.merge(z.object({ apiProvider: z.literal("requesty") })), @@ -297,6 +304,7 @@ export const providerSettingsSchema = z.object({ ...openAiNativeSchema.shape, ...mistralSchema.shape, ...deepSeekSchema.shape, + ...doubaoSchema.shape, ...moonshotSchema.shape, ...unboundSchema.shape, ...requestySchema.shape, diff --git a/packages/types/src/providers/doubao.ts b/packages/types/src/providers/doubao.ts new file mode 100644 index 00000000000..f948450bc42 --- /dev/null +++ b/packages/types/src/providers/doubao.ts @@ -0,0 +1,44 @@ +import type { ModelInfo } from "../model.js" + +export const doubaoDefaultModelId = "doubao-seed-1-6-250615" + +export const doubaoModels = { + "doubao-seed-1-6-250615": { + maxTokens: 32_768, + contextWindow: 128_000, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 0.0001, // $0.0001 per million tokens (cache miss) + outputPrice: 0.0004, // $0.0004 per million tokens + cacheWritesPrice: 0.0001, // $0.0001 per million tokens (cache miss) + cacheReadsPrice: 0.00002, // $0.00002 per million tokens (cache hit) + description: `Doubao Seed 1.6 is a powerful model designed for high-performance tasks with extensive context handling.`, + }, + "doubao-seed-1-6-thinking-250715": { + maxTokens: 32_768, + contextWindow: 128_000, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 0.0002, // $0.0002 per million tokens + outputPrice: 0.0008, // $0.0008 per million tokens + cacheWritesPrice: 0.0002, // $0.0002 per million + cacheReadsPrice: 0.00004, // $0.00004 per million tokens (cache hit) + description: `Doubao Seed 1.6 Thinking is optimized for reasoning tasks, providing enhanced performance in complex problem-solving scenarios.`, + }, + "doubao-seed-1-6-flash-250715": { + maxTokens: 32_768, + contextWindow: 128_000, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 0.00015, // $0.00015 per million tokens + outputPrice: 0.0006, // $0.0006 per million tokens + cacheWritesPrice: 0.00015, // $0.00015 per million + cacheReadsPrice: 0.00003, // $0.00003 per million tokens (cache hit) + description: `Doubao Seed 1.6 Flash is tailored for speed and efficiency, making it ideal for applications requiring rapid responses.`, + }, +} as const satisfies Record + +export const doubaoDefaultModelInfo: ModelInfo = doubaoModels[doubaoDefaultModelId] + +export const DOUBAO_API_BASE_URL = "https://ark.cn-beijing.volces.com/api/v3" +export const DOUBAO_API_CHAT_PATH = "/chat/completions" diff --git a/packages/types/src/providers/index.ts b/packages/types/src/providers/index.ts index 2e9a2a74a27..d6676b885a9 100644 --- a/packages/types/src/providers/index.ts +++ b/packages/types/src/providers/index.ts @@ -20,3 +20,4 @@ export * from "./unbound.js" export * from "./vertex.js" export * from "./vscode-llm.js" export * from "./xai.js" +export * from "./doubao.js" diff --git a/src/api/index.ts b/src/api/index.ts index 1e9d2f6e595..f726063a82b 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -31,6 +31,7 @@ import { LiteLLMHandler, ClaudeCodeHandler, SambaNovaHandler, + DoubaoHandler, } from "./providers" export interface SingleCompletionHandler { @@ -92,6 +93,8 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler { return new OpenAiNativeHandler(options) case "deepseek": return new DeepSeekHandler(options) + case "doubao": + return new DoubaoHandler(options) case "moonshot": return new MoonshotHandler(options) case "vscode-lm": diff --git a/src/api/providers/doubao.ts b/src/api/providers/doubao.ts new file mode 100644 index 00000000000..84fd8e7c77d --- /dev/null +++ b/src/api/providers/doubao.ts @@ -0,0 +1,93 @@ +import { OpenAiHandler } from "./openai" +import type { ApiHandlerOptions } from "../../shared/api" +import { DOUBAO_API_BASE_URL, doubaoDefaultModelId, doubaoModels } from "@roo-code/types" +import { getModelParams } from "../transform/model-params" +import { ApiStreamUsageChunk } from "../transform/stream" + +// by a fan of Doubao, his name on Github is AntiMoron. +// Core types for Doubao API +interface ChatCompletionMessageParam { + role: "system" | "user" | "assistant" | "developer" + content: + | string + | Array<{ + type: "text" | "image_url" + text?: string + image_url?: { url: string } + }> +} + +interface ChatCompletionParams { + model: string + messages: ChatCompletionMessageParam[] + temperature?: number + stream?: boolean + stream_options?: { include_usage: boolean } + max_completion_tokens?: number +} + +interface ChatCompletion { + choices: Array<{ + message: { + content: string + } + }> + usage?: { + prompt_tokens: number + completion_tokens: number + } +} + +interface ChatCompletionChunk { + choices: Array<{ + delta: { + content?: string + } + }> + usage?: { + prompt_tokens: number + completion_tokens: number + } +} + +// interface ApiHandlerOptions { +// doubaoBaseUrl?: string +// doubaoApiKey?: string +// doubaoHeaders?: Record +// doubaoModelId?: string +// doubaoStreamingEnabled?: boolean +// modelTemperature?: number +// includeMaxTokens?: boolean +// modelMaxTokens?: number +// } + +export class DoubaoHandler extends OpenAiHandler { + constructor(options: ApiHandlerOptions) { + super({ + ...options, + openAiApiKey: options.doubaoApiKey ?? "not-provided", + openAiModelId: options.apiModelId ?? doubaoDefaultModelId, + openAiBaseUrl: options.doubaoBaseUrl ?? DOUBAO_API_BASE_URL, + openAiStreamingEnabled: true, + includeMaxTokens: true, + }) + } + + override getModel() { + const id = this.options.apiModelId ?? doubaoDefaultModelId + const info = doubaoModels[id as keyof typeof doubaoModels] || doubaoModels[doubaoDefaultModelId] + const params = getModelParams({ format: "openai", modelId: id, model: info, settings: this.options }) + return { id, info, ...params } + } + + // Override to handle Doubao's usage metrics, including caching. + protected override processUsageMetrics(usage: any): ApiStreamUsageChunk { + return { + type: "usage", + inputTokens: usage?.prompt_tokens || 0, + outputTokens: usage?.completion_tokens || 0, + cacheWriteTokens: usage?.prompt_tokens_details?.cache_miss_tokens, + cacheReadTokens: usage?.prompt_tokens_details?.cached_tokens, + } + } +} diff --git a/src/api/providers/index.ts b/src/api/providers/index.ts index e49dc55c76a..7b35e02f15f 100644 --- a/src/api/providers/index.ts +++ b/src/api/providers/index.ts @@ -4,6 +4,7 @@ export { AwsBedrockHandler } from "./bedrock" export { ChutesHandler } from "./chutes" export { ClaudeCodeHandler } from "./claude-code" export { DeepSeekHandler } from "./deepseek" +export { DoubaoHandler } from "./doubao" export { MoonshotHandler } from "./moonshot" export { FakeAIHandler } from "./fake-ai" export { GeminiHandler } from "./gemini" diff --git a/src/services/code-index/constants/index.ts b/src/services/code-index/constants/index.ts index 6f0e0fe7e62..979b8d61dab 100644 --- a/src/services/code-index/constants/index.ts +++ b/src/services/code-index/constants/index.ts @@ -29,3 +29,6 @@ export const BATCH_PROCESSING_CONCURRENCY = 10 /**Gemini Embedder */ export const GEMINI_MAX_ITEM_TOKENS = 2048 + +/**Doubao Embedder */ +export const DOUBAO_MAX_ITEM_TOKENS = 2048 diff --git a/src/services/code-index/embedders/doubao.ts b/src/services/code-index/embedders/doubao.ts new file mode 100644 index 00000000000..7cd90e504c2 --- /dev/null +++ b/src/services/code-index/embedders/doubao.ts @@ -0,0 +1,76 @@ +import { OpenAICompatibleEmbedder } from "./openai-compatible" +import { IEmbedder, EmbeddingResponse, EmbedderInfo } from "../interfaces/embedder" +import { t } from "../../../i18n" +import { TelemetryEventName } from "@roo-code/types" +import { TelemetryService } from "@roo-code/telemetry" +import { DOUBAO_MAX_ITEM_TOKENS } from "../constants" + +export class DoubaoEmbedder implements IEmbedder { + private readonly openAICompatibleEmbedder: OpenAICompatibleEmbedder + private static readonly Doubao_BASE_URL = "https://ark.cn-beijing.volces.com/api/v3/" + private static readonly DEFAULT_MODEL = "doubao-embedding-text-240515" + private readonly modelId: string + + constructor(apiKey: string, modelId?: string) { + if (!apiKey) { + throw new Error(t("embeddings:validation.apiKeyRequired")) + } + + // Use provided model or default + this.modelId = modelId || DoubaoEmbedder.DEFAULT_MODEL + + // Create an OpenAI Compatible embedder with Doubao's configuration + this.openAICompatibleEmbedder = new OpenAICompatibleEmbedder( + DoubaoEmbedder.Doubao_BASE_URL, + apiKey, + this.modelId, + DOUBAO_MAX_ITEM_TOKENS, + ) + } + + /** + * Creates embeddings for the given texts using Doubao's embedding API + * @param texts Array of text strings to embed + * @param model Optional model identifier (uses constructor model if not provided) + * @returns Promise resolving to embedding response + */ + async createEmbeddings(texts: string[], model?: string): Promise { + try { + // Use the provided model or fall back to the instance's model + const modelToUse = model || this.modelId + return await this.openAICompatibleEmbedder.createEmbeddings(texts, modelToUse) + } catch (error) { + TelemetryService.instance.captureEvent(TelemetryEventName.CODE_INDEX_ERROR, { + error: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + location: "DoubaoEmbedder:createEmbeddings", + }) + throw error + } + } + + /** + * Validates the Doubao embedder configuration by delegating to the underlying OpenAI-compatible embedder + * @returns Promise resolving to validation result with success status and optional error message + */ + async validateConfiguration(): Promise<{ valid: boolean; error?: string }> { + try { + // Delegate validation to the OpenAI-compatible embedder + // The error messages will be specific to Doubao since we're using Doubao's base URL + return await this.openAICompatibleEmbedder.validateConfiguration() + } catch (error) { + TelemetryService.instance.captureEvent(TelemetryEventName.CODE_INDEX_ERROR, { + error: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + location: "DoubaoEmbedder:validateConfiguration", + }) + throw error + } + } + + get embedderInfo(): EmbedderInfo { + return { + name: "doubao", + } + } +} diff --git a/src/services/code-index/embedders/index.ts b/src/services/code-index/embedders/index.ts new file mode 100644 index 00000000000..f30b76815f2 --- /dev/null +++ b/src/services/code-index/embedders/index.ts @@ -0,0 +1,6 @@ +export * from "./openai-compatible" +export * from "./openai" +export * from "./ollama" +export * from "./gemini" +export * from "./mistral" +export * from "./doubao" diff --git a/src/services/code-index/interfaces/embedder.ts b/src/services/code-index/interfaces/embedder.ts index c5653ea2b7e..dbfd208edda 100644 --- a/src/services/code-index/interfaces/embedder.ts +++ b/src/services/code-index/interfaces/embedder.ts @@ -28,7 +28,7 @@ export interface EmbeddingResponse { } } -export type AvailableEmbedders = "openai" | "ollama" | "openai-compatible" | "gemini" | "mistral" +export type AvailableEmbedders = "openai" | "ollama" | "openai-compatible" | "gemini" | "mistral" | "doubao" export interface EmbedderInfo { name: AvailableEmbedders diff --git a/src/shared/embeddingModels.ts b/src/shared/embeddingModels.ts index a3cd61e6593..eca8c2095c1 100644 --- a/src/shared/embeddingModels.ts +++ b/src/shared/embeddingModels.ts @@ -2,7 +2,7 @@ * Defines profiles for different embedding models, including their dimensions. */ -export type EmbedderProvider = "openai" | "ollama" | "openai-compatible" | "gemini" | "mistral" // Add other providers as needed +export type EmbedderProvider = "openai" | "ollama" | "openai-compatible" | "gemini" | "mistral" | "doubao" // Add other providers as needed export interface EmbeddingModelProfile { dimension: number diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index 486702a2f7b..5b9d90b3438 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -15,6 +15,7 @@ import { litellmDefaultModelId, openAiNativeDefaultModelId, anthropicDefaultModelId, + doubaoDefaultModelId, claudeCodeDefaultModelId, geminiDefaultModelId, deepSeekDefaultModelId, @@ -57,6 +58,7 @@ import { Chutes, ClaudeCode, DeepSeek, + Doubao, Gemini, Glama, Groq, @@ -292,6 +294,7 @@ const ApiOptions = ({ "openai-native": { field: "apiModelId", default: openAiNativeDefaultModelId }, gemini: { field: "apiModelId", default: geminiDefaultModelId }, deepseek: { field: "apiModelId", default: deepSeekDefaultModelId }, + doubao: { field: "apiModelId", default: doubaoDefaultModelId }, moonshot: { field: "apiModelId", default: moonshotDefaultModelId }, mistral: { field: "apiModelId", default: mistralDefaultModelId }, xai: { field: "apiModelId", default: xaiDefaultModelId }, @@ -475,6 +478,10 @@ const ApiOptions = ({ )} + {selectedProvider === "doubao" && ( + + )} + {selectedProvider === "moonshot" && ( )} diff --git a/webview-ui/src/components/settings/constants.ts b/webview-ui/src/components/settings/constants.ts index 7d07e41f460..b8aa84cb72f 100644 --- a/webview-ui/src/components/settings/constants.ts +++ b/webview-ui/src/components/settings/constants.ts @@ -14,6 +14,7 @@ import { groqModels, chutesModels, sambaNovaModels, + doubaoModels, } from "@roo-code/types" export const MODELS_BY_PROVIDER: Partial>> = { @@ -21,6 +22,7 @@ export const MODELS_BY_PROVIDER: Partial void +} + +export const Doubao = ({ apiConfiguration, setApiConfigurationField }: DoubaoProps) => { + const { t } = useAppTranslation() + + const handleInputChange = useCallback( + ( + field: K, + transform: (event: E) => ProviderSettings[K] = inputEventTransform, + ) => + (event: E | Event) => { + setApiConfigurationField(field, transform(event as E)) + }, + [setApiConfigurationField], + ) + + return ( + <> + + + +
+ {t("settings:providers.apiKeyStorageNotice")} +
+ {!apiConfiguration?.doubaoApiKey && ( + + {t("settings:providers.getDoubaoApiKey")} + + )} + + ) +} diff --git a/webview-ui/src/components/settings/providers/index.ts b/webview-ui/src/components/settings/providers/index.ts index 957edb79922..13420b26797 100644 --- a/webview-ui/src/components/settings/providers/index.ts +++ b/webview-ui/src/components/settings/providers/index.ts @@ -3,6 +3,7 @@ export { Bedrock } from "./Bedrock" export { Chutes } from "./Chutes" export { ClaudeCode } from "./ClaudeCode" export { DeepSeek } from "./DeepSeek" +export { Doubao } from "./Doubao" export { Gemini } from "./Gemini" export { Glama } from "./Glama" export { Groq } from "./Groq" diff --git a/webview-ui/src/components/ui/hooks/useSelectedModel.ts b/webview-ui/src/components/ui/hooks/useSelectedModel.ts index a6b76fbd7cf..6bda83ab94a 100644 --- a/webview-ui/src/components/ui/hooks/useSelectedModel.ts +++ b/webview-ui/src/components/ui/hooks/useSelectedModel.ts @@ -36,6 +36,8 @@ import { claudeCodeModels, sambaNovaModels, sambaNovaDefaultModelId, + doubaoModels, + doubaoDefaultModelId, } from "@roo-code/types" import type { RouterModels } from "@roo/api" @@ -176,6 +178,11 @@ function getSelectedModel({ const info = deepSeekModels[id as keyof typeof deepSeekModels] return { id, info } } + case "doubao": { + const id = apiConfiguration.apiModelId ?? doubaoDefaultModelId + const info = doubaoModels[id as keyof typeof doubaoModels] + return { id, info } + } case "moonshot": { const id = apiConfiguration.apiModelId ?? moonshotDefaultModelId const info = moonshotModels[id as keyof typeof moonshotModels] diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index b156d0193b4..87a941d214d 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -238,7 +238,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode codebaseIndexSearchMaxResults: undefined, codebaseIndexSearchMinScore: undefined, }, - codebaseIndexModels: { ollama: {}, openai: {} }, + codebaseIndexModels: { ollama: {}, openai: {}, doubao: {} }, alwaysAllowUpdateTodoList: true, includeDiagnosticMessages: true, maxDiagnosticMessages: 50, @@ -515,5 +515,5 @@ export const useExtensionState = () => { throw new Error("useExtensionState must be used within an ExtensionStateContextProvider") } - return context + return context as ExtensionStateContextType } diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index adde176b319..3da1f5e50e5 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -253,6 +253,8 @@ "getChutesApiKey": "Obtenir clau API de Chutes", "deepSeekApiKey": "Clau API de DeepSeek", "getDeepSeekApiKey": "Obtenir clau API de DeepSeek", + "doubaoApiKey": "Clau API de Doubao", + "getDoubaoApiKey": "Obtenir clau API de Doubao", "moonshotApiKey": "Clau API de Moonshot", "getMoonshotApiKey": "Obtenir clau API de Moonshot", "moonshotBaseUrl": "Punt d'entrada de Moonshot", diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 429f1ccb5cb..a96b41f0c35 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -225,6 +225,8 @@ "awsCustomArnDesc": "Stellen Sie sicher, dass die Region in der ARN mit Ihrer oben ausgewählten AWS-Region übereinstimmt.", "openRouterApiKey": "OpenRouter API-Schlüssel", "getOpenRouterApiKey": "OpenRouter API-Schlüssel erhalten", + "doubaoApiKey": "Doubao API-Schlüssel", + "getDoubaoApiKey": "Doubao API-Schlüssel erhalten", "apiKeyStorageNotice": "API-Schlüssel werden sicher im VSCode Secret Storage gespeichert", "glamaApiKey": "Glama API-Schlüssel", "getGlamaApiKey": "Glama API-Schlüssel erhalten", diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 93b184fc279..5f67268bd9c 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -253,6 +253,8 @@ "getChutesApiKey": "Get Chutes API Key", "deepSeekApiKey": "DeepSeek API Key", "getDeepSeekApiKey": "Get DeepSeek API Key", + "doubaoApiKey": "Doubao API Key", + "getDoubaoApiKey": "Get Doubao API Key", "moonshotApiKey": "Moonshot API Key", "getMoonshotApiKey": "Get Moonshot API Key", "moonshotBaseUrl": "Moonshot Entrypoint", diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index c56058dff5e..c4c7fb39c0f 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -253,6 +253,8 @@ "getChutesApiKey": "Obtener clave API de Chutes", "deepSeekApiKey": "Clave API de DeepSeek", "getDeepSeekApiKey": "Obtener clave API de DeepSeek", + "doubaoApiKey": "Clave API de Doubao", + "getDoubaoApiKey": "Obtener clave API de Doubao", "moonshotApiKey": "Clave API de Moonshot", "getMoonshotApiKey": "Obtener clave API de Moonshot", "moonshotBaseUrl": "Punto de entrada de Moonshot", diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 5ea19d71f9d..e00b0c05591 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -253,6 +253,8 @@ "getChutesApiKey": "Obtenir la clé API Chutes", "deepSeekApiKey": "Clé API DeepSeek", "getDeepSeekApiKey": "Obtenir la clé API DeepSeek", + "doubaoApiKey": "Clé API Doubao", + "getDoubaoApiKey": "Obtenir la clé API Doubao", "moonshotApiKey": "Clé API Moonshot", "getMoonshotApiKey": "Obtenir la clé API Moonshot", "moonshotBaseUrl": "Point d'entrée Moonshot", diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index 088b5234005..2497ffe6dad 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -253,6 +253,8 @@ "getChutesApiKey": "Chutes API कुंजी प्राप्त करें", "deepSeekApiKey": "DeepSeek API कुंजी", "getDeepSeekApiKey": "DeepSeek API कुंजी प्राप्त करें", + "doubaoApiKey": "डौबाओ API कुंजी", + "getDoubaoApiKey": "डौबाओ API कुंजी प्राप्त करें", "moonshotApiKey": "Moonshot API कुंजी", "getMoonshotApiKey": "Moonshot API कुंजी प्राप्त करें", "moonshotBaseUrl": "Moonshot प्रवेश बिंदु", diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index a8b8600c1bf..3665c99c1bf 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -257,6 +257,8 @@ "getChutesApiKey": "Dapatkan Chutes API Key", "deepSeekApiKey": "DeepSeek API Key", "getDeepSeekApiKey": "Dapatkan DeepSeek API Key", + "doubaoApiKey": "Kunci API Doubao", + "getDoubaoApiKey": "Dapatkan Kunci API Doubao", "moonshotApiKey": "Kunci API Moonshot", "getMoonshotApiKey": "Dapatkan Kunci API Moonshot", "moonshotBaseUrl": "Titik Masuk Moonshot", diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index b6eeeb65bf7..056b0f9124a 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -253,6 +253,8 @@ "getChutesApiKey": "Ottieni chiave API Chutes", "deepSeekApiKey": "Chiave API DeepSeek", "getDeepSeekApiKey": "Ottieni chiave API DeepSeek", + "doubaoApiKey": "Chiave API Doubao", + "getDoubaoApiKey": "Ottieni chiave API Doubao", "moonshotApiKey": "Chiave API Moonshot", "getMoonshotApiKey": "Ottieni chiave API Moonshot", "moonshotBaseUrl": "Punto di ingresso Moonshot", diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index ee81d1cef61..3b38277b866 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -253,6 +253,8 @@ "getChutesApiKey": "Chutes APIキーを取得", "deepSeekApiKey": "DeepSeek APIキー", "getDeepSeekApiKey": "DeepSeek APIキーを取得", + "doubaoApiKey": "Doubao APIキー", + "getDoubaoApiKey": "Doubao APIキーを取得", "moonshotApiKey": "Moonshot APIキー", "getMoonshotApiKey": "Moonshot APIキーを取得", "moonshotBaseUrl": "Moonshot エントリーポイント", diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index d1d43642322..89739f4c4aa 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -253,6 +253,8 @@ "getChutesApiKey": "Chutes API 키 받기", "deepSeekApiKey": "DeepSeek API 키", "getDeepSeekApiKey": "DeepSeek API 키 받기", + "doubaoApiKey": "Doubao API 키", + "getDoubaoApiKey": "Doubao API 키 받기", "moonshotApiKey": "Moonshot API 키", "getMoonshotApiKey": "Moonshot API 키 받기", "moonshotBaseUrl": "Moonshot 엔트리포인트", diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index 435886c522a..7d8721ffd83 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -253,6 +253,8 @@ "getChutesApiKey": "Chutes API-sleutel ophalen", "deepSeekApiKey": "DeepSeek API-sleutel", "getDeepSeekApiKey": "DeepSeek API-sleutel ophalen", + "doubaoApiKey": "Doubao API-sleutel", + "getDoubaoApiKey": "Doubao API-sleutel ophalen", "moonshotApiKey": "Moonshot API-sleutel", "getMoonshotApiKey": "Moonshot API-sleutel ophalen", "moonshotBaseUrl": "Moonshot-ingangspunt", diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index 16833329343..5a23d2137de 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -253,6 +253,8 @@ "getChutesApiKey": "Uzyskaj klucz API Chutes", "deepSeekApiKey": "Klucz API DeepSeek", "getDeepSeekApiKey": "Uzyskaj klucz API DeepSeek", + "doubaoApiKey": "Klucz API Doubao", + "getDoubaoApiKey": "Uzyskaj klucz API Doubao", "moonshotApiKey": "Klucz API Moonshot", "getMoonshotApiKey": "Uzyskaj klucz API Moonshot", "moonshotBaseUrl": "Punkt wejścia Moonshot", diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index 3b3abd2dc29..2e39982d273 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -253,6 +253,8 @@ "getChutesApiKey": "Obter chave de API Chutes", "deepSeekApiKey": "Chave de API DeepSeek", "getDeepSeekApiKey": "Obter chave de API DeepSeek", + "doubaoApiKey": "Chave de API Doubao", + "getDoubaoApiKey": "Obter chave de API Doubao", "moonshotApiKey": "Chave de API Moonshot", "getMoonshotApiKey": "Obter chave de API Moonshot", "moonshotBaseUrl": "Ponto de entrada Moonshot", diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index dc45d922d07..76c3877e10d 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -253,6 +253,8 @@ "getChutesApiKey": "Получить Chutes API-ключ", "deepSeekApiKey": "DeepSeek API-ключ", "getDeepSeekApiKey": "Получить DeepSeek API-ключ", + "doubaoApiKey": "Doubao API-ключ", + "getDoubaoApiKey": "Получить Doubao API-ключ", "moonshotApiKey": "Moonshot API-ключ", "getMoonshotApiKey": "Получить Moonshot API-ключ", "moonshotBaseUrl": "Точка входа Moonshot", diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 52ab8b17c8e..26a295ffae4 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -253,6 +253,8 @@ "getChutesApiKey": "Chutes API Anahtarı Al", "deepSeekApiKey": "DeepSeek API Anahtarı", "getDeepSeekApiKey": "DeepSeek API Anahtarı Al", + "doubaoApiKey": "Doubao API Anahtarı", + "getDoubaoApiKey": "Doubao API Anahtarı Al", "moonshotApiKey": "Moonshot API Anahtarı", "getMoonshotApiKey": "Moonshot API Anahtarı Al", "moonshotBaseUrl": "Moonshot Giriş Noktası", diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index 65fd58d0ede..48f63bdf42e 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -253,6 +253,8 @@ "getChutesApiKey": "Lấy khóa API Chutes", "deepSeekApiKey": "Khóa API DeepSeek", "getDeepSeekApiKey": "Lấy khóa API DeepSeek", + "doubaoApiKey": "Khóa API Doubao", + "getDoubaoApiKey": "Lấy khóa API Doubao", "moonshotApiKey": "Khóa API Moonshot", "getMoonshotApiKey": "Lấy khóa API Moonshot", "moonshotBaseUrl": "Điểm vào Moonshot", diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 9f1cbd34b15..6d46e337c52 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -253,6 +253,8 @@ "getChutesApiKey": "获取 Chutes API 密钥", "deepSeekApiKey": "DeepSeek API 密钥", "getDeepSeekApiKey": "获取 DeepSeek API 密钥", + "doubaoApiKey": "豆包 API 密钥", + "getDoubaoApiKey": "获取豆包 API 密钥", "moonshotApiKey": "Moonshot API 密钥", "getMoonshotApiKey": "获取 Moonshot API 密钥", "moonshotBaseUrl": "Moonshot 服务站点", diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 6d96be360e9..ffd852397ff 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -253,6 +253,8 @@ "getChutesApiKey": "取得 Chutes API 金鑰", "deepSeekApiKey": "DeepSeek API 金鑰", "getDeepSeekApiKey": "取得 DeepSeek API 金鑰", + "doubaoApiKey": "豆包 API 金鑰", + "getDoubaoApiKey": "取得豆包 API 金鑰", "moonshotApiKey": "Moonshot API 金鑰", "getMoonshotApiKey": "取得 Moonshot API 金鑰", "moonshotBaseUrl": "Moonshot 服務站點", From d3de137001826d084590ca7df7d0f9fad3340ffc Mon Sep 17 00:00:00 2001 From: Daniel Riccio Date: Wed, 30 Jul 2025 13:11:21 -0500 Subject: [PATCH 2/4] Remove Doubao embedder and clean up provider code - Removed all Doubao embedder-related code - Cleaned up commented code and personal comments in src/api/providers/doubao.ts - Updated related imports and configurations --- packages/types/src/codebase-index.ts | 1 - src/api/providers/doubao.ts | 12 --- src/services/code-index/constants/index.ts | 3 - src/services/code-index/embedders/doubao.ts | 76 ------------------- src/services/code-index/embedders/index.ts | 1 - src/shared/embeddingModels.ts | 2 +- .../src/context/ExtensionStateContext.tsx | 2 +- 7 files changed, 2 insertions(+), 95 deletions(-) delete mode 100644 src/services/code-index/embedders/doubao.ts diff --git a/packages/types/src/codebase-index.ts b/packages/types/src/codebase-index.ts index a2aa863cd3a..89d5b168d78 100644 --- a/packages/types/src/codebase-index.ts +++ b/packages/types/src/codebase-index.ts @@ -48,7 +48,6 @@ export const codebaseIndexModelsSchema = z.object({ "openai-compatible": z.record(z.string(), z.object({ dimension: z.number() })).optional(), gemini: z.record(z.string(), z.object({ dimension: z.number() })).optional(), mistral: z.record(z.string(), z.object({ dimension: z.number() })).optional(), - doubao: z.record(z.string(), z.object({ dimension: z.number() })).optional(), }) export type CodebaseIndexModels = z.infer diff --git a/src/api/providers/doubao.ts b/src/api/providers/doubao.ts index 84fd8e7c77d..a1337ed558a 100644 --- a/src/api/providers/doubao.ts +++ b/src/api/providers/doubao.ts @@ -4,7 +4,6 @@ import { DOUBAO_API_BASE_URL, doubaoDefaultModelId, doubaoModels } from "@roo-co import { getModelParams } from "../transform/model-params" import { ApiStreamUsageChunk } from "../transform/stream" -// by a fan of Doubao, his name on Github is AntiMoron. // Core types for Doubao API interface ChatCompletionMessageParam { role: "system" | "user" | "assistant" | "developer" @@ -50,17 +49,6 @@ interface ChatCompletionChunk { } } -// interface ApiHandlerOptions { -// doubaoBaseUrl?: string -// doubaoApiKey?: string -// doubaoHeaders?: Record -// doubaoModelId?: string -// doubaoStreamingEnabled?: boolean -// modelTemperature?: number -// includeMaxTokens?: boolean -// modelMaxTokens?: number -// } - export class DoubaoHandler extends OpenAiHandler { constructor(options: ApiHandlerOptions) { super({ diff --git a/src/services/code-index/constants/index.ts b/src/services/code-index/constants/index.ts index 979b8d61dab..6f0e0fe7e62 100644 --- a/src/services/code-index/constants/index.ts +++ b/src/services/code-index/constants/index.ts @@ -29,6 +29,3 @@ export const BATCH_PROCESSING_CONCURRENCY = 10 /**Gemini Embedder */ export const GEMINI_MAX_ITEM_TOKENS = 2048 - -/**Doubao Embedder */ -export const DOUBAO_MAX_ITEM_TOKENS = 2048 diff --git a/src/services/code-index/embedders/doubao.ts b/src/services/code-index/embedders/doubao.ts deleted file mode 100644 index 7cd90e504c2..00000000000 --- a/src/services/code-index/embedders/doubao.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { OpenAICompatibleEmbedder } from "./openai-compatible" -import { IEmbedder, EmbeddingResponse, EmbedderInfo } from "../interfaces/embedder" -import { t } from "../../../i18n" -import { TelemetryEventName } from "@roo-code/types" -import { TelemetryService } from "@roo-code/telemetry" -import { DOUBAO_MAX_ITEM_TOKENS } from "../constants" - -export class DoubaoEmbedder implements IEmbedder { - private readonly openAICompatibleEmbedder: OpenAICompatibleEmbedder - private static readonly Doubao_BASE_URL = "https://ark.cn-beijing.volces.com/api/v3/" - private static readonly DEFAULT_MODEL = "doubao-embedding-text-240515" - private readonly modelId: string - - constructor(apiKey: string, modelId?: string) { - if (!apiKey) { - throw new Error(t("embeddings:validation.apiKeyRequired")) - } - - // Use provided model or default - this.modelId = modelId || DoubaoEmbedder.DEFAULT_MODEL - - // Create an OpenAI Compatible embedder with Doubao's configuration - this.openAICompatibleEmbedder = new OpenAICompatibleEmbedder( - DoubaoEmbedder.Doubao_BASE_URL, - apiKey, - this.modelId, - DOUBAO_MAX_ITEM_TOKENS, - ) - } - - /** - * Creates embeddings for the given texts using Doubao's embedding API - * @param texts Array of text strings to embed - * @param model Optional model identifier (uses constructor model if not provided) - * @returns Promise resolving to embedding response - */ - async createEmbeddings(texts: string[], model?: string): Promise { - try { - // Use the provided model or fall back to the instance's model - const modelToUse = model || this.modelId - return await this.openAICompatibleEmbedder.createEmbeddings(texts, modelToUse) - } catch (error) { - TelemetryService.instance.captureEvent(TelemetryEventName.CODE_INDEX_ERROR, { - error: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - location: "DoubaoEmbedder:createEmbeddings", - }) - throw error - } - } - - /** - * Validates the Doubao embedder configuration by delegating to the underlying OpenAI-compatible embedder - * @returns Promise resolving to validation result with success status and optional error message - */ - async validateConfiguration(): Promise<{ valid: boolean; error?: string }> { - try { - // Delegate validation to the OpenAI-compatible embedder - // The error messages will be specific to Doubao since we're using Doubao's base URL - return await this.openAICompatibleEmbedder.validateConfiguration() - } catch (error) { - TelemetryService.instance.captureEvent(TelemetryEventName.CODE_INDEX_ERROR, { - error: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - location: "DoubaoEmbedder:validateConfiguration", - }) - throw error - } - } - - get embedderInfo(): EmbedderInfo { - return { - name: "doubao", - } - } -} diff --git a/src/services/code-index/embedders/index.ts b/src/services/code-index/embedders/index.ts index f30b76815f2..69fec820292 100644 --- a/src/services/code-index/embedders/index.ts +++ b/src/services/code-index/embedders/index.ts @@ -3,4 +3,3 @@ export * from "./openai" export * from "./ollama" export * from "./gemini" export * from "./mistral" -export * from "./doubao" diff --git a/src/shared/embeddingModels.ts b/src/shared/embeddingModels.ts index eca8c2095c1..a3cd61e6593 100644 --- a/src/shared/embeddingModels.ts +++ b/src/shared/embeddingModels.ts @@ -2,7 +2,7 @@ * Defines profiles for different embedding models, including their dimensions. */ -export type EmbedderProvider = "openai" | "ollama" | "openai-compatible" | "gemini" | "mistral" | "doubao" // Add other providers as needed +export type EmbedderProvider = "openai" | "ollama" | "openai-compatible" | "gemini" | "mistral" // Add other providers as needed export interface EmbeddingModelProfile { dimension: number diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index 87a941d214d..c0b36c9dc4e 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -238,7 +238,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode codebaseIndexSearchMaxResults: undefined, codebaseIndexSearchMinScore: undefined, }, - codebaseIndexModels: { ollama: {}, openai: {}, doubao: {} }, + codebaseIndexModels: { ollama: {}, openai: {} }, alwaysAllowUpdateTodoList: true, includeDiagnosticMessages: true, maxDiagnosticMessages: 50, From a31eeeaf66a8dad10f9497de705ff76654c3d63a Mon Sep 17 00:00:00 2001 From: Daniel Riccio Date: Wed, 30 Jul 2025 14:07:15 -0500 Subject: [PATCH 3/4] revert: remove remaining code-index embedder changes - Remove src/services/code-index/embedders/index.ts - Revert AvailableEmbedders type change in embedder.ts --- src/services/code-index/embedders/index.ts | 5 ----- src/services/code-index/interfaces/embedder.ts | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) delete mode 100644 src/services/code-index/embedders/index.ts diff --git a/src/services/code-index/embedders/index.ts b/src/services/code-index/embedders/index.ts deleted file mode 100644 index 69fec820292..00000000000 --- a/src/services/code-index/embedders/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./openai-compatible" -export * from "./openai" -export * from "./ollama" -export * from "./gemini" -export * from "./mistral" diff --git a/src/services/code-index/interfaces/embedder.ts b/src/services/code-index/interfaces/embedder.ts index dbfd208edda..c5653ea2b7e 100644 --- a/src/services/code-index/interfaces/embedder.ts +++ b/src/services/code-index/interfaces/embedder.ts @@ -28,7 +28,7 @@ export interface EmbeddingResponse { } } -export type AvailableEmbedders = "openai" | "ollama" | "openai-compatible" | "gemini" | "mistral" | "doubao" +export type AvailableEmbedders = "openai" | "ollama" | "openai-compatible" | "gemini" | "mistral" export interface EmbedderInfo { name: AvailableEmbedders From 58899eac19654cd1cd19b378acee96bc4ec95921 Mon Sep 17 00:00:00 2001 From: Daniel Riccio Date: Wed, 30 Jul 2025 14:21:11 -0500 Subject: [PATCH 4/4] fix: remove unnecessary type cast in useExtensionState --- webview-ui/src/context/ExtensionStateContext.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index c0b36c9dc4e..b156d0193b4 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -515,5 +515,5 @@ export const useExtensionState = () => { throw new Error("useExtensionState must be used within an ExtensionStateContextProvider") } - return context as ExtensionStateContextType + return context }