Skip to content

Commit 47f3374

Browse files
committed
fix(codex): start budget native compaction
1 parent d886816 commit 47f3374

4 files changed

Lines changed: 49 additions & 5 deletions

File tree

docs/plugins/codex-harness-runtime.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,17 @@ history, search, `/new`, `/reset`, and future model or harness switching.
214214

215215
Explicit compaction requests, such as `/compact` or a plugin-requested manual
216216
compact operation, start native Codex compaction with `thread/compact/start`.
217+
OpenClaw also starts native Codex compaction for the `budget` preflight trigger
218+
used by `agents.defaults.compaction.maxActiveTranscriptBytes`, because that
219+
trigger protects the local channel transcript mirror from growing without a
220+
native cleanup request. Other automatic triggers remain Codex-owned and are not
221+
started by OpenClaw.
222+
217223
OpenClaw returns after starting that native operation. It does not wait for
218224
completion, impose a separate OpenClaw timeout, restart the shared Codex
219225
app-server, or record the operation as an OpenClaw-completed compaction.
226+
Operators debugging oversized transcript behavior can search gateway logs for
227+
`started codex app-server compaction` with `trigger: "budget"`.
220228

221229
When a context engine requests Codex thread-bootstrap projection, OpenClaw
222230
projects tool-call names and ids, input shapes, and redacted tool-result content

docs/reference/session-management-compaction.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,9 @@ OpenClaw also enforces a safety floor for embedded runs:
354354
string such as `"20mb"` to run local compaction before a turn when the active
355355
transcript gets large. This guard is active only when
356356
`truncateAfterCompaction` is also enabled. Leave it unset or set `0` to
357-
disable.
357+
disable. For Codex harness sessions, this preflight starts native Codex
358+
compaction with `thread/compact/start` rather than replacing Codex compaction
359+
with an OpenClaw summarizer.
358360
- When `agents.defaults.compaction.truncateAfterCompaction` is enabled,
359361
OpenClaw rotates the active transcript to a compacted successor JSONL after
360362
compaction. Branch/restore checkpoint actions use that compacted successor;

extensions/codex/src/app-server/compact.test.ts

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ describe("maybeCompactCodexAppServerSession", () => {
126126
expect(details.pending).toBe(true);
127127
});
128128

129-
it("skips native app-server compaction for automatic budget triggers", async () => {
129+
it("starts native app-server compaction for automatic budget triggers", async () => {
130130
const fake = createFakeCodexClient();
131131
setCodexAppServerClientFactoryForTest(async () => fake.client);
132132
const sessionFile = await writeTestBinding();
@@ -142,16 +142,45 @@ describe("maybeCompactCodexAppServerSession", () => {
142142
}),
143143
);
144144

145+
expect(fake.request).toHaveBeenCalledWith("thread/compact/start", { threadId: "thread-1" });
146+
expect(result.ok).toBe(true);
147+
expect(result.compacted).toBe(false);
148+
expect(result.reason).toBeUndefined();
149+
expect(result.result?.tokensBefore).toBe(456);
150+
expect(compactDetails(result)).toMatchObject({
151+
backend: "codex-app-server",
152+
threadId: "thread-1",
153+
signal: "thread/compact/start",
154+
pending: true,
155+
});
156+
});
157+
158+
it("skips native app-server compaction for overflow triggers", async () => {
159+
const fake = createFakeCodexClient();
160+
setCodexAppServerClientFactoryForTest(async () => fake.client);
161+
const sessionFile = await writeTestBinding();
162+
163+
const result = requireCompactResult(
164+
await maybeCompactCodexAppServerSession({
165+
sessionId: "session-1",
166+
sessionKey: "agent:main:session-1",
167+
sessionFile,
168+
workspaceDir: tempDir,
169+
trigger: "overflow",
170+
currentTokenCount: 654,
171+
}),
172+
);
173+
145174
expect(fake.request).not.toHaveBeenCalled();
146175
expect(result.ok).toBe(true);
147176
expect(result.compacted).toBe(false);
148177
expect(result.reason).toBe("codex app-server owns automatic compaction");
149-
expect(result.result?.tokensBefore).toBe(456);
178+
expect(result.result?.tokensBefore).toBe(654);
150179
expect(compactDetails(result)).toMatchObject({
151180
backend: "codex-app-server",
152181
skipped: true,
153182
reason: "non_manual_trigger",
154-
trigger: "budget",
183+
trigger: "overflow",
155184
});
156185
});
157186

extensions/codex/src/app-server/compact.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,10 @@ async function compactCodexNativeThread(
122122
params: CompactEmbeddedPiSessionParams,
123123
options: { pluginConfig?: unknown; clientFactory?: CodexAppServerClientFactory } = {},
124124
): Promise<EmbeddedPiCompactResult | undefined> {
125-
if (params.trigger !== "manual") {
125+
// The transcript-byte budget preflight is an explicit OpenClaw request to
126+
// shrink a large channel mirror; skipping it leaves long-lived Codex sessions
127+
// above the configured local transcript guard.
128+
if (params.trigger !== "manual" && params.trigger !== "budget") {
126129
embeddedAgentLog.info("skipping codex app-server compaction for non-manual trigger", {
127130
sessionId: params.sessionId,
128131
sessionKey: params.sessionKey,
@@ -185,6 +188,7 @@ async function compactCodexNativeThread(
185188
embeddedAgentLog.info("started codex app-server compaction", {
186189
sessionId: params.sessionId,
187190
threadId: binding.threadId,
191+
trigger: params.trigger ?? "manual",
188192
});
189193
} catch (error) {
190194
if (isCodexThreadNotFoundError(error)) {
@@ -198,6 +202,7 @@ async function compactCodexNativeThread(
198202
sessionId: params.sessionId,
199203
sessionKey: params.sessionKey,
200204
threadId: binding.threadId,
205+
trigger: params.trigger ?? "manual",
201206
reason: formatCompactionError(error),
202207
});
203208
return {

0 commit comments

Comments
 (0)