@openclaw/codex 2026.9.2 → 2026.9.4

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 (120) hide show
  1. package/README.md +2 -0
  2. package/dist/api.js +29 -26
  3. package/dist/apply-CvT8tW5i.js +356 -0
  4. package/dist/{attempt-client-cleanup-Bp1ZOnk2.js → attempt-client-cleanup-DKHzbwt5.js} +38 -214
  5. package/dist/{attempt-context-CSazkWns.js → attempt-context-D44yeDII.js} +9 -7
  6. package/dist/{event-projector-usage-ZqEVbAEY.js → attempt-notifications-C9XufG6l.js} +3 -106
  7. package/dist/{auth-binding-Ds_QVm-X.js → auth-binding-CWlKVccJ.js} +2 -2
  8. package/dist/auth-cache-key-7orQae_j.js +498 -0
  9. package/dist/auth-profile-CwzO4_RG.js +43 -0
  10. package/dist/auth-profile-selection-DFu9e167.js +45 -0
  11. package/dist/binding-connection-D3udKbIE.js +60 -0
  12. package/dist/{bounded-turn-DxGJRYbY.js → bounded-turn-C_Hneydj.js} +28 -125
  13. package/dist/build-state-BCmg9-5p.js +19 -0
  14. package/dist/{capabilities-B1mgvpP8.js → capabilities-8vx68WLH.js} +1 -1
  15. package/dist/cli-metadata.js +1 -1
  16. package/dist/client-B57KWPQx.js +4005 -0
  17. package/dist/command-dispatch-BpduNGVf.js +21 -0
  18. package/dist/{command-formatters-DSbGMXA0.js → command-formatters-lxlkNZgU.js} +4 -3
  19. package/dist/{command-handlers-DOJvGv6-.js → command-handlers-tiL9iWj7.js} +788 -135
  20. package/dist/command-rpc-CR5EOEZX.js +233 -0
  21. package/dist/{compact-Y_xBqrHN.js → compact-B_H3AOd7.js} +19 -14
  22. package/dist/config-oIORaQ5T.js +106 -0
  23. package/dist/{config-CyapYSji.js → config-options-CXMq1T-C.js} +205 -593
  24. package/dist/config-runtime-D0zGNIHu.js +11 -0
  25. package/dist/{config-utils-C57JiJrU.js → config-utils-DujwEnhg.js} +2 -4
  26. package/dist/conversation-binding-DsB4-O7U.js +900 -0
  27. package/dist/{plugin-marketplace-discovery-B7gHXJ3d.js → conversation-control-CtUu1b3m.js} +11 -143
  28. package/dist/doctor-contract-api.js +5 -5
  29. package/dist/{dynamic-tools-BwpvTxaX.js → dynamic-tools-CmN5RAip.js} +133 -76
  30. package/dist/{effective-mcp-catalog-CY9Jn4bA.js → effective-mcp-catalog-Bd73bqA8.js} +3 -3
  31. package/dist/{elicitation-input-DMkeki8d.js → elicitation-input-DPoK8F7w.js} +8 -22
  32. package/dist/ephemeral-turn-D78_VmzO.js +101 -0
  33. package/dist/{event-projector-assistant-message-B9kp6iGC.js → event-projector-assistant-message-BmBM4qBV.js} +12 -25
  34. package/dist/event-projector-items-5VhsECCO.js +200 -0
  35. package/dist/event-projector-usage-BfXmpOec.js +102 -0
  36. package/dist/{harness-Czh2Sdoc.js → harness-C7rRa7bm.js} +48 -24
  37. package/dist/harness.js +1 -1
  38. package/dist/history-rejection-B4nOXNXF.js +13 -0
  39. package/dist/incognito-session-uhrBF6wJ.js +15 -0
  40. package/dist/index.js +406 -2915
  41. package/dist/inference-context-Dr_mzvk4.js +94 -0
  42. package/dist/inference-proxy-HGXKUIre.js +311 -0
  43. package/dist/{isolated-completion-CRh-51AK.js → isolated-completion-DWVb5U2J.js} +7 -4
  44. package/dist/launch-args-RXQwn8zV.js +90 -0
  45. package/dist/{managed-binary-DcpnJF9x.js → managed-binary-D22rNEcR.js} +13 -103
  46. package/dist/managed-thread-store-D1t5jh3G.js +66 -0
  47. package/dist/media-understanding-provider.js +4 -1
  48. package/dist/migration-provider-api.js +2 -0
  49. package/dist/{model-catalog-DT5vo6qo.js → model-catalog-Dq2n8f_p.js} +6 -5
  50. package/dist/{models-CcrgSMQR.js → models-PCKOim-h.js} +3 -3
  51. package/dist/native-execution-policy-umd0tgh4.js +128 -0
  52. package/dist/native-subagent-history-DjtPloaU.js +140 -0
  53. package/dist/native-subagent-history-owner-Pcp7JuVF.js +34 -0
  54. package/dist/{native-subagent-monitor-B3bvQGcg.js → native-subagent-monitor-fQ7eIXEf.js} +115 -460
  55. package/dist/native-subagent-task-ids-BzTdT0Uw.js +387 -0
  56. package/dist/node-cli-sessions-DKaOmVUh.js +527 -0
  57. package/dist/{node-exec-server.runtime-nfbUOtUB.js → node-exec-server.runtime-Cl2vapEi.js} +55 -24
  58. package/dist/plan-7uG-Fp36.js +947 -0
  59. package/dist/plugin-activation-BYQculil.js +138 -0
  60. package/dist/{thread-resume-BLgqkUc1.js → plugin-app-cache-key-d0eKxy7b.js} +4 -52
  61. package/dist/{plugin-approval-roundtrip-aQVdyL5g.js → plugin-approval-roundtrip-Bz3FT8W5.js} +1 -1
  62. package/dist/plugin-inventory-oL4Na1ZG.js +328 -0
  63. package/dist/plugin-marketplace-discovery-P-Vndfqq.js +137 -0
  64. package/dist/{plugin-metadata-cache-BwCLTY_U.js → plugin-metadata-cache-ClPJpRio.js} +17 -9
  65. package/dist/protocol-5bh1G-H7.js +275 -0
  66. package/dist/provider-MQ8PVkuE.js +50 -0
  67. package/dist/{provider-capabilities-BpG9Ltc5.js → provider-capabilities-BvCUL69A.js} +2 -2
  68. package/dist/{rate-limits-Fx_l4eNa.js → rate-limits-CBMmWBr9.js} +1 -1
  69. package/dist/request-B7hEkBGq.js +212 -0
  70. package/dist/rpc-error-ttN_QjEm.js +30 -0
  71. package/dist/{run-attempt-BzthFQSM.js → run-attempt-CvsAAGa0.js} +664 -377
  72. package/dist/{runtime-artifact-Bh_gf6-t.js → runtime-artifact-BJ0rXBZ_.js} +27 -27
  73. package/dist/sandbox-guard-BxgyoM8M.js +166 -0
  74. package/dist/{session-binding-4Ki04sW-.js → session-binding-CI8UuilT.js} +30 -48
  75. package/dist/{session-binding-record-CyaXZvTe.js → session-binding-record-Bcvslnhf.js} +12 -26
  76. package/dist/session-catalog-adoption-tcZi1IfX.js +251 -0
  77. package/dist/session-catalog-archive-CwKg8Xz2.js +56 -0
  78. package/dist/session-catalog-ct-AH01I.js +1477 -0
  79. package/dist/session-catalog-home-id-CwhLdC03.js +18 -0
  80. package/dist/session-catalog-node-adoption-B1tgDW-m.js +182 -0
  81. package/dist/session-catalog-node-continue-Ci-DXyJP.js +238 -0
  82. package/dist/session-catalog-provenance-D-dIfRAH.js +96 -0
  83. package/dist/{session-cli-BjLhpmS1.js → session-cli-DNN_jhGc.js} +3 -2
  84. package/dist/{session-history-DWmMqiqW.js → session-history-Cz-tOOYj.js} +6 -3
  85. package/dist/{session-upstream-marker-DReTpGz6.js → session-history-import-DwyijFI6.js} +5 -50
  86. package/dist/{session-history-read-LHldwvyh.js → session-history-read-cxPUxyVV.js} +21 -7
  87. package/dist/session-history-worker-runtime.js +18 -6
  88. package/dist/session-history.worker-BeK1YOyT.js +378 -0
  89. package/dist/session-history.worker.js +1 -1
  90. package/dist/{session-initialization-BCFVnLL4.js → session-initialization-Ct0_Hzmg.js} +2 -2
  91. package/dist/{session-permission-policy-BaueHmSj.js → session-permission-policy-BBmXA8Eg.js} +4 -7
  92. package/dist/{session-retirement-DNdmYdFc.js → session-retirement-B2YfbAAT.js} +6 -5
  93. package/dist/session-upstream-marker-D15C9NHp.js +46 -0
  94. package/dist/{settled-turn-context-BOM3Y1pl.js → settled-turn-context-Du6gdUDd.js} +9 -9
  95. package/dist/{settled-turn-finalizer-BI-b1sry.js → settled-turn-finalizer-Dn91stmc.js} +8 -7
  96. package/dist/shared-client-CscigXXL.js +3109 -0
  97. package/dist/{side-question-B6DWAw1A.js → side-question-BGMJQf4U.js} +65 -170
  98. package/dist/source-CElXU0Oy.js +518 -0
  99. package/dist/thread-archive-guard-DfpBr-Sz.js +53 -0
  100. package/dist/thread-history-page-D0JIp48V.js +361 -0
  101. package/dist/{thread-lifecycle-DPK30jad.js → thread-lifecycle-DXl1-I6b.js} +187 -639
  102. package/dist/{thread-ownership-CbucAmmp.js → thread-ownership-BsDRTsyp.js} +13 -15
  103. package/dist/thread-policy-BuEQfE0g.js +54 -0
  104. package/dist/thread-resume-DsDOZpFg.js +52 -0
  105. package/dist/timeout-BVw8aaM1.js +33 -0
  106. package/dist/transcript-history-projection-v17wXgdK.js +238 -0
  107. package/dist/{transcript-mirror-_njEB84z.js → transcript-mirror-C5CKgNy6.js} +50 -260
  108. package/dist/{transcript-mirror-attestation-Byl34PC-.js → transcript-mirror-attestation-DibE0krH.js} +17 -4
  109. package/dist/{transport-stdio-CzTngV0j.js → transport-stdio-BGjHoYLr.js} +73 -43
  110. package/dist/{upstream-session-fork-1fwbNKzQ.js → upstream-session-fork-BZerMte_.js} +27 -19
  111. package/dist/{usage-i9fv5-4m.js → usage-tCk-mg_x.js} +4 -3
  112. package/dist/version-omm6IPI3.js +12 -0
  113. package/dist/{web-search-provider.runtime-DKQn67A7.js → web-search-provider.runtime-B7bGbGWq.js} +3 -3
  114. package/openclaw.plugin.json +23 -1
  115. package/package.json +4 -4
  116. package/dist/request-C8H22rPi.js +0 -475
  117. package/dist/session-catalog-B47uwekb.js +0 -3272
  118. package/dist/session-history.worker-zZVcx0ME.js +0 -267
  119. package/dist/shared-client-CKhX2kFt.js +0 -7505
  120. package/dist/thread-policy-CTalhWFy.js +0 -105
