Problem (one or two sentences)
When using moonshotai/kimi-k3 via OpenRouter, Zoo Code sends every request without a reasoning field and with a fabricated max_tokens of 209,716 (20% of the 1M context window, since OpenRouter reports max_completion_tokens: null). On heavy turns the model then burns exactly 32,768 completion tokens (the real upstream cap) on invisible thinking — I captured turns of 507 s and 309 s producing under 40 KB of visible output.
Context (who is affected and when)
Anyone running moonshotai/kimi-k3 (or moonshotai/kimi-latest) through the OpenRouter provider. Symptoms: multi-minute stalls with almost no visible output on long tasks, inflated completion-token bills (hidden thinking is billed as completion and not reported as reasoning tokens), ~200k tokens wrongly reserved from the usable context window, and a model that explores for hours instead of writing files (in one session, the first file-mutating tool call came at assistant block 39 of 78 — 2h10m and $3.72 in). Claude and Gemini are unaffected because they have hand-written per-model overrides; no Moonshot override exists.
Reproduction steps
- Environment: Linux, Zoo Code 3.76.0, OpenRouter provider, model
moonshotai/kimi-k3.
- Start any non-trivial agentic task.
- Capture the outgoing request (proxy or logging): it contains no
reasoning field, max_tokens: 209716, temperature: 0. OpenRouter's catalogue correctly lists reasoning in supported_parameters, and Zoo Code sets supportsReasoningEffort: true — but no effort value is ever populated (only Anthropic models have hand-written overrides), so the field is dropped from the request.
- On a long turn, watch usage:
completion_tokens climbs to exactly 32,768 (the upstream's true output cap) with only ~27–39 KB of streamed SSE content — hidden reasoning billed as completion, because no reasoning field was requested.
- Root causes (with code pointers):
reasoning dropped: parseOpenRouterModel never sets reasoningEffort for non-Anthropic ids → shouldUseReasoningEffort() returns false → field omitted.
max_tokens fabricated: fetchers/openrouter.ts falls back to Math.ceil(context_length * 0.2) when OpenRouter reports null; the value is also reserved against the usable window in context-management.
- Wrong temperature: 0 sent, while Moonshot documents K3 as fixed at 1.0.
- Latent:
finish_reason: "length" silently drops in-flight tool calls in NativeToolCallParser (never observed firing, but the failure mode is silent).
Expected result
Requests to Kimi K3 via OpenRouter carry reasoning: {"effort": ...}, a truthful max_tokens (32,768), and temperature: 1.0; thinking is bounded and reported as reasoning tokens.
Actual result
No reasoning field, max_tokens: 209716, temperature: 0. Measured: two turns at exactly 32,768 completion tokens, 507 s / 309 s wall clock, <40 KB visible output; one turn emitted the same tool-call pair 9 times after such a marathon.
Variations tried (optional)
Benchmarked 16 tasks (12 short + 4 stress) through the real extension in a real VS Code instance with a fetch-level recorder capturing every request body and SSE stream. Pass rate was already 16/16 — the damage is latency, cost, and predictability, not correctness. Regression-checked Claude Sonnet 4.5 and Gemini 2.5 Pro on the same bench: unaffected (byte-identical tool schemas, their own params untouched). I have a working fix: a model-id-conditional Moonshot capability profile (maxTokens: 32,768, reasoning ladder ["low","high","max"] default high, temperature: 1.0) applied at fetch and consumption time (the model cache blocks fetch-time fixes), plus a 6-line provider-agnostic fix for finish_reason: "length". Post-fix wire: {"max_tokens":32768,"temperature":1,"reasoning":{"effort":"high"}}; worst turn dropped from 32,768 tokens / 507 s to 804 tokens / 6.7 s. Happy to open a PR with the full investigation (raw request/SSE captures included).
Workaround available: I am currently running a self-compiled build of Zoo Code with a Moonshot capability profile, and Kimi K3 now works correctly (bounded, reported thinking; truthful max_tokens). Until an official fix lands, anyone affected can apply the same patch — happy to share it.
App Version
3.76.0
API Provider (optional)
OpenRouter
BEFORE-req-001-baseline-buggy-max_tokens-209716-no-reasoning.json
AFTER-req-001-patched-max_tokens-32768-reasoning-high-temp-1.json
Model Used (optional)
moonshotai/kimi-k3`
Zoo Code Task Links (optional)
(none — evidence is local wire captures, both shared as .json files.
Relevant logs or errors (optional)
Problem (one or two sentences)
When using
moonshotai/kimi-k3via OpenRouter, Zoo Code sends every request without areasoningfield and with a fabricatedmax_tokensof 209,716 (20% of the 1M context window, since OpenRouter reportsmax_completion_tokens: null). On heavy turns the model then burns exactly 32,768 completion tokens (the real upstream cap) on invisible thinking — I captured turns of 507 s and 309 s producing under 40 KB of visible output.Context (who is affected and when)
Anyone running
moonshotai/kimi-k3(ormoonshotai/kimi-latest) through the OpenRouter provider. Symptoms: multi-minute stalls with almost no visible output on long tasks, inflated completion-token bills (hidden thinking is billed as completion and not reported as reasoning tokens), ~200k tokens wrongly reserved from the usable context window, and a model that explores for hours instead of writing files (in one session, the first file-mutating tool call came at assistant block 39 of 78 — 2h10m and $3.72 in). Claude and Gemini are unaffected because they have hand-written per-model overrides; no Moonshot override exists.Reproduction steps
moonshotai/kimi-k3.reasoningfield,max_tokens: 209716,temperature: 0. OpenRouter's catalogue correctly listsreasoninginsupported_parameters, and Zoo Code setssupportsReasoningEffort: true— but no effort value is ever populated (only Anthropic models have hand-written overrides), so the field is dropped from the request.completion_tokensclimbs to exactly 32,768 (the upstream's true output cap) with only ~27–39 KB of streamed SSE content — hidden reasoning billed as completion, because noreasoningfield was requested.reasoningdropped:parseOpenRouterModelnever setsreasoningEffortfor non-Anthropic ids →shouldUseReasoningEffort()returns false → field omitted.max_tokensfabricated:fetchers/openrouter.tsfalls back toMath.ceil(context_length * 0.2)when OpenRouter reports null; the value is also reserved against the usable window in context-management.finish_reason: "length"silently drops in-flight tool calls inNativeToolCallParser(never observed firing, but the failure mode is silent).Expected result
Requests to Kimi K3 via OpenRouter carry
reasoning: {"effort": ...}, a truthfulmax_tokens(32,768), andtemperature: 1.0; thinking is bounded and reported as reasoning tokens.Actual result
No
reasoningfield,max_tokens: 209716,temperature: 0. Measured: two turns at exactly 32,768 completion tokens, 507 s / 309 s wall clock, <40 KB visible output; one turn emitted the same tool-call pair 9 times after such a marathon.Variations tried (optional)
Benchmarked 16 tasks (12 short + 4 stress) through the real extension in a real VS Code instance with a fetch-level recorder capturing every request body and SSE stream. Pass rate was already 16/16 — the damage is latency, cost, and predictability, not correctness. Regression-checked Claude Sonnet 4.5 and Gemini 2.5 Pro on the same bench: unaffected (byte-identical tool schemas, their own params untouched). I have a working fix: a model-id-conditional Moonshot capability profile (
maxTokens: 32,768, reasoning ladder["low","high","max"]defaulthigh,temperature: 1.0) applied at fetch and consumption time (the model cache blocks fetch-time fixes), plus a 6-line provider-agnostic fix forfinish_reason: "length". Post-fix wire:{"max_tokens":32768,"temperature":1,"reasoning":{"effort":"high"}}; worst turn dropped from 32,768 tokens / 507 s to 804 tokens / 6.7 s. Happy to open a PR with the full investigation (raw request/SSE captures included).Workaround available: I am currently running a self-compiled build of Zoo Code with a Moonshot capability profile, and Kimi K3 now works correctly (bounded, reported thinking; truthful
max_tokens). Until an official fix lands, anyone affected can apply the same patch — happy to share it.App Version
3.76.0
API Provider (optional)
OpenRouter
BEFORE-req-001-baseline-buggy-max_tokens-209716-no-reasoning.json
AFTER-req-001-patched-max_tokens-32768-reasoning-high-temp-1.json
Model Used (optional)
moonshotai/kimi-k3`
Zoo Code Task Links (optional)
(none — evidence is local wire captures, both shared as .json files.
Relevant logs or errors (optional)