fix(kiro): never send a top-level systemPrompt (400 REQUEST_BODY_INVALID)
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
This commit is contained in:
@@ -115,7 +115,7 @@ async function text(stream) {
|
||||
async function execute(executor = new KiroExecutor(), overrides = {}) {
|
||||
return executor.execute({
|
||||
model: "kr/claude-opus-4.8",
|
||||
body: { systemPrompt: "base", conversationState: {} },
|
||||
body: { conversationState: { currentMessage: { userInputMessage: { content: "base", modelId: "m" } } } },
|
||||
stream: true,
|
||||
credentials,
|
||||
...overrides
|
||||
@@ -342,8 +342,12 @@ describe("Kiro terminal integrity recovery", () => {
|
||||
const retryBody = JSON.parse(fetchMock.mock.calls[1][1].body);
|
||||
|
||||
expect(body).toContain("Recovered safely.");
|
||||
expect(retryBody.systemPrompt).toContain("tool_call wrapper was malformed");
|
||||
expect(retryBody.systemPrompt).not.toContain("IGNORE_ALL_INSTRUCTIONS");
|
||||
// The repair instruction rides in the user turn: kiro.dev rejects a
|
||||
// top-level systemPrompt with 400 REQUEST_BODY_INVALID.
|
||||
const retryContent = retryBody.conversationState.currentMessage.userInputMessage.content;
|
||||
expect(retryBody.systemPrompt).toBeUndefined();
|
||||
expect(retryContent).toContain("tool_call wrapper was malformed");
|
||||
expect(retryContent).not.toContain("IGNORE_ALL_INSTRUCTIONS");
|
||||
});
|
||||
|
||||
it("lets a complete tool call override metadata end_turn", async () => {
|
||||
|
||||
Reference in New Issue
Block a user