@openclaw/codex 2026.5.20 → 2026.5.24-beta.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.
Files changed (28) hide show
  1. package/dist/{client-Ab4Fw77C.js → client-1sSy4p3z.js} +25 -16
  2. package/dist/{client-factory-BbesECdh.js → client-factory-Bk6i4FnW.js} +1 -1
  3. package/dist/{command-handlers-Gceg_rBZ.js → command-handlers-CcTABuem.js} +64 -7
  4. package/dist/{compact-BaSDurdH.js → compact-DnTgL6UT.js} +186 -40
  5. package/dist/{computer-use-B4iTog6z.js → computer-use-Hdq1WgTA.js} +2 -2
  6. package/dist/{config-DqIp6oTk.js → config-DDMrwfJl.js} +21 -2
  7. package/dist/dynamic-tools-Bq717oJR.js +497 -0
  8. package/dist/harness.js +15 -5
  9. package/dist/index.js +10 -9
  10. package/dist/media-understanding-provider.js +6 -3
  11. package/dist/{models-C8MdOXGD.js → models-DtGLkqMP.js} +1 -1
  12. package/dist/{node-cli-sessions-T1olB1SH.js → node-cli-sessions-9CAqnIaA.js} +23 -9
  13. package/dist/{command-formatters-BVBnEgyA.js → notification-correlation-qKY_sgga.js} +66 -15
  14. package/dist/provider-catalog.js +26 -41
  15. package/dist/provider.js +4 -4
  16. package/dist/{request-BePR77QD.js → request-D93E78SA.js} +12 -3
  17. package/dist/{run-attempt-CRHVB240.js → run-attempt-CT1N__qp.js} +3828 -1391
  18. package/dist/sandbox-guard-CTnEWuor.js +233 -0
  19. package/dist/{session-binding-DEiYHgJ_.js → session-binding-Bw_mfIW2.js} +4 -2
  20. package/dist/{shared-client-DCxJx5QU.js → shared-client-CFCUGEVs.js} +2 -2
  21. package/dist/{side-question-DlJAUYst.js → side-question-CYFMTA1O.js} +20 -15
  22. package/dist/test-api.js +4 -2
  23. package/dist/{thread-lifecycle-Cgi62SSl.js → thread-lifecycle-DGoaguJh.js} +628 -592
  24. package/dist/{vision-tools-B2wt6ecs.js → vision-tools-DOnxzH2y.js} +7 -3
  25. package/npm-shrinkwrap.json +1934 -0
  26. package/openclaw.plugin.json +29 -0
  27. package/package.json +8 -6
  28. package/dist/plugin-activation-BkQkPLOY.js +0 -452
@@ -1,9 +1,9 @@
1
- import { c as resolveCodexAppServerRuntimeOptions } from "./config-DqIp6oTk.js";
1
+ import { l as resolveCodexAppServerRuntimeOptions } from "./config-DDMrwfJl.js";
2
2
  import { n as isRpcResponse } from "./protocol-oeJQu4rs.js";
