@openclaw/codex 2026.9.1 → 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 (109) hide show
  1. package/README.md +2 -0
  2. package/dist/api.js +18 -23
  3. package/dist/apply-B6el6hdO.js +357 -0
  4. package/dist/{attempt-client-cleanup-DYHcRQAa.js → attempt-client-cleanup-D6cR54TV.js} +113 -49
  5. package/dist/{attempt-context-DmQUNWwT.js → attempt-context-AO4DSjE0.js} +11 -9
  6. package/dist/{event-projector-usage-C5mcrGjp.js → attempt-notifications--H8zXR5-.js} +3 -89
  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-E6uDsPlx.js → binding-connection-QqgcPCgk.js} +18 -3
  11. package/dist/{bounded-turn-wzJrwKKe.js → bounded-turn-lRpmZHFv.js} +54 -150
  12. package/dist/build-state-6RL6qohz.js +19 -0
  13. package/dist/{capabilities-dIjNVCYH.js → capabilities-BeqLPbtM.js} +2 -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-CLHhEB1Q.js → command-formatters-DeTfrapr.js} +2 -2
  18. package/dist/{command-handlers-CTGb2csu.js → command-handlers-BfIsJEuA.js} +158 -76
  19. package/dist/command-rpc-BMqRQOFX.js +226 -0
  20. package/dist/{compact-_t0HQrUS.js → compact-CGJZ2rlb.js} +89 -49
  21. package/dist/config-JDfTI4VI.js +106 -0
  22. package/dist/{config-BhmfC1s6.js → config-options-jnIFvwxD.js} +208 -654
  23. package/dist/config-runtime-BWf6JLWG.js +11 -0
  24. package/dist/config-utils-C57JiJrU.js +69 -0
  25. package/dist/conversation-binding-CxOlHiix.js +889 -0
  26. package/dist/{plugin-marketplace-discovery-CfFlKqDl.js → conversation-control-CUCrSIQI.js} +36 -155
  27. package/dist/doctor-contract-api.js +8 -9
  28. package/dist/{dynamic-tools-BU9tmlYm.js → dynamic-tools-D-JBoaLt.js} +734 -698
  29. package/dist/{effective-mcp-catalog-DzYBW4h1.js → effective-mcp-catalog-J_5Ep5Um.js} +4 -3
  30. package/dist/{elicitation-input-DMkeki8d.js → elicitation-input-DPoK8F7w.js} +8 -22
  31. package/dist/ephemeral-turn-DSwzP8YY.js +101 -0
  32. package/dist/{event-projector-assistant-message-DHRFXKbS.js → event-projector-assistant-message-BmBM4qBV.js} +23 -27
  33. package/dist/event-projector-usage-CIyrYYid.js +102 -0
  34. package/dist/{harness-DXVZ5II5.js → harness-FR6eQgyO.js} +47 -17
  35. package/dist/harness.js +1 -1
  36. package/dist/history-rejection-B4nOXNXF.js +13 -0
  37. package/dist/{image-payload-sanitizer-CnfoUPCE.js → image-payload-sanitizer-tupAr-2o.js} +29 -15
  38. package/dist/incognito-session-uhrBF6wJ.js +15 -0
  39. package/dist/index.js +413 -2893
  40. package/dist/{isolated-completion-kg9kv4iH.js → isolated-completion-DHBefrzg.js} +12 -21
  41. package/dist/{managed-binary-4-Vjz5GH.js → managed-binary-DrjjRRUD.js} +17 -84
  42. package/dist/managed-thread-store-D1t5jh3G.js +66 -0
  43. package/dist/media-understanding-provider.js +4 -1
  44. package/dist/{model-catalog-CUM68Hkl.js → model-catalog-B_6M04Wo.js} +6 -5
  45. package/dist/{models-sYnEc0gd.js → models-P9k2qAof.js} +4 -4
  46. package/dist/native-execution-policy-umd0tgh4.js +128 -0
  47. package/dist/{native-subagent-monitor-CnH147jH.js → native-subagent-monitor-BbCUKRwC.js} +76 -48
  48. package/dist/node-cli-sessions-rj0ysJwM.js +527 -0
  49. package/dist/{node-exec-server.runtime-CstNHCmC.js → node-exec-server.runtime-BY_ctYnT.js} +54 -23
  50. package/dist/plan-BMJdMOEF.js +711 -0
  51. package/dist/plugin-activation-BQK-f5sV.js +133 -0
  52. package/dist/{thread-resume-C7pyVKeW.js → plugin-app-cache-key-CdSQzWyX.js} +5 -53
  53. package/dist/{plugin-approval-roundtrip-CNe-Xrjx.js → plugin-approval-roundtrip-DeW95wB5.js} +1 -1
  54. package/dist/plugin-inventory-CoRCzWW4.js +325 -0
  55. package/dist/plugin-marketplace-discovery-3akBizzF.js +134 -0
  56. package/dist/{plugin-metadata-cache-BFrPhb2c.js → plugin-metadata-cache-DgNfRAGA.js} +13 -9
  57. package/dist/protocol-CAAcVIKF.js +275 -0
  58. package/dist/{provider-capabilities-DW5p4k9w.js → provider-capabilities-W4tfK5Y5.js} +2 -2
  59. package/dist/{rate-limits-CawQJfUS.js → rate-limits-Bqnx1N4z.js} +1 -1
  60. package/dist/request-CGvGOpeR.js +198 -0
  61. package/dist/{run-attempt-D1hJO4fX.js → run-attempt-DwKds3DN.js} +1498 -1028
  62. package/dist/{runtime-artifact-C3jVimFn.js → runtime-artifact-T-NwqeSH.js} +28 -28
  63. package/dist/sandbox-guard-BcT66fWy.js +165 -0
  64. package/dist/{session-binding-BHuTCRZQ.js → session-binding-CKSepwIC.js} +118 -324
  65. package/dist/session-binding-record-CaZjYwNS.js +256 -0
  66. package/dist/session-catalog-HaDcp7Sv.js +1533 -0
  67. package/dist/session-catalog-adoption-BKLtSrwi.js +251 -0
  68. package/dist/session-catalog-archive-D0i2pGj2.js +56 -0
  69. package/dist/session-catalog-home-id-D7-aLiNt.js +190 -0
  70. package/dist/session-catalog-node-adoption-BUuDYY8R.js +182 -0
  71. package/dist/session-catalog-node-continue-CBtc4wkI.js +238 -0
  72. package/dist/session-catalog-parsing-CdD3JhdM.js +280 -0
  73. package/dist/session-catalog-provenance-DkJHo735.js +124 -0
  74. package/dist/{session-cli-CmFEXMAM.js → session-cli-CbgaHh0f.js} +3 -2
  75. package/dist/session-history-Cz-tOOYj.js +96 -0
  76. package/dist/{session-upstream-marker-C351-5Qw.js → session-history-import-DFN7sWRU.js} +5 -49
  77. package/dist/session-history-read-cxPUxyVV.js +50 -0
  78. package/dist/session-history-worker-runtime.js +60 -0
  79. package/dist/{settled-turn-context-D3SNWtUn.js → session-history.worker-CNEvGaU5.js} +75 -69
  80. package/dist/session-history.worker.js +2 -0
  81. package/dist/{session-initialization-BeWzjGiR.js → session-initialization-Jo86C60I.js} +2 -1
  82. package/dist/{session-permission-policy-DeWVTCMj.js → session-permission-policy-B22InTp_.js} +4 -7
  83. package/dist/{session-retirement-BujDjXVF.js → session-retirement-BSNG_mhf.js} +8 -7
  84. package/dist/session-upstream-marker-D15C9NHp.js +46 -0
  85. package/dist/settled-turn-context-Du6gdUDd.js +45 -0
  86. package/dist/{settled-turn-finalizer-BVJx4yoc.js → settled-turn-finalizer-BuLUrZl2.js} +54 -42
  87. package/dist/shared-client-CVhez2Uo.js +2911 -0
  88. package/dist/{side-question-BTZAII4l.js → side-question-DLbr2vUU.js} +135 -191
  89. package/dist/source-Da-h6f7e.js +518 -0
  90. package/dist/thread-archive-guard-D1bP04Tf.js +53 -0
  91. package/dist/{thread-lifecycle-DAcEJ_Om.js → thread-lifecycle-D1pzRwHB.js} +467 -977
  92. package/dist/{thread-ownership-zGokd8i1.js → thread-ownership-D6oASVRu.js} +15 -17
  93. package/dist/{thread-policy-g4KbJPzp.js → thread-policy-D8kI7yAO.js} +2 -2
  94. package/dist/thread-resume-T5cveyxA.js +52 -0
  95. package/dist/timeout-BVw8aaM1.js +33 -0
  96. package/dist/transcript-mirror-attestation-DibE0krH.js +89 -0
  97. package/dist/{transcript-mirror-DTUxFWa_.js → transcript-mirror-t5TOccct.js} +111 -379
  98. package/dist/{transport-stdio-CyPldczm.js → transport-stdio-BGjHoYLr.js} +80 -48
  99. package/dist/{upstream-session-fork-CYlBIGVt.js → upstream-session-fork-De-sLJ2r.js} +94 -166
  100. package/dist/{usage-Bj-rrzkR.js → usage-CPPTmBvZ.js} +4 -3
  101. package/dist/version-omm6IPI3.js +12 -0
  102. package/dist/{web-search-provider.runtime-D2FWSK4w.js → web-search-provider.runtime-CSVgQL0w.js} +3 -3
  103. package/openclaw.plugin.json +22 -1
  104. package/package.json +6 -6
  105. package/dist/request-DYAI5FQE.js +0 -475
  106. package/dist/session-catalog-yyvTWFOw.js +0 -3120
  107. package/dist/session-history-C5J1AKzG.js +0 -87
  108. package/dist/shared-client-DxcfF9KX.js +0 -7494
  109. package/dist/{auth-binding-Ds_QVm-X.js → auth-binding-Co2Vfcf_.js} +1 -1
