@openclaw/codex 2026.9.2 → 2026.9.3

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 (108) hide show
  1. package/README.md +2 -0
  2. package/dist/api.js +14 -19
  3. package/dist/apply-B6el6hdO.js +357 -0
  4. package/dist/{attempt-client-cleanup-Bp1ZOnk2.js → attempt-client-cleanup-D6cR54TV.js} +39 -19
  5. package/dist/{attempt-context-CSazkWns.js → attempt-context-AO4DSjE0.js} +8 -6
  6. package/dist/{event-projector-usage-ZqEVbAEY.js → attempt-notifications--H8zXR5-.js} +3 -106
  7. package/dist/auth-cache-key-Kq6oerr6.js +498 -0
  8. package/dist/auth-profile-CwzO4_RG.js +43 -0
  9. package/dist/auth-profile-selection-DFu9e167.js +45 -0
  10. package/dist/binding-connection-QqgcPCgk.js +60 -0
  11. package/dist/{bounded-turn-DxGJRYbY.js → bounded-turn-lRpmZHFv.js} +25 -122
  12. package/dist/build-state-6RL6qohz.js +19 -0
  13. package/dist/{capabilities-B1mgvpP8.js → capabilities-BeqLPbtM.js} +1 -1
  14. package/dist/cli-metadata.js +1 -1
  15. package/dist/client-BEKu4yDx.js +3983 -0
  16. package/dist/command-dispatch-CisT9Jqq.js +21 -0
  17. package/dist/{command-formatters-DSbGMXA0.js → command-formatters-DeTfrapr.js} +2 -2
  18. package/dist/{command-handlers-DOJvGv6-.js → command-handlers-BfIsJEuA.js} +31 -21
  19. package/dist/command-rpc-BMqRQOFX.js +226 -0
  20. package/dist/{compact-Y_xBqrHN.js → compact-CGJZ2rlb.js} +19 -14
  21. package/dist/config-JDfTI4VI.js +106 -0
  22. package/dist/{config-CyapYSji.js → config-options-jnIFvwxD.js} +204 -592
  23. package/dist/config-runtime-BWf6JLWG.js +11 -0
  24. package/dist/conversation-binding-CxOlHiix.js +889 -0
  25. package/dist/{plugin-marketplace-discovery-B7gHXJ3d.js → conversation-control-CUCrSIQI.js} +10 -142
  26. package/dist/doctor-contract-api.js +5 -5
  27. package/dist/{dynamic-tools-BwpvTxaX.js → dynamic-tools-D-JBoaLt.js} +66 -70
  28. package/dist/{effective-mcp-catalog-CY9Jn4bA.js → effective-mcp-catalog-J_5Ep5Um.js} +3 -3
  29. package/dist/{elicitation-input-DMkeki8d.js → elicitation-input-DPoK8F7w.js} +8 -22
  30. package/dist/ephemeral-turn-DSwzP8YY.js +101 -0
  31. package/dist/{event-projector-assistant-message-B9kp6iGC.js → event-projector-assistant-message-BmBM4qBV.js} +12 -25
  32. package/dist/event-projector-usage-CIyrYYid.js +102 -0
  33. package/dist/{harness-Czh2Sdoc.js → harness-FR6eQgyO.js} +31 -24
  34. package/dist/harness.js +1 -1
  35. package/dist/history-rejection-B4nOXNXF.js +13 -0
  36. package/dist/incognito-session-uhrBF6wJ.js +15 -0
  37. package/dist/index.js +411 -2875
  38. package/dist/{isolated-completion-CRh-51AK.js → isolated-completion-DHBefrzg.js} +7 -4
  39. package/dist/launch-args-RXQwn8zV.js +90 -0
  40. package/dist/{managed-binary-DcpnJF9x.js → managed-binary-DrjjRRUD.js} +4 -103
  41. package/dist/managed-thread-store-D1t5jh3G.js +66 -0
  42. package/dist/media-understanding-provider.js +4 -1
  43. package/dist/{model-catalog-DT5vo6qo.js → model-catalog-B_6M04Wo.js} +6 -5
  44. package/dist/{models-CcrgSMQR.js → models-P9k2qAof.js} +3 -3
  45. package/dist/native-execution-policy-umd0tgh4.js +128 -0
  46. package/dist/{native-subagent-monitor-B3bvQGcg.js → native-subagent-monitor-BbCUKRwC.js} +69 -42
  47. package/dist/node-cli-sessions-rj0ysJwM.js +527 -0
  48. package/dist/{node-exec-server.runtime-nfbUOtUB.js → node-exec-server.runtime-BY_ctYnT.js} +53 -22
  49. package/dist/plan-BMJdMOEF.js +711 -0
  50. package/dist/plugin-activation-BQK-f5sV.js +133 -0
  51. package/dist/{thread-resume-BLgqkUc1.js → plugin-app-cache-key-CdSQzWyX.js} +4 -52
  52. package/dist/{plugin-approval-roundtrip-aQVdyL5g.js → plugin-approval-roundtrip-DeW95wB5.js} +1 -1
  53. package/dist/plugin-inventory-CoRCzWW4.js +325 -0
  54. package/dist/plugin-marketplace-discovery-3akBizzF.js +134 -0
  55. package/dist/{plugin-metadata-cache-BwCLTY_U.js → plugin-metadata-cache-DgNfRAGA.js} +13 -9
  56. package/dist/protocol-CAAcVIKF.js +275 -0
  57. package/dist/{provider-capabilities-BpG9Ltc5.js → provider-capabilities-W4tfK5Y5.js} +2 -2
  58. package/dist/{rate-limits-Fx_l4eNa.js → rate-limits-Bqnx1N4z.js} +1 -1
  59. package/dist/request-CGvGOpeR.js +198 -0
  60. package/dist/{run-attempt-BzthFQSM.js → run-attempt-DwKds3DN.js} +589 -373
  61. package/dist/{runtime-artifact-Bh_gf6-t.js → runtime-artifact-T-NwqeSH.js} +27 -27
  62. package/dist/sandbox-guard-BcT66fWy.js +165 -0
  63. package/dist/{session-binding-4Ki04sW-.js → session-binding-CKSepwIC.js} +29 -47
  64. package/dist/{session-binding-record-CyaXZvTe.js → session-binding-record-CaZjYwNS.js} +11 -25
  65. package/dist/session-catalog-HaDcp7Sv.js +1533 -0
  66. package/dist/session-catalog-adoption-BKLtSrwi.js +251 -0
  67. package/dist/session-catalog-archive-D0i2pGj2.js +56 -0
  68. package/dist/session-catalog-home-id-D7-aLiNt.js +190 -0
  69. package/dist/session-catalog-node-adoption-BUuDYY8R.js +182 -0
  70. package/dist/session-catalog-node-continue-CBtc4wkI.js +238 -0
  71. package/dist/session-catalog-parsing-CdD3JhdM.js +280 -0
  72. package/dist/session-catalog-provenance-DkJHo735.js +124 -0
  73. package/dist/{session-cli-BjLhpmS1.js → session-cli-CbgaHh0f.js} +3 -2
  74. package/dist/{session-history-DWmMqiqW.js → session-history-Cz-tOOYj.js} +6 -3
  75. package/dist/{session-upstream-marker-DReTpGz6.js → session-history-import-DFN7sWRU.js} +5 -50
  76. package/dist/{session-history-read-LHldwvyh.js → session-history-read-cxPUxyVV.js} +21 -7
  77. package/dist/session-history-worker-runtime.js +18 -6
  78. package/dist/{session-history.worker-zZVcx0ME.js → session-history.worker-CNEvGaU5.js} +58 -51
  79. package/dist/session-history.worker.js +1 -1
  80. package/dist/{session-initialization-BCFVnLL4.js → session-initialization-Jo86C60I.js} +2 -2
  81. package/dist/{session-permission-policy-BaueHmSj.js → session-permission-policy-B22InTp_.js} +4 -7
  82. package/dist/{session-retirement-DNdmYdFc.js → session-retirement-BSNG_mhf.js} +6 -5
  83. package/dist/session-upstream-marker-D15C9NHp.js +46 -0
  84. package/dist/{settled-turn-context-BOM3Y1pl.js → settled-turn-context-Du6gdUDd.js} +9 -9
  85. package/dist/{settled-turn-finalizer-BI-b1sry.js → settled-turn-finalizer-BuLUrZl2.js} +7 -6
  86. package/dist/shared-client-CVhez2Uo.js +2911 -0
  87. package/dist/{side-question-B6DWAw1A.js → side-question-DLbr2vUU.js} +64 -169
  88. package/dist/source-Da-h6f7e.js +518 -0
  89. package/dist/thread-archive-guard-D1bP04Tf.js +53 -0
  90. package/dist/{thread-lifecycle-DPK30jad.js → thread-lifecycle-D1pzRwHB.js} +112 -616
  91. package/dist/{thread-ownership-CbucAmmp.js → thread-ownership-D6oASVRu.js} +13 -15
  92. package/dist/thread-policy-D8kI7yAO.js +54 -0
  93. package/dist/thread-resume-T5cveyxA.js +52 -0
  94. package/dist/timeout-BVw8aaM1.js +33 -0
  95. package/dist/{transcript-mirror-attestation-Byl34PC-.js → transcript-mirror-attestation-DibE0krH.js} +17 -4
  96. package/dist/{transcript-mirror-_njEB84z.js → transcript-mirror-t5TOccct.js} +50 -260
  97. package/dist/{transport-stdio-CzTngV0j.js → transport-stdio-BGjHoYLr.js} +73 -43
  98. package/dist/{upstream-session-fork-1fwbNKzQ.js → upstream-session-fork-De-sLJ2r.js} +26 -18
  99. package/dist/{usage-i9fv5-4m.js → usage-CPPTmBvZ.js} +4 -3
  100. package/dist/version-omm6IPI3.js +12 -0
  101. package/dist/{web-search-provider.runtime-DKQn67A7.js → web-search-provider.runtime-CSVgQL0w.js} +3 -3
  102. package/openclaw.plugin.json +22 -1
  103. package/package.json +4 -4
  104. package/dist/request-C8H22rPi.js +0 -475
  105. package/dist/session-catalog-B47uwekb.js +0 -3272
  106. package/dist/shared-client-CKhX2kFt.js +0 -7505
  107. package/dist/thread-policy-CTalhWFy.js +0 -105
  108. package/dist/{auth-binding-Ds_QVm-X.js → auth-binding-Co2Vfcf_.js} +1 -1
