@openclaw/codex 2026.7.2-beta.3 → 2026.7.2-beta.5
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-DUMF2Xyr.js → app-server-policy-BmDgseo_.js} +1 -1
- package/dist/attempt-client-cleanup-Ia52yRWc.js +127 -0
- package/dist/{attempt-notifications-Ecjyzufe.js → attempt-notifications-CMR2_fmR.js} +1 -1
- package/dist/{media-understanding-provider-IPNNQre6.js → bounded-turn-FEbUXoYT.js} +71 -188
- package/dist/capabilities-BHRSI6Cn.js +36 -0
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-NCTL7A2q.js → command-formatters-ico4ZFnk.js} +3 -37
- package/dist/{command-handlers-DtFbZiba.js → command-handlers-CRmnwI2N.js} +1233 -1221
- package/dist/{compact-Kgy26gIM.js → compact-dEN49UH6.js} +8 -7
- package/dist/{computer-use-C7x4ZaqR.js → computer-use-BjGylO-E.js} +16 -6
- package/dist/{conversation-control-B0s3aIjT.js → conversation-control-DE7d9DOj.js} +6 -5
- package/dist/doctor-contract-api.js +24 -86
- package/dist/{dynamic-tools-D_vSVmv9.js → dynamic-tools-LIt9ojep.js} +135 -2696
- package/dist/event-projector-assistant-message-DTgnPPVF.js +101 -0
- package/dist/event-projector-usage-tvgb1NCX.js +69 -0
- package/dist/harness.js +31 -11
- package/dist/incognito-session-ET_ufDH-.js +2 -0
- package/dist/index.js +250 -275
- package/dist/media-understanding-provider.js +173 -1
- package/dist/{models-DD5zBdX5.js → models-BA01NEez.js} +2 -2
- package/dist/{notification-correlation-C8DVQ_Bq.js → notification-correlation-Bj_Ak_jI.js} +3 -3
- package/dist/{plugin-app-cache-key-DJbhLYSK.js → plugin-app-cache-key-DSXX-rXO.js} +5 -5
- package/dist/{transcript-mirror-D9rTxx2P.js → protocol-validators-Dm4eXZmt.js} +335 -595
- package/dist/{rate-limits-CqhWQ2R9.js → rate-limits-S_PXs0ul.js} +1 -1
- package/dist/realtime-voice-api-BPcA1uN9.js +494 -0
- package/dist/realtime-voice-api.js +2 -0
- package/dist/{request-9yf9pZjf.js → request-CXpPennK.js} +1 -1
- package/dist/{run-attempt-BIoO8ISr.js → run-attempt-C5GTPJOE.js} +3111 -387
- package/dist/{session-binding-Bmt20HfB.js → session-binding-DlVQ-Pxs.js} +957 -890
- package/dist/{session-catalog-CA7R-hX2.js → session-catalog-CP2oCcEb.js} +98 -87
- package/dist/{session-cli-Bxk3-Wqz.js → session-cli-CqZ0Fp2a.js} +2 -2
- package/dist/session-upstream-marker-QE-m5QFG.js +82 -0
- package/dist/settled-turn-finalizer-CA_2QXIE.js +303 -0
- package/dist/{shared-client-CSXLtCLE.js → shared-client-BVKE40c-.js} +1870 -1694
- package/dist/{side-question-DtzquMOb.js → side-question-CO12sHxo.js} +24 -16
- package/dist/{thread-lifecycle-CQ_9mAa1.js → thread-lifecycle-DRg_FdzC.js} +127 -153
- package/dist/transcript-mirror-uKA-A4tB.js +550 -0
- package/dist/upstream-session-fork-_Vrz4WJr.js +320 -0
- package/dist/{usage-CuPpFgTc.js → usage-UpVbdX5G.js} +3 -3
- package/dist/{web-search-provider.runtime-_x5XTeqh.js → web-search-provider.runtime-CaQMYDbp.js} +3 -3
- package/package.json +7 -8
- package/npm-shrinkwrap.json +0 -202
- package/dist/{auth-binding-C1czuHPA.js → auth-binding-B4FfbcCg.js} +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { b as canUseCodexModelBackedApprovalsReviewerForModel } from "./session-binding-DlVQ-Pxs.js";
|
|
2
2
|
//#region extensions/codex/src/app-server/app-server-policy.ts
|
|
3
3
|
/**
|
|
4
4
|
* Policy promotion for Codex app-server runs that can safely use OpenClaw tool
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { f as retireSharedCodexAppServerClientIfCurrent, n as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, t as clearSharedCodexAppServerClientIfCurrent } from "./shared-client-BVKE40c-.js";
|
|
2
|
+
import { embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
3
|
+
//#region extensions/codex/src/app-server/attempt-client-cleanup.ts
|
|
4
|
+
/**
|
|
5
|
+
* Best-effort cleanup helpers for Codex app-server startup attempts and turns.
|
|
6
|
+
*/
|
|
7
|
+
/** Timeout for best-effort app-server turn interruption during cleanup. */
|
|
8
|
+
const CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS = 5e3;
|
|
9
|
+
/** Timeout for best-effort thread unsubscribe during cleanup. */
|
|
10
|
+
const CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS = 5e3;
|
|
11
|
+
/** Raised when a thread subscription may be live on a client OpenClaw no longer controls. */
|
|
12
|
+
var CodexAppServerUnsafeSubscriptionError = class extends Error {
|
|
13
|
+
constructor(message, options) {
|
|
14
|
+
super(message, options);
|
|
15
|
+
this.name = "CodexAppServerUnsafeSubscriptionError";
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
function isCodexAppServerUnsafeSubscriptionError(error) {
|
|
19
|
+
return error instanceof CodexAppServerUnsafeSubscriptionError;
|
|
20
|
+
}
|
|
21
|
+
/** Asserts Codex resumed the exact thread this attempt subscribed to. */
|
|
22
|
+
function assertCodexThreadResumeSubscription(requestedThreadId, returnedThreadId) {
|
|
23
|
+
if (returnedThreadId !== requestedThreadId) throw new CodexAppServerUnsafeSubscriptionError(`Codex thread/resume returned ${returnedThreadId} for ${requestedThreadId}`);
|
|
24
|
+
}
|
|
25
|
+
async function closeClientAndWaitIfAvailable(client) {
|
|
26
|
+
const closeable = client;
|
|
27
|
+
if (typeof closeable.closeAndWait === "function") {
|
|
28
|
+
await closeable.closeAndWait();
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
closeable.close?.();
|
|
32
|
+
}
|
|
33
|
+
async function closeCodexStartupClientBestEffort(client) {
|
|
34
|
+
if (!client) return;
|
|
35
|
+
const unclaimedSharedClient = clearSharedCodexAppServerClientIfCurrentAndUnclaimed(client);
|
|
36
|
+
if (unclaimedSharedClient.closed) {
|
|
37
|
+
await closeClientAndWaitIfAvailable(client);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (unclaimedSharedClient.found) {
|
|
41
|
+
if (retireSharedCodexAppServerClientIfCurrent(client)?.closed) await closeClientAndWaitIfAvailable(client);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const retiredSharedClient = retireSharedCodexAppServerClientIfCurrent(client);
|
|
45
|
+
if (retiredSharedClient) {
|
|
46
|
+
if (retiredSharedClient.closed) await closeClientAndWaitIfAvailable(client);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (clearSharedCodexAppServerClientIfCurrent(client)) {
|
|
50
|
+
await closeClientAndWaitIfAvailable(client);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
await closeClientAndWaitIfAvailable(client);
|
|
54
|
+
}
|
|
55
|
+
/** Sends a turn interrupt without blocking abort cleanup on app-server errors. */
|
|
56
|
+
function interruptCodexTurnBestEffort(client, params) {
|
|
57
|
+
interruptCodexTurnAndWaitBestEffort(client, params);
|
|
58
|
+
}
|
|
59
|
+
/** Sends a bounded turn interrupt and waits for Codex to confirm terminal abort handling. */
|
|
60
|
+
async function interruptCodexTurnAndWaitBestEffort(client, params) {
|
|
61
|
+
const requestOptions = params.timeoutMs && Number.isFinite(params.timeoutMs) && params.timeoutMs > 0 ? { timeoutMs: params.timeoutMs } : void 0;
|
|
62
|
+
const requestParams = {
|
|
63
|
+
threadId: params.threadId,
|
|
64
|
+
turnId: params.turnId
|
|
65
|
+
};
|
|
66
|
+
try {
|
|
67
|
+
await (requestOptions ? client.request("turn/interrupt", requestParams, requestOptions) : client.request("turn/interrupt", requestParams));
|
|
68
|
+
} catch (error) {
|
|
69
|
+
embeddedAgentLog.debug("codex app-server turn interrupt failed during abort", { error });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** Unsubscribes from a thread while swallowing cleanup-only failures. */
|
|
73
|
+
async function unsubscribeCodexThreadBestEffort(client, params) {
|
|
74
|
+
try {
|
|
75
|
+
await client.request("thread/unsubscribe", { threadId: params.threadId }, { timeoutMs: params.timeoutMs });
|
|
76
|
+
return true;
|
|
77
|
+
} catch (error) {
|
|
78
|
+
embeddedAgentLog.debug("codex app-server thread unsubscribe cleanup failed", {
|
|
79
|
+
threadId: params.threadId,
|
|
80
|
+
error
|
|
81
|
+
});
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Retires the shared client after a timed-out turn so later runs do not reuse a
|
|
87
|
+
* potentially wedged app-server connection.
|
|
88
|
+
*/
|
|
89
|
+
async function retireCodexAppServerClientAfterTimedOutTurn(client, params) {
|
|
90
|
+
const retiredSharedClient = retireSharedCodexAppServerClientIfCurrent(client, { failActiveLeases: params.suspectPhysicalClient });
|
|
91
|
+
const detachedSharedClient = Boolean(retiredSharedClient);
|
|
92
|
+
if (!(params.suspectPhysicalClient && (retiredSharedClient?.closed ?? false))) {
|
|
93
|
+
interruptCodexTurnBestEffort(client, {
|
|
94
|
+
threadId: params.threadId,
|
|
95
|
+
turnId: params.turnId,
|
|
96
|
+
timeoutMs: CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS
|
|
97
|
+
});
|
|
98
|
+
await unsubscribeCodexThreadBestEffort(client, {
|
|
99
|
+
threadId: params.threadId,
|
|
100
|
+
timeoutMs: CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
let closedClient = retiredSharedClient?.closed ?? false;
|
|
104
|
+
if (!detachedSharedClient) {
|
|
105
|
+
const close = client.close;
|
|
106
|
+
if (typeof close === "function") try {
|
|
107
|
+
close.call(client);
|
|
108
|
+
closedClient = true;
|
|
109
|
+
} catch (error) {
|
|
110
|
+
embeddedAgentLog.debug("codex app-server client close failed during timeout cleanup", {
|
|
111
|
+
threadId: params.threadId,
|
|
112
|
+
turnId: params.turnId,
|
|
113
|
+
error
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
embeddedAgentLog.warn("codex app-server client retired after timed-out turn", {
|
|
118
|
+
threadId: params.threadId,
|
|
119
|
+
turnId: params.turnId,
|
|
120
|
+
reason: params.reason,
|
|
121
|
+
detachedSharedClient,
|
|
122
|
+
closedClient,
|
|
123
|
+
activeSharedClientLeases: retiredSharedClient?.activeLeases ?? 0
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
127
|
+
export { closeCodexStartupClientBestEffort as a, isCodexAppServerUnsafeSubscriptionError as c, assertCodexThreadResumeSubscription as i, retireCodexAppServerClientAfterTimedOutTurn as l, CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS as n, interruptCodexTurnAndWaitBestEffort as o, CodexAppServerUnsafeSubscriptionError as r, interruptCodexTurnBestEffort as s, CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS as t, unsubscribeCodexThreadBestEffort as u };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { V as isJsonObject } from "./shared-client-BVKE40c-.js";
|
|
2
2
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
3
3
|
//#region extensions/codex/src/app-server/attempt-notifications.ts
|
|
4
4
|
/**
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { _ as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { V as isJsonObject, s as isCodexAppServerStartSelectionChangedError } from "./shared-client-BVKE40c-.js";
|
|
2
|
+
import { p as resolveCodexAppServerRuntimeOptions } from "./session-binding-DlVQ-Pxs.js";
|
|
3
|
+
import { o as interruptCodexTurnAndWaitBestEffort, t as CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS } from "./attempt-client-cleanup-Ia52yRWc.js";
|
|
4
|
+
import { _ as readCodexNotificationItem, h as isRetryableErrorNotification } from "./attempt-notifications-CMR2_fmR.js";
|
|
5
|
+
import { G as mergeCodexThreadConfigs, d as buildCodexRingZeroThreadConfigPatch, f as buildCodexRuntimeThreadConfig, l as assertCodexRingZeroHasNoManagedHooks, p as readCodexInheritedMcpServerNames, u as attestCodexRingZeroThreadHasNoMcpServers } from "./thread-lifecycle-DRg_FdzC.js";
|
|
6
|
+
import { t as normalizeCodexResponseTokenUsage } from "./event-projector-usage-tvgb1NCX.js";
|
|
7
|
+
import { a as assertCodexTurnStartResponse, i as assertCodexThreadStartResponse, s as readCodexErrorNotification, u as readCodexTurnCompletedNotification } from "./protocol-validators-Dm4eXZmt.js";
|
|
8
|
+
import { r as readModelListResult } from "./models-BA01NEez.js";
|
|
8
9
|
import fs from "node:fs/promises";
|
|
9
10
|
import path from "node:path";
|
|
10
11
|
import { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
@@ -15,7 +16,7 @@ const CODEX_PRIVATE_STDIO_ARGS = [
|
|
|
15
16
|
"--listen",
|
|
16
17
|
"stdio://"
|
|
17
18
|
];
|
|
18
|
-
const
|
|
19
|
+
const CODEX_APP_SERVER_ARGS_ENV_KEY = "OPENCLAW_CODEX_APP_SERVER_ARGS";
|
|
19
20
|
const CODEX_BOUNDED_THREAD_CONFIG = {
|
|
20
21
|
"features.multi_agent": false,
|
|
21
22
|
"features.apps": false,
|
|
@@ -28,6 +29,10 @@ const CODEX_PRIVATE_BOUNDED_THREAD_CONFIG = {
|
|
|
28
29
|
"features.hooks": false,
|
|
29
30
|
notify: []
|
|
30
31
|
};
|
|
32
|
+
const CODEX_SETTLED_FINALIZER_THREAD_CONFIG = {
|
|
33
|
+
"skills.include_instructions": false,
|
|
34
|
+
include_environment_context: false
|
|
35
|
+
};
|
|
31
36
|
async function runBoundedCodexAppServerTurn(params) {
|
|
32
37
|
const appServer = resolveCodexAppServerRuntimeOptions({
|
|
33
38
|
pluginConfig: params.options.pluginConfig,
|
|
@@ -61,22 +66,39 @@ async function runBoundedCodexAppServerTurnInWorkspace(params, appServer, worksp
|
|
|
61
66
|
authProfileId: params.profile,
|
|
62
67
|
agentDir,
|
|
63
68
|
config: params.config,
|
|
64
|
-
timeoutMs
|
|
65
|
-
|
|
69
|
+
timeoutMs,
|
|
70
|
+
...params.signal ? { abandonSignal: params.signal } : {}
|
|
71
|
+
}) : await import("./shared-client-BVKE40c-.js").then((n) => n.p).then(({ createIsolatedCodexAppServerClient }) => createIsolatedCodexAppServerClient({
|
|
66
72
|
startOptions,
|
|
67
73
|
timeoutMs,
|
|
68
74
|
authProfileId: params.profile,
|
|
69
75
|
agentDir,
|
|
70
76
|
authProfileStore: params.authProfileStore,
|
|
71
|
-
config: params.config
|
|
77
|
+
config: params.config,
|
|
78
|
+
...params.signal ? { abandonSignal: params.signal } : {}
|
|
72
79
|
}));
|
|
73
80
|
const abortController = new AbortController();
|
|
74
|
-
|
|
81
|
+
let activeThreadId;
|
|
82
|
+
let activeTurnId = "";
|
|
83
|
+
let interruptPromise;
|
|
84
|
+
const requestInterrupt = () => {
|
|
85
|
+
if (!activeThreadId || interruptPromise) return;
|
|
86
|
+
interruptPromise = interruptCodexTurnAndWaitBestEffort(client, {
|
|
87
|
+
threadId: activeThreadId,
|
|
88
|
+
turnId: activeTurnId,
|
|
89
|
+
timeoutMs: CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
const abortRun = (reason) => {
|
|
93
|
+
abortController.abort(reason);
|
|
94
|
+
requestInterrupt();
|
|
95
|
+
};
|
|
96
|
+
const abortFromCaller = () => abortRun(params.signal?.reason ?? "aborted");
|
|
75
97
|
if (params.signal?.aborted) abortFromCaller();
|
|
76
98
|
else params.signal?.addEventListener("abort", abortFromCaller, { once: true });
|
|
77
99
|
const remainingRunMs = deadline - Date.now();
|
|
78
|
-
if (remainingRunMs <= 0)
|
|
79
|
-
const timeout = setTimeout(() =>
|
|
100
|
+
if (remainingRunMs <= 0) abortRun("timeout");
|
|
101
|
+
const timeout = setTimeout(() => abortRun("timeout"), Math.max(1, remainingRunMs));
|
|
80
102
|
timeout.unref?.();
|
|
81
103
|
let retrySelection = false;
|
|
82
104
|
try {
|
|
@@ -87,6 +109,8 @@ async function runBoundedCodexAppServerTurnInWorkspace(params, appServer, worksp
|
|
|
87
109
|
timeoutMs,
|
|
88
110
|
signal: abortController.signal
|
|
89
111
|
});
|
|
112
|
+
const inheritedMcpServerNames = params.requireNoExternalCapabilities ? await readCodexInheritedMcpServerNames(client, workspace.cwd, abortController.signal) : [];
|
|
113
|
+
if (params.requireNoExternalCapabilities) await assertCodexRingZeroHasNoManagedHooks(client, abortController.signal);
|
|
90
114
|
const thread = assertCodexThreadStartResponse(await client.request("thread/start", {
|
|
91
115
|
model,
|
|
92
116
|
modelProvider: "openai",
|
|
@@ -94,8 +118,9 @@ async function runBoundedCodexAppServerTurnInWorkspace(params, appServer, worksp
|
|
|
94
118
|
approvalPolicy: "on-request",
|
|
95
119
|
sandbox: "read-only",
|
|
96
120
|
serviceName: "OpenClaw",
|
|
121
|
+
...params.requireNoExternalCapabilities ? { baseInstructions: "" } : {},
|
|
97
122
|
developerInstructions: params.developerInstructions,
|
|
98
|
-
config: buildCodexRuntimeThreadConfig(resolveBoundedThreadConfig(params, workspace), { nativeCodeModeEnabled: false }),
|
|
123
|
+
config: buildCodexRuntimeThreadConfig(resolveBoundedThreadConfig(params, workspace, inheritedMcpServerNames), { nativeCodeModeEnabled: false }),
|
|
99
124
|
environments: [],
|
|
100
125
|
dynamicTools: [],
|
|
101
126
|
experimentalRawEvents: true,
|
|
@@ -104,6 +129,16 @@ async function runBoundedCodexAppServerTurnInWorkspace(params, appServer, worksp
|
|
|
104
129
|
timeoutMs,
|
|
105
130
|
signal: abortController.signal
|
|
106
131
|
}));
|
|
132
|
+
activeThreadId = thread.thread.id;
|
|
133
|
+
if (abortController.signal.aborted) requestInterrupt();
|
|
134
|
+
if (params.requireNoExternalCapabilities) await attestCodexRingZeroThreadHasNoMcpServers(client, thread.thread.id, abortController.signal);
|
|
135
|
+
if (params.historyItems?.length) await client.request("thread/inject_items", {
|
|
136
|
+
threadId: thread.thread.id,
|
|
137
|
+
items: params.historyItems
|
|
138
|
+
}, {
|
|
139
|
+
timeoutMs,
|
|
140
|
+
signal: abortController.signal
|
|
141
|
+
});
|
|
107
142
|
const collector = createCodexBoundedTurnCollector(thread.thread.id, params.taskLabel);
|
|
108
143
|
const cleanup = client.addNotificationHandler(collector.handleNotification);
|
|
109
144
|
const requestCleanup = client.addRequestHandler(createCodexBoundedApprovalHandler(params.taskLabel));
|
|
@@ -119,6 +154,8 @@ async function runBoundedCodexAppServerTurnInWorkspace(params, appServer, worksp
|
|
|
119
154
|
timeoutMs,
|
|
120
155
|
signal: abortController.signal
|
|
121
156
|
}));
|
|
157
|
+
activeTurnId = turn.turn.id;
|
|
158
|
+
if (abortController.signal.aborted) requestInterrupt();
|
|
122
159
|
return {
|
|
123
160
|
...await collector.collect(turn.turn, {
|
|
124
161
|
timeoutMs,
|
|
@@ -136,6 +173,7 @@ async function runBoundedCodexAppServerTurnInWorkspace(params, appServer, worksp
|
|
|
136
173
|
} finally {
|
|
137
174
|
clearTimeout(timeout);
|
|
138
175
|
params.signal?.removeEventListener("abort", abortFromCaller);
|
|
176
|
+
await interruptPromise;
|
|
139
177
|
if (ownsClient) client.close();
|
|
140
178
|
}
|
|
141
179
|
if (retrySelection) return await runBoundedCodexAppServerTurnInWorkspace(params, appServer, workspace, selectionAttempt + 1, {
|
|
@@ -144,15 +182,17 @@ async function runBoundedCodexAppServerTurnInWorkspace(params, appServer, worksp
|
|
|
144
182
|
});
|
|
145
183
|
throw new Error("Codex bounded turn selection retry exited unexpectedly");
|
|
146
184
|
}
|
|
147
|
-
function resolveBoundedThreadConfig(params, workspace) {
|
|
185
|
+
function resolveBoundedThreadConfig(params, workspace, inheritedMcpServerNames) {
|
|
148
186
|
const boundedConfig = mergeCodexThreadConfigs(CODEX_BOUNDED_THREAD_CONFIG, params.threadConfig) ?? CODEX_BOUNDED_THREAD_CONFIG;
|
|
149
|
-
|
|
187
|
+
const privateConfig = workspace.codexHome ? mergeCodexThreadConfigs(boundedConfig, CODEX_PRIVATE_BOUNDED_THREAD_CONFIG) ?? boundedConfig : boundedConfig;
|
|
188
|
+
if (!params.requireNoExternalCapabilities) return privateConfig;
|
|
189
|
+
return mergeCodexThreadConfigs(privateConfig, CODEX_SETTLED_FINALIZER_THREAD_CONFIG, buildCodexRingZeroThreadConfigPatch({ toolsAllow: ["openclaw"] }, true, inheritedMcpServerNames)) ?? privateConfig;
|
|
150
190
|
}
|
|
151
191
|
function buildPrivateCodexAppServerStartOptions(start, codexHome) {
|
|
152
|
-
const privateEnv = Object.fromEntries(Object.entries(start.env ?? {}).filter(([name]) => name.trim().toUpperCase() !==
|
|
192
|
+
const privateEnv = Object.fromEntries(Object.entries(start.env ?? {}).filter(([name]) => name.trim().toUpperCase() !== CODEX_APP_SERVER_ARGS_ENV_KEY));
|
|
153
193
|
const clearEnv = (start.clearEnv ?? []).filter((name) => {
|
|
154
194
|
const normalized = name.trim().toUpperCase();
|
|
155
|
-
return normalized !== "CODEX_HOME" && normalized !==
|
|
195
|
+
return normalized !== "CODEX_HOME" && normalized !== CODEX_APP_SERVER_ARGS_ENV_KEY;
|
|
156
196
|
});
|
|
157
197
|
return {
|
|
158
198
|
...start,
|
|
@@ -161,7 +201,7 @@ function buildPrivateCodexAppServerStartOptions(start, codexHome) {
|
|
|
161
201
|
...privateEnv,
|
|
162
202
|
CODEX_HOME: codexHome
|
|
163
203
|
},
|
|
164
|
-
clearEnv: [...clearEnv,
|
|
204
|
+
clearEnv: [...clearEnv, CODEX_APP_SERVER_ARGS_ENV_KEY]
|
|
165
205
|
};
|
|
166
206
|
}
|
|
167
207
|
function createCodexBoundedApprovalHandler(taskLabel) {
|
|
@@ -207,6 +247,7 @@ function createCodexBoundedTurnCollector(threadId, taskLabel) {
|
|
|
207
247
|
let turnId;
|
|
208
248
|
let completedTurn;
|
|
209
249
|
let promptError;
|
|
250
|
+
let responseUsage;
|
|
210
251
|
const pending = [];
|
|
211
252
|
const completedItems = /* @__PURE__ */ new Map();
|
|
212
253
|
const assistantTextByItem = /* @__PURE__ */ new Map();
|
|
@@ -242,12 +283,18 @@ function createCodexBoundedTurnCollector(threadId, taskLabel) {
|
|
|
242
283
|
rememberAssistantText(itemId, `${assistantTextByItem.get(itemId) ?? ""}${delta}`);
|
|
243
284
|
return;
|
|
244
285
|
}
|
|
286
|
+
if (notification.method === "rawResponse/completed") {
|
|
287
|
+
const usage = isJsonObject(params.usage) ? params.usage : void 0;
|
|
288
|
+
responseUsage = usage ? normalizeCodexResponseTokenUsage(usage) : void 0;
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
245
291
|
if (notification.method === "turn/completed") {
|
|
246
292
|
completedTurn = readCodexTurnCompletedNotification(notification.params)?.turn ?? completedTurn;
|
|
247
293
|
resolveCompletion?.();
|
|
248
294
|
return;
|
|
249
295
|
}
|
|
250
296
|
if (notification.method === "error") {
|
|
297
|
+
if (isRetryableErrorNotification(notification.params)) return;
|
|
251
298
|
promptError = readCodexErrorNotification(notification.params)?.error.message ?? `codex app-server ${taskLabel} turn failed`;
|
|
252
299
|
resolveCompletion?.();
|
|
253
300
|
}
|
|
@@ -266,6 +313,7 @@ function createCodexBoundedTurnCollector(threadId, taskLabel) {
|
|
|
266
313
|
});
|
|
267
314
|
if (promptError) throw new Error(promptError);
|
|
268
315
|
if (completedTurn?.status === "failed") throw new Error(completedTurn.error?.message ?? `codex app-server ${taskLabel} turn failed`);
|
|
316
|
+
if (completedTurn?.status !== "completed") throw new Error(`codex app-server ${taskLabel} turn ended with status ${completedTurn?.status ?? "unknown"}`);
|
|
269
317
|
const items = collectCompletedItems(completedTurn?.items, completedItems);
|
|
270
318
|
const itemText = collectAssistantTextFromItems(items);
|
|
271
319
|
const deltaText = assistantItemOrder.map((itemId) => assistantTextByItem.get(itemId)?.trim()).filter((text) => Boolean(text)).join("\n\n").trim();
|
|
@@ -273,7 +321,8 @@ function createCodexBoundedTurnCollector(threadId, taskLabel) {
|
|
|
273
321
|
if (!text) throw new Error(`Codex app-server ${taskLabel} turn returned no text.`);
|
|
274
322
|
return {
|
|
275
323
|
text,
|
|
276
|
-
items
|
|
324
|
+
items,
|
|
325
|
+
...responseUsage ? { usage: responseUsage } : {}
|
|
277
326
|
};
|
|
278
327
|
}
|
|
279
328
|
};
|
|
@@ -316,170 +365,4 @@ function isTerminalTurn(turn) {
|
|
|
316
365
|
return turn.status === "completed" || turn.status === "interrupted" || turn.status === "failed";
|
|
317
366
|
}
|
|
318
367
|
//#endregion
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* Codex-backed media understanding provider for bounded image description and
|
|
322
|
-
* structured extraction turns.
|
|
323
|
-
*/
|
|
324
|
-
const CODEX_MEDIA_PROVIDER_ID = "codex";
|
|
325
|
-
const DEFAULT_CODEX_IMAGE_MODEL = "gpt-5.6-sol";
|
|
326
|
-
const DEFAULT_CODEX_IMAGE_PROMPT = "Describe the image.";
|
|
327
|
-
/**
|
|
328
|
-
* Builds the media-understanding provider that delegates image tasks to an
|
|
329
|
-
* isolated Codex app-server session.
|
|
330
|
-
*/
|
|
331
|
-
function buildCodexMediaUnderstandingProvider(options = {}) {
|
|
332
|
-
return {
|
|
333
|
-
id: CODEX_MEDIA_PROVIDER_ID,
|
|
334
|
-
capabilities: ["image"],
|
|
335
|
-
defaultModels: { image: DEFAULT_CODEX_IMAGE_MODEL },
|
|
336
|
-
describeImage: async (req) => describeCodexImages({
|
|
337
|
-
images: [{
|
|
338
|
-
buffer: req.buffer,
|
|
339
|
-
fileName: req.fileName,
|
|
340
|
-
mime: req.mime
|
|
341
|
-
}],
|
|
342
|
-
provider: req.provider,
|
|
343
|
-
model: req.model,
|
|
344
|
-
prompt: req.prompt,
|
|
345
|
-
maxTokens: req.maxTokens,
|
|
346
|
-
timeoutMs: req.timeoutMs,
|
|
347
|
-
profile: req.profile,
|
|
348
|
-
preferredProfile: req.preferredProfile,
|
|
349
|
-
authStore: req.authStore,
|
|
350
|
-
agentDir: req.agentDir,
|
|
351
|
-
cfg: req.cfg
|
|
352
|
-
}, options),
|
|
353
|
-
describeImages: async (req) => describeCodexImages(req, options),
|
|
354
|
-
extractStructured: async (req) => extractCodexStructured(req, options)
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
async function describeCodexImages(req, options) {
|
|
358
|
-
const model = req.model.trim();
|
|
359
|
-
if (!model) throw new Error("Codex image understanding requires model id.");
|
|
360
|
-
const { text } = await runBoundedCodexAppServerTurn({
|
|
361
|
-
config: req.cfg,
|
|
362
|
-
model: {
|
|
363
|
-
mode: "required",
|
|
364
|
-
id: model
|
|
365
|
-
},
|
|
366
|
-
profile: req.profile,
|
|
367
|
-
timeoutMs: req.timeoutMs,
|
|
368
|
-
agentDir: req.agentDir,
|
|
369
|
-
authProfileStore: req.authStore,
|
|
370
|
-
options,
|
|
371
|
-
taskLabel: "image understanding",
|
|
372
|
-
developerInstructions: "You are OpenClaw's bounded image-understanding worker. Describe only the provided image content. Do not call tools, edit files, or ask follow-up questions.",
|
|
373
|
-
input: [{
|
|
374
|
-
type: "text",
|
|
375
|
-
text: buildCodexImagePrompt(req),
|
|
376
|
-
text_elements: []
|
|
377
|
-
}, ...req.images.map((image) => ({
|
|
378
|
-
type: "image",
|
|
379
|
-
url: `data:${image.mime ?? "image/png"};base64,${image.buffer.toString("base64")}`
|
|
380
|
-
}))],
|
|
381
|
-
requiredModalities: ["text", "image"],
|
|
382
|
-
isolation: "configured-transport"
|
|
383
|
-
});
|
|
384
|
-
return {
|
|
385
|
-
text,
|
|
386
|
-
model
|
|
387
|
-
};
|
|
388
|
-
}
|
|
389
|
-
async function extractCodexStructured(req, options) {
|
|
390
|
-
const model = req.model.trim();
|
|
391
|
-
if (!model) throw new Error("Codex structured extraction requires model id.");
|
|
392
|
-
if (!req.instructions.trim()) throw new Error("Codex structured extraction requires instructions.");
|
|
393
|
-
if (req.input.length === 0) throw new Error("Codex structured extraction requires at least one input.");
|
|
394
|
-
if (!req.input.some((entry) => entry.type === "image")) throw new Error("Codex structured extraction requires at least one image input.");
|
|
395
|
-
const { text } = await runBoundedCodexAppServerTurn({
|
|
396
|
-
config: req.cfg,
|
|
397
|
-
model: {
|
|
398
|
-
mode: "required",
|
|
399
|
-
id: model
|
|
400
|
-
},
|
|
401
|
-
profile: req.profile,
|
|
402
|
-
timeoutMs: req.timeoutMs,
|
|
403
|
-
agentDir: req.agentDir,
|
|
404
|
-
authProfileStore: req.authStore,
|
|
405
|
-
options,
|
|
406
|
-
taskLabel: "structured extraction",
|
|
407
|
-
developerInstructions: "You are OpenClaw's bounded structured-extraction worker. Return only the requested extraction. Do not call tools, edit files, ask follow-up questions, or include secrets.",
|
|
408
|
-
input: buildCodexStructuredInput(req),
|
|
409
|
-
requiredModalities: requiredStructuredModalities(),
|
|
410
|
-
isolation: "configured-transport"
|
|
411
|
-
});
|
|
412
|
-
return normalizeStructuredExtractionResult({
|
|
413
|
-
text,
|
|
414
|
-
model,
|
|
415
|
-
provider: req.provider,
|
|
416
|
-
req
|
|
417
|
-
});
|
|
418
|
-
}
|
|
419
|
-
function buildCodexImagePrompt(req) {
|
|
420
|
-
const prompt = req.prompt?.trim() || DEFAULT_CODEX_IMAGE_PROMPT;
|
|
421
|
-
if (req.images.length <= 1) return prompt;
|
|
422
|
-
return `${prompt}\n\nAnalyze all ${req.images.length} images together.`;
|
|
423
|
-
}
|
|
424
|
-
function requiredStructuredModalities() {
|
|
425
|
-
return ["text", "image"];
|
|
426
|
-
}
|
|
427
|
-
function buildCodexStructuredInput(req) {
|
|
428
|
-
return [{
|
|
429
|
-
type: "text",
|
|
430
|
-
text: buildStructuredExtractionPrompt(req),
|
|
431
|
-
text_elements: []
|
|
432
|
-
}, ...req.input.map((entry) => {
|
|
433
|
-
if (entry.type === "text") return {
|
|
434
|
-
type: "text",
|
|
435
|
-
text: entry.text,
|
|
436
|
-
text_elements: []
|
|
437
|
-
};
|
|
438
|
-
return {
|
|
439
|
-
type: "image",
|
|
440
|
-
url: `data:${entry.mime ?? "image/png"};base64,${entry.buffer.toString("base64")}`
|
|
441
|
-
};
|
|
442
|
-
})];
|
|
443
|
-
}
|
|
444
|
-
function buildStructuredExtractionPrompt(req) {
|
|
445
|
-
return [
|
|
446
|
-
req.instructions.trim(),
|
|
447
|
-
req.schemaName ? `Schema name: ${req.schemaName}` : void 0,
|
|
448
|
-
req.jsonSchema ? `JSON schema:\n${JSON.stringify(req.jsonSchema)}` : void 0,
|
|
449
|
-
req.jsonMode === false ? "Return the extraction as concise text." : "Return valid JSON only. Do not wrap the JSON in Markdown fences."
|
|
450
|
-
].filter((part) => Boolean(part)).join("\n\n");
|
|
451
|
-
}
|
|
452
|
-
function isJsonSchemaObject(value) {
|
|
453
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
454
|
-
}
|
|
455
|
-
function normalizeStructuredExtractionResult(params) {
|
|
456
|
-
const result = {
|
|
457
|
-
text: params.text,
|
|
458
|
-
model: params.model,
|
|
459
|
-
provider: params.provider,
|
|
460
|
-
contentType: params.req.jsonMode === false ? "text" : "json"
|
|
461
|
-
};
|
|
462
|
-
if (params.req.jsonMode !== false) {
|
|
463
|
-
try {
|
|
464
|
-
result.parsed = JSON.parse(params.text);
|
|
465
|
-
} catch {
|
|
466
|
-
throw new Error("Codex structured extraction returned invalid JSON.");
|
|
467
|
-
}
|
|
468
|
-
if (isJsonSchemaObject(params.req.jsonSchema)) {
|
|
469
|
-
const validation = validateJsonSchemaValue({
|
|
470
|
-
schema: params.req.jsonSchema,
|
|
471
|
-
cacheKey: "codex.media-understanding.extractStructured",
|
|
472
|
-
value: result.parsed,
|
|
473
|
-
cache: false
|
|
474
|
-
});
|
|
475
|
-
if (!validation.ok) {
|
|
476
|
-
const message = validation.errors.map((error) => error.text).join("; ") || "invalid";
|
|
477
|
-
throw new Error(`Codex structured extraction JSON did not match schema: ${message}`);
|
|
478
|
-
}
|
|
479
|
-
result.parsed = validation.value;
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
return result;
|
|
483
|
-
}
|
|
484
|
-
//#endregion
|
|
485
|
-
export { runBoundedCodexAppServerTurn as n, buildCodexMediaUnderstandingProvider as t };
|
|
368
|
+
export { runBoundedCodexAppServerTurn as t };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { _ as CodexAppServerRpcError } from "./shared-client-BVKE40c-.js";
|
|
2
|
+
//#region extensions/codex/src/app-server/capabilities.ts
|
|
3
|
+
/**
|
|
4
|
+
* Capability helpers for optional Codex app-server control-plane methods.
|
|
5
|
+
*/
|
|
6
|
+
/** Known app-server methods used by OpenClaw control surfaces. */
|
|
7
|
+
const CODEX_CONTROL_METHODS = {
|
|
8
|
+
account: "account/read",
|
|
9
|
+
compact: "thread/compact/start",
|
|
10
|
+
feedback: "feedback/upload",
|
|
11
|
+
forkThread: "thread/fork",
|
|
12
|
+
listMcpServers: "mcpServerStatus/list",
|
|
13
|
+
listSkills: "skills/list",
|
|
14
|
+
listThreads: "thread/list",
|
|
15
|
+
listThreadTurns: "thread/turns/list",
|
|
16
|
+
readThread: "thread/read",
|
|
17
|
+
rateLimits: "account/rateLimits/read",
|
|
18
|
+
archiveThread: "thread/archive",
|
|
19
|
+
renameThread: "thread/name/set",
|
|
20
|
+
resumeThread: "thread/resume",
|
|
21
|
+
review: "review/start",
|
|
22
|
+
unarchiveThread: "thread/unarchive",
|
|
23
|
+
getThreadGoal: "thread/goal/get",
|
|
24
|
+
setThreadGoal: "thread/goal/set",
|
|
25
|
+
clearThreadGoal: "thread/goal/clear"
|
|
26
|
+
};
|
|
27
|
+
/** Formats unsupported control calls differently from ordinary RPC failures. */
|
|
28
|
+
function describeControlFailure(error) {
|
|
29
|
+
if (isUnsupportedControlError(error)) return "unsupported by this Codex app-server";
|
|
30
|
+
return error instanceof Error ? error.message : String(error);
|
|
31
|
+
}
|
|
32
|
+
function isUnsupportedControlError(error) {
|
|
33
|
+
return error instanceof CodexAppServerRpcError && error.code === -32601;
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { describeControlFailure as n, CODEX_CONTROL_METHODS as t };
|
package/dist/cli-metadata.js
CHANGED
|
@@ -2,7 +2,7 @@ import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
|
2
2
|
//#region extensions/codex/cli-metadata.ts
|
|
3
3
|
function registerCodexCliMetadata(api) {
|
|
4
4
|
api.registerCli(async ({ program }) => {
|
|
5
|
-
const { registerCodexSessionCli } = await import("./session-cli-
|
|
5
|
+
const { registerCodexSessionCli } = await import("./session-cli-CqZ0Fp2a.js");
|
|
6
6
|
registerCodexSessionCli(program);
|
|
7
7
|
}, { descriptors: [{
|
|
8
8
|
name: "codex",
|
|
@@ -1,39 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { c as summarizeCodexRateLimits, o as summarizeCodexAccountRateLimits, r as hasCodexRateLimitSnapshots } from "./rate-limits-
|
|
3
|
-
//#region extensions/codex/src/app-server/capabilities.ts
|
|
4
|
-
/**
|
|
5
|
-
* Capability helpers for optional Codex app-server control-plane methods.
|
|
6
|
-
*/
|
|
7
|
-
/** Known app-server methods used by OpenClaw control surfaces. */
|
|
8
|
-
const CODEX_CONTROL_METHODS = {
|
|
9
|
-
account: "account/read",
|
|
10
|
-
compact: "thread/compact/start",
|
|
11
|
-
feedback: "feedback/upload",
|
|
12
|
-
forkThread: "thread/fork",
|
|
13
|
-
listMcpServers: "mcpServerStatus/list",
|
|
14
|
-
listSkills: "skills/list",
|
|
15
|
-
listThreads: "thread/list",
|
|
16
|
-
listThreadTurns: "thread/turns/list",
|
|
17
|
-
readThread: "thread/read",
|
|
18
|
-
rateLimits: "account/rateLimits/read",
|
|
19
|
-
archiveThread: "thread/archive",
|
|
20
|
-
renameThread: "thread/name/set",
|
|
21
|
-
resumeThread: "thread/resume",
|
|
22
|
-
review: "review/start",
|
|
23
|
-
unarchiveThread: "thread/unarchive",
|
|
24
|
-
getThreadGoal: "thread/goal/get",
|
|
25
|
-
setThreadGoal: "thread/goal/set",
|
|
26
|
-
clearThreadGoal: "thread/goal/clear"
|
|
27
|
-
};
|
|
28
|
-
/** Formats unsupported control calls differently from ordinary RPC failures. */
|
|
29
|
-
function describeControlFailure(error) {
|
|
30
|
-
if (isUnsupportedControlError(error)) return "unsupported by this Codex app-server";
|
|
31
|
-
return error instanceof Error ? error.message : String(error);
|
|
32
|
-
}
|
|
33
|
-
function isUnsupportedControlError(error) {
|
|
34
|
-
return error instanceof CodexAppServerRpcError && error.code === -32601;
|
|
35
|
-
}
|
|
36
|
-
//#endregion
|
|
1
|
+
import { V as isJsonObject } from "./shared-client-BVKE40c-.js";
|
|
2
|
+
import { c as summarizeCodexRateLimits, o as summarizeCodexAccountRateLimits, r as hasCodexRateLimitSnapshots } from "./rate-limits-S_PXs0ul.js";
|
|
37
3
|
//#region extensions/codex/src/command-formatters.ts
|
|
38
4
|
/** Formats the combined `/codex status` probe result. */
|
|
39
5
|
function formatCodexStatus(probes) {
|
|
@@ -312,4 +278,4 @@ function readString(record, key) {
|
|
|
312
278
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
313
279
|
}
|
|
314
280
|
//#endregion
|
|
315
|
-
export { formatComputerUseStatus as a, formatSkills as c,
|
|
281
|
+
export { formatComputerUseStatus as a, formatSkills as c, formatCodexStatus as i, formatThreads as l, formatAccount as n, formatList as o, formatCodexDisplayText as r, formatModels as s, buildHelp as t, readString as u };
|