@openclaw/codex 2026.9.1 → 2026.9.2

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 (67) hide show
  1. package/dist/api.js +6 -6
  2. package/dist/{attempt-client-cleanup-DYHcRQAa.js → attempt-client-cleanup-Bp1ZOnk2.js} +76 -32
  3. package/dist/{attempt-context-DmQUNWwT.js → attempt-context-CSazkWns.js} +6 -6
  4. package/dist/{bounded-turn-wzJrwKKe.js → bounded-turn-DxGJRYbY.js} +46 -45
  5. package/dist/{capabilities-dIjNVCYH.js → capabilities-B1mgvpP8.js} +2 -1
  6. package/dist/cli-metadata.js +1 -1
  7. package/dist/{command-formatters-CLHhEB1Q.js → command-formatters-DSbGMXA0.js} +2 -2
  8. package/dist/{command-handlers-CTGb2csu.js → command-handlers-DOJvGv6-.js} +146 -74
  9. package/dist/{compact-_t0HQrUS.js → compact-Y_xBqrHN.js} +83 -48
  10. package/dist/{config-BhmfC1s6.js → config-CyapYSji.js} +47 -105
  11. package/dist/config-utils-C57JiJrU.js +69 -0
  12. package/dist/doctor-contract-api.js +4 -5
  13. package/dist/{dynamic-tools-BU9tmlYm.js → dynamic-tools-BwpvTxaX.js} +678 -638
  14. package/dist/{effective-mcp-catalog-DzYBW4h1.js → effective-mcp-catalog-CY9Jn4bA.js} +4 -3
  15. package/dist/{event-projector-assistant-message-DHRFXKbS.js → event-projector-assistant-message-B9kp6iGC.js} +11 -2
  16. package/dist/{event-projector-usage-C5mcrGjp.js → event-projector-usage-ZqEVbAEY.js} +30 -13
  17. package/dist/{harness-DXVZ5II5.js → harness-Czh2Sdoc.js} +36 -13
  18. package/dist/harness.js +1 -1
  19. package/dist/{image-payload-sanitizer-CnfoUPCE.js → image-payload-sanitizer-tupAr-2o.js} +29 -15
  20. package/dist/index.js +68 -84
  21. package/dist/{isolated-completion-kg9kv4iH.js → isolated-completion-CRh-51AK.js} +9 -21
  22. package/dist/{managed-binary-4-Vjz5GH.js → managed-binary-DcpnJF9x.js} +105 -73
  23. package/dist/media-understanding-provider.js +1 -1
  24. package/dist/{model-catalog-CUM68Hkl.js → model-catalog-DT5vo6qo.js} +5 -5
  25. package/dist/{models-sYnEc0gd.js → models-CcrgSMQR.js} +4 -4
  26. package/dist/{native-subagent-monitor-CnH147jH.js → native-subagent-monitor-B3bvQGcg.js} +12 -11
  27. package/dist/{node-exec-server.runtime-CstNHCmC.js → node-exec-server.runtime-nfbUOtUB.js} +3 -3
  28. package/dist/{plugin-approval-roundtrip-CNe-Xrjx.js → plugin-approval-roundtrip-aQVdyL5g.js} +1 -1
  29. package/dist/{plugin-marketplace-discovery-CfFlKqDl.js → plugin-marketplace-discovery-B7gHXJ3d.js} +35 -22
  30. package/dist/{plugin-metadata-cache-BFrPhb2c.js → plugin-metadata-cache-BwCLTY_U.js} +5 -5
  31. package/dist/{provider-capabilities-DW5p4k9w.js → provider-capabilities-BpG9Ltc5.js} +2 -2
  32. package/dist/{rate-limits-CawQJfUS.js → rate-limits-Fx_l4eNa.js} +1 -1
  33. package/dist/{request-DYAI5FQE.js → request-C8H22rPi.js} +2 -2
  34. package/dist/{run-attempt-D1hJO4fX.js → run-attempt-BzthFQSM.js} +977 -723
  35. package/dist/{runtime-artifact-C3jVimFn.js → runtime-artifact-Bh_gf6-t.js} +3 -3
  36. package/dist/{session-binding-BHuTCRZQ.js → session-binding-4Ki04sW-.js} +94 -282
  37. package/dist/session-binding-record-CyaXZvTe.js +270 -0
  38. package/dist/{session-catalog-yyvTWFOw.js → session-catalog-B47uwekb.js} +266 -114
  39. package/dist/{session-cli-CmFEXMAM.js → session-cli-BjLhpmS1.js} +1 -1
  40. package/dist/session-history-DWmMqiqW.js +93 -0
  41. package/dist/session-history-read-LHldwvyh.js +36 -0
  42. package/dist/session-history-worker-runtime.js +48 -0
  43. package/dist/{settled-turn-context-D3SNWtUn.js → session-history.worker-zZVcx0ME.js} +30 -31
  44. package/dist/session-history.worker.js +2 -0
  45. package/dist/{session-initialization-BeWzjGiR.js → session-initialization-BCFVnLL4.js} +2 -1
  46. package/dist/{session-permission-policy-DeWVTCMj.js → session-permission-policy-BaueHmSj.js} +1 -1
  47. package/dist/{session-retirement-BujDjXVF.js → session-retirement-DNdmYdFc.js} +7 -7
  48. package/dist/{session-upstream-marker-C351-5Qw.js → session-upstream-marker-DReTpGz6.js} +4 -3
  49. package/dist/settled-turn-context-BOM3Y1pl.js +45 -0
  50. package/dist/{settled-turn-finalizer-BVJx4yoc.js → settled-turn-finalizer-BI-b1sry.js} +53 -42
  51. package/dist/{shared-client-DxcfF9KX.js → shared-client-CKhX2kFt.js} +279 -268
  52. package/dist/{side-question-BTZAII4l.js → side-question-B6DWAw1A.js} +85 -36
  53. package/dist/{thread-lifecycle-DAcEJ_Om.js → thread-lifecycle-DPK30jad.js} +382 -388
  54. package/dist/{thread-ownership-zGokd8i1.js → thread-ownership-CbucAmmp.js} +5 -5
  55. package/dist/thread-policy-CTalhWFy.js +105 -0
  56. package/dist/{thread-resume-C7pyVKeW.js → thread-resume-BLgqkUc1.js} +7 -7
  57. package/dist/{transcript-mirror-DTUxFWa_.js → transcript-mirror-_njEB84z.js} +67 -125
  58. package/dist/transcript-mirror-attestation-Byl34PC-.js +76 -0
  59. package/dist/{transport-stdio-CyPldczm.js → transport-stdio-CzTngV0j.js} +10 -8
  60. package/dist/{upstream-session-fork-CYlBIGVt.js → upstream-session-fork-1fwbNKzQ.js} +85 -165
  61. package/dist/{usage-Bj-rrzkR.js → usage-i9fv5-4m.js} +3 -3
  62. package/dist/{web-search-provider.runtime-D2FWSK4w.js → web-search-provider.runtime-DKQn67A7.js} +3 -3
  63. package/package.json +6 -6
  64. package/dist/binding-connection-E6uDsPlx.js +0 -45
  65. package/dist/launch-args-RXQwn8zV.js +0 -90
  66. package/dist/session-history-C5J1AKzG.js +0 -87
  67. package/dist/thread-policy-g4KbJPzp.js +0 -54
