fix: limit Z AI to only two coding endpoints (International/China)

- Updated zaiApiLineSchema to only include international_coding and china_coding
- Removed non-coding endpoints (international, china) from zaiApiLineConfigs
- Added migration in ProviderSettingsManager to convert old values to new ones
- Updated UI components to use china_coding instead of china
- Updated tests to reflect the new endpoint structure

Fixes #8687
This commit is contained in:
Roo Code 2025-10-16 18:35:03 +00:00
parent 270dce5050
commit 3bd349ec64
6 changed files with 45 additions and 20 deletions

View file

@ -377,7 +377,7 @@ const sambaNovaSchema = apiModelIdProviderModelSchema.extend({
sambaNovaApiKey: z.string().optional(),
})
export const zaiApiLineSchema = z.enum(["international_coding", "international", "china_coding", "china"])
export const zaiApiLineSchema = z.enum(["international_coding", "china_coding"])
export type ZaiApiLine = z.infer<typeof zaiApiLineSchema>

View file

@ -161,7 +161,5 @@ export const zaiApiLineConfigs = {
baseUrl: "https://api.z.ai/api/coding/paas/v4",
isChina: false,
},
international: { name: "International Standard", baseUrl: "https://api.z.ai/api/paas/v4", isChina: false },
china_coding: { name: "China Coding Plan", baseUrl: "https://open.bigmodel.cn/api/coding/paas/v4", isChina: true },
china: { name: "China Standard", baseUrl: "https://open.bigmodel.cn/api/paas/v4", isChina: true },
} satisfies Record<ZaiApiLine, { name: string; baseUrl: string; isChina: boolean }>

View file

