@openclaw/codex 2026.9.4 → 2026.9.6

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 (160) hide show
  1. package/assets/activity.svg +30 -0
  2. package/assets/icon.png +0 -0
  3. package/dist/.setup/account-usage-runtime-Eem_WGqY.mjs +75 -0
  4. package/dist/{apply-CvT8tW5i.js → .setup/apply-DDOi8uNx.mjs} +24 -30
  5. package/dist/.setup/async-questions-DdhOCwGi.mjs +27 -0
  6. package/dist/{attempt-client-cleanup-DKHzbwt5.js → .setup/attempt-client-cleanup-CEv1cKwF.mjs} +79 -49
  7. package/dist/.setup/attempt-terminal-gZrxQ35N.mjs +5 -0
  8. package/dist/.setup/attempt-workspace-context-DUVEn_CS.mjs +331 -0
  9. package/dist/{auth-binding-CWlKVccJ.js → .setup/auth-binding-DhLWa_7K.mjs} +1 -1
  10. package/dist/{auth-cache-key-7orQae_j.js → .setup/auth-cache-key-B2mpaI9D.mjs} +9 -81
  11. package/dist/{auth-profile-CwzO4_RG.js → .setup/auth-profile-WqZtZfXN.mjs} +1 -1
  12. package/dist/.setup/auth-profile-health-oHizqgye.mjs +53 -0
  13. package/dist/.setup/auth-profile-recovery-BREezV0L.mjs +14 -0
  14. package/dist/.setup/binding-connection-ThoatDcb.mjs +50 -0
  15. package/dist/.setup/binding-connection.runtime-yoHrABt-.mjs +48 -0
  16. package/dist/{bounded-turn-C_Hneydj.js → .setup/bounded-turn-B2HScEgT.mjs} +143 -32
  17. package/dist/{build-state-BCmg9-5p.js → .setup/build-state-C7EnDVgr.mjs} +1 -1
  18. package/dist/{capabilities-8vx68WLH.js → .setup/capabilities-CDXOOFdZ.mjs} +1 -1
  19. package/dist/{client-B57KWPQx.js → .setup/client-Cs08OXVQ.mjs} +705 -512
  20. package/dist/.setup/client-catalog-response-BMgt_4q4.mjs +285 -0
  21. package/dist/{command-dispatch-BpduNGVf.js → .setup/command-dispatch-B4JuOsOk.mjs} +8 -4
  22. package/dist/{command-formatters-lxlkNZgU.js → .setup/command-formatters-Bmqvr9tO.mjs} +8 -4
  23. package/dist/{command-handlers-tiL9iWj7.js → .setup/command-handlers-DW7Lx9oH.mjs} +137 -186
  24. package/dist/{command-rpc-CR5EOEZX.js → .setup/command-rpc-DixIj3HW.mjs} +47 -23
  25. package/dist/{compact-B_H3AOd7.js → .setup/compact-Du5UvtxA.mjs} +29 -51
  26. package/dist/{config-oIORaQ5T.js → .setup/config-BoTP_mrL.mjs} +5 -4
  27. package/dist/{config-options-CXMq1T-C.js → .setup/config-options-BvaRs51b.mjs} +50 -446
  28. package/dist/{protocol-5bh1G-H7.js → .setup/config-parsing-CcB9iPoq.mjs} +9 -51
  29. package/dist/{config-runtime-D0zGNIHu.js → .setup/config-runtime-C8Rw1m1m.mjs} +2 -2
  30. package/dist/.setup/config-security-BEReZ6go.mjs +380 -0
  31. package/dist/{conversation-binding-DsB4-O7U.js → .setup/conversation-binding-DP-gMrBP.mjs} +29 -38
  32. package/dist/{conversation-binding-data-BiodpIzq.js → .setup/conversation-binding-data-CrcyZk6O.mjs} +1 -1
  33. package/dist/{conversation-control-CtUu1b3m.js → .setup/conversation-control-uK9Jomlc.mjs} +32 -67
  34. package/dist/.setup/cyber-failover-DYwbmf1o.mjs +123 -0
  35. package/dist/.setup/cyber-failover-notice-e9G3J9-e.mjs +17 -0
  36. package/dist/{dynamic-tools-CmN5RAip.js → .setup/dynamic-tools-BDXl-8Cw.mjs} +936 -620
  37. package/dist/{effective-mcp-catalog-Bd73bqA8.js → .setup/effective-mcp-catalog-CvnvnGIe.mjs} +3 -3
  38. package/dist/{ephemeral-turn-D78_VmzO.js → .setup/ephemeral-turn-poidXgek.mjs} +9 -7
  39. package/dist/{event-projector-assistant-message-BmBM4qBV.js → .setup/event-projector-assistant-message-BsruvNrH.mjs} +8 -7
  40. package/dist/{event-projector-items-5VhsECCO.js → .setup/event-projector-items-C6L_5ZiT.mjs} +42 -8
  41. package/dist/{attempt-notifications-C9XufG6l.js → .setup/event-projector-usage-CnBS8Wa3.mjs} +102 -9
  42. package/dist/{harness-C7rRa7bm.js → .setup/harness-a_MsE4-_.mjs} +81 -21
  43. package/dist/{inference-context-Dr_mzvk4.js → .setup/inference-context-D96l9-ew.mjs} +1 -1
  44. package/dist/.setup/inference-proxy-b-aJMSxm.mjs +601 -0
  45. package/dist/{isolated-completion-DWVb5U2J.js → .setup/isolated-completion-BIZFhTNG.mjs} +18 -11
  46. package/dist/.setup/launch-args-DbFCehO7.mjs +196 -0
  47. package/dist/{managed-binary-D22rNEcR.js → .setup/managed-binary-BnshlFag.mjs} +14 -3
  48. package/dist/{managed-thread-store-D1t5jh3G.js → .setup/managed-thread-store-BMqgThVL.mjs} +48 -14
  49. package/dist/{model-catalog-Dq2n8f_p.js → .setup/model-catalog-CfXJf9Ay.mjs} +36 -12
  50. package/dist/{models-PCKOim-h.js → .setup/models-KnqBv0hE.mjs} +3 -3
  51. package/dist/.setup/native-auth-rWbGbMn3.mjs +57 -0
  52. package/dist/{native-subagent-history-DjtPloaU.js → .setup/native-subagent-history-0nYYgo0k.mjs} +43 -35
  53. package/dist/.setup/native-subagent-monitor-D3filLY2.mjs +4859 -0
  54. package/dist/{native-subagent-task-ids-BzTdT0Uw.js → .setup/native-subagent-task-ids-wb8CKZGN.mjs} +98 -44
  55. package/dist/{node-cli-sessions-DKaOmVUh.js → .setup/node-cli-sessions-r3avj02l.mjs} +86 -68
  56. package/dist/.setup/node-exec-server.runtime-BDwWXVpK.mjs +247 -0
  57. package/dist/{plan-7uG-Fp36.js → .setup/plan-CN3VwfNU.mjs} +133 -119
  58. package/dist/{plugin-activation-BYQculil.js → .setup/plugin-activation-DT3MNtqj.mjs} +7 -16
  59. package/dist/{plugin-app-cache-key-d0eKxy7b.js → .setup/plugin-app-cache-key-B2CsSdnV.mjs} +32 -44
  60. package/dist/{plugin-approval-roundtrip-Bz3FT8W5.js → .setup/plugin-approval-roundtrip-C0MZzCuP.mjs} +1 -1
  61. package/dist/{plugin-inventory-oL4Na1ZG.js → .setup/plugin-inventory-BoRei8Z4.mjs} +21 -11
  62. package/dist/{plugin-marketplace-discovery-P-Vndfqq.js → .setup/plugin-marketplace-discovery-CDOi8IFs.mjs} +4 -1
  63. package/dist/{plugin-metadata-cache-ClPJpRio.js → .setup/plugin-metadata-cache-Ctmo83k_.mjs} +226 -141
  64. package/dist/.setup/protocol-CANUwXJ3.mjs +17 -0
  65. package/dist/{provider-MQ8PVkuE.js → .setup/provider-BOsxQHOM.mjs} +9 -5
  66. package/dist/{provider-capabilities-BvCUL69A.js → .setup/provider-capabilities-BfE88FZ5.mjs} +31 -3
  67. package/dist/{rate-limits-CBMmWBr9.js → .setup/rate-limits-CMU3DUD0.mjs} +174 -151
  68. package/dist/{request-B7hEkBGq.js → .setup/request-D2L0zMrq.mjs} +130 -42
  69. package/dist/{run-attempt-CvsAAGa0.js → .setup/run-attempt-BHu11r7h.mjs} +1628 -966
  70. package/dist/.setup/run-attempt-lifecycle-B7JbY4-F.mjs +71 -0
  71. package/dist/{runtime-artifact-BJ0rXBZ_.js → .setup/runtime-artifact-CLZ8udh-.mjs} +29 -45
  72. package/dist/{sandbox-guard-BxgyoM8M.js → .setup/sandbox-guard-C2sRMOEY.mjs} +3 -3
  73. package/dist/{session-binding-CI8UuilT.js → .setup/session-binding-Cm0apEbd.mjs} +36 -83
  74. package/dist/{session-binding-record-Bcvslnhf.js → .setup/session-binding-record-BGoz8wOK.mjs} +202 -5
  75. package/dist/.setup/session-binding-sidecars-BlB5EvIS.mjs +546 -0
  76. package/dist/.setup/session-catalog-Pno1xGcl.mjs +2764 -0
  77. package/dist/{session-catalog-adoption-tcZi1IfX.js → .setup/session-catalog-adoption-BI6UTDZT.mjs} +58 -26
  78. package/dist/{session-catalog-archive-CwKg8Xz2.js → .setup/session-catalog-archive-lHBqzhaO.mjs} +6 -6
  79. package/dist/.setup/session-catalog-events-Bj6j94E_.mjs +347 -0
  80. package/dist/.setup/session-catalog-index-B9_VQIUz.mjs +1170 -0
  81. package/dist/.setup/session-catalog-index-order-hcdz07yN.mjs +48 -0
  82. package/dist/.setup/session-catalog-index-state-Dgh8ORJm.mjs +183 -0
  83. package/dist/{thread-history-page-D0JIp48V.js → .setup/session-catalog-native-projection-DowriLid.mjs} +223 -95
  84. package/dist/{session-catalog-node-adoption-B1tgDW-m.js → .setup/session-catalog-node-adoption-ITddWx_X.mjs} +25 -13
  85. package/dist/{session-catalog-node-continue-Ci-DXyJP.js → .setup/session-catalog-node-continue-6g6qi4A9.mjs} +24 -15
  86. package/dist/.setup/session-catalog-projection-zK_PUsiE.mjs +422 -0
  87. package/dist/{session-cli-DNN_jhGc.js → .setup/session-cli-irrD-uo7.mjs} +3 -3
  88. package/dist/{session-history-Cz-tOOYj.js → .setup/session-history-BrqhSCf9.mjs} +19 -19
  89. package/dist/{session-history-import-DwyijFI6.js → .setup/session-history-import-D-3wAgOP.mjs} +4 -4
  90. package/dist/{session-history-read-cxPUxyVV.js → .setup/session-history-read-B3ZfSUbF.mjs} +2 -2
  91. package/dist/{session-history.worker-BeK1YOyT.js → .setup/session-history.worker-CaCh0xF_.mjs} +10 -24
  92. package/dist/{session-initialization-Ct0_Hzmg.js → .setup/session-initialization-rcgbZiid.mjs} +2 -2
  93. package/dist/{session-permission-policy-BBmXA8Eg.js → .setup/session-permission-policy-BI1QK_98.mjs} +2 -2
  94. package/dist/{session-retirement-B2YfbAAT.js → .setup/session-retirement-BH-S6qkJ.mjs} +26 -7
  95. package/dist/{settled-turn-context-Du6gdUDd.js → .setup/settled-turn-context-fmwouT5I.mjs} +2 -2
  96. package/dist/{settled-turn-finalizer-Dn91stmc.js → .setup/settled-turn-finalizer-DiAi6Kx6.mjs} +12 -12
  97. package/dist/{shared-client-CscigXXL.js → .setup/shared-client-DA4VR4Eb.mjs} +332 -221
  98. package/dist/{side-question-BGMJQf4U.js → .setup/side-question-BJ1wSDcB.mjs} +183 -230
  99. package/dist/{source-CElXU0Oy.js → .setup/source-CUzJq5WN.mjs} +11 -10
  100. package/dist/.setup/spawn-error-CL3n6MAa.mjs +57 -0
  101. package/dist/{thread-archive-guard-DfpBr-Sz.js → .setup/thread-archive-guard-C9frICzX.mjs} +10 -3
  102. package/dist/.setup/thread-history-page-DoVpnHim.mjs +83 -0
  103. package/dist/{thread-lifecycle-DXl1-I6b.js → .setup/thread-lifecycle-B3mfz1TG.mjs} +347 -2318
  104. package/dist/{thread-ownership-BsDRTsyp.js → .setup/thread-ownership-DcTtAcXj.mjs} +6 -4
  105. package/dist/{thread-policy-BuEQfE0g.js → .setup/thread-policy-DGuQsuFC.mjs} +19 -3
  106. package/dist/.setup/thread-requests-BLvGkP2R.mjs +2205 -0
  107. package/dist/{thread-resume-DsDOZpFg.js → .setup/thread-resume-DIBXwOpE.mjs} +8 -5
  108. package/dist/.setup/timeout-C910MdAB.mjs +80 -0
  109. package/dist/{transcript-history-projection-v17wXgdK.js → .setup/transcript-history-projection-ZZpkFkJ_.mjs} +96 -61
  110. package/dist/{transcript-mirror-C5CKgNy6.js → .setup/transcript-mirror-BtHDBp1G.mjs} +224 -195
  111. package/dist/{transcript-mirror-attestation-DibE0krH.js → .setup/transcript-mirror-attestation-CzM-94NC.mjs} +4 -1
  112. package/dist/{transport-stdio-BGjHoYLr.js → .setup/transport-stdio-h2VHOskC.mjs} +274 -89
  113. package/dist/{upstream-session-fork-BZerMte_.js → .setup/upstream-session-fork-BUr4OUbC.mjs} +51 -42
  114. package/dist/{usage-tCk-mg_x.js → .setup/usage-BML0r-ua.mjs} +5 -4
  115. package/dist/.setup/usage-limit-error-DUMbefVY.mjs +166 -0
  116. package/dist/{web-search-provider.runtime-B7bGbGWq.js → .setup/web-search-provider.runtime-CDKlN-Rv.mjs} +4 -3
  117. package/dist/api.js +23 -12
  118. package/dist/catalog-page-worker-entrypoint.js +12 -0
  119. package/dist/catalog-page.worker.js +9 -0
  120. package/dist/cli-metadata.js +1 -1
  121. package/dist/doctor-contract-api.js +8 -528
  122. package/dist/harness.js +1 -1
  123. package/dist/index.js +306 -215
  124. package/dist/media-understanding-provider.js +3 -3
  125. package/dist/migration-provider-api.js +1 -1
  126. package/dist/native-tool-policy.js +12 -0
  127. package/dist/provider-discovery.js +18 -0
  128. package/dist/session-history-worker-runtime.js +36 -35
  129. package/dist/session-history.worker.js +2 -2
  130. package/dist/web-search-contract-api.js +1 -1
  131. package/openclaw.plugin.json +354 -69
  132. package/package.json +14 -8
  133. package/dist/attempt-context-D44yeDII.js +0 -636
  134. package/dist/binding-connection-D3udKbIE.js +0 -60
  135. package/dist/event-projector-usage-BfXmpOec.js +0 -102
  136. package/dist/inference-proxy-HGXKUIre.js +0 -311
  137. package/dist/launch-args-RXQwn8zV.js +0 -90
  138. package/dist/native-subagent-history-owner-Pcp7JuVF.js +0 -34
  139. package/dist/native-subagent-monitor-fQ7eIXEf.js +0 -2978
  140. package/dist/node-exec-server.runtime-Cl2vapEi.js +0 -226
  141. package/dist/rpc-error-ttN_QjEm.js +0 -30
  142. package/dist/session-catalog-ct-AH01I.js +0 -1477
  143. package/dist/session-catalog-home-id-CwhLdC03.js +0 -18
  144. package/dist/session-catalog-provenance-D-dIfRAH.js +0 -96
  145. package/dist/timeout-BVw8aaM1.js +0 -33
  146. package/dist/version-omm6IPI3.js +0 -12
  147. /package/dist/{auth-profile-selection-DFu9e167.js → .setup/auth-profile-selection-DFu9e167.mjs} +0 -0
  148. /package/dist/{config-utils-DujwEnhg.js → .setup/config-utils-DujwEnhg.mjs} +0 -0
  149. /package/dist/{context-compaction-activity-CMla5FPJ.js → .setup/context-compaction-activity-CMla5FPJ.mjs} +0 -0
  150. /package/dist/{elicitation-input-DPoK8F7w.js → .setup/elicitation-input-DPoK8F7w.mjs} +0 -0
  151. /package/dist/{history-rejection-B4nOXNXF.js → .setup/history-rejection-B4nOXNXF.mjs} +0 -0
  152. /package/dist/{image-payload-sanitizer-tupAr-2o.js → .setup/image-payload-sanitizer-tupAr-2o.mjs} +0 -0
  153. /package/dist/{incognito-session-uhrBF6wJ.js → .setup/incognito-session-uhrBF6wJ.mjs} +0 -0
  154. /package/dist/{local-runtime-attribution-B_2mnqhb.js → .setup/local-runtime-attribution-B_2mnqhb.mjs} +0 -0
  155. /package/dist/{native-execution-policy-umd0tgh4.js → .setup/native-execution-policy-umd0tgh4.mjs} +0 -0
  156. /package/dist/{rolldown-runtime-8H4AJuhK.js → .setup/rolldown-runtime-8H4AJuhK.mjs} +0 -0
  157. /package/dist/{session-binding-meta-B7aEMU7g.js → .setup/session-binding-meta-B7aEMU7g.mjs} +0 -0
  158. /package/dist/{session-upstream-marker-D15C9NHp.js → .setup/session-upstream-marker-D15C9NHp.mjs} +0 -0
  159. /package/dist/{upstream-prompt-provenance-LphB8slG.js → .setup/upstream-prompt-provenance-LphB8slG.mjs} +0 -0
  160. /package/dist/{web-search-provider.shared-BrZmlqyR.js → .setup/web-search-provider.shared-BrZmlqyR.mjs} +0 -0
