Skip to content

Commit 64c1dea

Browse files
committed
Add coding plan support to Z.ai provider
Adds support for Z.ai's coding plan subscription tiers: - International Coding Plan - China Coding Plan Pulls changes from downstream PR Kilo-Org/kilocode#2402
1 parent 94b4511 commit 64c1dea

File tree

5 files changed

+43
-14
lines changed

5 files changed

+43
-14
lines changed

packages/types/src/provider-settings.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,9 +308,13 @@ const sambaNovaSchema = apiModelIdProviderModelSchema.extend({
308308
sambaNovaApiKey: z.string().optional(),
309309
})
310310

311+
export const zaiApiLineSchema = z.enum(["international_coding", "international", "china_coding", "china"])
312+
313+
export type ZaiApiLine = z.infer<typeof zaiApiLineSchema>
314+
311315
const zaiSchema = apiModelIdProviderModelSchema.extend({
312316
zaiApiKey: z.string().optional(),
313-
zaiApiLine: z.union([z.literal("china"), z.literal("international")]).optional(),
317+
zaiApiLine: zaiApiLineSchema.optional(),
314318
})
315319

316320
const fireworksSchema = apiModelIdProviderModelSchema.extend({

packages/types/src/providers/zai.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { ModelInfo } from "../model.js"
2+
import { ZaiApiLine } from "../provider-settings.js" // kilocode_change
23

34
// Z AI
45
// https://docs.z.ai/guides/llm/glm-4.5
@@ -103,3 +104,16 @@ export const mainlandZAiModels = {
103104
} as const satisfies Record<string, ModelInfo>
104105

105106
export const ZAI_DEFAULT_TEMPERATURE = 0
107+
108+
// kilocode_change start
109+
export const zaiApiLineConfigs = {
110+
international_coding: {
111+
name: "International Coding Plan",
112+
baseUrl: "https://api.z.ai/api/coding/paas/v4",
113+
isChina: false,
114+
},
115+
international: { name: "International Standard", baseUrl: "https://api.z.ai/api/paas/v4", isChina: false },
116+
china_coding: { name: "China Coding Plan", baseUrl: "https://open.bigmodel.cn/api/coding/paas/v4", isChina: true },
117+
china: { name: "China Standard", baseUrl: "https://open.bigmodel.cn/api/paas/v4", isChina: true },
118+
} satisfies Record<ZaiApiLine, { name: string; baseUrl: string; isChina: boolean }>
119+
// kilocode_change end

src/api/providers/__tests__/zai.spec.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ describe("ZAiHandler", () => {
4141

4242
it("should use the correct international Z AI base URL", () => {
4343
new ZAiHandler({ zaiApiKey: "test-zai-api-key", zaiApiLine: "international" })
44-
expect(OpenAI).toHaveBeenCalledWith(expect.objectContaining({ baseURL: "https://api.z.ai/api/paas/v4" }))
44+
expect(OpenAI).toHaveBeenCalledWith(
45+
expect.objectContaining({
46+
baseURL: "https://api.z.ai/api/paas/v4",
47+
}),
48+
)
4549
})
4650

4751
it("should use the provided API key for international", () => {
@@ -109,7 +113,11 @@ describe("ZAiHandler", () => {
109113
describe("Default behavior", () => {
110114
it("should default to international when no zaiApiLine is specified", () => {
111115
const handlerDefault = new ZAiHandler({ zaiApiKey: "test-zai-api-key" })
112-
expect(OpenAI).toHaveBeenCalledWith(expect.objectContaining({ baseURL: "https://api.z.ai/api/paas/v4" }))
116+
expect(OpenAI).toHaveBeenCalledWith(
117+
expect.objectContaining({
118+
baseURL: "https://api.z.ai/api/coding/paas/v4",
119+
}),
120+
)
113121

114122
const model = handlerDefault.getModel()
115123
expect(model.id).toBe(internationalZAiDefaultModelId)

src/api/providers/zai.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
type InternationalZAiModelId,
77
type MainlandZAiModelId,
88
ZAI_DEFAULT_TEMPERATURE,
9+
zaiApiLineConfigs,
910
} from "@roo-code/types"
1011

1112
import type { ApiHandlerOptions } from "../../shared/api"
@@ -14,14 +15,14 @@ import { BaseOpenAiCompatibleProvider } from "./base-openai-compatible-provider"
1415

1516
export class ZAiHandler extends BaseOpenAiCompatibleProvider<InternationalZAiModelId | MainlandZAiModelId> {
1617
constructor(options: ApiHandlerOptions) {
17-
const isChina = options.zaiApiLine === "china"
18+
const isChina = zaiApiLineConfigs[options.zaiApiLine ?? "international_coding"].isChina
1819
const models = isChina ? mainlandZAiModels : internationalZAiModels
1920
const defaultModelId = isChina ? mainlandZAiDefaultModelId : internationalZAiDefaultModelId
2021

2122
super({
2223
...options,
2324
providerName: "Z AI",
24-
baseURL: isChina ? "https://open.bigmodel.cn/api/paas/v4" : "https://api.z.ai/api/paas/v4",
25+
baseURL: zaiApiLineConfigs[options.zaiApiLine ?? "international_coding"].baseUrl,
2526
apiKey: options.zaiApiKey ?? "not-provided",
2627
defaultProviderModelId: defaultModelId,
2728
providerModels: models,

webview-ui/src/components/settings/providers/ZAi.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useCallback } from "react"
22
import { VSCodeTextField, VSCodeDropdown, VSCodeOption } from "@vscode/webview-ui-toolkit/react"
33

4-
import type { ProviderSettings } from "@roo-code/types"
4+
import { zaiApiLineConfigs, zaiApiLineSchema, type ProviderSettings } from "@roo-code/types"
55

66
import { useAppTranslation } from "@src/i18n/TranslationContext"
77
import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
@@ -33,15 +33,17 @@ export const ZAi = ({ apiConfiguration, setApiConfigurationField }: ZAiProps) =>
3333
<div>
3434
<label className="block font-medium mb-1">{t("settings:providers.zaiEntrypoint")}</label>
3535
<VSCodeDropdown
36-
value={apiConfiguration.zaiApiLine || "international"}
36+
value={apiConfiguration.zaiApiLine || zaiApiLineSchema.enum.international_coding}
3737
onChange={handleInputChange("zaiApiLine")}
3838
className={cn("w-full")}>
39-
<VSCodeOption value="international" className="p-2">
40-
api.z.ai
41-
</VSCodeOption>
42-
<VSCodeOption value="china" className="p-2">
43-
open.bigmodel.cn
44-
</VSCodeOption>
39+
{zaiApiLineSchema.options.map((zaiApiLine) => {
40+
const config = zaiApiLineConfigs[zaiApiLine]
41+
return (
42+
<VSCodeOption key={zaiApiLine} value={zaiApiLine} className="p-2">
43+
{config.name} ({config.baseUrl})
44+
</VSCodeOption>
45+
)
46+
})}
4547
</VSCodeDropdown>
4648
<div className="text-xs text-vscode-descriptionForeground mt-1">
4749
{t("settings:providers.zaiEntrypointDescription")}
@@ -62,7 +64,7 @@ export const ZAi = ({ apiConfiguration, setApiConfigurationField }: ZAiProps) =>
6264
{!apiConfiguration?.zaiApiKey && (
6365
<VSCodeButtonLink
6466
href={
65-
apiConfiguration.zaiApiLine === "china"
67+
zaiApiLineConfigs[apiConfiguration.zaiApiLine ?? "international_coding"].isChina
6668
? "https://open.bigmodel.cn/console/overview"
6769
: "https://z.ai/manage-apikey/apikey-list"
6870
}

0 commit comments

Comments
 (0)