@openclaw/codex 2026.5.20-beta.2 → 2026.5.22
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/{client-Ab4Fw77C.js → client-D3SUwPFl.js} +14 -8
- package/dist/{client-factory-BbesECdh.js → client-factory-DdrIY1lw.js} +1 -1
- package/dist/{command-handlers-Gceg_rBZ.js → command-handlers-DsB0GYd2.js} +64 -7
- package/dist/{compact-BaSDurdH.js → compact-BwQn7jKq.js} +186 -40
- package/dist/{computer-use-B4iTog6z.js → computer-use-BMMwWwno.js} +2 -2
- package/dist/{config-DqIp6oTk.js → config-DDMrwfJl.js} +21 -2
- package/dist/dynamic-tools-DA42no4X.js +497 -0
- package/dist/harness.js +15 -5
- package/dist/index.js +10 -9
- package/dist/media-understanding-provider.js +6 -3
- package/dist/{models-C8MdOXGD.js → models-B_uo1pf5.js} +1 -1
- package/dist/{node-cli-sessions-T1olB1SH.js → node-cli-sessions-yVCifOyG.js} +23 -9
- package/dist/{command-formatters-BVBnEgyA.js → notification-correlation-qKY_sgga.js} +66 -15
- package/dist/provider.js +3 -3
- package/dist/{request-BePR77QD.js → request-NklFaHM4.js} +12 -3
- package/dist/{run-attempt-CRHVB240.js → run-attempt-DzlLXP5Y.js} +3750 -1409
- package/dist/sandbox-guard-CTnEWuor.js +233 -0
- package/dist/{session-binding-DEiYHgJ_.js → session-binding-Bw_mfIW2.js} +4 -2
- package/dist/{shared-client-DCxJx5QU.js → shared-client-C_RbGxW8.js} +2 -2
- package/dist/{side-question-DlJAUYst.js → side-question-DzP1wClA.js} +20 -15
- package/dist/test-api.js +3 -2
- package/dist/{thread-lifecycle-Cgi62SSl.js → thread-lifecycle-4Ul7RoW4.js} +606 -589
- package/dist/{vision-tools-B2wt6ecs.js → vision-tools-DOnxzH2y.js} +7 -3
- package/npm-shrinkwrap.json +1934 -0
- package/openclaw.plugin.json +29 -0
- package/package.json +8 -6
- package/dist/plugin-activation-BkQkPLOY.js +0 -452
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { l as resolveCodexAppServerRuntimeOptions } from "./config-DDMrwfJl.js";
|
|
2
2
|
import { n as isRpcResponse } from "./protocol-oeJQu4rs.js";
|
|
3
|
-
import {
|
|
3
|
+
import { materializeWindowsSpawnProgram, resolveWindowsSpawnProgram } from "openclaw/plugin-sdk/windows-spawn";
|
|
4
4
|
import { OPENCLAW_VERSION, embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
5
|
+
import { createInterface } from "node:readline";
|
|
5
6
|
import { spawn } from "node:child_process";
|
|
6
|
-
import { materializeWindowsSpawnProgram, resolveWindowsSpawnProgram } from "openclaw/plugin-sdk/windows-spawn";
|
|
7
7
|
import { EventEmitter } from "node:events";
|
|
8
8
|
import { PassThrough, Writable } from "node:stream";
|
|
9
9
|
import WebSocket from "ws";
|
|
@@ -193,6 +193,7 @@ function signalCodexAppServerTransport(child, signal) {
|
|
|
193
193
|
//#endregion
|
|
194
194
|
//#region extensions/codex/src/app-server/version.ts
|
|
195
195
|
const MIN_CODEX_APP_SERVER_VERSION = "0.125.0";
|
|
196
|
+
const MIN_CODEX_SANDBOX_EXEC_SERVER_APP_SERVER_VERSION = "0.132.0";
|
|
196
197
|
const MANAGED_CODEX_APP_SERVER_PACKAGE = "@openai/codex";
|
|
197
198
|
//#endregion
|
|
198
199
|
//#region extensions/codex/src/app-server/client.ts
|
|
@@ -271,17 +272,21 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
271
272
|
}
|
|
272
273
|
async initialize() {
|
|
273
274
|
if (this.initialized) return;
|
|
274
|
-
|
|
275
|
+
const response = await this.request("initialize", {
|
|
275
276
|
clientInfo: {
|
|
276
277
|
name: "openclaw",
|
|
277
278
|
title: "OpenClaw",
|
|
278
279
|
version: OPENCLAW_VERSION
|
|
279
280
|
},
|
|
280
281
|
capabilities: { experimentalApi: true }
|
|
281
|
-
})
|
|
282
|
+
});
|
|
283
|
+
this.serverVersion = assertSupportedCodexAppServerVersion(response);
|
|
282
284
|
this.notify("initialized");
|
|
283
285
|
this.initialized = true;
|
|
284
286
|
}
|
|
287
|
+
getServerVersion() {
|
|
288
|
+
return this.serverVersion;
|
|
289
|
+
}
|
|
285
290
|
request(method, params, options) {
|
|
286
291
|
options ??= {};
|
|
287
292
|
if (this.closed) return Promise.reject(this.closeError ?? /* @__PURE__ */ new Error("codex app-server client is closed"));
|
|
@@ -568,12 +573,13 @@ function timeoutServerRequestResponse(request) {
|
|
|
568
573
|
function assertSupportedCodexAppServerVersion(response) {
|
|
569
574
|
const detectedVersion = readCodexVersionFromUserAgent(response.userAgent);
|
|
570
575
|
if (!detectedVersion) throw new Error(`Codex app-server ${MIN_CODEX_APP_SERVER_VERSION} or newer is required, but OpenClaw could not determine the running Codex version. Update the configured Codex app-server binary, or remove custom command overrides to use the managed binary.`);
|
|
571
|
-
if (
|
|
576
|
+
if (compareCodexAppServerVersions(detectedVersion, "0.125.0") < 0) throw new Error(`Codex app-server ${MIN_CODEX_APP_SERVER_VERSION} or newer is required, but detected ${detectedVersion}. Update the configured Codex app-server binary, or remove custom command overrides to use the managed binary.`);
|
|
577
|
+
return detectedVersion;
|
|
572
578
|
}
|
|
573
579
|
function readCodexVersionFromUserAgent(userAgent) {
|
|
574
580
|
return (userAgent?.match(/^[^/]+\/(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?)(?:[\s(]|$)/))?.[1];
|
|
575
581
|
}
|
|
576
|
-
function
|
|
582
|
+
function compareCodexAppServerVersions(left, right) {
|
|
577
583
|
const leftVersion = parseVersionForComparison(left);
|
|
578
584
|
const rightVersion = parseVersionForComparison(right);
|
|
579
585
|
const leftParts = leftVersion.parts;
|
|
@@ -639,4 +645,4 @@ function formatExitValue(value) {
|
|
|
639
645
|
return "unknown";
|
|
640
646
|
}
|
|
641
647
|
//#endregion
|
|
642
|
-
export {
|
|
648
|
+
export { isCodexAppServerConnectionClosedError as a, resolveCodexAppServerSpawnEnv as c, isCodexAppServerApprovalRequest as i, CodexAppServerRpcError as n, MANAGED_CODEX_APP_SERVER_PACKAGE as o, compareCodexAppServerVersions as r, MIN_CODEX_SANDBOX_EXEC_SERVER_APP_SERVER_VERSION as s, CodexAppServerClient as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region extensions/codex/src/app-server/client-factory.ts
|
|
2
|
-
const defaultCodexAppServerClientFactory = (startOptions, authProfileId, agentDir, config) => import("./shared-client-
|
|
2
|
+
const defaultCodexAppServerClientFactory = (startOptions, authProfileId, agentDir, config) => import("./shared-client-C_RbGxW8.js").then((n) => n.a).then(({ getSharedCodexAppServerClient }) => getSharedCodexAppServerClient({
|
|
3
3
|
startOptions,
|
|
4
4
|
authProfileId,
|
|
5
5
|
agentDir,
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { a as isCodexFastServiceTier,
|
|
2
|
-
import { n as listCodexAppServerModels, t as listAllCodexAppServerModels } from "./models-
|
|
1
|
+
import { a as isCodexFastServiceTier, l as resolveCodexAppServerRuntimeOptions } from "./config-DDMrwfJl.js";
|
|
2
|
+
import { n as listCodexAppServerModels, t as listAllCodexAppServerModels } from "./models-B_uo1pf5.js";
|
|
3
3
|
import { t as isJsonObject } from "./protocol-oeJQu4rs.js";
|
|
4
|
-
import { i as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
4
|
+
import { i as readCodexAppServerBinding, o as writeCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-Bw_mfIW2.js";
|
|
5
|
+
import { i as describeControlFailure, r as CODEX_CONTROL_METHODS, t as requestCodexAppServerJson } from "./request-NklFaHM4.js";
|
|
6
|
+
import { _ as summarizeCodexAccountUsage, a as buildHelp, c as formatCodexStatus, d as formatModels, f as formatThreads, l as formatComputerUseStatus, o as formatAccount, p as readString$1, s as formatCodexDisplayText, u as formatList } from "./notification-correlation-qKY_sgga.js";
|
|
7
|
+
import { n as resolveCodexNativeExecutionBlock, r as resolveCodexNativeSandboxBlock } from "./sandbox-guard-CTnEWuor.js";
|
|
8
|
+
import { _ as steerCodexConversationTurn, b as readCodexConversationBindingData, d as parseCodexFastModeArg, f as parseCodexPermissionsModeArg, g as setCodexConversationPermissions, h as setCodexConversationModel, l as startCodexConversationThread, m as setCodexConversationFastMode, p as readCodexConversationActiveTurn, r as formatCodexCliSessions, u as formatPermissionsMode, v as stopCodexConversationTurn, x as resolveCodexDefaultWorkspaceDir, y as createCodexCliNodeConversationBindingData } from "./node-cli-sessions-yVCifOyG.js";
|
|
9
|
+
import { n as installCodexComputerUse, r as readCodexComputerUseStatus } from "./computer-use-BMMwWwno.js";
|
|
9
10
|
import { n as rememberCodexRateLimits } from "./rate-limit-cache-N66I-Rd7.js";
|
|
10
11
|
import crypto from "node:crypto";
|
|
11
12
|
import { ensureAuthProfileStore, findNormalizedProviderValue, resolveAgentDir, resolveAuthProfileEligibility, resolveAuthProfileOrder, resolveDefaultAgentDir, resolveProfileUnusableUntilForDisplay, resolveSessionAgentIds } from "openclaw/plugin-sdk/agent-runtime";
|
|
@@ -398,6 +399,8 @@ async function codexControlRequest(pluginConfig, method, requestParams, options
|
|
|
398
399
|
timeoutMs: runtime.requestTimeoutMs,
|
|
399
400
|
startOptions: runtime.start,
|
|
400
401
|
config: options.config,
|
|
402
|
+
sessionKey: options.sessionKey,
|
|
403
|
+
sessionId: options.sessionId,
|
|
401
404
|
authProfileId: options.authProfileId,
|
|
402
405
|
agentDir: options.agentDir,
|
|
403
406
|
isolated: options.isolated
|
|
@@ -477,6 +480,16 @@ const CODEX_DIAGNOSTICS_CONFIRMATION_MAX_REQUESTS_PER_SCOPE = 100;
|
|
|
477
480
|
const CODEX_DIAGNOSTICS_CONFIRMATION_MAX_SCOPES = 100;
|
|
478
481
|
const CODEX_DIAGNOSTICS_SCOPE_FIELD_MAX_CHARS = 128;
|
|
479
482
|
const CODEX_RESUME_SAFE_THREAD_ID_PATTERN = /^[A-Za-z0-9._:-]+$/;
|
|
483
|
+
const CODEX_NATIVE_EXECUTION_SUBCOMMANDS = new Set([
|
|
484
|
+
"bind",
|
|
485
|
+
"resume",
|
|
486
|
+
"steer",
|
|
487
|
+
"model",
|
|
488
|
+
"fast",
|
|
489
|
+
"permissions",
|
|
490
|
+
"compact",
|
|
491
|
+
"review"
|
|
492
|
+
]);
|
|
480
493
|
const lastCodexDiagnosticsUploadByThread = /* @__PURE__ */ new Map();
|
|
481
494
|
const lastCodexDiagnosticsUploadByScope = /* @__PURE__ */ new Map();
|
|
482
495
|
const pendingCodexDiagnosticsConfirmations = /* @__PURE__ */ new Map();
|
|
@@ -489,6 +502,8 @@ async function handleCodexSubcommand(ctx, options) {
|
|
|
489
502
|
const [subcommand = "status", ...rest] = splitArgs(ctx.args);
|
|
490
503
|
const normalized = subcommand.toLowerCase();
|
|
491
504
|
if (normalized === "help") return { text: buildHelp() };
|
|
505
|
+
const sandboxBlock = resolveCodexNativeCommandSandboxBlock(ctx, normalized, rest);
|
|
506
|
+
if (sandboxBlock) return { text: sandboxBlock };
|
|
492
507
|
if (normalized === "plugins") {
|
|
493
508
|
if (!deps.codexPluginsManagementIo) return { text: "Codex sub-plugin management is not wired up (codexPluginsManagementIo dep is undefined). Edit ~/.openclaw/openclaw.json or use `openclaw config patch` until the runtime exposes the IO." };
|
|
494
509
|
return await handleCodexPluginsSubcommand(ctx, rest, deps.codexPluginsManagementIo);
|
|
@@ -547,6 +562,48 @@ async function handleCodexSubcommand(ctx, options) {
|
|
|
547
562
|
}
|
|
548
563
|
return { text: `Unknown Codex command: ${formatCodexDisplayText(subcommand)}\n\n${buildHelp()}` };
|
|
549
564
|
}
|
|
565
|
+
function resolveCodexNativeCommandSandboxBlock(ctx, subcommand, args) {
|
|
566
|
+
if (!CODEX_NATIVE_EXECUTION_SUBCOMMANDS.has(subcommand)) return;
|
|
567
|
+
if (returnsBeforeNativeCodexExecution(subcommand, args)) return;
|
|
568
|
+
if (isCodexCliNodeResumeBind(subcommand, args)) return resolveCodexNativeSandboxBlock({
|
|
569
|
+
config: ctx.config,
|
|
570
|
+
sessionKey: ctx.sessionKey,
|
|
571
|
+
sessionId: ctx.sessionId,
|
|
572
|
+
surface: `/${["codex", subcommand].join(" ")}`
|
|
573
|
+
});
|
|
574
|
+
return resolveCodexNativeExecutionBlock({
|
|
575
|
+
config: ctx.config,
|
|
576
|
+
sessionKey: ctx.sessionKey,
|
|
577
|
+
sessionId: ctx.sessionId,
|
|
578
|
+
surface: `/${["codex", subcommand].join(" ")}`
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
function returnsBeforeNativeCodexExecution(subcommand, args) {
|
|
582
|
+
switch (subcommand) {
|
|
583
|
+
case "bind": return parseBindArgs([...args]).help === true;
|
|
584
|
+
case "resume": return returnsBeforeNativeCodexResume(args);
|
|
585
|
+
case "steer": return args.join(" ").trim() === "";
|
|
586
|
+
case "model": return args.length === 0 || args.length > 1;
|
|
587
|
+
case "fast": return args.length === 0 || args.length > 1 || parseCodexFastModeArg(args[0]) === void 0;
|
|
588
|
+
case "permissions": return args.length === 0 || args.length > 1 || parseCodexPermissionsModeArg(args[0]) === void 0;
|
|
589
|
+
case "compact":
|
|
590
|
+
case "review":
|
|
591
|
+
case "stop": return args.length > 0;
|
|
592
|
+
default: return false;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
function isCodexCliNodeResumeBind(subcommand, args) {
|
|
596
|
+
if (subcommand !== "resume") return false;
|
|
597
|
+
const parsed = parseResumeArgs([...args]);
|
|
598
|
+
return Boolean(parsed.host && parsed.threadId && parsed.bindHere === true && !parsed.help);
|
|
599
|
+
}
|
|
600
|
+
function returnsBeforeNativeCodexResume(args) {
|
|
601
|
+
const parsed = parseResumeArgs([...args]);
|
|
602
|
+
const normalizedThreadId = parsed.threadId?.trim();
|
|
603
|
+
if (parsed.help) return true;
|
|
604
|
+
if (parsed.host) return !normalizedThreadId || parsed.bindHere !== true;
|
|
605
|
+
return !normalizedThreadId || args.length !== 1;
|
|
606
|
+
}
|
|
550
607
|
async function handleComputerUseCommand(deps, pluginConfig, args) {
|
|
551
608
|
const parsed = parseComputerUseArgs(args);
|
|
552
609
|
if (parsed.help) return ["Usage: /codex computer-use [status|install] [--source <marketplace-source>] [--marketplace-path <path>] [--marketplace <name>]", "Checks or installs the configured Codex Computer Use plugin through app-server."].join("\n");
|
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { l as resolveCodexAppServerRuntimeOptions } from "./config-DDMrwfJl.js";
|
|
2
2
|
import { t as isJsonObject } from "./protocol-oeJQu4rs.js";
|
|
3
|
-
import { i as readCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-
|
|
4
|
-
import {
|
|
3
|
+
import { i as readCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-Bw_mfIW2.js";
|
|
4
|
+
import { n as resolveCodexNativeExecutionBlock } from "./sandbox-guard-CTnEWuor.js";
|
|
5
|
+
import { t as defaultCodexAppServerClientFactory } from "./client-factory-DdrIY1lw.js";
|
|
5
6
|
import { compactContextEngineWithSafetyTimeout, embeddedAgentLog, formatErrorMessage, isActiveHarnessContextEngine, resolveCompactionTimeoutMs, resolveContextEngineOwnerPluginId, runHarnessContextEngineMaintenance } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
6
7
|
//#region extensions/codex/src/app-server/compact.ts
|
|
7
8
|
const DEFAULT_CODEX_COMPACTION_WAIT_TIMEOUT_MS = 300 * 1e3;
|
|
9
|
+
const CODEX_COMPACTION_TOKEN_USAGE_GRACE_MS = 250;
|
|
10
|
+
const MAX_CODEX_NATIVE_COMPACTION_ATTEMPTS = 2;
|
|
8
11
|
const warnedIgnoredCompactionOverrides = /* @__PURE__ */ new Set();
|
|
12
|
+
var CodexNativeCompactionTimeoutError = class extends Error {
|
|
13
|
+
constructor(threadId) {
|
|
14
|
+
super(`timed out waiting for codex app-server compaction for ${threadId}`);
|
|
15
|
+
this.threadId = threadId;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
9
18
|
async function maybeCompactCodexAppServerSession(params, options = {}) {
|
|
10
19
|
const activeContextEngine = isActiveHarnessContextEngine(params.contextEngine) ? params.contextEngine : void 0;
|
|
11
20
|
if (activeContextEngine?.info.ownsCompaction) return await compactOwningContextEngine(params, activeContextEngine);
|
|
@@ -31,6 +40,8 @@ async function maybeCompactCodexAppServerSession(params, options = {}) {
|
|
|
31
40
|
return nativeResult;
|
|
32
41
|
}
|
|
33
42
|
async function compactOwningContextEngine(params, contextEngine) {
|
|
43
|
+
const compactionTarget = params.trigger === "manual" ? "threshold" : "budget";
|
|
44
|
+
const force = params.force === true || params.trigger === "manual";
|
|
34
45
|
embeddedAgentLog.info("starting context-engine-owned Codex app-server compaction", {
|
|
35
46
|
sessionId: params.sessionId,
|
|
36
47
|
sessionKey: params.sessionKey,
|
|
@@ -38,8 +49,8 @@ async function compactOwningContextEngine(params, contextEngine) {
|
|
|
38
49
|
tokenBudget: params.contextTokenBudget,
|
|
39
50
|
currentTokenCount: params.currentTokenCount,
|
|
40
51
|
trigger: params.trigger,
|
|
41
|
-
compactionTarget
|
|
42
|
-
force
|
|
52
|
+
compactionTarget,
|
|
53
|
+
force
|
|
43
54
|
});
|
|
44
55
|
let result;
|
|
45
56
|
try {
|
|
@@ -49,9 +60,9 @@ async function compactOwningContextEngine(params, contextEngine) {
|
|
|
49
60
|
sessionFile: params.sessionFile,
|
|
50
61
|
tokenBudget: params.contextTokenBudget,
|
|
51
62
|
currentTokenCount: params.currentTokenCount,
|
|
52
|
-
compactionTarget
|
|
63
|
+
compactionTarget,
|
|
53
64
|
customInstructions: params.customInstructions,
|
|
54
|
-
force
|
|
65
|
+
force,
|
|
55
66
|
runtimeContext: params.contextEngineRuntimeContext
|
|
56
67
|
}, resolveCompactionTimeoutMs(params.config), params.abortSignal);
|
|
57
68
|
} catch (error) {
|
|
@@ -87,8 +98,8 @@ async function compactOwningContextEngine(params, contextEngine) {
|
|
|
87
98
|
error: formatErrorMessage(error)
|
|
88
99
|
});
|
|
89
100
|
}
|
|
90
|
-
await clearCodexAppServerBinding(params.sessionFile);
|
|
91
|
-
if (compactedSessionFile !== params.sessionFile) await clearCodexAppServerBinding(compactedSessionFile);
|
|
101
|
+
await clearCodexAppServerBinding(params.sessionFile, { config: params.config });
|
|
102
|
+
if (compactedSessionFile !== params.sessionFile) await clearCodexAppServerBinding(compactedSessionFile, { config: params.config });
|
|
92
103
|
}
|
|
93
104
|
embeddedAgentLog.info("completed context-engine-owned Codex app-server compaction", {
|
|
94
105
|
sessionId: params.sessionId,
|
|
@@ -191,45 +202,92 @@ function readStringPath(value, path) {
|
|
|
191
202
|
return typeof current === "string" && current.trim() ? current.trim() : void 0;
|
|
192
203
|
}
|
|
193
204
|
async function compactCodexNativeThread(params, options = {}) {
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
205
|
+
const nativeExecutionBlock = resolveCodexNativeExecutionBlock({
|
|
206
|
+
config: params.config,
|
|
207
|
+
sessionKey: params.sandboxSessionKey ?? params.sessionKey,
|
|
208
|
+
sessionId: params.sessionId,
|
|
209
|
+
surface: "native compaction"
|
|
210
|
+
});
|
|
211
|
+
if (nativeExecutionBlock) return {
|
|
197
212
|
ok: false,
|
|
198
213
|
compacted: false,
|
|
199
|
-
reason:
|
|
214
|
+
reason: nativeExecutionBlock
|
|
200
215
|
};
|
|
216
|
+
const appServer = resolveCodexAppServerRuntimeOptions({ pluginConfig: options.pluginConfig });
|
|
217
|
+
const binding = await readCodexAppServerBinding(params.sessionFile, { config: params.config });
|
|
218
|
+
if (!binding?.threadId) return failedCodexThreadBindingCompactionResult(params, {
|
|
219
|
+
reason: "no codex app-server thread binding",
|
|
220
|
+
recovery: "missing_thread_binding"
|
|
221
|
+
});
|
|
201
222
|
const requestedAuthProfileId = params.authProfileId?.trim() || void 0;
|
|
202
223
|
if (requestedAuthProfileId && binding.authProfileId && binding.authProfileId !== requestedAuthProfileId) return {
|
|
203
224
|
ok: false,
|
|
204
225
|
compacted: false,
|
|
205
226
|
reason: "auth profile mismatch for session binding"
|
|
206
227
|
};
|
|
207
|
-
const
|
|
208
|
-
const waiter = createCodexNativeCompactionWaiter(client, binding.threadId);
|
|
228
|
+
const clientFactory = options.clientFactory ?? defaultCodexAppServerClientFactory;
|
|
209
229
|
let completion;
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
230
|
+
let attempt = 0;
|
|
231
|
+
for (attempt = 1; attempt <= MAX_CODEX_NATIVE_COMPACTION_ATTEMPTS; attempt += 1) {
|
|
232
|
+
const client = await clientFactory(appServer.start, requestedAuthProfileId ?? binding.authProfileId, params.agentDir, params.config);
|
|
233
|
+
const waiter = createCodexNativeCompactionWaiter(client, binding.threadId);
|
|
234
|
+
try {
|
|
235
|
+
await client.request("thread/compact/start", { threadId: binding.threadId });
|
|
236
|
+
embeddedAgentLog.info("started codex app-server compaction", {
|
|
237
|
+
sessionId: params.sessionId,
|
|
238
|
+
threadId: binding.threadId,
|
|
239
|
+
attempt
|
|
240
|
+
});
|
|
241
|
+
waiter.startTimeout();
|
|
242
|
+
completion = await waiter.promise;
|
|
243
|
+
break;
|
|
244
|
+
} catch (error) {
|
|
245
|
+
waiter.cancel();
|
|
246
|
+
if (isCodexThreadNotFoundError(error)) {
|
|
247
|
+
await clearCodexAppServerBinding(params.sessionFile, { config: params.config });
|
|
248
|
+
return failedCodexThreadBindingCompactionResult(params, {
|
|
249
|
+
threadId: binding.threadId,
|
|
250
|
+
reason: formatCompactionError(error),
|
|
251
|
+
recovery: "stale_thread_binding"
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
if (isCodexNativeCompactionTimeoutError(error, binding.threadId) && attempt < MAX_CODEX_NATIVE_COMPACTION_ATTEMPTS) {
|
|
255
|
+
restartCodexAppServerAfterNativeCompactionTimeout(client, params, binding.threadId, attempt);
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (isCodexNativeCompactionTimeoutError(error, binding.threadId)) restartCodexAppServerAfterNativeCompactionTimeout(client, params, binding.threadId, attempt);
|
|
259
|
+
return {
|
|
260
|
+
ok: false,
|
|
261
|
+
compacted: false,
|
|
262
|
+
reason: formatCompactionError(error)
|
|
263
|
+
};
|
|
264
|
+
}
|
|
225
265
|
}
|
|
266
|
+
if (!completion) return {
|
|
267
|
+
ok: false,
|
|
268
|
+
compacted: false,
|
|
269
|
+
reason: `codex app-server compaction did not complete for ${binding.threadId}`
|
|
270
|
+
};
|
|
226
271
|
embeddedAgentLog.info("completed codex app-server compaction", {
|
|
227
272
|
sessionId: params.sessionId,
|
|
228
273
|
threadId: binding.threadId,
|
|
229
274
|
signal: completion.signal,
|
|
230
275
|
turnId: completion.turnId,
|
|
231
|
-
itemId: completion.itemId
|
|
276
|
+
itemId: completion.itemId,
|
|
277
|
+
tokensAfter: completion.tokensAfter
|
|
232
278
|
});
|
|
279
|
+
const resultDetails = {
|
|
280
|
+
backend: "codex-app-server",
|
|
281
|
+
threadId: binding.threadId,
|
|
282
|
+
signal: completion.signal
|
|
283
|
+
};
|
|
284
|
+
if (completion.turnId) resultDetails.turnId = completion.turnId;
|
|
285
|
+
if (completion.itemId) resultDetails.itemId = completion.itemId;
|
|
286
|
+
if (completion.tokensAfter !== void 0) resultDetails.tokenUsageSource = "thread/tokenUsage/updated";
|
|
287
|
+
if (attempt > 1) {
|
|
288
|
+
resultDetails.compactionAttempts = attempt;
|
|
289
|
+
resultDetails.recoveredAfterAppServerRestart = true;
|
|
290
|
+
}
|
|
233
291
|
return {
|
|
234
292
|
ok: true,
|
|
235
293
|
compacted: true,
|
|
@@ -237,26 +295,57 @@ async function compactCodexNativeThread(params, options = {}) {
|
|
|
237
295
|
summary: "",
|
|
238
296
|
firstKeptEntryId: "",
|
|
239
297
|
tokensBefore: params.currentTokenCount ?? 0,
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
298
|
+
...completion.tokensAfter !== void 0 ? { tokensAfter: completion.tokensAfter } : {},
|
|
299
|
+
details: resultDetails
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
function failedCodexThreadBindingCompactionResult(params, recovery) {
|
|
304
|
+
embeddedAgentLog.warn("codex app-server compaction could not use thread binding", {
|
|
305
|
+
sessionId: params.sessionId,
|
|
306
|
+
sessionKey: params.sessionKey,
|
|
307
|
+
threadId: recovery.threadId,
|
|
308
|
+
reason: recovery.reason,
|
|
309
|
+
recovery: recovery.recovery
|
|
310
|
+
});
|
|
311
|
+
return {
|
|
312
|
+
ok: false,
|
|
313
|
+
compacted: false,
|
|
314
|
+
reason: recovery.reason,
|
|
315
|
+
failure: {
|
|
316
|
+
reason: recovery.recovery,
|
|
317
|
+
rawError: recovery.reason
|
|
247
318
|
}
|
|
248
319
|
};
|
|
249
320
|
}
|
|
321
|
+
function isCodexThreadNotFoundError(error) {
|
|
322
|
+
return formatCompactionError(error).toLowerCase().includes("thread not found");
|
|
323
|
+
}
|
|
324
|
+
function isCodexNativeCompactionTimeoutError(error, threadId) {
|
|
325
|
+
return error instanceof CodexNativeCompactionTimeoutError && error.threadId === threadId;
|
|
326
|
+
}
|
|
327
|
+
function restartCodexAppServerAfterNativeCompactionTimeout(client, params, threadId, attempt) {
|
|
328
|
+
embeddedAgentLog.warn("codex app-server compaction timed out; restarting app-server", {
|
|
329
|
+
sessionId: params.sessionId,
|
|
330
|
+
sessionKey: params.sessionKey,
|
|
331
|
+
threadId,
|
|
332
|
+
attempt,
|
|
333
|
+
maxAttempts: MAX_CODEX_NATIVE_COMPACTION_ATTEMPTS
|
|
334
|
+
});
|
|
335
|
+
client.close();
|
|
336
|
+
}
|
|
250
337
|
function createCodexNativeCompactionWaiter(client, threadId) {
|
|
251
338
|
let settled = false;
|
|
252
339
|
let removeHandler = () => {};
|
|
253
340
|
let timeout;
|
|
341
|
+
let tokenUsageGraceTimeout;
|
|
254
342
|
let failWaiter = () => {};
|
|
255
343
|
return {
|
|
256
344
|
promise: new Promise((resolve, reject) => {
|
|
257
345
|
const cleanup = () => {
|
|
258
346
|
removeHandler();
|
|
259
347
|
if (timeout) clearTimeout(timeout);
|
|
348
|
+
if (tokenUsageGraceTimeout) clearTimeout(tokenUsageGraceTimeout);
|
|
260
349
|
};
|
|
261
350
|
const complete = (completion) => {
|
|
262
351
|
if (settled) return;
|
|
@@ -270,17 +359,50 @@ function createCodexNativeCompactionWaiter(client, threadId) {
|
|
|
270
359
|
cleanup();
|
|
271
360
|
reject(error);
|
|
272
361
|
};
|
|
362
|
+
let latestTokensAfter;
|
|
363
|
+
const completionWithLatestTokenUsage = (completion) => latestTokensAfter === void 0 ? completion : {
|
|
364
|
+
...completion,
|
|
365
|
+
tokensAfter: latestTokensAfter
|
|
366
|
+
};
|
|
367
|
+
const completeAfterTokenUsageGrace = (completion) => {
|
|
368
|
+
if (settled || tokenUsageGraceTimeout) return;
|
|
369
|
+
if (timeout) {
|
|
370
|
+
clearTimeout(timeout);
|
|
371
|
+
timeout = void 0;
|
|
372
|
+
}
|
|
373
|
+
tokenUsageGraceTimeout = setTimeout(() => complete(completionWithLatestTokenUsage(observedCompletion ?? completion)), CODEX_COMPACTION_TOKEN_USAGE_GRACE_MS);
|
|
374
|
+
tokenUsageGraceTimeout.unref?.();
|
|
375
|
+
};
|
|
273
376
|
failWaiter = fail;
|
|
377
|
+
let observedCompletion;
|
|
274
378
|
const handler = (notification) => {
|
|
379
|
+
const tokensAfter = readNativeCompactionTokenUsage(notification, threadId);
|
|
380
|
+
if (tokensAfter !== void 0) {
|
|
381
|
+
latestTokensAfter = tokensAfter;
|
|
382
|
+
if (observedCompletion) {
|
|
383
|
+
complete(completionWithLatestTokenUsage(observedCompletion));
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
275
387
|
const completion = readNativeCompactionCompletion(notification, threadId);
|
|
276
|
-
if (completion)
|
|
388
|
+
if (completion) {
|
|
389
|
+
observedCompletion = completionWithLatestTokenUsage({
|
|
390
|
+
...observedCompletion,
|
|
391
|
+
...completion
|
|
392
|
+
});
|
|
393
|
+
if (latestTokensAfter !== void 0) {
|
|
394
|
+
complete(observedCompletion);
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
completeAfterTokenUsageGrace(observedCompletion);
|
|
398
|
+
}
|
|
277
399
|
};
|
|
278
400
|
removeHandler = client.addNotificationHandler(handler);
|
|
279
401
|
}),
|
|
280
402
|
startTimeout() {
|
|
281
403
|
if (settled || timeout) return;
|
|
282
404
|
timeout = setTimeout(() => {
|
|
283
|
-
failWaiter(
|
|
405
|
+
failWaiter(new CodexNativeCompactionTimeoutError(threadId));
|
|
284
406
|
}, resolveCompactionWaitTimeoutMs());
|
|
285
407
|
timeout.unref?.();
|
|
286
408
|
},
|
|
@@ -292,6 +414,30 @@ function createCodexNativeCompactionWaiter(client, threadId) {
|
|
|
292
414
|
}
|
|
293
415
|
};
|
|
294
416
|
}
|
|
417
|
+
function readNativeCompactionTokenUsage(notification, threadId) {
|
|
418
|
+
const params = notification.params;
|
|
419
|
+
if (!isJsonObject(params) || readString(params, "threadId", "thread_id") !== threadId) return;
|
|
420
|
+
if (notification.method !== "thread/tokenUsage/updated") return;
|
|
421
|
+
return readCodexTotalTokens(readCodexCurrentTokenUsage(isJsonObject(params.tokenUsage) ? params.tokenUsage : void 0) ?? readCodexCurrentTokenUsage(params));
|
|
422
|
+
}
|
|
423
|
+
function readCodexCurrentTokenUsage(value) {
|
|
424
|
+
if (!value) return;
|
|
425
|
+
for (const key of [
|
|
426
|
+
"last",
|
|
427
|
+
"current",
|
|
428
|
+
"lastCall",
|
|
429
|
+
"lastCallUsage",
|
|
430
|
+
"lastTokenUsage",
|
|
431
|
+
"last_token_usage"
|
|
432
|
+
]) {
|
|
433
|
+
const usage = value[key];
|
|
434
|
+
if (isJsonObject(usage)) return usage;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
function readCodexTotalTokens(value) {
|
|
438
|
+
const totalTokens = value?.total_tokens ?? value?.totalTokens ?? value?.total;
|
|
439
|
+
return typeof totalTokens === "number" && Number.isFinite(totalTokens) && totalTokens > 0 ? Math.floor(totalTokens) : void 0;
|
|
440
|
+
}
|
|
295
441
|
function readNativeCompactionCompletion(notification, threadId) {
|
|
296
442
|
const params = notification.params;
|
|
297
443
|
if (!isJsonObject(params) || readString(params, "threadId", "thread_id") !== threadId) return;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as describeControlFailure, t as requestCodexAppServerJson } from "./request-
|
|
1
|
+
import { l as resolveCodexAppServerRuntimeOptions, u as resolveCodexComputerUseConfig } from "./config-DDMrwfJl.js";
|
|
2
|
+
import { i as describeControlFailure, t as requestCodexAppServerJson } from "./request-NklFaHM4.js";
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
4
|
//#region extensions/codex/src/app-server/computer-use.ts
|
|
5
5
|
var CodexComputerUseSetupError = class extends Error {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHmac, randomBytes } from "node:crypto";
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { hostname } from "node:os";
|
|
4
|
+
import { detectWindowsSpawnCommandInlineArgs } from "openclaw/plugin-sdk/windows-spawn";
|
|
4
5
|
import { z } from "zod";
|
|
5
6
|
//#region extensions/codex/src/app-server/config.ts
|
|
6
7
|
const START_OPTIONS_KEY_SECRET_SYMBOL = Symbol.for("openclaw.codexAppServerStartOptionsKeySecret");
|
|
@@ -31,6 +32,7 @@ const codexAppServerApprovalsReviewerSchema = z.enum([
|
|
|
31
32
|
]);
|
|
32
33
|
const codexDynamicToolsLoadingSchema = z.enum(["searchable", "direct"]);
|
|
33
34
|
const codexAppServerServiceTierSchema = z.preprocess((value) => value === null ? null : normalizeCodexServiceTier(value), z.string().trim().min(1).nullable().optional()).optional();
|
|
35
|
+
const codexAppServerExperimentalSchema = z.object({ sandboxExecServer: z.boolean().optional() }).strict();
|
|
34
36
|
const codexPluginEntryConfigSchema = z.object({
|
|
35
37
|
enabled: z.boolean().optional(),
|
|
36
38
|
marketplaceName: z.literal(CODEX_PLUGINS_MARKETPLACE_NAME).optional(),
|
|
@@ -72,11 +74,13 @@ const codexPluginConfigSchema = z.object({
|
|
|
72
74
|
codeModeOnly: z.boolean().optional(),
|
|
73
75
|
requestTimeoutMs: z.number().positive().optional(),
|
|
74
76
|
turnCompletionIdleTimeoutMs: z.number().positive().optional(),
|
|
77
|
+
postToolRawAssistantCompletionIdleTimeoutMs: z.number().positive().optional(),
|
|
75
78
|
approvalPolicy: codexAppServerApprovalPolicySchema.optional(),
|
|
76
79
|
sandbox: codexAppServerSandboxSchema.optional(),
|
|
77
80
|
approvalsReviewer: codexAppServerApprovalsReviewerSchema.optional(),
|
|
78
81
|
serviceTier: codexAppServerServiceTierSchema,
|
|
79
|
-
defaultWorkspaceDir: z.string().optional()
|
|
82
|
+
defaultWorkspaceDir: z.string().optional(),
|
|
83
|
+
experimental: codexAppServerExperimentalSchema.optional()
|
|
80
84
|
}).strict().optional()
|
|
81
85
|
}).strict();
|
|
82
86
|
function readCodexPluginConfig(value) {
|
|
@@ -90,6 +94,16 @@ function readCodexPluginConfig(value) {
|
|
|
90
94
|
...plugins.data ? { codexPlugins: plugins.data } : {}
|
|
91
95
|
};
|
|
92
96
|
}
|
|
97
|
+
function isCodexSandboxExecServerEnabled(pluginConfig) {
|
|
98
|
+
return readCodexPluginConfig(pluginConfig).appServer?.experimental?.sandboxExecServer === true;
|
|
99
|
+
}
|
|
100
|
+
function assertCodexAppServerCommandHasNoInlineArgs(params) {
|
|
101
|
+
const inlineArgs = detectWindowsSpawnCommandInlineArgs(params.command);
|
|
102
|
+
if (!inlineArgs) return;
|
|
103
|
+
const sourceLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_BIN" : "plugins.entries.codex.config.appServer.command";
|
|
104
|
+
const argsLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_ARGS" : "plugins.entries.codex.config.appServer.args";
|
|
105
|
+
throw new Error(`${sourceLabel} must be only the Codex app-server executable path; "${inlineArgs.executable}" was configured with inline arguments "${inlineArgs.arguments}". Move those arguments to ${argsLabel}, or remove the override to use the managed Codex startup path.`);
|
|
106
|
+
}
|
|
93
107
|
function resolveCodexPluginsPolicy(pluginConfig) {
|
|
94
108
|
const config = readCodexPluginConfig(pluginConfig).codexPlugins;
|
|
95
109
|
const configured = config !== void 0;
|
|
@@ -119,6 +133,10 @@ function resolveCodexAppServerRuntimeOptions(params = {}) {
|
|
|
119
133
|
const envCommand = readNonEmptyString(env.OPENCLAW_CODEX_APP_SERVER_BIN);
|
|
120
134
|
const command = configCommand ?? envCommand ?? "codex";
|
|
121
135
|
const commandSource = configCommand ? "config" : envCommand ? "env" : "managed";
|
|
136
|
+
if (commandSource === "config" || commandSource === "env") assertCodexAppServerCommandHasNoInlineArgs({
|
|
137
|
+
command,
|
|
138
|
+
source: commandSource
|
|
139
|
+
});
|
|
122
140
|
const args = resolveArgs(config.args, env.OPENCLAW_CODEX_APP_SERVER_ARGS);
|
|
123
141
|
const headers = normalizeHeaders(config.headers);
|
|
124
142
|
const clearEnv = normalizeStringList(config.clearEnv);
|
|
@@ -155,6 +173,7 @@ function resolveCodexAppServerRuntimeOptions(params = {}) {
|
|
|
155
173
|
codeModeOnly: config.codeModeOnly === true,
|
|
156
174
|
requestTimeoutMs: normalizePositiveNumber(config.requestTimeoutMs, 6e4),
|
|
157
175
|
turnCompletionIdleTimeoutMs: normalizePositiveNumber(config.turnCompletionIdleTimeoutMs, 6e4),
|
|
176
|
+
...config.postToolRawAssistantCompletionIdleTimeoutMs !== void 0 ? { postToolRawAssistantCompletionIdleTimeoutMs: normalizePositiveNumber(config.postToolRawAssistantCompletionIdleTimeoutMs, 6e4) } : {},
|
|
158
177
|
approvalPolicy: resolveApprovalPolicy(config.approvalPolicy) ?? resolveApprovalPolicy(env.OPENCLAW_CODEX_APP_SERVER_APPROVAL_POLICY) ?? defaultPolicy?.approvalPolicy ?? (policyMode === "guardian" ? "on-request" : "never"),
|
|
159
178
|
sandbox: resolveSandbox(config.sandbox) ?? resolveSandbox(env.OPENCLAW_CODEX_APP_SERVER_SANDBOX) ?? defaultPolicy?.sandbox ?? (policyMode === "guardian" ? "workspace-write" : "danger-full-access"),
|
|
160
179
|
approvalsReviewer: resolveApprovalsReviewer(config.approvalsReviewer) ?? defaultPolicy?.approvalsReviewer ?? (policyMode === "guardian" ? "auto_review" : "user"),
|
|
@@ -507,4 +526,4 @@ function splitShellWords(value) {
|
|
|
507
526
|
return words;
|
|
508
527
|
}
|
|
509
528
|
//#endregion
|
|
510
|
-
export { isCodexFastServiceTier as a,
|
|
529
|
+
export { isCodexFastServiceTier as a, readCodexPluginConfig as c, resolveCodexPluginsPolicy as d, withMcpElicitationsApprovalPolicy as f, isCodexAppServerApprovalPolicyAllowedByRequirements as i, resolveCodexAppServerRuntimeOptions as l, codexAppServerStartOptionsKey as n, isCodexSandboxExecServerEnabled as o, codexSandboxPolicyForTurn as r, normalizeCodexServiceTier as s, CODEX_PLUGINS_MARKETPLACE_NAME as t, resolveCodexComputerUseConfig as u };
|