mirror of
https://github.com/cline/cline.git
synced 2026-09-19 02:05:44 +08:00
Budget basic compaction projections
This commit is contained in:
@@ -3,6 +3,7 @@ import type {
|
||||
CoreCompactionContext,
|
||||
CoreCompactionResult,
|
||||
} from "../../types/config";
|
||||
import { buildBudgetProjection } from "./budget-projection";
|
||||
import {
|
||||
type EstimateMessageTokens,
|
||||
findFirstUserMessageIndex,
|
||||
@@ -390,7 +391,23 @@ export function runBasicCompaction(options: {
|
||||
...candidates.map((candidate) => candidate.message),
|
||||
...protectedTail,
|
||||
];
|
||||
if (!haveMessagesChanged(options.context.messages, nextMessages)) {
|
||||
const budgeted = buildBudgetProjection({
|
||||
messages: nextMessages,
|
||||
targetTokens,
|
||||
policyIntent: "basic_compaction_projection",
|
||||
estimateMessageTokens: options.estimateMessageTokens,
|
||||
});
|
||||
if (budgeted.status === "failed") {
|
||||
options.logger?.debug("Basic compaction returned best-effort projection", {
|
||||
budgetWarnings: budgeted.warnings.map((warning) => warning.code),
|
||||
projectedTokens: budgeted.estimatedTokens,
|
||||
targetTokens,
|
||||
maxInputTokens: options.context.maxInputTokens,
|
||||
});
|
||||
}
|
||||
const resultMessages = budgeted.messages;
|
||||
|
||||
if (!haveMessagesChanged(options.context.messages, resultMessages)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -402,18 +419,20 @@ export function runBasicCompaction(options: {
|
||||
options.estimateMessageTokens,
|
||||
);
|
||||
const afterTokens = getTotalTokens(
|
||||
nextMessages,
|
||||
resultMessages,
|
||||
options.estimateMessageTokens,
|
||||
);
|
||||
options.logger?.debug("Performed basic compaction", {
|
||||
messagesBefore: options.context.messages.length,
|
||||
messagesAfter: nextMessages.length,
|
||||
messagesRemoved: options.context.messages.length - nextMessages.length,
|
||||
messagesAfter: resultMessages.length,
|
||||
messagesRemoved: options.context.messages.length - resultMessages.length,
|
||||
tokensBefore: beforeTokens,
|
||||
tokensAfter: afterTokens,
|
||||
budgetActions: budgeted.actions.length,
|
||||
budgetWarnings: budgeted.warnings.map((warning) => warning.code),
|
||||
targetTokens,
|
||||
maxInputTokens: options.context.maxInputTokens,
|
||||
});
|
||||
|
||||
return { messages: nextMessages };
|
||||
return { messages: resultMessages };
|
||||
}
|
||||
|
||||
@@ -365,13 +365,28 @@ describe("createContextCompactionPrepareTurn", () => {
|
||||
const compacted = runForcedBasicCompaction(messages, 1);
|
||||
|
||||
expect(compacted).toEqual([
|
||||
{ role: "user", content: "Old request" },
|
||||
{ role: "user", content: "Read the latest file" },
|
||||
assistantToolUseMessage("tool-a"),
|
||||
toolResultMessage("tool-a", "latest result"),
|
||||
]);
|
||||
});
|
||||
|
||||
it("budgets the complete basic compaction output including the latest turn", () => {
|
||||
const messages: LlmsProviders.Message[] = [
|
||||
{ role: "user", content: "original task" },
|
||||
{ role: "assistant", content: "old assistant " + "x".repeat(10_000) },
|
||||
{ role: "user", content: "latest typed prompt" },
|
||||
assistantToolUseMessage("tool-live"),
|
||||
toolResultMessage("tool-live", "live result " + "y".repeat(10_000)),
|
||||
];
|
||||
|
||||
const compacted = runForcedBasicCompaction(messages, 700);
|
||||
|
||||
expect(totalJsonTokens(compacted)).toBeLessThanOrEqual(700);
|
||||
expect(JSON.stringify(compacted)).toContain("latest typed prompt");
|
||||
expectNoOrphanedToolPairs(compacted);
|
||||
});
|
||||
|
||||
it("does not compact a single typed user message", () => {
|
||||
const messages: LlmsProviders.Message[] = [
|
||||
{ role: "user", content: "Only current request" },
|
||||
|
||||
Reference in New Issue
Block a user