Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/types/src/provider-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ const sambaNovaSchema = apiModelIdProviderModelSchema.extend({
sambaNovaApiKey: z.string().optional(),
})

export const zaiApiLineSchema = z.enum(["international_coding", "china_coding"])
export const zaiApiLineSchema = z.enum(["international_coding", "international", "china_coding", "china"])

export type ZaiApiLine = z.infer<typeof zaiApiLineSchema>

Expand Down
115 changes: 101 additions & 14 deletions packages/types/src/providers/zai.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { ModelInfo } from "../model.js"
import { ZaiApiLine } from "../provider-settings.js"

// Z AI
// https://docs.z.ai/guides/llm/glm-4.5
// https://docs.z.ai/guides/llm/glm-4.6
// https://docs.z.ai/guides/overview/pricing

export type InternationalZAiModelId = keyof typeof internationalZAiModels
Expand All @@ -20,6 +20,30 @@ export const internationalZAiModels = {
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.6": {
maxTokens: 98_304,
contextWindow: 204_800,
supportsImages: false,
supportsPromptCache: true,
inputPrice: 0.6,
outputPrice: 2.2,
cacheWritesPrice: 0,
cacheReadsPrice: 0.11,
description:
"GLM-4.6 is Zhipu's newest model with an extended context window of up to 200k tokens, providing enhanced capabilities for processing longer documents and conversations.",
},
"glm-4.5v": {
maxTokens: 16_384,
contextWindow: 64_000,
supportsImages: true,
supportsPromptCache: true,
inputPrice: 0.6,
outputPrice: 1.8,
cacheWritesPrice: 0,
cacheReadsPrice: 0.11,
// International pricing tiers for GLM-4.5V are not publicly documented as of 2025-10-20; mainland tiers are defined below.
description: "GLM-4.5V is Zhipu's new generation of visual reasoning models based on the MOE architecture.",
},
"glm-4.5-air": {
maxTokens: 98_304,
contextWindow: 131_072,
Expand All @@ -32,17 +56,49 @@ export const internationalZAiModels = {
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.",
},
"glm-4.6": {
"glm-4.5-x": {
maxTokens: 98_304,
contextWindow: 204_800,
contextWindow: 131_072,
supportsImages: false,
supportsPromptCache: true,
inputPrice: 0.6,
outputPrice: 2.2,
inputPrice: 2.2,
outputPrice: 8.9,
cacheWritesPrice: 0,
cacheReadsPrice: 0.11,
description:
"GLM-4.6 is Zhipu's newest model with an extended context window of up to 200k tokens, providing enhanced capabilities for processing longer documents and conversations.",
cacheReadsPrice: 0.45,
description: "GLM-4.5-X is the extended version with enhanced capabilities and performance for complex tasks.",
},
"glm-4.5-airx": {
maxTokens: 98_304,
contextWindow: 131_072,
supportsImages: false,
supportsPromptCache: true,
inputPrice: 1.1,
outputPrice: 4.5,
cacheWritesPrice: 0,
cacheReadsPrice: 0.22,
description: "GLM-4.5-AirX is the extended version of GLM-4.5-Air with enhanced capabilities.",
},
"glm-4-32b-0414-128k": {
maxTokens: 98_304,
contextWindow: 131_072,
supportsImages: false,
supportsPromptCache: false,
inputPrice: 0.1,
outputPrice: 0.1,
cacheWritesPrice: 0,
cacheReadsPrice: 0,
description: "GLM-4-32B is a 32 billion parameter model with 128k context length, optimized for efficiency.",
},
"glm-4.5-flash": {
maxTokens: 98_304,
contextWindow: 131_072,
supportsImages: false,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
cacheWritesPrice: 0,
cacheReadsPrice: 0,
description: "Zhipu's most advanced free model to date.",
},
} as const satisfies Record<string, ModelInfo>

Expand Down Expand Up @@ -113,6 +169,37 @@ export const mainlandZAiModels = {
},
],
},
"glm-4.5v": {
maxTokens: 16_384,
contextWindow: 64_000,
supportsImages: true,
supportsPromptCache: true,
inputPrice: 0.6,
outputPrice: 1.8,
cacheWritesPrice: 0,
cacheReadsPrice: 0.11,
description: "GLM-4.5V is Zhipu's new generation of visual reasoning models based on the MOE architecture.",
tiers: [
{
contextWindow: 32_000,
inputPrice: 0.21,
outputPrice: 0.4,
cacheReadsPrice: 0.06,
},
{
contextWindow: 64_000,
inputPrice: 0.6,
outputPrice: 1.8,
cacheReadsPrice: 0.11,
},
{
contextWindow: Infinity,
inputPrice: 0.6,
outputPrice: 1.8,
cacheReadsPrice: 0.11,
},
],
},
"glm-4.6": {
maxTokens: 98_304,
contextWindow: 204_800,
Expand Down Expand Up @@ -155,15 +242,15 @@ export const mainlandZAiModels = {

export const ZAI_DEFAULT_TEMPERATURE = 0

type ZaiApiLineLiteral = "international_coding" | "international" | "china_coding" | "china"

export const zaiApiLineConfigs = {
international_coding: {
name: "International Coding Plan",
baseUrl: "https://api.z.ai/api/coding/paas/v4",
isChina: false,
},
china_coding: {
name: "China Coding Plan",
baseUrl: "https://open.bigmodel.cn/api/coding/paas/v4",
isChina: true,
},
} satisfies Record<ZaiApiLine, { name: string; baseUrl: string; isChina: boolean }>
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<ZaiApiLineLiteral, { name: string; baseUrl: string; isChina: boolean }>
33 changes: 33 additions & 0 deletions src/api/providers/__tests__/zai.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,20 @@ describe("ZAiHandler", () => {
expect(model.info).toEqual(internationalZAiModels[testModelId])
expect(model.info.contextWindow).toBe(204_800)
})

it("should return GLM-4.5V international model with image support", () => {
const testModelId: InternationalZAiModelId = "glm-4.5v"
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])
expect(model.info.supportsImages).toBe(true)
expect(model.info.contextWindow).toBe(64_000)
})
})

