Skip to content

Commit 83b7cdf

Browse files
author
liumingyao.marvin
committed
Merge remote-tracking branch 'upstream/main' into agent-tasks/1125
2 parents 55cffdd + 5c59201 commit 83b7cdf

17 files changed

Lines changed: 563 additions & 172 deletions

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@ Freebuff includes a curated model catalog. The regular picker currently offers:
3838
| **DeepSeek V4 Flash 07/31** | Full access | Fast coding and tool use; pauses during peak hours |
3939
| **MiMo 2.5** | Full and limited access | The limited-mode default; balanced performance with image support |
4040
| **Ox Alpha** | Full and limited access | 1M context, no session cost; experimental — may be unreliable |
41-
| **DeepSeek V4 Pro** | Full access | Deepest reasoning |
41+
| **GLM 5.3 Flash** | Full access | Deepest reasoning; 2 sessions a day |
4242

43-
Per-model daily caps are **gone**: every model now draws on your normal daily sessions rather than its own separate limit. MiMo 2.5 and Ox Alpha stay unmetered and cost no session at all. Models may still serve from a quantized (Q8_0) build.
43+
Most models draw on your normal daily sessions rather than a separate limit. GLM 5.3 Flash is the exception, capped at 2 sessions a day while we measure what it costs at scale. MiMo 2.5 and Ox Alpha stay unmetered and cost no session at all. Models may still serve from a quantized (Q8_0) build.
44+
45+
DeepSeek V4 Pro was retired from the catalog; GLM 5.3 Flash replaces it as the deep-reasoning pick.
4446

4547
Beyond the regular picker:
4648

README.zh-CN.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@ Freebuff 提供经过筛选的模型目录。常规模型选择器目前包括
3838
| **DeepSeek V4 Flash 07/31** | 完整访问 | 快速编程和工具调用;高峰时段暂停 |
3939
| **MiMo 2.5** | 完整和受限访问 | 受限模式的默认模型;均衡性能并支持图像 |
4040
| **Ox Alpha** | 完整和受限访问 | 100 万上下文,不消耗会话;实验性功能,可能不稳定 |
41-
| **DeepSeek V4 Pro** | 完整访问 | 推理最深入 |
41+
| **GLM 5.3 Flash** | 完整访问 | 推理最深入;每天 2 次会话 |
4242

43-
单个模型的每日上限**已取消**:所有模型现在都使用你的常规每日会话,而不再各自设限。MiMo 2.5 和 Ox Alpha 保持无限使用,完全不消耗会话。模型仍可能由量化(Q8_0)版本提供服务。
43+
大多数模型使用你的常规每日会话,而不再各自设限。GLM 5.3 Flash 是例外:在我们评估其规模化成本期间,每天限用 2 次会话。MiMo 2.5 和 Ox Alpha 保持无限使用,完全不消耗会话。模型仍可能由量化(Q8_0)版本提供服务。
44+
45+
DeepSeek V4 Pro 已从模型目录中下线,由 GLM 5.3 Flash 接替其深度推理的位置。
4446

4547
常规模型选择器之外:
4648

agents/__tests__/base3.test.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import base3FreeDeepseekFlash from '../base3-free-deepseek-flash'
1212
import base3FreeDeepseekFlashEvals from '../base3-free-deepseek-flash-evals'
1313
import base3FreeFable from '../base3-free-fable'
1414
import base3FreeGlm from '../base3-free-glm'
15+
import base3FreeGlmV53Flash from '../base3-free-glm-5-3-flash'
1516
import base3FreeLuna from '../base3-free-luna'
1617
import base3FreeMimo from '../base3-free-mimo'
1718
import base3FreeMinimaxM3 from '../base3-free-minimax-m3'
@@ -45,16 +46,17 @@ const CLI_ROOTS = [
4546
base3FreeMinimaxM3,
4647
base3FreeMimo,
4748
base3FreeGlm,
49+
base3FreeGlmV53Flash,
4850
base3FreeLuna,
4951
base3FreeFable,
5052
base3FreeOxAlpha,
5153
]
5254

