




















@@ -1003,6 +1003,100 @@ describe("runCliTurnCompactionLifecycle", () => {
10031003expect(updatedEntry?.compactionCount).toBe(1);
10041004});
100510051006+it("clears stale Codex native binding when context-engine fallback is below target", async () => {
1007+const sessionKey = "agent:main:codex-stale-binding-under-target";
1008+const sessionId = "session-codex-stale-binding-under-target";
1009+const sessionFile = path.join(tmpDir, "session-codex-stale-binding-under-target.jsonl");
1010+const storePath = path.join(tmpDir, "sessions-codex-stale-binding-under-target.json");
1011+await writeSessionFile({ sessionFile, sessionId });
1012+1013+const sessionEntry: SessionEntry = {
1014+ sessionId,
1015+updatedAt: Date.now(),
1016+ sessionFile,
1017+contextTokens: 1_000,
1018+totalTokens: 950,
1019+totalTokensFresh: true,
1020+agentHarnessId: "codex",
1021+cliSessionBindings: {
1022+codex: { sessionId: "thread-1" },
1023+},
1024+cliSessionIds: {
1025+codex: "thread-1",
1026+},
1027+};
1028+const sessionStore: Record<string, SessionEntry> = { [sessionKey]: sessionEntry };
1029+await fs.writeFile(storePath, JSON.stringify(sessionStore, null, 2), "utf-8");
1030+1031+const compactCalls: Array<Parameters<ContextEngine["compact"]>[0]> = [];
1032+const compactAgentHarnessSession = vi.fn(async () => ({
1033+ok: false,
1034+compacted: false,
1035+reason: "thread not found: thread-1",
1036+failure: {
1037+reason: "stale_thread_binding",
1038+},
1039+}));
1040+const maintenance = vi.fn(async () => ({ changed: false, bytesFreed: 0, rewrittenEntries: 0 }));
1041+const recordCliCompactionInStore = vi.fn();
1042+setCliCompactionTestDeps({
1043+resolveContextEngine: async () => ({
1044+ ...buildContextEngine({ compactCalls }),
1045+async compact(compactParams) {
1046+compactCalls.push(compactParams);
1047+return {
1048+ok: true,
1049+compacted: false,
1050+reason: "already under target",
1051+};
1052+},
1053+}),
1054+ensureSelectedAgentHarnessPlugin: vi.fn(async () => undefined),
1055+maybeCompactAgentHarnessSession: compactAgentHarnessSession as never,
1056+createPreparedEmbeddedAgentSettingsManager: async () => ({
1057+getCompactionReserveTokens: () => 200,
1058+getCompactionKeepRecentTokens: () => 0,
1059+applyOverrides: () => {},
1060+}),
1061+shouldPreemptivelyCompactBeforePrompt: () => ({
1062+route: "fits",
1063+shouldCompact: false,
1064+estimatedPromptTokens: 600,
1065+promptBudgetBeforeReserve: 800,
1066+overflowTokens: 0,
1067+toolResultReducibleChars: 0,
1068+effectiveReserveTokens: 200,
1069+}),
1070+resolveLiveToolResultMaxChars: () => 20_000,
1071+runContextEngineMaintenance: maintenance,
1072+ recordCliCompactionInStore,
1073+});
1074+1075+const updatedEntry = await runCliTurnCompactionLifecycle({
1076+cfg: {} as OpenClawConfig,
1077+ sessionId,
1078+ sessionKey,
1079+ sessionEntry,
1080+ sessionStore,
1081+ storePath,
1082+sessionAgentId: "main",
1083+workspaceDir: tmpDir,
1084+agentDir: tmpDir,
1085+provider: "codex",
1086+model: "gpt-5.5",
1087+});
1088+1089+expect(compactAgentHarnessSession).toHaveBeenCalledTimes(1);
1090+expect(compactCalls).toHaveLength(1);
1091+expect(maintenance).not.toHaveBeenCalled();
1092+expect(recordCliCompactionInStore).not.toHaveBeenCalled();
1093+expect(updatedEntry?.compactionCount).toBeUndefined();
1094+expect(updatedEntry?.cliSessionBindings?.codex).toBeUndefined();
1095+expect(updatedEntry?.cliSessionIds?.codex).toBeUndefined();
1096+expect(sessionStore[sessionKey]?.cliSessionBindings?.codex).toBeUndefined();
1097+expect(sessionStore[sessionKey]?.cliSessionIds?.codex).toBeUndefined();
1098+});
1099+10061100it("falls back to context-engine compaction when Codex native compaction returns a raw missing thread reason", async () => {
10071101const sessionKey = "agent:main:codex-raw-stale-binding";
10081102const sessionId = "session-codex-raw-stale-binding";
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。