describe("China Z AI", () => {
Expand Down Expand Up @@ -134,6 +148,25 @@ describe("ZAiHandler", () => {
expect(model.info).toEqual(mainlandZAiModels[testModelId])
expect(model.info.contextWindow).toBe(204_800)
})

it("should return GLM-4.5V China model with image support", () => {
const testModelId: MainlandZAiModelId = "glm-4.5v"
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])
expect(model.info.supportsImages).toBe(true)
expect(model.info.contextWindow).toBe(64_000)
})

it("should include tiers for GLM-4.5V China model", () => {
const info = mainlandZAiModels["glm-4.5v"]
expect(info.tiers?.length).toBe(3)
})
})

describe("Default behavior", () => {
Expand Down
34 changes: 26 additions & 8 deletions src/api/providers/zai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,47 @@ import {
mainlandZAiModels,
internationalZAiDefaultModelId,
mainlandZAiDefaultModelId,
type InternationalZAiModelId,
type MainlandZAiModelId,
ZAI_DEFAULT_TEMPERATURE,
zaiApiLineConfigs,
} from "@roo-code/types"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Re-introduce type-only imports so the class can use the precise union type without any-casts (e.g., type InternationalZAiModelId, type MainlandZAiModelId).


import type { ApiHandlerOptions } from "../../shared/api"
import type { InternationalZAiModelId, MainlandZAiModelId, ModelInfo } from "@roo-code/types"

import { BaseOpenAiCompatibleProvider } from "./base-openai-compatible-provider"

export class ZAiHandler extends BaseOpenAiCompatibleProvider<InternationalZAiModelId | MainlandZAiModelId> {
type ZAiModelId = InternationalZAiModelId | MainlandZAiModelId

// Local mapping to avoid cross-package runtime dependency issues in CI
type ZaiApiLineLocal = "international_coding" | "international" | "china_coding" | "china"
const ZAI_LINE_CONFIGS: Record<ZaiApiLineLocal, { name: string; baseUrl: string; isChina: boolean }> = {
international_coding: {
name: "International Coding Plan",
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 },
}

export class ZAiHandler extends BaseOpenAiCompatibleProvider<ZAiModelId> {
constructor(options: ApiHandlerOptions) {
const isChina = zaiApiLineConfigs[options.zaiApiLine ?? "international_coding"].isChina
const models = isChina ? mainlandZAiModels : internationalZAiModels
const line = (options.zaiApiLine ?? "international_coding") as ZaiApiLineLocal
const { isChina, baseUrl } = ZAI_LINE_CONFIGS[line]

const defaultModelId = isChina ? mainlandZAiDefaultModelId : internationalZAiDefaultModelId
const providerModels = (isChina ? mainlandZAiModels : internationalZAiModels) as unknown as Record<
ZAiModelId,
ModelInfo
>

super({
...options,
providerName: "Z AI",
baseURL: zaiApiLineConfigs[options.zaiApiLine ?? "international_coding"].baseUrl,
baseURL: baseUrl,
apiKey: options.zaiApiKey ?? "not-provided",
defaultProviderModelId: defaultModelId,
providerModels: models,
providerModels,
defaultTemperature: ZAI_DEFAULT_TEMPERATURE,
})
}
Expand Down