@openclaw/codex 2026.6.11-beta.2 → 2026.7.1-1
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/dist/{app-server-policy-BPTiVNsW.js → app-server-policy-C968Kgin.js} +5 -5
- package/dist/{attempt-notifications-BYnndyFl.js → attempt-notifications-BGsEIIDI.js} +29 -40
- package/dist/{command-handlers-DEPTJYk0.js → command-handlers-Dv-pzAmg.js} +278 -237
- package/dist/command-rpc-eLM_mtC7.js +784 -0
- package/dist/compact-4mVBriKT.js +603 -0
- package/dist/{computer-use-ClrJwoFp.js → computer-use-Bmaz333N.js} +3 -3
- package/dist/{config-CszD0vP3.js → config-CYEDnLJ2.js} +44 -18
- package/dist/conversation-binding-data-BHRpYbX3.js +121 -0
- package/dist/doctor-contract-api.js +590 -22
- package/dist/harness.js +29 -10
- package/dist/index.js +1134 -35
- package/dist/{media-understanding-provider-ZUQHN7gT.js → media-understanding-provider-BHOu9-Gg.js} +13 -8
- package/dist/media-understanding-provider.js +1 -1
- package/dist/{models-CAmfBWRl.js → models-DDmO1zwd.js} +2 -2
- package/dist/notification-correlation-Bo7KB3ks.js +35 -0
- package/dist/{plugin-app-cache-key-C9ILt7bl.js → plugin-app-cache-key-BrhVdeEf.js} +13 -5
- package/dist/{protocol-dh-ETiNd.js → protocol-2POPqAY4.js} +2 -1
- package/dist/{protocol-validators-B19q5BIX.js → protocol-validators-dZQ-UTOa.js} +205 -56
- package/dist/provider-capabilities-DzI8fgEu.js +6172 -0
- package/dist/provider-catalog.js +4 -2
- package/dist/{provider-B-OHpbD3.js → provider-zjPfx5Fs.js} +94 -23
- package/dist/provider.js +2 -2
- package/dist/{request-Dcd452Nk.js → request-BcJyl8KL.js} +2 -2
- package/dist/{run-attempt-CXxtFC9d.js → run-attempt-DNSNk_G8.js} +1250 -2992
- package/dist/{sandbox-guard-3tnjhjFb.js → sandbox-guard-DA2TQfZW.js} +5 -3
- package/dist/session-binding-C1ZXdP-x.js +627 -0
- package/dist/session-binding-meta-B7aEMU7g.js +6 -0
- package/dist/shared-client-4ICy3U6d.js +1853 -0
- package/dist/{side-question-C-DhgJOd.js → side-question-CMOpEhvY.js} +134 -142
- package/dist/{thread-lifecycle-DtT3-ehU.js → thread-lifecycle-qWE88Dn2.js} +803 -481
- package/dist/{web-search-provider.runtime-CkwxrXQj.js → web-search-provider.runtime-BSlriav6.js} +3 -3
- package/npm-shrinkwrap.json +34 -34
- package/openclaw.plugin.json +23 -3
- package/package.json +9 -6
- package/dist/client-CLrtWgrD.js +0 -729
- package/dist/client-factory-Bm6HsGob.js +0 -18
- package/dist/compact-aQJ0ZKhe.js +0 -278
- package/dist/conversation-binding-t0XMLz-j.js +0 -1557
- package/dist/provider-capabilities-D7hnTO76.js +0 -3201
- package/dist/rate-limit-cache-C7qmZ0Jh.js +0 -26
- package/dist/session-binding-HOuPt-E0.js +0 -338
- package/dist/shared-client-Dtx5i7Ez.js +0 -1013
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
import { r as isJsonObject } from "./protocol-2POPqAY4.js";
|
|
2
|
+
import { _ as readCodexNotificationItem } from "./attempt-notifications-BGsEIIDI.js";
|
|
3
|
+
import { d as resolveCodexAppServerRuntimeOptions } from "./config-CYEDnLJ2.js";
|
|
4
|
+
import { a as getLeasedSharedCodexAppServerClient, o as releaseLeasedSharedCodexAppServerClient, u as CodexAppServerRpcError } from "./shared-client-4ICy3U6d.js";
|
|
5
|
+
import { s as sessionBindingIdentity, t as CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS } from "./session-binding-C1ZXdP-x.js";
|
|
6
|
+
import { n as resolveCodexNativeExecutionBlock } from "./sandbox-guard-DA2TQfZW.js";
|
|
7
|
+
import { n as readCodexNotificationThreadId, r as readCodexNotificationTurnId } from "./notification-correlation-Bo7KB3ks.js";
|
|
8
|
+
import { embeddedAgentLog, resolveCompactionTimeoutMs } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
9
|
+
//#region extensions/codex/src/app-server/compact.ts
|
|
10
|
+
/**
|
|
11
|
+
* Native Codex app-server compaction bridge for bound OpenClaw sessions.
|
|
12
|
+
*/
|
|
13
|
+
const warnedIgnoredCompactionOverrides = /* @__PURE__ */ new Set();
|
|
14
|
+
const codexNativeCompactionQueues = /* @__PURE__ */ new Map();
|
|
15
|
+
const CODEX_NATIVE_COMPACTION_INTERRUPT_GRACE_MS = 3e4;
|
|
16
|
+
const CODEX_NO_ACTIVE_TURN_ERROR_CODE = -32600;
|
|
17
|
+
const CODEX_NO_ACTIVE_TURN_ERROR_MESSAGE = "no active turn to interrupt";
|
|
18
|
+
function isAlreadyTerminalInterruptError(error) {
|
|
19
|
+
return error instanceof CodexAppServerRpcError && error.code === CODEX_NO_ACTIVE_TURN_ERROR_CODE && error.message === CODEX_NO_ACTIVE_TURN_ERROR_MESSAGE;
|
|
20
|
+
}
|
|
21
|
+
function watchCodexNativeCompactionCompletion(params) {
|
|
22
|
+
let settled = false;
|
|
23
|
+
let requestStarted = false;
|
|
24
|
+
let abortRequested = false;
|
|
25
|
+
let interruptRequested = false;
|
|
26
|
+
let retirementStarted = false;
|
|
27
|
+
let compactionTurnId;
|
|
28
|
+
let compactionItemId;
|
|
29
|
+
let compactionItemCompleted = false;
|
|
30
|
+
let resolveCompletion = (_result) => {};
|
|
31
|
+
const completion = new Promise((resolve) => {
|
|
32
|
+
resolveCompletion = resolve;
|
|
33
|
+
});
|
|
34
|
+
let removeNotificationHandler = () => {};
|
|
35
|
+
let removeCloseHandler = () => {};
|
|
36
|
+
let removeAbortHandler = () => {};
|
|
37
|
+
let completionTimeout;
|
|
38
|
+
let interruptGraceTimeout;
|
|
39
|
+
const finish = (result) => {
|
|
40
|
+
if (settled) return;
|
|
41
|
+
settled = true;
|
|
42
|
+
removeNotificationHandler();
|
|
43
|
+
removeCloseHandler();
|
|
44
|
+
removeAbortHandler();
|
|
45
|
+
clearTimeout(completionTimeout);
|
|
46
|
+
clearTimeout(interruptGraceTimeout);
|
|
47
|
+
resolveCompletion(result);
|
|
48
|
+
};
|
|
49
|
+
const retireUnconfirmed = (reason) => {
|
|
50
|
+
if (settled || retirementStarted) return;
|
|
51
|
+
retirementStarted = true;
|
|
52
|
+
params.retireUnconfirmed().then(() => finish({
|
|
53
|
+
completed: false,
|
|
54
|
+
reason
|
|
55
|
+
})).catch((error) => {
|
|
56
|
+
embeddedAgentLog.error("failed to retire unconfirmed codex app-server compaction", {
|
|
57
|
+
threadId: params.threadId,
|
|
58
|
+
turnId: compactionTurnId,
|
|
59
|
+
reason: formatCompactionError(error)
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
const requestInterrupt = () => {
|
|
64
|
+
if (settled || !requestStarted || !abortRequested || !compactionTurnId || interruptRequested) return;
|
|
65
|
+
interruptRequested = true;
|
|
66
|
+
params.client.request("turn/interrupt", {
|
|
67
|
+
threadId: params.threadId,
|
|
68
|
+
turnId: compactionTurnId
|
|
69
|
+
}, { timeoutMs: Math.max(1, params.interruptGraceMs) }).then(() => {
|
|
70
|
+
finish({
|
|
71
|
+
completed: false,
|
|
72
|
+
reason: "codex app-server confirmed native compaction interruption"
|
|
73
|
+
});
|
|
74
|
+
}).catch((error) => {
|
|
75
|
+
if (isAlreadyTerminalInterruptError(error)) {
|
|
76
|
+
finish(compactionItemCompleted ? { completed: true } : {
|
|
77
|
+
completed: false,
|
|
78
|
+
reason: "codex app-server compaction reached terminal state without a completed compaction item"
|
|
79
|
+
});
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
embeddedAgentLog.warn("codex app-server compaction interrupt request failed", {
|
|
83
|
+
threadId: params.threadId,
|
|
84
|
+
turnId: compactionTurnId,
|
|
85
|
+
reason: formatCompactionError(error)
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
const beginInterruptGrace = () => {
|
|
90
|
+
if (settled || !requestStarted || interruptGraceTimeout) return;
|
|
91
|
+
requestInterrupt();
|
|
92
|
+
interruptGraceTimeout = setTimeout(() => {
|
|
93
|
+
embeddedAgentLog.warn("codex app-server compaction did not reach terminal state after interruption", {
|
|
94
|
+
threadId: params.threadId,
|
|
95
|
+
turnId: compactionTurnId,
|
|
96
|
+
interruptGraceMs: params.interruptGraceMs
|
|
97
|
+
});
|
|
98
|
+
retireUnconfirmed("codex app-server compaction did not reach terminal state after interruption");
|
|
99
|
+
}, Math.max(1, params.interruptGraceMs));
|
|
100
|
+
interruptGraceTimeout.unref?.();
|
|
101
|
+
};
|
|
102
|
+
const beginCompletionTimeout = () => {
|
|
103
|
+
completionTimeout = setTimeout(() => {
|
|
104
|
+
abortRequested = true;
|
|
105
|
+
beginInterruptGrace();
|
|
106
|
+
embeddedAgentLog.warn("codex app-server compaction exceeded its completion budget", {
|
|
107
|
+
threadId: params.threadId,
|
|
108
|
+
timeoutMs: params.timeoutMs,
|
|
109
|
+
interruptRequested
|
|
110
|
+
});
|
|
111
|
+
}, Math.max(1, params.timeoutMs));
|
|
112
|
+
completionTimeout.unref?.();
|
|
113
|
+
};
|
|
114
|
+
removeNotificationHandler = params.client.addNotificationHandler((notification) => {
|
|
115
|
+
if (!requestStarted) return;
|
|
116
|
+
if (!isJsonObject(notification.params)) return;
|
|
117
|
+
if (readCodexNotificationThreadId(notification.params) !== params.threadId) return;
|
|
118
|
+
const notificationTurnId = readCodexNotificationTurnId(notification.params);
|
|
119
|
+
if (notification.method === "turn/started") {
|
|
120
|
+
compactionTurnId = notificationTurnId;
|
|
121
|
+
requestInterrupt();
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (compactionTurnId && notificationTurnId !== compactionTurnId) return;
|
|
125
|
+
const item = readCodexNotificationItem(notification.params);
|
|
126
|
+
if (item?.type === "contextCompaction") {
|
|
127
|
+
if (notification.method === "item/started") {
|
|
128
|
+
compactionTurnId = compactionTurnId ?? notificationTurnId;
|
|
129
|
+
compactionItemId = item.id;
|
|
130
|
+
requestInterrupt();
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (notification.method === "item/completed" && compactionItemId === item.id) {
|
|
134
|
+
compactionItemCompleted = true;
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (notification.method !== "turn/completed" || !compactionTurnId || notificationTurnId !== compactionTurnId) return;
|
|
139
|
+
const turn = isJsonObject(notification.params.turn) ? notification.params.turn : void 0;
|
|
140
|
+
const status = typeof turn?.status === "string" ? turn.status : void 0;
|
|
141
|
+
if (status !== "completed") {
|
|
142
|
+
finish({
|
|
143
|
+
completed: false,
|
|
144
|
+
reason: `codex app-server compaction turn ended with status ${status ?? "unknown"}`
|
|
145
|
+
});
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (!compactionItemId) {
|
|
149
|
+
finish({
|
|
150
|
+
completed: false,
|
|
151
|
+
reason: "codex app-server compaction turn completed without a compaction item"
|
|
152
|
+
});
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (!compactionItemCompleted) {
|
|
156
|
+
finish({
|
|
157
|
+
completed: false,
|
|
158
|
+
reason: "codex app-server compaction turn completed before its compaction item"
|
|
159
|
+
});
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
finish({ completed: true });
|
|
163
|
+
});
|
|
164
|
+
removeCloseHandler = params.client.addCloseHandler(() => {
|
|
165
|
+
retireUnconfirmed("codex app-server closed before native compaction completed");
|
|
166
|
+
});
|
|
167
|
+
if (params.signal) {
|
|
168
|
+
const onAbort = () => {
|
|
169
|
+
abortRequested = true;
|
|
170
|
+
beginInterruptGrace();
|
|
171
|
+
};
|
|
172
|
+
params.signal.addEventListener("abort", onAbort, { once: true });
|
|
173
|
+
removeAbortHandler = () => params.signal?.removeEventListener("abort", onAbort);
|
|
174
|
+
if (params.signal.aborted) onAbort();
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
completion,
|
|
178
|
+
beginRequest: () => {
|
|
179
|
+
requestStarted = true;
|
|
180
|
+
beginCompletionTimeout();
|
|
181
|
+
if (abortRequested) beginInterruptGrace();
|
|
182
|
+
},
|
|
183
|
+
confirmRequestRejected: () => finish({
|
|
184
|
+
completed: false,
|
|
185
|
+
reason: "codex app-server rejected the compaction request"
|
|
186
|
+
}),
|
|
187
|
+
retireUnconfirmedRequest: async (reason) => {
|
|
188
|
+
retireUnconfirmed(reason);
|
|
189
|
+
return await completion;
|
|
190
|
+
},
|
|
191
|
+
cancel: () => {
|
|
192
|
+
if (!requestStarted) finish({
|
|
193
|
+
completed: false,
|
|
194
|
+
reason: "compaction request did not start"
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
async function runExclusiveCodexNativeCompaction(threadId, signal, run) {
|
|
200
|
+
const previous = codexNativeCompactionQueues.get(threadId) ?? Promise.resolve();
|
|
201
|
+
let releaseCurrent;
|
|
202
|
+
const current = new Promise((resolve) => {
|
|
203
|
+
releaseCurrent = resolve;
|
|
204
|
+
});
|
|
205
|
+
const queued = previous.then(() => current, () => current);
|
|
206
|
+
codexNativeCompactionQueues.set(threadId, queued);
|
|
207
|
+
try {
|
|
208
|
+
await waitForCodexNativeCompactionQueue(previous, signal);
|
|
209
|
+
signal?.throwIfAborted();
|
|
210
|
+
return await run();
|
|
211
|
+
} finally {
|
|
212
|
+
releaseCurrent();
|
|
213
|
+
queued.then(() => {
|
|
214
|
+
if (codexNativeCompactionQueues.get(threadId) === queued) codexNativeCompactionQueues.delete(threadId);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
async function waitForCodexNativeCompactionQueue(previous, signal) {
|
|
219
|
+
if (!signal) {
|
|
220
|
+
await previous.catch(() => void 0);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
signal.throwIfAborted();
|
|
224
|
+
let removeAbortListener = () => {};
|
|
225
|
+
const aborted = new Promise((_, reject) => {
|
|
226
|
+
const onAbort = () => {
|
|
227
|
+
reject(signal.reason instanceof Error ? signal.reason : /* @__PURE__ */ new Error("compaction aborted"));
|
|
228
|
+
};
|
|
229
|
+
removeAbortListener = () => signal.removeEventListener("abort", onAbort);
|
|
230
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
231
|
+
});
|
|
232
|
+
try {
|
|
233
|
+
await Promise.race([previous.catch(() => void 0), aborted]);
|
|
234
|
+
} finally {
|
|
235
|
+
removeAbortListener();
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Starts native Codex compaction for a manually requested bound session, or
|
|
240
|
+
* reports why Codex-owned automatic compaction should handle the trigger.
|
|
241
|
+
*/
|
|
242
|
+
async function maybeCompactCodexAppServerSession(params, options) {
|
|
243
|
+
warnIfIgnoringOpenClawCompactionOverrides(params);
|
|
244
|
+
return compactCodexNativeThread(params, options);
|
|
245
|
+
}
|
|
246
|
+
function warnIfIgnoringOpenClawCompactionOverrides(params) {
|
|
247
|
+
const ignoredConfig = readIgnoredCompactionOverridePaths(params);
|
|
248
|
+
if (ignoredConfig.length === 0) return;
|
|
249
|
+
const warningKey = ignoredConfig.join("\0");
|
|
250
|
+
if (warnedIgnoredCompactionOverrides.has(warningKey)) return;
|
|
251
|
+
warnedIgnoredCompactionOverrides.add(warningKey);
|
|
252
|
+
embeddedAgentLog.warn("ignoring OpenClaw compaction overrides for Codex app-server compaction; Codex uses native server-side compaction", {
|
|
253
|
+
sessionId: params.sessionId,
|
|
254
|
+
sessionKey: params.sessionKey,
|
|
255
|
+
ignoredConfig
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
function readIgnoredCompactionOverridePaths(params) {
|
|
259
|
+
const ignored = /* @__PURE__ */ new Set();
|
|
260
|
+
for (const entry of readCompactionOverrideEntries(params)) {
|
|
261
|
+
const localProvider = typeof entry.record.provider === "string" ? entry.record.provider.trim() : "";
|
|
262
|
+
const inheritedProvider = !localProvider && typeof entry.inheritedRecord?.provider === "string" ? entry.inheritedRecord.provider.trim() : "";
|
|
263
|
+
const providerPath = localProvider ? `${entry.path}.compaction.provider` : inheritedProvider && entry.inheritedPath ? `${entry.inheritedPath}.compaction.provider` : void 0;
|
|
264
|
+
if (typeof entry.record.model === "string" && entry.record.model.trim()) ignored.add(`${entry.path}.compaction.model`);
|
|
265
|
+
if (providerPath) ignored.add(providerPath);
|
|
266
|
+
}
|
|
267
|
+
return [...ignored];
|
|
268
|
+
}
|
|
269
|
+
function readCompactionOverrideEntries(params) {
|
|
270
|
+
const entries = [];
|
|
271
|
+
const defaultCompaction = readRecord(readRecord(params.config?.agents)?.defaults)?.compaction;
|
|
272
|
+
const defaultRecord = readRecord(defaultCompaction);
|
|
273
|
+
if (defaultRecord) entries.push({
|
|
274
|
+
path: "agents.defaults",
|
|
275
|
+
record: defaultRecord
|
|
276
|
+
});
|
|
277
|
+
const agentId = readAgentIdFromSessionKey(params.sessionKey ?? params.sandboxSessionKey);
|
|
278
|
+
if (!agentId) return entries;
|
|
279
|
+
const agentCompaction = readRecord((Array.isArray(params.config?.agents?.list) ? params.config.agents.list : []).find((agent) => {
|
|
280
|
+
return (typeof agent?.id === "string" ? agent.id.trim().toLowerCase() : "") === agentId;
|
|
281
|
+
}))?.compaction;
|
|
282
|
+
const agentRecord = readRecord(agentCompaction);
|
|
283
|
+
if (agentRecord) entries.push({
|
|
284
|
+
path: `agents.list.${agentId}`,
|
|
285
|
+
record: agentRecord,
|
|
286
|
+
inheritedRecord: defaultRecord,
|
|
287
|
+
inheritedPath: "agents.defaults"
|
|
288
|
+
});
|
|
289
|
+
return entries;
|
|
290
|
+
}
|
|
291
|
+
function readAgentIdFromSessionKey(sessionKey) {
|
|
292
|
+
const parts = sessionKey?.trim().toLowerCase().split(":").filter(Boolean) ?? [];
|
|
293
|
+
if (parts.length < 3 || parts[0] !== "agent") return;
|
|
294
|
+
return parts[1]?.trim() || void 0;
|
|
295
|
+
}
|
|
296
|
+
function readRecord(value) {
|
|
297
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
298
|
+
}
|
|
299
|
+
async function compactCodexNativeThread(params, options) {
|
|
300
|
+
if (params.trigger !== "manual" && !options.allowNonManualNativeRequest) {
|
|
301
|
+
embeddedAgentLog.info("skipping codex app-server compaction for non-manual trigger", {
|
|
302
|
+
sessionId: params.sessionId,
|
|
303
|
+
sessionKey: params.sessionKey,
|
|
304
|
+
trigger: params.trigger
|
|
305
|
+
});
|
|
306
|
+
return {
|
|
307
|
+
ok: true,
|
|
308
|
+
compacted: false,
|
|
309
|
+
reason: "codex app-server owns automatic compaction",
|
|
310
|
+
result: {
|
|
311
|
+
summary: "",
|
|
312
|
+
firstKeptEntryId: "",
|
|
313
|
+
tokensBefore: params.currentTokenCount ?? 0,
|
|
314
|
+
details: {
|
|
315
|
+
backend: "codex-app-server",
|
|
316
|
+
skipped: true,
|
|
317
|
+
reason: "non_manual_trigger",
|
|
318
|
+
trigger: params.trigger ?? "unknown"
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
const nativeExecutionBlock = resolveCodexNativeExecutionBlock({
|
|
324
|
+
config: params.config,
|
|
325
|
+
sessionKey: params.sandboxSessionKey ?? params.sessionKey,
|
|
326
|
+
sessionId: params.sessionId,
|
|
327
|
+
surface: "native compaction"
|
|
328
|
+
});
|
|
329
|
+
if (nativeExecutionBlock) return {
|
|
330
|
+
ok: false,
|
|
331
|
+
compacted: false,
|
|
332
|
+
reason: nativeExecutionBlock
|
|
333
|
+
};
|
|
334
|
+
const appServer = resolveCodexAppServerRuntimeOptions({ pluginConfig: options.pluginConfig });
|
|
335
|
+
const bindingIdentity = sessionBindingIdentity({
|
|
336
|
+
sessionId: params.sessionId,
|
|
337
|
+
sessionKey: params.sessionKey,
|
|
338
|
+
agentId: params.agentId,
|
|
339
|
+
config: params.config
|
|
340
|
+
});
|
|
341
|
+
const initialBinding = await options.bindingStore.read(bindingIdentity);
|
|
342
|
+
if (!initialBinding?.threadId) return failedCodexThreadBindingCompactionResult(params, {
|
|
343
|
+
reason: "no codex app-server thread binding",
|
|
344
|
+
recovery: "missing_thread_binding"
|
|
345
|
+
});
|
|
346
|
+
let binding = initialBinding;
|
|
347
|
+
const requestedAuthProfileId = params.authProfileId?.trim() || void 0;
|
|
348
|
+
if (requestedAuthProfileId && binding.authProfileId && binding.authProfileId !== requestedAuthProfileId) return {
|
|
349
|
+
ok: false,
|
|
350
|
+
compacted: false,
|
|
351
|
+
reason: "auth profile mismatch for session binding"
|
|
352
|
+
};
|
|
353
|
+
const shouldReleaseDefaultLease = !options.clientFactory;
|
|
354
|
+
const clientFactory = options.clientFactory ?? getLeasedSharedCodexAppServerClient;
|
|
355
|
+
try {
|
|
356
|
+
return await runExclusiveCodexNativeCompaction(binding.threadId, params.abortSignal, async () => {
|
|
357
|
+
const client = await clientFactory({
|
|
358
|
+
startOptions: appServer.start,
|
|
359
|
+
authProfileId: requestedAuthProfileId ?? binding.authProfileId,
|
|
360
|
+
agentDir: params.agentDir,
|
|
361
|
+
config: params.config
|
|
362
|
+
});
|
|
363
|
+
const completionWatch = watchCodexNativeCompactionCompletion({
|
|
364
|
+
client,
|
|
365
|
+
threadId: binding.threadId,
|
|
366
|
+
signal: params.abortSignal,
|
|
367
|
+
timeoutMs: options.nativeCompletionTimeoutMs ?? resolveCompactionTimeoutMs(params.config),
|
|
368
|
+
interruptGraceMs: options.nativeInterruptGraceMs ?? CODEX_NATIVE_COMPACTION_INTERRUPT_GRACE_MS,
|
|
369
|
+
retireUnconfirmed: async () => {
|
|
370
|
+
const transportStopped = await client.closeAndWait({
|
|
371
|
+
exitTimeoutMs: 5e3,
|
|
372
|
+
forceKillDelayMs: 250
|
|
373
|
+
});
|
|
374
|
+
if (appServer.start.transport === "stdio") {
|
|
375
|
+
if (transportStopped) return;
|
|
376
|
+
throw new Error("failed to stop unconfirmed codex app-server process");
|
|
377
|
+
}
|
|
378
|
+
if (await options.bindingStore.mutate(bindingIdentity, {
|
|
379
|
+
kind: "clear",
|
|
380
|
+
threadId: binding.threadId
|
|
381
|
+
})) return;
|
|
382
|
+
if ((await options.bindingStore.read(bindingIdentity))?.threadId !== binding.threadId) return;
|
|
383
|
+
throw new Error("failed to detach unconfirmed codex app-server thread binding");
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
const beginNativeCompactionRequest = async (timeoutMs) => {
|
|
387
|
+
completionWatch.beginRequest();
|
|
388
|
+
const requestParams = { threadId: binding.threadId };
|
|
389
|
+
if (timeoutMs === void 0) await client.request("thread/compact/start", requestParams);
|
|
390
|
+
else await client.request("thread/compact/start", requestParams, { timeoutMs });
|
|
391
|
+
};
|
|
392
|
+
const settleNativeCompactionRequestError = async (error) => {
|
|
393
|
+
if (error instanceof CodexAppServerRpcError) completionWatch.confirmRequestRejected();
|
|
394
|
+
else await completionWatch.retireUnconfirmedRequest(`codex app-server compaction start was unconfirmed: ${formatCompactionError(error)}`);
|
|
395
|
+
};
|
|
396
|
+
try {
|
|
397
|
+
if (options.allowNonManualNativeRequest) {
|
|
398
|
+
const guardedResult = await options.bindingStore.withLease(bindingIdentity, async () => {
|
|
399
|
+
const currentBinding = await options.bindingStore.read(bindingIdentity);
|
|
400
|
+
if (params.abortSignal?.aborted) return {
|
|
401
|
+
started: false,
|
|
402
|
+
result: skippedCodexNativeCompactionResult(params, {
|
|
403
|
+
reason: "codex app-server compaction aborted before native compaction",
|
|
404
|
+
code: "aborted_before_native_compaction",
|
|
405
|
+
expectedThreadId: binding.threadId,
|
|
406
|
+
currentThreadId: currentBinding?.threadId
|
|
407
|
+
})
|
|
408
|
+
};
|
|
409
|
+
if (!currentBinding || !isSameNativeCompactionBinding(currentBinding, binding)) {
|
|
410
|
+
embeddedAgentLog.warn("skipping codex app-server compaction because the thread binding changed", {
|
|
411
|
+
sessionId: params.sessionId,
|
|
412
|
+
sessionKey: params.sessionKey,
|
|
413
|
+
expectedThreadId: binding.threadId,
|
|
414
|
+
currentThreadId: currentBinding?.threadId
|
|
415
|
+
});
|
|
416
|
+
return {
|
|
417
|
+
started: false,
|
|
418
|
+
result: skippedCodexNativeCompactionResult(params, {
|
|
419
|
+
reason: "codex app-server binding changed before native compaction",
|
|
420
|
+
code: "binding_changed_before_native_compaction",
|
|
421
|
+
expectedThreadId: binding.threadId,
|
|
422
|
+
currentThreadId: currentBinding?.threadId
|
|
423
|
+
})
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
binding = currentBinding;
|
|
427
|
+
await clearContextEngineProjectionBeforeNativeCompaction({
|
|
428
|
+
sessionId: params.sessionId,
|
|
429
|
+
bindingStore: options.bindingStore,
|
|
430
|
+
identity: bindingIdentity,
|
|
431
|
+
binding
|
|
432
|
+
});
|
|
433
|
+
try {
|
|
434
|
+
await beginNativeCompactionRequest(Math.min(appServer.requestTimeoutMs, CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS));
|
|
435
|
+
return {
|
|
436
|
+
started: true,
|
|
437
|
+
accepted: true
|
|
438
|
+
};
|
|
439
|
+
} catch (error) {
|
|
440
|
+
await options.bindingStore.mutate(bindingIdentity, {
|
|
441
|
+
kind: "set",
|
|
442
|
+
binding
|
|
443
|
+
});
|
|
444
|
+
return {
|
|
445
|
+
started: true,
|
|
446
|
+
accepted: false,
|
|
447
|
+
error
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
if (!guardedResult.started) return guardedResult.result;
|
|
452
|
+
if (!guardedResult.accepted) {
|
|
453
|
+
await settleNativeCompactionRequestError(guardedResult.error);
|
|
454
|
+
throw guardedResult.error;
|
|
455
|
+
}
|
|
456
|
+
} else {
|
|
457
|
+
params.abortSignal?.throwIfAborted();
|
|
458
|
+
try {
|
|
459
|
+
await beginNativeCompactionRequest();
|
|
460
|
+
} catch (error) {
|
|
461
|
+
await settleNativeCompactionRequestError(error);
|
|
462
|
+
throw error;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
embeddedAgentLog.info("started codex app-server compaction", {
|
|
466
|
+
sessionId: params.sessionId,
|
|
467
|
+
threadId: binding.threadId
|
|
468
|
+
});
|
|
469
|
+
const completion = await completionWatch.completion;
|
|
470
|
+
if (!completion.completed) throw new Error(completion.reason);
|
|
471
|
+
embeddedAgentLog.info("completed codex app-server compaction", {
|
|
472
|
+
sessionId: params.sessionId,
|
|
473
|
+
threadId: binding.threadId
|
|
474
|
+
});
|
|
475
|
+
} catch (error) {
|
|
476
|
+
if (isCodexThreadNotFoundError(error)) return failedCodexThreadBindingCompactionResult(params, {
|
|
477
|
+
threadId: binding.threadId,
|
|
478
|
+
reason: formatCompactionError(error),
|
|
479
|
+
recovery: "stale_thread_binding"
|
|
480
|
+
});
|
|
481
|
+
embeddedAgentLog.warn("codex app-server compaction failed", {
|
|
482
|
+
sessionId: params.sessionId,
|
|
483
|
+
sessionKey: params.sessionKey,
|
|
484
|
+
threadId: binding.threadId,
|
|
485
|
+
reason: formatCompactionError(error)
|
|
486
|
+
});
|
|
487
|
+
return {
|
|
488
|
+
ok: false,
|
|
489
|
+
compacted: false,
|
|
490
|
+
reason: formatCompactionError(error)
|
|
491
|
+
};
|
|
492
|
+
} finally {
|
|
493
|
+
completionWatch.cancel();
|
|
494
|
+
if (shouldReleaseDefaultLease) releaseLeasedSharedCodexAppServerClient(client);
|
|
495
|
+
}
|
|
496
|
+
const resultDetails = {
|
|
497
|
+
backend: "codex-app-server",
|
|
498
|
+
threadId: binding.threadId,
|
|
499
|
+
signal: "thread/compact/start",
|
|
500
|
+
pending: false,
|
|
501
|
+
completed: true,
|
|
502
|
+
...options.allowNonManualNativeRequest ? {
|
|
503
|
+
request: "after_context_engine",
|
|
504
|
+
trigger: params.trigger ?? "unknown"
|
|
505
|
+
} : {}
|
|
506
|
+
};
|
|
507
|
+
return {
|
|
508
|
+
ok: true,
|
|
509
|
+
compacted: true,
|
|
510
|
+
result: {
|
|
511
|
+
summary: "",
|
|
512
|
+
firstKeptEntryId: "",
|
|
513
|
+
tokensBefore: params.currentTokenCount ?? 0,
|
|
514
|
+
details: resultDetails
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
});
|
|
518
|
+
} catch (error) {
|
|
519
|
+
if (params.abortSignal?.aborted) {
|
|
520
|
+
if (options.allowNonManualNativeRequest) return skippedCodexNativeCompactionResult(params, {
|
|
521
|
+
reason: "codex app-server compaction aborted before native compaction",
|
|
522
|
+
code: "aborted_before_native_compaction",
|
|
523
|
+
expectedThreadId: initialBinding.threadId,
|
|
524
|
+
currentThreadId: binding.threadId
|
|
525
|
+
});
|
|
526
|
+
return {
|
|
527
|
+
ok: false,
|
|
528
|
+
compacted: false,
|
|
529
|
+
reason: "codex app-server compaction aborted while waiting to start"
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
throw error;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
function skippedCodexNativeCompactionResult(params, skipped) {
|
|
536
|
+
return {
|
|
537
|
+
ok: true,
|
|
538
|
+
compacted: false,
|
|
539
|
+
reason: skipped.reason,
|
|
540
|
+
result: {
|
|
541
|
+
summary: "",
|
|
542
|
+
firstKeptEntryId: "",
|
|
543
|
+
tokensBefore: params.currentTokenCount ?? 0,
|
|
544
|
+
details: {
|
|
545
|
+
backend: "codex-app-server",
|
|
546
|
+
skipped: true,
|
|
547
|
+
reason: skipped.code,
|
|
548
|
+
request: "after_context_engine",
|
|
549
|
+
trigger: params.trigger ?? "unknown",
|
|
550
|
+
...skipped.expectedThreadId ? { expectedThreadId: skipped.expectedThreadId } : {},
|
|
551
|
+
...skipped.currentThreadId ? { currentThreadId: skipped.currentThreadId } : {}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
function failedCodexThreadBindingCompactionResult(params, recovery) {
|
|
557
|
+
embeddedAgentLog.warn("codex app-server compaction could not use thread binding", {
|
|
558
|
+
sessionId: params.sessionId,
|
|
559
|
+
sessionKey: params.sessionKey,
|
|
560
|
+
threadId: recovery.threadId,
|
|
561
|
+
reason: recovery.reason,
|
|
562
|
+
recovery: recovery.recovery
|
|
563
|
+
});
|
|
564
|
+
return {
|
|
565
|
+
ok: false,
|
|
566
|
+
compacted: false,
|
|
567
|
+
reason: recovery.reason,
|
|
568
|
+
failure: {
|
|
569
|
+
reason: recovery.recovery,
|
|
570
|
+
rawError: recovery.reason
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
async function clearContextEngineProjectionBeforeNativeCompaction(params) {
|
|
575
|
+
const contextEngineBinding = params.binding.contextEngine;
|
|
576
|
+
if (!contextEngineBinding?.projection) return;
|
|
577
|
+
await params.bindingStore.mutate(params.identity, {
|
|
578
|
+
kind: "patch",
|
|
579
|
+
threadId: params.binding.threadId,
|
|
580
|
+
patch: { contextEngine: {
|
|
581
|
+
...contextEngineBinding,
|
|
582
|
+
projection: void 0
|
|
583
|
+
} }
|
|
584
|
+
});
|
|
585
|
+
embeddedAgentLog.info("cleared codex context-engine projection before native compaction", {
|
|
586
|
+
sessionId: params.sessionId,
|
|
587
|
+
threadId: params.binding.threadId,
|
|
588
|
+
previousEpoch: contextEngineBinding.projection.epoch,
|
|
589
|
+
previousFingerprint: contextEngineBinding.projection.fingerprint
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
function isSameNativeCompactionBinding(current, expected) {
|
|
593
|
+
return current.threadId === expected.threadId && 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;
|
|
594
|
+
}
|
|
595
|
+
function isCodexThreadNotFoundError(error) {
|
|
596
|
+
return formatCompactionError(error).toLowerCase().includes("thread not found");
|
|
597
|
+
}
|
|
598
|
+
function formatCompactionError(error) {
|
|
599
|
+
if (error instanceof Error) return error.message;
|
|
600
|
+
return String(error);
|
|
601
|
+
}
|
|
602
|
+
//#endregion
|
|
603
|
+
export { maybeCompactCodexAppServerSession };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { d as resolveCodexAppServerRuntimeOptions,
|
|
2
|
-
import { i as describeControlFailure } from "./plugin-app-cache-key-
|
|
3
|
-
import { t as requestCodexAppServerJson } from "./request-
|
|
1
|
+
import { d as resolveCodexAppServerRuntimeOptions, p as resolveCodexComputerUseConfig } from "./config-CYEDnLJ2.js";
|
|
2
|
+
import { i as describeControlFailure } from "./plugin-app-cache-key-BrhVdeEf.js";
|
|
3
|
+
import { t as requestCodexAppServerJson } from "./request-BcJyl8KL.js";
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
5
|
//#region extensions/codex/src/app-server/computer-use.ts
|
|
6
6
|
/**
|