Skip to content

[BUG] OpenRouter + Kimi K3: requests sent with no reasoning effort and fabricated max_tokens=209,716 → multi-minute invisible-thinking turns #1316

Description

@Lamonz88

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

  1. Environment: Linux, Zoo Code 3.76.0, OpenRouter provider, model moonshotai/kimi-k3.
  2. Start any non-trivial agentic task.
  3. 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.
  4. 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.
  5. 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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions