mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-09 05:43:57 +00:00
Treat already-compacted CLI compaction as no-op (#99136)
This commit is contained in:
@@ -273,6 +273,74 @@ describe("runCliTurnCompactionLifecycle", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("treats already-compacted CLI transcript compaction as a no-op", async () => {
|
||||
const sessionKey = "agent:main:qwen-already-compacted";
|
||||
const sessionId = "session-qwen-already-compacted";
|
||||
const sessionFile = path.join(tmpDir, "session-qwen-already-compacted.jsonl");
|
||||
const storePath = path.join(tmpDir, "sessions-qwen-already-compacted.json");
|
||||
await writeSessionFile({ sessionFile, sessionId });
|
||||
|
||||
const sessionEntry: SessionEntry = {
|
||||
sessionId,
|
||||
updatedAt: Date.now(),
|
||||
sessionFile,
|
||||
contextTokens: 1_000,
|
||||
totalTokens: 950,
|
||||
totalTokensFresh: true,
|
||||
};
|
||||
const sessionStore: Record<string, SessionEntry> = { [sessionKey]: sessionEntry };
|
||||
await fs.writeFile(storePath, JSON.stringify(sessionStore, null, 2), "utf-8");
|
||||
|
||||
const compactCalls: Array<Parameters<ContextEngine["compact"]>[0]> = [];
|
||||
const maintenance = vi.fn(async () => ({ changed: false, bytesFreed: 0, rewrittenEntries: 0 }));
|
||||
const recordCliCompactionInStore = vi.fn();
|
||||
setCliCompactionTestDeps({
|
||||
resolveContextEngine: async () => ({
|
||||
...buildContextEngine({ compactCalls }),
|
||||
async compact(compactParams) {
|
||||
compactCalls.push(compactParams);
|
||||
throw new Error("Already compacted");
|
||||
},
|
||||
}),
|
||||
createPreparedEmbeddedAgentSettingsManager: async () => ({
|
||||
getCompactionReserveTokens: () => 200,
|
||||
getCompactionKeepRecentTokens: () => 0,
|
||||
applyOverrides: () => {},
|
||||
}),
|
||||
shouldPreemptivelyCompactBeforePrompt: () => ({
|
||||
route: "fits",
|
||||
shouldCompact: false,
|
||||
estimatedPromptTokens: 600,
|
||||
promptBudgetBeforeReserve: 800,
|
||||
overflowTokens: 0,
|
||||
toolResultReducibleChars: 0,
|
||||
effectiveReserveTokens: 200,
|
||||
}),
|
||||
resolveLiveToolResultMaxChars: () => 20_000,
|
||||
runContextEngineMaintenance: maintenance,
|
||||
recordCliCompactionInStore,
|
||||
});
|
||||
|
||||
const updatedEntry = await runCliTurnCompactionLifecycle({
|
||||
cfg: {} as OpenClawConfig,
|
||||
sessionId,
|
||||
sessionKey,
|
||||
sessionEntry,
|
||||
sessionStore,
|
||||
storePath,
|
||||
sessionAgentId: "main",
|
||||
workspaceDir: tmpDir,
|
||||
agentDir: tmpDir,
|
||||
provider: "ollama",
|
||||
model: "qwen3:14b",
|
||||
});
|
||||
|
||||
expect(compactCalls).toHaveLength(1);
|
||||
expect(maintenance).not.toHaveBeenCalled();
|
||||
expect(recordCliCompactionInStore).not.toHaveBeenCalled();
|
||||
expect(updatedEntry).toBe(sessionEntry);
|
||||
});
|
||||
|
||||
it("routes OpenAI Codex harness CLI compaction through native harness compaction", async () => {
|
||||
const sessionKey = "agent:main:codex";
|
||||
const sessionId = "session-codex";
|
||||
|
||||
@@ -200,8 +200,9 @@ function isUnsupportedNativeHarnessCompaction(
|
||||
return result?.ok === false && result.failure?.reason === "unsupported_harness_compaction";
|
||||
}
|
||||
|
||||
function isBelowCompactionTargetReason(reason: string | undefined): boolean {
|
||||
return classifyCompactionReason(reason) === "below_threshold";
|
||||
function isBenignCliCompactionNoopReason(reason: string | undefined): boolean {
|
||||
const classification = classifyCompactionReason(reason);
|
||||
return classification === "below_threshold" || classification === "already_compacted_recently";
|
||||
}
|
||||
|
||||
function isIntentionalNativeAutoCompactionSkip(
|
||||
@@ -317,18 +318,23 @@ async function compactCliTranscript(params: {
|
||||
resolveCompactionTimeoutMs(params.cfg),
|
||||
);
|
||||
} catch (error) {
|
||||
log.warn(
|
||||
`CLI transcript compaction failed for ${params.provider}/${params.model}: ${error instanceof Error ? error.message : String(error)}`,
|
||||
);
|
||||
const reason = error instanceof Error ? error.message : String(error);
|
||||
if (isBenignCliCompactionNoopReason(reason)) {
|
||||
log.info(
|
||||
`CLI transcript compaction skipped for ${params.provider}/${params.model}: ${reason}`,
|
||||
);
|
||||
return { compacted: false };
|
||||
}
|
||||
log.warn(`CLI transcript compaction failed for ${params.provider}/${params.model}: ${reason}`);
|
||||
return {
|
||||
compacted: false,
|
||||
failureReason: error instanceof Error ? error.message : String(error),
|
||||
failureReason: reason,
|
||||
};
|
||||
}
|
||||
|
||||
if (!compactResult.compacted) {
|
||||
const reason = compactResult.reason ?? "nothing to compact";
|
||||
if (isBelowCompactionTargetReason(reason)) {
|
||||
if (isBenignCliCompactionNoopReason(reason)) {
|
||||
log.info(
|
||||
`CLI transcript compaction skipped for ${params.provider}/${params.model}: ${reason}`,
|
||||
);
|
||||
@@ -466,7 +472,7 @@ async function compactNativeHarnessCliTranscript(params: {
|
||||
|
||||
if (!result?.compacted) {
|
||||
const reason = result?.reason ?? "nothing to compact";
|
||||
if (isBelowCompactionTargetReason(reason)) {
|
||||
if (isBenignCliCompactionNoopReason(reason)) {
|
||||
log.info(
|
||||
`CLI native harness compaction skipped for ${params.provider}/${params.model}: ${reason}`,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user