@openclaw/codex 2026.9.6 → 2026.9.7

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 (158) hide show
  1. package/README.md +2 -0
  2. package/assets/icon.png +0 -0
  3. package/dist/.setup/{account-usage-runtime-Eem_WGqY.mjs → account-usage-runtime-DFhbh1zz.mjs} +5 -5
  4. package/dist/.setup/{apply-DDOi8uNx.mjs → apply-D3GcSoSa.mjs} +22 -36
  5. package/dist/.setup/{attempt-client-cleanup-CEv1cKwF.mjs → attempt-client-cleanup-DOP-cW5j.mjs} +128 -37
  6. package/dist/.setup/attempt-workspace-context-C5HigshI.mjs +164 -0
  7. package/dist/.setup/{auth-binding-DhLWa_7K.mjs → auth-binding-BLWz7stm.mjs} +14 -1
  8. package/dist/.setup/{auth-cache-key-B2mpaI9D.mjs → auth-cache-key-Dbvq-QgB.mjs} +36 -34
  9. package/dist/.setup/{auth-profile-WqZtZfXN.mjs → auth-profile-B0okYl2D.mjs} +1 -2
  10. package/dist/.setup/auth-start-options-BPIPeEX8.mjs +44 -0
  11. package/dist/.setup/{binding-connection-ThoatDcb.mjs → binding-connection-DTtN1KrX.mjs} +2 -2
  12. package/dist/.setup/{binding-connection.runtime-yoHrABt-.mjs → binding-connection.runtime-6TpgD1M6.mjs} +4 -4
  13. package/dist/.setup/{bounded-turn-B2HScEgT.mjs → bounded-turn-CbjoN2OW.mjs} +15 -18
  14. package/dist/.setup/bounded-turn-isolation-B8K_ylqk.mjs +14 -0
  15. package/dist/.setup/{build-state-C7EnDVgr.mjs → build-state-Da1_z0kd.mjs} +1 -1
  16. package/dist/.setup/{capabilities-CDXOOFdZ.mjs → capabilities-B3WEZl4e.mjs} +2 -10
  17. package/dist/.setup/{client-Cs08OXVQ.mjs → client-N0JpgSzF.mjs} +138 -399
  18. package/dist/.setup/{client-catalog-response-BMgt_4q4.mjs → client-catalog-response-5HHLdcde.mjs} +1 -1
  19. package/dist/.setup/{command-dispatch-B4JuOsOk.mjs → command-dispatch-BeAoaovI.mjs} +5 -8
  20. package/dist/.setup/{command-formatters-Bmqvr9tO.mjs → command-formatters-R3ckE3Co.mjs} +29 -61
  21. package/dist/.setup/{command-handlers-DW7Lx9oH.mjs → command-handlers-ylTMS00z.mjs} +222 -343
  22. package/dist/.setup/{command-rpc-DixIj3HW.mjs → command-rpc-CGJGUQ6Y.mjs} +15 -18
  23. package/dist/.setup/compact-C2WamavS.mjs +776 -0
  24. package/dist/.setup/{config-BoTP_mrL.mjs → config-DKhXquav.mjs} +26 -28
  25. package/dist/.setup/{config-options-BvaRs51b.mjs → config-options-CzyWLTJt.mjs} +24 -37
  26. package/dist/.setup/{config-parsing-CcB9iPoq.mjs → config-parsing-b088LyhT.mjs} +57 -60
  27. package/dist/.setup/{config-runtime-C8Rw1m1m.mjs → config-runtime-C0NbLms1.mjs} +2 -2
  28. package/dist/.setup/{config-security-BEReZ6go.mjs → config-security-CE-FcGw9.mjs} +32 -111
  29. package/dist/.setup/{config-utils-DujwEnhg.mjs → config-utils-D0CXecki.mjs} +3 -13
  30. package/dist/.setup/context-engine-projection-PezSESth.mjs +387 -0
  31. package/dist/.setup/{conversation-binding-DP-gMrBP.mjs → conversation-binding-3Min8qvP.mjs} +67 -90
  32. package/dist/.setup/{conversation-binding-data-CrcyZk6O.mjs → conversation-binding-data-C746z5Pn.mjs} +8 -12
  33. package/dist/.setup/{conversation-control-uK9Jomlc.mjs → conversation-control-CEP8X5JC.mjs} +8 -8
  34. package/dist/.setup/{cyber-failover-DYwbmf1o.mjs → cyber-failover-XV0nNRZu.mjs} +1 -1
  35. package/dist/.setup/{cyber-failover-notice-e9G3J9-e.mjs → cyber-failover-notice-RNpGpTyP.mjs} +1 -1
  36. package/dist/.setup/{dynamic-tools-BDXl-8Cw.mjs → dynamic-tools-DzlsLUuS.mjs} +2305 -2606
  37. package/dist/.setup/{effective-mcp-catalog-CvnvnGIe.mjs → effective-mcp-catalog-CxUtC-xG.mjs} +8 -17
  38. package/dist/.setup/{ephemeral-turn-poidXgek.mjs → ephemeral-turn-CDsPJOa2.mjs} +3 -3
  39. package/dist/.setup/event-projector-assistant-message-CigreO4K.mjs +69 -0
  40. package/dist/.setup/{event-projector-usage-CnBS8Wa3.mjs → event-projector-usage-03R0I2dM.mjs} +3 -25
  41. package/dist/.setup/event-projector-values-DJSz8BTk.mjs +106 -0
  42. package/dist/.setup/incognito-session-DWYapfwf.mjs +2 -0
  43. package/dist/.setup/{inference-context-D96l9-ew.mjs → inference-context-D-9gWlTR.mjs} +16 -18
  44. package/dist/.setup/inference-dispatch-CMZtjQyz.mjs +359 -0
  45. package/dist/.setup/inference-metadata-CgIf7sOx.mjs +81 -0
  46. package/dist/.setup/{inference-proxy-b-aJMSxm.mjs → inference-proxy-DhcXOgUE.mjs} +174 -214
  47. package/dist/.setup/{isolated-completion-BIZFhTNG.mjs → isolated-completion-Dm3PzxJk.mjs} +9 -12
  48. package/dist/.setup/{managed-binary-BnshlFag.mjs → managed-binary-kiWRhNRE.mjs} +8 -12
  49. package/dist/.setup/{model-catalog-CfXJf9Ay.mjs → model-catalog-PAuZgJC6.mjs} +11 -10
  50. package/dist/.setup/model-runtime-BdqzOMkU.mjs +11 -0
  51. package/dist/.setup/{models-KnqBv0hE.mjs → models-DHXZtVVk.mjs} +9 -18
  52. package/dist/.setup/{native-auth-rWbGbMn3.mjs → native-auth-CuG53tu4.mjs} +4 -4
  53. package/dist/.setup/{native-execution-policy-umd0tgh4.mjs → native-execution-policy-BxZJy5mP.mjs} +5 -30
  54. package/dist/.setup/{native-subagent-monitor-D3filLY2.mjs → native-subagent-monitor-Dpsmf2wz.mjs} +4395 -3609
  55. package/dist/.setup/native-subagent-pending-assignments-DwkCzLvD.mjs +203 -0
  56. package/dist/.setup/native-task-assignments-DMQ0g3hu.mjs +194 -0
  57. package/dist/.setup/{node-cli-sessions-r3avj02l.mjs → node-cli-sessions-HC4W6FLI.mjs} +19 -49
  58. package/dist/.setup/{node-exec-server.runtime-BDwWXVpK.mjs → node-exec-server.runtime-BgBfWQqo.mjs} +3 -6
  59. package/dist/.setup/{plan-CN3VwfNU.mjs → plan-Y-QIvrKB.mjs} +49 -92
  60. package/dist/.setup/{plugin-activation-DT3MNtqj.mjs → plugin-activation-cNHRfaxU.mjs} +8 -36
  61. package/dist/.setup/{plugin-app-cache-key-B2CsSdnV.mjs → plugin-app-cache-key-BL9B5H0L.mjs} +6 -23
  62. package/dist/.setup/{plugin-inventory-BoRei8Z4.mjs → plugin-inventory-Cky2XJUw.mjs} +21 -21
  63. package/dist/.setup/{plugin-marketplace-discovery-CDOi8IFs.mjs → plugin-marketplace-discovery-D_dV9FXa.mjs} +18 -24
  64. package/dist/.setup/{plugin-metadata-cache-Ctmo83k_.mjs → plugin-metadata-cache-DsjsL1dr.mjs} +115 -175
  65. package/dist/.setup/{provider-BOsxQHOM.mjs → provider-DH8NSzGt.mjs} +11 -14
  66. package/dist/.setup/{provider-capabilities-BfE88FZ5.mjs → provider-capabilities-CAxoF-X1.mjs} +13 -18
  67. package/dist/.setup/{rate-limits-CMU3DUD0.mjs → rate-limits-B7-X2TgG.mjs} +9 -31
  68. package/dist/.setup/{request-D2L0zMrq.mjs → request-BHZ1nz8d.mjs} +7 -6
  69. package/dist/.setup/responses-oauth-twnuTaAa.mjs +93 -0
  70. package/dist/.setup/rpc-error-BlD2vuzn.mjs +31 -0
  71. package/dist/.setup/{run-attempt-BHu11r7h.mjs → run-attempt-D8RZUOzY.mjs} +1035 -1023
  72. package/dist/.setup/{run-attempt-lifecycle-B7JbY4-F.mjs → run-attempt-lifecycle-C-6O3Exn.mjs} +10 -24
  73. package/dist/.setup/{runtime-artifact-CLZ8udh-.mjs → runtime-artifact-DDQ-HGXf.mjs} +16 -4
  74. package/dist/.setup/runtime-artifact-connection-D68qQn1m.mjs +78 -0
  75. package/dist/.setup/sandbox-guard-DjCz2eOw.mjs +126 -0
  76. package/dist/.setup/scope-DOC1Xjc8.mjs +6 -0
  77. package/dist/.setup/session-binding-DGCYAfvD.mjs +443 -0
  78. package/dist/.setup/{session-binding-record-BGoz8wOK.mjs → session-binding-record-Oe9L-CNY.mjs} +52 -130
  79. package/dist/.setup/{session-binding-sidecars-BlB5EvIS.mjs → session-binding-sidecars-jo6H8dFr.mjs} +196 -17
  80. package/dist/.setup/{session-catalog-Pno1xGcl.mjs → session-catalog-4sCdv5qx.mjs} +170 -324
  81. package/dist/.setup/{session-catalog-adoption-BI6UTDZT.mjs → session-catalog-adoption-BU_pHWG7.mjs} +7 -6
  82. package/dist/.setup/{session-catalog-archive-lHBqzhaO.mjs → session-catalog-archive-spHfihri.mjs} +6 -6
  83. package/dist/.setup/session-catalog-events-DePDzzjc.mjs +139 -0
  84. package/dist/.setup/session-catalog-home-id-vlih0B_g.mjs +22 -0
  85. package/dist/.setup/{session-catalog-index-B9_VQIUz.mjs → session-catalog-index-CZvDzC6z.mjs} +126 -122
  86. package/dist/.setup/{session-catalog-index-order-hcdz07yN.mjs → session-catalog-index-order-BcQpHks3.mjs} +1 -1
  87. package/dist/.setup/{session-catalog-index-state-Dgh8ORJm.mjs → session-catalog-index-state-TeO7EyO-.mjs} +3 -2
  88. package/dist/.setup/session-catalog-limits-DDxOsQeC.mjs +14 -0
  89. package/dist/.setup/session-catalog-list-request-CvtxrYSe.mjs +170 -0
  90. package/dist/.setup/session-catalog-native-projection-DjhwGL6x.mjs +178 -0
  91. package/dist/.setup/{session-catalog-node-adoption-ITddWx_X.mjs → session-catalog-node-adoption-DgXvSGu0.mjs} +10 -27
  92. package/dist/.setup/{session-catalog-node-continue-6g6qi4A9.mjs → session-catalog-node-continue-DjKXHBbi.mjs} +8 -10
  93. package/dist/.setup/session-catalog-node-lookup-CtAXI5W5.mjs +56 -0
  94. package/dist/.setup/{session-catalog-native-projection-DowriLid.mjs → session-catalog-parsing-CPGaPYr-.mjs} +11 -194
  95. package/dist/.setup/{session-catalog-projection-zK_PUsiE.mjs → session-catalog-projection-Cr5qP5Dj.mjs} +6 -4
  96. package/dist/.setup/session-catalog-provenance-DoAvktcj.mjs +95 -0
  97. package/dist/.setup/{session-cli-irrD-uo7.mjs → session-cli-Cn_nCqfq.mjs} +9 -22
  98. package/dist/.setup/{session-history-BrqhSCf9.mjs → session-history-D83lJWHG.mjs} +4 -6
  99. package/dist/.setup/{session-history-import-D-3wAgOP.mjs → session-history-import-WhX-X33a.mjs} +7 -10
  100. package/dist/.setup/session-history-read-Ov3StuL4.mjs +133 -0
  101. package/dist/.setup/{session-history.worker-CaCh0xF_.mjs → session-history.worker-MnPKncqP.mjs} +9 -5
  102. package/dist/.setup/session-initialization-6aveB9qb.mjs +22 -0
  103. package/dist/.setup/{session-permission-policy-BI1QK_98.mjs → session-permission-policy-Ci_fVX6y.mjs} +4 -8
  104. package/dist/.setup/{session-retirement-BH-S6qkJ.mjs → session-retirement-qMTxkNx2.mjs} +17 -17
  105. package/dist/.setup/{settled-turn-context-fmwouT5I.mjs → settled-turn-context-D4yj4rxf.mjs} +1 -1
  106. package/dist/.setup/{settled-turn-finalizer-DiAi6Kx6.mjs → settled-turn-finalizer-BsvEabkw.mjs} +14 -10
  107. package/dist/.setup/{shared-client-DA4VR4Eb.mjs → shared-client-DqyTMYug.mjs} +783 -412
  108. package/dist/.setup/shared-client-lifecycle-DJIgqgMw.mjs +153 -0
  109. package/dist/.setup/{side-question-BJ1wSDcB.mjs → side-question-C4kCmQy1.mjs} +79 -143
  110. package/dist/.setup/{source-CUzJq5WN.mjs → source-CS_7GFJZ.mjs} +80 -137
  111. package/dist/.setup/{thread-lifecycle-B3mfz1TG.mjs → thread-lifecycle-DPflntEJ.mjs} +294 -737
  112. package/dist/.setup/{incognito-session-uhrBF6wJ.mjs → thread-ownership-queue-Dp24d7-F.mjs} +1 -2
  113. package/dist/.setup/{thread-ownership-DcTtAcXj.mjs → thread-ownership-roNP0l1c.mjs} +45 -10
  114. package/dist/.setup/{thread-policy-DGuQsuFC.mjs → thread-policy-DTd-DtkX.mjs} +46 -7
  115. package/dist/.setup/{thread-requests-BLvGkP2R.mjs → thread-requests-B_bRnMGN.mjs} +199 -302
  116. package/dist/.setup/{thread-resume-DIBXwOpE.mjs → thread-resume-CdDaoc7T.mjs} +6 -6
  117. package/dist/.setup/{timeout-C910MdAB.mjs → timeout-CXOfNoaX.mjs} +1 -35
  118. package/dist/.setup/{transcript-history-projection-ZZpkFkJ_.mjs → transcript-history-projection-DRSifI-1.mjs} +17 -89
  119. package/dist/.setup/{transcript-mirror-attestation-CzM-94NC.mjs → transcript-mirror-attestation-YSegaktH.mjs} +3 -4
  120. package/dist/.setup/{transcript-mirror-BtHDBp1G.mjs → transcript-mirror-kxmCYsuF.mjs} +7 -9
  121. package/dist/.setup/{transport-stdio-h2VHOskC.mjs → transport-stdio-Bdegpn2V.mjs} +5 -22
  122. package/dist/.setup/transport-websocket-BTBE-LD9.mjs +211 -0
  123. package/dist/.setup/{upstream-prompt-provenance-LphB8slG.mjs → upstream-prompt-provenance-fXkKbPVC.mjs} +3 -9
  124. package/dist/.setup/{upstream-session-fork-BUr4OUbC.mjs → upstream-session-fork-CBeVjBpT.mjs} +23 -23
  125. package/dist/.setup/{usage-BML0r-ua.mjs → usage-BMzNxeR_.mjs} +4 -4
  126. package/dist/.setup/{usage-limit-error-DUMbefVY.mjs → usage-limit-error-QXerDo3i.mjs} +4 -19
  127. package/dist/.setup/{web-search-provider.runtime-CDKlN-Rv.mjs → web-search-provider.runtime-P77OUeoo.mjs} +8 -19
  128. package/dist/api.js +9 -11
  129. package/dist/catalog-page.worker.js +1 -1
  130. package/dist/cli-metadata.js +1 -1
  131. package/dist/doctor-contract-api.js +50 -8
  132. package/dist/harness.js +344 -1
  133. package/dist/index.js +193 -245
  134. package/dist/media-understanding-provider.js +9 -22
  135. package/dist/migration-provider-api.js +1 -1
  136. package/dist/provider-discovery.js +1 -1
  137. package/dist/session-history-worker-runtime.js +3 -3
  138. package/dist/session-history.worker.js +1 -1
  139. package/openclaw.plugin.json +14 -2
  140. package/package.json +7 -6
  141. package/dist/.setup/attempt-workspace-context-DUVEn_CS.mjs +0 -331
  142. package/dist/.setup/compact-Du5UvtxA.mjs +0 -680
  143. package/dist/.setup/event-projector-assistant-message-BsruvNrH.mjs +0 -103
  144. package/dist/.setup/event-projector-items-C6L_5ZiT.mjs +0 -234
  145. package/dist/.setup/harness-a_MsE4-_.mjs +0 -355
  146. package/dist/.setup/history-rejection-B4nOXNXF.mjs +0 -13
  147. package/dist/.setup/image-payload-sanitizer-tupAr-2o.mjs +0 -79
  148. package/dist/.setup/local-runtime-attribution-B_2mnqhb.mjs +0 -19
  149. package/dist/.setup/native-subagent-history-0nYYgo0k.mjs +0 -148
  150. package/dist/.setup/native-subagent-task-ids-wb8CKZGN.mjs +0 -441
  151. package/dist/.setup/plugin-approval-roundtrip-C0MZzCuP.mjs +0 -122
  152. package/dist/.setup/rolldown-runtime-8H4AJuhK.mjs +0 -14
  153. package/dist/.setup/sandbox-guard-C2sRMOEY.mjs +0 -166
  154. package/dist/.setup/session-binding-Cm0apEbd.mjs +0 -692
  155. package/dist/.setup/session-catalog-events-Bj6j94E_.mjs +0 -347
  156. package/dist/.setup/session-history-read-B3ZfSUbF.mjs +0 -50
  157. package/dist/.setup/session-initialization-rcgbZiid.mjs +0 -75
  158. package/dist/.setup/thread-history-page-DoVpnHim.mjs +0 -83
