@openclaw/codex 2026.7.2-beta.5 → 2026.8.1-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/{app-server-policy-BmDgseo_.js → app-server-policy-zcBDc1JU.js} +1 -1
- package/dist/attempt-client-cleanup-DMLXUfa8.js +735 -0
- package/dist/binding-connection-I5Bo-AsX.js +33 -0
- package/dist/{bounded-turn-FEbUXoYT.js → bounded-turn-qgZmzy_4.js} +71 -63
- package/dist/{capabilities-BHRSI6Cn.js → capabilities-CybGI1oz.js} +8 -2
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-ico4ZFnk.js → command-formatters-B1AEz8ZA.js} +18 -18
- package/dist/{command-handlers-CRmnwI2N.js → command-handlers-Db8pu_ds.js} +484 -95
- package/dist/{compact-dEN49UH6.js → compact-LspQaGfl.js} +213 -199
- package/dist/{conversation-binding-data-BHRpYbX3.js → conversation-binding-data-CW2GuupV.js} +6 -10
- package/dist/doctor-contract-api.js +40 -43
- package/dist/{dynamic-tools-LIt9ojep.js → dynamic-tools-BVdyWkUD.js} +2984 -1221
- package/dist/effective-mcp-catalog-DIIhAtOZ.js +119 -0
- package/dist/{event-projector-assistant-message-DTgnPPVF.js → event-projector-assistant-message-BwxV4d6N.js} +11 -23
- package/dist/{attempt-notifications-CMR2_fmR.js → event-projector-usage-e5huIQWu.js} +113 -29
- package/dist/harness.js +83 -13
- package/dist/image-payload-sanitizer-CnfoUPCE.js +65 -0
- package/dist/index.js +703 -329
- package/dist/isolated-completion-C58NbL40.js +75 -0
- package/dist/local-runtime-attribution-B_2mnqhb.js +19 -0
- package/dist/media-understanding-provider.js +5 -5
- package/dist/{models-BA01NEez.js → models-BFlpn1Ex.js} +12 -17
- package/dist/native-subagent-monitor-DyTGmTUx.js +3111 -0
- package/dist/{plugin-app-cache-key-DSXX-rXO.js → plugin-app-cache-key-C3H2CVp6.js} +135 -42
- package/dist/plugin-marketplace-discovery-CzrGJdCR.js +385 -0
- package/dist/{computer-use-BjGylO-E.js → plugin-metadata-cache-CNJPj4_b.js} +211 -113
- package/dist/protocol-validators-B4F7L8Rf.js +2346 -0
- package/dist/{rate-limits-S_PXs0ul.js → rate-limits-DZXmOL8-.js} +17 -35
- package/dist/{request-CXpPennK.js → request-BRl5_UfX.js} +4 -4
- package/dist/{run-attempt-C5GTPJOE.js → run-attempt-P8BdxC1I.js} +1996 -5728
- package/dist/{runtime-artifact-C2ITXdhM.js → runtime-artifact-BVSPdd6g.js} +91 -40
- package/dist/{sandbox-guard-D1Wky__S.js → sandbox-guard-Cmwc9eIk.js} +10 -13
- package/dist/{session-binding-DlVQ-Pxs.js → session-binding-DPxIvMgE.js} +305 -271
- package/dist/{session-catalog-CP2oCcEb.js → session-catalog-xwNi_SDM.js} +418 -144
- package/dist/{session-cli-CqZ0Fp2a.js → session-cli-7hgXZDV7.js} +1 -1
- package/dist/session-retirement-DoMMJFKm.js +36 -0
- package/dist/{session-upstream-marker-QE-m5QFG.js → session-upstream-marker-CrIFX06J.js} +1 -1
- package/dist/{settled-turn-finalizer-CA_2QXIE.js → settled-turn-finalizer-BRWBO4MO.js} +36 -15
- package/dist/{shared-client-BVKE40c-.js → shared-client-kIBbGjk4.js} +721 -240
- package/dist/{side-question-CO12sHxo.js → side-question-9HAL26l9.js} +102 -53
- package/dist/{thread-lifecycle-DRg_FdzC.js → thread-lifecycle-Bu1BTDXr.js} +1355 -660
- package/dist/thread-ownership-6kOQHlyC.js +92 -0
- package/dist/thread-resume-CPrJNQVM.js +30 -0
- package/dist/{transcript-mirror-uKA-A4tB.js → transcript-mirror-B9gGgnJS.js} +202 -182
- package/dist/{transport-stdio-DXgGZ7Ib.js → transport-stdio-DIImwDVS.js} +11 -0
- package/dist/upstream-prompt-provenance-ClRBije0.js +41 -0
- package/dist/{upstream-session-fork-_Vrz4WJr.js → upstream-session-fork-CE-_LdnP.js} +5 -5
- package/dist/{usage-UpVbdX5G.js → usage-CHlV0e-o.js} +3 -3
- package/dist/{web-search-provider.runtime-CaQMYDbp.js → web-search-provider.runtime-DRw2Vl42.js} +8 -9
- package/openclaw.plugin.json +18 -3
- package/package.json +6 -7
- package/dist/attempt-client-cleanup-Ia52yRWc.js +0 -127
- package/dist/conversation-control-DE7d9DOj.js +0 -287
- package/dist/event-projector-usage-tvgb1NCX.js +0 -69
- package/dist/notification-correlation-Bj_Ak_jI.js +0 -67
- package/dist/protocol-validators-Dm4eXZmt.js +0 -6337
- package/dist/realtime-voice-api-BPcA1uN9.js +0 -494
- package/dist/realtime-voice-api.js +0 -2
|
@@ -1,23 +1,32 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { l as
|
|
3
|
-
import { _ as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { d as sessionBindingIdentity, t as CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS } from "./session-binding-DPxIvMgE.js";
|
|
2
|
+
import { V as consumeCodexAppServerLiveThread, a as getLeasedSharedCodexAppServerClient, ct as isJsonObject, l as releaseLeasedSharedCodexAppServerClient, q as retainCodexAppServerLiveThread, z as CodexAppServerRpcError } from "./shared-client-kIBbGjk4.js";
|
|
3
|
+
import { _ as readCodexNotificationTurnId, a as closeCodexStartupClientBestEffort, d as unsubscribeCodexThreadBestEffort, g as readCodexNotificationThreadId, r as CodexAppServerUnsafeSubscriptionError, s as isCodexAlreadyTerminalInterruptError } from "./attempt-client-cleanup-DMLXUfa8.js";
|
|
4
|
+
import { i as readCodexThreadContextSnapshot, x as readCodexNotificationItem } from "./event-projector-usage-e5huIQWu.js";
|
|
5
|
+
import { t as isIncognitoSessionKey } from "./incognito-session-ET_ufDH-.js";
|
|
6
|
+
import { t as resumeCodexAppServerThread } from "./thread-resume-CPrJNQVM.js";
|
|
7
|
+
import { n as resolveCodexNativeExecutionBlock } from "./sandbox-guard-Cmwc9eIk.js";
|
|
8
|
+
import { t as isSameCodexAppServerThreadOwner } from "./thread-ownership-6kOQHlyC.js";
|
|
9
|
+
import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-I5Bo-AsX.js";
|
|
10
|
+
import { asOptionalRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
11
|
+
import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
|
|
6
12
|
import { embeddedAgentLog, resolveCompactionTimeoutMs } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
7
13
|
import { resolveAgentDir as resolveAgentDir$1, resolveDefaultAgentId } from "openclaw/plugin-sdk/agent-runtime";
|
|
14
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
15
|
+
import { coerceErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
16
|
+
import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
|
|
17
|
+
import { createDedupeCache } from "openclaw/plugin-sdk/dedupe-runtime";
|
|
8
18
|
//#region extensions/codex/src/app-server/compact.ts
|
|
9
19
|
/**
|
|
10
20
|
* Native Codex app-server compaction bridge for bound OpenClaw sessions.
|
|
11
21
|
*/
|
|
12
|
-
const warnedIgnoredCompactionOverrides =
|
|
13
|
-
|
|
22
|
+
const warnedIgnoredCompactionOverrides = createDedupeCache({
|
|
23
|
+
ttlMs: 0,
|
|
24
|
+
maxSize: 4096
|
|
25
|
+
});
|
|
26
|
+
const codexNativeCompactionQueue = new KeyedAsyncQueue();
|
|
14
27
|
const CODEX_NATIVE_COMPACTION_INTERRUPT_GRACE_MS = 3e4;
|
|
15
|
-
const CODEX_NO_ACTIVE_TURN_ERROR_CODE = -32600;
|
|
16
|
-
const CODEX_NO_ACTIVE_TURN_ERROR_MESSAGE = "no active turn to interrupt";
|
|
17
|
-
function isAlreadyTerminalInterruptError(error) {
|
|
18
|
-
return error instanceof CodexAppServerRpcError && error.code === CODEX_NO_ACTIVE_TURN_ERROR_CODE && error.message === CODEX_NO_ACTIVE_TURN_ERROR_MESSAGE;
|
|
19
|
-
}
|
|
20
28
|
function watchCodexNativeCompactionCompletion(params) {
|
|
29
|
+
const runOutsideBindingLease = AsyncLocalStorage.snapshot();
|
|
21
30
|
let settled = false;
|
|
22
31
|
let requestStarted = false;
|
|
23
32
|
let abortRequested = false;
|
|
@@ -26,10 +35,8 @@ function watchCodexNativeCompactionCompletion(params) {
|
|
|
26
35
|
let compactionTurnId;
|
|
27
36
|
let compactionItemId;
|
|
28
37
|
let compactionItemCompleted = false;
|
|
29
|
-
let
|
|
30
|
-
const completion =
|
|
31
|
-
resolveCompletion = resolve;
|
|
32
|
-
});
|
|
38
|
+
let tokensAfter;
|
|
39
|
+
const { promise: completion, resolve: resolveCompletion } = createDeferred();
|
|
33
40
|
let removeNotificationHandler = () => {};
|
|
34
41
|
let removeCloseHandler = () => {};
|
|
35
42
|
let removeAbortHandler = () => {};
|
|
@@ -45,17 +52,22 @@ function watchCodexNativeCompactionCompletion(params) {
|
|
|
45
52
|
clearTimeout(interruptGraceTimeout);
|
|
46
53
|
resolveCompletion(result);
|
|
47
54
|
};
|
|
55
|
+
const complete = () => finish({
|
|
56
|
+
completed: true,
|
|
57
|
+
...tokensAfter !== void 0 ? { tokensAfter } : {}
|
|
58
|
+
});
|
|
59
|
+
const fail = (reason) => finish({
|
|
60
|
+
completed: false,
|
|
61
|
+
reason
|
|
62
|
+
});
|
|
48
63
|
const retireUnconfirmed = (reason) => {
|
|
49
64
|
if (settled || retirementStarted) return;
|
|
50
65
|
retirementStarted = true;
|
|
51
|
-
params.retireUnconfirmed().then(() =>
|
|
52
|
-
completed: false,
|
|
53
|
-
reason
|
|
54
|
-
})).catch((error) => {
|
|
66
|
+
runOutsideBindingLease(() => params.retireUnconfirmed()).then(() => fail(reason)).catch((error) => {
|
|
55
67
|
embeddedAgentLog.error("failed to retire unconfirmed codex app-server compaction", {
|
|
56
68
|
threadId: params.threadId,
|
|
57
69
|
turnId: compactionTurnId,
|
|
58
|
-
reason:
|
|
70
|
+
reason: coerceErrorMessage(error)
|
|
59
71
|
});
|
|
60
72
|
});
|
|
61
73
|
};
|
|
@@ -65,23 +77,19 @@ function watchCodexNativeCompactionCompletion(params) {
|
|
|
65
77
|
params.client.request("turn/interrupt", {
|
|
66
78
|
threadId: params.threadId,
|
|
67
79
|
turnId: compactionTurnId
|
|
68
|
-
}, { timeoutMs: Math.max(1, params.interruptGraceMs) }).
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
finish(compactionItemCompleted ? { completed: true } : {
|
|
76
|
-
completed: false,
|
|
77
|
-
reason: "codex app-server compaction reached terminal state without a completed compaction item"
|
|
78
|
-
});
|
|
80
|
+
}, { timeoutMs: Math.max(1, params.interruptGraceMs) }).catch((error) => {
|
|
81
|
+
if (isCodexAlreadyTerminalInterruptError(error)) {
|
|
82
|
+
if (compactionItemCompleted) {
|
|
83
|
+
complete();
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
fail("codex app-server compaction reached terminal state without a completed compaction item");
|
|
79
87
|
return;
|
|
80
88
|
}
|
|
81
89
|
embeddedAgentLog.warn("codex app-server compaction interrupt request failed", {
|
|
82
90
|
threadId: params.threadId,
|
|
83
91
|
turnId: compactionTurnId,
|
|
84
|
-
reason:
|
|
92
|
+
reason: coerceErrorMessage(error)
|
|
85
93
|
});
|
|
86
94
|
});
|
|
87
95
|
};
|
|
@@ -121,6 +129,10 @@ function watchCodexNativeCompactionCompletion(params) {
|
|
|
121
129
|
return;
|
|
122
130
|
}
|
|
123
131
|
if (compactionTurnId && notificationTurnId !== compactionTurnId) return;
|
|
132
|
+
if (notification.method === "thread/tokenUsage/updated") {
|
|
133
|
+
tokensAfter = readCodexThreadContextSnapshot(notification.params).activeContextTokens ?? tokensAfter;
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
124
136
|
const item = readCodexNotificationItem(notification.params);
|
|
125
137
|
if (item?.type === "contextCompaction") {
|
|
126
138
|
if (notification.method === "item/started") {
|
|
@@ -138,27 +150,15 @@ function watchCodexNativeCompactionCompletion(params) {
|
|
|
138
150
|
const turn = isJsonObject(notification.params.turn) ? notification.params.turn : void 0;
|
|
139
151
|
const status = typeof turn?.status === "string" ? turn.status : void 0;
|
|
140
152
|
if (status !== "completed") {
|
|
141
|
-
|
|
142
|
-
completed: false,
|
|
143
|
-
reason: `codex app-server compaction turn ended with status ${status ?? "unknown"}`
|
|
144
|
-
});
|
|
153
|
+
fail(`codex app-server compaction turn ended with status ${status ?? "unknown"}`);
|
|
145
154
|
return;
|
|
146
155
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
reason: "codex app-server compaction turn completed without a compaction item"
|
|
151
|
-
});
|
|
156
|
+
const incompleteReason = !compactionItemId ? "codex app-server compaction turn completed without a compaction item" : !compactionItemCompleted ? "codex app-server compaction turn completed before its compaction item" : void 0;
|
|
157
|
+
if (incompleteReason) {
|
|
158
|
+
fail(incompleteReason);
|
|
152
159
|
return;
|
|
153
160
|
}
|
|
154
|
-
|
|
155
|
-
finish({
|
|
156
|
-
completed: false,
|
|
157
|
-
reason: "codex app-server compaction turn completed before its compaction item"
|
|
158
|
-
});
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
finish({ completed: true });
|
|
161
|
+
complete();
|
|
162
162
|
});
|
|
163
163
|
removeCloseHandler = params.client.addCloseHandler(() => {
|
|
164
164
|
retireUnconfirmed("codex app-server closed before native compaction completed");
|
|
@@ -179,57 +179,35 @@ function watchCodexNativeCompactionCompletion(params) {
|
|
|
179
179
|
beginCompletionTimeout();
|
|
180
180
|
if (abortRequested) beginInterruptGrace();
|
|
181
181
|
},
|
|
182
|
-
confirmRequestRejected: () =>
|
|
183
|
-
completed: false,
|
|
184
|
-
reason: "codex app-server rejected the compaction request"
|
|
185
|
-
}),
|
|
182
|
+
confirmRequestRejected: () => fail("codex app-server rejected the compaction request"),
|
|
186
183
|
retireUnconfirmedRequest: async (reason) => {
|
|
187
184
|
retireUnconfirmed(reason);
|
|
188
185
|
return await completion;
|
|
189
186
|
},
|
|
190
187
|
cancel: () => {
|
|
191
|
-
if (!requestStarted)
|
|
192
|
-
completed: false,
|
|
193
|
-
reason: "compaction request did not start"
|
|
194
|
-
});
|
|
188
|
+
if (!requestStarted) fail("compaction request did not start");
|
|
195
189
|
}
|
|
196
190
|
};
|
|
197
191
|
}
|
|
198
192
|
async function runExclusiveCodexNativeCompaction(threadId, signal, run) {
|
|
199
|
-
|
|
200
|
-
let
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
});
|
|
204
|
-
const queued = previous.then(() => current, () => current);
|
|
205
|
-
codexNativeCompactionQueues.set(threadId, queued);
|
|
206
|
-
try {
|
|
207
|
-
await waitForCodexNativeCompactionQueue(previous, signal);
|
|
193
|
+
signal?.throwIfAborted();
|
|
194
|
+
let started = false;
|
|
195
|
+
const queued = codexNativeCompactionQueue.enqueue(threadId, async () => {
|
|
196
|
+
started = true;
|
|
208
197
|
signal?.throwIfAborted();
|
|
209
|
-
return
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
queued.then(() => {
|
|
213
|
-
if (codexNativeCompactionQueues.get(threadId) === queued) codexNativeCompactionQueues.delete(threadId);
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
async function waitForCodexNativeCompactionQueue(previous, signal) {
|
|
218
|
-
if (!signal) {
|
|
219
|
-
await previous.catch(() => void 0);
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
signal.throwIfAborted();
|
|
198
|
+
return run();
|
|
199
|
+
});
|
|
200
|
+
if (!signal) return queued;
|
|
223
201
|
let removeAbortListener = () => {};
|
|
224
202
|
const aborted = new Promise((_, reject) => {
|
|
225
203
|
const onAbort = () => {
|
|
226
|
-
reject(signal.reason instanceof Error ? signal.reason : /* @__PURE__ */ new Error("compaction aborted"));
|
|
204
|
+
if (!started) reject(signal.reason instanceof Error ? signal.reason : /* @__PURE__ */ new Error("compaction aborted"));
|
|
227
205
|
};
|
|
228
206
|
removeAbortListener = () => signal.removeEventListener("abort", onAbort);
|
|
229
207
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
230
208
|
});
|
|
231
209
|
try {
|
|
232
|
-
await Promise.race([
|
|
210
|
+
return await Promise.race([queued, aborted]);
|
|
233
211
|
} finally {
|
|
234
212
|
removeAbortListener();
|
|
235
213
|
}
|
|
@@ -246,8 +224,7 @@ function warnIfIgnoringOpenClawCompactionOverrides(params) {
|
|
|
246
224
|
const ignoredConfig = readIgnoredCompactionOverridePaths(params);
|
|
247
225
|
if (ignoredConfig.length === 0) return;
|
|
248
226
|
const warningKey = ignoredConfig.join("\0");
|
|
249
|
-
if (warnedIgnoredCompactionOverrides.
|
|
250
|
-
warnedIgnoredCompactionOverrides.add(warningKey);
|
|
227
|
+
if (warnedIgnoredCompactionOverrides.check(warningKey)) return;
|
|
251
228
|
embeddedAgentLog.warn("ignoring OpenClaw compaction overrides for Codex app-server compaction; Codex uses native server-side compaction", {
|
|
252
229
|
sessionId: params.sessionId,
|
|
253
230
|
sessionKey: params.sessionKey,
|
|
@@ -268,18 +245,16 @@ function readIgnoredCompactionOverridePaths(params) {
|
|
|
268
245
|
}
|
|
269
246
|
function readCompactionOverrideEntries(params) {
|
|
270
247
|
const entries = [];
|
|
271
|
-
const
|
|
272
|
-
const defaultRecord = readRecord(defaultCompaction);
|
|
248
|
+
const defaultRecord = asOptionalRecord(params.config?.agents?.defaults?.compaction);
|
|
273
249
|
if (defaultRecord) entries.push({
|
|
274
250
|
path: "agents.defaults",
|
|
275
251
|
record: defaultRecord
|
|
276
252
|
});
|
|
277
253
|
const agentId = readAgentIdFromSessionKey(params.sessionKey ?? params.sandboxSessionKey);
|
|
278
254
|
if (!agentId) return entries;
|
|
279
|
-
const
|
|
255
|
+
const agentRecord = asOptionalRecord((Array.isArray(params.config?.agents?.list) ? params.config.agents.list : []).find((agent) => {
|
|
280
256
|
return (typeof agent?.id === "string" ? agent.id.trim().toLowerCase() : "") === agentId;
|
|
281
|
-
})
|
|
282
|
-
const agentRecord = readRecord(agentCompaction);
|
|
257
|
+
})?.compaction);
|
|
283
258
|
if (agentRecord) entries.push({
|
|
284
259
|
path: `agents.list.${agentId}`,
|
|
285
260
|
record: agentRecord,
|
|
@@ -293,9 +268,6 @@ function readAgentIdFromSessionKey(sessionKey) {
|
|
|
293
268
|
if (parts.length < 3 || parts[0] !== "agent") return;
|
|
294
269
|
return parts[1]?.trim() || void 0;
|
|
295
270
|
}
|
|
296
|
-
function readRecord(value) {
|
|
297
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
298
|
-
}
|
|
299
271
|
async function compactCodexNativeThread(params, options) {
|
|
300
272
|
if (params.trigger !== "manual" && !options.allowNonManualNativeRequest) {
|
|
301
273
|
embeddedAgentLog.info("skipping codex app-server compaction for non-manual trigger", {
|
|
@@ -303,27 +275,23 @@ async function compactCodexNativeThread(params, options) {
|
|
|
303
275
|
sessionKey: params.sessionKey,
|
|
304
276
|
trigger: params.trigger
|
|
305
277
|
});
|
|
306
|
-
return {
|
|
307
|
-
ok: true,
|
|
278
|
+
return codexNativeCompactionResult(params, {
|
|
308
279
|
compacted: false,
|
|
309
280
|
reason: "codex app-server owns automatic compaction",
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
backend: "codex-app-server",
|
|
316
|
-
skipped: true,
|
|
317
|
-
reason: "non_manual_trigger",
|
|
318
|
-
trigger: params.trigger ?? "unknown"
|
|
319
|
-
}
|
|
281
|
+
details: {
|
|
282
|
+
backend: "codex-app-server",
|
|
283
|
+
skipped: true,
|
|
284
|
+
reason: "non_manual_trigger",
|
|
285
|
+
trigger: params.trigger ?? "unknown"
|
|
320
286
|
}
|
|
321
|
-
};
|
|
287
|
+
});
|
|
322
288
|
}
|
|
289
|
+
const sandbox = params.sandbox;
|
|
323
290
|
const nativeExecutionBlock = resolveCodexNativeExecutionBlock({
|
|
324
291
|
config: params.config,
|
|
325
292
|
sessionKey: params.sandboxSessionKey ?? params.sessionKey,
|
|
326
293
|
sessionId: params.sessionId,
|
|
294
|
+
sandbox,
|
|
327
295
|
surface: "native compaction"
|
|
328
296
|
});
|
|
329
297
|
if (nativeExecutionBlock) return {
|
|
@@ -342,6 +310,16 @@ async function compactCodexNativeThread(params, options) {
|
|
|
342
310
|
reason: "no codex app-server thread binding",
|
|
343
311
|
recovery: "missing_thread_binding"
|
|
344
312
|
});
|
|
313
|
+
if (params.nativeToolSurface === "host-isolated" || initialBinding.nativeToolPolicyRestricted === true || initialBinding.ringZeroConfigFingerprint !== void 0) return codexNativeCompactionResult(params, {
|
|
314
|
+
compacted: false,
|
|
315
|
+
reason: "native compaction is unavailable for a host-isolated Codex session",
|
|
316
|
+
details: {
|
|
317
|
+
backend: "codex-app-server",
|
|
318
|
+
skipped: true,
|
|
319
|
+
reason: "native_tool_policy_restricted",
|
|
320
|
+
expectedThreadId: initialBinding.threadId
|
|
321
|
+
}
|
|
322
|
+
});
|
|
345
323
|
let binding = initialBinding;
|
|
346
324
|
const requestedAuthProfileId = params.authProfileId?.trim() || void 0;
|
|
347
325
|
let connection;
|
|
@@ -359,7 +337,7 @@ async function compactCodexNativeThread(params, options) {
|
|
|
359
337
|
return {
|
|
360
338
|
ok: false,
|
|
361
339
|
compacted: false,
|
|
362
|
-
reason:
|
|
340
|
+
reason: coerceErrorMessage(error)
|
|
363
341
|
};
|
|
364
342
|
}
|
|
365
343
|
const { appServer, usesSupervisionConnection } = connection;
|
|
@@ -389,6 +367,19 @@ async function compactCodexNativeThread(params, options) {
|
|
|
389
367
|
agentDir: params.agentDir,
|
|
390
368
|
config: params.config
|
|
391
369
|
});
|
|
370
|
+
let releaseThreadSubscription;
|
|
371
|
+
let retainedThreadOwnership;
|
|
372
|
+
let compactionSucceeded = false;
|
|
373
|
+
let compactionRequestDefinitelyRejected = false;
|
|
374
|
+
let tokensAfter;
|
|
375
|
+
const releaseCompactionThread = async (threadId) => {
|
|
376
|
+
if (await unsubscribeCodexThreadBestEffort(client, {
|
|
377
|
+
threadId,
|
|
378
|
+
timeoutMs: 5e3
|
|
379
|
+
})) return;
|
|
380
|
+
await closeCodexStartupClientBestEffort(client);
|
|
381
|
+
throw new CodexAppServerUnsafeSubscriptionError(`Codex compaction thread subscription could not be released: ${threadId}`);
|
|
382
|
+
};
|
|
392
383
|
const completionWatch = watchCodexNativeCompactionCompletion({
|
|
393
384
|
client,
|
|
394
385
|
threadId: binding.threadId,
|
|
@@ -396,6 +387,7 @@ async function compactCodexNativeThread(params, options) {
|
|
|
396
387
|
timeoutMs: options.nativeCompletionTimeoutMs ?? resolveCompactionTimeoutMs(params.config),
|
|
397
388
|
interruptGraceMs: options.nativeInterruptGraceMs ?? CODEX_NATIVE_COMPACTION_INTERRUPT_GRACE_MS,
|
|
398
389
|
retireUnconfirmed: async () => {
|
|
390
|
+
releaseThreadSubscription = void 0;
|
|
399
391
|
const transportStopped = await client.closeAndWait({
|
|
400
392
|
exitTimeoutMs: 5e3,
|
|
401
393
|
forceKillDelayMs: 250
|
|
@@ -413,21 +405,28 @@ async function compactCodexNativeThread(params, options) {
|
|
|
413
405
|
throw new Error("failed to detach unconfirmed codex app-server thread binding");
|
|
414
406
|
}
|
|
415
407
|
});
|
|
416
|
-
const
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
408
|
+
const acquireThreadSubscription = async (timeoutMs) => {
|
|
409
|
+
if (!isIncognitoSessionKey(params.sessionKey)) {
|
|
410
|
+
retainedThreadOwnership = await consumeCodexAppServerLiveThread(client, binding.threadId);
|
|
411
|
+
if (!retainedThreadOwnership) await resumeCodexAppServerThread({
|
|
412
|
+
client,
|
|
413
|
+
abandonClient: async () => closeCodexStartupClientBestEffort(client),
|
|
414
|
+
request: {
|
|
415
|
+
threadId: binding.threadId,
|
|
416
|
+
excludeTurns: true
|
|
417
|
+
},
|
|
418
|
+
timeoutMs: timeoutMs ?? appServer.requestTimeoutMs,
|
|
419
|
+
...params.abortSignal ? { signal: params.abortSignal } : {}
|
|
420
|
+
});
|
|
421
|
+
releaseThreadSubscription = async () => releaseCompactionThread(binding.threadId);
|
|
422
|
+
}
|
|
425
423
|
};
|
|
426
424
|
try {
|
|
427
|
-
|
|
428
|
-
const
|
|
429
|
-
|
|
430
|
-
if (params.abortSignal
|
|
425
|
+
const guardedResult = await options.bindingStore.withLease(bindingIdentity, async () => {
|
|
426
|
+
const currentBinding = await options.bindingStore.read(bindingIdentity);
|
|
427
|
+
if (params.abortSignal?.aborted) {
|
|
428
|
+
if (!options.allowNonManualNativeRequest) params.abortSignal.throwIfAborted();
|
|
429
|
+
return {
|
|
431
430
|
started: false,
|
|
432
431
|
result: skippedCodexNativeCompactionResult(params, {
|
|
433
432
|
reason: "codex app-server compaction aborted before native compaction",
|
|
@@ -436,61 +435,65 @@ async function compactCodexNativeThread(params, options) {
|
|
|
436
435
|
currentThreadId: currentBinding?.threadId
|
|
437
436
|
})
|
|
438
437
|
};
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
sessionKey: params.sessionKey,
|
|
443
|
-
expectedThreadId: binding.threadId,
|
|
444
|
-
currentThreadId: currentBinding?.threadId
|
|
445
|
-
});
|
|
446
|
-
return {
|
|
447
|
-
started: false,
|
|
448
|
-
result: skippedCodexNativeCompactionResult(params, {
|
|
449
|
-
reason: "codex app-server binding changed before native compaction",
|
|
450
|
-
code: "binding_changed_before_native_compaction",
|
|
451
|
-
expectedThreadId: binding.threadId,
|
|
452
|
-
currentThreadId: currentBinding?.threadId
|
|
453
|
-
})
|
|
454
|
-
};
|
|
455
|
-
}
|
|
456
|
-
binding = currentBinding;
|
|
457
|
-
await clearContextEngineProjectionBeforeNativeCompaction({
|
|
438
|
+
}
|
|
439
|
+
if (!currentBinding || !isSameNativeCompactionBinding(currentBinding, binding)) {
|
|
440
|
+
embeddedAgentLog.warn("skipping codex app-server compaction because the thread binding changed", {
|
|
458
441
|
sessionId: params.sessionId,
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
442
|
+
sessionKey: params.sessionKey,
|
|
443
|
+
expectedThreadId: binding.threadId,
|
|
444
|
+
currentThreadId: currentBinding?.threadId
|
|
462
445
|
});
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
446
|
+
return {
|
|
447
|
+
started: false,
|
|
448
|
+
result: options.allowNonManualNativeRequest ? skippedCodexNativeCompactionResult(params, {
|
|
449
|
+
reason: "codex app-server binding changed before native compaction",
|
|
450
|
+
code: "binding_changed_before_native_compaction",
|
|
451
|
+
expectedThreadId: binding.threadId,
|
|
452
|
+
currentThreadId: currentBinding?.threadId
|
|
453
|
+
}) : failedCodexThreadBindingCompactionResult(params, {
|
|
454
|
+
threadId: binding.threadId,
|
|
455
|
+
reason: "codex app-server binding changed before native compaction",
|
|
456
|
+
recovery: "stale_thread_binding"
|
|
457
|
+
})
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
binding = currentBinding;
|
|
461
|
+
const guardedRequestTimeoutMs = options.allowNonManualNativeRequest ? Math.min(appServer.requestTimeoutMs, CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS) : void 0;
|
|
462
|
+
await acquireThreadSubscription(guardedRequestTimeoutMs);
|
|
463
|
+
await clearContextEngineProjectionBeforeNativeCompaction({
|
|
464
|
+
sessionId: params.sessionId,
|
|
465
|
+
bindingStore: options.bindingStore,
|
|
466
|
+
identity: bindingIdentity,
|
|
467
|
+
binding
|
|
468
|
+
});
|
|
469
|
+
try {
|
|
470
|
+
completionWatch.beginRequest();
|
|
471
|
+
if (guardedRequestTimeoutMs === void 0) await client.request("thread/compact/start", { threadId: binding.threadId });
|
|
472
|
+
else await client.request("thread/compact/start", { threadId: binding.threadId }, { timeoutMs: guardedRequestTimeoutMs });
|
|
473
|
+
return {
|
|
474
|
+
started: true,
|
|
475
|
+
accepted: true
|
|
476
|
+
};
|
|
477
|
+
} catch (error) {
|
|
478
|
+
if (error instanceof CodexAppServerRpcError) {
|
|
470
479
|
await options.bindingStore.mutate(bindingIdentity, {
|
|
471
480
|
kind: "set",
|
|
472
481
|
binding
|
|
473
482
|
});
|
|
474
|
-
|
|
475
|
-
started: true,
|
|
476
|
-
accepted: false,
|
|
477
|
-
error
|
|
478
|
-
};
|
|
483
|
+
compactionRequestDefinitelyRejected = !isCodexThreadNotFoundError(error);
|
|
479
484
|
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
}
|
|
486
|
-
} else {
|
|
487
|
-
params.abortSignal?.throwIfAborted();
|
|
488
|
-
try {
|
|
489
|
-
await beginNativeCompactionRequest();
|
|
490
|
-
} catch (error) {
|
|
491
|
-
await settleNativeCompactionRequestError(error);
|
|
492
|
-
throw error;
|
|
485
|
+
return {
|
|
486
|
+
started: true,
|
|
487
|
+
accepted: false,
|
|
488
|
+
error
|
|
489
|
+
};
|
|
493
490
|
}
|
|
491
|
+
});
|
|
492
|
+
if (!guardedResult.started) return guardedResult.result;
|
|
493
|
+
if (!guardedResult.accepted) {
|
|
494
|
+
if (guardedResult.error instanceof CodexAppServerRpcError) completionWatch.confirmRequestRejected();
|
|
495
|
+
else await completionWatch.retireUnconfirmedRequest(`codex app-server compaction start was unconfirmed: ${coerceErrorMessage(guardedResult.error)}`);
|
|
496
|
+
throw guardedResult.error;
|
|
494
497
|
}
|
|
495
498
|
embeddedAgentLog.info("started codex app-server compaction", {
|
|
496
499
|
sessionId: params.sessionId,
|
|
@@ -498,32 +501,44 @@ async function compactCodexNativeThread(params, options) {
|
|
|
498
501
|
});
|
|
499
502
|
const completion = await completionWatch.completion;
|
|
500
503
|
if (!completion.completed) throw new Error(completion.reason);
|
|
504
|
+
tokensAfter = completion.tokensAfter;
|
|
501
505
|
embeddedAgentLog.info("completed codex app-server compaction", {
|
|
502
506
|
sessionId: params.sessionId,
|
|
503
507
|
threadId: binding.threadId
|
|
504
508
|
});
|
|
509
|
+
compactionSucceeded = true;
|
|
505
510
|
} catch (error) {
|
|
506
511
|
if (isCodexThreadNotFoundError(error)) return failedCodexThreadBindingCompactionResult(params, {
|
|
507
512
|
threadId: binding.threadId,
|
|
508
|
-
reason:
|
|
513
|
+
reason: coerceErrorMessage(error),
|
|
509
514
|
recovery: "stale_thread_binding"
|
|
510
515
|
});
|
|
511
516
|
embeddedAgentLog.warn("codex app-server compaction failed", {
|
|
512
517
|
sessionId: params.sessionId,
|
|
513
518
|
sessionKey: params.sessionKey,
|
|
514
519
|
threadId: binding.threadId,
|
|
515
|
-
reason:
|
|
520
|
+
reason: coerceErrorMessage(error)
|
|
516
521
|
});
|
|
517
522
|
return {
|
|
518
523
|
ok: false,
|
|
519
524
|
compacted: false,
|
|
520
|
-
reason:
|
|
525
|
+
reason: coerceErrorMessage(error)
|
|
521
526
|
};
|
|
522
527
|
} finally {
|
|
523
528
|
completionWatch.cancel();
|
|
524
|
-
|
|
529
|
+
try {
|
|
530
|
+
if ((compactionSucceeded || compactionRequestDefinitelyRejected) && retainedThreadOwnership) {
|
|
531
|
+
const ownership = retainedThreadOwnership;
|
|
532
|
+
if (!(isSameCodexAppServerThreadOwner(await options.bindingStore.read(bindingIdentity), binding) && await options.bindingStore.withLease(bindingIdentity, async () => {
|
|
533
|
+
if (!isSameCodexAppServerThreadOwner(await options.bindingStore.read(bindingIdentity), binding)) return false;
|
|
534
|
+
return await retainCodexAppServerLiveThread(client, binding.threadId, ownership.release, ownership.configFingerprint, ownership.serviceTier);
|
|
535
|
+
}))) await releaseThreadSubscription?.();
|
|
536
|
+
} else await releaseThreadSubscription?.();
|
|
537
|
+
} finally {
|
|
538
|
+
if (shouldReleaseDefaultLease) releaseLeasedSharedCodexAppServerClient(client);
|
|
539
|
+
}
|
|
525
540
|
}
|
|
526
|
-
const
|
|
541
|
+
const details = {
|
|
527
542
|
backend: "codex-app-server",
|
|
528
543
|
threadId: binding.threadId,
|
|
529
544
|
signal: "thread/compact/start",
|
|
@@ -534,16 +549,11 @@ async function compactCodexNativeThread(params, options) {
|
|
|
534
549
|
trigger: params.trigger ?? "unknown"
|
|
535
550
|
} : {}
|
|
536
551
|
};
|
|
537
|
-
return {
|
|
538
|
-
ok: true,
|
|
552
|
+
return codexNativeCompactionResult(params, {
|
|
539
553
|
compacted: true,
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
tokensBefore: params.currentTokenCount ?? 0,
|
|
544
|
-
details: resultDetails
|
|
545
|
-
}
|
|
546
|
-
};
|
|
554
|
+
tokensAfter,
|
|
555
|
+
details
|
|
556
|
+
});
|
|
547
557
|
});
|
|
548
558
|
} catch (error) {
|
|
549
559
|
if (params.abortSignal?.aborted) {
|
|
@@ -562,27 +572,35 @@ async function compactCodexNativeThread(params, options) {
|
|
|
562
572
|
throw error;
|
|
563
573
|
}
|
|
564
574
|
}
|
|
565
|
-
function
|
|
575
|
+
function codexNativeCompactionResult(params, outcome) {
|
|
566
576
|
return {
|
|
567
577
|
ok: true,
|
|
568
|
-
compacted:
|
|
569
|
-
reason:
|
|
578
|
+
compacted: outcome.compacted,
|
|
579
|
+
...outcome.reason ? { reason: outcome.reason } : {},
|
|
570
580
|
result: {
|
|
571
581
|
summary: "",
|
|
572
582
|
firstKeptEntryId: "",
|
|
573
583
|
tokensBefore: params.currentTokenCount ?? 0,
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
skipped: true,
|
|
577
|
-
reason: skipped.code,
|
|
578
|
-
request: "after_context_engine",
|
|
579
|
-
trigger: params.trigger ?? "unknown",
|
|
580
|
-
...skipped.expectedThreadId ? { expectedThreadId: skipped.expectedThreadId } : {},
|
|
581
|
-
...skipped.currentThreadId ? { currentThreadId: skipped.currentThreadId } : {}
|
|
582
|
-
}
|
|
584
|
+
...outcome.tokensAfter !== void 0 ? { tokensAfter: outcome.tokensAfter } : {},
|
|
585
|
+
details: outcome.details
|
|
583
586
|
}
|
|
584
587
|
};
|
|
585
588
|
}
|
|
589
|
+
function skippedCodexNativeCompactionResult(params, skipped) {
|
|
590
|
+
return codexNativeCompactionResult(params, {
|
|
591
|
+
compacted: false,
|
|
592
|
+
reason: skipped.reason,
|
|
593
|
+
details: {
|
|
594
|
+
backend: "codex-app-server",
|
|
595
|
+
skipped: true,
|
|
596
|
+
reason: skipped.code,
|
|
597
|
+
request: "after_context_engine",
|
|
598
|
+
trigger: params.trigger ?? "unknown",
|
|
599
|
+
...skipped.expectedThreadId ? { expectedThreadId: skipped.expectedThreadId } : {},
|
|
600
|
+
...skipped.currentThreadId ? { currentThreadId: skipped.currentThreadId } : {}
|
|
601
|
+
}
|
|
602
|
+
});
|
|
603
|
+
}
|
|
586
604
|
function failedCodexThreadBindingCompactionResult(params, recovery) {
|
|
587
605
|
embeddedAgentLog.warn("codex app-server compaction could not use thread binding", {
|
|
588
606
|
sessionId: params.sessionId,
|
|
@@ -620,14 +638,10 @@ async function clearContextEngineProjectionBeforeNativeCompaction(params) {
|
|
|
620
638
|
});
|
|
621
639
|
}
|
|
622
640
|
function isSameNativeCompactionBinding(current, expected) {
|
|
623
|
-
return current
|
|
641
|
+
return isSameCodexAppServerThreadOwner(current, expected) && current.authProfileId === expected.authProfileId && current.contextEngine?.engineId === expected.contextEngine?.engineId && current.contextEngine?.policyFingerprint === expected.contextEngine?.policyFingerprint && current.contextEngine?.projection?.mode === expected.contextEngine?.projection?.mode && current.contextEngine?.projection?.epoch === expected.contextEngine?.projection?.epoch && current.contextEngine?.projection?.fingerprint === expected.contextEngine?.projection?.fingerprint;
|
|
624
642
|
}
|
|
625
643
|
function isCodexThreadNotFoundError(error) {
|
|
626
|
-
return
|
|
627
|
-
}
|
|
628
|
-
function formatCompactionError(error) {
|
|
629
|
-
if (error instanceof Error) return error.message;
|
|
630
|
-
return String(error);
|
|
644
|
+
return coerceErrorMessage(error).toLowerCase().includes("thread not found");
|
|
631
645
|
}
|
|
632
646
|
//#endregion
|
|
633
647
|
export { maybeCompactCodexAppServerSession };
|