

























@@ -769,6 +769,86 @@ describe("runCliTurnCompactionLifecycle", () => {
769769expect(updatedEntry?.compactionCount).toBe(1);
770770});
771771772+it("falls back to context-engine compaction when Codex native compaction returns a raw missing thread reason", async () => {
773+const sessionKey = "agent:main:codex-raw-stale-binding";
774+const sessionId = "session-codex-raw-stale-binding";
775+const sessionFile = path.join(tmpDir, "session-codex-raw-stale-binding.jsonl");
776+const storePath = path.join(tmpDir, "sessions-codex-raw-stale-binding.json");
777+await writeSessionFile({ sessionFile, sessionId });
778+779+const sessionEntry: SessionEntry = {
780+ sessionId,
781+updatedAt: Date.now(),
782+ sessionFile,
783+contextTokens: 1_000,
784+totalTokens: 950,
785+totalTokensFresh: true,
786+agentHarnessId: "codex",
787+};
788+const sessionStore: Record<string, SessionEntry> = { [sessionKey]: sessionEntry };
789+await fs.writeFile(storePath, JSON.stringify(sessionStore, null, 2), "utf-8");
790+791+const compactCalls: Array<Parameters<ContextEngine["compact"]>[0]> = [];
792+const compactAgentHarnessSession = vi.fn(async () => ({
793+ok: false,
794+compacted: false,
795+reason: "thread not found: thread-raw",
796+}));
797+const maintenance = vi.fn(async () => ({ changed: false, bytesFreed: 0, rewrittenEntries: 0 }));
798+const recordCliCompactionInStore = vi.fn(async () => ({
799+ ...sessionEntry,
800+compactionCount: 1,
801+}));
802+setCliCompactionTestDeps({
803+resolveContextEngine: async () => buildContextEngine({ compactCalls }),
804+ensureSelectedAgentHarnessPlugin: vi.fn(async () => undefined),
805+maybeCompactAgentHarnessSession: compactAgentHarnessSession as never,
806+createPreparedEmbeddedAgentSettingsManager: async () => ({
807+getCompactionReserveTokens: () => 200,
808+getCompactionKeepRecentTokens: () => 0,
809+applyOverrides: () => {},
810+}),
811+shouldPreemptivelyCompactBeforePrompt: () => ({
812+route: "fits",
813+shouldCompact: false,
814+estimatedPromptTokens: 600,
815+promptBudgetBeforeReserve: 800,
816+overflowTokens: 0,
817+toolResultReducibleChars: 0,
818+effectiveReserveTokens: 200,
819+}),
820+resolveLiveToolResultMaxChars: () => 20_000,
821+runContextEngineMaintenance: maintenance,
822+ recordCliCompactionInStore,
823+});
824+825+const updatedEntry = await runCliTurnCompactionLifecycle({
826+cfg: {} as OpenClawConfig,
827+ sessionId,
828+ sessionKey,
829+ sessionEntry,
830+ sessionStore,
831+ storePath,
832+sessionAgentId: "main",
833+workspaceDir: tmpDir,
834+agentDir: tmpDir,
835+provider: "codex",
836+model: "gpt-5.5",
837+});
838+839+expect(compactAgentHarnessSession).toHaveBeenCalledTimes(1);
840+expect(compactCalls).toHaveLength(1);
841+expect(maintenance).toHaveBeenCalledTimes(1);
842+expect(recordCliCompactionInStore).toHaveBeenCalledWith(
843+expect.objectContaining({
844+provider: "codex",
845+ sessionKey,
846+tokensAfter: undefined,
847+}),
848+);
849+expect(updatedEntry?.compactionCount).toBe(1);
850+});
851+772852it("keeps successful context-engine fallback when post-compaction maintenance fails", async () => {
773853const sessionKey = "agent:main:codex-stale-maintenance";
774854const sessionId = "session-codex-stale-maintenance";
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。