kiro.dev rejects any body carrying a top-level systemPrompt with
400 REQUEST_BODY_INVALID. The translators stopped emitting the field in
v0.5.59 (the prompt travels in the first user turn via contentPrefix),
but two paths kept writing it back downstream of the translator:
- rtk/systemInject.js::injectKiroSystem() appended the RTK prompt to
body.systemPrompt, so every kr/ model failed whenever an RTK injector
(caveman, ponytail) was active. It now appends to the first history
user turn's content (else currentMessage), reusing
dedupStringAppend/hasPrompt so retries stay idempotent.
- executors/kiro.js::appendRepairInstruction() wrote the tool-call repair
instruction to systemPrompt on the retry, turning every repair into a
hard failure. It now appends to currentMessage.userInputMessage.content.
isKiroBody() no longer requires a string body.systemPrompt — that marker
is gone from the wire shape — and sniffs the conversation turn shape
instead, keeping the stray-conversationState guard intact. Stale comments
in both kiro translators corrected: the systemPrompt local is only a
session-replay cache key, not a wire field.
Also drops the mirror/rollback repair heuristic the injector no longer
needs: net -52 lines.
Fixes#3641, #3845, #2890, #2901, #2939, #3109, #3459, #3749
Caveman/Ponytail injection now matches each target wire format instead of
assuming an OpenAI-shaped body:
- Chat arrays append a text block; Responses arrays append input_text and
create typed message items
- Claude inserts before the final cache-control block; Gemini preserves the
snake/camel systemInstruction wrapper
- Kiro updates systemPrompt and its mirrored first-user prefix atomically,
rolling back if the pair fails to converge
- Format label decides Claude/Gemini before the wire-shape sniff, since their
bodies also carry messages[]/contents[] and Anthropic rejects a "system"
role inside messages[]
- Delimiter-aware dedup makes injection exact-idempotent across retries, so
distinct prompts sharing a long prefix are no longer collapsed
- Every write is fail-open on frozen or proxied bodies
Saver order and X-9Router-Token-Saver: off behavior are unchanged.
Fixes#3202.