@@ -1,6 +1,5 @@
1
- import { B as isJsonObject } from "./config-CyapYSji.js";
2
- import { asSafeIntegerInRange, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
3
- import { normalizeUsage } from "openclaw/plugin-sdk/agent-harness-runtime";
1
+ import { o as isJsonObject } from "./protocol-CAAcVIKF.js";
2
+ import { readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
4
3
  //#region extensions/codex/src/app-server/attempt-notifications.ts
5
4
  const CODEX_TURN_ABORT_MARKER_START = "<turn_aborted>";
6
5
  const CODEX_TURN_ABORT_MARKER_END = "</turn_aborted>";
@@ -41,10 +40,6 @@ function isAssistantCommentaryCompletionNotification(notification) {
41
40
  const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
42
41
  return Boolean(item && readStringField(item, "type") === "agentMessage" && (readStringField(item, "phase") === "commentary" || readStringField(item, "delivery") === "async"));
43
42
  }
44
- /** A retryable native error is not a terminal outcome for bounded operations. */
45
- function isRetryableErrorNotification(value) {
46
- return isJsonObject(value) && value.willRetry === true;
47
- }
48
43
  /** Returns true for terminal app-server thread status strings. */
49
44
  function isTerminalTurnStatus(status) {
50
45
  return status === "completed" || status === "interrupted" || status === "failed";
@@ -111,102 +106,4 @@ function isNonEmptyString(value) {
111
106
  return typeof value === "string" && value.length > 0;
112
107
  }
113
108
  //#endregion
114
- //#region extensions/codex/src/app-server/event-projector-usage.ts
115
- function readTokenCount(record, key) {
116
- return asSafeIntegerInRange(record[key], { min: 0 });
117
- }
118
- function readCodexThreadTokenUsage(params) {
119
- const tokenUsage = isJsonObject(params.tokenUsage) ? params.tokenUsage : void 0;
120
- const last = tokenUsage && isJsonObject(tokenUsage.last) ? tokenUsage.last : void 0;
121
- return last ? normalizeCodexResponseTokenUsage(last) : void 0;
122
- }
123
- function readCodexThreadContextSnapshot(params) {
124
- const tokenUsage = isJsonObject(params.tokenUsage) ? params.tokenUsage : void 0;
125
- const last = tokenUsage && isJsonObject(tokenUsage.last) ? tokenUsage.last : void 0;
126
- const modelContextWindow = tokenUsage ? readTokenCount(tokenUsage, "modelContextWindow") : void 0;
127
- const activeContextTokens = last ? readTokenCount(last, "totalTokens") : void 0;
128
- const inputTokens = last ? readTokenCount(last, "inputTokens") : void 0;
129
- const cachedInputTokens = last ? readTokenCount(last, "cachedInputTokens") : void 0;
130
- const cacheWriteInputTokens = last ? readTokenCount(last, "cacheWriteInputTokens") : void 0;
131
- const reasoningOutputTokens = last ? readTokenCount(last, "reasoningOutputTokens") : void 0;
132
- return {
133
- ...activeContextTokens !== void 0 ? { activeContextTokens } : {},
134
- ...cachedInputTokens !== void 0 ? { cachedInputTokens } : {},
135
- ...cacheWriteInputTokens !== void 0 ? { cacheWriteInputTokens } : {},
136
- ...inputTokens !== void 0 ? { inputTokens } : {},
137
- ...modelContextWindow && modelContextWindow > 0 ? { modelContextWindow } : {},
138
- ...inputTokens !== void 0 ? { promptTokens: inputTokens } : {},
139
- ...reasoningOutputTokens !== void 0 ? { reasoningOutputTokens } : {}
140
- };
141
- }
142
- function normalizeCodexResponseTokenUsage(record) {
143
- const totalTokens = readTokenCount(record, "totalTokens");
144
- const inputTokens = readTokenCount(record, "inputTokens");
145
- const cacheRead = readTokenCount(record, "cachedInputTokens");
146
- const output = readTokenCount(record, "outputTokens");
147
- const reasoningTokens = readTokenCount(record, "reasoningOutputTokens");
148
- const cacheWrite = record.cacheWriteInputTokens === void 0 ? 0 : readTokenCount(record, "cacheWriteInputTokens");
149
- const hasCoherentInput = inputTokens !== void 0 && cacheRead !== void 0 && cacheWrite !== void 0 && cacheRead + cacheWrite <= inputTokens;
150
- const hasCoherentContext = hasCoherentInput && totalTokens !== void 0 && output !== void 0 && totalTokens === inputTokens + output;
151
- const usage = normalizeUsage({
152
- input: hasCoherentInput ? inputTokens - cacheRead - cacheWrite : void 0,
153
- output,
154
- cacheRead,
155
- cacheWrite,
156
- reasoningTokens,
157
- total: totalTokens
158
- });
159
- if (!usage) return;
160
- return {
161
- ...usage,
162
- contextUsage: hasCoherentContext ? {
163
- state: "available",
164
- promptTokens: inputTokens,
165
- totalTokens
166
- } : { state: "unavailable" }
167
- };
168
- }
169
- var CodexUsageProjection = class {
170
- constructor() {
171
- this.responseIds = /* @__PURE__ */ new Set();
172
- }
173
- get usage() {
174
- const usage = this.responseUsage ?? this.threadUsage;
175
- return usage ? {
176
- ...usage,
177
- contextUsage: this.contextUsage
178
- } : void 0;
179
- }
180
- get modelIterations() {
181
- return this.responseIds.size;
182
- }
183
- invalidateContext() {
184
- this.contextUsage = { state: "unavailable" };
185
- }
186
- recordThread(params) {
187
- const usage = readCodexThreadTokenUsage(params);
188
- this.threadUsage = usage ?? this.threadUsage;
189
- if (!this.responseUsage && usage) this.contextUsage = usage.contextUsage;
190
- return readCodexThreadContextSnapshot(params);
191
- }
192
- record(params, reportOutputTokens) {
193
- const responseId = readStringField(params, "responseId");
194
- if (!responseId || this.responseIds.has(responseId)) return;
195
- this.responseIds.add(responseId);
196
- const usage = isJsonObject(params.usage) ? normalizeCodexResponseTokenUsage(params.usage) : void 0;
197
- this.contextUsage = usage?.contextUsage ?? { state: "unavailable" };
198
- this.responseUsage ??= {};
199
- for (const field of [
200
- "input",
201
- "output",
202
- "cacheRead",
203
- "cacheWrite",
204
- "reasoningTokens",
205
- "total"
206
- ]) if (usage?.[field] !== void 0) this.responseUsage[field] = (this.responseUsage[field] ?? 0) + usage[field];
207
- const outputTokens = usage?.output;
208
- if (outputTokens !== void 0) reportOutputTokens?.(outputTokens);
209
- }
210
- };
211
- //#endregion
212
- export { isCodexTurnAbortMarkerNotification as a, isRetryableErrorNotification as c, readNotificationItemId as d, readRawResponseToolCallId as f, isAssistantCommentaryCompletionNotification as i, isTerminalTurnStatus as l, readCodexThreadContextSnapshot as n, isPendingOpenClawDynamicToolCompletionNotification as o, updateActiveTurnItemIds as p, codexExecutionToolName as r, isRawFunctionToolOutputCompletionNotification as s, CodexUsageProjection as t, readCodexNotificationItem as u };
109
+ export { isRawFunctionToolOutputCompletionNotification as a, readNotificationItemId as c, isPendingOpenClawDynamicToolCompletionNotification as i, readRawResponseToolCallId as l, isAssistantCommentaryCompletionNotification as n, isTerminalTurnStatus as o, isCodexTurnAbortMarkerNotification as r, readCodexNotificationItem as s, codexExecutionToolName as t, updateActiveTurnItemIds as u };
@@ -0,0 +1,498 @@
1
+ import { n as defineCodexBuildState } from "./build-state-6RL6qohz.js";
2
+ import { s as resolveMacOSDesktopCodexAppPathCandidates } from "./managed-binary-DrjjRRUD.js";
3
+ import { n as resolveCodexAppServerSpawnEnv } from "./transport-stdio-BGjHoYLr.js";
4
+ import { createHash } from "node:crypto";
5
+ import fs, { constants, existsSync, watch } from "node:fs";
6
+ import path from "node:path";
7
+ import os from "node:os";
8
+ import fs$1 from "node:fs/promises";
9
+ import { readSecretFile } from "openclaw/plugin-sdk/secret-file";
10
+ //#region extensions/codex/src/app-server/desktop-generation-fingerprint.ts
11
+ const MAX_COMPUTER_USE_PLUGIN_TREE_ENTRIES = 4096;
12
+ /** Fingerprints every desktop candidate that can own a managed fallback artifact. */
13
+ async function readMacOSDesktopGenerationFingerprint(candidates = resolveMacOSDesktopCodexAppPathCandidates("darwin")) {
14
+ const entries = [];
15
+ for (const candidate of candidates) {
16
+ const command = await statFingerprint(candidate.appServerCommandPath);
17
+ entries.push(`candidate:${candidate.appName}:${candidate.appServerCommandPath}:${command}`);
18
+ for (const artifactPath of resolveMacOSDesktopGenerationPaths(candidate)) entries.push(`${artifactPath}\0${await statFingerprint(artifactPath)}`);
19
+ const pluginRoot = resolveComputerUsePluginRoot(candidate);
20
+ entries.push(`${pluginRoot}\0${await directoryTreeFingerprint(pluginRoot)}`);
21
+ }
22
+ return createHash("sha256").update(entries.join("\0")).digest("hex");
23
+ }
24
+ function resolveMacOSDesktopGenerationPaths(candidate) {
25
+ return [
26
+ candidate.appBundlePath,
27
+ path.join(candidate.bundledMarketplacePath, ".agents", "plugins", "marketplace.json"),
28
+ ...candidate.computerUseServiceAppPaths.flatMap((servicePath) => [
29
+ servicePath,
30
+ path.join(servicePath, "Contents", "Info.plist"),
31
+ path.join(servicePath, "Contents", "SharedSupport", "SkyComputerUseClient.app", "Contents", "MacOS", "SkyComputerUseClient")
32
+ ])
33
+ ];
34
+ }
35
+ function resolveComputerUsePluginRoot(candidate) {
36
+ return path.join(candidate.bundledMarketplacePath, "plugins", "computer-use");
37
+ }
38
+ /** Stable roots that cover bundle replacement and recursive artifact updates. */
39
+ function resolveMacOSDesktopGenerationWatchPaths(candidates = resolveMacOSDesktopCodexAppPathCandidates("darwin")) {
40
+ const watched = /* @__PURE__ */ new Set(["/Applications"]);
41
+ for (const candidate of candidates) watched.add(candidate.appBundlePath);
42
+ return [...watched];
43
+ }
44
+ async function directoryTreeFingerprint(root) {
45
+ let rootStat;
46
+ try {
47
+ rootStat = await fs$1.lstat(root, { bigint: true });
48
+ } catch (error) {
49
+ if (isNodeError(error, "ENOENT") || isNodeError(error, "ENOTDIR")) return "missing";
50
+ throw error;
51
+ }
52
+ if (!rootStat.isDirectory()) return statFingerprint(root);
53
+ let entryCount = 0;
54
+ const hash = createHash("sha256");
55
+ hash.update("openclaw-codex-computer-use-plugin-tree-v1\0");
56
+ const visit = async (directory, relativeDirectory, before) => {
57
+ hash.update(`directory\0${relativeDirectory}\0${statTuple(before)}\0`);
58
+ const entries = (await fs$1.readdir(directory, { withFileTypes: true })).toSorted((left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0);
59
+ for (const entry of entries) {
60
+ entryCount += 1;
61
+ if (entryCount > MAX_COMPUTER_USE_PLUGIN_TREE_ENTRIES) throw new Error("Codex Computer Use plugin exceeds the bounded tree size");
62
+ const entryPath = path.join(directory, entry.name);
63
+ const relativePath = path.join(relativeDirectory, entry.name);
64
+ const entryStat = await fs$1.lstat(entryPath, { bigint: true });
65
+ if (entryStat.isDirectory()) await visit(entryPath, relativePath, entryStat);
66
+ else hash.update(`entry\0${relativePath}\0${await statFingerprint(entryPath)}\0`);
67
+ }
68
+ if (!sameStat(before, await fs$1.lstat(directory, { bigint: true }))) throw new Error(`Codex desktop artifact changed while fingerprinting: ${directory}`);
69
+ };
70
+ await visit(root, ".", rootStat);
71
+ return hash.digest("hex");
72
+ }
73
+ async function statFingerprint(filePath) {
74
+ try {
75
+ const entry = await fs$1.lstat(filePath, { bigint: true });
76
+ const type = entry.isSymbolicLink() ? "link" : entry.isDirectory() ? "directory" : entry.isFile() ? "file" : "other";
77
+ const own = statTuple(entry);
78
+ if (!entry.isSymbolicLink()) return `${type}:${own}:${entry.isFile() ? await readFileFingerprint(filePath, entry, false) : ""}`;
79
+ const [link, realPath, target] = await Promise.all([
80
+ fs$1.readlink(filePath),
81
+ fs$1.realpath(filePath),
82
+ fs$1.stat(filePath, { bigint: true })
83
+ ]);
84
+ const content = target.isFile() ? await readFileFingerprint(filePath, target, true) : "";
85
+ return `${type}:${own}:${link}:${realPath}:${statTuple(target)}:${content}`;
86
+ } catch (error) {
87
+ if (isNodeError(error, "ENOENT") || isNodeError(error, "ENOTDIR")) return "missing";
88
+ throw error;
89
+ }
90
+ }
91
+ async function readFileFingerprint(filePath, expected, followsSymlink) {
92
+ const noFollow = followsSymlink ? 0 : constants.O_NOFOLLOW ?? 0;
93
+ const handle = await fs$1.open(filePath, constants.O_RDONLY | noFollow);
94
+ try {
95
+ const before = await handle.stat({ bigint: true });
96
+ if (!sameStat(before, expected)) throw new Error(`Codex desktop artifact changed while fingerprinting: ${filePath}`);
97
+ const hash = createHash("sha256");
98
+ for await (const chunk of handle.createReadStream({ autoClose: false })) hash.update(chunk);
99
+ if (!sameStat(before, await handle.stat({ bigint: true }))) throw new Error(`Codex desktop artifact changed while fingerprinting: ${filePath}`);
100
+ return hash.digest("hex");
101
+ } finally {
102
+ await handle.close();
103
+ }
104
+ }
105
+ function sameStat(left, right) {
106
+ return statTuple(left) === statTuple(right);
107
+ }
108
+ function statTuple(stat) {
109
+ return [
110
+ stat.dev,
111
+ stat.ino,
112
+ stat.mode,
113
+ stat.size,
114
+ stat.mtimeNs,
115
+ stat.ctimeNs
116
+ ].join(":");
117
+ }
118
+ function isNodeError(error, code) {
119
+ return Boolean(error && typeof error === "object" && "code" in error && error.code === code);
120
+ }
121
+ //#endregion
122
+ //#region extensions/codex/src/app-server/desktop-generation-owner.ts
123
+ const SETTLE_DELAY_MS = 1e3;
124
+ /** Coalesces filesystem invalidations into one stable desktop generation. */
125
+ function createCodexDesktopGenerationOwner(params) {
126
+ let generation = params.initialGeneration;
127
+ let invalidation = 0;
128
+ let dirty = false;
129
+ let refresh;
130
+ let stopped = false;
131
+ const markDirty = () => {
132
+ invalidation += 1;
133
+ dirty = true;
134
+ };
135
+ const reconcile = () => {
136
+ if (refresh) return refresh;
137
+ refresh = (async () => {
138
+ for (;;) {
139
+ if (stopped) throw new Error("Codex desktop generation owner stopped");
140
+ const observedInvalidation = invalidation;
141
+ const first = await params.readFingerprint();
142
+ await delay(SETTLE_DELAY_MS);
143
+ if (stopped) throw new Error("Codex desktop generation owner stopped");
144
+ const second = await params.readFingerprint();
145
+ if (stopped) throw new Error("Codex desktop generation owner stopped");
146
+ if (observedInvalidation !== invalidation || first !== second) continue;
147
+ const previous = generation;
148
+ generation = previous?.fingerprint === second ? previous : {
149
+ epoch: (previous?.epoch ?? 0) + 1,
150
+ fingerprint: second
151
+ };
152
+ dirty = false;
153
+ if (previous && generation !== previous) params.onGenerationChange?.(generation);
154
+ return generation;
155
+ }
156
+ })().finally(() => {
157
+ refresh = void 0;
158
+ });
159
+ return refresh;
160
+ };
161
+ return {
162
+ read: () => generation,
163
+ markDirty,
164
+ wait: () => dirty ? reconcile() : Promise.resolve(generation),
165
+ refresh: () => {
166
+ markDirty();
167
+ return reconcile();
168
+ },
169
+ isCurrent: (candidate) => Boolean(candidate && !dirty && generation && candidate.epoch === generation.epoch && candidate.fingerprint === generation.fingerprint),
170
+ stop: () => {
171
+ stopped = true;
172
+ }
173
+ };
174
+ }
175
+ function delay(ms) {
176
+ return new Promise((resolve) => {
177
+ setTimeout(resolve, ms);
178
+ });
179
+ }
180
+ //#endregion
181
+ //#region extensions/codex/src/app-server/desktop-generation.ts
182
+ /** Lifecycle-owned generation for managed macOS Codex desktop artifacts. */
183
+ const APPLICATIONS_PATH = "/Applications";
184
+ const REARM_INITIAL_DELAY_MS = 100;
185
+ const REARM_MAX_DELAY_MS = 3e4;
186
+ const state = defineCodexBuildState("openclaw.codexDesktopGenerationState", () => ({}));
187
+ function waitForCodexDesktopGeneration() {
188
+ return state().owner?.wait() ?? Promise.resolve(void 0);
189
+ }
190
+ function isCodexDesktopGenerationCurrent(generation) {
191
+ return state().owner?.isCurrent(generation) ?? false;
192
+ }
193
+ function createCodexDesktopGenerationService(params, runtime = {
194
+ platform: process.platform,
195
+ readFingerprint: readMacOSDesktopGenerationFingerprint,
196
+ resolveWatchPaths: resolveMacOSDesktopGenerationWatchPaths,
197
+ pathExists: existsSync,
198
+ watchPath: (watchedPath, options, listener) => watch(watchedPath, options, listener)
199
+ }) {
200
+ return {
201
+ id: "codex-desktop-generation",
202
+ async start(ctx) {
203
+ if (runtime.platform !== "darwin") return;
204
+ const current = state();
205
+ current.context = ctx;
206
+ current.readFingerprint = runtime.readFingerprint;
207
+ current.resolveWatchPaths = runtime.resolveWatchPaths;
208
+ current.pathExists = runtime.pathExists;
209
+ current.watchPath = runtime.watchPath;
210
+ current.owner = createCodexDesktopGenerationOwner({
211
+ readFingerprint: current.readFingerprint,
212
+ onGenerationChange: params.onGenerationChange,
213
+ initialGeneration: current.lastGeneration
214
+ });
215
+ armWatchers(current);
216
+ refreshGeneration(current, current.owner, current.owner.refresh());
217
+ },
218
+ async stop() {
219
+ const current = state();
220
+ current.lastGeneration = current.owner?.read() ?? current.lastGeneration;
221
+ current.owner?.stop();
222
+ current.owner = void 0;
223
+ current.armEpoch = (current.armEpoch ?? 0) + 1;
224
+ current.context = void 0;
225
+ current.readFingerprint = void 0;
226
+ current.resolveWatchPaths = void 0;
227
+ current.pathExists = void 0;
228
+ current.watchPath = void 0;
229
+ current.watchHealthy = void 0;
230
+ current.rearmDelayMs = void 0;
231
+ if (current.rearmTimer) {
232
+ clearTimeout(current.rearmTimer);
233
+ current.rearmTimer = void 0;
234
+ }
235
+ closeWatchers(current);
236
+ }
237
+ };
238
+ }
239
+ function armWatchers(current) {
240
+ const owner = current.owner;
241
+ if (!owner || current.watchers) return false;
242
+ const armEpoch = (current.armEpoch ?? 0) + 1;
243
+ current.armEpoch = armEpoch;
244
+ const watchers = /* @__PURE__ */ new Set();
245
+ current.watchers = watchers;
246
+ const candidateNames = new Set(resolveMacOSDesktopCodexAppPathCandidates("darwin").map((candidate) => candidate.appName));
247
+ let complete = true;
248
+ for (const watchedPath of current.resolveWatchPaths?.() ?? []) {
249
+ if (!current.pathExists?.(watchedPath)) continue;
250
+ try {
251
+ const watcher = current.watchPath?.(watchedPath, { recursive: watchedPath !== APPLICATIONS_PATH }, (_eventType, filename) => {
252
+ if (!isCurrentArm(current, owner, watchers, armEpoch)) return;
253
+ if (watchedPath === APPLICATIONS_PATH && filename && !candidateNames.has(filename.toString().split(path.sep)[0] ?? "")) return;
254
+ owner.markDirty();
255
+ scheduleRearm(current, owner);
256
+ });
257
+ if (!watcher) {
258
+ complete = false;
259
+ reportWatcherFailure(current, owner, /* @__PURE__ */ new Error(`Could not watch ${watchedPath}`));
260
+ scheduleRearm(current, owner);
261
+ continue;
262
+ }
263
+ watchers.add(watcher);
264
+ watcher.on("error", (error) => {
265
+ if (!isCurrentArm(current, owner, watchers, armEpoch)) return;
266
+ reportWatcherFailure(current, owner, error);
267
+ scheduleRearm(current, owner);
268
+ });
269
+ } catch (error) {
270
+ complete = false;
271
+ reportWatcherFailure(current, owner, error);
272
+ scheduleRearm(current, owner);
273
+ }
274
+ }
275
+ current.watchHealthy = complete;
276
+ if (complete) current.rearmDelayMs = REARM_INITIAL_DELAY_MS;
277
+ return complete;
278
+ }
279
+ function reportWatcherFailure(current, owner, error) {
280
+ if (current.watchHealthy === false) return;
281
+ current.watchHealthy = false;
282
+ owner.markDirty();
283
+ current.context?.serviceHealth?.reportFailure(error);
284
+ current.context?.logger.warn(`codex desktop generation watcher failed: ${String(error)}`);
285
+ }
286
+ function isCurrentArm(current, owner, watchers, armEpoch) {
287
+ return current.owner === owner && current.watchers === watchers && current.armEpoch === armEpoch;
288
+ }
289
+ function scheduleRearm(current, owner) {
290
+ if (current.rearmTimer) {
291
+ if (current.watchHealthy === false) return;
292
+ clearTimeout(current.rearmTimer);
293
+ }
294
+ const delayMs = current.watchHealthy === false ? current.rearmDelayMs ?? REARM_INITIAL_DELAY_MS : REARM_INITIAL_DELAY_MS;
295
+ if (current.watchHealthy === false) current.rearmDelayMs = Math.min(delayMs * 2, REARM_MAX_DELAY_MS);
296
+ current.rearmTimer = setTimeout(() => {
297
+ current.rearmTimer = void 0;
298
+ if (current.owner !== owner) return;
299
+ const wasUnhealthy = current.watchHealthy === false;
300
+ closeWatchers(current);
301
+ if (!armWatchers(current) || wasUnhealthy) owner.markDirty();
302
+ refreshGeneration(current, owner, owner.wait());
303
+ }, delayMs);
304
+ current.rearmTimer.unref();
305
+ }
306
+ function logRefreshFailure(current, owner) {
307
+ return (error) => {
308
+ if (current.owner !== owner) return;
309
+ current.context?.serviceHealth?.reportFailure(error);
310
+ current.context?.logger.warn(`codex desktop generation refresh failed: ${String(error)}`);
311
+ };
312
+ }
313
+ function refreshGeneration(current, owner, refresh) {
314
+ refresh.then(() => {
315
+ if (current.owner === owner && current.watchHealthy) current.context?.serviceHealth?.clearFailure();
316
+ }).catch(logRefreshFailure(current, owner));
317
+ }
318
+ function closeWatchers(current) {
319
+ const watchers = current.watchers;
320
+ current.watchers = void 0;
321
+ for (const watcher of watchers ?? []) watcher.close();
322
+ }
323
+ //#endregion
324
+ //#region extensions/codex/src/app-server/shared-client-lifecycle.ts
325
+ /** Client ownership and synchronous retirement, independent of startup/auth execution. */
326
+ const createCodexAppServerStartupLifetime = () => ({
327
+ controller: new AbortController(),
328
+ pending: /* @__PURE__ */ new Set()
329
+ });
330
+ const getSharedCodexAppServerClientState = defineCodexBuildState("openclaw.codexAppServerClientState", () => ({
331
+ clients: /* @__PURE__ */ new Map(),
332
+ liveClients: /* @__PURE__ */ new Set(),
333
+ isolatedClients: /* @__PURE__ */ new Set(),
334
+ entriesByClient: /* @__PURE__ */ new WeakMap(),
335
+ desktopGenerationDrainChecks: /* @__PURE__ */ new Set(),
336
+ startup: createCodexAppServerStartupLifetime(),
337
+ startMetadata: /* @__PURE__ */ new WeakMap()
338
+ }));
339
+ function getCurrentSharedClientEntry(client) {
340
+ const state = getSharedCodexAppServerClientState();
341
+ const entry = client ? state.entriesByClient.get(client) : void 0;
342
+ return entry && entry.client === client && state.clients.get(entry.key) === entry ? entry : void 0;
343
+ }
344
+ /**
345
+ * Retires a matching shared client. Default is graceful: detach from the map
346
+ * (future acquisitions get a fresh client) and close once leases drain.
347
+ * `failActiveLeases` is for suspect clients only (timed-out turns): it closes
348
+ * the physical connection immediately so co-leased attempts hit the normal
349
+ * client-closed retry path, and pending acquires reject instead of leasing
350
+ * the poisoned process. Routine cleanup must NOT use it — it would abort
351
+ * healthy sibling turns on a working client.
352
+ */
353
+ function retireSharedCodexAppServerClientIfCurrent(client, opts) {
354
+ if (!client) return;
355
+ const state = getSharedCodexAppServerClientState();
356
+ const currentEntry = getCurrentSharedClientEntry(client);
357
+ const entry = currentEntry ?? state.entriesByClient.get(client);
358
+ if (!entry || entry.client !== client && !entry.closeError) return;
359
+ if (currentEntry) {
360
+ state.clients.delete(entry.key);
361
+ entry.closeWhenIdle = true;
362
+ }
363
+ if (opts?.failActiveLeases && (currentEntry || !entry.closeError)) {
364
+ entry.closeError = /* @__PURE__ */ new Error("codex app-server client is closed");
365
+ return {
366
+ activeLeases: entry.activeLeases,
367
+ closed: closeRetiredSharedClientEntry(entry)
368
+ };
369
+ }
370
+ return {
371
+ activeLeases: entry.activeLeases,
372
+ closed: currentEntry ? closeRetiredSharedClientEntryIfIdle(entry) : false
373
+ };
374
+ }
375
+ /** Gracefully retires exact clients attached to an older desktop generation. */
376
+ function retireSharedCodexAppServerClientsBeforeDesktopGeneration(generation) {
377
+ const state = getSharedCodexAppServerClientState();
378
+ for (const entry of state.clients.values()) {
379
+ const client = entry.client;
380
+ const attached = client ? state.startMetadata.get(client) : void 0;
381
+ if (client && attached?.desktopGeneration && attached.desktopGeneration.epoch < generation.epoch) retireSharedCodexAppServerClientIfCurrent(client);
382
+ }
383
+ }
384
+ function closeRetiredSharedClientEntryIfIdle(entry) {
385
+ if (!entry.closeWhenIdle || entry.activeLeases > 0 || entry.pendingAcquires > 0 || !entry.client) return false;
386
+ entry.closeWhenIdle = false;
387
+ return closeRetiredSharedClientEntry(entry);
388
+ }
389
+ function closeRetiredSharedClientEntry(entry) {
390
+ const client = entry.client;
391
+ if (!client) return false;
392
+ entry.client = void 0;
393
+ client.close();
394
+ return true;
395
+ }
396
+ //#endregion
397
+ //#region extensions/codex/src/app-server/auth-cache-key.ts
398
+ /** Auth cache identity and native CLI credential reads, without login or refresh. */
399
+ const CODEX_HOME_ENV_VAR = "CODEX_HOME";
400
+ const HOME_ENV_VAR = "HOME";
401
+ const CODEX_HOME_DIRNAME = ".codex";
402
+ const CODEX_AUTH_JSON_FILENAME = "auth.json";
403
+ const CODEX_APP_SERVER_API_KEY_ENV_VARS = ["CODEX_API_KEY", "OPENAI_API_KEY"];
404
+ function resolveCodexAppServerEnvApiKeyCacheKey(params) {
405
+ if (params.startOptions.transport !== "stdio") return;
406
+ const apiKey = readFirstNonEmptyEnvEntry(resolveCodexAppServerSpawnEnv(params.startOptions, params.baseEnv ?? process.env, params.platform ?? process.platform), CODEX_APP_SERVER_API_KEY_ENV_VARS);
407
+ if (!apiKey) return;
408
+ const hash = createHash("sha256");
409
+ hash.update("openclaw:codex:app-server-env-api-key:v1");
410
+ hash.update("\0");
411
+ hash.update(apiKey.key);
412
+ hash.update("\0");
413
+ hash.update(apiKey.value);
414
+ return `${apiKey.key}:sha256:${hash.digest("hex")}`;
415
+ }
416
+ function resolveCodexAppServerFallbackApiKeyCacheKey(params) {
417
+ if (params.startOptions.transport !== "stdio") return;
418
+ return resolveCodexAppServerEnvApiKeyCacheKey(params) ?? resolveCodexCliAuthFileApiKeyCacheKey(params.baseEnv ?? process.env);
419
+ }
420
+ /** Secret-free cache identity for an API key already resolved by the runtime plan. */
421
+ function resolveCodexAppServerPreparedApiKeyCacheKey(apiKey) {
422
+ const resolved = apiKey?.trim();
423
+ return resolved ? fingerprintApiKeyAuthProfileCacheKey(resolved) : void 0;
424
+ }
425
+ function fingerprintApiKeyAuthProfileCacheKey(apiKey) {
426
+ const hash = createHash("sha256");
427
+ hash.update("openclaw:codex:app-server-auth-profile-api-key:v1");
428
+ hash.update("\0");
429
+ hash.update(apiKey);
430
+ return `api_key:sha256:${hash.digest("hex")}`;
431
+ }
432
+ function fingerprintTokenAuthProfileCacheKey(accessToken) {
433
+ const hash = createHash("sha256");
434
+ hash.update("openclaw:codex:app-server-auth-profile-token:v1");
435
+ hash.update("\0");
436
+ hash.update(accessToken);
437
+ return `token:sha256:${hash.digest("hex")}`;
438
+ }
439
+ function fingerprintCodexCliAuthFileApiKeyCacheKey(apiKey) {
440
+ const hash = createHash("sha256");
441
+ hash.update("openclaw:codex:app-server-cli-auth-json-api-key:v1");
442
+ hash.update("\0");
443
+ hash.update(apiKey);
444
+ return `CODEX_AUTH_JSON:sha256:${hash.digest("hex")}`;
445
+ }
446
+ function resolveCodexCliAuthFilePath(env) {
447
+ const configuredCodexHome = env[CODEX_HOME_ENV_VAR]?.trim();
448
+ if (configuredCodexHome) return path.join(resolveHomeRelativePath(configuredCodexHome, env), CODEX_AUTH_JSON_FILENAME);
449
+ const home = env[HOME_ENV_VAR]?.trim() || env.USERPROFILE?.trim() || os.homedir();
450
+ return path.join(home, CODEX_HOME_DIRNAME, CODEX_AUTH_JSON_FILENAME);
451
+ }
452
+ function resolveHomeRelativePath(value, env) {
453
+ if (value === "~" || value.startsWith("~/") || value.startsWith("~\\")) {
454
+ const home = env[HOME_ENV_VAR]?.trim() || env.USERPROFILE?.trim() || os.homedir();
455
+ return path.join(home, value.slice(value === "~" ? 1 : 2));
456
+ }
457
+ return value;
458
+ }
459
+ function parseCodexCliAuthFileApiKey(raw) {
460
+ let parsed;
461
+ try {
462
+ parsed = JSON.parse(raw);
463
+ } catch {
464
+ return;
465
+ }
466
+ if (!parsed || typeof parsed !== "object") return;
467
+ const apiKey = parsed.OPENAI_API_KEY;
468
+ return typeof apiKey === "string" && apiKey.trim() ? apiKey.trim() : void 0;
469
+ }
470
+ async function readCodexCliAuthFileApiKey(env) {
471
+ try {
472
+ return parseCodexCliAuthFileApiKey(await readSecretFile(resolveCodexCliAuthFilePath(env), "Codex CLI auth file"));
473
+ } catch {
474
+ return;
475
+ }
476
+ }
477
+ function resolveCodexCliAuthFileApiKeyCacheKey(env) {
478
+ try {
479
+ const apiKey = parseCodexCliAuthFileApiKey(fs.readFileSync(resolveCodexCliAuthFilePath(env), "utf8"));
480
+ return apiKey ? fingerprintCodexCliAuthFileApiKeyCacheKey(apiKey) : void 0;
481
+ } catch {
482
+ return;
483
+ }
484
+ }
485
+ function readFirstNonEmptyEnv(env, keys) {
486
+ return readFirstNonEmptyEnvEntry(env, keys)?.value;
487
+ }
488
+ function readFirstNonEmptyEnvEntry(env, keys) {
489
+ for (const key of keys) {
490
+ const value = env[key]?.trim();
491
+ if (value) return {
492
+ key,
493
+ value
494
+ };
495
+ }
496
+ }
497
+ //#endregion
498
+ export { isCodexDesktopGenerationCurrent as _, readCodexCliAuthFileApiKey as a, resolveCodexAppServerPreparedApiKeyCacheKey as c, createCodexAppServerStartupLifetime as d, getCurrentSharedClientEntry as f, createCodexDesktopGenerationService as g, retireSharedCodexAppServerClientsBeforeDesktopGeneration as h, fingerprintTokenAuthProfileCacheKey as i, closeRetiredSharedClientEntry as l, retireSharedCodexAppServerClientIfCurrent as m, CODEX_AUTH_JSON_FILENAME as n, readFirstNonEmptyEnv as o, getSharedCodexAppServerClientState as p, fingerprintApiKeyAuthProfileCacheKey as r, resolveCodexAppServerFallbackApiKeyCacheKey as s, CODEX_APP_SERVER_API_KEY_ENV_VARS as t, closeRetiredSharedClientEntryIfIdle as u, waitForCodexDesktopGeneration as v };
@@ -0,0 +1,43 @@
1
+ import { n as createCodexAuthProfileSelection } from "./auth-profile-selection-DFu9e167.js";
2
+ import { embeddedAgentLog, resolveDefaultAgentDir } from "openclaw/plugin-sdk/agent-harness-registration";
3
+ import { resolveProviderIdForAuth } from "openclaw/plugin-sdk/provider-auth-aliases";
4
+ import { ensureAuthProfileStore, resolveAuthProfileOrder } from "openclaw/plugin-sdk/provider-auth";
5
+ //#region extensions/codex/src/app-server/auth-profile.ts
6
+ /** Synchronous auth-profile selection and native provider identity. */
7
+ const CODEX_APP_SERVER_NATIVE_AUTH_PROVIDER = "openai";
8
+ const PUBLIC_OPENAI_MODEL_PROVIDER = "openai";
9
+ const { resolveCodexAppServerAuthProfileId, resolveCodexAppServerAuthProfileIdForAgent, resolveCodexAppServerAuthProfileStore } = createCodexAuthProfileSelection({
10
+ ensureAuthProfileStore,
11
+ resolveAuthProfileOrder
12
+ });
13
+ /** Returns true when an auth profile uses native Codex/OpenAI app-server auth. */
14
+ function isCodexAppServerNativeAuthProfile(lookup) {
15
+ const authProfileId = lookup.authProfileId?.trim();
16
+ if (!authProfileId) return false;
17
+ try {
18
+ const credential = (lookup.authProfileStore ?? ensureAuthProfileStore(lookup.agentDir?.trim() || resolveDefaultAgentDir(lookup.config ?? {}), {
19
+ allowKeychainPrompt: false,
20
+ config: lookup.config,
21
+ externalCliProviderIds: [CODEX_APP_SERVER_NATIVE_AUTH_PROVIDER],
22
+ externalCliProfileIds: [authProfileId]
23
+ })).profiles[authProfileId];
24
+ if (!credential || credential.type === "api_key") return false;
25
+ const provider = credential.provider?.trim();
26
+ return Boolean(provider && resolveProviderIdForAuth(provider, { config: lookup.config }) === CODEX_APP_SERVER_NATIVE_AUTH_PROVIDER);
27
+ } catch (error) {
28
+ embeddedAgentLog.debug("failed to resolve codex app-server auth profile provider", {
29
+ authProfileId,
30
+ error
31
+ });
32
+ return false;
33
+ }
34
+ }
35
+ /** Hides redundant OpenAI provider attribution for native Codex auth bindings. */
36
+ function normalizeCodexAppServerBindingModelProvider(params) {
37
+ const modelProvider = params.modelProvider?.trim();
38
+ if (!modelProvider) return;
39
+ if (isCodexAppServerNativeAuthProfile(params) && modelProvider.toLowerCase() === PUBLIC_OPENAI_MODEL_PROVIDER) return;
40
+ return modelProvider;
41
+ }
42
+ //#endregion
43
+ export { resolveCodexAppServerAuthProfileStore as a, resolveCodexAppServerAuthProfileIdForAgent as i, normalizeCodexAppServerBindingModelProvider as n, resolveCodexAppServerAuthProfileId as r, isCodexAppServerNativeAuthProfile as t };