Repository navigation
Conversation
The K3.1 spellings (kimi-k3.1-pro[-highspeed] on the direct platform, k3.1-pro[-highspeed] on Kimi Code) inherit the K3 contract verbatim, including the replay rule: the API requires the assistant reasoning_content on later tool turns and answers HTTP 400 when a replayed tool-call message misses it (Kimi Code error reference, missing-reasoning-content-field). The reasoning-replay gate only learned the bare k3 ids through the exact-K3 matchers, so a K3.1 tool round fell through to the generic heuristics and stripped the required field. The gate carries its own K3.1 arm on the vendor's two official routes; it is deliberately narrower than extending the shared matchers, whose other consumers (effort shaping, route validation, pickers) carry different K3-only contracts. Regression pins both routes with a tool-call round. Signed-off-by: asto18089 <asto18089@126.com>
b8d90c9 to
1d9b74b
Compare
|
Rebased onto the current #131 head ( The single K3.1 commit was replayed onto Also retargeted this PR's base from |
The host catalog registers https://api.kimi.ai/coding/v1 as an official alias of the Kimi Code membership plan and saved settings keep it verbatim, but the exact route gate only learned api.kimi.com — so on the overseas route the K3.1 tool-turn replay contract (and the default model fallback, credential guidance, and billing presentation) still missed. Teach both the exact and the loose Kimi Code route gates the .ai host, keeping neighboring paths, lookalike hosts, and custom gateways outside the membership semantics. The K3.1 regression now pins both bare ids on the overseas route. Review: pinjou-agent#825 5765736266 / 5765853804 Signed-off-by: asto <asto18089@126.com>
|
Pushed the overseas-endpoint follow-up for the review P2 (
Sequencing note for the parent pin: once this and the #131 stack land on |
asto18089
left a comment
There was a problem hiding this comment.
Fresh multi-lane review (7 lanes + 2 verification lanes: gate semantics, shared-matcher consumer audit, Kimi-family sweep, other-vendor sweep incl. all pinvoy-agent#825 families, mutation testing at both heads, smuggle/CI classification, claim verification). All findings verified at head 5e4545615. Verdict: the fix is real, root-caused, and well-scoped; requesting changes on three items before merge.
Verified-good
- Root cause confirmed:
build_chat_messages_with_reasoningemitsreasoning_contenton the replayed tool-call assistant message only whenshould_replay_reasoning_content_for_provider_on_routereturns true (chat.rs:2885,2918-2920); pre-PR the gate only learned bare K3 via the exact matchers. The new arm is catalog-independent, effort-immune (consistent with the always-reasoning contract), and correctly ordered (no shadowing with the K3 arms — spelling sets are disjoint, all matchers exact-compare). - Dedicated arm (vs extending the shared matchers) is justified: ~23 production consumers of
is_exact_direct_moonshot_k3_route/is_exact_kimi_code_k3_routegate K3-only contracts (effort dialects, route shapes, picker ladders, output limits, search timeout floor, two display labels); teaching the shared matchers K3.1 would have flipped all of them at once. PR body claim verified factually accurate. - Commit 2's
.aigate arm is exactly as strict as the.comarm (is_exact_https_routereuse), with negative neighbors (case/path/scheme/port/query) inprovider.rs:2226-2253. Loose-helper over-match safety verified (host+path pinned, no substring matching). - Smuggle: clean — 4 files, every hunk serves the disclosed purpose; no deps/submodule/workflow changes. Both commits DCO-signed, conventional subjects.
- Mutations at
5e4545615: arm deletion, Kimi-Code URL,.aiURL, and 3 of 4 spellings all go red when removed. fmt rc=0; applicable clippy gates rc=0; kimi/replay suites 125/75 green; ubuntu CI passed the full suite with the PR applied.
Must fix
- M1 — doc-comment hijack (
chat.rs:3485-3504): the helperis_kimi_k31_model_spellingwas inserted between the gate fn's doc block and the gate fn, so the entire "Route-aware reasoning replay policy." block now rustdoc-attaches to the 4-line spelling helper; the gate fn is left undocumented; "see the arm inside" (3494) points backwards; sentences 3492-3494 vs 3495-3496 duplicate each other. The inherited sentence "only Kimi Code's exact membership-plan endpoint has this replay contract" (3489-3490) is contradicted by the direct-platform K3 arm (3513) and the new arm itself (3533-3534) as the block now stands. Compiles clean, so CI cannot catch it. - M2 — commit 2 is incomplete on the config side (split-brain): the TUI exact gate and the TUI copy of the loose fallback learned
api.kimi.ai/coding/v1, but the config-crate twins did not:moonshot_base_url_uses_kimi_code(crates/config/src/lib.rs:4619-4624, still.com-only) andprovider_base_url_is_official(Moonshot, …)(lib.rs:4874-4882, delegates to it). Verified consequence: a Moonshot route onapi.kimi.ai/coding/v1with no model resolves the default tokimi-k2.7-code(the config-crate fallback misses), whichvalidate_kimi_code_api_model_idthen hard-rejects as a direct-platform id on the membership endpoint — a config-resolution failure on exactly the route commit 2 exists to support (the same config works onapi.kimi.com/coding/v1).provider_base_url_is_officialreturning false also contradicts its own "so route canonicalization and credential scoping cannot disagree" doctrine (lib.rs:4852-4856); consumers includeclient/responses.rs:905, clilib.rs:3117, app-serverchat_completions.rs:153/255. - M3 — required
linkgate red ×3, PR-caused: the body has no line-startCloses #N/No-Issue:anchor (checkedpr-issue-link.yml's regex; the mid-sentence "pinvoy-agent#825" mentions don't satisfy it). Will add the line in the fix wave.
Minors (will fix in the fix wave unless noted)
m— PR body overstates the pre-PR bug: the twokimi-k3.1-pro[-highspeed]spellings already replayed at default effort via thekimi-prefix heuristic (models.rs:447); the actual pre-PR failures were (a) barek3.1-pro[-highspeed]on Kimi Code never replaying and (b) all four spellings stripped at stored effort=off. Will recalibrate the body wording.m— "the host catalog registers api.kimi.ai" (provider.rs:517-518,client.rs:9386-9387, commit 2 body): no host catalog in this repo registers it (docs still documentapi.kimi.comonly); name the app-side catalog explicitly or updatedocs/PROVIDERS.md/docs/CONFIGURATION.md.m— typo "pinjou-agent#825" ×3 in code (provider.rs:518,client.rs:9328,client.rs:9387) + commit 2 body.m— stale adjacent strings: the membership-rejection error still names onlyapi.kimi.com/coding/v1(config.rs:10227); Moonshot guidance suggests only the.comURL (config.rs:7075).m— test-strength (mutation-verified): unpinned — the direct-platform matcher (masked by the generickimi-prefix; an effort=off direct leg would pin it), theprovider == Moonshotroute restriction (no custom-gateway negative), case/trim normalization (no variant input), and the 4th spellingkimi-k3.1-pro-highspeed. Sibling K3 tests (chat.rs:5166-5191,6228-6282) set the negative-test norm.m— commit 2's.aiwidening legitimately extends K3 effort shaping / sampling / route shape / billing / pickers to the overseas endpoint, but only the gate + replay legs are tested on.ai.
Follow-ups disclosed (not for this PR)
- OpenRouter
moonshotai/kimi-k3.1-pro(a codewhale-hq#825 row): not deterministically covered — theprovider == Moonshotrestriction is faithful to the aggregator precedent, but the generic heuristics miss themoonshotai/prefix (only k2.x org ids enumerated,models.rs:473-476), so replay depends on the runtime models.dev cache (fails offline/fresh installs); the same id on Volcengine replays via the bare-kimi-prefix — a pure prefix artifact. Cheap fix: add the org-prefixed spellings to the recognition list. - MiniMax M3.1-Flash (codewhale-hq#825-served, always-thinking):
minimax-m3.1-flashis in no recognition list → no replay, no stream classification. Different vendor contract; genuine follow-up. - Other codewhale-hq#825-family recognition staleness (pre-existing):
zai-org/GLM-5.3on SiliconFlow,minimax/minimax-m3.1-flashandanthropic/claude-opus-5.5org-prefixes on OpenRouter,Qwen/Qwen3.8-27B, mimo v2.6 ids,gemini-4thought-signature matcher,kimi-k2.5preserve_thinking verification, and the app-side bridge-arm gap for Mistral/Together/Meta/Groq (belongs on pinvoy-agent#825, not here). - CI reds other than
linkare base/environmental (verified against base0583e19cb): Lint = pre-existingclippy::collapsible_ifatturn_loop.rs:5611(untouched file); cargo-audit/cargo-deny = RUSTSEC-2026-0430 in the untouched lockfile; Lint & Type Check = release-data drift; Version drift / Integrations / Test-windows = unrelated subsystems (the PR's own test passed on Windows). - Upstream-first note: the gate is foundation code; fork-policy letter prefers upstream-first for all-embedder fixes — worth an upstream PR once the stack lands.
- Known pre-existing flake observed during verification:
forkguard_model_operation_auxiliary_retry_keys(operation_tests.rs:379) is order-dependent, passes in isolation, unrelated to this PR.
Fix wave incoming for M1-M3 + the minors; follow-ups stay disclosed.
Commit 2 taught the TUI-side loose fallback about api.kimi.ai/coding/v1 but left the config-crate twin and provider_base_url_is_official behind, so the two layers disagreed about the official endpoint family: a model-less Moonshot route on the overseas host resolved the default direct-platform id and then hard-failed membership validation on exactly the route the commit exists to support. Widen the loose membership recognition to both hosts, document the exact-gate subset doctrine it must keep, and pin the relation (and the lookalike/neighbor negatives) with tests. Also fixes the route-gate comment premise (the overseas alias is registered by the app-side model catalog, pinvoy-agent#825) and its pinjou typo. Signed-off-by: asto <asto18089@126.com>
The K3.1 helper was inserted between the replay gate and its doc block, so the whole route-aware replay policy comment rustdoc- attaches to the 4-line spelling matcher while the gate itself is left undocumented, with a duplicated sentence pair and a backwards "see the arm inside" pointer. Give the helper its own doc line and restore the gate's policy doc with an accurate K3.1 paragraph. The regression test now pins what the arm actually promises: all four spellings across both vendor hosts, the stale-effort-off always-replay case (which is what the direct-platform matcher is for — the generic kimi- prefix masks it at default effort), the case/padding normalization on the bare Kimi Code ids, and the custom-gateway / non-Moonshot dialect boundary as negatives. Also aligns the membership-rejection and plan-key guidance strings with both membership hosts and fixes the remaining pinjou typo in the overseas test comment. Signed-off-by: asto <asto18089@126.com>
|
Fix wave pushed as fd0aef4 + e11b90e (head M1 — doc-comment hijack (e11b90e): the spelling helper now carries its own doc line; the gate's "Route-aware reasoning replay policy." block is restored directly above M2 — config-crate M3 — Minors: route-gate comment premise reworded to "the app's model catalog registers api.kimi.ai" (provider.rs); membership-rejection and plan-key guidance strings now name both hosts; remaining Test-strength (e11b90e): the K3.1 regression test now pins all four spellings across both hosts, plus — each verified red under its targeted mutation before revert —
Erratum to the review comment: the Local gates: Disclosed, not fixed here (follow-ups): OpenRouter |
Jensen's review 5779604267 (P2): after the rebase onto main 78dcc1c the PR's child is the public maintenance head 11cba403d, whose exact-route exceptions only recognize k3/k3-256k - a tool turn on the bare k3.1-pro ids omits the required assistant reasoning_content and the Kimi Code gateway answers 400. Defer the two bare rows from the Kimi Coding Plan group (en/ja keys follow; the row-scoped FE imageCapable annotation goes with them) until the pinned child carries the upstream replay repair (Pinvou/CodeWhale#137). The prefixed platform rows ride the kimi-k3 fallback and stay; the custom row still permits manual ids. Test expectations flipped to the deferred semantics with the restore condition documented. Signed-off-by: asto <asto18089@126.com>
Jensen's review 5779604267 (P2): after the rebase onto main 78dcc1c the PR's child is the public maintenance head 11cba403d, whose exact-route exceptions only recognize k3/k3-256k - a tool turn on the bare k3.1-pro ids omits the required assistant reasoning_content and the Kimi Code gateway answers 400. Defer the two bare rows from the Kimi Coding Plan group (en/ja keys follow; the row-scoped FE imageCapable annotation goes with them) until the pinned child carries the upstream replay repair (Pinvou/CodeWhale#137). The prefixed platform rows ride the kimi-k3 fallback and stay; the custom row still permits manual ids. Test expectations flipped to the deferred semantics with the restore condition documented. Signed-off-by: asto <asto18089@126.com>
The Moonshot chat path prefixes a digit-led registry tool name with `_` to satisfy Kimi's documented `name` pattern, but the loop only ran outbound: the response decoder deliberately keeps the wire spelling, no layer mapped `_3d_render` back to `3d_render`, and every model call for such a tool died at dispatch with "tool not available" — the tools array kept advertising the name, so the model would retry the same spelling until the turn ended. Two halves now close the loop: - Engine dispatch: after every exact and alias lookup misses, `resolve_tool_definition` falls back to the unprefixed name for the exact `_<digit>` shape the prefix produces. A genuinely underscore-led name is never stripped, and a registry holding both spellings still resolves exactly (the fallback only fires after the exact lookups missed), so approval and policy gates see the canonical registry name. - Replay: assistant tool_calls persist the registry spelling, so the Moonshot message builder re-applies the wire prefix on replayed `tool_calls` (shared `prefix_digit_led_function_name` helper with the tools-array pass). The history now matches the tools array and stays inside the documented pattern; pre-fixture histories that already carry `_` pass through untouched. Also pins the hand-copied sampling-route matcher to the config-crate reference on the shared host (the twin covers the overseas host until PR #137 widens the shared matcher; that assertion is what flips when it lands), and restores the doc comment that `sanitize_moonshot_chat_tools` had lost when the prefix function was inserted between the comment and its function. No-Issue: completes the digit-led fix in this PR's own series; the repository has issues disabled. Signed-off-by: asto <asto18089@126.com>
Jensen's review 5779604267 (P2): after the rebase onto main 78dcc1c the PR's child is the public maintenance head 11cba403d, whose exact-route exceptions only recognize k3/k3-256k - a tool turn on the bare k3.1-pro ids omits the required assistant reasoning_content and the Kimi Code gateway answers 400. Defer the two bare rows from the Kimi Coding Plan group (en/ja keys follow; the row-scoped FE imageCapable annotation goes with them) until the pinned child carries the upstream replay repair (Pinvou/CodeWhale#137). The prefixed platform rows ride the kimi-k3 fallback and stay; the custom row still permits manual ids. Test expectations flipped to the deferred semantics with the restore condition documented. Signed-off-by: asto <asto18089@126.com>
Jensen's review 5779604267 (P2): after the rebase onto main 78dcc1c the PR's child is the public maintenance head 11cba403d, whose exact-route exceptions only recognize k3/k3-256k - a tool turn on the bare k3.1-pro ids omits the required assistant reasoning_content and the Kimi Code gateway answers 400. Defer the two bare rows from the Kimi Coding Plan group (en/ja keys follow; the row-scoped FE imageCapable annotation goes with them) until the pinned child carries the upstream replay repair (Pinvou/CodeWhale#137). The prefixed platform rows ride the kimi-k3 fallback and stay; the custom row still permits manual ids. Test expectations flipped to the deferred semantics with the restore condition documented. Signed-off-by: asto <asto18089@126.com>
Summary
Teaches the reasoning-replay gate the K3.1 family spellings so a K3.1 tool round replays
reasoning_contentlike bare K3 does.The replay gate only learned the bare k3 ids through
is_exact_direct_moonshot_k3_route/is_exact_kimi_code_k3_route. Thek3.1-pro[-highspeed]Kimi Code membership spellings fell through to the generic heuristics, which never matched, so the sender omitted the assistant tool-call message'sreasoning_contenton the follow-up request — the Kimi Code error reference documents that missing field as HTTP 400. Thekimi-k3.1-pro[-highspeed]direct-platform spellings did replay at default effort via the generickimi-prefix heuristic, but were still stripped whenever a stored effort ofoffwas present; the review-round arm (2026-11-04) makes all four spellings replay catalog-independently and effort-immune on both vendor routes, including the overseasapi.kimi.ai/coding/v1endpoint.Contract
reasoning_content.Scope
Deliberately narrow: the gate gains its own K3.1 arm on the vendor's two official routes instead of extending the shared exact-K3 matchers, whose other consumers (effort shaping, route validation, pickers) carry different K3-only contracts. Regression pins both routes with a tool-call round (assistant thinking + tool use → tool result → assert
reasoning_contentreplays).Context
Surfaced by the pinvou-agent#825 review round 3 (the app's model-catalog refresh adds these presets); the consumer's wire-body harness is ready to pin the second request once this lands.
No-Issue: follow-up to the pinvoy-agent#825 model-catalog review; this repository has issues disabled.