@@ -0,0 +1,18 @@
1
+ import { createHash } from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ //#region extensions/codex/src/session-catalog-home-id.ts
5
+ function canonicalCodexCatalogHome(value) {
6
+ const resolved = path.resolve(value);
7
+ try {
8
+ return fs.realpathSync.native(resolved);
9
+ } catch {
10
+ return resolved;
11
+ }
12
+ }
13
+ /** One canonical identity for catalog discovery and durable ownership rows. */
14
+ function codexCatalogHomeId(codexHome) {
15
+ return createHash("sha256").update("openclaw:codex-session-catalog-home:v1\0").update(canonicalCodexCatalogHome(codexHome)).digest("hex");
16
+ }
17
+ //#endregion
18
+ export { codexCatalogHomeId as n, canonicalCodexCatalogHome as t };
@@ -0,0 +1,182 @@
1
+ import { c as CatalogParamsError } from "./thread-history-page-D0JIp48V.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-C5CKgNy6.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 };
@@ -0,0 +1,238 @@
1
+ import { n as createCodexCliNodeConversationBindingData } from "./conversation-binding-data-BiodpIzq.js";
2
+ import { t as CODEX_CLI_SESSION_RESUME_COMMAND } from "./node-cli-sessions-DKaOmVUh.js";
3
+ import { a as lookupNodeCodexCatalogRecord } from "./session-catalog-ct-AH01I.js";
4
+ import { D as unwrapNodeInvokePayload, _ as parseCatalogPage, a as CODEX_APP_SERVER_THREAD_TURNS_LIST_COMMAND, c as CatalogParamsError, d as NODE_INVOKE_TIMEOUT_MS, f as boundedCatalogString, h as isInteractiveThreadSource, i as CODEX_APP_SERVER_THREADS_LIST_COMMAND, m as filterCatalogPageByTitle, p as catalogError, y as parseTranscriptPage } from "./thread-history-page-D0JIp48V.js";
5
+ import { t as codexLastTerminalTurnId } from "./session-upstream-marker-D15C9NHp.js";
6
+ import { n as withTimeout } from "./timeout-BVw8aaM1.js";
7
+ import { createOrReuseNodeAdoptedSession, finalizeNodeAdoptedSession, findNodeAdoptedSessionEntry, nodeSessionMarker, runSessionActionExclusive } from "./session-catalog-node-adoption-B1tgDW-m.js";
8
+ import { resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
9
+ import { createSessionCatalogAdoptionCoordinator, publishSessionCatalogHost, sessionCatalogAdoptedSourceKey } from "openclaw/plugin-sdk/session-catalog";
10
+ //#region extensions/codex/src/session-catalog-node-continue.ts
11
+ const CODEX_NODE_CONTINUE_COMMANDS = [
12
+ CODEX_APP_SERVER_THREADS_LIST_COMMAND,
13
+ CODEX_APP_SERVER_THREAD_TURNS_LIST_COMMAND,
14
+ CODEX_CLI_SESSION_RESUME_COMMAND
15
+ ];
16
+ const NODE_CATALOG_LIST_RESPONSE_TIMEOUT_MS = 8e3;
17
+ const continueNodeAdoption = createSessionCatalogAdoptionCoordinator();
18
+ function nodeLabel(node) {
19
+ return node.displayName?.trim() || node.remoteIp?.trim() || node.nodeId;
20
+ }
21
+ function compareNodeLabels(left, right) {
22
+ const leftLabel = nodeLabel(left);
23
+ const rightLabel = nodeLabel(right);
24
+ if (leftLabel < rightLabel) return -1;
25
+ if (leftLabel > rightLabel) return 1;
26
+ return 0;
27
+ }
28
+ function canContinueCodexOnNode(node) {
29
+ return node.connected === true && CODEX_NODE_CONTINUE_COMMANDS.every((command) => node.commands?.includes(command) === true && node.invocableCommands?.includes(command) === true);
30
+ }
31
+ async function listPairedNode(params) {
32
+ const hostId = `node:${params.node.nodeId}`;
33
+ const common = {
34
+ hostId,
35
+ label: nodeLabel(params.node),
36
+ kind: "node",
37
+ nodeId: params.node.nodeId,
38
+ canContinueCodex: canContinueCodexOnNode(params.node),
39
+ ...params.terminalCapabilities
40
+ };
41
+ if (params.node.connected !== true) {
42
+ const host = {
43
+ ...common,
44
+ connected: false,
45
+ sessions: [],
46
+ error: {
47
+ code: "NODE_OFFLINE",
48
+ message: "Paired node is offline"
49
+ }
50
+ };
51
+ params.onHost?.(host);
52
+ return host;
53
+ }
54
+ if (!params.node.commands?.includes("codex.appServer.threads.list.v1")) {
55
+ const host = {
56
+ ...common,
57
+ connected: true,
58
+ sessions: []
59
+ };
60
+ params.onHost?.(host);
61
+ return host;
62
+ }
63
+ const eventualHost = Promise.resolve().then(async () => {
64
+ const raw = await params.runtime.nodes.invoke({
65
+ nodeId: params.node.nodeId,
66
+ command: CODEX_APP_SERVER_THREADS_LIST_COMMAND,
67
+ params: {
68
+ agentId: params.agentId,
69
+ cursor: params.query.cursors?.[hostId],
70
+ limit: params.query.limitPerHost,
71
+ searchTerm: params.query.search
72
+ },
73
+ timeoutMs: NODE_INVOKE_TIMEOUT_MS,
74
+ scopes: ["operator.write"],
75
+ signal: params.signal
76
+ });
77
+ const page = filterCatalogPageByTitle(parseCatalogPage(unwrapNodeInvokePayload(raw)), params.query.search);
78
+ return {
79
+ ...common,
80
+ connected: true,
81
+ ...page,
82
+ sessions: page.sessions.map((session) => {
83
+ const adopted = params.adoptedSessions.get(sessionCatalogAdoptedSourceKey(hostId, session.threadId));
84
+ return adopted ? Object.assign({}, session, { sessionKey: adopted.key }) : session;
85
+ })
86
+ };
87
+ }).catch((error) => ({
88
+ ...common,
89
+ connected: true,
90
+ sessions: [],
91
+ error: catalogError("NODE_INVOKE_FAILED", error)
92
+ }));
93
+ publishSessionCatalogHost(params, eventualHost);
94
+ try {
95
+ return await withTimeout(eventualHost, NODE_CATALOG_LIST_RESPONSE_TIMEOUT_MS, "paired node Codex session catalog timed out");
96
+ } catch (error) {
97
+ return {
98
+ ...common,
99
+ connected: true,
100
+ sessions: [],
101
+ error: catalogError("NODE_INVOKE_FAILED", error)
102
+ };
103
+ }
104
+ }
105
+ async function requireNodeForCodexContinue(params) {
106
+ const nodeId = params.hostId.slice(5).trim();
107
+ if (!nodeId || params.hostId !== `node:${nodeId}`) throw new CatalogParamsError("Codex session catalog hostId is invalid");
108
+ const node = (await params.runtime.nodes.list()).nodes.find((candidate) => candidate.nodeId === nodeId);
109
+ if (!node || !canContinueCodexOnNode(node)) throw new CatalogParamsError("paired node does not permit Codex session continuation");
110
+ return {
111
+ node,
112
+ nodeId
113
+ };
114
+ }
115
+ function requireContinuableNodeRecord(record) {
116
+ if (record.archived) throw new CatalogParamsError("Codex session is archived on the paired node");
117
+ if (!isInteractiveThreadSource(record.source)) throw new CatalogParamsError("Codex session is not a non-archived interactive Codex session");
118
+ if (record.status === "idle" || record.status === "notLoaded") return;
119
+ if (record.status === "active") throw new CatalogParamsError("Codex session is active on the paired node; wait for it to finish before continuing");
120
+ throw new CatalogParamsError("Codex session cannot be continued in its current state");
121
+ }
122
+ async function readNodeCodexHistory(params) {
123
+ const raw = await params.runtime.nodes.invoke({
124
+ nodeId: params.nodeId,
125
+ command: CODEX_APP_SERVER_THREAD_TURNS_LIST_COMMAND,
126
+ params: {
127
+ agentId: params.agentId,
128
+ threadId: params.record.threadId,
129
+ limit: 50
130
+ },
131
+ timeoutMs: NODE_INVOKE_TIMEOUT_MS,
132
+ scopes: ["operator.write"]
133
+ });
134
+ const page = parseTranscriptPage(unwrapNodeInvokePayload(raw));
135
+ const thread = {
136
+ id: params.record.threadId,
137
+ createdAt: params.record.createdAt ?? 0,
138
+ modelProvider: params.record.modelProvider ?? "openai",
139
+ projectId: null,
140
+ turns: page.data.toReversed()
141
+ };
142
+ return {
143
+ thread,
144
+ throughTurnId: codexLastTerminalTurnId(thread, (value) => boundedCatalogString(value, 256)) ?? null
145
+ };
146
+ }
147
+ async function continueNodeCodexSessionInner(params) {
148
+ const { nodeId } = await requireNodeForCodexContinue({
149
+ runtime: params.api.runtime,
150
+ hostId: params.hostId
151
+ });
152
+ const lookup = await lookupNodeCodexCatalogRecord({
153
+ agentId: params.agentId,
154
+ runtime: params.api.runtime,
155
+ nodeId,
156
+ threadId: params.threadId
157
+ });
158
+ if (lookup.kind !== "found") throw new CatalogParamsError(lookup.kind === "cursor-cycle" ? "Codex session eligibility could not be verified" : "Codex session is unavailable on the paired node");
159
+ const record = lookup.record;
160
+ requireContinuableNodeRecord(record);
161
+ const existing = findNodeAdoptedSessionEntry({
162
+ agentId: params.agentId,
163
+ config: params.config,
164
+ runtime: params.api.runtime,
165
+ hostId: params.hostId,
166
+ threadId: params.threadId,
167
+ includeInitializing: true
168
+ });
169
+ let adopted;
170
+ let disposition;
171
+ if (existing) {
172
+ adopted = existing;
173
+ disposition = "existing";
174
+ } else {
175
+ const history = await readNodeCodexHistory({
176
+ agentId: params.agentId,
177
+ runtime: params.api.runtime,
178
+ nodeId,
179
+ record
180
+ });
181
+ adopted = await createOrReuseNodeAdoptedSession({
182
+ agentId: params.agentId,
183
+ api: params.api,
184
+ config: params.config,
185
+ hostId: params.hostId,
186
+ nodeId,
187
+ record,
188
+ history
189
+ });
190
+ disposition = "forked";
191
+ }
192
+ const marker = nodeSessionMarker({
193
+ hostId: params.hostId,
194
+ threadId: params.threadId,
195
+ nodeId
196
+ });
197
+ return {
198
+ sessionKey: adopted.key,
199
+ disposition,
200
+ conversationBinding: {
201
+ summary: "Continue this Codex session on its paired node.",
202
+ detachHint: "Start a new chat to leave the paired-node Codex session.",
203
+ data: createCodexCliNodeConversationBindingData({
204
+ nodeId,
205
+ sessionId: params.threadId,
206
+ agentId: adopted.agentId,
207
+ cwd: record.cwd
208
+ })
209
+ },
210
+ afterConversationBound: async () => await finalizeNodeAdoptedSession({
211
+ api: params.api,
212
+ adopted,
213
+ marker
214
+ })
215
+ };
216
+ }
217
+ async function continueNodeCodexSession(params) {
218
+ if (params.clientScopes?.includes("operator.admin") !== true) throw new CatalogParamsError("continuing a paired-node Codex session requires operator.admin");
219
+ const nodeId = params.hostId.slice(5).trim();
220
+ if (!nodeId || params.hostId !== `node:${nodeId}`) throw new CatalogParamsError("Codex session catalog hostId is invalid");
221
+ const agentId = resolveSessionAgentIdsStrict({
222
+ config: params.config,
223
+ agentId: params.agentId
224
+ }).sessionAgentId;
225
+ const sourceKey = sessionCatalogAdoptedSourceKey(`node:${nodeId}`, params.threadId);
226
+ const operationKey = sessionCatalogAdoptedSourceKey(agentId, sourceKey);
227
+ return await continueNodeAdoption({
228
+ sourceKey: operationKey,
229
+ findExisting: () => void 0,
230
+ create: () => runSessionActionExclusive(sourceKey, async () => continueNodeCodexSessionInner({
231
+ ...params,
232
+ agentId
233
+ })),
234
+ complete: async (continued) => continued
235
+ });
236
+ }
237
+ //#endregion
238
+ export { compareNodeLabels, continueNodeCodexSession, listPairedNode, nodeLabel };
@@ -0,0 +1,96 @@
1
+ import { o as isJsonObject } from "./protocol-5bh1G-H7.js";
2
+ import path from "node:path";
3
+ import { createZstdDecompress } from "node:zlib";
4
+ import { root } from "openclaw/plugin-sdk/file-access-runtime";
5
+ //#region extensions/codex/src/session-catalog-provenance.ts
6
+ const MAX_SESSION_META_BYTES = 1048576;
7
+ const SESSION_META_READ_CHUNK_BYTES = 65536;
8
+ const MAX_PROVENANCE_CACHE_ENTRIES = 2e4;
9
+ const provenanceByPath = /* @__PURE__ */ new Map();
10
+ function cacheProvenance(key, value) {
11
+ provenanceByPath.delete(key);
12
+ provenanceByPath.set(key, value);
13
+ while (provenanceByPath.size > MAX_PROVENANCE_CACHE_ENTRIES) {
14
+ const oldest = provenanceByPath.keys().next().value;
15
+ if (oldest === void 0) break;
16
+ provenanceByPath.delete(oldest);
17
+ }
18
+ }
19
+ /** Undefined means the metadata line is not durable enough to cache yet. */
20
+ async function readCodexSessionMeta(sessionsRoot, rolloutPath, threadId) {
21
+ let safeRoot;
22
+ try {
23
+ safeRoot = await root(sessionsRoot, {
24
+ hardlinks: "reject",
25
+ maxBytes: Number.MAX_SAFE_INTEGER,
26
+ symlinks: "reject"
27
+ });
28
+ } catch {
29
+ return;
30
+ }
31
+ const candidates = rolloutPath.endsWith(".zst") ? [rolloutPath, rolloutPath.slice(0, -4)] : [rolloutPath, `${rolloutPath}.zst`];
32
+ for (const candidate of candidates) {
33
+ let opened;
34
+ try {
35
+ opened = await safeRoot.open(path.relative(sessionsRoot, candidate));
36
+ } catch {
37
+ continue;
38
+ }
39
+ const input = opened.handle.createReadStream({
40
+ autoClose: false,
41
+ highWaterMark: SESSION_META_READ_CHUNK_BYTES
42
+ });
43
+ const reader = candidate.endsWith(".zst") ? input.pipe(createZstdDecompress()) : input;
44
+ try {
45
+ const chunks = [];
46
+ let bytesReadTotal = 0;
47
+ let line;
48
+ for await (const value of reader) {
49
+ const chunk = Buffer.isBuffer(value) ? value : Buffer.from(value);
50
+ const remaining = MAX_SESSION_META_BYTES - bytesReadTotal;
51
+ if (remaining <= 0) break;
52
+ const bounded = chunk.subarray(0, remaining);
53
+ bytesReadTotal += bounded.length;
54
+ const newline = bounded.indexOf(10);
55
+ chunks.push(newline >= 0 ? bounded.subarray(0, newline) : bounded);
56
+ if (newline >= 0) {
57
+ line = Buffer.concat(chunks).toString("utf8");
58
+ break;
59
+ }
60
+ }
61
+ if (!line) continue;
62
+ let parsed;
63
+ try {
64
+ parsed = JSON.parse(line);
65
+ } catch {
66
+ continue;
67
+ }
68
+ if (!isJsonObject(parsed) || parsed.type !== "session_meta" || !isJsonObject(parsed.payload)) return null;
69
+ const payload = parsed.payload;
70
+ return payload.id === threadId ? payload : null;
71
+ } catch {
72
+ continue;
73
+ } finally {
74
+ reader.destroy();
75
+ input.destroy();
76
+ await opened.handle.close().catch(() => void 0);
77
+ }
78
+ }
79
+ }
80
+ /**
81
+ * Codex 0.147 reports OpenClaw app-server rollouts as `vscode`, so the rollout's
82
+ * immutable session metadata is the authoritative historical provenance.
83
+ */
84
+ async function isOpenClawManagedCodexThread(thread, localSessionsRoot) {
85
+ const rolloutPath = typeof thread.path === "string" ? thread.path.trim() : "";
86
+ if (!localSessionsRoot || !rolloutPath) return false;
87
+ const cacheKey = `${localSessionsRoot}\0${rolloutPath}`;
88
+ const cached = provenanceByPath.get(cacheKey);
89
+ if (cached !== void 0) return cached;
90
+ const metadata = await readCodexSessionMeta(localSessionsRoot, rolloutPath, thread.id);
91
+ const managed = metadata === void 0 ? void 0 : metadata?.originator === "openclaw";
92
+ if (managed !== void 0) cacheProvenance(cacheKey, managed);
93
+ return managed ?? false;
94
+ }
95
+ //#endregion
96
+ export { readCodexSessionMeta as n, isOpenClawManagedCodexThread as t };
@@ -1,8 +1,9 @@
1
- import "./session-catalog-B47uwekb.js";
1
+ import "./session-catalog-ct-AH01I.js";
2
+ import "./thread-history-page-D0JIp48V.js";
2
3
  import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
3
4
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
4
- import { sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
5
5
  import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
6
+ import { sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
6
7
  import { addGatewayClientOptions, callGatewayFromCli } from "openclaw/plugin-sdk/gateway-runtime";
7
8
  //#region extensions/codex/src/session-cli.ts
8
9
  const CODEX_SESSION_CATALOG_CLI_TIMEOUT_MS = 75e3;
@@ -1,6 +1,6 @@
1
- import { n as readCodexNativeHistory, t as consumeCodexHistory } from "./session-history-read-LHldwvyh.js";
2
- import { getSessionEntry, parseSqliteSessionFileMarker, resolveTranscriptSessionKeyBySessionId } from "openclaw/plugin-sdk/session-store-runtime";
1
+ import { n as readCodexNativeHistory, t as consumeCodexHistory } from "./session-history-read-cxPUxyVV.js";
3
2
  import { SessionManager } from "openclaw/plugin-sdk/agent-sessions";
3
+ import { getSessionEntry, parseSqliteSessionFileMarker, resolveTranscriptSessionKeyBySessionId } from "openclaw/plugin-sdk/session-store-runtime";
4
4
  //#region extensions/codex/src/app-server/session-history.ts
5
5
  function resolveCodexHistoryTarget(target, admission) {
6
6
  if (target.sessionTarget) {
@@ -64,7 +64,10 @@ async function readCodexMirroredSessionHistoryMessages(target, admission, view =
64
64
  signal
65
65
  });
66
66
  result = consumeCodexHistory(loaded.buildSessionContext().messages, loaded.getHeader(), target.sessionId, read, "codex mirrored model context");
67
- } else result = await readCodexNativeHistory(resolved, target.sessionId, read, admission);
67
+ } else {
68
+ const history = await readCodexNativeHistory(resolved, target.sessionId, read, admission);
69
+ result = history.status === "ok" ? history.value : void 0;
70
+ }
68
71
  }
69
72
  signal?.throwIfAborted();
70
73
  return result;
@@ -1,7 +1,7 @@
1
- import { l as sessionBindingIdentity } from "./session-binding-record-CyaXZvTe.js";
2
- import "./session-binding-4Ki04sW-.js";
3
- import { r as importCodexThreadHistoryToTranscript } from "./transcript-mirror-_njEB84z.js";
4
- import { n as prepareCodexSessionInitialization } from "./session-initialization-BCFVnLL4.js";
1
+ import { l as sessionBindingIdentity } from "./session-binding-record-Bcvslnhf.js";
2
+ import "./session-binding-CI8UuilT.js";
3
+ import { r as importCodexThreadHistoryToTranscript } from "./transcript-mirror-C5CKgNy6.js";
4
+ import { n as prepareCodexSessionInitialization } from "./session-initialization-Ct0_Hzmg.js";
5
5
  import { resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
6
6
  //#region extensions/codex/src/app-server/session-history-import.ts
7
7
  /** Creates a session whose transcript is derived from one verified Codex thread snapshot. */
@@ -50,49 +50,4 @@ async function createImportedCodexSession(params) {
50
50
  }) : await params.runtime.agent.session.createSessionEntry(createParams);
51
51
  }