@@ -1,30 +1,32 @@
1
- import { $t as isJsonObject, Jt as readCodexSessionMeta, K as resolveCodexAppServerClientInstanceId, Nt as withTimeout, Vt as resolveCodexAppServerAuthProfileStore, Wt as resolveCodexAppServerPreparedAuthHandoff, Xt as CODEX_INTERACTIVE_THREAD_SOURCE_KINDS, Yt as CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES, Z as assertCodexThreadForkParams, c as getLeasedSharedCodexAppServerClient, h as releaseLeasedSharedCodexAppServerClient, q as CodexAppServerRpcError, qt as isOpenClawManagedCodexThread, y as retireSharedCodexAppServerClientIfCurrent, zt as resolveCodexAppServerAuthProfileId } from "./shared-client-DxcfF9KX.js";
2
- import { E as readCodexPluginConfig, F as resolveCodexAppServerHomeDir, I as resolveCodexAppServerLocalHomeDir, L as resolveCodexAppServerUserHomeDir, i as resolveCodexAppServerRuntimeOptions, s as resolveCodexSupervisionAppServerRuntimeOptions } from "./config-BhmfC1s6.js";
3
- import { c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity } from "./session-binding-BHuTCRZQ.js";
4
- import { a as closeCodexStartupClientBestEffort } from "./attempt-client-cleanup-DYHcRQAa.js";
5
- import { n as listCodexAppServerModels } from "./models-sYnEc0gd.js";
6
- import { a as replaceCodexCatalogConnectionHomes, n as buildCodexAppServerConnectionFingerprint, t as resumeCodexAppServerThread } from "./thread-resume-C7pyVKeW.js";
7
- import { g as codexCatalogHomeId, h as canonicalCodexCatalogHome, m as projectCodexUserItemText, r as importCodexThreadHistoryToTranscript } from "./transcript-mirror-DTUxFWa_.js";
8
- import { i as requestCodexAppServerJson, o as withCodexAppServerJsonClient, r as requestCodexAppServerClientJson } from "./request-DYAI5FQE.js";
9
- import { n as describeControlFailure, t as CODEX_CONTROL_METHODS } from "./capabilities-dIjNVCYH.js";
10
- import { a as formatCodexDisplayText } from "./command-formatters-CLHhEB1Q.js";
1
+ import { l as sessionBindingIdentity } from "./session-binding-record-CyaXZvTe.js";
2
+ import { B as isJsonObject, I as CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES, L as CODEX_INTERACTIVE_THREAD_SOURCE_KINDS, M as resolveCodexAppServerHomeDir, N as resolveCodexAppServerLocalHomeDir, O as readCodexPluginConfig, P as resolveCodexAppServerUserHomeDir, i as resolveCodexAppServerRuntimeOptions, s as resolveCodexSupervisionAppServerRuntimeOptions } from "./config-CyapYSji.js";
3
+ import { $ as assertCodexThreadForkParams, Ft as withTimeout, J as isCodexThreadReadMissingError, K as resolveCodexAppServerClientInstanceId, Kt as resolveCodexAppServerPreparedAuthHandoff, Ut as resolveCodexAppServerAuthProfileStore, Vt as resolveCodexAppServerAuthProfileId, Xt as readCodexSessionMeta, Yt as isOpenClawManagedCodexThread, c as getLeasedSharedCodexAppServerClient, h as releaseLeasedSharedCodexAppServerClient, y as retireSharedCodexAppServerClientIfCurrent } from "./shared-client-CKhX2kFt.js";
4
+ import { r as createCodexSessionGenerationSupersededError, s as reclaimCurrentCodexSessionGeneration } from "./session-binding-4Ki04sW-.js";
5
+ import { a as closeCodexStartupClientBestEffort } from "./attempt-client-cleanup-Bp1ZOnk2.js";
6
+ import { n as listCodexAppServerModels } from "./models-CcrgSMQR.js";
7
+ import { a as replaceCodexCatalogConnectionHomes, n as buildCodexAppServerConnectionFingerprint, t as resumeCodexAppServerThread } from "./thread-resume-BLgqkUc1.js";
8
+ import { d as codexCatalogHomeId, l as projectCodexUserItemText, r as importCodexThreadHistoryToTranscript, u as canonicalCodexCatalogHome } from "./transcript-mirror-_njEB84z.js";
9
+ import { i as requestCodexAppServerJson, o as withCodexAppServerJsonClient, r as requestCodexAppServerClientJson } from "./request-C8H22rPi.js";
10
+ import { n as describeControlFailure, t as CODEX_CONTROL_METHODS } from "./capabilities-B1mgvpP8.js";
11
+ import { a as formatCodexDisplayText } from "./command-formatters-DSbGMXA0.js";
11
12
  import { n as createCodexCliNodeConversationBindingData } from "./conversation-binding-data-BiodpIzq.js";
12
13
  import { n as prepareCodexAppServerAuthBinding } from "./auth-binding-Ds_QVm-X.js";
