diff --git a/packages/types/src/provider-settings.ts b/packages/types/src/provider-settings.ts index 207c60a5243..876f5114b66 100644 --- a/packages/types/src/provider-settings.ts +++ b/packages/types/src/provider-settings.ts @@ -36,6 +36,7 @@ export const providerNames = [ "huggingface", "cerebras", "sambanova", + "zai", ] as const export const providerNamesSchema = z.enum(providerNames) @@ -257,6 +258,11 @@ const sambaNovaSchema = apiModelIdProviderModelSchema.extend({ sambaNovaApiKey: z.string().optional(), }) +const zaiSchema = apiModelIdProviderModelSchema.extend({ + zaiApiKey: z.string().optional(), + zaiApiLine: z.union([z.literal("china"), z.literal("international")]).optional(), +}) + const defaultSchema = z.object({ apiProvider: z.undefined(), }) @@ -290,6 +296,7 @@ export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProv litellmSchema.merge(z.object({ apiProvider: z.literal("litellm") })), cerebrasSchema.merge(z.object({ apiProvider: z.literal("cerebras") })), sambaNovaSchema.merge(z.object({ apiProvider: z.literal("sambanova") })), + zaiSchema.merge(z.object({ apiProvider: z.literal("zai") })), defaultSchema, ]) @@ -323,6 +330,7 @@ export const providerSettingsSchema = z.object({ ...litellmSchema.shape, ...cerebrasSchema.shape, ...sambaNovaSchema.shape, + ...zaiSchema.shape, ...codebaseIndexProviderSchema.shape, }) diff --git a/packages/types/src/providers/index.ts b/packages/types/src/providers/index.ts index d6584e70eca..b0e316bf55f 100644 --- a/packages/types/src/providers/index.ts +++ b/packages/types/src/providers/index.ts @@ -22,3 +22,4 @@ export * from "./vertex.js" export * from "./vscode-llm.js" export * from "./xai.js" export * from "./doubao.js" +export * from "./zai.js" diff --git a/packages/types/src/providers/zai.ts b/packages/types/src/providers/zai.ts new file mode 100644 index 00000000000..f7247448272 --- /dev/null +++ b/packages/types/src/providers/zai.ts @@ -0,0 +1,105 @@ +import type { ModelInfo } from "../model.js" + +// Z AI +// https://docs.z.ai/guides/llm/glm-4.5 +// https://docs.z.ai/guides/overview/pricing + +export type InternationalZAiModelId = keyof typeof internationalZAiModels +export const internationalZAiDefaultModelId: InternationalZAiModelId = "glm-4.5" +export const internationalZAiModels = { + "glm-4.5": { + maxTokens: 98_304, + contextWindow: 131_072, + supportsImages: false, + supportsPromptCache: true, + inputPrice: 0.6, + outputPrice: 2.2, + cacheWritesPrice: 0, + cacheReadsPrice: 0.11, + description: + "GLM-4.5 is Zhipu's latest featured model. Its comprehensive capabilities in reasoning, coding, and agent reach the state-of-the-art (SOTA) level among open-source models, with a context length of up to 128k.", + }, + "glm-4.5-air": { + maxTokens: 98_304, + contextWindow: 131_072, + supportsImages: false, + supportsPromptCache: true, + inputPrice: 0.2, + outputPrice: 1.1, + cacheWritesPrice: 0, + cacheReadsPrice: 0.03, + description: + "GLM-4.5-Air is the lightweight version of GLM-4.5. It balances performance and cost-effectiveness, and can flexibly switch to hybrid thinking models.", + }, +} as const satisfies Record + +export type MainlandZAiModelId = keyof typeof mainlandZAiModels +export const mainlandZAiDefaultModelId: MainlandZAiModelId = "glm-4.5" +export const mainlandZAiModels = { + "glm-4.5": { + maxTokens: 98_304, + contextWindow: 131_072, + supportsImages: false, + supportsPromptCache: true, + inputPrice: 0.29, + outputPrice: 1.14, + cacheWritesPrice: 0, + cacheReadsPrice: 0.057, + description: + "GLM-4.5 is Zhipu's latest featured model. Its comprehensive capabilities in reasoning, coding, and agent reach the state-of-the-art (SOTA) level among open-source models, with a context length of up to 128k.", + tiers: [ + { + contextWindow: 32_000, + inputPrice: 0.21, + outputPrice: 1.0, + cacheReadsPrice: 0.043, + }, + { + contextWindow: 128_000, + inputPrice: 0.29, + outputPrice: 1.14, + cacheReadsPrice: 0.057, + }, + { + contextWindow: Infinity, + inputPrice: 0.29, + outputPrice: 1.14, + cacheReadsPrice: 0.057, + }, + ], + }, + "glm-4.5-air": { + maxTokens: 98_304, + contextWindow: 131_072, + supportsImages: false, + supportsPromptCache: true, + inputPrice: 0.1, + outputPrice: 0.6, + cacheWritesPrice: 0, + cacheReadsPrice: 0.02, + description: + "GLM-4.5-Air is the lightweight version of GLM-4.5. It balances performance and cost-effectiveness, and can flexibly switch to hybrid thinking models.", + tiers: [ + { + contextWindow: 32_000, + inputPrice: 0.07, + outputPrice: 0.4, + cacheReadsPrice: 0.014, + }, + { + contextWindow: 128_000, + inputPrice: 0.1, + outputPrice: 0.6, + cacheReadsPrice: 0.02, + }, + { + contextWindow: Infinity, + inputPrice: 0.1, + outputPrice: 0.6, + cacheReadsPrice: 0.02, + }, + ], + }, +} as const satisfies Record + +export const ZAI_DEFAULT_TEMPERATURE = 0 diff --git a/src/api/index.ts b/src/api/index.ts index 5daa53396fe..3ad3705ebaa 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -33,6 +33,7 @@ import { ClaudeCodeHandler, SambaNovaHandler, DoubaoHandler, + ZAiHandler, } from "./providers" export interface SingleCompletionHandler { @@ -124,6 +125,8 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler { return new CerebrasHandler(options) case "sambanova": return new SambaNovaHandler(options) + case "zai": + return new ZAiHandler(options) default: apiProvider satisfies "gemini-cli" | undefined return new AnthropicHandler(options) diff --git a/src/api/providers/__tests__/zai.spec.ts b/src/api/providers/__tests__/zai.spec.ts new file mode 100644 index 00000000000..6b93aaa43b7 --- /dev/null +++ b/src/api/providers/__tests__/zai.spec.ts @@ -0,0 +1,231 @@ +// npx vitest run src/api/providers/__tests__/zai.spec.ts + +// Mock vscode first to avoid import errors +vitest.mock("vscode", () => ({})) + +import OpenAI from "openai" +import { Anthropic } from "@anthropic-ai/sdk" + +import { + type InternationalZAiModelId, + type MainlandZAiModelId, + internationalZAiDefaultModelId, + mainlandZAiDefaultModelId, + internationalZAiModels, + mainlandZAiModels, + ZAI_DEFAULT_TEMPERATURE, +} from "@roo-code/types" + +import { ZAiHandler } from "../zai" + +vitest.mock("openai", () => { + const createMock = vitest.fn() + return { + default: vitest.fn(() => ({ chat: { completions: { create: createMock } } })), + } +}) + +describe("ZAiHandler", () => { + let handler: ZAiHandler + let mockCreate: any + + beforeEach(() => { + vitest.clearAllMocks() + mockCreate = (OpenAI as unknown as any)().chat.completions.create + }) + + describe("International Z AI", () => { + beforeEach(() => { + handler = new ZAiHandler({ zaiApiKey: "test-zai-api-key", zaiApiLine: "international" }) + }) + + it("should use the correct international Z AI base URL", () => { + new ZAiHandler({ zaiApiKey: "test-zai-api-key", zaiApiLine: "international" }) + expect(OpenAI).toHaveBeenCalledWith(expect.objectContaining({ baseURL: "https://api.z.ai/api/paas/v4" })) + }) + + it("should use the provided API key for international", () => { + const zaiApiKey = "test-zai-api-key" + new ZAiHandler({ zaiApiKey, zaiApiLine: "international" }) + expect(OpenAI).toHaveBeenCalledWith(expect.objectContaining({ apiKey: zaiApiKey })) + }) + + it("should return international default model when no model is specified", () => { + const model = handler.getModel() + expect(model.id).toBe(internationalZAiDefaultModelId) + expect(model.info).toEqual(internationalZAiModels[internationalZAiDefaultModelId]) + }) + + it("should return specified international model when valid model is provided", () => { + const testModelId: InternationalZAiModelId = "glm-4.5-air" + const handlerWithModel = new ZAiHandler({ + apiModelId: testModelId, + zaiApiKey: "test-zai-api-key", + zaiApiLine: "international", + }) + const model = handlerWithModel.getModel() + expect(model.id).toBe(testModelId) + expect(model.info).toEqual(internationalZAiModels[testModelId]) + }) + }) + + describe("China Z AI", () => { + beforeEach(() => { + handler = new ZAiHandler({ zaiApiKey: "test-zai-api-key", zaiApiLine: "china" }) + }) + + it("should use the correct China Z AI base URL", () => { + new ZAiHandler({ zaiApiKey: "test-zai-api-key", zaiApiLine: "china" }) + expect(OpenAI).toHaveBeenCalledWith( + expect.objectContaining({ baseURL: "https://open.bigmodel.cn/api/paas/v4" }), + ) + }) + + it("should use the provided API key for China", () => { + const zaiApiKey = "test-zai-api-key" + new ZAiHandler({ zaiApiKey, zaiApiLine: "china" }) + expect(OpenAI).toHaveBeenCalledWith(expect.objectContaining({ apiKey: zaiApiKey })) + }) + + it("should return China default model when no model is specified", () => { + const model = handler.getModel() + expect(model.id).toBe(mainlandZAiDefaultModelId) + expect(model.info).toEqual(mainlandZAiModels[mainlandZAiDefaultModelId]) + }) + + it("should return specified China model when valid model is provided", () => { + const testModelId: MainlandZAiModelId = "glm-4.5-air" + const handlerWithModel = new ZAiHandler({ + apiModelId: testModelId, + zaiApiKey: "test-zai-api-key", + zaiApiLine: "china", + }) + const model = handlerWithModel.getModel() + expect(model.id).toBe(testModelId) + expect(model.info).toEqual(mainlandZAiModels[testModelId]) + }) + }) + + describe("Default behavior", () => { + it("should default to international when no zaiApiLine is specified", () => { + const handlerDefault = new ZAiHandler({ zaiApiKey: "test-zai-api-key" }) + expect(OpenAI).toHaveBeenCalledWith(expect.objectContaining({ baseURL: "https://api.z.ai/api/paas/v4" })) + + const model = handlerDefault.getModel() + expect(model.id).toBe(internationalZAiDefaultModelId) + expect(model.info).toEqual(internationalZAiModels[internationalZAiDefaultModelId]) + }) + + it("should use 'not-provided' as default API key when none is specified", () => { + new ZAiHandler({ zaiApiLine: "international" }) + expect(OpenAI).toHaveBeenCalledWith(expect.objectContaining({ apiKey: "not-provided" })) + }) + }) + + describe("API Methods", () => { + beforeEach(() => { + handler = new ZAiHandler({ zaiApiKey: "test-zai-api-key", zaiApiLine: "international" }) + }) + + it("completePrompt method should return text from Z AI API", async () => { + const expectedResponse = "This is a test response from Z AI" + mockCreate.mockResolvedValueOnce({ choices: [{ message: { content: expectedResponse } }] }) + const result = await handler.completePrompt("test prompt") + expect(result).toBe(expectedResponse) + }) + + it("should handle errors in completePrompt", async () => { + const errorMessage = "Z AI API error" + mockCreate.mockRejectedValueOnce(new Error(errorMessage)) + await expect(handler.completePrompt("test prompt")).rejects.toThrow( + `Z AI completion error: ${errorMessage}`, + ) + }) + + it("createMessage should yield text content from stream", async () => { + const testContent = "This is test content from Z AI stream" + + mockCreate.mockImplementationOnce(() => { + return { + [Symbol.asyncIterator]: () => ({ + next: vitest + .fn() + .mockResolvedValueOnce({ + done: false, + value: { choices: [{ delta: { content: testContent } }] }, + }) + .mockResolvedValueOnce({ done: true }), + }), + } + }) + + const stream = handler.createMessage("system prompt", []) + const firstChunk = await stream.next() + + expect(firstChunk.done).toBe(false) + expect(firstChunk.value).toEqual({ type: "text", text: testContent }) + }) + + it("createMessage should yield usage data from stream", async () => { + mockCreate.mockImplementationOnce(() => { + return { + [Symbol.asyncIterator]: () => ({ + next: vitest + .fn() + .mockResolvedValueOnce({ + done: false, + value: { + choices: [{ delta: {} }], + usage: { prompt_tokens: 10, completion_tokens: 20 }, + }, + }) + .mockResolvedValueOnce({ done: true }), + }), + } + }) + + const stream = handler.createMessage("system prompt", []) + const firstChunk = await stream.next() + + expect(firstChunk.done).toBe(false) + expect(firstChunk.value).toEqual({ type: "usage", inputTokens: 10, outputTokens: 20 }) + }) + + it("createMessage should pass correct parameters to Z AI client", async () => { + const modelId: InternationalZAiModelId = "glm-4.5" + const modelInfo = internationalZAiModels[modelId] + const handlerWithModel = new ZAiHandler({ + apiModelId: modelId, + zaiApiKey: "test-zai-api-key", + zaiApiLine: "international", + }) + + mockCreate.mockImplementationOnce(() => { + return { + [Symbol.asyncIterator]: () => ({ + async next() { + return { done: true } + }, + }), + } + }) + + const systemPrompt = "Test system prompt for Z AI" + const messages: Anthropic.Messages.MessageParam[] = [{ role: "user", content: "Test message for Z AI" }] + + const messageGenerator = handlerWithModel.createMessage(systemPrompt, messages) + await messageGenerator.next() + + expect(mockCreate).toHaveBeenCalledWith( + expect.objectContaining({ + model: modelId, + max_tokens: modelInfo.maxTokens, + temperature: ZAI_DEFAULT_TEMPERATURE, + messages: expect.arrayContaining([{ role: "system", content: systemPrompt }]), + stream: true, + stream_options: { include_usage: true }, + }), + ) + }) + }) +}) diff --git a/src/api/providers/index.ts b/src/api/providers/index.ts index a1b8f255364..dfcf87b6c90 100644 --- a/src/api/providers/index.ts +++ b/src/api/providers/index.ts @@ -26,3 +26,4 @@ export { UnboundHandler } from "./unbound" export { VertexHandler } from "./vertex" export { VsCodeLmHandler } from "./vscode-lm" export { XAIHandler } from "./xai" +export { ZAiHandler } from "./zai" diff --git a/src/api/providers/zai.ts b/src/api/providers/zai.ts new file mode 100644 index 00000000000..e37e37f01b4 --- /dev/null +++ b/src/api/providers/zai.ts @@ -0,0 +1,31 @@ +import { + internationalZAiModels, + mainlandZAiModels, + internationalZAiDefaultModelId, + mainlandZAiDefaultModelId, + type InternationalZAiModelId, + type MainlandZAiModelId, + ZAI_DEFAULT_TEMPERATURE, +} from "@roo-code/types" + +import type { ApiHandlerOptions } from "../../shared/api" + +import { BaseOpenAiCompatibleProvider } from "./base-openai-compatible-provider" + +export class ZAiHandler extends BaseOpenAiCompatibleProvider { + constructor(options: ApiHandlerOptions) { + const isChina = options.zaiApiLine === "china" + const models = isChina ? mainlandZAiModels : internationalZAiModels + const defaultModelId = isChina ? mainlandZAiDefaultModelId : internationalZAiDefaultModelId + + super({ + ...options, + providerName: "Z AI", + baseURL: isChina ? "https://open.bigmodel.cn/api/paas/v4" : "https://api.z.ai/api/paas/v4", + apiKey: options.zaiApiKey ?? "not-provided", + defaultProviderModelId: defaultModelId, + providerModels: models, + defaultTemperature: ZAI_DEFAULT_TEMPERATURE, + }) + } +} diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index d70ca553ac6..6c521ecfdf2 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -28,6 +28,8 @@ import { bedrockDefaultModelId, vertexDefaultModelId, sambaNovaDefaultModelId, + internationalZAiDefaultModelId, + mainlandZAiDefaultModelId, } from "@roo-code/types" import { vscode } from "@src/utils/vscode" @@ -79,6 +81,7 @@ import { Vertex, VSCodeLM, XAI, + ZAi, } from "./providers" import { MODELS_BY_PROVIDER, PROVIDERS } from "./constants" @@ -306,6 +309,13 @@ const ApiOptions = ({ bedrock: { field: "apiModelId", default: bedrockDefaultModelId }, vertex: { field: "apiModelId", default: vertexDefaultModelId }, sambanova: { field: "apiModelId", default: sambaNovaDefaultModelId }, + zai: { + field: "apiModelId", + default: + apiConfiguration.zaiApiLine === "china" + ? mainlandZAiDefaultModelId + : internationalZAiDefaultModelId, + }, openai: { field: "openAiModelId" }, ollama: { field: "ollamaModelId" }, lmstudio: { field: "lmStudioModelId" }, @@ -530,6 +540,10 @@ const ApiOptions = ({ )} + {selectedProvider === "zai" && ( + + )} + {selectedProvider === "human-relay" && ( <>
diff --git a/webview-ui/src/components/settings/constants.ts b/webview-ui/src/components/settings/constants.ts index fae35b16939..c0ddaf89e1b 100644 --- a/webview-ui/src/components/settings/constants.ts +++ b/webview-ui/src/components/settings/constants.ts @@ -16,6 +16,7 @@ import { chutesModels, sambaNovaModels, doubaoModels, + internationalZAiModels, } from "@roo-code/types" export const MODELS_BY_PROVIDER: Partial>> = { @@ -34,6 +35,7 @@ export const MODELS_BY_PROVIDER: Partial a.label.localeCompare(b.label)) diff --git a/webview-ui/src/components/settings/providers/ZAi.tsx b/webview-ui/src/components/settings/providers/ZAi.tsx new file mode 100644 index 00000000000..bc23f28346a --- /dev/null +++ b/webview-ui/src/components/settings/providers/ZAi.tsx @@ -0,0 +1,76 @@ +import { useCallback } from "react" +import { VSCodeTextField, VSCodeDropdown, VSCodeOption } from "@vscode/webview-ui-toolkit/react" + +import type { ProviderSettings } from "@roo-code/types" + +import { useAppTranslation } from "@src/i18n/TranslationContext" +import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink" + +import { inputEventTransform } from "../transforms" +import { cn } from "@/lib/utils" + +type ZAiProps = { + apiConfiguration: ProviderSettings + setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void +} + +export const ZAi = ({ apiConfiguration, setApiConfigurationField }: ZAiProps) => { + 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 ( + <> +
+ + + + api.z.ai + + + open.bigmodel.cn + + +
+ {t("settings:providers.zaiEntrypointDescription")} +
+
+
+ + + +
+ {t("settings:providers.apiKeyStorageNotice")} +
+ {!apiConfiguration?.zaiApiKey && ( + + {t("settings:providers.getZaiApiKey")} + + )} +
+ + ) +} diff --git a/webview-ui/src/components/settings/providers/index.ts b/webview-ui/src/components/settings/providers/index.ts index 47430a0cc81..0f0048df0a8 100644 --- a/webview-ui/src/components/settings/providers/index.ts +++ b/webview-ui/src/components/settings/providers/index.ts @@ -22,4 +22,5 @@ export { Unbound } from "./Unbound" export { Vertex } from "./Vertex" export { VSCodeLM } from "./VSCodeLM" export { XAI } from "./XAI" +export { ZAi } from "./ZAi" export { LiteLLM } from "./LiteLLM" diff --git a/webview-ui/src/components/ui/hooks/useSelectedModel.ts b/webview-ui/src/components/ui/hooks/useSelectedModel.ts index 0c6a84a65e9..a191014981e 100644 --- a/webview-ui/src/components/ui/hooks/useSelectedModel.ts +++ b/webview-ui/src/components/ui/hooks/useSelectedModel.ts @@ -40,6 +40,10 @@ import { sambaNovaDefaultModelId, doubaoModels, doubaoDefaultModelId, + internationalZAiDefaultModelId, + mainlandZAiDefaultModelId, + internationalZAiModels, + mainlandZAiModels, } from "@roo-code/types" import type { ModelRecord, RouterModels } from "@roo/api" @@ -203,6 +207,14 @@ function getSelectedModel({ const info = moonshotModels[id as keyof typeof moonshotModels] return { id, info } } + case "zai": { + const isChina = apiConfiguration.zaiApiLine === "china" + const models = isChina ? mainlandZAiModels : internationalZAiModels + const defaultModelId = isChina ? mainlandZAiDefaultModelId : internationalZAiDefaultModelId + const id = apiConfiguration.apiModelId ?? defaultModelId + const info = models[id as keyof typeof models] + return { id, info } + } case "openai-native": { const id = apiConfiguration.apiModelId ?? openAiNativeDefaultModelId const info = openAiNativeModels[id as keyof typeof openAiNativeModels] diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index 9ab98a89802..5197885ca9a 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -268,6 +268,10 @@ "moonshotApiKey": "Clau API de Moonshot", "getMoonshotApiKey": "Obtenir clau API de Moonshot", "moonshotBaseUrl": "Punt d'entrada de Moonshot", + "zaiApiKey": "Clau API de Z AI", + "getZaiApiKey": "Obtenir clau API de Z AI", + "zaiEntrypoint": "Punt d'entrada de Z AI", + "zaiEntrypointDescription": "Si us plau, seleccioneu el punt d'entrada de l'API apropiat segons la vostra ubicació. Si sou a la Xina, trieu open.bigmodel.cn. Altrament, trieu api.z.ai.", "geminiApiKey": "Clau API de Gemini", "getGroqApiKey": "Obtenir clau API de Groq", "groqApiKey": "Clau API de Groq", diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 667b3134684..961ae9e8cb2 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -268,6 +268,10 @@ "moonshotApiKey": "Moonshot API-Schlüssel", "getMoonshotApiKey": "Moonshot API-Schlüssel erhalten", "moonshotBaseUrl": "Moonshot-Einstiegspunkt", + "zaiApiKey": "Z AI API-Schlüssel", + "getZaiApiKey": "Z AI API-Schlüssel erhalten", + "zaiEntrypoint": "Z AI Einstiegspunkt", + "zaiEntrypointDescription": "Bitte wählen Sie den entsprechenden API-Einstiegspunkt basierend auf Ihrem Standort. Wenn Sie sich in China befinden, wählen Sie open.bigmodel.cn. Andernfalls wählen Sie api.z.ai.", "geminiApiKey": "Gemini API-Schlüssel", "getGroqApiKey": "Groq API-Schlüssel erhalten", "groqApiKey": "Groq API-Schlüssel", diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 46c15556c8f..1b9c33abef9 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -267,6 +267,10 @@ "moonshotApiKey": "Moonshot API Key", "getMoonshotApiKey": "Get Moonshot API Key", "moonshotBaseUrl": "Moonshot Entrypoint", + "zaiApiKey": "Z AI API Key", + "getZaiApiKey": "Get Z AI API Key", + "zaiEntrypoint": "Z AI Entrypoint", + "zaiEntrypointDescription": "Please select the appropriate API entrypoint based on your location. If you are in China, choose open.bigmodel.cn. Otherwise, choose api.z.ai.", "geminiApiKey": "Gemini API Key", "getGroqApiKey": "Get Groq API Key", "groqApiKey": "Groq API Key", diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index 0f41e6dddae..5e69810db34 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -268,6 +268,10 @@ "moonshotApiKey": "Clave API de Moonshot", "getMoonshotApiKey": "Obtener clave API de Moonshot", "moonshotBaseUrl": "Punto de entrada de Moonshot", + "zaiApiKey": "Clave API de Z AI", + "getZaiApiKey": "Obtener clave API de Z AI", + "zaiEntrypoint": "Punto de entrada de Z AI", + "zaiEntrypointDescription": "Por favor, seleccione el punto de entrada de API apropiado según su ubicación. Si está en China, elija open.bigmodel.cn. De lo contrario, elija api.z.ai.", "geminiApiKey": "Clave API de Gemini", "getGroqApiKey": "Obtener clave API de Groq", "groqApiKey": "Clave API de Groq", diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 5af186e6b1a..a5e92adc75e 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -268,6 +268,10 @@ "moonshotApiKey": "Clé API Moonshot", "getMoonshotApiKey": "Obtenir la clé API Moonshot", "moonshotBaseUrl": "Point d'entrée Moonshot", + "zaiApiKey": "Clé API Z AI", + "getZaiApiKey": "Obtenir la clé API Z AI", + "zaiEntrypoint": "Point d'entrée Z AI", + "zaiEntrypointDescription": "Veuillez sélectionner le point d'entrée API approprié en fonction de votre emplacement. Si vous êtes en Chine, choisissez open.bigmodel.cn. Sinon, choisissez api.z.ai.", "geminiApiKey": "Clé API Gemini", "getGroqApiKey": "Obtenir la clé API Groq", "groqApiKey": "Clé API Groq", diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index e3743a531ec..93a7ddfc30a 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -268,6 +268,10 @@ "moonshotApiKey": "Moonshot API कुंजी", "getMoonshotApiKey": "Moonshot API कुंजी प्राप्त करें", "moonshotBaseUrl": "Moonshot प्रवेश बिंदु", + "zaiApiKey": "Z AI API कुंजी", + "getZaiApiKey": "Z AI API कुंजी प्राप्त करें", + "zaiEntrypoint": "Z AI प्रवेश बिंदु", + "zaiEntrypointDescription": "कृपया अपने स्थान के आधार पर उपयुक्त API प्रवेश बिंदु का चयन करें। यदि आप चीन में हैं, तो open.bigmodel.cn चुनें। अन्यथा, api.z.ai चुनें।", "geminiApiKey": "Gemini API कुंजी", "getGroqApiKey": "Groq API कुंजी प्राप्त करें", "groqApiKey": "Groq API कुंजी", diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index 0f47712f214..a18375003a7 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -272,6 +272,10 @@ "moonshotApiKey": "Kunci API Moonshot", "getMoonshotApiKey": "Dapatkan Kunci API Moonshot", "moonshotBaseUrl": "Titik Masuk Moonshot", + "zaiApiKey": "Kunci API Z AI", + "getZaiApiKey": "Dapatkan Kunci API Z AI", + "zaiEntrypoint": "Titik Masuk Z AI", + "zaiEntrypointDescription": "Silakan pilih titik masuk API yang sesuai berdasarkan lokasi Anda. Jika Anda berada di China, pilih open.bigmodel.cn. Jika tidak, pilih api.z.ai.", "geminiApiKey": "Gemini API Key", "getGroqApiKey": "Dapatkan Groq API Key", "groqApiKey": "Groq API Key", diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index e5bc317effa..cd487f7f34b 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -268,6 +268,10 @@ "moonshotApiKey": "Chiave API Moonshot", "getMoonshotApiKey": "Ottieni chiave API Moonshot", "moonshotBaseUrl": "Punto di ingresso Moonshot", + "zaiApiKey": "Chiave API Z AI", + "getZaiApiKey": "Ottieni chiave API Z AI", + "zaiEntrypoint": "Punto di ingresso Z AI", + "zaiEntrypointDescription": "Si prega di selezionare il punto di ingresso API appropriato in base alla propria posizione. Se ti trovi in Cina, scegli open.bigmodel.cn. Altrimenti, scegli api.z.ai.", "geminiApiKey": "Chiave API Gemini", "getGroqApiKey": "Ottieni chiave API Groq", "groqApiKey": "Chiave API Groq", diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index ab4cda177aa..045a47388c9 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -268,6 +268,10 @@ "moonshotApiKey": "Moonshot APIキー", "getMoonshotApiKey": "Moonshot APIキーを取得", "moonshotBaseUrl": "Moonshot エントリーポイント", + "zaiApiKey": "Z AI APIキー", + "getZaiApiKey": "Z AI APIキーを取得", + "zaiEntrypoint": "Z AI エントリーポイント", + "zaiEntrypointDescription": "お住まいの地域に応じて適切な API エントリーポイントを選択してください。中国にお住まいの場合は open.bigmodel.cn を選択してください。それ以外の場合は api.z.ai を選択してください。", "geminiApiKey": "Gemini APIキー", "getGroqApiKey": "Groq APIキーを取得", "groqApiKey": "Groq APIキー", diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index adad29a1529..e7432706383 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -268,6 +268,10 @@ "moonshotApiKey": "Moonshot API 키", "getMoonshotApiKey": "Moonshot API 키 받기", "moonshotBaseUrl": "Moonshot 엔트리포인트", + "zaiApiKey": "Z AI API 키", + "getZaiApiKey": "Z AI API 키 받기", + "zaiEntrypoint": "Z AI 엔트리포인트", + "zaiEntrypointDescription": "위치에 따라 적절한 API 엔트리포인트를 선택하세요. 중국에 있다면 open.bigmodel.cn을 선택하세요. 그렇지 않으면 api.z.ai를 선택하세요.", "geminiApiKey": "Gemini API 키", "getGroqApiKey": "Groq API 키 받기", "groqApiKey": "Groq API 키", diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index e635c8d2c85..ac122b3ed36 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -268,6 +268,10 @@ "moonshotApiKey": "Moonshot API-sleutel", "getMoonshotApiKey": "Moonshot API-sleutel ophalen", "moonshotBaseUrl": "Moonshot-ingangspunt", + "zaiApiKey": "Z AI API-sleutel", + "getZaiApiKey": "Z AI API-sleutel ophalen", + "zaiEntrypoint": "Z AI-ingangspunt", + "zaiEntrypointDescription": "Selecteer het juiste API-ingangspunt op basis van uw locatie. Als u zich in China bevindt, kies dan open.bigmodel.cn. Anders kiest u api.z.ai.", "geminiApiKey": "Gemini API-sleutel", "getGroqApiKey": "Groq API-sleutel ophalen", "groqApiKey": "Groq API-sleutel", diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index d176693143c..ae17daa5f66 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -268,6 +268,10 @@ "moonshotApiKey": "Klucz API Moonshot", "getMoonshotApiKey": "Uzyskaj klucz API Moonshot", "moonshotBaseUrl": "Punkt wejścia Moonshot", + "zaiApiKey": "Klucz API Z AI", + "getZaiApiKey": "Uzyskaj klucz API Z AI", + "zaiEntrypoint": "Punkt wejścia Z AI", + "zaiEntrypointDescription": "Wybierz odpowiedni punkt wejścia API w zależności od swojej lokalizacji. Jeśli jesteś w Chinach, wybierz open.bigmodel.cn. W przeciwnym razie wybierz api.z.ai.", "geminiApiKey": "Klucz API Gemini", "getGroqApiKey": "Uzyskaj klucz API Groq", "groqApiKey": "Klucz API Groq", diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index a646229164e..6adc780ec88 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -268,6 +268,10 @@ "moonshotApiKey": "Chave de API Moonshot", "getMoonshotApiKey": "Obter chave de API Moonshot", "moonshotBaseUrl": "Ponto de entrada Moonshot", + "zaiApiKey": "Chave de API Z AI", + "getZaiApiKey": "Obter chave de API Z AI", + "zaiEntrypoint": "Ponto de entrada Z AI", + "zaiEntrypointDescription": "Selecione o ponto de entrada da API apropriado com base na sua localização. Se você estiver na China, escolha open.bigmodel.cn. Caso contrário, escolha api.z.ai.", "geminiApiKey": "Chave de API Gemini", "getGroqApiKey": "Obter chave de API Groq", "groqApiKey": "Chave de API Groq", diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index 7476f0cb0a4..fce47c9e847 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -268,6 +268,10 @@ "moonshotApiKey": "Moonshot API-ключ", "getMoonshotApiKey": "Получить Moonshot API-ключ", "moonshotBaseUrl": "Точка входа Moonshot", + "zaiApiKey": "Z AI API-ключ", + "getZaiApiKey": "Получить Z AI API-ключ", + "zaiEntrypoint": "Точка входа Z AI", + "zaiEntrypointDescription": "Пожалуйста, выберите подходящую точку входа API в зависимости от вашего местоположения. Если вы находитесь в Китае, выберите open.bigmodel.cn. В противном случае выберите api.z.ai.", "geminiApiKey": "Gemini API-ключ", "getGroqApiKey": "Получить Groq API-ключ", "groqApiKey": "Groq API-ключ", diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 07e8dac1d67..25df6cfa7d9 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -268,6 +268,10 @@ "moonshotApiKey": "Moonshot API Anahtarı", "getMoonshotApiKey": "Moonshot API Anahtarı Al", "moonshotBaseUrl": "Moonshot Giriş Noktası", + "zaiApiKey": "Z AI API Anahtarı", + "getZaiApiKey": "Z AI API Anahtarı Al", + "zaiEntrypoint": "Z AI Giriş Noktası", + "zaiEntrypointDescription": "Konumunuza göre uygun API giriş noktasını seçin. Çin'de iseniz open.bigmodel.cn'yi seçin. Aksi takdirde api.z.ai'yi seçin.", "geminiApiKey": "Gemini API Anahtarı", "getGroqApiKey": "Groq API Anahtarı Al", "groqApiKey": "Groq API Anahtarı", diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index e1b91860b81..5cbe547d948 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -268,6 +268,10 @@ "moonshotApiKey": "Khóa API Moonshot", "getMoonshotApiKey": "Lấy khóa API Moonshot", "moonshotBaseUrl": "Điểm vào Moonshot", + "zaiApiKey": "Khóa API Z AI", + "getZaiApiKey": "Lấy khóa API Z AI", + "zaiEntrypoint": "Điểm vào Z AI", + "zaiEntrypointDescription": "Vui lòng chọn điểm vào API phù hợp dựa trên vị trí của bạn. Nếu bạn ở Trung Quốc, hãy chọn open.bigmodel.cn. Ngược lại, hãy chọn api.z.ai.", "geminiApiKey": "Khóa API Gemini", "getGroqApiKey": "Lấy khóa API Groq", "groqApiKey": "Khóa API Groq", diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 2b390f349c0..792289bad7d 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -268,6 +268,10 @@ "moonshotApiKey": "Moonshot API 密钥", "getMoonshotApiKey": "获取 Moonshot API 密钥", "moonshotBaseUrl": "Moonshot 服务站点", + "zaiApiKey": "Z AI API 密钥", + "getZaiApiKey": "获取 Z AI API 密钥", + "zaiEntrypoint": "Z AI 服务站点", + "zaiEntrypointDescription": "请根据您的位置选择适当的 API 服务站点。如果您在中国,请选择 open.bigmodel.cn。否则,请选择 api.z.ai。", "geminiApiKey": "Gemini API 密钥", "getGroqApiKey": "获取 Groq API 密钥", "groqApiKey": "Groq API 密钥", diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index b1ec67b8db5..84f861ea059 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -268,6 +268,10 @@ "moonshotApiKey": "Moonshot API 金鑰", "getMoonshotApiKey": "取得 Moonshot API 金鑰", "moonshotBaseUrl": "Moonshot 服務站點", + "zaiApiKey": "Z AI API 金鑰", + "getZaiApiKey": "取得 Z AI API 金鑰", + "zaiEntrypoint": "Z AI 服務站點", + "zaiEntrypointDescription": "請根據您的位置選擇適當的 API 服務站點。如果您在中國,請選擇 open.bigmodel.cn。否則,請選擇 api.z.ai。", "geminiApiKey": "Gemini API 金鑰", "getGroqApiKey": "取得 Groq API 金鑰", "groqApiKey": "Groq API 金鑰",