52
52
  //#endregion
53
- //#region extensions/codex/src/session-upstream-marker.ts
54
- function lastIdentifiableTurn(thread, normalizeTurnId) {
55
- for (let index = (thread.turns?.length ?? 0) - 1; index >= 0; index -= 1) {
56
- const turn = thread.turns?.[index];
57
- const turnId = normalizeTurnId(turn?.id);
58
- if (turn && turnId) return {
59
- ...turn,
60
- id: turnId
61
- };
62
- }
63
- }
64
- function codexUpstreamBaseline(thread, normalizeTurnId) {
65
- const turn = lastIdentifiableTurn(thread, normalizeTurnId);
66
- return {
67
- turnId: turn?.id ?? null,
68
- userMessageCount: turn?.items.filter((item) => item.type === "userMessage").length ?? 0
69
- };
70
- }
71
- function codexLastTerminalTurnId(thread, normalizeTurnId) {
72
- for (let index = (thread.turns?.length ?? 0) - 1; index >= 0; index -= 1) {
73
- const turn = thread.turns?.[index];
74
- const turnId = normalizeTurnId(turn?.id);
75
- if (!turn || !turnId) continue;
76
- if (turn.status === "completed" || turn.status === "interrupted" || turn.status === "failed") return turnId;
77
- }
78
- }
79
- /** Build the upstream link seed for a continued Codex session, if a baseline exists. */
80
- function codexUpstreamContinueResult(sessionKey, threadId, baseline) {
81
- if (!baseline) return { sessionKey };
82
- return {
83
- sessionKey,
84
- upstream: {
85
- kind: "codex-app-server",
86
- ref: {
87
- connectionFingerprint: baseline.connectionFingerprint,
88
- threadId
89
- },
90
- marker: {
91
- turnId: baseline.turnId,
92
- userMessageCount: baseline.userMessageCount
93
- }
94
- }
95
- };
96
- }
97
- //#endregion
98
- export { createImportedCodexSession as i, codexUpstreamBaseline as n, codexUpstreamContinueResult as r, codexLastTerminalTurnId as t };
53
+ export { createImportedCodexSession };