13
- import { i as createImportedCodexSession, n as codexUpstreamBaseline, r as codexUpstreamContinueResult, t as codexLastTerminalTurnId } from "./session-upstream-marker-C351-5Qw.js";
14
+ import { i as createImportedCodexSession, n as codexUpstreamBaseline, r as codexUpstreamContinueResult, t as codexLastTerminalTurnId } from "./session-upstream-marker-DReTpGz6.js";
14
15
  import { asFiniteNumber, isRecord, normalizeBoundedOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
16
+ import { resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
17
+ import { getSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
18
+ import { z } from "zod";
19
+ import { timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
20
+ import { runCommandBuffered } from "openclaw/plugin-sdk/process-runtime";
15
21
  import fs from "node:fs/promises";
16
22
  import path from "node:path";
17
- import { timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
18
23
  import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/temp-path";
19
24
  import { prepareAgentRuntimeAuth } from "openclaw/plugin-sdk/agent-harness-runtime";
20
25
  import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
21
26
  import fsSync from "node:fs";
22
27
  import os from "node:os";
23
- import { listAgentIds, resolveAgentDir as resolveAgentDir$1, resolveAgentWorkspaceDir, resolveAllowedModelRef, resolveDefaultAgentDir, resolveDefaultAgentId, resolveDefaultModelForAgent } from "openclaw/plugin-sdk/agent-runtime";
24
- import { runCommandBuffered } from "openclaw/plugin-sdk/process-runtime";
25
- import { resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
28
+ import { listAgentIds as listAgentIds$1, resolveAgentDir as resolveAgentDir$2, resolveAgentWorkspaceDir, resolveAllowedModelRef, resolveDefaultAgentDir, resolveDefaultAgentId as resolveDefaultAgentId$1, resolveDefaultModelForAgent } from "openclaw/plugin-sdk/agent-runtime";
26
29
  import { materializeWindowsSpawnProgram, resolveWindowsSpawnProgram } from "openclaw/plugin-sdk/windows-spawn";
27
- import { getSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
28
30
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
29
31
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
30
32
  import { sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
@@ -32,7 +34,7 @@ import { parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
32
34
  import process$1 from "node:process";
33
35
  import { resolveSessionModelRef } from "openclaw/plugin-sdk/model-session-runtime";
34
36
  import { resolveApiKeyForProvider } from "openclaw/plugin-sdk/provider-auth-runtime";
35
- import { createSessionCatalogAdoptionCoordinator, listSessionCatalogEntries, sessionCatalogAdoptedSessionKey, sessionCatalogAdoptedSourceKey } from "openclaw/plugin-sdk/session-catalog";
37
+ import { createSessionCatalogAdoptionCoordinator, listSessionCatalogEntries, publishSessionCatalogHost, sessionCatalogAdoptedSessionKey, sessionCatalogAdoptedSourceKey, sessionCatalogPaging } from "openclaw/plugin-sdk/session-catalog";
36
38
  import { decodeNodePtyResumeParams, decodeNodePtyStartParams, resolveNodeHostExecutable, runNodePtyCommand } from "openclaw/plugin-sdk/node-host";
37
39
  //#region extensions/codex/src/jsonl-lines.ts
38
40
  const JSONL_STREAM_THRESHOLD_BYTES = 4194304;
@@ -550,29 +552,37 @@ function formatNodeLabel(node) {
550
552
  //#endregion
551
553
  //#region extensions/codex/src/command-rpc.ts
552
554
  async function prepareControlAuth(options, startOptions) {
553
- if (!options.onResponse || !options.config || !options.sessionKey || options.authProfileId === null || startOptions.homeScope === "user") return {
555
+ if (!options.onResponse) return {
554
556
  authProfileId: options.authProfileId ?? void 0,
555
557
  clientOptions: { authProfileId: options.authProfileId }
556
558
  };
559
+ if (!options.config || !options.sessionKey || !options.sessionId) throw new Error("Codex control subscription requires admitted session authority.");
557
560
  const config = options.config;
558
561
  const { sessionAgentId } = resolveSessionAgentIdsStrict({
559
562
  config,
560
563
  sessionKey: options.sessionKey,
561
564
  agentId: options.agentId
562
565
  });
563
- const agentDir = options.agentDir ?? resolveAgentDir$1(config, sessionAgentId);
566
+ const agentDir = options.agentDir ?? resolveAgentDir$2(config, sessionAgentId);
564
567
  const workspaceDir = resolveAgentWorkspaceDir(config, sessionAgentId);
565
568
  const entry = getSessionEntry({
566
569
  agentId: sessionAgentId,
567
- storePath: resolveStorePath(config.session?.store, { agentId: sessionAgentId }),
570
+ storePath: options.storePath?.trim() || resolveStorePath(config.session?.store, { agentId: sessionAgentId }),
568
571
  sessionKey: options.sessionKey,
569
572
  hydrateSkillPromptRefs: false,
570
573
  readConsistency: "latest"
571
574
  });
575
+ if (entry?.sessionId !== options.sessionId) throw createCodexSessionGenerationSupersededError(options.sessionId);
576
+ if (options.authProfileId === null || startOptions.homeScope === "user") return {
577
+ authProfileId: options.authProfileId ?? void 0,
578
+ clientOptions: { authProfileId: options.authProfileId }
579
+ };
572
580
  const model = resolveSessionModelRef(config, entry, sessionAgentId);
581
+ const authProfileId = entry?.authProfileOverride ?? options.authProfileId;
573
582
  const store = resolveCodexAppServerAuthProfileStore({
574
583
  agentDir,
575
- config
584
+ config,
585
+ authProfileId
576
586
  });
577
587
  const { plan, attempts } = prepareAgentRuntimeAuth({
578
588
  provider: model.provider,
@@ -581,7 +591,7 @@ async function prepareControlAuth(options, startOptions) {
581
591
  agentDir,
582
592
  workspaceDir,
583
593
  authProfileStore: store,
584
- sessionAuthProfileId: entry?.authProfileOverride ?? options.authProfileId,
594
+ sessionAuthProfileId: authProfileId,
585
595
  sessionAuthProfileSource: entry?.authProfileOverrideSource,
586
596
  harnessId: "codex",
587
597
  harnessAuthBootstrap: "harness"
@@ -795,6 +805,7 @@ const DEFAULT_PAGE_LIMIT = 50;
795
805
  const CODEX_APP_SERVER_THREADS_CAPABILITY = "codex-app-server-threads";
796
806
  const CODEX_APP_SERVER_THREADS_LIST_COMMAND = "codex.appServer.threads.list.v1";
797
807
  const CODEX_APP_SERVER_THREAD_TURNS_LIST_COMMAND = "codex.appServer.thread.turns.list.v1";
808
+ const CODEX_CATALOG_TRANSCRIPT_READ_COMMAND = "codex.sessionCatalog.transcript.read.v1";
798
809
  const CODEX_LOCAL_SESSION_HOST_ID = "gateway:local";
799
810
  const NODE_INVOKE_TIMEOUT_MS = 65e3;
800
811
  const MAX_SEARCH_LENGTH = 500;
@@ -1057,7 +1068,7 @@ function parseTranscriptPage(value) {
1057
1068
  ...nextCursor ? { nextCursor } : {},
1058
1069
  ...backwardsCursor ? { backwardsCursor } : {}
1059
1070
  };
1060
- if (Buffer.byteLength(JSON.stringify(page), "utf8") > MAX_TRANSCRIPT_PAGE_BYTES) throw new Error("Codex app-server transcript page exceeds the safe response size");
1071
+ if (Buffer.byteLength(JSON.stringify(page), "utf8") > 20971520) throw new Error("Codex app-server transcript page exceeds the safe response size");
1061
1072
  return page;
1062
1073
  }
1063
1074
  function requireBoundThread(entry) {
@@ -1142,10 +1153,16 @@ async function finalizeNodeAdoptedSession(params) {
1142
1153
  update: (entry) => {
1143
1154
  const current = readNodeSessionMarker(entry);
1144
1155
  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();
1145
- if (current.initializing !== true) return { archivedAt: void 0 };
1156
+ if (current.initializing !== true) return {
1157
+ archivedAt: void 0,
1158
+ archivedBy: void 0,
1159
+ archiveReason: void 0
1160
+ };
1146
1161
  const codex = isRecord(entry.pluginExtensions?.codex) ? entry.pluginExtensions.codex : {};
1147
1162
  return {
1148
1163
  archivedAt: void 0,
1164
+ archivedBy: void 0,
1165
+ archiveReason: void 0,
1149
1166
  pluginExtensions: {
1150
1167
  ...entry.pluginExtensions,
1151
1168
  codex: {
@@ -1273,7 +1290,7 @@ async function listAdoptedSessionEntries(params) {
1273
1290
  if (!sessionKeyRest.startsWith(CODEX_SUPERVISION_SESSION_KEY_PREFIX) || !marker || entry.initializationPending === true || entry.agentHarnessId !== "codex" || entry.modelSelectionLocked !== true) continue;
1274
1291
  const sessionId = entry.sessionId?.trim();
1275
1292
  if (!sessionId) continue;
1276
- const binding = await params.bindingStore.read(sessionBindingIdentity({
1293
+ const binding = params.bindingStore.read(sessionBindingIdentity({
1277
1294
  sessionId,
1278
1295
  sessionKey,
1279
1296
  config: params.config
@@ -1314,7 +1331,7 @@ async function ensurePendingAdoptionBinding(params) {
1314
1331
  });
1315
1332
  params.initialization.assertCurrent();
1316
1333
  if (!ownsGeneration) throw new Error(`failed to claim the OpenClaw session generation for ${params.sourceThreadId}`);
1317
- const existing = await params.bindingStore.read(params.identity);
1334
+ const existing = params.bindingStore.read(params.identity);
1318
1335
  params.initialization.assertCurrent();
1319
1336
  if (existing) {
1320
1337
  if (matchesPendingAdoptionBinding(existing, params)) return;
@@ -1418,7 +1435,11 @@ async function continueLocalCodexSessionInner(params) {
1418
1435
  preserveActivity: true,
1419
1436
  update: (entry) => {
1420
1437
  if (entry.sessionId?.trim() !== existing.sessionId || entry.initializationPending === true || entry.agentHarnessId !== "codex" || entry.modelSelectionLocked !== true) throw changedError();
1421
- return { archivedAt: void 0 };
1438
+ return {
1439
+ archivedAt: void 0,
1440
+ archivedBy: void 0,
1441
+ archiveReason: void 0
1442
+ };
1422
1443
  }
1423
1444
  })) throw changedError();
1424
1445
  const connectionFingerprint = params.control.connectionFingerprint;
@@ -1473,8 +1494,8 @@ async function continueLocalCodexSession(params) {
1473
1494
  }
1474
1495
  //#endregion
1475
1496
  //#region extensions/codex/src/session-catalog-archive.ts
1476
- async function assertNoPendingSupervisionBranch(params) {
1477
- const adoptedEntries = [params.agentId, ...listAgentIds(params.config).filter((agentId) => agentId !== params.agentId)].flatMap((agentId) => params.runtime.agent.session.listSessionEntries({
1497
+ function assertNoPendingSupervisionBranch(params) {
1498
+ const adoptedEntries = [params.agentId, ...listAgentIds$1(params.config).filter((agentId) => agentId !== params.agentId)].flatMap((agentId) => params.runtime.agent.session.listSessionEntries({
1478
1499
  agentId,
1479
1500
  readOnly: true
1480
1501
  })).filter((candidate) => isAdoptionSessionKeyForThread(candidate.sessionKey, params.threadId, params.sourceHomeId) || params.sourceHomeId !== void 0 && params.allowLegacy === true && isAdoptionSessionKeyForThread(candidate.sessionKey, params.threadId));
@@ -1482,7 +1503,7 @@ async function assertNoPendingSupervisionBranch(params) {
1482
1503
  if (adopted.entry.initializationPending === true) throw new CatalogParamsError("Codex session cannot be archived while its OpenClaw branch is initializing");
1483
1504
  const sessionId = adopted.entry.sessionId?.trim();
1484
1505
  if (!sessionId) continue;
1485
- const binding = await params.bindingStore.read(sessionBindingIdentity({
1506
+ const binding = params.bindingStore.read(sessionBindingIdentity({
1486
1507
  sessionId,
1487
1508
  sessionKey: adopted.sessionKey,
1488
1509
  config: params.config
@@ -1495,7 +1516,7 @@ async function archiveLocalCodexSession(params) {
1495
1516
  return await runSessionActionExclusive(sessionCatalogAdoptedSourceKey(params.hostId ?? "gateway:local", params.threadId), async () => {
1496
1517
  return await params.bindingStore.withThreadArchiveFence(async () => {
1497
1518
  const run = async (control) => {
1498
- await assertNoPendingSupervisionBranch(params);
1519
+ assertNoPendingSupervisionBranch(params);
1499
1520
  await control.requireEligibleThread(params.threadId);
1500
1521
  const thread = await control.readThread(params.threadId, false);
1501
1522
  if (thread.id !== params.threadId) throw new Error("Codex app-server returned a different thread than requested");
@@ -1524,7 +1545,7 @@ const CODEX_AGENT_RUNTIME_ID = "codex";
1524
1545
  const CODEX_CATALOG_DEFAULT_MODEL_REF = "openai/gpt-5.6-sol";
1525
1546
  function resolveCodexCatalogCreateSession(config, requestedAgentId) {
1526
1547
  if (!config) return;
1527
- const agentId = requestedAgentId ?? resolveDefaultAgentId(config);
1548
+ const agentId = requestedAgentId ?? resolveDefaultAgentId$1(config);
1528
1549
  const defaultModel = resolveDefaultModelForAgent({
1529
1550
  cfg: config,
1530
1551
  agentId
@@ -1606,7 +1627,8 @@ async function listPairedNode(params) {
1606
1627
  searchTerm: params.query.search
1607
1628
  },
1608
1629
  timeoutMs: NODE_INVOKE_TIMEOUT_MS,
1609
- scopes: ["operator.write"]
1630
+ scopes: ["operator.write"],
1631
+ signal: params.signal
1610
1632
  }))), params.query.search);
1611
1633
  return {
1612
1634
  ...common,
@@ -1623,7 +1645,7 @@ async function listPairedNode(params) {
1623
1645
  sessions: [],
1624
1646
  error: catalogError("NODE_INVOKE_FAILED", error)
1625
1647
  }));
1626
- if (params.onHost) eventualHost.then(params.onHost).catch(() => void 0);
1648
+ publishSessionCatalogHost(params, eventualHost);
1627
1649
  try {
1628
1650
  return await withTimeout(eventualHost, NODE_CATALOG_LIST_RESPONSE_TIMEOUT_MS, "paired node Codex session catalog timed out");
1629
1651
  } catch (error) {
@@ -1822,7 +1844,7 @@ function createCodexTerminalStartNodeHostCommand() {
1822
1844
  function resolveCodexCatalogTerminalHome(sources) {
1823
1845
  const runtimeConfig = sources.getRuntimeConfig();
1824
1846
  if (!runtimeConfig) throw new Error("OpenClaw runtime config is unavailable");
1825
- const agentDir = sources.source?.agentDir ?? (sources.agentId ? resolveAgentDir$1(runtimeConfig, sources.agentId) : resolveDefaultAgentDir(runtimeConfig));
1847
+ const agentDir = sources.source?.agentDir ?? (sources.agentId ? resolveAgentDir$2(runtimeConfig, sources.agentId) : resolveDefaultAgentDir(runtimeConfig));
1826
1848
  const startOptions = sources.source?.appServer.start ?? resolveCodexSupervisionAppServerRuntimeOptions({ pluginConfig: sources.getPluginConfig() }).start;
1827
1849
  return resolveCodexAppServerLocalHomeDir(startOptions, agentDir);
1828
1850
  }
@@ -1978,6 +2000,144 @@ async function startCodexCatalogTerminal(params) {
1978
2000
  };
1979
2001
  }
1980
2002
  //#endregion
2003
+ //#region extensions/codex/src/session-catalog-transcript-item.ts
2004
+ const CODEX_MESSAGE_TYPES = /* @__PURE__ */ new Map([
2005
+ ["userMessage", "userMessage"],
2006
+ ["agentMessage", "agentMessage"],
2007
+ ["reasoning", "reasoning"]
2008
+ ]);
2009
+ const CODEX_TOOL_TYPES = /* @__PURE__ */ new Set([
2010
+ "commandExecution",
2011
+ "fileChange",
2012
+ "mcpToolCall",
2013
+ "dynamicToolCall",
2014
+ "collabAgentToolCall",
2015
+ "webSearch",
2016
+ "imageView",
2017
+ "imageGeneration"
2018
+ ]);
2019
+ function toGenericTranscriptItem(item) {
2020
+ let type = CODEX_MESSAGE_TYPES.get(item.type);
2021
+ if (!type && CODEX_TOOL_TYPES.has(item.type)) type = item.result !== void 0 || Boolean(item.aggregatedOutput) ? "toolResult" : "toolCall";
2022
+ type ??= "other";
2023
+ const fallback = item.title ?? item.name ?? item.tool ?? item.command ?? item.query ?? void 0;
2024
+ const resultText = item.aggregatedOutput || (item.result === void 0 ? void 0 : JSON.stringify(item.result, null, 2));
2025
+ const changesText = Array.isArray(item.changes) ? item.changes.map((change) => `${change.kind}: ${change.path}`).join("\n") || void 0 : void 0;
2026
+ const text = item.type === "userMessage" ? projectCodexUserItemText(item) : item.text || resultText || changesText || fallback;
2027
+ return {
2028
+ id: item.id,
2029
+ type,
2030
+ ...text ? { text } : {},
2031
+ raw: item
2032
+ };
2033
+ }
2034
+ //#endregion
2035
+ //#region extensions/codex/src/session-catalog-transcript.ts
2036
+ const TURN_ITEM_CURSOR_PREFIX = "turn-item:";
2037
+ const transcriptPageSchema = z.strictObject({
2038
+ items: z.array(z.strictObject({
2039
+ id: z.string(),
2040
+ type: z.enum([
2041
+ "userMessage",
2042
+ "agentMessage",
2043
+ "reasoning",
2044
+ "toolCall",
2045
+ "toolResult",
2046
+ "other"
2047
+ ]),
2048
+ text: z.string().optional(),
2049
+ raw: z.record(z.string(), z.json()).optional(),
2050
+ truncated: z.boolean().optional()
2051
+ })),
2052
+ nextCursor: z.string().optional()
2053
+ });
2054
+ function parseCodexCatalogTranscriptPage(value) {
2055
+ return transcriptPageSchema.parse(value);
2056
+ }
2057
+ function encodeTurnItemCursor(turnCursor, itemId) {
2058
+ return TURN_ITEM_CURSOR_PREFIX + Buffer.from(JSON.stringify([turnCursor, itemId])).toString("base64url");
2059
+ }
2060
+ function decodeTurnItemCursor(cursor) {
2061
+ if (!cursor?.startsWith(TURN_ITEM_CURSOR_PREFIX)) return { turnCursor: cursor };
2062
+ let value;
2063
+ try {
2064
+ value = JSON.parse(Buffer.from(cursor.slice(10), "base64url").toString());
2065
+ } catch {
2066
+ throw new CatalogParamsError("invalid Codex transcript item cursor");
2067
+ }
2068
+ if (!Array.isArray(value) || value.length !== 2 || typeof value[0] !== "string" || !value[0] || typeof value[1] !== "string" || !value[1]) throw new CatalogParamsError("invalid Codex transcript item cursor");
2069
+ return {
2070
+ turnCursor: value[0],
2071
+ itemId: value[1]
2072
+ };
2073
+ }
2074
+ function projectTranscriptPage(items, limit) {
2075
+ const projected = items.map(toGenericTranscriptItem);
2076
+ const page = sessionCatalogPaging.boundTranscriptPage(projected.toReversed(), limit, 0).items;
2077
+ for (const [index, item] of page.entries()) if (item.text !== projected[index]?.text && projected[index]?.text) item.truncated = true;
2078
+ return page;
2079
+ }
2080
+ function pageFitsNodeTransport(page) {
2081
+ return Buffer.byteLength(JSON.stringify({ payloadJSON: JSON.stringify(page) }), "utf8") <= MAX_TRANSCRIPT_PAGE_BYTES;
2082
+ }
2083
+ /** The legacy API can anchor a turn, but cannot continue within that turn. */
2084
+ async function readLegacyCodexTranscriptPage(readTurns, request) {
2085
+ const { turnCursor, itemId } = decodeTurnItemCursor(request.cursor);
2086
+ const page = parseTranscriptPage(await readTurns({
2087
+ threadId: request.threadId,
2088
+ limit: 1,
2089
+ sortDirection: "desc",
2090
+ itemsView: "full",
2091
+ ...turnCursor ? { cursor: turnCursor } : {}
2092
+ }));
2093
+ const source = page.data.flatMap((turn) => turn.items.toReversed());
2094
+ const anchorIndex = itemId ? source.findIndex((item) => item.id === itemId) : -1;
2095
+ if (itemId && anchorIndex < 0) throw new CatalogParamsError("Codex transcript changed; refresh the session before loading older items");
2096
+ const remaining = source.slice(anchorIndex + 1);
2097
+ const items = projectTranscriptPage(remaining, request.limit);
2098
+ const result = () => {
2099
+ const lastSource = remaining[items.length - 1];
2100
+ const partial = lastSource !== void 0 && items.length < remaining.length;
2101
+ const nativeCursor = partial ? page.backwardsCursor : page.nextCursor;
2102
+ const cursor = nativeCursor ? partial ? encodeTurnItemCursor(nativeCursor, lastSource.id) : nativeCursor : void 0;
2103
+ if (partial && !cursor) throw new Error("Codex app-server did not provide a transcript continuation anchor");
2104
+ return {
2105
+ items,
2106
+ ...cursor ? { nextCursor: cursor } : {}
2107
+ };
2108
+ };
2109
+ let bounded = result();
2110
+ while (!pageFitsNodeTransport(bounded)) {
2111
+ if (items.length <= 1) throw new Error("Codex transcript item exceeds the safe response size");
2112
+ items.pop();
2113
+ bounded = result();
2114
+ }
2115
+ return bounded;
2116
+ }
2117
+ /** Uses the native store's item cursor whenever that store supports item history. */
2118
+ async function readCodexCatalogTranscriptPage(control, request) {
2119
+ if ((await control.requireEligibleThread(request.threadId)).historyMode !== "paginated") return readLegacyCodexTranscriptPage((params) => control.listTurnPage(params), request);
2120
+ let limit = request.limit;
2121
+ for (;;) {
2122
+ const page = await control.listItemPage({
2123
+ threadId: request.threadId,
2124
+ limit,
2125
+ sortDirection: "desc",
2126
+ ...request.cursor ? { cursor: request.cursor } : {}
2127
+ });
2128
+ const nextCursor = readControlCursor(page.nextCursor, "transcript next response");
2129
+ const items = projectTranscriptPage(page.data.map(({ item }) => item), limit);
2130
+ const result = {
2131
+ items,
2132
+ ...nextCursor ? { nextCursor } : {}
2133
+ };
2134
+ const fittingCount = items.length - (pageFitsNodeTransport(result) ? 0 : 1);
2135
+ if (fittingCount === page.data.length) return result;
2136
+ if (fittingCount < 1) throw new Error("Codex transcript item exceeds the safe response size");
2137
+ limit = fittingCount;
2138
+ }
2139
+ }
2140
+ //#endregion
1981
2141
  //#region extensions/codex/src/session-catalog-listing.ts
1982
2142
  async function listVisiblePage(params) {
1983
2143
  const excluded = params.excludedThreadIds;
@@ -1987,6 +2147,7 @@ async function listVisiblePage(params) {
1987
2147
  let backwardsCursor;
1988
2148
  const seenCursors = /* @__PURE__ */ new Set();
1989
2149
  for (let pageIndex = 0; pageIndex < 20; pageIndex += 1) {
2150
+ params.signal?.throwIfAborted();
1990
2151
  let excludedFromPage = false;
1991
2152
  const rawPage = await params.control.listPage({
1992
2153
  limit: params.limit - sessions.length,
@@ -1994,10 +2155,12 @@ async function listVisiblePage(params) {
1994
2155
  ...params.searchTerm ? { searchTerm: params.searchTerm } : {},
1995
2156
  ...params.cwd ? { cwd: params.cwd } : {}
1996
2157
  });
2158
+ params.signal?.throwIfAborted();
1997
2159
  const page = filterCatalogPageByTitle(parseCatalogPage(rawPage), params.searchTerm);
1998
2160
  if (pageIndex === 0) backwardsCursor = page.backwardsCursor;
1999
2161
  for (const managed of rawPage.managedThreads ?? []) {
2000
2162
  excludedFromPage = true;
2163
+ params.signal?.throwIfAborted();
2001
2164
  await params.onExcludedThread?.(managed);
2002
2165
  }
2003
2166
  for (const session of page.sessions) {
@@ -2006,6 +2169,7 @@ async function listVisiblePage(params) {
2006
2169
  continue;
2007
2170
  }
2008
2171
  excludedFromPage = true;
2172
+ params.signal?.throwIfAborted();
2009
2173
  await params.onExcludedThread?.({ threadId: session.threadId });
2010
2174
  }
2011
2175
  nextCursor = page.nextCursor;
@@ -2031,8 +2195,10 @@ async function listGatewayHost(params) {
2031
2195
  excludedThreadIds: params.excludedThreadIds,
2032
2196
  limit: params.query.limitPerHost,
2033
2197
  onExcludedThread: params.onExcludedThread,
2034
- searchTerm: params.query.search
2198
+ searchTerm: params.query.search,
2199
+ signal: params.signal
2035
2200
  });
2201
+ params.signal?.throwIfAborted();
2036
2202
  const adoptedSessions = await listAdoptedSessionEntries({
2037
2203
  agentId: params.agentId,
2038
2204
  bindingStore: params.bindingStore,
@@ -2073,6 +2239,7 @@ async function listCodexSessionCatalog(params) {
2073
2239
  const requestedHostIds = query.hostIds ? new Set(query.hostIds) : void 0;
2074
2240
  const localSources = params.localHomes?.filter((source) => !requestedHostIds || requestedHostIds.has(source.hostId)) ?? (params.includeLocal !== false && (!requestedHostIds || requestedHostIds.has("gateway:local")) ? [void 0] : []);
2075
2241
  const managedThreads = await params.bindingStore.managedThreads?.snapshot();
2242
+ params.signal?.throwIfAborted();
2076
2243
  const fallbackSource = params.control.homesForAgent(agentId)[0];
2077
2244
  const localHosts = localSources.map((source) => (() => {
2078
2245
  const ownershipSource = source ?? fallbackSource;
@@ -2085,6 +2252,7 @@ async function listCodexSessionCatalog(params) {
2085
2252
  query,
2086
2253
  runtime: params.runtime,
2087
2254
  sessionEntries: params.sessionEntries,
2255
+ signal: params.signal,
2088
2256
  excludedThreadIds: managedThreadIds,
2089
2257
  ...ownershipSource && params.bindingStore.managedThreads ? { onExcludedThread: async ({ threadId, rolloutPath }) => {
2090
2258
  if (!managedThreadIds?.has(threadId)) await params.bindingStore.managedThreads?.mark({
@@ -2096,7 +2264,7 @@ async function listCodexSessionCatalog(params) {
2096
2264
  ...source ? { source } : {}
2097
2265
  });
2098
2266
  })());
2099
- for (const host of localHosts) if (params.onHost) host.then(params.onHost).catch(() => void 0);
2267
+ for (const host of localHosts) publishSessionCatalogHost(params, host);
2100
2268
  if (!(!requestedHostIds || query.hostIds?.some((hostId) => hostId.startsWith("node:")))) return { hosts: await Promise.all(localHosts) };
2101
2269
  let nodes;
2102
2270
  try {
@@ -2114,6 +2282,7 @@ async function listCodexSessionCatalog(params) {
2114
2282
  params.onHost?.(registryHost);
2115
2283
  return { hosts: [...await Promise.all(localHosts), registryHost] };
2116
2284
  }
2285
+ params.signal?.throwIfAborted();
2117
2286
  const adoptedNodeSessions = listNodeAdoptedSessionEntries({
2118
2287
  agentId,
2119
2288
  config: params.config,
@@ -2127,6 +2296,8 @@ async function listCodexSessionCatalog(params) {
2127
2296
  query,
2128
2297
  adoptedSessions: adoptedNodeSessions,
2129
2298
  terminalCapabilities: codexNodeTerminalCapability(node),
2299
+ waitUntil: params.waitUntil,
2300
+ signal: params.signal,
2130
2301
  ...params.onHost ? { onHost: params.onHost } : {}
2131
2302
  }));
2132
2303
  return { hosts: await Promise.all([...localHosts, ...nodeHosts]) };
@@ -2142,7 +2313,7 @@ function createCodexSessionCatalogNodeHostCommands(controlFactory, configSources
2142
2313
  config,
2143
2314
  agentId: requestedAgentId
2144
2315
  }).sessionAgentId;
2145
- if (!listAgentIds(config).includes(agentId)) throw new CatalogParamsError(`unknown Codex session catalog agent: ${agentId}`);
2316
+ if (!listAgentIds$1(config).includes(agentId)) throw new CatalogParamsError(`unknown Codex session catalog agent: ${agentId}`);
2146
2317
  const request = { ...parsed };
2147
2318
  delete request.agentId;
2148
2319
  const source = controlFactory.homesForAgent(agentId)[0];
@@ -2154,7 +2325,7 @@ function createCodexSessionCatalogNodeHostCommands(controlFactory, configSources
2154
2325
  paramsJSON: JSON.stringify(request)
2155
2326
  };
2156
2327
  };
2157
- return [
2328
+ const commands = [
2158
2329
  {
2159
2330
  command: CODEX_APP_SERVER_THREADS_LIST_COMMAND,
2160
2331
  cap: CODEX_APP_SERVER_THREADS_CAPABILITY,
@@ -2210,9 +2381,25 @@ function createCodexSessionCatalogNodeHostCommands(controlFactory, configSources
2210
2381
  }
2211
2382
  }
2212
2383
  },
2384
+ {
2385
+ command: CODEX_CATALOG_TRANSCRIPT_READ_COMMAND,
2386
+ cap: CODEX_APP_SERVER_THREADS_CAPABILITY,
2387
+ dangerous: false,
2388
+ handle: async (paramsJSON) => {
2389
+ const request = bindRequest(paramsJSON);
2390
+ const action = readNodeTranscriptParams(request.params);
2391
+ try {
2392
+ return JSON.stringify(await readCodexCatalogTranscriptPage(request.control, action));
2393
+ } catch (error) {
2394
+ if (error instanceof CatalogParamsError) throw error;
2395
+ throw new Error("Codex app-server transcript is unavailable", { cause: error });
2396
+ }
2397
+ }
2398
+ },
2213
2399
  createCodexTerminalNodeHostCommand(bindRequest, configSources),
2214
2400
  createCodexTerminalStartNodeHostCommand()
2215
2401
  ];
2402
+ return process.env.OPENCLAW_NODE_EXEC_HOST?.trim().toLowerCase() === "app" ? commands.filter(({ command }) => command !== CODEX_CATALOG_TRANSCRIPT_READ_COMMAND) : commands;
2216
2403
  }
2217
2404
  function readNodeTranscriptParams(value) {
2218
2405
  if (!isRecord(value)) throw new CatalogParamsError("Codex session read parameters must be an object");
@@ -2235,94 +2422,58 @@ function readBoundedLimit(value, key, fallback, max) {
2235
2422
  if (!Number.isInteger(value) || value < 1 || value > max) throw new CatalogParamsError(`${key} must be an integer from 1 to ${max}`);
2236
2423
  return value;
2237
2424
  }
2238
- function flattenTranscriptPageDesc(page) {
2239
- return page.data.flatMap((turn) => turn.items.toReversed());
2240
- }
2241
2425
  /** Reads the persisted transcript for a Gateway-local or paired-node Codex session. */
2242
2426
  async function readCodexSessionTranscript(params) {
2427
+ const cursor = readControlCursor(params.cursor, "transcript request");
2428
+ const limit = readBoundedLimit(params.limit, "limit", 20, 50);
2243
2429
  if (params.source || params.hostId === "gateway:local") {
2244
- await params.control.requireEligibleThread(params.threadId);
2245
- const listParams = {
2430
+ const page = await readCodexCatalogTranscriptPage(params.control, {
2246
2431
  threadId: params.threadId,
2247
- limit: params.limit,
2248
- sortDirection: "desc",
2249
- itemsView: "full",
2250
- ...params.cursor ? { cursor: params.cursor } : {}
2251
- };
2252
- const page = parseTranscriptPage(await params.control.listTurnPage(listParams));
2432
+ limit,
2433
+ cursor
2434
+ });
2253
2435
  return {
2254
2436
  hostId: params.hostId,
2255
2437
  label: params.source?.label ?? "Local Codex",
2256
2438
  threadId: params.threadId,
2257
- items: flattenTranscriptPageDesc(page),
2258
- ...page.nextCursor ? { nextCursor: page.nextCursor } : {},
2259
- ...page.backwardsCursor ? { backwardsCursor: page.backwardsCursor } : {}
2439
+ ...page
2260
2440
  };
2261
2441
  }
2262
2442
  const nodeId = params.hostId.slice(5);
2263
2443
  const node = (await params.runtime.nodes.list()).nodes.find((candidate) => candidate.nodeId === nodeId && candidate.connected === true && candidate.commands?.includes("codex.appServer.thread.turns.list.v1"));
2264
2444
  if (!node) throw new CatalogParamsError("paired-node Codex session host is offline or unavailable");
2265
- const page = parseTranscriptPage(unwrapNodeInvokePayload(await params.runtime.nodes.invoke({
2445
+ const invoke = async (command, request) => unwrapNodeInvokePayload(await params.runtime.nodes.invoke({
2266
2446
  nodeId,
2267
- command: CODEX_APP_SERVER_THREAD_TURNS_LIST_COMMAND,
2447
+ command,
2268
2448
  params: {
2269
2449
  agentId: params.agentId,
2270
2450
  threadId: params.threadId,
2271
- limit: params.limit,
2272
- ...params.cursor ? { cursor: params.cursor } : {}
2451
+ ...request
2273
2452
  },
2274
2453
  timeoutMs: NODE_INVOKE_TIMEOUT_MS,
2275
2454
  scopes: ["operator.write"]
2276
- })));
2455
+ }));
2456
+ const page = node.commands?.includes("codex.sessionCatalog.transcript.read.v1") ? parseCodexCatalogTranscriptPage(await invoke(CODEX_CATALOG_TRANSCRIPT_READ_COMMAND, {
2457
+ cursor,
2458
+ limit
2459
+ })) : await readLegacyCodexTranscriptPage(async ({ cursor: turnCursor, limit: turnLimit }) => parseTranscriptPage(await invoke(CODEX_APP_SERVER_THREAD_TURNS_LIST_COMMAND, {
2460
+ cursor: turnCursor,
2461
+ limit: turnLimit
2462
+ })), {
2463
+ threadId: params.threadId,
2464
+ cursor,
2465
+ limit
2466
+ });
2277
2467
  return {
2278
2468
  hostId: params.hostId,
2279
2469
  label: nodeLabel(node),
2280
2470
  threadId: params.threadId,
2281
- items: flattenTranscriptPageDesc(page),
2282
- ...page.nextCursor ? { nextCursor: page.nextCursor } : {},
2283
- ...page.backwardsCursor ? { backwardsCursor: page.backwardsCursor } : {}
2284
- };
2285
- }
2286
- //#endregion
2287
- //#region extensions/codex/src/session-catalog-transcript-item.ts
2288
- const CODEX_MESSAGE_TYPES = /* @__PURE__ */ new Map([
2289
- ["userMessage", "userMessage"],
2290
- ["agentMessage", "agentMessage"],
2291
- ["reasoning", "reasoning"]
2292
- ]);
2293
- const CODEX_TOOL_TYPES = /* @__PURE__ */ new Set([
2294
- "commandExecution",
2295
- "fileChange",
2296
- "mcpToolCall",
2297
- "dynamicToolCall",
2298
- "collabAgentToolCall",
2299
- "webSearch",
2300
- "imageView",
2301
- "imageGeneration"
2302
- ]);
2303
- function toGenericTranscriptItem(item) {
2304
- let type = CODEX_MESSAGE_TYPES.get(item.type);
2305
- if (!type && CODEX_TOOL_TYPES.has(item.type)) type = item.result !== void 0 || Boolean(item.aggregatedOutput) ? "toolResult" : "toolCall";
2306
- type ??= "other";
2307
- const fallback = item.title ?? item.name ?? item.tool ?? item.command ?? item.query ?? void 0;
2308
- const resultText = item.aggregatedOutput || (item.result === void 0 ? void 0 : JSON.stringify(item.result, null, 2));
2309
- const changesText = Array.isArray(item.changes) ? item.changes.map((change) => `${change.kind}: ${change.path}`).join("\n") || void 0 : void 0;
2310
- const text = item.type === "userMessage" ? projectCodexUserItemText(item) : item.text || resultText || changesText || fallback;
2311
- return {
2312
- id: item.id,
2313
- type,
2314
- ...text ? { text } : {},
2315
- raw: item
2471
+ ...page
2316
2472
  };
2317
2473
  }
2318
2474
  //#endregion
2319
2475
  //#region extensions/codex/src/session-upstream-activity.ts
2320
2476
  const CODEX_UPSTREAM_TURN_LIMIT = 100;
2321
- const CODEX_APP_SERVER_INVALID_REQUEST_CODE = -32600;
2322
- const CODEX_THREAD_NOT_LOADED_MESSAGE_PREFIX = "thread not loaded:";
2323
- function isCodexThreadGoneError(error) {
2324
- return error instanceof CodexAppServerRpcError && error.code === CODEX_APP_SERVER_INVALID_REQUEST_CODE && error.message.startsWith(CODEX_THREAD_NOT_LOADED_MESSAGE_PREFIX);
2325
- }
2326
2477
  function readMarker(probe) {
2327
2478
  if (!isRecord(probe.marker)) return;
2328
2479
  const turnId = probe.marker.turnId;
@@ -2385,14 +2536,14 @@ function normalizeUserMessageTexts(item) {
2385
2536
  const contentTexts = typed.content?.filter((input) => input.type === "text").map((input) => input.text.trim().replace(/\s+/g, " ")).filter(Boolean);
2386
2537
  return contentTexts?.length ? contentTexts : [(typed.text ?? "").trim().replace(/\s+/g, " ")];
2387
2538
  }
2388
- async function checkCodexUpstreamActivity(probes, control, resolveThreadId = async (probe) => probe.threadId) {
2539
+ async function checkCodexUpstreamActivity(probes, control, resolveThreadId = (probe) => probe.threadId) {
2389
2540
  return await control.withPinnedConnection(async (pinned) => {
2390
2541
  const activities = [];
2391
2542
  for (const probe of probes) {
2392
2543
  const fingerprint = upstreamConnectionFingerprint(probe);
2393
2544
  if (probe.upstreamKind !== "codex-app-server" || !fingerprint || fingerprint !== pinned.connectionFingerprint) continue;
2394
2545
  try {
2395
- const threadId = await resolveThreadId(probe);
2546
+ const threadId = resolveThreadId(probe);
2396
2547
  const page = await pinned.listTurnPage({
2397
2548
  threadId,
2398
2549
  limit: CODEX_UPSTREAM_TURN_LIMIT,
@@ -2404,7 +2555,7 @@ async function checkCodexUpstreamActivity(probes, control, resolveThreadId = asy
2404
2555
  try {
2405
2556
  await pinned.readThread(threadId, false);
2406
2557
  } catch (error) {
2407
- if (isCodexThreadGoneError(error)) activities.push({
2558
+ if (isCodexThreadReadMissingError(error, threadId)) activities.push({
2408
2559
  kind: "missing",
2409
2560
  sessionKey: probe.sessionKey
2410
2561
  });
@@ -2422,7 +2573,7 @@ async function checkCodexUpstreamActivity(probes, control, resolveThreadId = asy
2422
2573
  });
2423
2574
  }
2424
2575
  function createChecker(params) {
2425
- const resolveThreadId = async (probe) => {
2576
+ const resolveThreadId = (probe) => {
2426
2577
  const config = params.getRuntimeConfig();
2427
2578
  const sessionId = params.api.runtime.agent.session.getSessionEntry({
2428
2579
  agentId: probe.agentId,
@@ -2430,7 +2581,7 @@ function createChecker(params) {
2430
2581
  readConsistency: "latest"
2431
2582
  })?.sessionId?.trim();
2432
2583
  if (!sessionId) return probe.threadId;
2433
- const binding = await params.bindingStore.read(sessionBindingIdentity({
2584
+ const binding = params.bindingStore.read(sessionBindingIdentity({
2434
2585
  sessionId,
2435
2586
  sessionKey: probe.sessionKey,
2436
2587
  config
@@ -2472,7 +2623,7 @@ function existingCatalogHomeCandidates(value, label) {
2472
2623
  /** Resolves every local Codex store the operator already owns, without path disclosure. */
2473
2624
  function resolveCodexCatalogHomes(params) {
2474
2625
  const { config, env, ownerAgentId, pluginConfig } = params;
2475
- const ownerAgentDir = resolveAgentDir$1(config, ownerAgentId, env);
2626
+ const ownerAgentDir = resolveAgentDir$2(config, ownerAgentId, env);
2476
2627
  const configuredHomes = readCodexPluginConfig(pluginConfig).sessionCatalog?.homes ?? [];
2477
2628
  const base = resolveCodexSupervisionAppServerRuntimeOptions({
2478
2629
  pluginConfig,
@@ -2494,8 +2645,8 @@ function resolveCodexCatalogHomes(params) {
2494
2645
  label: "Local Codex · user",
2495
2646
  usesProcessHomeFallback: !processHomeConfigured
2496
2647
  });
2497
- const agentIds = listAgentIds(config).toSorted((left, right) => left === ownerAgentId ? -1 : right === ownerAgentId ? 1 : left.localeCompare(right));
2498
- candidates.push(...agentIds.flatMap((agentId) => existingCatalogHomeCandidates(resolveCodexAppServerHomeDir(resolveAgentDir$1(config, agentId, env)), agentId)), ...configuredHomes.flatMap((entry) => {
2648
+ const agentIds = listAgentIds$1(config).toSorted((left, right) => left === ownerAgentId ? -1 : right === ownerAgentId ? 1 : left.localeCompare(right));
2649
+ candidates.push(...agentIds.flatMap((agentId) => existingCatalogHomeCandidates(resolveCodexAppServerHomeDir(resolveAgentDir$2(config, agentId, env)), agentId)), ...configuredHomes.flatMap((entry) => {
2499
2650
  const { path: home, label } = typeof entry === "string" ? { path: entry } : entry;
2500
2651
  return existingCatalogHomeCandidates(home, label);
2501
2652
  }));
@@ -2536,7 +2687,7 @@ function createCodexCatalogHomeResolver(params) {
2536
2687
  const homesByConfig = /* @__PURE__ */ new WeakMap();
2537
2688
  const buildSnapshot = (config) => {
2538
2689
  const pluginConfig = params.getPluginConfig();
2539
- const homesByAgent = new Map(listAgentIds(config).map((agentId) => [agentId, resolveCodexCatalogHomes({
2690
+ const homesByAgent = new Map(listAgentIds$1(config).map((agentId) => [agentId, resolveCodexCatalogHomes({
2540
2691
  config,
2541
2692
  pluginConfig,
2542
2693
  ownerAgentId: agentId,
@@ -2579,6 +2730,7 @@ function createCodexCatalogRequestSnapshot(requestTimeoutMs, request) {
2579
2730
  requestTimeoutMs,
2580
2731
  listThreads: (params, timeoutMs) => request(CODEX_CONTROL_METHODS.listThreads, params, timeoutMs),
2581
2732
  listThreadTurns: (params) => request(CODEX_CONTROL_METHODS.listThreadTurns, params),
2733
+ listThreadItems: (params) => request(CODEX_CONTROL_METHODS.listThreadItems, params),
2582
2734
  forkThread: (params, assertCurrent) => request(CODEX_CONTROL_METHODS.forkThread, assertCodexThreadForkParams(params), void 0, assertCurrent),
2583
2735
  readThread: async (threadId, includeTurns, timeoutMs) => (await request(CODEX_CONTROL_METHODS.readThread, {
2584
2736
  threadId,
@@ -2709,6 +2861,7 @@ function createCodexSessionCatalogControlFromRequests(params) {
2709
2861
  async listTurnPage(listParams) {
2710
2862
  return await params.createRequestSnapshot().listThreadTurns(listParams);
2711
2863
  },
2864
+ listItemPage: (listParams) => params.createRequestSnapshot().listThreadItems(listParams),
2712
2865
  async forkThread(forkParams, assertCurrent) {
2713
2866
  return await params.createRequestSnapshot().forkThread(forkParams, assertCurrent);
2714
2867
  },
@@ -2731,7 +2884,7 @@ function createCodexSessionCatalogControl(params) {
2731
2884
  const catalogPagesByConfig = /* @__PURE__ */ new WeakMap();
2732
2885
  const resolveRequestOptions = (startOptions, agentId, source) => {
2733
2886
  const runtimeConfig = params.getRuntimeConfig();
2734
- const agentDir = source?.agentDir ?? resolveAgentDir$1(runtimeConfig ?? {}, agentId);
2887
+ const agentDir = source?.agentDir ?? resolveAgentDir$2(runtimeConfig ?? {}, agentId);
2735
2888
  const resolvedStartOptions = source?.appServer.start ?? startOptions;
2736
2889
  if (!runtimeConfig) return {
2737
2890
  agentDir,
@@ -2891,6 +3044,7 @@ function createCodexSessionCatalogNodeInvokePolicies() {
2891
3044
  commands: [
2892
3045
  CODEX_APP_SERVER_THREADS_LIST_COMMAND,
2893
3046
  CODEX_APP_SERVER_THREAD_TURNS_LIST_COMMAND,
3047
+ CODEX_CATALOG_TRANSCRIPT_READ_COMMAND,
2894
3048
  CODEX_TERMINAL_RESUME_COMMAND,
2895
3049
  CODEX_TERMINAL_START_COMMAND
2896
3050
  ],
@@ -2993,7 +3147,7 @@ function registerCodexSessionCatalog(params) {
2993
3147
  resolveCreateSession: ({ agentId }) => resolveCodexCatalogCreateSession(params.getRuntimeConfig() ?? params.api.config, agentId),
2994
3148
  list: async (query) => {
2995
3149
  const localTerminalAvailable = resolveLocalCodexTerminalExecutable() !== void 0;
2996
- const { agentId: requestedAgentId, allowProcessHomeFallback, listNodes, onHost, sessionEntries, ...gatewayQuery } = query;
3150
+ const { agentId: requestedAgentId, allowProcessHomeFallback, listNodes, onHost, waitUntil, signal, sessionEntries, ...gatewayQuery } = query;
2997
3151
  const agentId = resolveRequestAgentId(requestedAgentId);
2998
3152
  const localHomes = [...catalogHomes(agentId, allowProcessHomeFallback)];
2999
3153
  const mapHost = (host) => ({
@@ -3008,6 +3162,8 @@ function registerCodexSessionCatalog(params) {
3008
3162
  control: params.control,
3009
3163
  query: gatewayQuery,
3010
3164
  listNodes,
3165
+ waitUntil,
3166
+ signal,
3011
3167
  sessionEntries,
3012
3168
  localHomes,
3013
3169
  ...onHost ? { onHost: (host) => onHost(mapHost(host)) } : {}
@@ -3015,7 +3171,7 @@ function registerCodexSessionCatalog(params) {
3015
3171
  },
3016
3172
  read: async (request) => {
3017
3173
  const { agentId, source, control } = bindRequest(request);
3018
- const page = await readCodexSessionTranscript({
3174
+ return await readCodexSessionTranscript({
3019
3175
  agentId,
3020
3176
  runtime: params.api.runtime,
3021
3177
  control,
@@ -3025,10 +3181,6 @@ function registerCodexSessionCatalog(params) {
3025
3181
  limit: request.limit ?? 20,
3026
3182
  ...source ? { source } : {}
3027
3183
  });
3028
- return {
3029
- ...page,
3030
- items: page.items.map(toGenericTranscriptItem)
3031
- };
3032
3184
  },
3033
3185
  continueSession: async (request) => {
3034
3186
  const config = params.getRuntimeConfig();