mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-01 06:53:36 +00:00
fix(agents): preserve compactionSummary in limitHistoryTurns (fixes #97590) (AI-assisted)
This commit is contained in:
@@ -118,6 +118,50 @@ describe("limitHistoryTurns", () => {
|
||||
expect(limited[1].role).toBe("assistant");
|
||||
});
|
||||
|
||||
it("preserves leading compactionSummary when limiting", () => {
|
||||
const compactionSummary: AgentMessage = {
|
||||
role: "compactionSummary",
|
||||
summary: "Previous conversation about topic X",
|
||||
tokensBefore: 5000,
|
||||
tokensAfter: 2000,
|
||||
timestamp: Date.now(),
|
||||
} as AgentMessage;
|
||||
const messages = [
|
||||
compactionSummary,
|
||||
...makeMessages(["user", "assistant", "user", "assistant"]),
|
||||
];
|
||||
const limited = limitHistoryTurns(messages, 1);
|
||||
// compactionSummary is preserved, last 1 user turn + assistant kept
|
||||
expect(limited.length).toBe(3);
|
||||
expect(limited[0].role).toBe("compactionSummary");
|
||||
expect(firstText(limited[1])).toBe("message 2");
|
||||
});
|
||||
|
||||
it("preserves leading branchSummary when limiting", () => {
|
||||
const branchSummary: AgentMessage = {
|
||||
role: "branchSummary",
|
||||
summary: "Branch context",
|
||||
fromId: "abc",
|
||||
timestamp: Date.now(),
|
||||
} as AgentMessage;
|
||||
const messages = [branchSummary, ...makeMessages(["user", "assistant", "user", "assistant"])];
|
||||
const limited = limitHistoryTurns(messages, 1);
|
||||
expect(limited.length).toBe(3);
|
||||
expect(limited[0].role).toBe("branchSummary");
|
||||
});
|
||||
|
||||
it("returns all when only non-conversation messages exist", () => {
|
||||
const compactionSummary: AgentMessage = {
|
||||
role: "compactionSummary",
|
||||
summary: "Summary only",
|
||||
tokensBefore: 1000,
|
||||
timestamp: Date.now(),
|
||||
} as AgentMessage;
|
||||
const limited = limitHistoryTurns([compactionSummary], 2);
|
||||
expect(limited).toHaveLength(1);
|
||||
expect(limited[0].role).toBe("compactionSummary");
|
||||
});
|
||||
|
||||
it("preserves message content integrity", () => {
|
||||
// Limiting should slice whole turns, not mutate tool calls or message bodies.
|
||||
const messages: AgentMessage[] = [
|
||||
|
||||
@@ -16,6 +16,10 @@ function stripThreadSuffix(value: string): string {
|
||||
/**
|
||||
* Limits conversation history to the last N user turns (and their associated
|
||||
* assistant responses). This reduces token usage for long-running DM sessions.
|
||||
*
|
||||
* Leading non-conversation messages (e.g. compactionSummary, branchSummary)
|
||||
* placed at index 0 by buildSessionContext are always preserved, since they
|
||||
* carry summarized pre-compaction context that history limiting must not drop.
|
||||
*/
|
||||
export function limitHistoryTurns(
|
||||
messages: AgentMessage[],
|
||||
@@ -25,14 +29,30 @@ export function limitHistoryTurns(
|
||||
return messages;
|
||||
}
|
||||
|
||||
let userCount = 0;
|
||||
let lastUserIndex = messages.length;
|
||||
// Preserve leading non-conversation messages (compactionSummary, branchSummary, etc.)
|
||||
// that buildSessionContext places at index 0 to carry pre-compaction context.
|
||||
let conversationStart = 0;
|
||||
while (conversationStart < messages.length) {
|
||||
const role = messages[conversationStart].role;
|
||||
if (role === "user" || role === "assistant") {
|
||||
break;
|
||||
}
|
||||
conversationStart++;
|
||||
}
|
||||
|
||||
for (let i = messages.length - 1; i >= 0; i--) {
|
||||
if (messages[i].role === "user") {
|
||||
const tail = messages.slice(conversationStart);
|
||||
if (tail.length === 0) {
|
||||
return messages;
|
||||
}
|
||||
|
||||
let userCount = 0;
|
||||
let lastUserIndex = tail.length;
|
||||
|
||||
for (let i = tail.length - 1; i >= 0; i--) {
|
||||
if (tail[i].role === "user") {
|
||||
userCount++;
|
||||
if (userCount > limit) {
|
||||
return messages.slice(lastUserIndex);
|
||||
return [...messages.slice(0, conversationStart), ...tail.slice(lastUserIndex)];
|
||||
}
|
||||
lastUserIndex = i;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user