@@ -0,0 +1,251 @@
1
+ import { l as sessionBindingIdentity } from "./session-binding-record-CaZjYwNS.js";
2
+ import { S as requireBoundThread, o as CatalogParamsError, u as boundedCatalogString } from "./session-catalog-parsing-CdD3JhdM.js";
3
+ import { n as codexUpstreamBaseline, t as codexLastTerminalTurnId } from "./session-upstream-marker-D15C9NHp.js";
4
+ import { i as reclaimCurrentCodexSessionGeneration } from "./session-binding-CKSepwIC.js";
5
+ import { adoptionSessionKeyRest, continueOperations, runSessionActionExclusive } from "./session-catalog-node-adoption-BUuDYY8R.js";
6
+ import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
7
+ import { listSessionCatalogEntries, sessionCatalogAdoptedSessionKey, sessionCatalogAdoptedSourceKey } from "openclaw/plugin-sdk/session-catalog";
8
+ //#region extensions/codex/src/session-catalog-adoption.ts
9
+ const CODEX_SUPERVISION_SESSION_KEY_PREFIX = "harness:codex:supervision:";
10
+ const boundCatalogSessionId = (value) => boundedCatalogString(value, 256);
11
+ function requireIdleThread(thread, action) {
12
+ if (thread.status?.type === "idle" || action === "archive" && thread.status?.type === "notLoaded") return;
13
+ if (thread.status?.type === "active") throw new CatalogParamsError(`Codex session is active in this App Server; wait for it to finish before ${action === "continue" ? "starting a branch" : "archiving"}`);
14
+ throw new CatalogParamsError(action === "archive" ? "Codex session cannot be archived in its current state" : "Codex session cannot start a branch in its current state");
15
+ }
16
+ function adoptionSessionKey(threadId, sourceHomeId) {
17
+ const source = sourceHomeId ? JSON.stringify([sourceHomeId, threadId]) : threadId;
18
+ return sessionCatalogAdoptedSessionKey(CODEX_SUPERVISION_SESSION_KEY_PREFIX, source);
19
+ }
20
+ function isAdoptionSessionKeyForThread(sessionKey, threadId, sourceHomeId) {
21
+ return adoptionSessionKeyRest(sessionKey) === adoptionSessionKey(threadId, sourceHomeId);
22
+ }
23
+ function readCodexSupervisionMarker(entry) {
24
+ const codex = isRecord(entry.pluginExtensions?.codex) ? entry.pluginExtensions.codex : void 0;
25
+ const marker = codex && isRecord(codex.supervision) ? codex.supervision : void 0;
26
+ const sourceThreadId = marker?.sourceThreadId;
27
+ const sourceHomeId = marker?.sourceHomeId;
28
+ if (typeof sourceThreadId !== "string" || !sourceThreadId.trim() || sourceHomeId !== void 0 && (typeof sourceHomeId !== "string" || !sourceHomeId.trim())) return;
29
+ return {
30
+ sourceThreadId: sourceThreadId.trim(),
31
+ ...typeof sourceHomeId === "string" ? { sourceHomeId: sourceHomeId.trim() } : {}
32
+ };
33
+ }
34
+ async function listAdoptedSessionEntries(params) {
35
+ const adopted = /* @__PURE__ */ new Map();
36
+ for (const { agentId, entry, sessionKey } of listSessionCatalogEntries({
37
+ ...params.agentId ? { agentId: params.agentId } : {},
38
+ config: params.config ?? {},
39
+ runtime: params.runtime,
40
+ sessionEntries: params.sessionEntries
41
+ })) {
42
+ const sessionKeyRest = adoptionSessionKeyRest(sessionKey);
43
+ const marker = readCodexSupervisionMarker(entry);
44
+ if (!sessionKeyRest.startsWith(CODEX_SUPERVISION_SESSION_KEY_PREFIX) || !marker || entry.initializationPending === true || entry.agentHarnessId !== "codex" || entry.modelSelectionLocked !== true) continue;
45
+ const sessionId = entry.sessionId?.trim();
46
+ if (!sessionId) continue;
47
+ const binding = params.bindingStore.read(sessionBindingIdentity({
48
+ sessionId,
49
+ sessionKey,
50
+ config: params.config
51
+ }));
52
+ const sourceThreadId = binding?.supervisionSourceThreadId?.trim();
53
+ const boundThreadId = binding?.threadId.trim();
54
+ if (binding?.connectionScope !== "supervision" || !sourceThreadId || !boundThreadId || sessionKeyRest !== adoptionSessionKey(sourceThreadId, marker.sourceHomeId)) continue;
55
+ const sourceKey = sessionCatalogAdoptedSourceKey(marker.sourceHomeId ?? "gateway:local", sourceThreadId);
56
+ if (adopted.has(sourceKey)) throw new Error(`multiple OpenClaw sessions adopt Codex thread ${sourceThreadId} from the same home`);
57
+ adopted.set(sourceKey, {
58
+ key: sessionKey,
59
+ sessionId,
60
+ agentId,
61
+ boundThreadId
62
+ });
63
+ }
64
+ return adopted;
65
+ }
66
+ async function findAdoptedSessionEntry(params) {
67
+ const adopted = await listAdoptedSessionEntries(params);
68
+ return adopted.get(sessionCatalogAdoptedSourceKey(params.sourceHomeId ?? "gateway:local", params.threadId)) ?? (params.sourceHomeId && params.allowLegacy === true ? adopted.get(sessionCatalogAdoptedSourceKey("gateway:local", params.threadId)) : void 0);
69
+ }
70
+ function matchesPendingAdoptionBinding(binding, expected) {
71
+ const historyCoveredThrough = binding?.historyCoveredThrough;
72
+ return binding?.threadId === expected.sourceThreadId && binding.connectionScope === "supervision" && binding.supervisionSourceThreadId === expected.sourceThreadId && binding.cwd === expected.cwd && binding.conversationSourceTransferComplete === true && binding.preserveNativeModel === true && binding.pendingSupervisionBranch?.sourceThreadId === expected.sourceThreadId && binding.pendingSupervisionBranch.connectionFingerprint === expected.connectionFingerprint && binding.pendingSupervisionBranch.lastTurnId === expected.lastTurnId && (binding.pendingSupervisionBranch.cleanupThreadIds?.length ?? 0) === 0 && typeof historyCoveredThrough === "string" && Number.isFinite(Date.parse(historyCoveredThrough));
73
+ }
74
+ async function ensurePendingAdoptionBinding(params) {
75
+ const pending = {
76
+ sourceThreadId: params.sourceThreadId,
77
+ connectionFingerprint: params.connectionFingerprint,
78
+ ...params.lastTurnId ? { lastTurnId: params.lastTurnId } : {}
79
+ };
80
+ const ownsGeneration = await reclaimCurrentCodexSessionGeneration({
81
+ assertCurrent: params.initialization.assertCurrent,
82
+ bindingStore: params.bindingStore,
83
+ identity: params.identity,
84
+ config: params.config
85
+ });
86
+ params.initialization.assertCurrent();
87
+ if (!ownsGeneration) throw new Error(`failed to claim the OpenClaw session generation for ${params.sourceThreadId}`);
88
+ const existing = params.bindingStore.read(params.identity);
89
+ params.initialization.assertCurrent();
90
+ if (existing) {
91
+ if (matchesPendingAdoptionBinding(existing, params)) return;
92
+ throw new Error(`OpenClaw session is already bound to Codex thread ${existing.threadId}`);
93
+ }
94
+ const binding = {
95
+ threadId: params.sourceThreadId,
96
+ connectionScope: "supervision",
97
+ supervisionSourceThreadId: params.sourceThreadId,
98
+ cwd: params.cwd,
99
+ historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString(),
100
+ conversationSourceTransferComplete: true,
101
+ preserveNativeModel: true,
102
+ pendingSupervisionBranch: pending
103
+ };
104
+ await params.initialization.bind(binding);
105
+ }
106
+ async function createOrReuseAdoptedSession(params) {
107
+ const runtime = params.api.runtime;
108
+ const lookup = {
109
+ ...params,
110
+ runtime,
111
+ threadId: params.sourceThread.id
112
+ };
113
+ const existing = await findAdoptedSessionEntry(lookup);
114
+ if (existing) return existing;
115
+ try {
116
+ const spawnedCwd = params.sourceThread.cwd?.trim() || void 0;
117
+ const pendingLastTurnId = codexLastTerminalTurnId(params.sourceThread, boundCatalogSessionId);
118
+ const marker = {
119
+ sourceThreadId: params.sourceThread.id,
120
+ ...params.sourceHomeId ? { sourceHomeId: params.sourceHomeId } : {}
121
+ };
122
+ const { createImportedCodexSession } = await import("./session-history-import-DFN7sWRU.js");
123
+ const created = await createImportedCodexSession({
124
+ runtime: params.api.runtime,
125
+ bindingStore: params.bindingStore,
126
+ config: params.config,
127
+ key: adoptionSessionKey(params.sourceThread.id, params.sourceHomeId),
128
+ agentId: params.agentId,
129
+ displayName: params.sourceThread.name ?? void 0,
130
+ thread: params.sourceThread,
131
+ throughTurnId: pendingLastTurnId ?? null,
132
+ recoverMatchingInitialEntry: true,
133
+ initialEntry: {
134
+ agentHarnessId: "codex",
135
+ modelSelectionLocked: true,
136
+ pluginExtensions: { codex: { supervision: {
137
+ ...marker,
138
+ initializing: true,
139
+ modelLocked: true
140
+ } } }
141
+ },
142
+ afterImport: async (entry, initialization) => {
143
+ const identity = sessionBindingIdentity({
144
+ sessionId: entry.sessionId,
145
+ sessionKey: entry.key,
146
+ config: params.config
147
+ });
148
+ await ensurePendingAdoptionBinding({
149
+ bindingStore: params.bindingStore,
150
+ config: params.config,
151
+ identity,
152
+ initialization,
153
+ sourceThreadId: params.sourceThread.id,
154
+ connectionFingerprint: params.connectionFingerprint,
155
+ cwd: spawnedCwd ?? "",
156
+ ...pendingLastTurnId ? { lastTurnId: pendingLastTurnId } : {}
157
+ });
158
+ return { pluginExtensions: { codex: { supervision: {
159
+ ...marker,
160
+ modelLocked: true
161
+ } } } };
162
+ }
163
+ });
164
+ return {
165
+ key: created.key,
166
+ sessionId: created.sessionId,
167
+ agentId: created.agentId,
168
+ boundThreadId: params.sourceThread.id
169
+ };
170
+ } catch (error) {
171
+ const raced = await findAdoptedSessionEntry(lookup);
172
+ if (raced) return raced;
173
+ throw error;
174
+ }
175
+ }
176
+ async function continueLocalCodexSessionInner(params) {
177
+ await params.control.requireEligibleThread(params.threadId);
178
+ const existing = await findAdoptedSessionEntry({
179
+ ...params,
180
+ runtime: params.api.runtime
181
+ });
182
+ if (existing) {
183
+ const boundThreadId = requireBoundThread(existing);
184
+ const boundThread = await params.control.readThread(boundThreadId, true);
185
+ if (boundThread.id !== boundThreadId) throw new Error("Codex app-server returned a different thread than requested");
186
+ const changedError = () => new CatalogParamsError("Codex OpenClaw session changed before it could be opened. Retry.");
187
+ if (!await params.api.runtime.agent.session.patchSessionEntry({
188
+ sessionKey: existing.key,
189
+ readConsistency: "latest",
190
+ preserveActivity: true,
191
+ update: (entry) => {
192
+ if (entry.sessionId?.trim() !== existing.sessionId || entry.initializationPending === true || entry.agentHarnessId !== "codex" || entry.modelSelectionLocked !== true) throw changedError();
193
+ return {
194
+ archivedAt: void 0,
195
+ archivedBy: void 0,
196
+ archiveReason: void 0
197
+ };
198
+ }
199
+ })) throw changedError();
200
+ const connectionFingerprint = params.control.connectionFingerprint;
201
+ if (connectionFingerprint) params.onContinued?.({
202
+ connectionFingerprint,
203
+ ...codexUpstreamBaseline(boundThread, boundCatalogSessionId)
204
+ });
205
+ return {
206
+ sessionKey: existing.key,
207
+ disposition: "existing"
208
+ };
209
+ }
210
+ const sourceThread = await params.control.readThread(params.threadId, true);
211
+ if (sourceThread.id !== params.threadId) throw new Error("Codex app-server returned a different thread than requested");
212
+ if (sourceThread.status?.type !== "notLoaded") requireIdleThread(sourceThread, "continue");
213
+ const connectionFingerprint = params.control.connectionFingerprint;
214
+ if (!connectionFingerprint) throw new Error("Codex Continue requires a pinned app-server connection");
215
+ const adopted = await createOrReuseAdoptedSession({
216
+ ...params,
217
+ sourceThread,
218
+ connectionFingerprint
219
+ });
220
+ const boundThreadId = requireBoundThread(adopted);
221
+ const baselineThread = boundThreadId === sourceThread.id ? sourceThread : await params.control.readThread(boundThreadId, true);
222
+ if (baselineThread.id !== boundThreadId) throw new Error("Codex app-server returned a different thread than requested");
223
+ params.onContinued?.({
224
+ connectionFingerprint,
225
+ ...codexUpstreamBaseline(baselineThread, boundCatalogSessionId)
226
+ });
227
+ return {
228
+ sessionKey: adopted.key,
229
+ disposition: "forked"
230
+ };
231
+ }
232
+ /** Creates one locked OpenClaw branch whose first harness run forks the Codex source. */
233
+ async function continueLocalCodexSession(params) {
234
+ const sourceKey = sessionCatalogAdoptedSourceKey(params.hostId ?? "gateway:local", params.threadId);
235
+ const operationKey = sessionCatalogAdoptedSourceKey(params.agentId, sourceKey);
236
+ const current = continueOperations.get(operationKey);
237
+ if (current) return await current;
238
+ const run = async (control) => await continueLocalCodexSessionInner({
239
+ ...params,
240
+ control
241
+ });
242
+ const operation = runSessionActionExclusive(sourceKey, async () => params.control.withPinnedConnection(run));
243
+ continueOperations.set(operationKey, operation);
244
+ try {
245
+ return await operation;
246
+ } finally {
247
+ if (continueOperations.get(operationKey) === operation) continueOperations.delete(operationKey);
248
+ }
249
+ }
250
+ //#endregion
251
+ export { continueLocalCodexSession, isAdoptionSessionKeyForThread, listAdoptedSessionEntries, requireIdleThread };
@@ -0,0 +1,56 @@
1
+ import { l as sessionBindingIdentity } from "./session-binding-record-CaZjYwNS.js";
2
+ import { t as assertCodexArchiveDescendantsUnowned } from "./thread-archive-guard-D1bP04Tf.js";
3
+ import { o as CatalogParamsError } from "./session-catalog-parsing-CdD3JhdM.js";
4
+ import "./session-binding-CKSepwIC.js";
5
+ import { runSessionActionExclusive } from "./session-catalog-node-adoption-BUuDYY8R.js";
6
+ import { isAdoptionSessionKeyForThread, requireIdleThread } from "./session-catalog-adoption-BKLtSrwi.js";
7
+ import { listAgentIds } from "openclaw/plugin-sdk/agent-scope-runtime";
8
+ import { sessionCatalogAdoptedSourceKey } from "openclaw/plugin-sdk/session-catalog";
9
+ //#region extensions/codex/src/session-catalog-archive.ts
10
+ function assertNoPendingSupervisionBranch(params) {
11
+ const adoptedEntries = [params.agentId, ...listAgentIds(params.config).filter((agentId) => agentId !== params.agentId)].flatMap((agentId) => params.runtime.agent.session.listSessionEntries({
12
+ agentId,
13
+ readOnly: true
14
+ })).filter((candidate) => isAdoptionSessionKeyForThread(candidate.sessionKey, params.threadId, params.sourceHomeId) || params.sourceHomeId !== void 0 && params.allowLegacy === true && isAdoptionSessionKeyForThread(candidate.sessionKey, params.threadId));
15
+ for (const adopted of adoptedEntries) {
16
+ if (adopted.entry.initializationPending === true) throw new CatalogParamsError("Codex session cannot be archived while its OpenClaw branch is initializing");
17
+ const sessionId = adopted.entry.sessionId?.trim();
18
+ if (!sessionId) continue;
19
+ const binding = params.bindingStore.read(sessionBindingIdentity({
20
+ sessionId,
21
+ sessionKey: adopted.sessionKey,
22
+ config: params.config
23
+ }));
24
+ if (binding?.connectionScope === "supervision" && binding.supervisionSourceThreadId === params.threadId && binding.pendingSupervisionBranch?.sourceThreadId === params.threadId) throw new CatalogParamsError("Codex session cannot be archived until its OpenClaw branch starts");
25
+ }
26
+ }
27
+ /** Archives one inactive Gateway-local Codex thread after a fresh status read. */
28
+ async function archiveLocalCodexSession(params) {
29
+ return await runSessionActionExclusive(sessionCatalogAdoptedSourceKey(params.hostId ?? "gateway:local", params.threadId), async () => {
30
+ return await params.bindingStore.withThreadArchiveFence(async () => {
31
+ const run = async (control) => {
32
+ assertNoPendingSupervisionBranch(params);
33
+ await control.requireEligibleThread(params.threadId);
34
+ const thread = await control.readThread(params.threadId, false);
35
+ if (thread.id !== params.threadId) throw new Error("Codex app-server returned a different thread than requested");
36
+ requireIdleThread(thread, "archive");
37
+ if (await params.bindingStore.hasOtherThreadOwner(params.threadId)) throw new CatalogParamsError("Codex session cannot be archived while it is attached to an OpenClaw session");
38
+ await assertCodexArchiveDescendantsUnowned({
39
+ bindingStore: params.bindingStore,
40
+ threadId: params.threadId,
41
+ listPage: (request) => control.listDescendantPage(request),
42
+ assertDescendantIdle: async (descendantThreadId) => {
43
+ const descendant = await control.readThread(descendantThreadId, false);
44
+ if (descendant.id !== descendantThreadId) throw new Error("Codex app-server returned a different descendant than requested");
45
+ requireIdleThread(descendant, "archive");
46
+ }
47
+ });
48
+ await control.archiveThread(params.threadId);
49
+ return { archived: true };
50
+ };
51
+ return await params.control.withPinnedConnection(run);
52
+ });
53
+ });
54
+ }
55
+ //#endregion
56
+ export { archiveLocalCodexSession };
@@ -0,0 +1,190 @@
1
+ import { t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-LphB8slG.js";
2
+ import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
+ import { createHash } from "node:crypto";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import { truncateUtf8Prefix } from "openclaw/plugin-sdk/text-utility-runtime";
7
+ import { Buffer } from "node:buffer";
8
+ //#region extensions/codex/src/app-server/transcript-history-projection.ts
9
+ const CODEX_HISTORY_IMPORT_MAX_MESSAGES = 200;
10
+ const CODEX_HISTORY_IMPORT_MAX_BYTES = 524288;
11
+ const CODEX_HISTORY_IMPORT_MAX_MESSAGE_BYTES = 65536;
12
+ const CODEX_HISTORY_TRUNCATION_SUFFIX = "\n\n[Message truncated during Codex history import.]";
13
+ const CODEX_HISTORY_ASSISTANT_API = "openai-chatgpt-responses";
14
+ const CODEX_HISTORY_ASSISTANT_PROVIDER = "openai";
15
+ const CODEX_HISTORY_ASSISTANT_MODEL = "native-history";
16
+ const CODEX_HISTORY_ZERO_USAGE = {
17
+ input: 0,
18
+ output: 0,
19
+ cacheRead: 0,
20
+ cacheWrite: 0,
21
+ totalTokens: 0,
22
+ cost: {
23
+ input: 0,
24
+ output: 0,
25
+ cacheRead: 0,
26
+ cacheWrite: 0,
27
+ total: 0
28
+ }
29
+ };
30
+ function normalizeImportedHistoryText(value) {
31
+ if (typeof value !== "string") return;
32
+ const text = value.trim();
33
+ if (!text) return;
34
+ if (Buffer.byteLength(text, "utf8") <= CODEX_HISTORY_IMPORT_MAX_MESSAGE_BYTES) return text;
35
+ const suffixBytes = Buffer.byteLength(CODEX_HISTORY_TRUNCATION_SUFFIX, "utf8");
36
+ const contentLimitBytes = Math.max(0, CODEX_HISTORY_IMPORT_MAX_MESSAGE_BYTES - suffixBytes);
37
+ return `${truncateUtf8Prefix(text, contentLimitBytes)}${CODEX_HISTORY_TRUNCATION_SUFFIX}`;
38
+ }
39
+ function projectCodexUserItemText(item) {
40
+ if (!Array.isArray(item.content)) return;
41
+ const parts = [];
42
+ for (const value of item.content) {
43
+ if (!value || typeof value !== "object" || Array.isArray(value)) continue;
44
+ const input = value;
45
+ if (input.type === "text") {
46
+ const text = normalizeImportedHistoryText(input.text);
47
+ if (text) parts.push(text);
48
+ continue;
49
+ }
50
+ if (input.type === "image" || input.type === "localImage") {
51
+ parts.push("[Image attachment]");
52
+ continue;
53
+ }
54
+ if (input.type === "audio" || input.type === "localAudio" || input.type === "local_audio") parts.push("[Audio attachment]");
55
+ if (input.type === "skill" || input.type === "mention") {
56
+ const name = normalizeOptionalString(input.name);
57
+ if (name) parts.push(`${input.type === "skill" ? "$" : "@"}${name}`);
58
+ }
59
+ }
60
+ return normalizeImportedHistoryText(parts.join("\n"));
61
+ }
62
+ function selectTurnsThroughBoundary(thread, throughTurnId) {
63
+ if (throughTurnId === null) return [];
64
+ const turns = thread.turns ?? [];
65
+ const boundaryIndex = turns.findIndex((turn) => turn.id === throughTurnId);
66
+ if (boundaryIndex < 0) throw new Error(`Codex history boundary turn not found: ${throughTurnId}`);
67
+ const boundary = turns[boundaryIndex];
68
+ if (boundary?.status !== "completed" && boundary?.status !== "interrupted" && boundary?.status !== "failed") throw new Error(`Codex history boundary turn is not terminal: ${throughTurnId}`);
69
+ return turns.slice(0, boundaryIndex + 1);
70
+ }
71
+ function projectCodexThreadHistory(params) {
72
+ const projected = [];
73
+ const threadTimestamp = typeof params.thread.createdAt === "number" && Number.isFinite(params.thread.createdAt) ? params.thread.createdAt * 1e3 : params.importedAt;
74
+ let itemOffset = 0;
75
+ for (const turn of selectTurnsThroughBoundary(params.thread, params.throughTurnId)) for (const value of turn.items) {
76
+ const item = value;
77
+ const itemId = normalizeOptionalString(item.id);
78
+ const identity = `${turn.id}:${itemId ?? itemOffset}`;
79
+ const timestampSeconds = item.type === "agentMessage" ? turn.completedAt ?? turn.startedAt : turn.startedAt ?? turn.completedAt;
80
+ const timestamp = typeof timestampSeconds === "number" && Number.isFinite(timestampSeconds) ? timestampSeconds * 1e3 + itemOffset : threadTimestamp + itemOffset;
81
+ const text = item.type === "userMessage" ? projectCodexUserItemText(item) : item.type === "agentMessage" ? normalizeImportedHistoryText(item.text) : void 0;
82
+ const role = item.type === "userMessage" ? "user" : item.type === "agentMessage" ? "assistant" : void 0;
83
+ itemOffset += 1;
84
+ if (!text || !role) continue;
85
+ const phase = item.phase === "commentary" || item.phase === "final_answer" ? item.phase : void 0;
86
+ const asyncDelivery = item.delivery === "async";
87
+ const message = role === "assistant" ? attachCodexMirrorIdentity({
88
+ role,
89
+ content: [{
90
+ type: "text",
91
+ text
92
+ }],
93
+ api: CODEX_HISTORY_ASSISTANT_API,
94
+ provider: normalizeOptionalString(params.modelProvider) ?? normalizeOptionalString(params.thread.modelProvider) ?? CODEX_HISTORY_ASSISTANT_PROVIDER,
95
+ model: CODEX_HISTORY_ASSISTANT_MODEL,
96
+ usage: CODEX_HISTORY_ZERO_USAGE,
97
+ stopReason: turn.status === "interrupted" ? "aborted" : turn.status === "failed" ? "error" : "stop",
98
+ ...turn.status === "failed" && turn.error?.message ? { errorMessage: turn.error.message } : {},
99
+ ...phase ? { phase } : {},
100
+ ...asyncDelivery && itemId ? { openclawAsyncDelivery: { itemId } } : {},
101
+ timestamp
102
+ }, identity) : attachCodexMirrorIdentity({
103
+ role,
104
+ content: text,
105
+ timestamp
106
+ }, identity);
107
+ projected.push({
108
+ message,
109
+ responseItem: {
110
+ type: "message",
111
+ role,
112
+ content: [{
113
+ type: role === "assistant" ? "output_text" : "input_text",
114
+ text
115
+ }],
116
+ ...role === "assistant" && phase ? { phase } : {}
117
+ },
118
+ textBytes: Buffer.byteLength(text, "utf8")
119
+ });
120
+ }
121
+ return projected;
122
+ }
123
+ function selectBoundedCodexHistoryTail(projected) {
124
+ const selected = [];
125
+ let selectedBytes = 0;
126
+ for (let index = projected.length - 1; index >= 0; index -= 1) {
127
+ const candidate = projected[index];
128
+ if (!candidate) continue;
129
+ if (selected.length >= CODEX_HISTORY_IMPORT_MAX_MESSAGES || selectedBytes + candidate.textBytes > CODEX_HISTORY_IMPORT_MAX_BYTES) break;
130
+ selected.push(candidate);
131
+ selectedBytes += candidate.textBytes;
132
+ }
133
+ return selected.toReversed();
134
+ }
135
+ /** Projects one terminal Codex history prefix into transcript and Responses API items. */
136
+ function projectBoundedCodexThreadHistory(params) {
137
+ const projected = projectCodexThreadHistory({
138
+ thread: params.thread,
139
+ throughTurnId: params.throughTurnId,
140
+ importedAt: params.importedAt,
141
+ ...params.modelProvider ? { modelProvider: params.modelProvider } : {}
142
+ });
143
+ const selected = selectBoundedCodexHistoryTail(projected);
144
+ return {
145
+ importedMessages: selected.length,
146
+ omittedMessages: projected.length - selected.length,
147
+ responseItems: selected.filter(({ message }) => message.role !== "assistant" || message.stopReason !== "aborted" && message.stopReason !== "error" && !("openclawAsyncDelivery" in message)).map(({ responseItem }) => responseItem),
148
+ transcriptMessages: selected.map(({ message }) => message)
149
+ };
150
+ }
151
+ /** Projects only visible local user/assistant messages through the same bounded history policy. */
152
+ function projectBoundedCodexVisibleSessionHistory(entries) {
153
+ const projected = [];
154
+ for (const entry of entries) {
155
+ if (entry.role !== "user" && entry.role !== "assistant" || !("content" in entry.message)) continue;
156
+ if (entry.role === "assistant" && ("stopReason" in entry.message && (entry.message.stopReason === "aborted" || entry.message.stopReason === "error") || "openclawAsyncDelivery" in entry.message)) continue;
157
+ const content = entry.message.content;
158
+ const text = normalizeImportedHistoryText(typeof content === "string" ? content : Array.isArray(content) ? content.flatMap((part) => part && typeof part === "object" && "text" in part && typeof part.text === "string" ? [part.text] : []).join("\n") : void 0);
159
+ if (!text) continue;
160
+ projected.push({
161
+ message: entry.message,
162
+ responseItem: {
163
+ type: "message",
164
+ role: entry.role,
165
+ content: [{
166
+ type: entry.role === "assistant" ? "output_text" : "input_text",
167
+ text
168
+ }]
169
+ },
170
+ textBytes: Buffer.byteLength(text, "utf8")
171
+ });
172
+ }
173
+ return selectBoundedCodexHistoryTail(projected).map(({ responseItem }) => responseItem);
174
+ }
175
+ //#endregion
176
+ //#region extensions/codex/src/session-catalog-home-id.ts
177
+ function canonicalCodexCatalogHome(value) {
178
+ const resolved = path.resolve(value);
179
+ try {
180
+ return fs.realpathSync.native(resolved);
181
+ } catch {
182
+ return resolved;
183
+ }
184
+ }
185
+ /** One canonical identity for catalog discovery and durable ownership rows. */
186
+ function codexCatalogHomeId(codexHome) {
187
+ return createHash("sha256").update("openclaw:codex-session-catalog-home:v1\0").update(canonicalCodexCatalogHome(codexHome)).digest("hex");
188
+ }
189
+ //#endregion
190
+ export { projectCodexUserItemText as a, projectBoundedCodexVisibleSessionHistory as i, codexCatalogHomeId as n, projectBoundedCodexThreadHistory as r, canonicalCodexCatalogHome as t };
@@ -0,0 +1,182 @@
1
+ import { o as CatalogParamsError } from "./session-catalog-parsing-CdD3JhdM.js";
2
+ import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
3
+ import { parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
4
+ import { resolveStorePath } from "openclaw/plugin-sdk/session-store-paths";
5
+ import { listSessionCatalogEntries, sessionCatalogAdoptedSessionKey, sessionCatalogAdoptedSourceKey } from "openclaw/plugin-sdk/session-catalog";
6
+ //#region extensions/codex/src/session-catalog-node-adoption.ts
7
+ const CODEX_NODE_SESSION_KEY_PREFIX = "harness:codex:node-session:";
8
+ const continueOperations = /* @__PURE__ */ new Map();
9
+ const sessionActionTails = /* @__PURE__ */ new Map();
10
+ async function runSessionActionExclusive(threadId, run) {
11
+ const operation = (sessionActionTails.get(threadId) ?? Promise.resolve()).then(run);
12
+ const tail = operation.then(() => void 0, () => void 0);
13
+ sessionActionTails.set(threadId, tail);
14
+ try {
15
+ return await operation;
16
+ } finally {
17
+ if (sessionActionTails.get(threadId) === tail) sessionActionTails.delete(threadId);
18
+ }
19
+ }
20
+ function adoptionSessionKeyRest(sessionKey) {
21
+ const trimmed = sessionKey.trim();
22
+ return parseAgentSessionKey(trimmed)?.rest ?? trimmed;
23
+ }
24
+ function nodeAdoptionSessionKey(hostId, threadId) {
25
+ const source = JSON.stringify([hostId, threadId]);
26
+ return sessionCatalogAdoptedSessionKey(CODEX_NODE_SESSION_KEY_PREFIX, source);
27
+ }
28
+ function readNodeSessionMarker(entry) {
29
+ const codex = isRecord(entry.pluginExtensions?.codex) ? entry.pluginExtensions.codex : void 0;
30
+ const marker = codex && isRecord(codex.sessionCatalog) ? codex.sessionCatalog : void 0;
31
+ if (!marker || typeof marker.sourceHostId !== "string" || !marker.sourceHostId.startsWith("node:") || typeof marker.sourceThreadId !== "string" || !marker.sourceThreadId.trim() || typeof marker.nodeId !== "string" || !marker.nodeId.trim()) return;
32
+ return {
33
+ sourceHostId: marker.sourceHostId,
34
+ sourceThreadId: marker.sourceThreadId,
35
+ nodeId: marker.nodeId,
36
+ ...marker.initializing === true ? { initializing: true } : {}
37
+ };
38
+ }
39
+ function listNodeAdoptedSessionEntries(params) {
40
+ const adopted = /* @__PURE__ */ new Map();
41
+ for (const { agentId, entry, sessionKey } of listSessionCatalogEntries({
42
+ ...params.agentId ? { agentId: params.agentId } : {},
43
+ config: params.config ?? {},
44
+ runtime: params.runtime,
45
+ sessionEntries: params.sessionEntries
46
+ })) {
47
+ const marker = readNodeSessionMarker(entry);
48
+ const sessionId = entry.sessionId?.trim();
49
+ if (!marker || marker.initializing === true && params.includeInitializing !== true || entry.initializationPending === true || entry.agentHarnessId !== "codex" || entry.modelSelectionLocked !== true || !sessionId || adoptionSessionKeyRest(sessionKey) !== nodeAdoptionSessionKey(marker.sourceHostId, marker.sourceThreadId) || marker.sourceHostId !== `node:${marker.nodeId}`) continue;
50
+ const sourceKey = sessionCatalogAdoptedSourceKey(marker.sourceHostId, marker.sourceThreadId);
51
+ if (adopted.has(sourceKey)) throw new Error(`multiple OpenClaw sessions adopt Codex thread ${marker.sourceThreadId} on ${marker.sourceHostId}`);
52
+ adopted.set(sourceKey, {
53
+ key: sessionKey,
54
+ sessionId,
55
+ agentId,
56
+ ...marker.initializing === true ? { initializing: true } : {}
57
+ });
58
+ }
59
+ return adopted;
60
+ }
61
+ function findNodeAdoptedSessionEntry(params) {
62
+ return listNodeAdoptedSessionEntries(params).get(sessionCatalogAdoptedSourceKey(params.hostId, params.threadId));
63
+ }
64
+ function nodeSessionMarker(params) {
65
+ return {
66
+ sourceHostId: params.hostId,
67
+ sourceThreadId: params.threadId,
68
+ nodeId: params.nodeId,
69
+ ...params.initializing === true ? { initializing: true } : {}
70
+ };
71
+ }
72
+ async function finalizeNodeAdoptedSession(params) {
73
+ const changedError = () => new CatalogParamsError("Codex OpenClaw session changed before it could be bound. Retry.");
74
+ let finalized;
75
+ try {
76
+ finalized = await params.api.runtime.agent.session.patchSessionEntry({
77
+ sessionKey: params.adopted.key,
78
+ readConsistency: "latest",
79
+ preserveActivity: true,
80
+ update: (entry) => {
81
+ const current = readNodeSessionMarker(entry);
82
+ if (entry.sessionId?.trim() !== params.adopted.sessionId || entry.initializationPending === true || entry.agentHarnessId !== "codex" || entry.modelSelectionLocked !== true || !current || current.sourceHostId !== params.marker.sourceHostId || current.sourceThreadId !== params.marker.sourceThreadId || current.nodeId !== params.marker.nodeId) throw changedError();
83
+ if (current.initializing !== true) return {
84
+ archivedAt: void 0,
85
+ archivedBy: void 0,
86
+ archiveReason: void 0
87
+ };
88
+ const codex = isRecord(entry.pluginExtensions?.codex) ? entry.pluginExtensions.codex : {};
89
+ return {
90
+ archivedAt: void 0,
91
+ archivedBy: void 0,
92
+ archiveReason: void 0,
93
+ pluginExtensions: {
94
+ ...entry.pluginExtensions,
95
+ codex: {
96
+ ...codex,
97
+ sessionCatalog: params.marker
98
+ }
99
+ }
100
+ };
101
+ }
102
+ });
103
+ } catch (error) {
104
+ const currentEntry = params.api.runtime.agent.session.getSessionEntry({
105
+ sessionKey: params.adopted.key,
106
+ readConsistency: "latest"
107
+ });
108
+ const current = currentEntry ? readNodeSessionMarker(currentEntry) : void 0;
109
+ if (currentEntry?.sessionId?.trim() === params.adopted.sessionId && current?.initializing !== true && current?.sourceHostId === params.marker.sourceHostId && current.sourceThreadId === params.marker.sourceThreadId && current.nodeId === params.marker.nodeId) return;
110
+ throw error;
111
+ }
112
+ if (!finalized) throw changedError();
113
+ }
114
+ async function createOrReuseNodeAdoptedSession(params) {
115
+ const existing = findNodeAdoptedSessionEntry({
116
+ agentId: params.agentId,
117
+ config: params.config,
118
+ runtime: params.api.runtime,
119
+ hostId: params.hostId,
120
+ threadId: params.record.threadId,
121
+ includeInitializing: true
122
+ });
123
+ if (existing) return existing;
124
+ const initializingMarker = {
125
+ ...nodeSessionMarker({
126
+ hostId: params.hostId,
127
+ threadId: params.record.threadId,
128
+ nodeId: params.nodeId
129
+ }),
130
+ initializing: true
131
+ };
132
+ try {
133
+ const created = await params.api.runtime.agent.session.createSessionEntry({
134
+ cfg: params.config,
135
+ key: nodeAdoptionSessionKey(params.hostId, params.record.threadId),
136
+ agentId: params.agentId,
137
+ recoverMatchingInitialEntry: true,
138
+ displayName: params.record.name ?? void 0,
139
+ ...params.record.cwd?.trim() ? { spawnedCwd: params.record.cwd.trim() } : {},
140
+ initialEntry: {
141
+ agentHarnessId: "codex",
142
+ modelSelectionLocked: true,
143
+ pluginExtensions: { codex: { sessionCatalog: initializingMarker } }
144
+ },
145
+ afterCreate: async (entry) => {
146
+ const storePath = resolveStorePath(params.config.session?.store, { agentId: entry.agentId });
147
+ const { importCodexThreadHistoryToTranscript } = await import("./transcript-mirror-t5TOccct.js").then((n) => n.a);
148
+ await importCodexThreadHistoryToTranscript({
149
+ thread: params.history.thread,
150
+ throughTurnId: params.history.throughTurnId,
151
+ storePath,
152
+ sessionId: entry.sessionId,
153
+ sessionKey: entry.key,
154
+ agentId: entry.agentId,
155
+ ...params.record.cwd?.trim() ? { cwd: params.record.cwd.trim() } : {},
156
+ modelProvider: params.record.modelProvider,
157
+ config: params.config
158
+ });
159
+ return { pluginExtensions: { codex: { sessionCatalog: initializingMarker } } };
160
+ }
161
+ });
162
+ return {
163
+ key: created.key,
164
+ sessionId: created.sessionId,
165
+ agentId: created.agentId,
166
+ initializing: true
167
+ };
168
+ } catch (error) {
169
+ const raced = findNodeAdoptedSessionEntry({
170
+ agentId: params.agentId,
171
+ config: params.config,
172
+ runtime: params.api.runtime,
173
+ hostId: params.hostId,
174
+ threadId: params.record.threadId,
175
+ includeInitializing: true
176
+ });
177
+ if (raced) return raced;
178
+ throw error;
179
+ }
180
+ }
181
+ //#endregion
182
+ export { adoptionSessionKeyRest, continueOperations, createOrReuseNodeAdoptedSession, finalizeNodeAdoptedSession, findNodeAdoptedSessionEntry, listNodeAdoptedSessionEntries, nodeSessionMarker, runSessionActionExclusive };