Skip to content

Commit 9f796a8

Browse files
committed
Implement switch to glm-5.1 for free mode
1 parent 2859e1c commit 9f796a8

9 files changed

Lines changed: 53 additions & 30 deletions

File tree

agents/__tests__/editor.test.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ describe('editor agent', () => {
6262
expect(gpt5Editor.model).toBe('openai/gpt-5.1')
6363
})
6464

65-
test('creates minimax editor', () => {
66-
const minimaxEditor = createCodeEditor({ model: 'minimax' })
67-
expect(minimaxEditor.model).toBe('minimax/minimax-m2.5')
65+
test('creates glm editor', () => {
66+
const glmEditor = createCodeEditor({ model: 'glm' })
67+
expect(glmEditor.model).toBe('z-ai/glm-5.1')
6868
})
6969

7070
test('gpt-5 editor does not include think tags in instructions', () => {
@@ -74,9 +74,9 @@ describe('editor agent', () => {
7474
})
7575

7676
test('glm editor does not include think tags in instructions', () => {
77-
const minimaxEditor = createCodeEditor({ model: 'minimax' })
78-
expect(minimaxEditor.instructionsPrompt).not.toContain('<think>')
79-
expect(minimaxEditor.instructionsPrompt).not.toContain('</think>')
77+
const glmEditor = createCodeEditor({ model: 'glm' })
78+
expect(glmEditor.instructionsPrompt).not.toContain('<think>')
79+
expect(glmEditor.instructionsPrompt).not.toContain('</think>')
8080
})
8181

8282
test('opus editor includes think tags in instructions', () => {
@@ -88,17 +88,17 @@ describe('editor agent', () => {
8888
test('all variants have same base properties', () => {
8989
const opusEditor = createCodeEditor({ model: 'opus' })
9090
const gpt5Editor = createCodeEditor({ model: 'gpt-5' })
91-
const minimaxEditor = createCodeEditor({ model: 'minimax' })
91+
const glmEditor = createCodeEditor({ model: 'glm' })
9292

9393
// All should have same basic structure
9494
expect(opusEditor.displayName).toBe(gpt5Editor.displayName)
95-
expect(gpt5Editor.displayName).toBe(minimaxEditor.displayName)
95+
expect(gpt5Editor.displayName).toBe(glmEditor.displayName)
9696

9797
expect(opusEditor.outputMode).toBe(gpt5Editor.outputMode)
98-
expect(gpt5Editor.outputMode).toBe(minimaxEditor.outputMode)
98+
expect(gpt5Editor.outputMode).toBe(glmEditor.outputMode)
9999

100100
expect(opusEditor.toolNames).toEqual(gpt5Editor.toolNames)
101-
expect(gpt5Editor.toolNames).toEqual(minimaxEditor.toolNames)
101+
expect(gpt5Editor.toolNames).toEqual(glmEditor.toolNames)
102102
})
103103
})
104104

agents/base2/base2.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export function createBase2(
2828

2929
return {
3030
publisher,
31-
model: isFree ? 'minimax/minimax-m2.5' : 'anthropic/claude-opus-4.6',
31+
model: isFree ? 'z-ai/glm-5.1' : 'anthropic/claude-opus-4.6',
3232
providerOptions: isFree ? {
3333
data_collection: 'deny',
3434
} : {

agents/editor/editor-lite.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { createCodeEditor } from './editor'
33
import type { AgentDefinition } from '../types/agent-definition'
44

55
const definition: AgentDefinition = {
6-
...createCodeEditor({ model: 'minimax' }),
6+
...createCodeEditor({ model: 'glm' }),
77
id: 'editor-lite',
88
}
99
export default definition

agents/editor/editor.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ import { publisher } from '../constants'
44
import type { AgentDefinition } from '../types/agent-definition'
55

66
export const createCodeEditor = (options: {
7-
model: 'gpt-5' | 'opus' | 'minimax'
7+
model: 'gpt-5' | 'opus' | 'glm'
88
}): Omit<AgentDefinition, 'id'> => {
99
const { model } = options
1010
return {
1111
publisher,
1212
model:
1313
options.model === 'gpt-5'
1414
? 'openai/gpt-5.1'
15-
: options.model === 'minimax'
16-
? 'minimax/minimax-m2.5'
15+
: options.model === 'glm'
16+
? 'z-ai/glm-5.1'
1717
: 'anthropic/claude-opus-4.6',
1818
...(options.model === 'opus' && {
1919
providerOptions: {
@@ -65,7 +65,7 @@ OR for new files or major rewrites:
6565
}
6666
</codebuff_tool_call>
6767
68-
${model === 'gpt-5' || model === 'minimax'
68+
${model === 'gpt-5' || model === 'glm'
6969
? ''
7070
: `Before you start writing your implementation, you should use <think> tags to think about the best way to implement the changes.
7171

agents/reviewer/code-reviewer-lite.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { createReviewer } from './code-reviewer'
55
const definition: SecretAgentDefinition = {
66
id: 'code-reviewer-lite',
77
publisher,
8-
...createReviewer('minimax/minimax-m2.5'),
8+
...createReviewer('z-ai/glm-5.1'),
99
}
1010

1111
export default definition

agents/types/agent-definition.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ export type ModelName =
424424
| 'moonshotai/kimi-k2.5'
425425
| 'moonshotai/kimi-k2.5:nitro'
426426
| 'z-ai/glm-5'
427+
| 'z-ai/glm-5.1'
427428
| 'z-ai/glm-4.6'
428429
| 'z-ai/glm-4.6:nitro'
429430
| 'z-ai/glm-4.7'

common/src/constants/free-agents.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const FREE_COST_MODE = 'free' as const
1818
*/
1919
export const FREE_MODE_AGENT_MODELS: Record<string, Set<string>> = {
2020
// Root orchestrator
21-
'base2-free': new Set(['minimax/minimax-m2.5']),
21+
'base2-free': new Set(['minimax/minimax-m2.5', 'z-ai/glm-5.1']),
2222

2323
// File exploration agents
2424
'file-picker': new Set(['google/gemini-2.5-flash-lite']),
@@ -33,10 +33,10 @@ export const FREE_MODE_AGENT_MODELS: Record<string, Set<string>> = {
3333
'basher': new Set(['google/gemini-3.1-flash-lite-preview']),
3434

3535
// Editor for free mode
36-
'editor-lite': new Set(['minimax/minimax-m2.5']),
36+
'editor-lite': new Set(['minimax/minimax-m2.5', 'z-ai/glm-5.1']),
3737

3838
// Code reviewer for free mode
39-
'code-reviewer-lite': new Set(['minimax/minimax-m2.5']),
39+
'code-reviewer-lite': new Set(['minimax/minimax-m2.5', 'z-ai/glm-5.1']),
4040

4141
// Thinker for free mode
4242
'thinker-with-files-gemini': new Set(['google/gemini-3.1-pro-preview']),

common/src/templates/initial-agents-dir/types/agent-definition.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ export type ModelName =
424424
| 'moonshotai/kimi-k2.5'
425425
| 'moonshotai/kimi-k2.5:nitro'
426426
| 'z-ai/glm-5'
427+
| 'z-ai/glm-5.1'
427428
| 'z-ai/glm-4.6'
428429
| 'z-ai/glm-4.6:nitro'
429430
| 'z-ai/glm-4.7'

web/src/llm-api/fireworks.ts

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const fireworksAgent = new Agent({
2929
/** Map from OpenRouter model IDs to Fireworks standard API model IDs */
3030
const FIREWORKS_MODEL_MAP: Record<string, string> = {
3131
'minimax/minimax-m2.5': 'accounts/fireworks/models/minimax-m2p5',
32+
'z-ai/glm-5.1': 'accounts/fireworks/models/glm-5p1',
3233
}
3334

3435
/** Flag to enable custom Fireworks deployments (set to false to use global API only) */
@@ -137,12 +138,31 @@ function createFireworksRequest(params: {
137138
})
138139
}
139140

140-
// Fireworks per-token pricing (dollars per token)
141-
const FIREWORKS_INPUT_COST_PER_TOKEN = 0.30 / 1_000_000
142-
const FIREWORKS_CACHED_INPUT_COST_PER_TOKEN = 0.03 / 1_000_000
143-
const FIREWORKS_OUTPUT_COST_PER_TOKEN = 1.20 / 1_000_000
141+
// Fireworks per-token pricing (dollars per token), keyed by OpenRouter model ID
142+
interface FireworksPricing {
143+
inputCostPerToken: number
144+
cachedInputCostPerToken: number
145+
outputCostPerToken: number
146+
}
147+
148+
const FIREWORKS_PRICING_MAP: Record<string, FireworksPricing> = {
149+
'minimax/minimax-m2.5': {
150+
inputCostPerToken: 0.30 / 1_000_000,
151+
cachedInputCostPerToken: 0.03 / 1_000_000,
152+
outputCostPerToken: 1.20 / 1_000_000,
153+
},
154+
'z-ai/glm-5.1': {
155+
inputCostPerToken: 1.40 / 1_000_000,
156+
cachedInputCostPerToken: 0.26 / 1_000_000,
157+
outputCostPerToken: 4.40 / 1_000_000,
158+
},
159+
}
160+
161+
function getFireworksPricing(model: string): FireworksPricing {
162+
return FIREWORKS_PRICING_MAP[model] ?? FIREWORKS_MODEL_MAP['z-ai/glm-5.1']
163+
}
144164

145-
function extractUsageAndCost(usage: Record<string, unknown> | undefined | null): UsageData {
165+
function extractUsageAndCost(usage: Record<string, unknown> | undefined | null, model: string): UsageData {
146166
if (!usage) return { inputTokens: 0, outputTokens: 0, cacheReadInputTokens: 0, reasoningTokens: 0, cost: 0 }
147167
const promptDetails = usage.prompt_tokens_details as Record<string, unknown> | undefined | null
148168
const completionDetails = usage.completion_tokens_details as Record<string, unknown> | undefined | null
@@ -153,11 +173,12 @@ function extractUsageAndCost(usage: Record<string, unknown> | undefined | null):
153173
const reasoningTokens = typeof completionDetails?.reasoning_tokens === 'number' ? completionDetails.reasoning_tokens : 0
154174

155175
// Fireworks doesn't return cost — compute from token counts and known pricing
176+
const pricing = getFireworksPricing(model)
156177
const nonCachedInputTokens = Math.max(0, inputTokens - cacheReadInputTokens)
157178
const cost =
158-
nonCachedInputTokens * FIREWORKS_INPUT_COST_PER_TOKEN +
159-
cacheReadInputTokens * FIREWORKS_CACHED_INPUT_COST_PER_TOKEN +
160-
outputTokens * FIREWORKS_OUTPUT_COST_PER_TOKEN
179+
nonCachedInputTokens * pricing.inputCostPerToken +
180+
cacheReadInputTokens * pricing.cachedInputCostPerToken +
181+
outputTokens * pricing.outputCostPerToken
161182

162183
return { inputTokens, outputTokens, cacheReadInputTokens, reasoningTokens, cost }
163184
}
@@ -192,7 +213,7 @@ export async function handleFireworksNonStream({
192213
const data = await response.json()
193214
const content = data.choices?.[0]?.message?.content ?? ''
194215
const reasoningText = data.choices?.[0]?.message?.reasoning_content ?? data.choices?.[0]?.message?.reasoning ?? ''
195-
const usageData = extractUsageAndCost(data.usage)
216+
const usageData = extractUsageAndCost(data.usage, originalModel)
196217

197218
insertMessageToBigQuery({
198219
messageId: data.id,
@@ -493,7 +514,7 @@ async function handleResponse({
493514
return { state }
494515
}
495516

496-
const usageData = extractUsageAndCost(data.usage as Record<string, unknown>)
517+
const usageData = extractUsageAndCost(data.usage as Record<string, unknown>, originalModel)
497518
const messageId = typeof data.id === 'string' ? data.id : 'unknown'
498519

499520
insertMessageToBigQuery({

0 commit comments

Comments
 (0)