@@ -1,9 +1,18 @@
1
- import { n as normalizeCodexAppServerArgs } from "./launch-args-RXQwn8zV.js";
1
+ import { r as normalizeCodexAppServerArgs } from "./launch-args-DbFCehO7.mjs";
2
+ import { i as resolveManagedCodexNativeCommand } from "./managed-binary-BnshlFag.mjs";
3
+ import { i as recordCodexAppServerSpawnFailure, r as getCodexAppServerSpawnFailure } from "./spawn-error-CL3n6MAa.mjs";
2
4
  import { createHash, randomUUID } from "node:crypto";
5
+ import { stripVTControlCharacters } from "node:util";
6
+ import { embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-registration";
3
7
  import { z } from "zod";
4
8
  import { materializeWindowsSpawnProgram, resolveWindowsSpawnProgram } from "openclaw/plugin-sdk/windows-spawn";
9
+ import { closeSync, constants, openSync, readSync } from "node:fs";
10
+ import path from "node:path";
5
11
  import { readFile, readdir } from "node:fs/promises";
12
+ import { resolveGlobalSingleton } from "openclaw/plugin-sdk/global-singleton";
6
13
  import { once } from "node:events";
14
+ import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
15
+ import { resolveStateDir } from "openclaw/plugin-sdk/state-paths";
7
16
  import { execFile, spawn } from "node:child_process";
8
17
  import { setImmediate } from "node:timers/promises";
9
18
  import { finished } from "node:stream/promises";
@@ -15,6 +24,32 @@ function isDeadProcessState(state) {
15
24
  const PROCESS_COLUMNS = "pid=,ppid=,pgid=,stat=,lstart=";
16
25
  const MAX_PROCESS_CONTAINMENT_MS$1 = 2e3;
17
26
  const PROCESS_INSPECTION_MAX_BYTES = 8388608;
27
+ const PROCFS_COMMAND_PERMISSION_EXIT = 77;
28
+ const PROCFS_COMMAND_READER = `
29
+ const fs = require("node:fs");
30
+ const [pid, maxBytes] = process.argv.slice(-2).map(Number);
31
+ try {
32
+ const fd = fs.openSync("/proc/" + pid + "/cmdline", "r");
33
+ const buffer = Buffer.alloc(4096);
34
+ const chunks = [];
35
+ let bytes = 0;
36
+ try {
37
+ for (;;) {
38
+ const count = fs.readSync(fd, buffer, 0, Math.min(buffer.length, maxBytes - bytes + 1), null);
39
+ if (count === 0) break;
40
+ bytes += count;
41
+ if (bytes > maxBytes) throw new Error("Command byte limit exceeded");
42
+ chunks.push(Buffer.from(buffer.subarray(0, count)));
43
+ }
44
+ } finally {
45
+ fs.closeSync(fd);
46
+ }
47
+ process.stdout.end(Buffer.concat(chunks, bytes));
48
+ } catch (error) {
49
+ process.exitCode = ["EACCES", "EPERM", "ERR_ACCESS_DENIED"].includes(error?.code)
50
+ ? ${PROCFS_COMMAND_PERMISSION_EXIT} : 1;
51
+ }
52
+ `;
18
53
  var ProcessInspectionError = class extends Error {
19
54
  constructor(reason) {
20
55
  const detail = {
@@ -56,17 +91,11 @@ async function readCodexAppServerProcessCommand(observed, deadline) {
56
91
  if (process.platform === "linux") {
57
92
  let pending = false;
58
93
  do {
59
- const remainingMs = deadline - Date.now();
60
- if (remainingMs <= 0) throw new ProcessInspectionError("deadline");
61
- let command;
62
- try {
63
- command = await readFile(`/proc/${observed.pid}/cmdline`, {
64
- encoding: "utf8",
65
- signal: AbortSignal.timeout(remainingMs)
66
- });
67
- } catch (error) {
68
- throw inspectionFailure(error);
69
- }
94
+ if (deadline - Date.now() <= 0) throw new ProcessInspectionError("deadline");
95
+ const command = await readProcessOutput({
96
+ kind: "procfs-command",
97
+ pid: observed.pid
98
+ }, deadline);
70
99
  if (!command || pending) {
71
100
  const current = await readCodexAppServerProcess(observed.pid, deadline);
72
101
  if (!current || current.startedAt !== observed.startedAt || current.ppid !== observed.ppid || current.pgid !== observed.pgid || current.state.startsWith("Z")) throw new ProcessInspectionError("unavailable");
@@ -75,20 +104,26 @@ async function readCodexAppServerProcessCommand(observed, deadline) {
75
104
  pending = command.length === 0;
76
105
  if (pending) await setImmediate();
77
106
  } while (pending);
78
- } else output = (await readProcessOutput([
79
- "-o",
80
- "command=",
81
- "-p",
82
- String(observed.pid)
83
- ], deadline)).split("\n")[0]?.trim() ?? "";
107
+ } else output = (await readProcessOutput({
108
+ kind: "ps",
109
+ args: [
110
+ "-o",
111
+ "command=",
112
+ "-p",
113
+ String(observed.pid)
114
+ ]
115
+ }, deadline)).split("\n")[0]?.trim() ?? "";
84
116
  if (Date.now() >= deadline) throw new ProcessInspectionError("deadline");
85
117
  if (!output) throw new ProcessInspectionError("unavailable");
86
118
  return output;
87
119
  }
88
120
  async function readProcesses(args, deadline, selected = false) {
89
- return parseProcesses(await readProcessOutput(args, deadline), selected);
121
+ return parseProcesses(await readProcessOutput({
122
+ kind: "ps",
123
+ args
124
+ }, deadline), selected);
90
125
  }
91
- async function readProcessOutput(args, deadline) {
126
+ async function readProcessOutput(command, deadline) {
92
127
  const remainingMs = deadline - Date.now();
93
128
  if (remainingMs <= 0) throw new ProcessInspectionError("deadline");
94
129
  return await new Promise((resolve, reject) => {
@@ -100,16 +135,24 @@ async function readProcessOutput(args, deadline) {
100
135
  if (output instanceof ProcessInspectionError) reject(output);
101
136
  else resolve(output);
102
137
  };
103
- const inspector = execFile("ps", args, {
138
+ const procfs = command.kind === "procfs-command";
139
+ const inspector = execFile(procfs ? process.execPath : "ps", procfs ? [
140
+ ...process.versions.bun ? ["--no-env-file", "--config=/dev/null"] : [],
141
+ "-e",
142
+ PROCFS_COMMAND_READER,
143
+ String(command.pid),
144
+ String(PROCESS_INSPECTION_MAX_BYTES)
145
+ ] : command.args, {
104
146
  encoding: "utf8",
105
147
  maxBuffer: PROCESS_INSPECTION_MAX_BYTES,
106
- env: {
148
+ cwd: procfs ? "/" : void 0,
149
+ env: procfs ? {} : {
107
150
  ...process.env,
108
151
  LC_ALL: "C",
109
152
  TZ: "UTC"
110
153
  }
111
154
  }, (error, stdout) => {
112
- settle(Date.now() >= deadline ? new ProcessInspectionError("deadline") : error ? inspectionFailure(error) : stdout);
155
+ settle(Date.now() >= deadline ? new ProcessInspectionError("deadline") : error ? procfs && error.code === PROCFS_COMMAND_PERMISSION_EXIT ? new ProcessInspectionError("permission") : inspectionFailure(error) : stdout);
113
156
  });
114
157
  const timer = setTimeout(() => {
115
158
  settle(new ProcessInspectionError("deadline"));
@@ -154,6 +197,7 @@ function parseProcesses(output, selected) {
154
197
  return rows;
155
198
  }
156
199
  async function readLinuxProcesses(selected, deadline) {
200
+ if (selected !== void 0) return readSelectedLinuxProcesses(selected, deadline);
157
201
  const remainingMs = deadline - Date.now();
158
202
  if (remainingMs <= 0) throw new ProcessInspectionError("deadline");
159
203
  const options = {
@@ -161,9 +205,8 @@ async function readLinuxProcesses(selected, deadline) {
161
205
  signal: AbortSignal.timeout(remainingMs)
162
206
  };
163
207
  try {
164
- const bootId = (await readFile("/proc/sys/kernel/random/boot_id", options)).trim();
165
- if (!/^[a-f0-9-]{36}$/.test(bootId)) throw new ProcessInspectionError("unavailable");
166
- const pids = selected === void 0 ? await readdir("/proc") : selected.map(String);
208
+ const bootId = parseLinuxBootId(await readFile("/proc/sys/kernel/random/boot_id", options));
209
+ const pids = await readdir("/proc");
167
210
  const rows = [];
168
211
  let bytes = 0;
169
212
  for (const entry of pids) {
@@ -176,23 +219,81 @@ async function readLinuxProcesses(selected, deadline) {
176
219
  if (stat === void 0) continue;
177
220
  bytes += stat.length;
178
221
  if (bytes > PROCESS_INSPECTION_MAX_BYTES) throw new ProcessInspectionError("unavailable");
179
- const commEnd = stat.lastIndexOf(")");
180
- const fields = stat.slice(commEnd + 1).trim().split(/\s+/);
181
- const ppid = Number(fields[1]);
182
- const pgid = Number(fields[2]);
183
- const startTicks = fields[19];
184
- if (commEnd < 0 || ![ppid, pgid].every(Number.isSafeInteger) || selected !== void 0 && (pgid <= 0 || ppid < 0) || !/^\d+$/.test(startTicks ?? "")) throw new ProcessInspectionError("unavailable");
185
- if (pgid > 0) {
186
- const threads = Number(fields[17]);
187
- if (!/^[1-9]\d*$/.test(fields[17] ?? "") || !Number.isSafeInteger(threads)) throw new ProcessInspectionError("unavailable");
188
- rows.push({
189
- pid: Number(entry),
190
- ppid,
191
- pgid,
192
- state: `${fields[0]}${threads > 1 ? "l" : ""}`,
193
- startedAt: `${bootId}:${startTicks}`
194
- });
222
+ const row = parseLinuxProcess(stat, entry, bootId, false);
223
+ if (row) rows.push(row);
224
+ }
225
+ if (Date.now() >= deadline) throw new ProcessInspectionError("deadline");
226
+ return rows;
227
+ } catch (error) {
228
+ throw inspectionFailure(error);
229
+ }
230
+ }
231
+ function parseLinuxBootId(value) {
232
+ const bootId = value.trim();
233
+ if (!/^[a-f0-9-]{36}$/.test(bootId)) throw new ProcessInspectionError("unavailable");
234
+ return bootId;
235
+ }
236
+ function parseLinuxProcess(stat, entry, bootId, selected) {
237
+ const commEnd = stat.lastIndexOf(")");
238
+ const fields = stat.slice(commEnd + 1).trim().split(/\s+/);
239
+ const ppid = Number(fields[1]);
240
+ const pgid = Number(fields[2]);
241
+ const startTicks = fields[19];
242
+ if (commEnd < 0 || ![ppid, pgid].every(Number.isSafeInteger) || selected && (pgid <= 0 || ppid < 0) || !/^\d+$/.test(startTicks ?? "")) throw new ProcessInspectionError("unavailable");
243
+ if (pgid > 0) {
244
+ const threads = Number(fields[17]);
245
+ if (!/^[1-9]\d*$/.test(fields[17] ?? "") || !Number.isSafeInteger(threads)) throw new ProcessInspectionError("unavailable");
246
+ return {
247
+ pid: Number(entry),
248
+ ppid,
249
+ pgid,
250
+ state: `${fields[0]}${threads > 1 ? "l" : ""}`,
251
+ startedAt: `${bootId}:${startTicks}`
252
+ };
253
+ }
254
+ }
255
+ /** Known procfs identities must not queue behind unrelated libuv filesystem work. */
256
+ function readSelectedProcFile(file, deadline, maxBytes = PROCESS_INSPECTION_MAX_BYTES) {
257
+ if (Date.now() >= deadline) throw new ProcessInspectionError("deadline");
258
+ const fd = openSync(file, constants.O_RDONLY | constants.O_NONBLOCK);
259
+ const chunks = [];
260
+ const buffer = Buffer.alloc(Math.min(4096, maxBytes + 1));
261
+ let bytes = 0;
262
+ try {
263
+ for (;;) {
264
+ if (Date.now() >= deadline) throw new ProcessInspectionError("deadline");
265
+ const count = readSync(fd, buffer, {
266
+ offset: 0,
267
+ length: Math.min(buffer.length, maxBytes - bytes + 1),
268
+ position: null
269
+ });
270
+ if (Date.now() >= deadline) throw new ProcessInspectionError("deadline");
271
+ if (count === 0) return Buffer.concat(chunks, bytes);
272
+ bytes += count;
273
+ if (bytes > maxBytes) throw new ProcessInspectionError("unavailable");
274
+ chunks.push(Buffer.from(buffer.subarray(0, count)));
275
+ }
276
+ } finally {
277
+ closeSync(fd);
278
+ }
279
+ }
280
+ function readSelectedLinuxProcesses(selected, deadline) {
281
+ try {
282
+ const bootId = parseLinuxBootId(readSelectedProcFile("/proc/sys/kernel/random/boot_id", deadline).toString("utf8"));
283
+ const rows = [];
284
+ let bytes = 0;
285
+ for (const entry of selected.map(String)) {
286
+ if (!/^\d+$/.test(entry)) continue;
287
+ let stat;
288
+ try {
289
+ stat = readSelectedProcFile(`/proc/${entry}/stat`, deadline, PROCESS_INSPECTION_MAX_BYTES - bytes);
290
+ } catch (error) {
291
+ if (error && typeof error === "object" && "code" in error && (error.code === "ENOENT" || error.code === "ESRCH")) continue;
292
+ throw error;
195
293
  }
294
+ bytes += stat.length;
295
+ const row = parseLinuxProcess(stat.toString("utf8"), entry, bootId, true);
296
+ if (row) rows.push(row);
196
297
  }
197
298
  if (Date.now() >= deadline) throw new ProcessInspectionError("deadline");
198
299
  return rows;
@@ -208,6 +309,8 @@ const MAX_PROCESS_QUIESCE_PASSES = 16;
208
309
  /** Discharges the registered root obligation, including an already-obsolete PID. */
209
310
  async function terminateCodexAppServerOrphan(expected) {
210
311
  const deadline = Date.now() + MAX_PROCESS_CONTAINMENT_MS;
312
+ const initial = (await readCodexAppServerProcessSnapshot(deadline, [expected.pid])).find((row) => row.pid === expected.pid);
313
+ if (!initial || !hasSameIdentity(initial, expected) || isDeadProcessState(initial.state)) return true;
211
314
  const result = await terminateCodexAppServerDescendants({
212
315
  pid: expected.pid,
213
316
  kill: (signal) => signalProcess(expected.pid, signal ?? "SIGTERM")
@@ -220,7 +323,7 @@ async function terminateCodexAppServerOrphan(expected) {
220
323
  if (current && isSameLiveRoot(current, contained.root, true)) signalProcess(current.pgid === current.pid ? -current.pid : current.pid, "SIGKILL");
221
324
  }
222
325
  while (Date.now() < deadline) {
223
- const snapshot = await readCodexAppServerProcessSnapshot(deadline).catch(() => void 0);
326
+ const snapshot = await readCodexAppServerProcessSnapshot(deadline, [expected.pid]).catch(() => void 0);
224
327
  if (!snapshot?.some((row) => row.pid === process.pid)) return false;
225
328
  const current = snapshot.find((row) => row.pid === expected.pid);
226
329
  if (!current || !hasSameIdentity(current, expected) || isDeadProcessState(current.state)) {
@@ -437,21 +540,37 @@ const registrationSchema = z.object({
437
540
  parent: processIdentity,
438
541
  child: childIdentity
439
542
  }).strict();
543
+ const registrationCleanup = /* @__PURE__ */ new WeakMap();
544
+ const processReaper = resolveGlobalSingleton(Symbol.for("openclaw.codexAppServerProcessReaper"), () => new KeyedAsyncQueue());
545
+ /** Join bookkeeping after the transport owner has observed physical exit. */
546
+ async function waitForCodexAppServerProcessRegistrationCleanup(child) {
547
+ await registrationCleanup.get(child);
548
+ }
440
549
  function fingerprintProcessCommand(command) {
441
550
  return createHash("sha256").update(command).digest("hex");
442
551
  }
443
552
  async function openProcessRegistrationStore() {
444
- const { createPluginStateSyncKeyedStore } = await import("openclaw/plugin-sdk/plugin-state-store-runtime");
445
- return createPluginStateSyncKeyedStore("codex", {
553
+ const env = {
554
+ ...process.env,
555
+ OPENCLAW_STATE_DIR: resolveStateDir()
556
+ };
557
+ const { createPluginStateKeyedStore } = await import("openclaw/plugin-sdk/plugin-state-store-runtime");
558
+ return createPluginStateKeyedStore("codex", {
446
559
  namespace: "app-server-processes",
447
560
  maxEntries: 512,
448
- overflowPolicy: "reject-new"
561
+ overflowPolicy: "reject-new",
562
+ env
449
563
  });
450
564
  }
451
565
  async function reapRegisteredCodexAppServerOrphans() {
452
566
  const store = await openProcessRegistrationStore();
567
+ await processReaper.enqueue("orphans", () => sweepRegisteredCodexAppServerOrphans(store));
568
+ return store;
569
+ }
570
+ async function sweepRegisteredCodexAppServerOrphans(store) {
571
+ const entries = await store.entries();
453
572
  const deadline = Date.now() + PROCESS_REGISTRATION_INSPECTION_MS;
454
- for (const entry of store.entries()) {
573
+ for (const entry of entries) {
455
574
  if (Date.now() >= deadline) throw new Error("Codex orphan cleanup exceeded its startup budget. Retry to finish cleanup.");
456
575
  const registration = registrationSchema.parse(entry.value);
457
576
  const snapshot = await readCodexAppServerProcessSnapshot(deadline, [registration.parent.pid, registration.child.pid]);
@@ -463,29 +582,34 @@ async function reapRegisteredCodexAppServerOrphans() {
463
582
  try {
464
583
  command = await readCodexAppServerProcessCommand(child, deadline);
465
584
  } catch (error) {
466
- if ((await readCodexAppServerProcessSnapshot(deadline, [registration.child.pid])).find((row) => row.pid === registration.child.pid)?.startedAt === registration.child.startedAt) throw error;
585
+ const current = (await readCodexAppServerProcessSnapshot(deadline, [registration.child.pid])).find((row) => row.pid === registration.child.pid);
586
+ if (current?.startedAt === registration.child.startedAt && !isDeadProcessState(current.state)) throw error;
467
587
  }
468
588
  if (command !== void 0 && fingerprintProcessCommand(command) !== registration.child.commandFingerprint) {
469
- store.delete(entry.key);
589
+ await store.delete(entry.key);
470
590
  continue;
471
591
  }
472
592
  }
473
593
  if (!await terminateCodexAppServerOrphan(registration.child)) throw new Error(`Cannot reap registered Codex process ${registration.child.pid}. Stop it before retrying.`);
474
- store.delete(entry.key);
594
+ await store.delete(entry.key);
475
595
  }
476
596
  }
477
597
  function createCodexAppServerProcessReaperService() {
598
+ let pendingSweep;
478
599
  return {
479
600
  id: "codex-app-server-process-reaper",
480
601
  start(ctx) {
481
602
  if (process.platform === "win32") return;
482
- (async () => {
603
+ pendingSweep = (async () => {
483
604
  try {
484
605
  await reapRegisteredCodexAppServerOrphans();
485
606
  } catch (error) {
486
607
  ctx.logger.warn(`Codex app-server orphan cleanup failed: ${String(error)}`);
487
608
  }
488
609
  })();
610
+ },
611
+ async stop() {
612
+ await pendingSweep;
489
613
  }
490
614
  };
491
615
  }
@@ -494,8 +618,7 @@ async function prepareCodexAppServerProcessRegistration() {
494
618
  if (process.platform === "win32") return async (child) => {
495
619
  await once(child, "spawn");
496
620
  };
497
- await reapRegisteredCodexAppServerOrphans();
498
- const store = await openProcessRegistrationStore();
621
+ const store = await reapRegisteredCodexAppServerOrphans();
499
622
  return async (child) => {
500
623
  await once(child, "spawn");
501
624
  if (!child.pid) throw new ProcessInspectionError("unavailable");
@@ -507,19 +630,61 @@ async function prepareCodexAppServerProcessRegistration() {
507
630
  const command = await readCodexAppServerProcessCommand(spawned, deadline);
508
631
  if (child.exitCode !== null || child.signalCode !== null) throw new Error("Cannot register the Codex child process command: the child exited during inspection. Retry.");
509
632
  const key = randomUUID();
510
- store.register(key, {
633
+ const value = {
511
634
  parent: processIdentity.parse(parent),
512
635
  child: childIdentity.parse({
513
636
  ...spawned,
514
637
  commandFingerprint: fingerprintProcessCommand(command)
515
638
  })
639
+ };
640
+ const exited = new Promise((resolve) => {
641
+ child.once("exit", () => resolve());
516
642
  });
517
- child.once("exit", () => {
643
+ const registered = store.register(key, value);
644
+ const cleanup = (async () => {
645
+ await exited;
646
+ await registered.catch(() => void 0);
518
647
  try {
519
- store.delete(key);
648
+ await store.delete(key);
520
649
  } catch {}
521
- });
650
+ })();
651
+ registrationCleanup.set(child, cleanup);
652
+ await registered;
653
+ if (child.exitCode !== null || child.signalCode !== null) {
654
+ await cleanup;
655
+ throw new Error("Cannot register the Codex child process: the child exited during registration. Retry.");
656
+ }
657
+ };
658
+ }
659
+ //#endregion
660
+ //#region extensions/codex/src/app-server/managed-launcher-failure.ts
661
+ /** The official npm launcher prints Node's native spawn error and exits before initialization. */
662
+ function observeManagedCodexLauncherFailure(child, nativeCommand) {
663
+ let prefix = "";
664
+ let launchCode;
665
+ const startupFailure = { complete() {
666
+ child.stderr.off("data", onData);
667
+ child.off("exit", onExit);
668
+ prefix = "";
669
+ } };
670
+ const onData = (chunk) => {
671
+ if (launchCode || prefix.length >= 16384) return;
672
+ prefix = (prefix + stripVTControlCharacters(chunk.toString())).slice(0, 16384);
673
+ if (/\bError: spawn\b/u.test(prefix) && /syscall: ['"]spawn(?: [^'"\r\n]*)?['"]/u.test(prefix)) launchCode = /\bcode: ['"](ENOENT|EACCES|EBADARCH|Unknown system error -86)['"]/u.exec(prefix)?.[1];
674
+ else if (/Error: Missing optional dependency @openai\/codex-[\w-]+\. Reinstall Codex:/u.test(prefix)) launchCode = "ENOENT";
675
+ };
676
+ const onExit = (code) => {
677
+ startupFailure.complete();
678
+ if (code !== 1 || !launchCode) return;
679
+ const described = recordCodexAppServerSpawnFailure(Object.assign(/* @__PURE__ */ new Error(`spawn ${launchCode}`), {
680
+ code: launchCode,
681
+ syscall: "spawn"
682
+ }), nativeCommand, nativeCommand);
683
+ if (described instanceof Error) startupFailure.error = described;
522
684
  };
685
+ child.stderr.on("data", onData);
686
+ child.once("exit", onExit);
687
+ Object.assign(child, { startupFailure });
523
688
  }
524
689
  //#endregion
525
690
  //#region extensions/codex/src/app-server/transport.ts
@@ -602,6 +767,7 @@ async function closeCodexAppServerTransportAndWait(child, options = {}) {
602
767
  const closure = beginCodexAppServerTransportClose(child, options);
603
768
  const containment = await closure.closing;
604
769
  const settled = await waitForCodexAppServerTransportExit(child, options.exitTimeoutMs ?? 2e3, drained);
770
+ if (settled) await waitForCodexAppServerProcessRegistrationCleanup(child);
605
771
  closure.naturalExit = containment === "natural" && settled;
606
772
  if (options.drainStdio) {
607
773
  child.stdout.destroy?.();
@@ -662,29 +828,29 @@ const RUNTIME_INJECTION_ENVIRONMENT_KEYS = /* @__PURE__ */ new Set([
662
828
  "LD_PRELOAD"
663
829
  ]);
664
830
  const QA_PARENT_PID_ENV = "OPENCLAW_QA_PARENT_PID";
665
- const DEFAULT_SPAWN_RUNTIME = {
666
- platform: process.platform,
667
- env: process.env,
668
- execPath: process.execPath
669
- };
670
831
  /** Resolves the concrete command/argv/shell settings used to spawn Codex app-server. */
671
- function resolveCodexAppServerSpawnInvocation(options, runtime = DEFAULT_SPAWN_RUNTIME) {
832
+ function resolveCodexAppServerSpawnInvocation(options, env) {
672
833
  if (options.commandSource === "managed") throw new Error("Managed Codex app-server start options must be resolved before spawn.");
673
834
  const program = resolveWindowsSpawnProgram({
674
835
  command: options.command,
675
- platform: runtime.platform,
676
- env: runtime.env,
677
- execPath: runtime.execPath,
836
+ platform: process.platform,
837
+ env,
838
+ execPath: process.execPath,
678
839
  packageName: "@openai/codex"
679
840
  });
680
841
  const args = normalizeCodexAppServerArgs(options.args);
681
842
  const resolved = materializeWindowsSpawnProgram(program, args);
682
- return {
683
- command: resolved.command,
684
- args: resolved.argv,
685
- shell: resolved.shell,
686
- windowsHide: resolved.windowsHide
843
+ if (options.commandSource === "resolved-managed" && resolved.resolution === "direct" && [
844
+ ".cjs",
845
+ ".js",
846
+ ".mjs"
847
+ ].includes(path.extname(resolved.command).toLowerCase())) return {
848
+ ...resolved,
849
+ command: process.execPath,
850
+ argv: [resolved.command, ...resolved.argv],
851
+ resolution: "node-entrypoint"
687
852
  };
853
+ return resolved;
688
854
  }
689
855
  /** Merges app-server environment overrides while honoring clearEnv and unsafe key filtering. */
690
856
  function resolveCodexAppServerSpawnEnv(options, baseEnv = process.env, platform = process.platform) {
@@ -724,26 +890,45 @@ function copySafeEnvironmentEntries(target, source) {
724
890
  /** Spawns the Codex app-server process and returns the shared transport interface. */
725
891
  async function createStdioTransport(options, baseEnv = process.env, assertCurrent, onSpawn) {
726
892
  const env = resolveCodexAppServerSpawnEnv(options, baseEnv);
727
- const invocation = resolveCodexAppServerSpawnInvocation(options, {
728
- platform: process.platform,
729
- env,
730
- execPath: process.execPath
731
- });
893
+ const invocation = resolveCodexAppServerSpawnInvocation(options, env);
894
+ const nativeCommand = options.commandSource === "resolved-managed" ? resolveManagedCodexNativeCommand(options.command, { pathExists: () => true }) : void 0;
895
+ const launchKey = JSON.stringify([
896
+ invocation.command,
897
+ options.cwd ?? process.cwd(),
898
+ nativeCommand ?? null,
899
+ path.isAbsolute(invocation.command) ? null : env.PATH ?? env.Path
900
+ ]);
901
+ const previousFailure = getCodexAppServerSpawnFailure(launchKey) ?? (nativeCommand ? getCodexAppServerSpawnFailure(nativeCommand) : void 0);
902
+ if (previousFailure) throw previousFailure;
732
903
  const register = await prepareCodexAppServerProcessRegistration();
733
904
  assertCurrent?.();
734
- const child = spawn(invocation.command, invocation.args, {
735
- ...options.cwd !== void 0 ? { cwd: options.cwd } : {},
736
- env,
737
- detached: resolveCodexAppServerDetachedMode(env),
738
- shell: invocation.shell,
739
- stdio: [
740
- "pipe",
741
- "pipe",
742
- "pipe"
743
- ],
744
- windowsHide: invocation.windowsHide
905
+ embeddedAgentLog.debug("Codex app-server spawn", {
906
+ command: invocation.command,
907
+ launcher: options.command,
908
+ ...options.cwd ? { cwd: options.cwd } : {},
909
+ ...nativeCommand ? { nativeCommand } : {},
910
+ platform: process.platform,
911
+ arch: process.arch
745
912
  });
913
+ let child;
914
+ try {
915
+ child = spawn(invocation.command, invocation.argv, {
916
+ ...options.cwd !== void 0 ? { cwd: options.cwd } : {},
917
+ env,
918
+ detached: resolveCodexAppServerDetachedMode(env),
919
+ shell: invocation.shell,
920
+ stdio: [
921
+ "pipe",
922
+ "pipe",
923
+ "pipe"
924
+ ],
925
+ windowsHide: invocation.windowsHide
926
+ });
927
+ } catch (error) {
928
+ throw recordCodexAppServerSpawnFailure(error, invocation.command, launchKey);
929
+ }
746
930
  try {
931
+ if (nativeCommand && invocation.resolution === "node-entrypoint") observeManagedCodexLauncherFailure(child, nativeCommand);
747
932
  onSpawn?.(child);
748
933
  await register(child);
749
934
  assertCurrent?.();
@@ -751,8 +936,8 @@ async function createStdioTransport(options, baseEnv = process.env, assertCurren
751
936
  } catch (error) {
752
937
  await closeCodexAppServerTransportAndWait(child, { drainStdio: true });
753
938
  assertCurrent?.();
754
- throw error;
939
+ throw child.startupFailure?.error ?? recordCodexAppServerSpawnFailure(error, invocation.command, launchKey);
755
940
  }
756
941
  }
757
942
  //#endregion
758
- export { hasCodexAppServerNaturalExit as a, closeCodexAppServerTransportAndWait as i, resolveCodexAppServerSpawnEnv as n, createCodexAppServerProcessReaperService as o, closeCodexAppServerTransport as r, createStdioTransport as t };
943
+ export { closeCodexAppServerTransportAndWait as a, closeCodexAppServerTransport as i, resolveCodexAppServerSpawnEnv as n, hasCodexAppServerNaturalExit as o, resolveCodexAppServerSpawnInvocation as r, createCodexAppServerProcessReaperService as s, createStdioTransport as t };