@@ -1,24 +1,11 @@
1
- import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
2
- import { n as defineCodexBuildState } from "./build-state-C7EnDVgr.mjs";
3
- import { i as isJsonObject } from "./protocol-CANUwXJ3.mjs";
1
+ import "./protocol-CANUwXJ3.mjs";
2
+ import { n as detachCodexCatalogString } from "./session-catalog-limits-DDxOsQeC.mjs";
4
3
  import { asFiniteNumber, isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
5
4
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
6
5
  //#region extensions/codex/src/app-server/protocol-session-source.ts
7
6
  const CODEX_INTERACTIVE_THREAD_SOURCE_KINDS = ["cli", "vscode"];
8
7
  const CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES = ["atlas", "chatgpt"];
9
8
  //#endregion
10
- //#region extensions/codex/src/session-catalog-limits.ts
11
- var session_catalog_limits_exports = /* @__PURE__ */ __exportAll({
12
- CODEX_CATALOG_MAX_ROWS: () => CODEX_CATALOG_MAX_ROWS,
13
- CODEX_CATALOG_MAX_STATE_KEY_BYTES: () => 512,
14
- detachCodexCatalogString: () => detachCodexCatalogString
15
- });
16
- const CODEX_CATALOG_MAX_ROWS = 2e4;
17
- /** Preserve UTF-16 code units without retaining an oversized source string. */
18
- function detachCodexCatalogString(value) {
19
- return Buffer.from(value, "utf16le").toString("utf16le");
20
- }
21
- //#endregion
22
9
  //#region extensions/codex/src/session-catalog-parsing.ts
23
10
  const DEFAULT_PAGE_LIMIT = 50;
24
11
  const CODEX_APP_SERVER_THREADS_CAPABILITY = "codex-app-server-threads";
@@ -67,8 +54,7 @@ function truncateCodexCatalogPreview(value, sanitize) {
67
54
  return Buffer.from(catalogPreview(value, sanitize) ?? "", "utf8").toString("utf8");
68
55
  }
69
56
  function normalizeInteractiveThreadSource(source) {
70
- if (CODEX_INTERACTIVE_THREAD_SOURCE_KINDS.some((kind) => kind === source) || CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES.some((kind) => kind === source)) return source;
71
- if (isRecord(source) && CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES.some((kind) => kind === source.custom)) return source.custom;
57
+ return CODEX_INTERACTIVE_THREAD_SOURCE_KINDS.find((kind) => kind === source) ?? CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES.find((kind) => kind === source) ?? (isRecord(source) ? CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES.find((kind) => kind === source.custom) : void 0);
72
58
  }
73
59
  function isInteractiveThreadSource(source) {
74
60
  return normalizeInteractiveThreadSource(source) !== void 0;
@@ -118,9 +104,9 @@ function toCatalogSession(thread, archived, sanitize, preparedPreview) {
118
104
  ...gitBranch ? { gitBranch } : {}
119
105
  };
120
106
  }
121
- function normalizeLimit(value, key) {
122
- if (value === void 0) return DEFAULT_PAGE_LIMIT;
123
- if (!Number.isInteger(value) || value < 1 || value > 100) throw new CatalogParamsError(`${key} must be an integer from 1 to 100`);
107
+ function normalizeLimit(value, key, fallback = DEFAULT_PAGE_LIMIT, max = 100) {
108
+ if (value === void 0) return fallback;
109
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 1 || value > max) throw new CatalogParamsError(`${key} must be an integer from 1 to ${max}`);
124
110
  return value;
125
111
  }
126
112
  function readBoundedOptionalString(params, key, maxLength) {
@@ -157,7 +143,7 @@ function readPageParams(value) {
157
143
  }
158
144
  function readGatewayParams(value) {
159
145
  if (value !== void 0 && !isRecord(value)) throw new CatalogParamsError("Codex session catalog parameters must be an object");
160
- const params = isRecord(value) ? value : {};
146
+ const params = value ?? {};
161
147
  requireOnlyKeys(params, /* @__PURE__ */ new Set([
162
148
  "search",
163
149
  "limitPerHost",
@@ -177,8 +163,7 @@ function readGatewayParams(value) {
177
163
  if (entries.length > MAX_CURSOR_COUNT) throw new CatalogParamsError(`cursors may contain at most ${MAX_CURSOR_COUNT} hosts`);
178
164
  cursors = {};
179
165
  for (const [hostId, cursor] of entries) {
180
- const normalizedHostId = hostId.trim();
181
- if (normalizedHostId.length === 0 || normalizedHostId.length > MAX_HOST_ID_LENGTH || !normalizedHostId.startsWith("gateway:") && !normalizedHostId.startsWith("node:")) throw new CatalogParamsError(`invalid Codex session catalog host id: ${hostId}`);
166
+ const normalizedHostId = readHostId(hostId);
182
167
  if (typeof cursor !== "string" || !cursor.trim() || cursor.trim().length > 4096) throw new CatalogParamsError(`invalid cursor for Codex session catalog host: ${hostId}`);
183
168
  cursors[normalizedHostId] = cursor.trim();
184
169
  }
@@ -271,12 +256,12 @@ function filterCatalogPageByTitle(page, searchTerm) {
271
256
  sessions: page.sessions.filter((session) => (session.name ?? session.fallbackName)?.toLocaleLowerCase().includes(searchTerm.toLocaleLowerCase()))
272
257
  };
273
258
  }
274
- function unwrapNodeInvokePayload(value) {
259
+ function unwrapNodeInvokePayload(value, malformedMessage = "Codex node returned malformed session catalog JSON") {
275
260
  if (!isRecord(value)) return value;
276
261
  if (typeof value.payloadJSON === "string" && value.payloadJSON.trim()) try {
277
262
  return JSON.parse(value.payloadJSON);
278
263
  } catch (error) {
279
- throw new Error("Codex node returned malformed session catalog JSON", { cause: error });
264
+ throw new Error(malformedMessage, { cause: error });
280
265
  }
281
266
  return "payload" in value ? value.payload : value;
282
267
  }
@@ -318,172 +303,4 @@ function requireBoundThread(entry) {
318
303
  return entry.boundThreadId;
319
304
  }
320
305
  //#endregion
321
- //#region extensions/codex/src/session-catalog-source.ts
322
- const getSources = defineCodexBuildState("openclaw.codexCatalogSources", () => ({
323
- clients: /* @__PURE__ */ new WeakMap(),
324
- values: /* @__PURE__ */ new WeakMap()
325
- }));
326
- const getEphemeralObservers = defineCodexBuildState("openclaw.codexCatalogEphemeralObservers", () => /* @__PURE__ */ new WeakMap());
327
- /** A passive lifetime fact; the token never retains its client or a lease. */
328
- function codexCatalogSourceForClient(client) {
329
- const { clients } = getSources();
330
- let source = clients.get(client);
331
- if (!source) {
332
- source = { closed: false };
333
- clients.set(client, source);
334
- }
335
- return source;
336
- }
337
- function closeCodexCatalogClientSource(client) {
338
- const { clients } = getSources();
339
- const source = clients.get(client);
340
- if (source) {
341
- source.closed = true;
342
- getEphemeralObservers().delete(source);
343
- } else clients.set(client, { closed: true });
344
- }
345
- /** The catalog observer is bound once per physical source and released on closure. */
346
- function observeCodexCatalogEphemeralThreads(source, observer) {
347
- getEphemeralObservers().set(source, observer);
348
- }
349
- function getCodexCatalogSource(value) {
350
- return value !== null && typeof value === "object" ? getSources().values.get(value) : void 0;
351
- }
352
- function setCodexCatalogSource(value, source) {
353
- if (source) getSources().values.set(value, source);
354
- return value;
355
- }
356
- /** Source attribution survives projection without becoming serialized row data. */
357
- function copyCodexCatalogSource(from, to) {
358
- return setCodexCatalogSource(to, getCodexCatalogSource(from));
359
- }
360
- /** Stamp the final decoded objects, including any bounded catalog DTO replacement. */
361
- function recordCodexCatalogResponseSource(method, result, source) {
362
- if (result === null || typeof result !== "object") return;
363
- if (method === "thread/list" && "data" in result && Array.isArray(result.data)) {
364
- setCodexCatalogSource(result, source);
365
- for (const thread of result.data) if (thread !== null && typeof thread === "object") setCodexCatalogSource(thread, source);
366
- } else if ((method === "thread/read" || method === "thread/start" || method === "thread/fork" || method === "thread/resume") && "thread" in result && result.thread !== null && typeof result.thread === "object") {
367
- setCodexCatalogSource(result, source);
368
- setCodexCatalogSource(result.thread, source);
369
- if ("ephemeral" in result.thread && result.thread.ephemeral === true && "id" in result.thread && typeof result.thread.id === "string") getEphemeralObservers().get(source)?.(result.thread.id);
370
- }
371
- }
372
- //#endregion
373
- //#region extensions/codex/src/session-catalog-native-projection.ts
374
- var session_catalog_native_projection_exports = /* @__PURE__ */ __exportAll({
375
- CODEX_CATALOG_NATIVE_PAGE_LIMIT: () => 64,
376
- projectCodexCatalogNativeResponse: () => projectCodexCatalogNativeResponse,
377
- projectCodexCatalogNativeThread: () => projectCodexCatalogNativeThread,
378
- reuseCodexCatalogPreview: () => reuseCodexCatalogPreview
379
- });
380
- const CODEX_CATALOG_NATIVE_PAGE_LIMIT = 64;
381
- const STRING_FIELDS = [
382
- [
383
- "name",
384
- 500,
385
- "truncate"
386
- ],
387
- [
388
- "cwd",
389
- MAX_CWD_LENGTH,
390
- "omit"
391
- ],
392
- [
393
- "modelProvider",
394
- 500,
395
- "truncate"
396
- ],
397
- [
398
- "cliVersion",
399
- 500,
400
- "truncate"
401
- ]
402
- ];
403
- /** Drop unused native fields before catalog-owned asynchronous work can retain them. */
404
- function projectCodexCatalogNativeThread(thread, sanitize, cachedPreview) {
405
- if (!isJsonObject(thread)) throw new Error("Codex catalog response contains an invalid thread");
406
- const id = boundedCatalogString(thread.id, 256);
407
- if (!id) throw new Error("Codex catalog response contains an invalid thread id");
408
- const row = {
409
- id,
410
- projectId: boundedCatalogString(thread.projectId, 256, "omit") ?? null
411
- };
412
- const sessionId = boundedCatalogString(thread.sessionId, 256, "omit");
413
- if (sessionId) row.sessionId = sessionId;
414
- if (thread.ephemeral === true) return copyCodexCatalogSource(thread, {
415
- ...row,
416
- ephemeral: true
417
- });
418
- for (const [field, limit, overflow] of STRING_FIELDS) {
419
- const value = thread[field];
420
- const bounded = boundedCatalogString(value, limit, overflow);
421
- if (value === null || bounded !== void 0) row[field] = bounded ?? null;
422
- }
423
- if (typeof thread.path === "string") {
424
- if (thread.path.length > 4096) throw new Error("Codex catalog rollout path exceeds its length limit");
425
- row.path = detachCodexCatalogString(thread.path);
426
- } else if (thread.path === null) row.path = null;
427
- if (typeof thread.originator === "string") row.originator = detachCodexCatalogString(thread.originator.slice(0, 500));
428
- for (const field of [
429
- "createdAt",
430
- "updatedAt",
431
- "recencyAt"
432
- ]) {
433
- const value = thread[field];
434
- if (value === null || typeof value === "number" && Number.isFinite(value)) row[field] = value;
435
- }
436
- const rawPreview = thread.preview;
437
- const preview = reuseCodexCatalogPreview(row, typeof rawPreview === "string" ? Boolean(rawPreview) : void 0, cachedPreview);
438
- if (preview !== void 0) row.preview = preview;
439
- else if (typeof rawPreview === "string") row.preview = rawPreview ? truncateCodexCatalogPreview(selectCodexCatalogPreviewInput(rawPreview), sanitize) : "";
440
- else if (rawPreview === null) row.preview = null;
441
- const source = typeof thread.source === "string" ? detachCodexCatalogString(thread.source.slice(0, 500)) : void 0;
442
- if (source === "cli" || source === "vscode" || source === "exec" || source === "appServer" || source === "unknown") row.source = source;
443
- else if (isJsonObject(thread.source) && typeof thread.source.custom === "string" && thread.source.custom.length <= 500) row.source = { custom: detachCodexCatalogString(thread.source.custom) };
444
- if (isJsonObject(thread.gitInfo)) {
445
- const branch = boundedCatalogString(thread.gitInfo.branch, 500, "truncate");
446
- if (branch !== void 0) row.gitInfo = { branch };
447
- }
448
- if (isJsonObject(thread.status)) {
449
- const type = boundedCatalogString(thread.status.type, 64);
450
- if (type === "active" || type === "idle" || type === "notLoaded" || type === "systemError") {
451
- const activeFlags = type === "active" && Array.isArray(thread.status.activeFlags) ? thread.status.activeFlags.slice(0, 16).flatMap((flag) => {
452
- const bounded = boundedCatalogString(flag, 128, "omit");
453
- return bounded ? [bounded] : [];
454
- }) : void 0;
455
- row.status = type === "active" ? {
456
- type,
457
- ...activeFlags ? { activeFlags } : {}
458
- } : { type };
459
- }
460
- }
461
- return copyCodexCatalogSource(thread, row);
462
- }
463
- /** Keep only the admitted prefix before an RPC promise retains its response. */
464
- function projectCodexCatalogNativeResponse(response, sanitize, cachedPreview, remainingRows = 64) {
465
- if (!Array.isArray(response.data) || response.data.length > 64) throw new Error("Codex catalog response exceeds its native page limit");
466
- const limit = Number.isFinite(remainingRows) ? Math.max(0, Math.min(64, Math.floor(remainingRows))) : 0;
467
- const page = { data: response.data.slice(0, limit).map((thread) => projectCodexCatalogNativeThread(thread, sanitize, cachedPreview)) };
468
- for (const field of ["nextCursor", "backwardsCursor"]) {
469
- const value = response[field];
470
- if (value === null) page[field] = null;
471
- else if (value !== void 0) {
472
- if (typeof value !== "string" || value.length > 4096) throw new Error("Codex catalog response contains an invalid cursor");
473
- page[field] = detachCodexCatalogString(value);
474
- }
475
- }
476
- return page;
477
- }
478
- /** Reuse resident text without transferring a cache or an unbounded native preview. */
479
- function reuseCodexCatalogPreview(thread, rawPreviewNonempty, cachedPreview) {
480
- const preview = cachedPreview?.({
481
- id: thread.id,
482
- path: typeof thread.path === "string" ? thread.path : null,
483
- updatedAt: typeof thread.updatedAt === "number" ? thread.updatedAt : null,
484
- recencyAt: typeof thread.recencyAt === "number" ? thread.recencyAt : null
485
- });
486
- return preview !== void 0 && preview.length <= 500 && (rawPreviewNonempty === void 0 || rawPreviewNonempty === Boolean(preview)) ? preview : void 0;
487
- }
488
- //#endregion
489
- export { parseCatalogPage as A, toCatalogSession as B, boundedCatalogString as C, filterCatalogPageByTitle as D, codexCatalogThreadStatus as E, readGatewayParams as F, session_catalog_limits_exports as G, unwrapNodeInvokePayload as H, readPageParams as I, CODEX_INTERACTIVE_THREAD_SOURCE_KINDS as K, requireBoundThread as L, parseTranscriptPage as M, readBoundedOptionalString as N, isInteractiveThreadSource as O, readControlCursor as P, requireOnlyKeys as R, NODE_INVOKE_TIMEOUT_MS as S, codexCatalogThreadName as T, CODEX_CATALOG_MAX_ROWS as U, truncateCodexCatalogPreview as V, detachCodexCatalogString as W, CODEX_LOCAL_SESSION_HOST_ID as _, session_catalog_native_projection_exports as a, MAX_CWD_LENGTH as b, copyCodexCatalogSource as c, recordCodexCatalogResponseSource as d, setCodexCatalogSource as f, CODEX_CATALOG_TRANSCRIPT_READ_COMMAND as g, CODEX_APP_SERVER_THREAD_TURNS_LIST_COMMAND as h, reuseCodexCatalogPreview as i, parseJsonParams as j, normalizeLimit as k, getCodexCatalogSource as l, CODEX_APP_SERVER_THREADS_LIST_COMMAND as m, projectCodexCatalogNativeResponse as n, closeCodexCatalogClientSource as o, CODEX_APP_SERVER_THREADS_CAPABILITY as p, projectCodexCatalogNativeThread as r, codexCatalogSourceForClient as s, CODEX_CATALOG_NATIVE_PAGE_LIMIT as t, observeCodexCatalogEphemeralThreads as u, CatalogParamsError as v, catalogError as w, MAX_TRANSCRIPT_PAGE_BYTES as x, MAX_CURSOR_LENGTH as y, selectCodexCatalogPreviewInput as z };
306
+ export { unwrapNodeInvokePayload as A, readGatewayParams as C, selectCodexCatalogPreviewInput as D, requireOnlyKeys as E, toCatalogSession as O, readControlCursor as S, requireBoundThread as T, normalizeLimit as _, CODEX_LOCAL_SESSION_HOST_ID as a, parseTranscriptPage as b, MAX_CWD_LENGTH as c, boundedCatalogString as d, catalogError as f, isInteractiveThreadSource as g, filterCatalogPageByTitle as h, CODEX_CATALOG_TRANSCRIPT_READ_COMMAND as i, CODEX_INTERACTIVE_THREAD_SOURCE_KINDS as j, truncateCodexCatalogPreview as k, MAX_TRANSCRIPT_PAGE_BYTES as l, codexCatalogThreadStatus as m, CODEX_APP_SERVER_THREADS_LIST_COMMAND as n, CatalogParamsError as o, codexCatalogThreadName as p, CODEX_APP_SERVER_THREAD_TURNS_LIST_COMMAND as r, MAX_CURSOR_LENGTH as s, CODEX_APP_SERVER_THREADS_CAPABILITY as t, NODE_INVOKE_TIMEOUT_MS as u, parseCatalogPage as v, readPageParams as w, readBoundedOptionalString as x, parseJsonParams as y };
@@ -1,11 +1,13 @@
1
- import { B as toCatalogSession, C as boundedCatalogString, P as readControlCursor, V as truncateCodexCatalogPreview, W as detachCodexCatalogString, c as copyCodexCatalogSource, f as setCodexCatalogSource, l as getCodexCatalogSource, r as projectCodexCatalogNativeThread, z as selectCodexCatalogPreviewInput } from "./session-catalog-native-projection-DowriLid.mjs";
2
- import { a as isOpenClawManagedCodexThread } from "./session-catalog-events-Bj6j94E_.mjs";
3
- import { n as codexCatalogRowRecency } from "./session-catalog-index-order-hcdz07yN.mjs";
1
+ import { D as selectCodexCatalogPreviewInput, O as toCatalogSession, S as readControlCursor, d as boundedCatalogString, k as truncateCodexCatalogPreview } from "./session-catalog-parsing-CPGaPYr-.mjs";
2
+ import { n as detachCodexCatalogString } from "./session-catalog-limits-DDxOsQeC.mjs";
3
+ import { n as codexCatalogRowRecency } from "./session-catalog-index-order-BcQpHks3.mjs";
4
+ import { t as isOpenClawManagedCodexThread } from "./session-catalog-provenance-DoAvktcj.mjs";
5
+ import { c as copyCodexCatalogSource, l as getCodexCatalogSource, p as setCodexCatalogSource, r as projectCodexCatalogNativeThread } from "./session-catalog-native-projection-DjhwGL6x.mjs";
4
6
  import { asFiniteNumber, isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
5
7
  import path from "node:path";
6
8
  import fs from "node:fs/promises";
7
- import { root } from "openclaw/plugin-sdk/file-access-runtime";
8
9
  import { extractErrorCode, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
10
+ import { root } from "openclaw/plugin-sdk/file-access-runtime";
9
11
  import { constants, createZstdDecompress } from "node:zlib";
10
12
  import { sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
11
13
  //#region extensions/codex/src/session-catalog-rollouts.ts
@@ -0,0 +1,95 @@
1
+ import { i as isJsonObject } from "./protocol-CANUwXJ3.mjs";
2
+ import path from "node:path";
3
+ import { root } from "openclaw/plugin-sdk/file-access-runtime";
4
+ import { createZstdDecompress } from "node:zlib";
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
+ if (provenanceByPath.size > MAX_PROVENANCE_CACHE_ENTRIES) provenanceByPath.delete(provenanceByPath.keys().next().value);
14
+ }
15
+ /** Undefined means the metadata line is not durable enough to cache yet. */
16
+ async function readCodexSessionMeta(sessionsRoot, rolloutPath, threadId) {
17
+ let safeRoot;
18
+ try {
19
+ safeRoot = await root(sessionsRoot, {
20
+ hardlinks: "reject",
21
+ maxBytes: Number.MAX_SAFE_INTEGER,
22
+ symlinks: "reject"
23
+ });
24
+ } catch {
25
+ return;
26
+ }
27
+ const candidates = rolloutPath.endsWith(".zst") ? [rolloutPath, rolloutPath.slice(0, -4)] : [rolloutPath, `${rolloutPath}.zst`];
28
+ for (const candidate of candidates) {
29
+ let opened;
30
+ try {
31
+ opened = await safeRoot.open(path.relative(sessionsRoot, candidate));
32
+ } catch {
33
+ continue;
34
+ }
35
+ const input = opened.handle.createReadStream({
36
+ autoClose: false,
37
+ highWaterMark: SESSION_META_READ_CHUNK_BYTES
38
+ });
39
+ const reader = candidate.endsWith(".zst") ? input.pipe(createZstdDecompress()) : input;
40
+ try {
41
+ const chunks = [];
42
+ let bytesReadTotal = 0;
43
+ let line;
44
+ for await (const value of reader) {
45
+ const chunk = Buffer.isBuffer(value) ? value : Buffer.from(value);
46
+ const remaining = MAX_SESSION_META_BYTES - bytesReadTotal;
47
+ if (remaining <= 0) break;
48
+ const bounded = chunk.subarray(0, remaining);
49
+ bytesReadTotal += bounded.length;
50
+ const newline = bounded.indexOf(10);
51
+ chunks.push(newline >= 0 ? bounded.subarray(0, newline) : bounded);
52
+ if (newline >= 0) {
53
+ line = Buffer.concat(chunks).toString("utf8");
54
+ break;
55
+ }
56
+ }
57
+ if (!line) continue;
58
+ const parsed = JSON.parse(line);
59
+ if (!isJsonObject(parsed) || parsed.type !== "session_meta" || !isJsonObject(parsed.payload)) return null;
60
+ const payload = parsed.payload;
61
+ return payload.id === threadId ? payload : null;
62
+ } catch {
63
+ continue;
64
+ } finally {
65
+ reader.destroy();
66
+ input.destroy();
67
+ await opened.handle.close().catch(() => void 0);
68
+ }
69
+ }
70
+ }
71
+ /** Passive local listing uses native creation provenance, with rollout fallback for older records. */
72
+ async function isOpenClawManagedCodexThread(thread, localSessionsRoot, diagnostics) {
73
+ const started = diagnostics ? performance.now() : 0;
74
+ if (diagnostics) diagnostics.fields.provenanceChecks++;
75
+ try {
76
+ const rolloutPath = typeof thread.path === "string" ? thread.path.trim() : "";
77
+ if (!localSessionsRoot || !rolloutPath) return false;
78
+ if (typeof thread.originator === "string" && thread.originator.length > 0) return thread.originator === "openclaw";
79
+ const cacheKey = `${localSessionsRoot}\0${rolloutPath}`;
80
+ const cached = provenanceByPath.get(cacheKey);
81
+ if (cached !== void 0) {
82
+ if (diagnostics) diagnostics.fields.provenanceCacheHits++;
83
+ return cached;
84
+ }
85
+ if (diagnostics) diagnostics.fields.provenanceReadCalls++;
86
+ const metadata = await readCodexSessionMeta(localSessionsRoot, rolloutPath, thread.id);
87
+ const managed = metadata === void 0 ? void 0 : metadata?.originator === "openclaw";
88
+ if (managed !== void 0) cacheProvenance(cacheKey, managed);
89
+ return managed ?? false;
90
+ } finally {
91
+ if (diagnostics) diagnostics.fields.provenanceMs = (diagnostics.fields.provenanceMs ?? 0) + performance.now() - started;
92
+ }
93
+ }
94
+ //#endregion
95
+ export { readCodexSessionMeta as n, isOpenClawManagedCodexThread as t };
@@ -1,5 +1,5 @@
1
- import "./session-catalog-native-projection-DowriLid.mjs";
2
- import "./session-catalog-Pno1xGcl.mjs";
1
+ import "./session-catalog-parsing-CPGaPYr-.mjs";
2
+ import "./session-catalog-4sCdv5qx.mjs";
3
3
  import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
5
5
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
@@ -79,12 +79,6 @@ function writeHost(host) {
79
79
  }
80
80
  if (host.nextCursor) writeLine(` More sessions: repeat the same filters with --host ${quoteShellArgument(host.hostId)} --cursor ${quoteShellArgument(host.nextCursor)}`);
81
81
  }
82
- function filterHosts(result, selector) {
83
- return selector ? {
84
- ...result,
85
- hosts: result.hosts.filter((host) => host.hostId === selector)
86
- } : result;
87
- }
88
82
  async function listCodexSessions(options) {
89
83
  const agentId = requestedAgentId(options);
90
84
  const host = options.host?.trim() || void 0;
@@ -93,23 +87,22 @@ async function listCodexSessions(options) {
93
87
  const search = options.search?.trim() || void 0;
94
88
  const limitPerHost = parsePageLimit(options.limit);
95
89
  const params = {
90
+ catalogId: "codex",
96
91
  ...agentId ? { agentId } : {},
97
92
  ...search ? { search } : {},
98
93
  ...limitPerHost !== void 0 ? { limitPerHost } : {},
99
94
  ...host ? { hostIds: [host] } : {},
100
95
  ...cursor && host ? { cursors: { [host]: cursor } } : {}
101
96
  };
102
- const raw = await callGatewayFromCli("sessions.catalog.list", gatewayOptions(options), {
103
- catalogId: "codex",
104
- ...params
105
- }, {
97
+ const raw = await callGatewayFromCli("sessions.catalog.list", gatewayOptions(options), params, {
106
98
  mode: "cli",
107
99
  scopes: ["operator.write"]
108
100
  });
109
101
  if (!isRecord(raw) || !Array.isArray(raw.catalogs)) throw new Error("Codex session catalog returned an invalid result");
110
102
  const catalog = raw.catalogs.find((candidate) => isRecord(candidate) && candidate.id === "codex" && Array.isArray(candidate.hosts));
111
103
  if (!isRecord(catalog)) throw new Error("Codex session catalog is unavailable on this Gateway");
112
- const result = filterHosts({ hosts: catalog.hosts }, host);
104
+ const hosts = catalog.hosts;
105
+ const result = { hosts: host ? hosts.filter((entry) => entry.hostId === host) : hosts };
113
106
  if (options.json) {
114
107
  writeJson(result);
115
108
  return;
@@ -175,15 +168,9 @@ async function archiveCodexSession(threadIdValue, options) {
175
168
  /** Registers the plugin-owned Codex session supervision CLI. */
176
169
  function registerCodexSessionCli(program) {
177
170
  const codex = program.command("codex").description("Inspect and branch from Codex sessions through the Gateway");
178
- addGatewayClientOptions(codex.command("sessions").description("List non-archived Codex app-server sessions across connected hosts").option("--agent <id>", "Agent id that owns the Codex sessions").option("--search <text>", "Search session titles (case-insensitive)").option("--host <id>", "Filter by stable host id").option("--limit <count>", "Maximum sessions returned per host").option("--cursor <cursor>", "Continue one host page (requires --host)").option("--json", "Print the structured catalog response", false), { timeoutMs: CODEX_SESSION_CATALOG_CLI_TIMEOUT_MS }).action(async (options) => {
179
- await listCodexSessions(options);
180
- });
181
- addGatewayClientOptions(codex.command("continue <thread-id>").description("Continue a Gateway-local Codex thread as an OpenClaw branch").option("--agent <id>", "Agent id that owns the Codex session").option("--host <id>", "Stable local host id from codex sessions").option("--json", "Print the structured response", false)).action(async (threadId, options) => {
182
- await continueCodexSession(threadId, options);
183
- });
184
- addGatewayClientOptions(codex.command("archive <thread-id>").description("Archive a stored or idle Gateway-local Codex thread").option("--agent <id>", "Agent id that owns the Codex session").option("--host <id>", "Stable local host id from codex sessions").option("--confirm-no-other-runner", "Confirm no other Codex client or OpenClaw runner is using this thread", false).option("--json", "Print the structured response", false)).action(async (threadId, options) => {
185
- await archiveCodexSession(threadId, options);
186
- });
171
+ addGatewayClientOptions(codex.command("sessions").description("List non-archived Codex app-server sessions across connected hosts").option("--agent <id>", "Agent id that owns the Codex sessions").option("--search <text>", "Search session titles (case-insensitive)").option("--host <id>", "Filter by stable host id").option("--limit <count>", "Maximum sessions returned per host").option("--cursor <cursor>", "Continue one host page (requires --host)").option("--json", "Print the structured catalog response", false), { timeoutMs: CODEX_SESSION_CATALOG_CLI_TIMEOUT_MS }).action(listCodexSessions);
172
+ addGatewayClientOptions(codex.command("continue <thread-id>").description("Continue a Gateway-local Codex thread as an OpenClaw branch").option("--agent <id>", "Agent id that owns the Codex session").option("--host <id>", "Stable local host id from codex sessions").option("--json", "Print the structured response", false)).action(continueCodexSession);
173
+ addGatewayClientOptions(codex.command("archive <thread-id>").description("Archive a stored or idle Gateway-local Codex thread").option("--agent <id>", "Agent id that owns the Codex session").option("--host <id>", "Stable local host id from codex sessions").option("--confirm-no-other-runner", "Confirm no other Codex client or OpenClaw runner is using this thread", false).option("--json", "Print the structured response", false)).action(archiveCodexSession);
187
174
  }
188
175
  //#endregion
189
176
  export { registerCodexSessionCli };
@@ -1,7 +1,9 @@
1
- import { n as readCodexNativeHistory, t as consumeCodexHistory } from "./session-history-read-B3ZfSUbF.mjs";
1
+ import { n as readCodexNativeHistory, t as consumeCodexHistory } from "./session-history-read-Ov3StuL4.mjs";
2
+ import { resolveAgentHarnessHistoryLimits } from "openclaw/plugin-sdk/agent-harness-attempt-runtime";
2
3
  import { SessionManager } from "openclaw/plugin-sdk/agent-sessions";
3
4
  import { getSessionEntry, parseSqliteSessionFileMarker, resolveTranscriptSessionKeyBySessionId } from "openclaw/plugin-sdk/session-store-runtime";
4
5
  //#region extensions/codex/src/app-server/session-history.ts
6
+ /** Reads bounded model context from the Codex transcript mirror. */
5
7
  function resolveCodexHistoryTarget(target, admission) {
6
8
  if (target.sessionTarget) {
7
9
  const { agentId, sessionId, sessionKey, storePath } = target.sessionTarget;
@@ -58,11 +60,7 @@ async function readCodexMirroredSessionHistoryMessages(target, admission, signal
58
60
  const loaded = await SessionManager.openModelContextAsync(resolved.target, {
59
61
  admission,
60
62
  signal,
61
- limits: {
62
- maxBytes: Math.min(67108864, Math.max(1024, Math.floor((contextTokenBudget ?? 128e3) * 8))),
63
- maxEvents: 1e4,
64
- toolResultOverflow: "omit"
65
- }
63
+ limits: resolveAgentHarnessHistoryLimits(contextTokenBudget)
66
64
  });
67
65
  result = consumeCodexHistory(loaded.buildSessionContext().messages, loaded.getHeader(), target.sessionId, read, "codex mirrored model context");
68
66
  } else {
@@ -1,19 +1,20 @@
1
- import { m as sessionBindingIdentity } from "./session-binding-record-BGoz8wOK.mjs";
2
- import "./session-binding-Cm0apEbd.mjs";
3
- import { r as importCodexThreadHistoryToTranscript } from "./transcript-mirror-BtHDBp1G.mjs";
4
- import { n as prepareCodexSessionInitialization } from "./session-initialization-rcgbZiid.mjs";
1
+ import { v as sessionBindingIdentity } from "./session-binding-record-Oe9L-CNY.mjs";
2
+ import "./session-binding-DGCYAfvD.mjs";
3
+ import { r as importCodexThreadHistoryToTranscript } from "./transcript-mirror-kxmCYsuF.mjs";
4
+ import { n as prepareCodexSessionInitialization } from "./session-initialization-6aveB9qb.mjs";
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. */
8
8
  async function createImportedCodexSession(params) {
9
9
  const spawnedCwd = params.thread.cwd?.trim() || void 0;
10
- const createParams = {
10
+ return await params.runtime.agent.session.createSessionEntry({
11
11
  cfg: params.config,
12
12
  key: params.key,
13
13
  agentId: params.agentId,
14
14
  ...params.displayName !== void 0 ? { displayName: params.displayName } : {},
15
15
  ...spawnedCwd ? { spawnedCwd } : {},
16
16
  initialEntry: params.initialEntry,
17
+ ...params.recoverMatchingInitialEntry ? { recoverMatchingInitialEntry: true } : {},
17
18
  afterCreate: async (entry) => {
18
19
  if (!entry.initialization) throw new Error("Codex history initialization requires host creation authority");
19
20
  const initialization = prepareCodexSessionInitialization({
@@ -43,11 +44,7 @@ async function createImportedCodexSession(params) {
43
44
  entry.initialization.assertCurrent();
44
45
  return await params.afterImport(entry, initialization);
45
46
  }
46
- };
47
- return params.recoverMatchingInitialEntry ? await params.runtime.agent.session.createSessionEntry({
48
- ...createParams,
49
- recoverMatchingInitialEntry: true
50
- }) : await params.runtime.agent.session.createSessionEntry(createParams);
47
+ });
51
48
  }
52
49
  //#endregion
53
50
  export { createImportedCodexSession };
@@ -0,0 +1,133 @@
1
+ import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
2
+ import fs from "node:fs/promises";
3
+ import { SessionTranscriptReadFenceError, readCodexSessionContext } from "openclaw/plugin-sdk/codex-session-transcript-runtime";
4
+ import { INLINE_IMAGE_DATA_URL_PREFIX, sanitizeInlineImageDataUrl } from "openclaw/plugin-sdk/inline-image-data-url-runtime";
5
+ //#region extensions/codex/src/app-server/history-rejection.ts
6
+ /** Only an owning rejection site can supply a diagnostic; exception text is never evidence. */
7
+ var CodexHistoryRejection = class extends Error {
8
+ constructor(reason) {
9
+ super(`Codex history rejected: ${reason}`);
10
+ this.reason = reason;
11
+ }
12
+ };
13
+ function codexHistoryRejectionReason(error) {
14
+ return error instanceof CodexHistoryRejection ? error.reason : "history_read_failed";
15
+ }
16
+ //#endregion
17
+ //#region extensions/codex/src/app-server/image-payload-sanitizer.ts
18
+ /**
19
+ * Sanitizes inline image payloads mirrored through Codex history so invalid
20
+ * base64 data becomes readable text instead of poisoning replayed transcripts.
21
+ */
22
+ const IMAGE_OMITTED_TEXT = "omitted image payload: invalid inline image data";
23
+ /** Builds the replacement text inserted when an inline image payload is invalid. */
24
+ function invalidInlineImageText(label) {
25
+ return `[${label}] ${IMAGE_OMITTED_TEXT}`;
26
+ }
27
+ function sanitizeImageContentRecord(record, label) {
28
+ if (record.type === "image" && typeof record.data === "string") {
29
+ const mimeType = typeof record.mimeType === "string" ? record.mimeType : "image/png";
30
+ const imageUrl = sanitizeInlineImageDataUrl(`data:${mimeType};base64,${record.data}`);
31
+ if (!imageUrl) return {
32
+ type: "text",
33
+ text: invalidInlineImageText(label)
34
+ };
35
+ const commaIndex = imageUrl.indexOf(",");
36
+ const mime = imageUrl.slice(INLINE_IMAGE_DATA_URL_PREFIX.length, commaIndex).split(";")[0] ?? mimeType;
37
+ const data = imageUrl.slice(commaIndex + 1);
38
+ return mime === record.mimeType && data === record.data ? record : {
39
+ ...record,
40
+ mimeType: mime,
41
+ data
42
+ };
43
+ }
44
+ if (record.type === "inputImage" && typeof record.imageUrl === "string") {
45
+ const imageUrl = sanitizeInlineImageDataUrl(record.imageUrl);
46
+ if (!imageUrl) return {
47
+ type: "inputText",
48
+ text: invalidInlineImageText(label)
49
+ };
50
+ return imageUrl === record.imageUrl ? record : {
51
+ ...record,
52
+ imageUrl
53
+ };
54
+ }
55
+ if (record.type === "input_image" && typeof record.image_url === "string") {
56
+ const imageUrl = sanitizeInlineImageDataUrl(record.image_url);
57
+ if (!imageUrl) return {
58
+ type: "input_text",
59
+ text: invalidInlineImageText(label)
60
+ };
61
+ return imageUrl === record.image_url ? record : {
62
+ ...record,
63
+ image_url: imageUrl
64
+ };
65
+ }
66
+ }
67
+ /** Sanitizes images without copying unchanged history or mutating its owned snapshot. */
68
+ function sanitizeCodexHistoryImagePayloads(value, label) {
69
+ if (Array.isArray(value)) {
70
+ let next;
71
+ for (let index = 0; index < value.length; index++) {
72
+ const child = sanitizeCodexHistoryImagePayloads(value[index], label);
73
+ if (child !== value[index]) (next ??= value.slice())[index] = child;
74
+ }
75
+ return next ?? value;
76
+ }
77
+ if (!isRecord(value)) return value;
78
+ const imageRecord = sanitizeImageContentRecord(value, label);
79
+ if (imageRecord) return imageRecord;
80
+ let next;
81
+ for (const key in value) {
82
+ if (!Object.hasOwn(value, key)) continue;
83
+ const child = sanitizeCodexHistoryImagePayloads(value[key], label);
84
+ if (child !== value[key]) (next ??= { ...value })[key] = child;
85
+ }
86
+ return next ?? value;
87
+ }
88
+ //#endregion
89
+ //#region extensions/codex/src/app-server/session-history-read.ts
90
+ function consumeCodexHistory(messages, header, sessionId, read, imageLabel = "codex mirrored history") {
91
+ if (!isRecord(header) || header.type !== "session") return read([]);
92
+ if (typeof header.id !== "string") throw new CodexHistoryRejection("malformed_header");
93
+ if (header.id !== sessionId) return read([]);
94
+ return read((function* () {
95
+ for (const message of messages) yield sanitizeCodexHistoryImagePayloads(message, imageLabel);
96
+ })());
97
+ }
98
+ /** Keeps native evidence and its synchronous consumer inside the same readonly snapshot. */
99
+ async function readCodexNativeHistory(target, sessionId, read, admission, onSnapshot) {
100
+ const consume = (messages, header, version) => {
101
+ try {
102
+ onSnapshot?.(version);
103
+ return {
104
+ status: "ok",
105
+ value: consumeCodexHistory(messages, header, sessionId, read)
106
+ };
107
+ } catch (error) {
108
+ return {
109
+ status: "rejected",
110
+ reason: codexHistoryRejectionReason(error)
111
+ };
112
+ }
113
+ };
114
+ try {
115
+ if (target.kind === "empty") return consume([], void 0);
116
+ if (target.kind === "sqlite") return readCodexSessionContext(target.target, consume, admission);
117
+ const { buildSessionContext, migrateSessionEntries, parseSessionEntries } = await import("openclaw/plugin-sdk/agent-sessions");
118
+ const entries = parseSessionEntries(await fs.readFile(target.sessionFile, "utf-8"));
119
+ return consume((function* () {
120
+ migrateSessionEntries(entries);
121
+ const sessionEntries = entries.filter((entry) => isRecord(entry) && entry.type !== "session");
122
+ yield* buildSessionContext(sessionEntries).messages;
123
+ })(), entries[0]);
124
+ } catch (error) {
125
+ if (isRecord(error) && error.code === "ENOENT") return consume([], void 0);
126
+ return {
127
+ status: "rejected",
128
+ reason: error instanceof SessionTranscriptReadFenceError || isRecord(error) && (error.code === "EACCES" || error.code === "EPERM") ? "access_rejected" : codexHistoryRejectionReason(error)
129
+ };
130
+ }
131
+ }
132
+ //#endregion
133
+ export { CodexHistoryRejection as a, sanitizeInlineImageDataUrl as i, readCodexNativeHistory as n, codexHistoryRejectionReason as o, invalidInlineImageText as r, consumeCodexHistory as t };