@ -36,21 +36,21 @@ describe("ZAiHandler", () => {
describe("International Z AI", () => {
beforeEach(() => {
handler = new ZAiHandler({ zaiApiKey: "test-zai-api-key", zaiApiLine: "international" })
handler = new ZAiHandler({ zaiApiKey: "test-zai-api-key", zaiApiLine: "international_coding" })
})
it("should use the correct international Z AI base URL", () => {
new ZAiHandler({ zaiApiKey: "test-zai-api-key", zaiApiLine: "international" })
new ZAiHandler({ zaiApiKey: "test-zai-api-key", zaiApiLine: "international_coding" })
expect(OpenAI).toHaveBeenCalledWith(
expect.objectContaining({
baseURL: "https://api.z.ai/api/paas/v4",
baseURL: "https://api.z.ai/api/coding/paas/v4",
}),
)
})
it("should use the provided API key for international", () => {
const zaiApiKey = "test-zai-api-key"
new ZAiHandler({ zaiApiKey, zaiApiLine: "international" })
new ZAiHandler({ zaiApiKey, zaiApiLine: "international_coding" })
expect(OpenAI).toHaveBeenCalledWith(expect.objectContaining({ apiKey: zaiApiKey }))
})
@ -65,7 +65,7 @@ describe("ZAiHandler", () => {
const handlerWithModel = new ZAiHandler({
apiModelId: testModelId,
zaiApiKey: "test-zai-api-key",
zaiApiLine: "international",
zaiApiLine: "international_coding",
})
const model = handlerWithModel.getModel()
expect(model.id).toBe(testModelId)
@ -77,7 +77,7 @@ describe("ZAiHandler", () => {
const handlerWithModel = new ZAiHandler({
apiModelId: testModelId,
zaiApiKey: "test-zai-api-key",
zaiApiLine: "international",
zaiApiLine: "international_coding",
})
const model = handlerWithModel.getModel()
expect(model.id).toBe(testModelId)
@ -88,19 +88,19 @@ describe("ZAiHandler", () => {
describe("China Z AI", () => {
beforeEach(() => {
handler = new ZAiHandler({ zaiApiKey: "test-zai-api-key", zaiApiLine: "china" })
handler = new ZAiHandler({ zaiApiKey: "test-zai-api-key", zaiApiLine: "china_coding" })
})
it("should use the correct China Z AI base URL", () => {
new ZAiHandler({ zaiApiKey: "test-zai-api-key", zaiApiLine: "china" })
new ZAiHandler({ zaiApiKey: "test-zai-api-key", zaiApiLine: "china_coding" })
expect(OpenAI).toHaveBeenCalledWith(
expect.objectContaining({ baseURL: "https://open.bigmodel.cn/api/paas/v4" }),
expect.objectContaining({ baseURL: "https://open.bigmodel.cn/api/coding/paas/v4" }),
)
})
it("should use the provided API key for China", () => {
const zaiApiKey = "test-zai-api-key"
new ZAiHandler({ zaiApiKey, zaiApiLine: "china" })
new ZAiHandler({ zaiApiKey, zaiApiLine: "china_coding" })
expect(OpenAI).toHaveBeenCalledWith(expect.objectContaining({ apiKey: zaiApiKey }))
})
@ -115,7 +115,7 @@ describe("ZAiHandler", () => {
const handlerWithModel = new ZAiHandler({
apiModelId: testModelId,
zaiApiKey: "test-zai-api-key",
zaiApiLine: "china",
zaiApiLine: "china_coding",
})
const model = handlerWithModel.getModel()
expect(model.id).toBe(testModelId)
@ -127,7 +127,7 @@ describe("ZAiHandler", () => {
const handlerWithModel = new ZAiHandler({
apiModelId: testModelId,
zaiApiKey: "test-zai-api-key",
zaiApiLine: "china",
zaiApiLine: "china_coding",
})
const model = handlerWithModel.getModel()
expect(model.id).toBe(testModelId)
@ -151,14 +151,14 @@ describe("ZAiHandler", () => {
})
it("should use 'not-provided' as default API key when none is specified", () => {
new ZAiHandler({ zaiApiLine: "international" })
new ZAiHandler({ zaiApiLine: "international_coding" })
expect(OpenAI).toHaveBeenCalledWith(expect.objectContaining({ apiKey: "not-provided" }))
})
})
describe("API Methods", () => {
beforeEach(() => {
handler = new ZAiHandler({ zaiApiKey: "test-zai-api-key", zaiApiLine: "international" })
handler = new ZAiHandler({ zaiApiKey: "test-zai-api-key", zaiApiLine: "international_coding" })
})
it("completePrompt method should return text from Z AI API", async () => {
@ -231,7 +231,7 @@ describe("ZAiHandler", () => {
const handlerWithModel = new ZAiHandler({
apiModelId: modelId,
zaiApiKey: "test-zai-api-key",
zaiApiLine: "international",
zaiApiLine: "international_coding",
})
mockCreate.mockImplementationOnce(() => {

View file

@ -46,6 +46,7 @@ export const providerProfilesSchema = z.object({
openAiHeadersMigrated: z.boolean().optional(),
consecutiveMistakeLimitMigrated: z.boolean().optional(),
todoListEnabledMigrated: z.boolean().optional(),
zaiApiLineMigrated: z.boolean().optional(),
})
.optional(),
})
@ -70,6 +71,7 @@ export class ProviderSettingsManager {
openAiHeadersMigrated: true, // Mark as migrated on fresh installs
consecutiveMistakeLimitMigrated: true, // Mark as migrated on fresh installs
todoListEnabledMigrated: true, // Mark as migrated on fresh installs
zaiApiLineMigrated: true, // Mark as migrated on fresh installs
},
}
@ -142,6 +144,7 @@ export class ProviderSettingsManager {
openAiHeadersMigrated: false,
consecutiveMistakeLimitMigrated: false,
todoListEnabledMigrated: false,
zaiApiLineMigrated: false,
} // Initialize with default values
isDirty = true
}
@ -176,6 +179,12 @@ export class ProviderSettingsManager {
isDirty = true
}
if (!providerProfiles.migrations.zaiApiLineMigrated) {
await this.migrateZaiApiLine(providerProfiles)
providerProfiles.migrations.zaiApiLineMigrated = true
isDirty = true
}
if (isDirty) {
await this.store(providerProfiles)
}
@ -293,6 +302,24 @@ export class ProviderSettingsManager {
}
}
private async migrateZaiApiLine(providerProfiles: ProviderProfiles) {
try {
for (const [_name, apiConfig] of Object.entries(providerProfiles.apiConfigs)) {
// Cast to any to access the zaiApiLine property which might exist
const configAny = apiConfig as any
// Migrate old "international" and "china" values to new "international_coding" and "china_coding"
if (configAny.zaiApiLine === "international") {
configAny.zaiApiLine = "international_coding"
} else if (configAny.zaiApiLine === "china") {
configAny.zaiApiLine = "china_coding"
}
}
} catch (error) {
console.error(`[MigrateZaiApiLine] Failed to migrate Z AI API line settings:`, error)
}
}
/**
* Apply model migrations for all providers
* Returns true if any migrations were applied

View file

@ -345,7 +345,7 @@ const ApiOptions = ({
zai: {
field: "apiModelId",
default:
apiConfiguration.zaiApiLine === "china"
apiConfiguration.zaiApiLine === "china_coding"
? mainlandZAiDefaultModelId
: internationalZAiDefaultModelId,
},

View file

@ -238,7 +238,7 @@ function getSelectedModel({
return { id, info }
}
case "zai": {
const isChina = apiConfiguration.zaiApiLine === "china"
const isChina = apiConfiguration.zaiApiLine === "china_coding"
const models = isChina ? mainlandZAiModels : internationalZAiModels
const defaultModelId = isChina ? mainlandZAiDefaultModelId : internationalZAiDefaultModelId
const id = apiConfiguration.apiModelId ?? defaultModelId