fix(llm): preserve provider message alternation

Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>
This commit is contained in:
chrarnoldus
2026-08-21 07:41:58 +00:00
parent 43c4491560
commit 1663c27e7a
7 changed files with 39 additions and 10 deletions
@@ -435,7 +435,10 @@ const lowerMessages = Effect.fn("AnthropicMessages.lowerMessages")(function* (
}
return yield* ProviderShared.unsupportedContent("Anthropic Messages", "user", ["text", "media"])
}
messages.push({ role: "user", content })
const previous = messages.at(-1) // kilocode_change
if (previous?.role === "user") // kilocode_change
messages[messages.length - 1] = { role: "user", content: [...previous.content, ...content] } // kilocode_change
else messages.push({ role: "user", content }) // kilocode_change
continue
}
@@ -482,7 +485,10 @@ const lowerMessages = Effect.fn("AnthropicMessages.lowerMessages")(function* (
cache_control: cacheControl(breakpoints, part.cache),
})
}
messages.push({ role: "user", content })
const previous = messages.at(-1) // kilocode_change
if (previous?.role === "user") // kilocode_change
messages[messages.length - 1] = { role: "user", content: [...previous.content, ...content] } // kilocode_change
else messages.push({ role: "user", content }) // kilocode_change
}
return messages
@@ -330,7 +330,10 @@ const lowerMessages = Effect.fn("BedrockConverse.lowerMessages")(function* (
continue
}
}
messages.push({ role: "user", content })
const previous = messages.at(-1) // kilocode_change
if (previous?.role === "user") // kilocode_change
messages[messages.length - 1] = { role: "user", content: [...previous.content, ...content] } // kilocode_change
else messages.push({ role: "user", content }) // kilocode_change
continue
}
@@ -372,7 +375,10 @@ const lowerMessages = Effect.fn("BedrockConverse.lowerMessages")(function* (
const cachePoint = BedrockCache.block(breakpoints, part.cache)
if (cachePoint) content.push(cachePoint)
}
messages.push({ role: "user", content })
const previous = messages.at(-1) // kilocode_change
if (previous?.role === "user") // kilocode_change
messages[messages.length - 1] = { role: "user", content: [...previous.content, ...content] } // kilocode_change
else messages.push({ role: "user", content }) // kilocode_change
}
return messages
+8 -2
View File
@@ -222,7 +222,10 @@ const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request: LLMR
return yield* ProviderShared.unsupportedContent("Gemini", "user", ["text", "media"])
parts.push(yield* lowerUserPart(part))
}
contents.push({ role: "user", parts })
const previous = contents.at(-1) // kilocode_change
if (previous?.role === "user") // kilocode_change
contents[contents.length - 1] = { role: "user", parts: [...previous.parts, ...parts] } // kilocode_change
else contents.push({ role: "user", parts }) // kilocode_change
continue
}
@@ -281,7 +284,10 @@ const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request: LLMR
parts.push({ inlineData: { mimeType: media.mime, data: media.base64 } })
}
}
contents.push({ role: "user", parts })
const previous = contents.at(-1) // kilocode_change
if (previous?.role === "user") // kilocode_change
contents[contents.length - 1] = { role: "user", parts: [...previous.parts, ...parts] } // kilocode_change
else contents.push({ role: "user", parts }) // kilocode_change
}
return contents
@@ -197,6 +197,7 @@ describe("Anthropic Messages route", () => {
Message.user("What is the weather?"),
Message.assistant([ToolCallPart.make({ id: "call_1", name: "lookup", input: { query: "weather" } })]),
Message.tool({ id: "call_1", name: "lookup", result: { forecast: "sunny" } }),
Message.user("Summarize the result."), // kilocode_change - preserve Anthropic role alternation
],
cache: "none",
}),
@@ -210,7 +211,15 @@ describe("Anthropic Messages route", () => {
role: "assistant",
content: [{ type: "tool_use", id: "call_1", name: "lookup", input: { query: "weather" } }],
},
{ role: "user", content: [{ type: "tool_result", tool_use_id: "call_1", content: '{"forecast":"sunny"}' }] },
// kilocode_change start - adjacent user content is coalesced with tool results
{
role: "user",
content: [
{ type: "tool_result", tool_use_id: "call_1", content: '{"forecast":"sunny"}' },
{ type: "text", text: "Summarize the result." },
],
},
// kilocode_change end
],
stream: true,
max_tokens: 4096,
@@ -164,6 +164,7 @@ describe("Bedrock Converse route", () => {
Message.user("What is the weather?"),
Message.assistant([ToolCallPart.make({ id: "tool_1", name: "lookup", input: { query: "weather" } })]),
Message.tool({ id: "tool_1", name: "lookup", result: { forecast: "sunny" } }),
Message.user("Summarize the result."), // kilocode_change - preserve Bedrock role alternation
],
cache: "none",
}),
@@ -186,6 +187,7 @@ describe("Bedrock Converse route", () => {
status: "success",
},
},
{ text: "Summarize the result." }, // kilocode_change - coalesce adjacent user content
],
},
],
@@ -73,6 +73,7 @@ describe("Gemini route", () => {
]),
Message.assistant([ToolCallPart.make({ id: "call_1", name: "lookup", input: { query: "weather" } })]),
Message.tool({ id: "call_1", name: "lookup", result: { forecast: "sunny" } }),
Message.user("Summarize the result."), // kilocode_change - preserve Gemini role alternation
],
}),
)
@@ -91,6 +92,7 @@ describe("Gemini route", () => {
role: "user",
parts: [
{ functionResponse: { name: "lookup", response: { name: "lookup", content: '{"forecast":"sunny"}' } } },
{ text: "Summarize the result." }, // kilocode_change - coalesce adjacent user content
],
},
],
@@ -577,9 +577,7 @@ it.instance(
if (!Array.isArray(messages)) throw new Error("expected LLM messages")
expect(messages.at(-1)).toMatchObject({
role: "user",
content: expect.arrayContaining([
{ type: "text", text: expect.stringContaining("MAXIMUM STEPS REACHED") },
]),
content: expect.stringContaining("MAXIMUM STEPS REACHED"),
})
}),
30_000,