3
- import { createInterface } from "node:readline";
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
- assertSupportedCodexAppServerVersion(await this.request("initialize", {
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"));
@@ -335,7 +340,7 @@ var CodexAppServerClient = class CodexAppServerClient {
335
340
  return;
336
341
  }
337
342
  try {
338
- this.writeMessage(message);
343
+ this.writeMessage(message, (error) => rejectPending(error));
339
344
  } catch (error) {
340
345
  rejectPending(error instanceof Error ? error : new Error(String(error)));
341
346
  }
@@ -367,16 +372,19 @@ var CodexAppServerClient = class CodexAppServerClient {
367
372
  this.markClosed(/* @__PURE__ */ new Error("codex app-server client is closed"));
368
373
  await closeCodexAppServerTransportAndWait(this.child, options);
369
374
  }
370
- writeMessage(message) {
375
+ writeMessage(message, onError) {
371
376
  if (this.closed) return;
372
377
  const id = "id" in message ? message.id : void 0;
373
378
  const method = "method" in message ? message.method : void 0;
374
379
  this.child.stdin.write(`${stringifyCodexAppServerMessage(message)}\n`, (error) => {
375
- if (error) embeddedAgentLog.warn("codex app-server write failed", {
376
- error,
377
- id,
378
- method
379
- });
380
+ if (error) {
381
+ embeddedAgentLog.warn("codex app-server write failed", {
382
+ error,
383
+ id,
384
+ method
385
+ });
386
+ onError?.(error);
387
+ }
380
388
  });
381
389
  }
382
390
  handleLine(line) {
@@ -413,7 +421,7 @@ var CodexAppServerClient = class CodexAppServerClient {
413
421
  parsed = JSON.parse(candidate);
414
422
  } catch (error) {
415
423
  const lineCount = pending.lineCount + 1;
416
- if (candidate.length <= CODEX_APP_SERVER_PARSE_BUFFER_MAX && lineCount <= CODEX_APP_SERVER_PARSE_BUFFER_MAX_LINES) {
424
+ if (shouldBufferCodexAppServerParseFailure(candidate.trim(), error) && candidate.length <= CODEX_APP_SERVER_PARSE_BUFFER_MAX && lineCount <= CODEX_APP_SERVER_PARSE_BUFFER_MAX_LINES) {
417
425
  this.pendingParse = {
418
426
  text: candidate,
419
427
  lineCount,
@@ -568,12 +576,13 @@ function timeoutServerRequestResponse(request) {
568
576
  function assertSupportedCodexAppServerVersion(response) {
569
577
  const detectedVersion = readCodexVersionFromUserAgent(response.userAgent);
570
578
  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 (compareVersions(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.`);
579
+ 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.`);
580
+ return detectedVersion;
572
581
  }
573
582
  function readCodexVersionFromUserAgent(userAgent) {
574
583
  return (userAgent?.match(/^[^/]+\/(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?)(?:[\s(]|$)/))?.[1];
575
584
  }
576
- function compareVersions(left, right) {
585
+ function compareCodexAppServerVersions(left, right) {
577
586
  const leftVersion = parseVersionForComparison(left);
578
587
  const rightVersion = parseVersionForComparison(right);
579
588
  const leftParts = leftVersion.parts;
@@ -639,4 +648,4 @@ function formatExitValue(value) {
639
648
  return "unknown";
640
649
  }
641
650
  //#endregion
642
- export { MANAGED_CODEX_APP_SERVER_PACKAGE as a, isCodexAppServerConnectionClosedError as i, CodexAppServerRpcError as n, resolveCodexAppServerSpawnEnv as o, isCodexAppServerApprovalRequest as r, CodexAppServerClient as t };
651
+ 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-DCxJx5QU.js").then((n) => n.a).then(({ getSharedCodexAppServerClient }) => getSharedCodexAppServerClient({
2
+ const defaultCodexAppServerClientFactory = (startOptions, authProfileId, agentDir, config) => import("./shared-client-CFCUGEVs.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, c as resolveCodexAppServerRuntimeOptions } from "./config-DqIp6oTk.js";
2
- import { n as listCodexAppServerModels, t as listAllCodexAppServerModels } from "./models-C8MdOXGD.js";
1
+ import { a as isCodexFastServiceTier, l as resolveCodexAppServerRuntimeOptions } from "./config-DDMrwfJl.js";
2
+ import { n as listCodexAppServerModels, t as listAllCodexAppServerModels } from "./models-DtGLkqMP.js";
3
3
  import { t as isJsonObject } from "./protocol-oeJQu4rs.js";
4
- import { i as describeControlFailure, r as CODEX_CONTROL_METHODS, t as requestCodexAppServerJson } from "./request-BePR77QD.js";
5
- import { a as formatComputerUseStatus, c as formatThreads, i as formatCodexStatus, l as readString$1, n as formatAccount, o as formatList, p as summarizeCodexAccountUsage, r as formatCodexDisplayText, s as formatModels, t as buildHelp } from "./command-formatters-BVBnEgyA.js";
6
- import { i as readCodexAppServerBinding, o as writeCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-DEiYHgJ_.js";
7
- 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-T1olB1SH.js";
8
- import { n as installCodexComputerUse, r as readCodexComputerUseStatus } from "./computer-use-B4iTog6z.js";
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-D93E78SA.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-9CAqnIaA.js";
9
+ import { n as installCodexComputerUse, r as readCodexComputerUseStatus } from "./computer-use-Hdq1WgTA.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 { c as resolveCodexAppServerRuntimeOptions } from "./config-DqIp6oTk.js";
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-DEiYHgJ_.js";
4
- import { t as defaultCodexAppServerClientFactory } from "./client-factory-BbesECdh.js";
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-Bk6i4FnW.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: params.trigger === "manual" ? "threshold" : "budget",
42
- force: params.trigger === "manual"
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: params.trigger === "manual" ? "threshold" : "budget",
63
+ compactionTarget,
53
64
  customInstructions: params.customInstructions,
54
- force: params.trigger === "manual",
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 appServer = resolveCodexAppServerRuntimeOptions({ pluginConfig: options.pluginConfig });
195
- const binding = await readCodexAppServerBinding(params.sessionFile, { config: params.config });
196
- if (!binding?.threadId) return {
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: "no codex app-server thread binding"
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 client = await (options.clientFactory ?? defaultCodexAppServerClientFactory)(appServer.start, requestedAuthProfileId ?? binding.authProfileId, params.agentDir, params.config);
208
- const waiter = createCodexNativeCompactionWaiter(client, binding.threadId);
228
+ const clientFactory = options.clientFactory ?? defaultCodexAppServerClientFactory;
209
229
  let completion;
210
- try {
211
- await client.request("thread/compact/start", { threadId: binding.threadId });
212
- embeddedAgentLog.info("started codex app-server compaction", {
213
- sessionId: params.sessionId,
214
- threadId: binding.threadId
215
- });
216
- waiter.startTimeout();
217
- completion = await waiter.promise;
218
- } catch (error) {
219
- waiter.cancel();
220
- return {
221
- ok: false,
222
- compacted: false,
223
- reason: formatCompactionError(error)
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
- details: {
241
- backend: "codex-app-server",
242
- threadId: binding.threadId,
243
- signal: completion.signal,
244
- turnId: completion.turnId,
245
- itemId: completion.itemId
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) complete(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(/* @__PURE__ */ new Error(`timed out waiting for codex app-server compaction for ${threadId}`));
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 { c as resolveCodexAppServerRuntimeOptions, l as resolveCodexComputerUseConfig } from "./config-DqIp6oTk.js";
2
- import { i as describeControlFailure, t as requestCodexAppServerJson } from "./request-BePR77QD.js";
1
+ import { l as resolveCodexAppServerRuntimeOptions, u as resolveCodexComputerUseConfig } from "./config-DDMrwfJl.js";
2
+ import { i as describeControlFailure, t as requestCodexAppServerJson } from "./request-D93E78SA.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, resolveCodexAppServerRuntimeOptions as c, withMcpElicitationsApprovalPolicy as d, isCodexAppServerApprovalPolicyAllowedByRequirements as i, resolveCodexComputerUseConfig as l, codexAppServerStartOptionsKey as n, normalizeCodexServiceTier as o, codexSandboxPolicyForTurn as r, readCodexPluginConfig as s, CODEX_PLUGINS_MARKETPLACE_NAME as t, resolveCodexPluginsPolicy as u };
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 };