You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Refresh Workers AI reasoning from Search while keeping the catalogue safe. Changes are confined to the Workers AI provider.
Source data
Sync contract
Concrete, valid model reasoning controls
Search wins
Missing, invalid, null, empty or incomplete controls
Existing catalogue wins, apart from the verified GLM exception below
Existing output caps, base-model links, curated names and dates
Existing catalogue wins
Usable context and pricing
Continue updating from Search
Missing models or failed later pages
Retain catalogue entries; use successful pages
Before: authored reasoning options always won, even when Search advertised corrected controls. After: valid model controls update the catalogue; invalid reasoning does not prevent other usable properties from updating. A concrete single mandatory effort means no effort choice ([]); supported_efforts: null never expands to an enum. Reasoning budgets require explicit supports_max_tokens: true.
Verified GLM-4.7 exception: a fresh September 19 Search response for @cf/zai-org/glm-4.7-flash contains exactly:
Its per-model ConfigAPI record matches. The verified Workers control is chat_template_kwargs.enable_thinking, consistent with the creator's template, which switches the assistant prefix using enable_thinking. The code requires this exact model ID plus explicit mandatory: false when efforts and budget support are absent. Missing reasoning, {}, null/empty efforts, or an absent mandatory flag still preserve the catalogue. A future concrete Search effort list remains authoritative.
The old catalogue header and published input schema still contain a shared low/medium/high enum. Those are the stale inputs being corrected: catalogue PR #7454 updates the header and controls; docs PR #33541 corrects the schema. They are separate from this provider-only change.
Curated headers are preserved. Unknown toggle wires retain existing reasoning; unreadable headers skip only that model. New reasoners without verified controls use the existing manual-authoring issue flow.
Validation: 19 temporary regression tests / 220 assertions pass, covering the preserve/update matrix, fixed mandatory effort, explicit GLM shape, header preservation/failures, unknown wires, retries and partial pages. All 15 existing OpenRouter tests pass. The PR author explicitly requested no tracked test file; that scope remains unchanged. The fresh GLM Search payload was replayed and produces toggle-only controls.
[high] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:708 - Check: Reasoning effort values must be the host/model baseline, not the full schema enum (AGENTS.md / audit-reasoning-options). Why:workersAiReasoningOptions maps supported_efforts: null to ["max","xhigh","high","medium","low","minimal","none"], and the new tests lock that in. Empty means “no caller control”; the full enum dump invents levels this host may not accept and will rewrite catalogue files incorrectly. Action: Stop expanding null to the full enum. Treat null/missing efforts as unknown (preserve authored / skip new reasoners) unless Search returns an explicit effort list verified for Workers AI.
[high] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:653 - Check: Every toggle requires a leading top-of-file wire-path comment; sync peers return header for this. Why:workersAiReasoningOptions can emit { type: "toggle" } (e.g. mandatory: false without none), but translateModel never sets header. New creates get no wire comment; updates that newly gain a toggle keep any prior non-toggle header because the runner prefers existing headers and this provider supplies none. Action: When translated options include toggle, return a Workers AI wire header (native chat_template_kwargs… and/or OpenAI-compat reasoning_effort / reasoning.effort per provider.toml), and cover creates + “options gained toggle” in tests.
[high] [possible mistake]packages/core/src/sync/providers/cloudflare-workers-ai.ts:679 - Check: Multi-model host options must match this host’s request surface, not a generic OpenRouter translator (AGENTS.md host classification). Why: Usable Search reasoning now always replaces authored reasoning_options. Catalogue entries are intentionally model-specific (e.g. DeepSeek toggle+high/max, Qwen toggle+low/medium/xhigh). OpenRouter-shaped Search metadata (full L/M/H, supports_max_tokens → budget_tokens) can overwrite those with wrong controls or invent budgets. Action: Before treating Search as authoritative, verify it matches Workers AI wire controls per model (or intersect with lab/peer baselines). Do not emit budget_tokens unless this host exposes a real reasoning-token budget; keep curated options when Search is generic/mismatched; document the final precedence in sync.md.
Null effort expansion — fixed. Removed the enum expansion. Although OpenRouter defines null as an unrestricted gateway allowlist, that is insufficient evidence of concrete model controls for this catalogue. supported_efforts: null now preserves existing reasoning and options; new reasoners with unknown controls are skipped. Other usable properties on an existing model still update. Explicit always-on reasoning without caller controls can still produce [].
Toggle wire-path headers — fixed. Toggle entries now get # Toggle: chat_template_kwargs.enable_thinking = true|false, matching the public Workers AI input schemas for GLM-4.7-Flash, Qwen3.8, and Nemotron. This also handles existing models gaining a toggle, preserves unrelated leading notes, removes only the generated toggle line when controls change, and is idempotent.
Host-specific controls and budgets — verified; precedence clarified in the PR description. Search is backed by each model's Workers AI configuration. The inspected 27-model response distinguishes GLM-4.7-Flash's toggle-only controls from GLM-5.3's low/high/max; absent Qwen/Nemotron reasoning metadata preserves their curated controls. We retain concrete Workers-specific metadata as authoritative instead of intersecting it with another host's controls. budget_tokens is emitted only for explicit supports_max_tokens: true, which the OpenRouter schema defines as support for reasoning.max_tokens. No inspected model advertises it, and completion/output limits never create a reasoning budget. Changes remain scoped to the Cloudflare provider; shared sync code and sync.md are unchanged.
Validation: 15 existing OpenRouter tests and 11 temporary Workers AI regression tests pass (154 assertions total), covering null preservation, new and gained toggle headers, preservation of authored notes, and repeated syncs. The temporary tests are outside the repository, keeping this PR to one provider file.
[high] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:30 - Check: Toggle wire-path headers must match this host’s real request field per model (AGENTS.md Reasoning options; existing Workers AI TOMLs). Why:TOGGLE_HEADER hardcodes chat_template_kwargs.enable_thinking for every model, and with authoritativeHeaders: true the runner replaces leading comments with translateModel.header. That is wrong for existing catalogue entries that document other wires (e.g. DeepSeek thinking.type, Kimi chat_template_kwargs.thinking). On the next sync, toggle models get a conflicting/incorrect header: the generic enable_thinking line is prepended while the old model-specific lines are kept (header.replace(TOGGLE_HEADER, "") only strips the exact new string). Action: Stop using one universal toggle string. Either regenerate a full authoritative header from the model’s actual controls (Friendli-style) using the correct per-model wire path, or do not enable authoritativeHeaders until headers can be authored correctly without clobbering curated DeepSeek/Kimi/Qwen comments.
[medium] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:147 - Check: Skips that need manual reasoning metadata should be tracked (sync.mdmissingModelID / missing-model issues). Why: New reasoning models with unknown controls return undefined after only a console.warn, with no missingModelID/sourceID/skippedNotice. Those IDs never enter the catalogue and never open a missing-model issue, so they can stay invisible to automation indefinitely. Action: For this skip path, return missingModelID (and ideally sourceID/skippedNotice) so unknown reasoners are filed for manual authoring instead of being silently dropped.
[medium] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:263 - Check: Sync fetch must not silently produce a partial catalogue. Why: Page 1 failure throws, but pages 2+ that exhaust retries return undefined and are skipped (if (response !== undefined) rows.push(...)). A flaky later page yields an incomplete model set while the run still succeeds; with deleteMissing: false files are kept, but updates for models only on failed pages never apply and there is no hard failure. Action: After retries, throw (same as page 1) so a partial Workers AI Search response cannot be treated as a successful full sync.
[medium] [possible mistake]packages/core/src/sync/providers/cloudflare-workers-ai.ts:223 - Check: New reasoning-option derivation needs regression coverage (peer: OpenRouter tests in packages/core/test/sync.test.ts). Why:workersAiReasoningOptions changes precedence (API concrete controls win; supported_efforts: null preserves catalogue; toggle/none/mandatory/budget_tokens rules) with no unit tests. Mistakes here will rewrite live Workers AI TOMLs on the next hourly sync. Action: Add focused tests for null efforts → preserve; concrete efforts → API wins; mandatory + no efforts → []; supports_max_tokens → budget_tokens; toggle + none excluded; and header behavior once the wire-path fix is in.
Toggle headers — fixed the conflicting-comment behavior. Existing DeepSeek thinking.type, Kimi chat_template_kwargs.thinking, and Qwen's split-line enable_thinking instructions are now preserved without prepending another toggle path. Other leading notes remain intact. The generated fallback is used only when a toggle has no wire comment. I rechecked the current Workers AI schemas: Kimi and DeepSeek both explicitly expose chat_template_kwargs.enable_thinking as a boolean, as do GLM, Qwen, and Nemotron. So the fallback has host-specific documentation; we do not infer the host field from a model name. Regression checks cover curated headers, a model gaining a toggle, missing API reasoning, and repeated syncs.
Unknown reasoners — fixed. Added the existing sourceID, missingModelID, and skippedNotice hooks. New reasoners skipped for unknown controls are now visible in the sync report and eligible for the runner's deduplicated missing-model issue flow. Known models continue syncing normally.
Later-page failures — keeping the deliberate partial-update contract. This is an explicit design requirement for this change: after the initial attempt and three retries, a failed later page must not discard usable pages. Failures are logged; deleteMissing: false preserves entries absent from the partial result. A failed first page or wholly unusable result aborts. Throwing for any later-page failure would undo that requirement. Added the rationale beside the pagination loop and in the PR's precedence table; the regression check confirms pages before and after a failure are retained.
Regression coverage — exercised, with no committed test file by request. The author explicitly requested removal of the test file and a one-provider-file PR. The 13 temporary Workers AI regression tests cover all requested reasoning cases, header behavior, missing-model reporting, and retry/page boundaries. They pass alongside 15 existing OpenRouter tests (174 assertions total). Shared tests and sync.md remain outside this PR's agreed scope.
[high] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:164 - Check: Every toggle needs a leading top-of-file wire comment for this host’s real request path (AGENTS.md → Reasoning options). Why: With authoritativeHeaders: true, the runner writes translateModel.header as the file header. For existing toggle models that already lack a recognized wire phrase (today: @cf/moonshotai/kimi-k2.7-code.toml, @cf/zai-org/glm-5.2.toml), the code always prepends a fixed # Toggle: chat_template_kwargs.enable_thinking = true|false. That path is wrong for Moonshot (chat_template_kwargs.thinking) and for any future non-enable_thinking surface, so automated sync will stamp an incorrect wire comment as authoritative. Action: Do not invent a default Workers AI toggle path. Only emit a toggle header when the preserved header already documents the model-specific wire path, or derive the path per model/publisher; leave header empty (or fail closed / missing-model) when toggle is present and the wire path is unknown.
[high] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:115 - Check:missingModelID must return an ID only for skips that need the missing-model issue flow; intentional skips return undefined (sync.md / SyncProvider). Why:missingModelID always returns model.id, but translateModel only returns undefined for new reasoners with unknown controls. On that path the runner still records the skip via sourceID/skippedNotice, and missingModelID also opens a deduped GitHub issue labeled as a missing catalog model. That is the wrong recovery channel for “API advertised reasoning but no concrete controls” and will create recurring false missing-model issues. Action: Return undefined from missingModelID for this intentional skip (keep sourceID + skippedNotice), or throw/MissingReasoningOptionsError only if you intentionally want the issue flow with an accurate reason string.
[medium] [possible mistake]packages/core/src/sync/providers/cloudflare-workers-ai.ts:236 - Check:workersAiReasoningOptions must not invent incomplete/empty control sets that overwrite curated catalogue options. Why:return options.length > 0 || reasoning.mandatory === true ? options : undefined can return [] when Search says mandatory: true with no efforts and no supports_max_tokens. That is treated as concrete API controls and replaces authored reasoning_options via existingWithReasoningOptions, turning known caller controls into “no control.” OpenRouter’s mapper does not special-case mandatory-empty this way. Action: Treat mandatory-with-no-enumerated-controls as insufficient metadata (undefined → preserve catalogue), or only emit [] when Search explicitly means always-on with no caller control and that is verified for Workers AI.
[medium] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts - Check: Sync behavior changes that introduce concrete regression risk need focused tests (sync.md validation expectations; peer providers cover this). Why: This PR rewrites fetch/parse/retry, reasoning precedence, skip/missing-model behavior, and authoritative headers, but there is no cloudflare-workers-ai test coverage for: null supported_efforts preserves authored options; concrete efforts/toggle refresh; new unknown reasoner skip without missing-model issue; partial page failure retains local models; toggle header preservation vs default injection. Action: Add unit/integration tests for those contracts before merge.
Toggle-path assumptions — fixed. Generated headers are now limited to nine exact model IDs verified against their current Workers AI input schemas. There is no fallback for future models or entire publishers. Existing curated wire comments still win. If a new toggle's path is unknown, the model goes to manual authoring; for an existing model, reasoning stays curated while other useful fields can still update. The two specifically cited models, Kimi K2.7 Code and GLM-5.2, currently both declare chat_template_kwargs.enable_thinking as a boolean in Workers AI's schema. We do not infer that from the publisher name.
Missing-model reporting — simplified to the existing reasoning-specific mechanism. Removed the three generic hooks and now use MissingReasoningOptionsError with an explicit reason. The runner already catches this per model, includes the reason in its report/issue, and deduplicates missing-model issues. Manual-authoring recovery is intentional: these are otherwise usable models that need researched controls, not models permanently excluded from the catalogue. Other models continue syncing normally.
Mandatory without controls — fixed.mandatory: true alone now preserves existing controls or defers a new reasoner. [] requires all three affirmative fields: mandatory: true, supported_efforts: [], and supports_max_tokens: false. This distinguishes “always on” from “always on with no caller controls.” Partial or contradictory empty evidence does not clear curated options.
Tests — expanded the separate regression checks while retaining the requested one-provider-file scope. All requested contracts are exercised locally, including null and mandatory-unknown preservation, concrete API controls, explicit no-control reasoning, budgets, toggle/none exclusion, curated headers, verified and unknown wire paths, reasoning-specific issue reporting, and partial-page retention. There are 15 passing Workers AI checks and 15 passing existing OpenRouter tests (198 assertions). No test file is added to this PR, as explicitly requested for its scope.
[high] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:31 - Check: Every toggle must carry an exact host wire-path leading comment (AGENTS.md → Reasoning options). Why:TOGGLE_HEADER hard-codes chat_template_kwargs.enable_thinking for every ID in ENABLE_THINKING_MODELS, but this host is not uniform: DeepSeek entries use thinking.type, Kimi uses chat_template_kwargs.thinking, and @cf/moonshotai/kimi-k2.7-code already has a toggle with no header so the next authoritative-header sync will invent the wrong path. Action: Map wire comments per model (or derive them from each model’s sync-input.json), never a single enable_thinking default; do not put DeepSeek/Kimi IDs on an enable_thinking allowlist.
[high] [possible mistake]packages/core/src/sync/providers/cloudflare-workers-ai.ts:208 - Check: Relay/host reasoning_options must match this host’s real controls (lab + verified Workers AI peers / sync-input.json), not a partial Search summary. Why: Search options replace catalogue options whenever workersAiReasoningOptions returns any non-undefined set. The PR states GLM-4.7-Flash becomes toggle-only, which would drop the catalogue’s verified effortlow|medium|high already cited from Workers AI sync-input.json. That is “concrete” Search metadata erasing stronger host evidence. Action: Prefer Search only when it is a complete, model-specific control set; otherwise merge/preserve catalogue efforts (and document the Search payload vs sync-input.json for each changed model).
[medium] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:273 - Check:mandatory: true without a concrete control set must not invent always-on [] or wipe curated controls. Why:noControls returns [] when mandatory === true, supported_efforts is [], and supports_max_tokens === false. Empty array means “no caller control,” overwrites existing reasoning_options, and contradicts the PR contract and AGENTS.md (uncertainty / incomplete metadata must preserve authored controls; [] only when affirmatively uncontrolled). Action: Return undefined in that case so the runner/catalogue keep existing options (same as null/missing efforts).
[medium] [possible mistake]packages/core/src/sync/providers/cloudflare-workers-ai.ts:258 - Check: Toggle detection must not require mandatory === false when the API omits mandatory. Why: Toggle is pushed only on mandatory === false. With WorkersAiReasoning making mandatory optional, mandatory: undefined + efforts without none yields effort-only and drops a real on/off control OpenRouter’s mapper would still emit via !reasoning.mandatory. Action: Treat non-mandatory / omitted mandatory like OpenRouter (!reasoning.mandatory) unless Workers AI always sends an explicit boolean—verify and test both shapes.
[medium] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:250 - Check: New sync control-mapping behavior needs focused regression coverage (sync.md / existing provider test pattern). Why:workersAiReasoningOptions, null-effort preserve, toggle wire-header injection, and “unknown toggle → keep catalogue” have no tests under packages/core/test/, so the failure modes above can ship silently on hourly sync. Action: Add unit tests for null/[]/partial reasoning objects, toggle+effort shapes, header allowlist behavior, and preserve-on-insufficient-metadata.
Re-evaluated each item against the catalogue-safety contract:
Fixed the unsafe fallback. DeepSeek and Kimi are removed from the enable_thinking allowlist. Existing authored wire comments remain authoritative; missing wire information preserves existing reasoning or sends new models through manual authoring. A generic schema is not sufficient evidence for these families.
Kept GLM-4.7-Flash toggle-only. Its per-model configuration was explicitly corrected by the Workers AI model owner to { "mandatory": false, "default_enabled": true }. The old sync-input.json enum is a shared Chat Completions schema, not evidence of three GLM effort grades. The creator template uses enable_thinking. Correcting the stale public schema is also in progress. Reintroducing those generic levels would undo the intended fix.
Simplified empty controls to preservation. Empty options now always keep the catalogue, including the explicit empty-array case.
Fixed partial metadata conservatively. An omitted mandatory flag without an explicit none effort now preserves existing controls. It neither drops an existing toggle nor invents one from an omitted boolean.
Verified separately; kept the requested PR scope. The author explicitly requested provider-only changes and removal of the tracked test file. The temporary regression suite passes: 15 tests, 184 assertions, including the added incomplete/empty metadata cases. No changes to shared providers or catalogue schemas.
[high] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:211 - Check: Concrete Search controls may replace catalogue options only when the payload is complete enough not to drop real controls. Why:workersAiReasoningOptions returns early only when mandatory is missing (or supported_efforts is null). For mandatory: false with no / empty efforts it still emits [{ type: "toggle" }]. The PR body cites GLM-4.7-Flash as toggle-only from Search, while the catalogue has toggle + low/medium/high (same pattern on Gemma, Nemotron, GLM-5.2, Kimi). That path overwrites verified effort lists with toggle-only. Action: Treat “toggle with no concrete effort allowlist” (and other partial shapes) as insufficient: return undefined so authored options are kept, or only replace when Search’s control set is a verified full description of this model’s surface.
[high] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:118 - Check: Authoritative headers must keep curated wire-path comments; stripping must not delete hand-authored docs. Why:preservedHeader = header.replace(TOGGLE_HEADER, "") only removes the exact one-line # Toggle: chat_template_kwargs.enable_thinking = true|false\n. Curated headers on Gemma, Nemotron, GLM-4.7-Flash, Qwen, Kimi, and DeepSeek document enable_thinking / thinking / thinking.type in multi-line form. On rewrite, authoritativeHeaders: true replaces the on-disk header with this stripped+rebuilt string, so those comments are dropped or reduced to a generic enable_thinking line that is wrong for DeepSeek/Kimi. Action: Stop string-replacing curated headers. Prefer runner-preserved headers, or rebuild headers only from known wire paths per model (as Friendli does), and never discard multi-line docs that already name the toggle field.
[medium] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:122 - Check: Every toggle must have a correct leading wire-path comment; unknown wires must not invent enable_thinking. Why: Toggle acceptance is gated on ENABLE_THINKING_MODELS or a loose header regex. Models with toggle but no header (e.g. @cf/moonshotai/kimi-k2.7-code) keep toggle while authoritativeHeaders writes an empty header. Models outside the allowlist that already document a non-enable_thinking wire keep options but can still lose header text via the strip above. New Search toggles for allowlisted IDs always get the enable_thinking header even if the real path differs. Action: Derive the toggle header from the known wire for that model ID (or require a curated header); refuse to write toggle without a verified path; do not default unknown toggles to chat_template_kwargs.enable_thinking.
[medium] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:198 - Check: Sync reasoning-mapping changes need focused tests (OpenRouter-style coverage in packages/core/test). Why: There are no tests for workersAiReasoningOptions, header preservation, incomplete Search payloads, or the “unknown toggle wire → keep catalogue” branch. Regressions like toggle-only wiping effort or header wipe will not be caught. Action: Add unit tests for: supported_efforts: null / missing mandatory → keep existing options; mandatory: false without efforts → do not emit toggle-only over a richer catalogue; null allowlist never expands to the full effort enum; toggle header behavior for enable_thinking vs thinking.type vs chat_template_kwargs.thinking; unknown toggle wire preserves catalogue options.
Addressed the concrete partial-metadata gap in 78d5d51:
An explicit empty effort list now always preserves catalogue controls. A toggle flag without efforts also preserves graded controls for other models. GLM-4.7-Flash is the verified toggle-only exception: its Workers AI configuration was corrected during this work, and the old shared low/medium/high docs are precisely the stale data being replaced. This does not infer that Gemma, Nemotron, or other models are toggle-only.
The multiline-header concern does not reproduce: replacement matches one exact generated line, then concatenates the complete remaining header. The regression harness round-trips multiline DeepSeek thinking.type, Kimi chat_template_kwargs.thinking, and Qwen comments unchanged, including a second idempotent sync. I added an explicit code comment and tightened the unknown-wire fallback to return the original header unchanged.
Newly introduced toggles require a curated wire comment or one of the five verified exact IDs. DeepSeek/Kimi receive no default enable_thinking wire. Existing catalogue controls with an unknown wire remain untouched while other properties update; this change deliberately does not invent a repair for an already-authored control.
The author explicitly requested removing the tracked test file and keeping this PR provider-only. I retained that scope and reran the external regression harness: 16 tests, 201 assertions, all passing. Coverage includes empty/partial/null preservation, the GLM exception, multiline headers and unknown wires, plus retries/partial pages. Existing OpenRouter tests also pass.
[high] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:263 - Check: GLM-4.7-Flash is the verified toggle-only exception (PR contract / comment). Why: The special-case only short-circuits when supported_efforts is missing. If Search returns mandatory: false plus the generic low|medium|high list the PR calls inaccurate, the mapper still emits toggle + those efforts and overwrites the catalogue. Toggle-only never wins when the bad enum is present. Action: For @cf/zai-org/glm-4.7-flash, force toggle-only (ignore graded efforts) whenever Search is treated as usable, or document and implement a different explicit rule that matches live Workers AI controls.
[medium] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:164 - Check: Sync must not fail closed on a single existing model’s header I/O; prefer runner-owned catalogue state. Why:modelHeader uses a CWD-relative this.modelsDir path and readFileSync with no guard. The runner already loaded headers into existing, but any ENOENT/CWD mismatch throws outside MissingReasoningOptionsError and aborts the whole provider sync. Action: Prefer the runner’s cached leading comments (e.g. pass header via context or drop the re-read), or resolve an absolute repo path and treat read failures as preserve-existing rather than a hard throw.
[medium] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:252 - Check: Complex sync control mapping needs focused regression tests (sync.md / peer providers like AI Gateway). Why:workersAiReasoningOptions encodes many fail-closed branches (null efforts, empty efforts, missing mandatory, glm special-case, toggle+effort, budget_tokens, unknown wire freeze). None are covered under packages/core/test/. Action: Add unit tests for those branches (and header/wire freeze behavior) so a later Search shape change cannot silently rewrite catalogue reasoning.
Addressed the actionable findings in the latest revision:
GLM-4.7 rule clarified. The inaccurate enum comes from the shared input JSON schema, which this sync does not consume. The model's corrected Search configuration supplies binary thinking with no graded efforts. The exception recognizes that current shape; it is not a permanent override of future concrete Search metadata. Per the source-priority contract, a valid, explicitly populated Search effort list remains authoritative. The code comment and PR description now state this rule, with regression coverage for both omitted and concrete efforts. Hardcoding toggle-only regardless of future Search data would violate that contract.
Header I/O isolated. Header reads now resolve from the module's absolute repository path; the provider keeps its repository-relative modelsDir so generated missing-model issues still show a useful path. A failed header read warns and skips only that model, preserving its file through deleteMissing: false; the remaining models still update. A regression removes read permission after the runner loads the catalogue and verifies the unreadable file stays byte-identical while another model updates. The shared runner remains untouched, as requested for this provider-scoped PR.
Tests verified without reintroducing a tracked test file. The PR author explicitly requested provider code only. The temporary harness now passes 19 tests / 214 assertions; all 15 existing OpenRouter tests also pass.
The companion catalogue review also identified a concrete single mandatory effort as no caller choice. The mapper now emits [] for that known fixed effort, retaining a separately advertised reasoning budget if present. Missing/null/empty/partial metadata still preserves authored controls.
[high] [possible mistake]packages/core/src/sync/providers/cloudflare-workers-ai.ts:223 - Check: Incomplete Search metadata must not clobber authored Workers AI reasoning controls; host controls must match verified wire/schema evidence. Why: For @cf/zai-org/glm-4.7-flash, omitted supported_efforts is treated as authoritative toggle-only and will replace the catalogue’s toggle + low|medium|high. That conflicts with the hand-authored file’s own citation that native /ai/run accepts reasoning_effort = low|medium|high and enable_thinking (providers/cloudflare-workers-ai/models/@cf/zai-org/glm-4.7-flash.toml), and with the PR’s stated rule that incomplete Search controls keep the catalogue. Action: Verify current Workers AI sync-input.json / Search payload for this model. If graded effort is still real, drop the special case so omitted efforts preserve catalogue options. If toggle-only is correct, update the model header/citation to match and only apply toggle-only on an explicit Search shape (not merely missing efforts).
[medium] [possible mistake]packages/core/src/sync/providers/cloudflare-workers-ai.ts:210 - Check: Sync behavior with many safety branches needs focused regression coverage. Why:workersAiReasoningOptions and the new translateModel header/wire paths encode several non-obvious contracts (supported_efforts: null, empty efforts, missing mandatory, fixed single mandatory effort → [], glm exception, unknown toggle wire preserve, deleteMissing: false page failures, generated toggle header allowlist). No tests were added; peers like Cloudflare AI Gateway cover the same class of logic. Regressions would silently rewrite or freeze reasoning options in hourly automation. Action: Add unit tests for the mapping/preserve matrix and translate-header cases (including unknown-wire preserve and allowlisted toggle header injection).
The provider now expresses the verified exception as a direct guarded return: the exact GLM ID and explicit mandatory: false, with no effort list or advertised budget. Missing efforts alone are insufficient. Missing reasoning, {}, default-only metadata, missing mandatory, null efforts and empty efforts preserve authored controls. Concrete future Search efforts remain authoritative. Replaying the fresh payload produces only the verified toggle. This keeps the agreed exception without inferring toggle-only behavior for other models or treating stale shared schema enums as model capabilities.
Regression coverage: the author explicitly requested no tracked test file in this provider-only PR, so I have not reintroduced it. The temporary regression harness now passes 19 tests / 220 assertions, including all preserve/update shapes listed above and the header/wire cases in the finding. The existing 15 OpenRouter tests also pass. This is an intentional repository-diff scope decision, not an untested mapping change.
The PR description now includes the fresh payload and links to the separate catalogue/schema corrections so the evidence is available in the review input itself.
[medium] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:189 - Check: Leading headers must match the authored reasoning_options (toggle wire path; no stale effort claims). Why: With authoritativeHeaders: true, translateModel rewrites the file header from preservedHeader whenever hasToggleWire is true. Search can change options (e.g. GLM-4.7-Flash → [{ type: "toggle" }]) while the on-disk header still documents reasoning_effort = low|medium|high, so the sync freezes contradictory comments into the catalogue. Action: When derived options drop or change effort/budget controls, regenerate or strip header lines that document those controls (keep only wire paths that still apply), instead of always preserving the prior comment block.
[medium] [violation]packages/core/src/sync/providers/cloudflare-workers-ai.ts:212 - Check: Sync behavior with concrete regression risk needs focused tests. Why:workersAiReasoningOptions / buildWorkersAiModel introduce many fail-closed branches (null/empty efforts, incomplete mandatory, fixed mandatory singleton → [], GLM-4.7 toggle exception, toggle wire-path fallback, deleteMissing: false + failed pages) with no unit coverage, unlike other provider syncs. Action: Add tests covering those branches via exported buildWorkersAiModel / translateModel (fixtures for Search reasoning shapes and header outcomes).
[low] [possible mistake]packages/core/src/sync/providers/cloudflare-workers-ai.ts:214 - Check: GLM-4.7 exception must apply for the verified Search shape. Why:supported_efforts === null returns before the glm-4.7-flash + mandatory === false special case. Omitting the field works; null would keep stale catalogue L/M/H instead of toggle-only. Action: Confirm Search never sends supported_efforts: null for that model, or treat null like omitted when the GLM exception predicates match.
[low] [violation]sync.md:208 - Check: Provider sync notes should match module contract. Why: The module now sets deleteMissing: false, retries pages, and refreshes reasoning from Search with fail-closed preservation; Workers AI notes still only describe the endpoint. Action: Document the retention, reasoning-refresh, and header rules in the Cloudflare Workers AI section.
Evaluated each item against the current source contract:
Header correction: the cited GLM header is stale, and fix(cloudflare): correct catalogue reasoning efforts & base_models #7454 already corrects it with the current toggle wire, Search source and creator citation. That PR has a clean review. This provider update deliberately preserves authored leading comments (including multiline wire instructions, source citations and serving-limit rationale). Broadly stripping or rewriting free-form effort/budget prose would risk deleting unrelated curation; I have not added such a parser. The catalogue correction remains in its separate, independently mergeable PR. Until fix(cloudflare): correct catalogue reasoning efforts & base_models #7454 merges, the old prose can remain even though this sync corrects the structured controls; that limitation is explicit.
Tracked tests: this remains an intentional author scope decision. The requested preserve/update and header cases were tested in the temporary harness (19 tests / 220 assertions); existing OpenRouter tests pass. The author explicitly requested deleting the tracked test file and keeping only Cloudflare provider code here. I am preserving that instruction rather than repeatedly reintroducing the file. Maintainer agreement on that testing scope is still needed.
Null versus omitted: the fresh September 19 GLM Search response omits supported_efforts; its reasoning is exactly {"mandatory":false,"default_enabled":true}. A future explicit supported_efforts: null intentionally preserves the catalogue for this model too. We do not claim that Search can never send null, and we do not equate a null allowlist with verified toggle-only metadata. This is a deliberate safety rule covered by the regression harness, not a missing exception.
sync.md: its existing Workers AI endpoint/auth/path statements remain accurate. The author explicitly excluded changes to this top-level file. The added source-priority, retention and header contract is documented in this PR description and provider comments; I have kept the requested scope.
No code was changed solely to satisfy these conflicting scope requests. The two outstanding review tradeoffs are persistent test coverage and preserving curated prose until the companion catalogue correction merges; they need a maintainer's scope decision rather than another speculative code change.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refresh Workers AI reasoning from Search while keeping the catalogue safe. Changes are confined to the Workers AI provider.
Before: authored reasoning options always won, even when Search advertised corrected controls. After: valid model controls update the catalogue; invalid reasoning does not prevent other usable properties from updating. A concrete single mandatory effort means no effort choice (
[]);supported_efforts: nullnever expands to an enum. Reasoning budgets require explicitsupports_max_tokens: true.Verified GLM-4.7 exception: a fresh September 19 Search response for
@cf/zai-org/glm-4.7-flashcontains exactly:{"reasoning":{"mandatory":false,"default_enabled":true}}Its per-model ConfigAPI record matches. The verified Workers control is
chat_template_kwargs.enable_thinking, consistent with the creator's template, which switches the assistant prefix usingenable_thinking. The code requires this exact model ID plus explicitmandatory: falsewhen efforts and budget support are absent. Missing reasoning,{}, null/empty efforts, or an absent mandatory flag still preserve the catalogue. A future concrete Search effort list remains authoritative.The old catalogue header and published input schema still contain a shared low/medium/high enum. Those are the stale inputs being corrected: catalogue PR #7454 updates the header and controls; docs PR #33541 corrects the schema. They are separate from this provider-only change.
Curated headers are preserved. Unknown toggle wires retain existing reasoning; unreadable headers skip only that model. New reasoners without verified controls use the existing manual-authoring issue flow.
Validation: 19 temporary regression tests / 220 assertions pass, covering the preserve/update matrix, fixed mandatory effort, explicit GLM shape, header preservation/failures, unknown wires, retries and partial pages. All 15 existing OpenRouter tests pass. The PR author explicitly requested no tracked test file; that scope remains unchanged. The fresh GLM Search payload was replayed and produces toggle-only controls.