Repository navigation
fix(core): size the qwen-latest-series invite aliases at 1M - #15758
Conversation
The invite-only series aliases name no model generation the curated 1M rows key on, and models.dev does not carry them, so they fell through to the 256K Qwen family row. A model with a 1M window then compacted at 222,822 tokens — roughly a quarter of the window it actually has — and its output requests were sized against the 32K family ceiling. Match the series prefix ahead of the family rows. The trailing hyphen keeps the prefix off ids that merely share its letters. The catalog is still consulted first, so this answers only for ids no upstream source describes, and it steps aside once models.dev carries one. Output limits, modalities and normalization are untouched. Both new assertions were checked to redden alone: removing the row reports 262144 against the expected 1000000, and dropping the trailing hyphen makes the boundary case report 1000000 against the expected 262144.
yiliang114
left a comment
There was a problem hiding this comment.
Review: APPROVE ✅
Scope: packages/core/src/core/tokenLimits.ts (+5) + tokenLimits.test.ts (+18)
Depth: default → escalated (auth-adjacent: API-key auth path reaches this detector; Qwen OAuth skips it)
Correctness
The new rule [/^qwen-latest-series-/, LIMITS['1m']] is placed correctly in the PATTERNS array — after the Qwen-family 1M rules (qwen3.x, qwen-plus-latest, qwen-flash-latest) and before coder-model, which sit ahead of the 256K fallback rows. Order is load-bearing here: without this position the series ids would still match the 256K Qwen family default below.
The trailing hyphen in ^qwen-latest-series- is the boundary guard. Removing it would claim ids like qwen-latest-seriesfoo — the test at line 288 (expect(tokenLimit('qwen-latest-seriesfoo')).toBe(262144)) proves that this guard works and that the test itself is not a vacuous pass.
Tests
Six test cases — the reported id, a future invite code, the beta-series spelling, the code-stripped form, the openai/ prefix, and the boundary rejection. Each was mutation-tested by the author (removing the rule → 262144 on the reported id; dropping the hyphen → 1000000 on seriesfoo). The surrounding suites (tokenLimits, modalityDefaults, model-catalog, model-catalog-refresh, modelConfigResolver) pass — 314 total.
Risk
The author correctly identifies the tradeoff: 1M is maintainer-reported, not confirmed from models.dev. If a future series member ships a smaller window, compaction fires late and one request may fail. This is recoverable (the server's own ceiling shrinks the reactive compaction target) and the alternative (standing up an internal catalog mirror) has its own cost. No breaking changes.
Verdict
No P0, P1, or P2 findings. The change is minimal, correctly ordered, boundary-guarded, and mutation-tested. APPROVE.
Reviewed at head dce317f — only review on this PR.
wenshao
left a comment
There was a problem hiding this comment.
Reviewed commit dce317f68584c45c0743355301af53ff7b2dfbdc. No actionable correctness or regression findings in this diff.
The series rule is ordered before the Qwen family fallback, and the tested invite/date/version/provider-prefix forms survive normalization as intended. Usable catalog context values and explicit context-window settings retain precedence. The output-limit and modality paths are unchanged.
Independent validation:
- Reproduced the old behavior through the installed Qwen CLI's
/context:262.1k tokens, with no model API request. The PR source resolves the same model ID to1,000,000. - Ran the unchanged
tokenLimits.test.ts: 104/104 passed, using an isolated Vitest configuration that retains the package test setup and omits the workspace-build prerequisite check. - Also passed 63 existing modality tests and 3 focused probes covering aliases, unchanged output limits, catalog precedence, and unrelated Qwen IDs: 170 passing tests in total.
- Verified both new regression tests independently: removing the rule fails with
262144versus1000000; removing its trailing hyphen fails the prefix-boundary test with1000000versus262144. These mutations were applied in memory; the reviewed source and test files remain byte-identical to the commit.
Validation limits: the separate model-catalog.test.ts suite could not collect because the shared local dependencies lack ajv/dist/2020.js; it is not counted as passing. No full workspace build/typecheck or live invite-model endpoint test was performed. The series-wide 1M capacity remains the maintainer-provided premise documented in the PR.
中文评审结论
已评审提交 dce317f68584c45c0743355301af53ff7b2dfbdc,未发现本次改动引入的、需要修复的正确性或回归问题。
新规则位于 Qwen 家族兜底规则之前;测试覆盖的邀测代号、日期、版本和 provider 前缀均能在归一化后正确匹配。可用的目录上下文值和显式窗口配置仍优先,输出上限与模态识别路径未变。
独立验证:全局 CLI 的 /context 复现了旧值 262.1k tokens,未发起模型 API 请求;PR 源码对同一模型返回 1,000,000。原有 tokenLimits.test.ts 在保留包级测试 setup、跳过工作区构建前置检查的隔离 Vitest 配置下 104/104 通过。移除规则和移除尾部连字符的两项内存变异,分别使新增的正向测试和边界测试按预期失败;被评审的源码和测试文件与提交内容完全一致。
另有 63 项原有模态测试及 3 项别名、输出上限、目录优先级和无关 Qwen 名称探针通过,共 170 项通过。
验证范围:单独的 model-catalog.test.ts 因共享本地依赖缺少 ajv/dist/2020.js 未完成收集,不计为通过。未运行完整工作区构建/typecheck,也未调用真实邀测模型端点;整个系列具有 1M 容量仍以 PR 中维护者提供的信息为前提。
qqqys
left a comment
There was a problem hiding this comment.
Critical-only scan at head dce317f6. Verdict: APPROVE — no prior blocking findings exist on this PR (no reviews, no threads), and the current scan found no provable blocking defect.
The change
One row added to the input table: [/^qwen-latest-series-/, LIMITS['1m']] at packages/core/src/core/tokenLimits.ts:272, placed after the specific Qwen 1M rows and before the /^qwen/ 256K family fallback at :279, plus 18 lines of test.
What I verified in the code
The rule is reachable and correctly ordered. PATTERNS is read at exactly one site — the first-match loop at :403 — and no row above :272 can match these ids: the Qwen 1M rows are ^qwen3-coder-plus, ^qwen3-coder-flash, ^qwen3\.\d, ^qwen-plus-latest$, ^qwen-flash-latest$, and the other families are anchored to gemini-, gpt-, o\d, claude-. Before this change such an id fell to /^qwen/ → 262144, which is the reported symptom; after it, :272 wins.
The catalog still answers first, so the rule only fills a gap. findTokenLimit consults lookupModelCatalog(norm) at :389 and returns at :395-397 whenever the catalog reports a context ≥ MIN_AUTO_DETECTED_CONTEXT_WINDOW, before the loop is reached. A future models.dev entry for any of these ids therefore overrides the new row rather than fighting it.
Output limits are structurally untouched. For type === 'output' the function returns at :400 (curatedOutputLimit(norm) ?? fromCatalog), which iterates the separate OUTPUT_PATTERNS table at :375; the loop at :403 is never reached. The row was added to PATTERNS, not OUTPUT_PATTERNS, so hasExplicitOutputLimit and defaultOutputCeiling cannot change behaviour — matching the description's decision to leave the output ceiling at the family default.
normalize() cannot defeat the prefix. Traced against :147-227 for each asserted id: the provider-prefix strip (^.*\/) turns openai/qwen-latest-series-invite-202610-m4 into the bare id; the trailing-suffix strip at :219-221 is $-anchored and its guard list (^qwen-(?:plus|flash|vl-max)-latest$, ^kimi-k2-\d{4}$, ^deepseek-v4) does not exempt this family, so -v28 is stripped from …-invite-beta-v28 and -202610 from …-invite-202610, leaving qwen-latest-series-invite-beta and qwen-latest-series-invite — both still carry the qwen-latest-series- prefix. -m4/-m5 match no alternative in that strip and survive. The -latest the description mentions as unreachable is only stripped when trailing, and here it is not.
The trailing hyphen does the boundary work it claims. qwen-latest-seriesfoo normalizes unchanged, fails ^qwen-latest-series-, and falls through to /^qwen/ → 262144, which tokenLimits.test.ts asserts. The new row is anchored at ^, so no id outside this prefix can change its answer.
CI at this head
Nothing red. The routing, classification, authorization and Managed Agent tier gates pass; Lint & Static (ubuntu-latest, Node 22.x) and Test (ubuntu-latest, Node 22.x) — the lane that runs tokenLimits.test.ts — are still pending, so the new assertions have not yet been executed by CI. No failure is attributable to this change.
|
Thanks for the PR! Template looks good ✓ — every section is filled in, including an honest account of what was not verified. Problem: Observed, and verifiable statically. I traced Direction: Aligned. Correct window detection is what every compaction threshold downstream is computed from, so a silent 256K on a 1M model is precisely the kind of quiet loss worth fixing. CHANGELOG has no direct reference to a prefix-series rule, but the area is clearly live in the reference agent — it carries entries for a Size: Core paths touched ( Approach: Minimal, and it's the path I'd have picked independently. I considered the alternatives before reading the diff: extending Risk: No elevated risk signals — neither changed file matches the revert-correlated path list. Two things I checked that are worth stating, because they're what make this safe to be this small: the new row lives only in Moving on to code review. 🔍 中文说明感谢贡献! 模板完整 ✓ —— 各节都填写了,包括对"哪些没有验证"的坦诚说明。 问题: 已观测,且可从源码静态验证。我手工跟踪了 方向: 对齐。上下文窗口识别是下游所有压缩阈值的计算基准,因此 1M 模型被静默当作 256K,正是那种值得修复的隐性损失。CHANGELOG 中没有关于前缀系列规则的直接条目,但这个领域在参考 agent 中显然很活跃 —— 它有 规模: 触及核心路径( 方案: 最小改动,也正是我独立会选的路径。在看 diff 之前我考虑过其他方案:扩展 风险: 无升级风险信号 —— 两个改动文件都不匹配与回滚相关的路径清单。有两点我核实过,值得说明,因为它们正是这个改动能做得这么小还安全的原因:新行只存在于 进入代码审查 🔍 — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
Code reviewNo critical blockers and no AGENTS.md violations. The change is one row in an existing ordered table, and I could satisfy myself about all of it by reading. Before looking at the diff I worked out what I'd do myself: add a row to The assertions are correct, and they're not vacuous. I hand-traced
Each of those is a distinct branch of the stripper, and the tests pin all of them plus the provider-prefixed spelling. That's better coverage than the change strictly needs. Ordering is right. The row sits after every pattern it cannot overlap and ahead of the The output path is genuinely untouched, which is the claim I most wanted to check, since an accidental output change would resize every request to these models. The new row is in Consumers, all of which move together off the same One non-blocking suggestion. The trailing hyphen is the right precision guard, but it interacts with the date-strip in a way that leaves one shape uncovered: an id that normalizes down to a bare One second-order effect worth naming, with its mitigation verified. Moving the window from 262,144 to 1,000,000 moves auto-compaction from 222,822 to 850,000, so sessions on these ids will retain roughly 3.8× more history before token-compaction fires. I checked this specifically because the in-repo E2E report that mentions this model family ( TestingThis is an unattended CI run, so per the triage rules I did not build, run, or execute anything from this PR — the evidence below is the PR's own CI, read through the API for commit Zero checks are red at the time of writing.
Sandboxed verification would settle the part CI cannot: 中文说明代码审查没有关键阻塞项,也没有违反 AGENTS.md 的地方。改动就是既有有序表里的一行,全部可以靠阅读确认。 在看 diff 之前我先想清了我会怎么做:往 断言正确,而且不是空跑。 我对这五个 id 逐一手工跟踪了 顺序正确。 新行位于所有不可能重叠的模式之后、位于它必须胜过的 输出路径确实未被触及 —— 这是我最想核实的一点,因为误改输出会改变发给这些模型的每个请求的大小。新行只在 下游消费方全部同源联动,都走 一条非阻塞建议。 尾部连字符是对的精度防护,但它与日期剥离的交互留下一个未覆盖形态:归一化后正好落到裸 一个值得点名的二阶效应,其缓解措施已核实。 窗口从 262,144 提到 1,000,000,会把自动压缩点从 222,822 推到 850,000,也就是说这些 id 上的会话在触发按 token 压缩之前会多保留约 3.8 倍的历史。我特意核查了这点,因为仓库内提到这个模型族的 E2E 报告( 测试这是一次无人值守的 CI 运行,因此按照 triage 规则,我没有构建、运行或执行本 PR 的任何代码 —— 下面的证据是通过 API 读取的、针对提交 截至撰写时没有任何检查为红。 沙箱化验证可以补上 CI 补不了的那部分: — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
|
Confidence: 4/5 — correct, minimal, and better tested than it needs to be; the single reservation is that CI hasn't landed yet and the 1M figure itself is one reviewer-uncheckable input. Going back to what I'd have written myself: the same one row in the same place. The PR doesn't just match that proposal, it exceeds it — I'd probably have written two assertions (the reported id and the family default) and called it done, whereas these tests pin all four branches of On whether users care: yes, and it's the annoying kind of bug. Nothing errors, nothing logs, the session just compacts at 22% of its real window — so the user experiences it as the assistant forgetting things early and has no way to trace it to a context-window table. Fixing a silent degradation like that is worth five lines. I went looking for reasons to say no, because that's the job. I checked the output path (untouched — The hesitation I did sit with is the one you name yourself: encoding an internal invite-only naming family in a shared detector. I landed on it being fine, for a concrete reason rather than a shrug — In six months I'd thank whoever wrote this, not curse them: the comment records that the value is maintainer-reported rather than derived, so the next person knows which fact to re-check if a series member ever behaves oddly. Verdict: approve — deferred until CI lands green on 中文说明Confidence: 4/5 —— 正确、最小,且测试覆盖超出必要程度;唯一的保留意见是 CI 尚未结束,而 1M 这个数值本身是一个评审方无法核实的输入。 回到我原本会怎么写:同一位置、同一行。这个 PR 不只是与我的方案一致,而是超出了它 —— 我大概只会写两条断言(所报告的 id 与家族默认值)就算完事,而这些测试钉住了前缀可能与之交互的 至于用户是否在意:在意,而且是那种讨厌的 bug。不报错、不打日志,会话只是在真实窗口的 22% 处就压缩 —— 于是用户的体验是助手过早开始遗忘,却完全无从追溯到一张上下文窗口表。修掉这种静默降级,值这五行代码。 我主动去找了反对理由,因为这就是门禁该做的事。我核查了输出路径(未被触及 —— 我确实停下来想过的一处犹豫,正是你自己点出的那一点:把内部邀测命名族写进共享识别逻辑。我的结论是可以接受,理由是具体的而非耸肩 —— 半年之后我会感谢写这行的人,而不是骂他:注释记下了这个数值来自维护者的说明而非推导得出,因此下一个人知道,万一某个系列成员行为异常,该重新核实的是哪一个事实。 结论:批准 —— 但推迟到 CI 在 — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
|
建议这个 PR 顺手把 qwen4 家族也一起设为 1M。 现在 qwen4 同样整族 1M,在 [/^qwen4/, LIMITS['1m']],在副本上验证过:qwen4 各 id(含裸 |
Local verification — real
|
| Observation | Base | Head |
|---|---|---|
Headless /context header |
Context window: 262.1k tokens |
Context window: 1000.0k tokens |
| TUI effective window | 242.1k | 980.0k |
| TUI warn threshold | 202.8k | 830.0k |
| TUI auto threshold | 222.8k | 850.0k |
| TUI hard threshold | 239.1k | 977.0k |
| 12.0k-token prompt shown as | 4.6% used | 1.2% used |
The threshold ladder matches computeThresholds exactly (85% auto, 13k ceiling buffer, 3k hard buffer), so the change moves compaction timing by the amount the PR claims, not just the header text.
Headless, head:
Headless, base:
Interactive TUI, head — a real turn then /context:
Interactive TUI, base, same flow:
Unit gates and mutation matrix
| Cell | Result |
|---|---|
tokenLimits.test.ts, head |
104 passed (104) |
tokenLimits.test.ts, base |
102 passed (102) |
| Head test file on base source | 1 failed / 103 passed — expected 262144 to be 1000000 |
Head 5-suite gate (tokenLimits, modalityDefaults, model-catalog, model-catalog-refresh, modelConfigResolver) |
314 passed (314) in 5 files |
| Same 5 suites, base (A/A control) | 312 passed (312) — exactly the 2 new tests fewer |
tsc --noEmit (core), prettier, eslint |
0 / clean / 0 |
| Mutant (head source, focused file) | Result | Assertion that reddened |
|---|---|---|
M1 drop the new PATTERNS row |
KILLED | expected 262144 to be 1000000 |
| M2 drop the trailing hyphen | KILLED | expected 1000000 to be 262144 (boundary test) |
M3 LIMITS['1m'] → ['256k'] |
KILLED | expected 262144 to be 1000000 |
| M4 narrow to one invite id | KILLED | expected 262144 to be 1000000 |
M5 move the row below ^qwen |
KILLED | expected 262144 to be 1000000 |
| C0 unmutated control | GREEN | 104 passed |
Every cell was restored with git checkout HEAD -- and verified clean (blob 40bf899db71cf291ff9e90b9b836e3ec93e36bea before and after). M2 is the cell that proves the precision guard: on base the boundary test passes vacuously (nothing is claimed), and only the over-claiming mutant reddens it.
No collateral change across 48 model ids
I compared the two built dists directly over 48 ids — every Qwen row, the boundary spellings, and representatives of Gemini/OpenAI/Claude/DeepSeek/GLM/MiniMax/Kimi/Seed-OSS/unknown.
- Exactly 9 ids changed input, and every one normalizes into
qwen-latest-series-: the five ids in the tests (four suffix shapes plus the provider-prefixed form),…-invite,…-beta, the:freesuffix form, and the uppercase form. qwen-latest-seriesfoo,qwen-latest-seriesx-invite-202610, bareqwen-latest-seriesstay 262,144 on both arms.- Output limit,
hasExplicitOutputLimitanddefaultOutputCeilingare identical for all 48 ids; series ids stay at 32,768 output. qwen-plusresolves to 1,000,000 in both arms — its models.dev catalog entry outranks the 256K family row, which is the catalog-first precedence the PR relies on, observed through the real loader.
N1 (non-blocking) — ids that normalize to a bare qwen-latest-series still fall back
Confirmed at both arms: qwen-latest-series-202610 and qwen-latest-series-v28 have their date/version suffix stripped by normalize() and become bare qwen-latest-series, which the trailing-hyphen rule deliberately does not claim, so they stay at 262,144. This is the shape the triage bot's non-blocking suggestion names; it is outside the PR's stated invite-alias scope, so I am not counting it as a defect.
I probed the suggested variant as a merge input, not as a requested change: changing the row to /^qwen-latest-series(?:-|$)/ keeps all 104 focused tests green, moves bare/date/version forms to 1,000,000, and still leaves qwen-latest-seriesfoo and qwen-latest-seriesx-… at 262,144. Whether a bare series id should answer 1M is a product call; the stricter regex is consistent with the PR's current scope.
What this does not settle
The detector and every downstream consequence are verified, but whether the real invite model truly has a 1,000,000-token window rests on maintainer knowledge, not on anything observable from outside — the PR says so, and I could not add evidence there without credentials.
中文摘要(点击展开)
本地验证 —— 真实 /context A/B:1000.0k vs 262.1k
我构建了两臂,并用产品真实的 /context 路径对接一个 OpenAI 兼容端点。被验证 head 为 dce317f68584c45c0743355301af53ff7b2dfbdc(轮次开始到发布未变化),base 为 9acb3a5a1d68aad0705ad4d420830affb59cc95a;机器为 macOS 26.6.2 / Apple M1 Max,Node 22.23.4。
本地结论:merge-ready,无阻塞发现。 末尾有一条非阻塞边界说明(N1)。发布时 CI 的 Node 22 测试任务仍在运行;本轮已在本地覆盖 tokenLimits.test.ts 及其四个邻接套件。
验证方式
- 两个 detached worktree,各自全量
npm run build(Node 22.23.4、8 GB 堆、EXIT=0)。head 的 core dist 带新规则(grep -c qwen-latest-series-→ 2),base 为 0,证明构建确实带上了改动。 - 无头 CLI:两臂执行同一命令
qwen -p '/context' --auth-type openai --model qwen-latest-series-invite-202610-m4 --openai-base-url <fake>/v1 --openai-api-key fake-key,使用独立QWEN_HOME与QWEN_CODE_MODELS_DEV_REFRESH=off。 - 交互式 TUI:先发一条真实模型请求(
hi→ 伪服务回复并携带usage.prompt_tokens=12000),再执行/context,用 tmux 150×48 抓取。两臂环境与参数一致。 - 端点使用仓库自带的
integration-tests/fake-openai-server.ts。未使用邀测模型凭据,因此验证的是完整的 配置 → 识别逻辑 →/context/阈值路径,而不是真实邀测端点 —— 这与 PR 自述的限制相同。
用户可见结果
| 观测项 | base | head |
|---|---|---|
无头 /context 头部 |
Context window: 262.1k tokens |
Context window: 1000.0k tokens |
| TUI 有效窗口 | 242.1k | 980.0k |
| TUI warn 阈值 | 202.8k | 830.0k |
| TUI auto 阈值 | 222.8k | 850.0k |
| TUI hard 阈值 | 239.1k | 977.0k |
| 12.0k token 提示词的占用显示 | 4.6% | 1.2% |
阈值阶梯与 computeThresholds 完全一致(85% auto、13k 上限缓冲、3k hard 缓冲),说明改动确实按 PR 所述移动了压缩时机,而不只是头部文字变化。
单测门禁与变异矩阵
| 格子 | 结果 |
|---|---|
tokenLimits.test.ts,head |
104 passed (104) |
tokenLimits.test.ts,base |
102 passed (102) |
| head 测试文件跑在 base 源码上 | 1 failed / 103 passed —— expected 262144 to be 1000000 |
head 五套件(tokenLimits、modalityDefaults、model-catalog、model-catalog-refresh、modelConfigResolver) |
314 passed (314),5 个文件 |
| 同样五套件在 base(A/A 对照) | 312 passed (312) —— 正好少两个新测试 |
tsc --noEmit(core)、prettier、eslint |
0 / clean / 0 |
| 变异(head 源码、聚焦测试文件) | 结果 | 变红的断言 |
|---|---|---|
M1 删除新增 PATTERNS 行 |
KILLED | expected 262144 to be 1000000 |
| M2 去掉尾部连字符 | KILLED | expected 1000000 to be 262144(边界测试) |
M3 LIMITS['1m'] → ['256k'] |
KILLED | expected 262144 to be 1000000 |
| M4 收窄为单一 invite id | KILLED | expected 262144 to be 1000000 |
M5 把该行移到 ^qwen 之后 |
KILLED | expected 262144 to be 1000000 |
| C0 未变异对照 | GREEN | 104 passed |
每格都用 git checkout HEAD -- 还原并校验干净(变异前后 blob 均为 40bf899db71cf291ff9e90b9b836e3ec93e36bea)。M2 是证明精度防护承重的那一格:在 base 上边界测试是空过的(base 不会认领任何 id),只有"过度认领"的变异会让它变红。
48 个模型 id 无附带变化
我直接对比两臂构建产物中的 48 个 id —— 覆盖全部 Qwen 行、边界拼写,以及 Gemini/OpenAI/Claude/DeepSeek/GLM/MiniMax/Kimi/Seed-OSS/未知模型的代表项。
- 输入值恰好 9 个发生变化,且全部归一化后落在
qwen-latest-series-:测试里的四种拼写、…-invite、…-beta、:free后缀形式、openai/…前缀形式和全大写形式。 qwen-latest-seriesfoo、qwen-latest-seriesx-invite-202610、裸qwen-latest-series在两臂都保持 262,144。- 输出上限、
hasExplicitOutputLimit与defaultOutputCeiling在全部 48 个 id 上完全一致;系列 id 的输出仍为 32,768。 qwen-plus在两臂都解析为 1,000,000 —— 它的 models.dev 目录条目胜过 256K 家族行,这正是 PR 依赖的"目录优先",且是通过真实加载器观测到的。
N1(非阻塞)—— 归一化为裸 qwen-latest-series 的 id 仍会回落
两臂实测:qwen-latest-series-202610 与 qwen-latest-series-v28 的日期/版本后缀会被 normalize() 剥掉,变成裸 qwen-latest-series,而尾部连字符规则有意不认领它,因此仍是 262,144。这正是 triage bot 非阻塞建议里点名的形态;它超出 PR 明示的邀测别名范围,所以我不把它计为缺陷。
我把建议的正则当作合并决策输入做了探针(不是要求改动):把该行改成 /^qwen-latest-series(?:-|$)/ 后,104 个聚焦测试仍全绿,裸/日期/版本形态变为 1,000,000,qwen-latest-seriesfoo 与 qwen-latest-seriesx-… 仍为 262,144。裸系列 id 是否应为 1M 属于产品判断;更严格的写法与 PR 当前范围自洽。
本轮未覆盖
识别逻辑及其全部下游后果都已验证;但真实邀测模型是否确有 1,000,000 token 窗口,取决于维护者知识,无法从外部观测 —— 这一点 PR 已明说,我也无法在缺少凭据的情况下补充证据。
Artifacts: wenshao/qwen-code@assets-pr15758 under pr15758/ (six PNGs, all raw URLs checked 200). Harness, logs and the full report live in tmp/pr15758-verify-20261028-114320/. Verified at head dce317f6; base 9acb3a5a.
|
感谢建议,已按此落地。本 PR 已合并,改动另开 #15762(基于 main 基线复核:在 改动:就是建议的那一行 真实 同一路径上 变异见证:两条新用例逐一验证过,每次只改一处 —— 把该行改成 256K,家族用例红(106 项中其余 105 项仍绿);跳过 catalog 分支让家族表先作答,catalog 覆盖用例在 400,000 上红。catalog 优先语义未变,并新增一条用例把它钉住,models.dev 收录 qwen4 后自动让位。 范围:输出上限仍保留在 32K 的 Qwen 家族默认值上,本次只动输入窗口;qwen4 的输出上限待明确后再单独钉定。整族 1M 这一点在 PR 正文的风险段里如实标注为评审者提供、代码与 models.dev 当前无法确认。 |
The Qwen 1M rules stopped at qwen3.x, so every qwen4 spelling fell through to the 256K family row and auto-compaction fired at 22% of the real window. Add a family row for the generation, as suggested in review of #15758.
|
Released in v0.26.3. |






What this PR does
Teaches the context-window detector to recognize the invite-only
qwen-latest-series-model aliases as 1M-context models. The series prefix is matched ahead of the Qwen family defaults, with a trailing hyphen so the prefix cannot claim ids that merely share its letters. Nothing else changes: output ceilings, input modalities and model-id normalization are untouched, and the models.dev catalog is still consulted first, so the new rule answers only for ids no upstream source describes and steps aside once the catalog carries one.Why it's needed
An id such as
qwen-latest-series-invite-202610-m4names no model generation that the curated 1M rules key on, and models.dev does not list it, so it fell through to the 256K Qwen family default. The model was then treated as having 262,144 tokens instead of 1,000,000: auto-compaction fired at 222,822 tokens — 22% of the real window — and output requests were sized against the 32K family ceiling. Nothing failed loudly, so the loss showed up only as conversations compacting far earlier than they needed to.Because the whole series shares the 1M window, a prefix rule also covers later invite codes without another code change, as well as the beta-series spelling that was already in use.
Reviewer Test Plan
How to verify
Point an OpenAI-compatible provider at
qwen-latest-series-invite-202610-m4and run/context. The header should readContext window: 1000.0k tokens; before this change the same model reportedContext window: 262.1k tokens. Note that the detector is reached only on the API-key auth paths — Qwen OAuth admitscoder-modelalone and substitutes it before any window is computed, so that auth type is unaffected either way.At the unit level, from
packages/core:Both new assertions were checked to redden on their own, one mutant at a time, so neither passes vacuously:
expected 262144 to be 1000000on the reported id.^qwen-latest-series): the boundary case reportsexpected 1000000 to be 262144.The surrounding suites were run as well —
tokenLimits,modalityDefaults,model-catalog,model-catalog-refresh,modelConfigResolver— 314 passed.prettier --check,eslintandtsc --noEmitare clean for the core package.Evidence (Before & After)
Not captured against a live endpoint: I have no credentials for this invite-only model, so the before/after below is the window and the thresholds computed from it at the source level, not a terminal capture.
/contextheader262.1k tokens1000.0k tokensTested on
Environment (optional)
Unit tests plus source-level evaluation of the detector and the threshold computation. No live model endpoint was exercised.
Risk & Scope
qwen-latestis not covered: normalization strips its trailing-latest, so no prefix rule can reach it, and changing that shared step would reach catalog keys and modality detection too.qwen-latest-series-, and only when the catalog has no entry for them.Linked Issues
None.
中文说明
这个 PR 做了什么
让上下文窗口识别逻辑把邀测专用的
qwen-latest-series-系列别名识别为 1M 上下文模型。该系列前缀在 Qwen 家族默认值之前匹配,并带尾部连字符,使这个前缀不会误认那些仅仅字母相同的 id。其余一切不变:输出上限、输入模态与模型 id 归一化都未触及,并且仍然优先查询 models.dev 目录,因此新规则只为那些上游数据源没有描述的 id 作答,一旦目录收录了它们,规则就自动让位。为什么需要
像
qwen-latest-series-invite-202610-m4这样的 id 不含任何可供既有 1M 规则据以判断的型号代际信息,models.dev 也没有收录它,于是它落到了 256K 的 Qwen 家族默认值上。这个模型因此被当作只有 262,144 而非 1,000,000 tokens 来处理:自动压缩在 222,822 tokens 处就触发 —— 只有真实窗口的 22% —— 而输出请求则按 32K 的家族上限设定。没有任何显式报错,所以损失只表现为对话远比必要的时机更早被压缩。由于整个系列共享 1M 窗口,一条前缀规则还能覆盖后续新的邀测代号而无需再次改码,同样覆盖此前已在使用的 beta 系列拼写。
评审验证计划
如何验证
把一个 OpenAI 兼容 provider 指向
qwen-latest-series-invite-202610-m4,然后执行/context。头部应显示Context window: 1000.0k tokens;改动之前同一模型显示的是Context window: 262.1k tokens。注意识别逻辑只在 API key 类认证路径上才会被走到 —— Qwen OAuth 仅准入coder-model,并在计算任何窗口之前就完成替换,因此该认证类型无论改动前后都不受影响。单测层面,在
packages/core目录下执行:两条新断言都逐一做过变异验证,每次只改一处,确认它们不是空跑通过:
expected 262144 to be 1000000。^qwen-latest-series):边界用例出现expected 1000000 to be 262144。周边套件也一并跑过 ——
tokenLimits、modalityDefaults、model-catalog、model-catalog-refresh、modelConfigResolver—— 314 项通过。core 包的prettier --check、eslint与tsc --noEmit均干净。证据(改动前后)
未在真实端点上采集:我没有这个邀测模型的凭据,因此下面的前后对比是在源码层面由窗口值及其推算出的阈值,而不是终端截图。
/context头部262.1k tokens1000.0k tokens测试环境
运行环境(可选)
单元测试,加上对识别逻辑与阈值计算的源码层面求值。未调用任何真实模型端点。
风险与范围
qwen-latest不在覆盖范围内:归一化会剥掉它尾部的-latest,因此任何前缀规则都到不了它,而改动那个共享步骤还会波及目录键与模态识别。qwen-latest-series-开头、且目录中没有对应条目的那些 id。关联 Issue
无。