feat: kimi client — K3 wire facts made first-class#47
Merged
Conversation
Kimi Code integration (OpenAI Chat Completions adapted into the
Responses model) hardened against the real K3 wire (devlog
2026-07-20-kimi-k3-wire-facts):
- session id: K3 sends prompt_cache_key ("session_<uuid>") in every
request body, stable across subagents, auto-compaction, and --resume.
New wire-table field sessionBodyField; extractSessionId reads it
(bare uuid), compact stubs preserve it -> session chip + cross-run
--continue stitching work for kimi.
- compaction: the restart packing merges later user text into the
first user message (NOT verbatim), so the sig fallback split the
thread and the boundary vanished. openai-dialect reunification is
marker-gated on the re-sent summary preamble ("The conversation so
far has been compacted..."); a marker-merged continuation appends
without the 10-turn-drop heuristic (the repack is known, not
inferred). Verified against the live 78-call trace: one main thread,
one boundary, zero unattributed turns, resume trace stitches clean.
- pricing: coding-plan wire ids estimate at the equivalent
pay-per-token rates (CATALOG_ALIASES: k3 -> moonshotai/kimi-k3,
kimi-for-coding -> kimi-k2.7-code). The cost chip is an estimate,
same convention as Claude Max OAuth traffic; models.dev's
kimi-for-coding provider lists $0 subscription entries we never use.
- media: tool-message parts arrays pass through; image_url parts map
to Anthropic-shape image blocks instead of hitting the floor.
- fixtures: kimi-k3-session.jsonl.zst (synthetic, mirrors the observed
wire incl. the mct=131072 compaction call + msgs=4 restart) joins
the K2.7 adapter tripwire; mitm tests scrub all six proxy env vars.
Repo hygiene: manual-test dirs -> temp/ (ignored), internal notes ->
docs/internal/ (ignored), stale package-lock.json dropped.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…round-trip
Two-axis review findings applied:
- openaiCompleted chat detection: request shape (messages[] without
input[]) is now the primary signal and the SSE marker keeps its
quotes ('"object":"chat.completion') — a bare indexOf misrouted any
codex Responses stream whose CONTENT merely discussed the Chat
Completions API, dropping its output and usage.
- openai marker reunification also requires the two dialect-neutral
structural facts (parent quiet forever, continuation starts smaller
than the deepest packing) — a user literally typing the summary
preamble mid-session no longer merges threads.
- The devlog's open question closes: rebuild identical pre/post
cctrace compact on the K3 fixture (reunification + boundary +
attribution through supersede-stubs), regression-tested.
- CHANGELOG: 0.19.0 entry (CONTRIBUTING requires it; missed in the
feature commit).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What
Hardens the Kimi Code integration against the real K3 wire (devlog
2026-07-20-kimi-k3-wire-facts.org), fixing the three gaps the review surfaced plus repo hygiene.Session identity (prompt_cache_key)
K3 sends
prompt_cache_key: "session_<uuid>"in every request body — stable across subagent threads, auto-compaction, and--resumeacross processes. New declarativesessionBodyFieldin the wire table;extractSessionIdreads it (bare uuid), compact stubs preserve it. Session chip + cross-run--continuestitching now work for kimi (the resume trace's 9 previously-unattributed turns attribute clean).Compaction reunification
Kimi's auto-compaction restarts the packing with the original first user message with later user text merged in — not verbatim — so the first-user-text sig split the thread and the boundary was invisible (the devlog's "main thread does not split" claim didn't hold on rebuild). openai-dialect reunification is marker-gated on the re-sent summary preamble ("The conversation so far has been compacted..."): structural signals alone could false-claim a tail subagent, since kimi subagents share the session id. A marker-merged continuation appends without the 10-turn-drop heuristic — the repack is known, not inferred. Verified against the live 78-call trace: one main thread, one displayed boundary, zero unattributed, zero false rewinds.
Pricing as estimate
The cost chip is an estimate, not a bill — it already prices Claude Max OAuth traffic at API rates. Coding-plan wire ids now estimate at the equivalent pay-per-token rates via
CATALOG_ALIASES(k3->moonshotai/kimi-k3$3/$15,kimi-for-coding->kimi-k2.7-code). models.dev'skimi-for-codingprovider lists $0 subscription entries; we never use them.Also
image_urlparts map to Anthropic-shape image blocks (were silently dropped)tests/mitm.test.tsscrubs all six proxy env vars per test (proxied dev shells leaked into the suite)mct=131072compaction call + msgs=4 restart; K2.7 fixture stays as the adapter tripwire; both privacy-scannedtemp/(ignored), internal notes ->docs/internal/(ignored), stalepackage-lock.jsondroppedTests
bun test: 476 pass, 0 fail (27 files). New regression coverage: K3 session rebuild (reunification + boundary + attribution), pck extraction incl. through compact stubs, catalog aliases.🤖 Generated with Claude Code