-
Notifications
You must be signed in to change notification settings - Fork 212
Expand file tree
/
Copy pathzai.ts
More file actions
109 lines (92 loc) · 4.18 KB
/
Copy pathzai.ts
File metadata and controls
109 lines (92 loc) · 4.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import { Anthropic } from "@anthropic-ai/sdk"
import OpenAI from "openai"
import {
internationalZAiModels,
mainlandZAiModels,
internationalZAiDefaultModelId,
mainlandZAiDefaultModelId,
type ModelInfo,
ZAI_DEFAULT_TEMPERATURE,
zaiApiLineConfigs,
} from "@roo-code/types"
import { type ApiHandlerOptions, shouldUseReasoningEffort } from "../../shared/api"
import { convertToZAiFormat } from "../transform/zai-format"
import type { ApiHandlerCreateMessageMetadata } from "../index"
import { BaseOpenAiCompatibleProvider } from "./base-openai-compatible-provider"
// Custom interface for Z.ai params to support thinking mode
type ZAiChatCompletionParams = OpenAI.Chat.ChatCompletionCreateParamsStreaming & {
thinking?: { type: "enabled" | "disabled" }
}
export class ZAiHandler extends BaseOpenAiCompatibleProvider<string> {
constructor(options: ApiHandlerOptions) {
const isChina = zaiApiLineConfigs[options.zaiApiLine ?? "international_coding"].isChina
const models = (isChina ? mainlandZAiModels : internationalZAiModels) as unknown as Record<string, ModelInfo>
const defaultModelId = (isChina ? mainlandZAiDefaultModelId : internationalZAiDefaultModelId) as string
super({
...options,
providerName: "Z.ai",
baseURL: zaiApiLineConfigs[options.zaiApiLine ?? "international_coding"].baseUrl,
apiKey: options.zaiApiKey ?? "not-provided",
defaultProviderModelId: defaultModelId,
providerModels: models,
defaultTemperature: ZAI_DEFAULT_TEMPERATURE,
})
}
/**
* Override createStream to handle GLM thinking-capable models.
* These models have thinking enabled by default in the API, so we need to
* explicitly send { type: "disabled" } when the user turns off reasoning.
*/
protected override createStream(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
requestOptions?: OpenAI.RequestOptions,
) {
const { id: modelId, info } = this.getModel()
// Check if this is a model with thinking support (e.g. GLM-4.7, GLM-5)
const isThinkingModel = Array.isArray(info.supportsReasoningEffort)
if (isThinkingModel) {
// For GLM-4.7, thinking is ON by default in the API.
// We need to explicitly disable it when reasoning is off.
const useReasoning = shouldUseReasoningEffort({ model: info, settings: this.options })
// Create the stream with our custom thinking parameter
return this.createStreamWithThinking(systemPrompt, messages, metadata, useReasoning)
}
// For non-thinking models, use the default behavior
return super.createStream(systemPrompt, messages, metadata, requestOptions)
}
/**
* Creates a stream with explicit thinking control for GLM thinking-capable models.
*/
private createStreamWithThinking(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
useReasoning?: boolean,
) {
const { id: model, info } = this.getModel()
// Use info.maxTokens directly — Z.ai model definitions are hand-curated and accurate.
// getModelMaxOutputTokens clamps to 20% of contextWindow (a guard for OpenRouter dynamic
// metadata where maxTokens ≈ contextWindow), but ApiHandlerOptions omits apiProvider so
// the zai bypass in api.ts never fires. glm-5.1 legitimately supports 128k output.
const max_tokens = this.options.modelMaxTokens || (info.maxTokens ?? undefined)
const temperature = this.options.modelTemperature ?? this.defaultTemperature
// Use Z.ai format to preserve reasoning_content and merge post-tool text into tool messages
const convertedMessages = convertToZAiFormat(messages, { mergeToolResultText: true })
const params: ZAiChatCompletionParams = {
model,
max_tokens,
temperature,
messages: [{ role: "system", content: systemPrompt }, ...convertedMessages],
stream: true,
stream_options: { include_usage: true },
// Thinking is ON by default for these models, so explicitly disable it when needed.
thinking: useReasoning ? { type: "enabled" } : { type: "disabled" },
tools: this.convertToolsForOpenAI(metadata?.tools),
tool_choice: metadata?.tool_choice,
parallel_tool_calls: metadata?.parallelToolCalls ?? true,
}
return this.client.chat.completions.create(params)
}
}