Skip to content

server: keep live KV reusable when clients strip transient metadata blocks - #727

Open
Flor1an-B wants to merge 1 commit into
antirez:mainfrom
Flor1an-B:fix-transient-metadata-kv-continuation
Open

server: keep live KV reusable when clients strip transient metadata blocks#727
Flor1an-B wants to merge 1 commit into
antirez:mainfrom
Flor1an-B:fix-transient-metadata-kv-continuation

Conversation

@Flor1an-B

Copy link
Copy Markdown

Fixes #364.

Coding agents (OpenCode, Claude Code, Kilo Code/Roo Code) inject per-turn transient metadata into user message content (<system-reminder>, <environment_details>) and rebuild the next request's history without it. The live KV keeps the bytes that were actually rendered, so the replayed transcript no longer token-matches the sampled session and every user turn pays a full reprefill.

This is the same shape hidden thinking already handles: the live state is richer than the visible replay, so the existing visible-key continuation mechanism applies. After a finished turn, remember the transcript the next request is expected to render — the current one minus the transient spans — keyed to the live token frontier. A client that replays the blocks verbatim simply never matches the key and still gets exact token-prefix matching; nothing changes for it.

Credit: original design and implementation by @adv0r in #378. That PR now has a real conflict with main, not just a stale rebase: native Metal/CUDA session batching (36cd0ca and follow-ups) added a server_slot parameter to every session/checkpoint function it touches (thinking_live_remember/clear, remember_thinking_checkpoint, canonicalize_tool_checkpoint), added after #378 was opened. This PR threads the same strip_transient_blocks() / should_remember_transient_checkpoint() / remember_transient_checkpoint() design through the slot-aware signatures — the diff is otherwise unchanged from #378, same test names and assertions. Opening as a new PR rather than pushing to #378's branch since I don't have write access to it.

Testing:

  • Full make ds4_test suite passes clean.
  • Live A/B on the real quant (ds4-server, 2-turn conversation with a <system-reminder> block dropped on replay between turns, exactly as OpenCode does):
    • before (baseline, patch reverted): live kv cache miss live=88 prompt=97 common=5 reason=token-mismatch — full reprefill.
    • after: transient live checkpoint remembered ... stripped=128 then, on the next turn, thinking live continuation match=visible-prefix cached=30 prompt=54 — live continuation, no reprefill.
  • Re-verified a 2-turn tool-calling round trip with no transient blocks present still gets exact-DSML-replay continuation unchanged (18 new tokens prefilled instead of a full 406-token reprefill), confirming the canonicalize_tool_checkpoint → remember-or-clear restructuring is behavior-preserving when nothing is stripped.

…locks

Coding agents (OpenCode, Claude Code, Kilo Code/Roo Code) inject per-turn
transient metadata into user message content (<system-reminder>,
<environment_details>) and rebuild the next request's history without it.
The live KV keeps the bytes that were actually rendered, so the replayed
transcript no longer token-matches the sampled session and every user turn
pays a full reprefill (issue antirez#364).

This is the same shape hidden thinking already handles: the live state is
richer than the visible replay, so the existing visible-key continuation
mechanism applies. After a finished turn, remember the transcript the next
request is expected to render -- the current one minus the transient spans
-- keyed to the live token frontier. A client that replays the blocks
verbatim simply never matches the key and still gets exact token-prefix
matching; nothing changes for it.

Original design and implementation by @adv0r in antirez#378. That PR now conflicts
with main: native Metal/CUDA session batching (36cd0ca and follow-ups) added
a server_slot parameter to the session/checkpoint functions it touches
(thinking_live_remember/clear, remember_thinking_checkpoint,
canonicalize_tool_checkpoint) after antirez#378 was opened. This threads the same
strip_transient_blocks()/should_remember_transient_checkpoint()/
remember_transient_checkpoint() design through the slot-aware signatures;
the diff is otherwise unchanged from antirez#378, same test names and assertions.

Tested: full `make ds4_test` suite passes. Live A/B on the real quant
(ds4-server, 2-turn conversation with a <system-reminder> block dropped on
replay, as OpenCode does):
  - before: `live kv cache miss live=88 prompt=97 common=5 reason=token-mismatch`
  - after:  `transient live checkpoint remembered ... stripped=128` then
            `thinking live continuation match=visible-prefix cached=30 prompt=54`
Also re-verified a 2-turn tool-calling round trip with no transient blocks
present still gets exact-DSML-replay continuation unchanged (18 new tokens
prefilled instead of a full 406-token reprefill), confirming the canonicalize
-> remember-or-clear restructuring is behavior-preserving when nothing is
stripped.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

KV cache invalidated on every turn by client-injected transient metadata in user messages

1 participant