5355
describe('base3 CLI roots', () => {
5456
test('keeps the efficiency flags the runtime reads', () => {
55-
// 12 since Ox Alpha reached the CLI on 2026-08-24. The count is asserted so
56-
// a root added without the flags below cannot slip in unnoticed.
57-
expect(CLI_ROOTS.length).toBe(12)
57+
// 13 since GLM 5.3 Flash shipped on 2026-08-26. The count is asserted so a
58+
// root added without the flags below cannot slip in unnoticed.
59+
expect(CLI_ROOTS.length).toBe(13)
5860
for (const agent of CLI_ROOTS) {
5961
// Windowed reads + the 100-entry glob cap + search-first tool wording.
6062
expect(agent.windowedFileReads).toBe(true)

agents/base-chat.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ End every response by calling the suggest_followups tool with exactly 3 followup
6666
'meta/muse-spark-1.2-contributor': 1_000_000,
6767
// Ox Alpha: 1,048,576 published, entered low for the same reason.
6868
'stealth/ox-alpha': 1_000_000,
69+
// GLM 5.3 Flash: 1,310,720 published, entered low for the same reason.
70+
'z-ai/glm-5.3-flash': 1_000_000,
6971
}
7072

7173
/** For any model not listed above. Assuming a window is smaller than it is
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { FREEBUFF_GLM_V53_FLASH_MODEL_ID } from '@codebuff/common/constants/freebuff-models'
2+
3+
import { createBase2 } from './base2'
4+
5+
const definition = {
6+
...createBase2('free', {
7+
model: FREEBUFF_GLM_V53_FLASH_MODEL_ID,
8+
}),
9+
id: 'base2-free-glm-5-3-flash',
10+
displayName: 'Buffy the GLM 5.3 Flash Free Orchestrator',
11+
}
12+
13+
export default definition

agents/base3-free-glm-5-3-flash.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { FREEBUFF_GLM_V53_FLASH_MODEL_ID } from '@codebuff/common/constants/freebuff-models'
2+
3+
import { createBase3CliRoot } from './base3'
4+
5+
// No `reasoningOptions`, for the reason spelled out on base3-free-luna: an
6+
// agent-declared reasoning reaches the wire as `body.reasoning`, which makes
7+
// the definition rather than the user the authority on effort. It costs nothing
8+
// here in particular — OpenRouter reports no effort levels for this model, so
9+
// the catalog row declares no ladder and the picker shows no control.
10+
const definition = {
11+
...createBase3CliRoot({
12+
model: FREEBUFF_GLM_V53_FLASH_MODEL_ID,
13+
isFreebuff: true,
14+
}),
15+
id: 'base3-free-glm-5-3-flash',
16+
displayName: 'Buffy on GLM 5.3 Flash',
17+
}
18+
19+
export default definition
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { FREEBUFF_GLM_V53_FLASH_MODEL_ID } from '@codebuff/common/constants/freebuff-models'
2+
3+
import { publisher } from '../constants'
4+
import type { SecretAgentDefinition } from '../types/secret-agent-definition'
5+
import { createReviewer } from './code-reviewer'
6+
7+
// Runs the SAME model as the root that spawns it. Not a style choice: the
8+
// chat-completions session gate rejects any request whose model differs from
9+
// the one the session was admitted on, so a cross-model reviewer 403s mid-run.
10+
const definition: SecretAgentDefinition = {
11+
id: 'code-reviewer-glm-5-3-flash',
12+
publisher,
13+
...createReviewer(FREEBUFF_GLM_V53_FLASH_MODEL_ID),
14+
}
15+
16+
export default definition

cli/src/components/__tests__/freebuff-model-selector.test.tsx

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
FALLBACK_FREEBUFF_MODEL_ID,
1111
FREEBUFF_DEEPSEEK_V4_FLASH_MODEL_ID,
1212
FREEBUFF_MIMO_V25_MODEL_ID,
13-
FREEBUFF_DEEPSEEK_V4_PRO_MODEL_ID,
13+
FREEBUFF_GLM_V53_FLASH_MODEL_ID,
1414
FREEBUFF_FABLE_5_MODEL_ID,
1515
FREEBUFF_GLM_V52_MODEL_ID,
1616
FREEBUFF_GPT_5_6_LUNA_MODEL_ID,
@@ -164,18 +164,19 @@ describe('FreebuffModelSelector tier layout', () => {
164164
// premium or the tier headers it is being ordered against don't apply to
165165
// it, non-hero or the landing picker opens collapsed and there are no tier
166166
// headers at all. The hero is GPT-5.6 Luna since 2026-08-24, which leaves
167-
// V4 Pro as the only row that is both. Flash filled this slot until
167+
// GLM 5.3 Flash as the only row that is both. Flash filled this slot until
168168
// 2026-08-24, when it left FREEBUFF_PREMIUM_MODEL_IDS and moved down into
169-
// UNLIMITED -- below the header this asserts it sits above.
169+
// UNLIMITED -- below the header this asserts it sits above; V4 Pro until
170+
// its withdrawal on 2026-08-26.
170171
useFreebuffModelStore
171172
.getState()
172-
.setSelectedModel(FREEBUFF_DEEPSEEK_V4_PRO_MODEL_ID)
173+
.setSelectedModel(FREEBUFF_GLM_V53_FLASH_MODEL_ID)
173174

174175
const setup = await renderSelector()
175176
const frame = setup.captureCharFrame()
176177
const premiumHeaderIndex = frame.indexOf('PREMIUM')
177178
const recommendedModelIndex = frame.indexOf('GPT-5.6 Luna')
178-
const selectedModelIndex = frame.indexOf('DeepSeek V4 Pro')
179+
const selectedModelIndex = frame.indexOf('GLM 5.3 Flash')
179180
const unlimitedHeaderIndex = frame.indexOf('UNLIMITED')
180181

181182
expect(premiumHeaderIndex).toBeGreaterThanOrEqual(0)
@@ -185,7 +186,7 @@ describe('FreebuffModelSelector tier layout', () => {
185186
// 2026-08-20 and left the picker entirely.
186187
expect(unlimitedHeaderIndex).toBeGreaterThan(selectedModelIndex)
187188
// The cursor sits on the SAVED pick, not on the recommendation.
188-
expect(frame).toContain('› DeepSeek V4 Pro')
189+
expect(frame).toContain('› GLM 5.3 Flash')
189190
expect(frame).not.toContain('› GPT-5.6 Luna')
190191
})
191192

@@ -377,7 +378,7 @@ describe('FreebuffModelSelector tier layout', () => {
377378
})
378379
useFreebuffModelStore
379380
.getState()
380-
.setSelectedModel(FREEBUFF_DEEPSEEK_V4_PRO_MODEL_ID)
381+
.setSelectedModel(FREEBUFF_GLM_V53_FLASH_MODEL_ID)
381382
const setup = await renderSelector()
382383

383384
flushSync(() => {
@@ -486,16 +487,16 @@ describe('FreebuffModelSelector tier layout', () => {
486487
accessTier: 'full',
487488
// Flash sends no pool row at all since 2026-08-24: it is unmetered.
488489
rateLimitsByModel: {
489-
[FREEBUFF_DEEPSEEK_V4_PRO_MODEL_ID]: pool(
490-
FREEBUFF_DEEPSEEK_V4_PRO_MODEL_ID,
490+
[FREEBUFF_GPT_5_6_LUNA_MODEL_ID]: pool(
491+
FREEBUFF_GPT_5_6_LUNA_MODEL_ID,
491492
'premium',
492493
'Premium',
493494
4,
494495
),
495-
[FREEBUFF_GPT_5_6_LUNA_MODEL_ID]: pool(
496-
FREEBUFF_GPT_5_6_LUNA_MODEL_ID,
497-
'luna',
498-
'Luna',
496+
[FREEBUFF_GLM_V53_FLASH_MODEL_ID]: pool(
497+
FREEBUFF_GLM_V53_FLASH_MODEL_ID,
498+
'glm_v53_flash',
499+
'GLM 5.3 Flash',
499500
2,
500501
),
501502
},
@@ -505,8 +506,8 @@ describe('FreebuffModelSelector tier layout', () => {
505506
// NOT the hero, so the picker opens expanded and the chip under test is
506507
// drawn at all. Luna took the hero slot on 2026-08-24; selecting it here
507508
// collapses the list to a single row and the chip disappears. Flash also
508-
// supplies the warning-ONLY second line asserted below, which no premium
509-
// row has any more now that V4 Pro's carries the chip as well.
509+
// supplies the warning-ONLY second line asserted below, which the chip
510+
// row cannot: every row carrying a pool row here also carries a chip.
510511
.setSelectedModel(FREEBUFF_DEEPSEEK_V4_FLASH_MODEL_ID)
511512

512513
const frame = (await renderSelector()).captureCharFrame()
@@ -522,11 +523,13 @@ describe('FreebuffModelSelector tier layout', () => {
522523
]
523524
}
524525
const lines = frame.split('\n')
525-
// V4 Pro's second line carries the training warning AND the chip. Anchored
526-
// on the chip, so a chip that stops being drawn fails here rather than
527-
// quietly re-measuring some warning-only line instead.
528-
const chipLine = lines.find((l) => l.includes('Premium: 0 of 4 used'))
529-
// Flash's carries the same warning with nothing after it — the shape the
526+
// GLM 5.3 Flash's second line carries its per-model ceiling chip. Anchored
527+
// on the chip text, so a chip that stops being drawn fails here rather than
528+
// quietly re-measuring some warning-only line instead. Deliberately the
529+
// PER-MODEL pool rather than the shared one: its label is the longest the
530+
// caps table can produce, which is the case the width math has to survive.
531+
const chipLine = lines.find((l) => l.includes('GLM 5.3 Flash: 0 of 2 used'))
532+
// Flash carries the training warning with nothing after it — the shape the
530533
// width math already handled, which is the "ordinary warning line" above.
531534
const warningOnlyLine = lines.find(
532535
(l) => l.includes('May use data for AI training') && !l.includes('used'),

cli/src/utils/__tests__/settings.test.ts

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
FREEBUFF_GLM_V52_MODEL_ID,
1010
FREEBUFF_MIMO_V25_MODEL_ID,
1111
FREEBUFF_DEEPSEEK_V4_PRO_MODEL_ID,
12+
FREEBUFF_GLM_V53_FLASH_MODEL_ID,
1213
} from '@codebuff/common/constants/freebuff-models'
1314

1415
import * as auth from '../auth'
@@ -48,33 +49,56 @@ describe('freebuff model preference', () => {
4849
)
4950
getConfigDirSpy = spyOn(auth, 'getConfigDir').mockReturnValue(testConfigDir)
5051

51-
// Two tests lived here, both asserting a stored V4 Pro pick was rewritten
52-
// to Flash on every launch. That migration is GONE as of 2026-08-21 along
53-
// with the supersedes notice driving it — Pro is now the cheapest premium
54-
// row and the catalog's first entry, so steering off it would be backwards.
55-
//
5652
// Written directly, with no migration marker, exactly like a real
5753
// pre-upgrade settings file — which is the case that would silently rewrite
58-
// if a notice came back.
54+
// if a supersedes notice came back.
5955
fs.writeFileSync(
6056
path.join(testConfigDir, 'settings.json'),
61-
JSON.stringify({ freebuffModel: FREEBUFF_DEEPSEEK_V4_PRO_MODEL_ID }),
62-
)
63-
expect(loadFreebuffModelPreference()).toBe(
64-
FREEBUFF_DEEPSEEK_V4_PRO_MODEL_ID,
57+
JSON.stringify({ freebuffModel: FREEBUFF_GLM_V53_FLASH_MODEL_ID }),
6558
)
59+
expect(loadFreebuffModelPreference()).toBe(FREEBUFF_GLM_V53_FLASH_MODEL_ID)
6660

6761
// And a round-trip through save/load leaves every selectable row alone. The
6862
// property is "the picker is the user's decision, not ours" — asserted
6963
// across the catalog rather than on one row, because the failure mode is a
7064
// notice added for ONE model quietly acquiring this behaviour.
7165
for (const id of [
72-
FREEBUFF_DEEPSEEK_V4_PRO_MODEL_ID,
66+
FREEBUFF_GLM_V53_FLASH_MODEL_ID,
7367
FREEBUFF_DEEPSEEK_V4_FLASH_MODEL_ID,
7468
FREEBUFF_MIMO_V25_MODEL_ID,
7569
]) {
7670
saveFreebuffModelPreference(id)
7771
expect(loadFreebuffModelPreference()).toBe(id)
7872
}
7973
})
74+
75+
test('a withdrawn pick is DROPPED, not carried or rewritten', () => {
76+
testConfigDir = fs.mkdtempSync(
77+
path.join(os.tmpdir(), 'freebuff-settings-test-'),
78+
)
79+
getConfigDirSpy = spyOn(auth, 'getConfigDir').mockReturnValue(testConfigDir)
80+
81+
// DeepSeek V4 Pro was withdrawn from free mode on 2026-08-26. A saved
82+
// preference is the longest-lived way to hold a dead id: it survives every
83+
// deploy and outlives the release that dropped the row, so this is the
84+
// client half of the withdrawal.
85+
//
86+
// Written directly, because that is the only way it can arrive — an updated
87+
// client cannot SAVE the id, and the file predates the update.
88+
fs.writeFileSync(
89+
path.join(testConfigDir, 'settings.json'),
90+
JSON.stringify({ freebuffModel: FREEBUFF_DEEPSEEK_V4_PRO_MODEL_ID }),
91+
)
92+
// Undefined, not a substitute. The catalog validation drops it and the
93+
// landing screen falls to its own default — which is a decision that
94+
// belongs there, not to a rewrite here. A migration would silently move the
95+
// user onto a specific model on every launch, which is exactly what the
96+
// supersedes machinery was removed for.
97+
expect(loadFreebuffModelPreference()).toBeUndefined()
98+
99+
// And the updated client refuses to write it back, so the drop is durable
100+
// rather than re-inflicted from the picker.
101+
saveFreebuffModelPreference(FREEBUFF_DEEPSEEK_V4_PRO_MODEL_ID)
102+
expect(loadFreebuffModelPreference()).toBeUndefined()
103+
})
80104
})

common/src/__tests__/free-agents.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,10 @@ describe('every freebuff root agent declares a prompt opening', () => {
683683
'base2-free-minimax-m3': BASE2,
684684
'base2-free-luna': BASE2,
685685
'base2-free-glm': BASE2,
686+
// GLM 5.3 Flash's own root — a separate agent from 'base2-free-glm' above
687+
// because the two models draw on different pools; createBase2('free', …)
688+
// like its siblings.
689+
'base2-free-glm-5-3-flash': BASE2,
686690
// God-only Kimi K3 test root; createBase2('free', …) like its siblings.
687691
'base2-free-kimi-k3-eco': BASE2,
688692
'base2-free-luna-es': BASE2,

0 commit comments

Comments
 (0)