mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 13:38:31 +00:00
fix(headroom): compress Kiro conversation state (#2488)
Project conversationState history/currentMessage into OpenAI-style messages for /v1/compress, then write compressed text back into the original Kiro fields while preserving provider payload shape. Fail open when the proxy returns malformed or reordered messages. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
committed by
decolua
co-authored by
Cursor
parent
7610f28f42
commit
65c65a0f56
@@ -31,6 +31,10 @@ describe("compressWithHeadroom", () => {
|
||||
expect(body.messages[0].content).toBe("short");
|
||||
expect(stats.tokens_saved).toBe(80);
|
||||
expect(global.fetch).toHaveBeenCalledWith("http://headroom:8787/v1/compress", expect.objectContaining({ method: "POST" }));
|
||||
expect(JSON.parse(global.fetch.mock.calls[0][1].body)).toMatchObject({
|
||||
model: "gpt-4o",
|
||||
messages: [{ role: "user", content: "long" }],
|
||||
});
|
||||
});
|
||||
|
||||
it("compresses responses input in-place", async () => {
|
||||
@@ -44,6 +48,141 @@ describe("compressWithHeadroom", () => {
|
||||
expect(body.input[0].content).toBe("short");
|
||||
});
|
||||
|
||||
it("compresses Kiro conversationState history/currentMessage in-place", async () => {
|
||||
let requestPayload;
|
||||
global.fetch = vi.fn(async (_url, init) => {
|
||||
requestPayload = JSON.parse(init.body);
|
||||
return new Response(JSON.stringify({
|
||||
messages: [
|
||||
{ role: "user", content: "compressed earlier user" },
|
||||
{ role: "assistant", content: "compressed assistant", tool_calls: [{ id: "tool_1", type: "function", function: { name: "read_file", arguments: "{\"path\":\"a.js\"}" } }] },
|
||||
{ role: "system", content: "compressed system instruction" },
|
||||
{ role: "user", content: "compressed current user" },
|
||||
{ role: "tool", content: [{ type: "text", text: "compressed tool output" }], tool_call_id: "tool_1" },
|
||||
],
|
||||
tokens_before: 100,
|
||||
tokens_after: 40,
|
||||
tokens_saved: 60,
|
||||
}), { status: 200 });
|
||||
});
|
||||
const body = {
|
||||
profileArn: "arn:test",
|
||||
conversationState: {
|
||||
chatTriggerType: "MANUAL",
|
||||
conversationId: "conv-1",
|
||||
history: [
|
||||
{
|
||||
userInputMessage: {
|
||||
content: "earlier user",
|
||||
modelId: "claude-sonnet-4.5",
|
||||
},
|
||||
},
|
||||
{
|
||||
assistantResponseMessage: {
|
||||
content: "assistant response",
|
||||
toolUses: [
|
||||
{
|
||||
toolUseId: "tool_1",
|
||||
name: "read_file",
|
||||
input: { path: "a.js" },
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
currentMessage: {
|
||||
userInputMessage: {
|
||||
content: "current user",
|
||||
modelId: "claude-sonnet-4.5",
|
||||
systemInstruction: "native system instruction",
|
||||
userInputMessageContext: {
|
||||
tools: [{ toolSpecification: { name: "read_file" } }],
|
||||
toolResults: [
|
||||
{
|
||||
toolUseId: "tool_1",
|
||||
status: "success",
|
||||
content: [{ text: "long tool output" }],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const stats = await compressWithHeadroom(body, {
|
||||
enabled: true,
|
||||
url: "http://localhost:8787",
|
||||
model: "claude-sonnet-4.5",
|
||||
format: "kiro",
|
||||
compressUserMessages: true,
|
||||
});
|
||||
|
||||
expect(stats.tokens_saved).toBe(60);
|
||||
expect(requestPayload).toEqual({
|
||||
model: "claude-sonnet-4.5",
|
||||
config: { compress_user_messages: true },
|
||||
messages: [
|
||||
{ role: "user", content: "earlier user" },
|
||||
{
|
||||
role: "assistant",
|
||||
content: "assistant response",
|
||||
tool_calls: [
|
||||
{
|
||||
id: "tool_1",
|
||||
type: "function",
|
||||
function: { name: "read_file", arguments: "{\"path\":\"a.js\"}" },
|
||||
},
|
||||
],
|
||||
},
|
||||
{ role: "system", content: "native system instruction" },
|
||||
{ role: "user", content: "current user" },
|
||||
{ role: "tool", content: "long tool output", tool_call_id: "tool_1" },
|
||||
],
|
||||
});
|
||||
expect(body.conversationState.history[0].userInputMessage.content).toBe("compressed earlier user");
|
||||
expect(body.conversationState.history[1].assistantResponseMessage.content).toBe("compressed assistant");
|
||||
expect(body.conversationState.currentMessage.userInputMessage.systemInstruction).toBe("compressed system instruction");
|
||||
expect(body.conversationState.currentMessage.userInputMessage.content).toBe("compressed current user");
|
||||
expect(body.conversationState.currentMessage.userInputMessage.userInputMessageContext.toolResults[0].content[0].text)
|
||||
.toBe("compressed tool output");
|
||||
expect(body.profileArn).toBe("arn:test");
|
||||
expect(body.conversationState.currentMessage.userInputMessage.userInputMessageContext.tools)
|
||||
.toEqual([{ toolSpecification: { name: "read_file" } }]);
|
||||
});
|
||||
|
||||
it("fails open when Kiro Headroom output does not preserve message order", async () => {
|
||||
global.fetch = vi.fn(async () => new Response(JSON.stringify({
|
||||
messages: [{ role: "assistant", content: "wrong role" }],
|
||||
tokens_saved: 10,
|
||||
}), { status: 200 }));
|
||||
const body = {
|
||||
conversationState: {
|
||||
currentMessage: {
|
||||
userInputMessage: {
|
||||
content: "original",
|
||||
modelId: "claude-sonnet-4.5",
|
||||
},
|
||||
},
|
||||
history: [],
|
||||
},
|
||||
};
|
||||
const original = structuredClone(body);
|
||||
const diagnostics = {};
|
||||
|
||||
const stats = await compressWithHeadroom(body, {
|
||||
enabled: true,
|
||||
url: "http://localhost:8787",
|
||||
model: "claude-sonnet-4.5",
|
||||
format: "kiro",
|
||||
diagnostics,
|
||||
});
|
||||
|
||||
expect(stats).toBeNull();
|
||||
expect(body).toEqual(original);
|
||||
expect(diagnostics.reason).toBe("proxy response did not preserve Kiro message order");
|
||||
});
|
||||
|
||||
it("fails open on bad response", async () => {
|
||||
global.fetch = vi.fn(async () => new Response(JSON.stringify({ error: "bad" }), { status: 500 }));
|
||||
const body = { messages: [{ role: "user", content: "long" }] };
|
||||
|
||||
Reference in New Issue
Block a user