@openclaw/codex 2026.7.2-beta.2 → 2026.7.2-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/{app-server-policy-Scc-Wevo.js → app-server-policy-BO3jYBkv.js} +1 -1
  2. package/dist/{attempt-notifications-BFmNhqFl.js → attempt-notifications-DdmnBMUp.js} +1 -1
  3. package/dist/{media-understanding-provider-D31dOJwb.js → bounded-turn-CaQL96kg.js} +43 -183
  4. package/dist/capabilities-CLICvTxf.js +36 -0
  5. package/dist/cli-metadata.js +1 -1
  6. package/dist/{command-formatters-Dq9InZUK.js → command-formatters-DgADqnHa.js} +4 -34
  7. package/dist/{command-handlers-IgqmL_kv.js → command-handlers-l_lVPNlB.js} +72 -13
  8. package/dist/{compact-DCTmg3id.js → compact-CC5KhBzX.js} +5 -4
  9. package/dist/{computer-use-CPcU8TjG.js → computer-use-Ip1-QGa-.js} +4 -4
  10. package/dist/{conversation-control-CGkBlfc5.js → conversation-control-sNPsbTCP.js} +6 -5
  11. package/dist/doctor-contract-api.js +1 -1
  12. package/dist/{dynamic-tools-C_1tEs34.js → dynamic-tools-CQI3UwqY.js} +117 -2543
  13. package/dist/event-projector-assistant-message-DTgnPPVF.js +101 -0
  14. package/dist/event-projector-usage-D6tE7_qD.js +69 -0
  15. package/dist/harness.js +27 -7
  16. package/dist/incognito-session-ET_ufDH-.js +2 -0
  17. package/dist/index.js +60 -26
  18. package/dist/media-understanding-provider.js +168 -1
  19. package/dist/{models-uh26C8QU.js → models-BNeMlHgg.js} +2 -2
  20. package/dist/{notification-correlation-KmfV4EkP.js → notification-correlation-BGLixv5_.js} +3 -3
  21. package/dist/{plugin-app-cache-key-Ceb-lm2c.js → plugin-app-cache-key-CvzvmBRz.js} +2 -2
  22. package/dist/{rate-limits-DyXaYAxU.js → rate-limits-D0IJT-a6.js} +3 -1
  23. package/dist/{request-B_oQsCXy.js → request-BTccUTD3.js} +1 -1
  24. package/dist/{run-attempt-MLzoMe_m.js → run-attempt--858NXDl.js} +2798 -172
  25. package/dist/{session-binding-h1mmCGnl.js → session-binding-ZSMX1omP.js} +9 -2
  26. package/dist/{session-catalog-CEvoXWHA.js → session-catalog-DsKaezgR.js} +119 -96
  27. package/dist/{session-cli-XsEuWb_C.js → session-cli-CYJTfRLG.js} +2 -2
  28. package/dist/session-upstream-marker-D7XlI9us.js +82 -0
  29. package/dist/settled-turn-finalizer-DHltNgtF.js +303 -0
  30. package/dist/{shared-client-JiAnW6pc.js → shared-client-wmgNFNYp.js} +82 -13
  31. package/dist/{side-question-DqDvIwSU.js → side-question-BfFZCsJ-.js} +21 -15
  32. package/dist/{thread-lifecycle-CN_pPtPh.js → thread-lifecycle-cqrOlJkq.js} +157 -32
  33. package/dist/{transcript-mirror-D9rTxx2P.js → transcript-mirror-2p7kl6e4.js} +433 -145
  34. package/dist/upstream-session-fork-vPjwkT1i.js +320 -0
  35. package/dist/{usage-D5Rohxoc.js → usage-DM_I3mPT.js} +3 -3
  36. package/dist/{web-search-provider.runtime-CKVBn3fP.js → web-search-provider.runtime-Bx6HAc_k.js} +3 -3
  37. package/npm-shrinkwrap.json +38 -38
  38. package/openclaw.plugin.json +11 -1
  39. package/package.json +7 -7
@@ -13,7 +13,7 @@ import { normalizeTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-ru
13
13
  import { detectWindowsSpawnCommandInlineArgs } from "openclaw/plugin-sdk/windows-spawn";
14
14
  import { parse } from "smol-toml";
15
15
  import { z } from "zod";
16
- import { embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
16
+ import { AgentHarnessSessionSupersededError, embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
17
17
  import { AsyncLocalStorage } from "node:async_hooks";
18
18
  import { getSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
19
19
  //#region extensions/codex/src/app-server/session-discovery-config.ts
@@ -171,6 +171,7 @@ const codexPluginConfigSchema = z.object({
171
171
  loopDetectionPreToolUseRelay: z.boolean().optional(),
172
172
  requestTimeoutMs: z.number().positive().optional(),
173
173
  turnCompletionIdleTimeoutMs: z.number().positive().optional(),
174
+ turnAssistantCompletionIdleTimeoutMs: z.number().positive().optional(),
174
175
  postToolRawAssistantCompletionIdleTimeoutMs: z.number().positive().optional(),
175
176
  approvalPolicy: codexAppServerApprovalPolicySchema.optional(),
176
177
  sandbox: codexAppServerSandboxSchema.optional(),
@@ -367,6 +368,7 @@ function resolveCodexAppServerRuntimeOptions(params = {}) {
367
368
  loopDetectionPreToolUseRelay: config.loopDetectionPreToolUseRelay !== false,
368
369
  requestTimeoutMs: normalizePositiveNumber(config.requestTimeoutMs, 6e4),
369
370
  turnCompletionIdleTimeoutMs: normalizePositiveNumber(config.turnCompletionIdleTimeoutMs, 6e4),
371
+ turnAssistantCompletionIdleTimeoutMs: normalizePositiveNumber(config.turnAssistantCompletionIdleTimeoutMs, 1e4),
370
372
  ...config.postToolRawAssistantCompletionIdleTimeoutMs !== void 0 ? { postToolRawAssistantCompletionIdleTimeoutMs: normalizePositiveNumber(config.postToolRawAssistantCompletionIdleTimeoutMs, 6e4) } : {},
371
373
  approvalPolicy: forcedPolicy?.approvalPolicy ?? approvalPolicy,
372
374
  approvalPolicySource,
@@ -1323,6 +1325,7 @@ var session_binding_exports = /* @__PURE__ */ __exportAll({
1323
1325
  assertCodexBindingMayBeReplaced: () => assertCodexBindingMayBeReplaced,
1324
1326
  bindingStoreKey: () => bindingStoreKey,
1325
1327
  createCodexAppServerBindingStore: () => createCodexAppServerBindingStore,
1328
+ createCodexSessionGenerationSupersededError: () => createCodexSessionGenerationSupersededError,
1326
1329
  createStoredCodexAppServerBinding: () => createStoredCodexAppServerBinding,
1327
1330
  hashCodexAppServerBindingFingerprint: () => hashCodexAppServerBindingFingerprint,
1328
1331
  isCodexAppServerNativeAuthProfile: () => isCodexAppServerNativeAuthProfile,
@@ -1354,6 +1357,10 @@ function sessionBindingIdentity(params) {
1354
1357
  ...sessionKey ? { sessionKey } : {}
1355
1358
  };
1356
1359
  }
1360
+ /** Builds the terminal coordination error used when a newer OpenClaw session owns the binding. */
1361
+ function createCodexSessionGenerationSupersededError(sessionId) {
1362
+ return new AgentHarnessSessionSupersededError(`Codex session generation is no longer current: ${sessionId}`);
1363
+ }
1357
1364
  const optionalStringSchema = z.string().optional().catch(void 0);
1358
1365
  const optionalBooleanSchema = z.boolean().optional().catch(void 0);
1359
1366
  const optionalNonBlankStringSchema = z.string().refine((value) => Boolean(value.trim())).optional().catch(void 0);
@@ -2089,4 +2096,4 @@ function resolveCodexAppServerBindingModelProvider(params) {
2089
2096
  return params.modelProvider?.trim() || (isCodexAppServerNativeAuthProfile(params) ? PUBLIC_OPENAI_MODEL_PROVIDER : void 0);
2090
2097
  }
2091
2098
  //#endregion
2092
- export { resolveCodexComputerUseConfig as C, resolveOpenClawExecPolicyForCodexAppServer as D, resolveCodexSupervisionAppServerRuntimeOptions as E, shouldAutoApproveCodexAppServerApprovals as O, resolveCodexAppServerUserHomeDir as S, resolveCodexPluginsPolicy as T, isCodexFastServiceTier as _, isCodexAppServerNativeAuthProfile as a, resolveCodexAppServerRuntimeOptions as b, sessionBindingIdentity as c, CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME as d, assertCodexAppServerConnectionSecurity as f, isCodexAppServerApprovalPolicyAllowedByRequirements as g, codexSandboxPolicyForTurn as h, hashCodexAppServerBindingFingerprint as i, withMcpElicitationsApprovalPolicy as k, session_binding_exports as l, codexAppServerStartOptionsKey as m, assertCodexBindingMayBeReplaced as n, normalizeCodexAppServerBindingModelProvider as o, canUseCodexModelBackedApprovalsReviewerForModel as p, bindingStoreKey as r, reclaimCurrentCodexSessionGeneration as s, CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS as t, CODEX_PLUGINS_MARKETPLACE_NAME as u, isCodexSandboxExecServerEnabled as v, resolveCodexModelBackedReviewerPolicyContext as w, resolveCodexAppServerStartOptionsForAgent as x, readCodexPluginConfig as y };
2099
+ export { withMcpElicitationsApprovalPolicy as A, resolveCodexAppServerUserHomeDir as C, resolveCodexSupervisionAppServerRuntimeOptions as D, resolveCodexPluginsPolicy as E, resolveOpenClawExecPolicyForCodexAppServer as O, resolveCodexAppServerStartOptionsForAgent as S, resolveCodexModelBackedReviewerPolicyContext as T, isCodexAppServerApprovalPolicyAllowedByRequirements as _, hashCodexAppServerBindingFingerprint as a, readCodexPluginConfig as b, reclaimCurrentCodexSessionGeneration as c, CODEX_PLUGINS_MARKETPLACE_NAME as d, CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME as f, codexSandboxPolicyForTurn as g, codexAppServerStartOptionsKey as h, createCodexSessionGenerationSupersededError as i, shouldAutoApproveCodexAppServerApprovals as k, sessionBindingIdentity as l, canUseCodexModelBackedApprovalsReviewerForModel as m, assertCodexBindingMayBeReplaced as n, isCodexAppServerNativeAuthProfile as o, assertCodexAppServerConnectionSecurity as p, bindingStoreKey as r, normalizeCodexAppServerBindingModelProvider as s, CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS as t, session_binding_exports as u, isCodexFastServiceTier as v, resolveCodexComputerUseConfig as w, resolveCodexAppServerRuntimeOptions as x, isCodexSandboxExecServerEnabled as y };
@@ -1,11 +1,13 @@
1
- import { J as CODEX_INTERACTIVE_THREAD_SOURCE_KINDS, R as CodexAppServerRpcError, Z as isJsonObject, a as getLeasedSharedCodexAppServerClient, c as releaseLeasedSharedCodexAppServerClient, q as CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES } from "./shared-client-JiAnW6pc.js";
2
- import { E as resolveCodexSupervisionAppServerRuntimeOptions, b as resolveCodexAppServerRuntimeOptions, c as sessionBindingIdentity, s as reclaimCurrentCodexSessionGeneration } from "./session-binding-h1mmCGnl.js";
3
- import { r as importCodexThreadHistoryToTranscript } from "./transcript-mirror-D9rTxx2P.js";
4
- import { n as listCodexAppServerModels } from "./models-uh26C8QU.js";
5
- import { t as buildCodexAppServerConnectionFingerprint } from "./plugin-app-cache-key-Ceb-lm2c.js";
6
- import { d as CODEX_CONTROL_METHODS, f as describeControlFailure, r as formatCodexDisplayText } from "./command-formatters-Dq9InZUK.js";
1
+ import { J as CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES, Q as isJsonObject, R as CodexAppServerRpcError, Y as CODEX_INTERACTIVE_THREAD_SOURCE_KINDS, a as getLeasedSharedCodexAppServerClient, c as releaseLeasedSharedCodexAppServerClient, m as withTimeout, q as resolveCodexAppServerClientInstanceId } from "./shared-client-wmgNFNYp.js";
2
+ import { D as resolveCodexSupervisionAppServerRuntimeOptions, c as reclaimCurrentCodexSessionGeneration, l as sessionBindingIdentity, x as resolveCodexAppServerRuntimeOptions } from "./session-binding-ZSMX1omP.js";
3
+ import { m as assertCodexThreadForkParams, r as importCodexThreadHistoryToTranscript } from "./transcript-mirror-2p7kl6e4.js";
4
+ import { n as listCodexAppServerModels } from "./models-BNeMlHgg.js";
5
+ import { t as buildCodexAppServerConnectionFingerprint } from "./plugin-app-cache-key-CvzvmBRz.js";
6
+ import { n as describeControlFailure, t as CODEX_CONTROL_METHODS } from "./capabilities-CLICvTxf.js";
7
+ import { r as formatCodexDisplayText } from "./command-formatters-DgADqnHa.js";
7
8
  import { n as createCodexCliNodeConversationBindingData } from "./conversation-binding-data-BHRpYbX3.js";
8
- import { n as requestCodexAppServerClientJson, r as requestCodexAppServerJson } from "./request-B_oQsCXy.js";
9
+ import { n as requestCodexAppServerClientJson, r as requestCodexAppServerJson } from "./request-BTccUTD3.js";
10
+ import { i as createImportedCodexSession, n as codexUpstreamBaseline, r as codexUpstreamContinueResult, t as codexLastTerminalTurnId } from "./session-upstream-marker-D7XlI9us.js";
9
11
  import fs from "node:fs/promises";
10
12
  import path from "node:path";
11
13
  import { timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
@@ -13,7 +15,7 @@ import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/temp-path";
13
15
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
14
16
  import { createHash } from "node:crypto";
15
17
  import os from "node:os";
16
- import { listAgentIds, resolveDefaultAgentDir, resolveDefaultAgentId } from "openclaw/plugin-sdk/agent-runtime";
18
+ import { listAgentIds, resolveAllowedModelRef, resolveDefaultAgentDir, resolveDefaultAgentId, resolveDefaultModelForAgent } from "openclaw/plugin-sdk/agent-runtime";
17
19
  import { parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
18
20
  import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
19
21
  import { materializeWindowsSpawnProgram, resolveWindowsSpawnProgram } from "openclaw/plugin-sdk/windows-spawn";
@@ -21,6 +23,7 @@ import { spawn } from "node:child_process";
21
23
  import { resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
22
24
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
23
25
  import process$1 from "node:process";
26
+ import { sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
24
27
  import { decodeNodePtyResumeParams, resolveNodeHostExecutable, runNodePtyCommand } from "openclaw/plugin-sdk/node-host";
25
28
  //#region extensions/codex/src/node-cli-sessions.ts
26
29
  const CODEX_CLI_SESSIONS_LIST_COMMAND = "codex.cli.sessions.list";
@@ -611,6 +614,29 @@ async function safeValue(read) {
611
614
  }
612
615
  }
613
616
  //#endregion
617
+ //#region extensions/codex/src/session-catalog-create.ts
618
+ const CODEX_AGENT_RUNTIME_ID = "codex";
619
+ const CODEX_CATALOG_DEFAULT_MODEL_REF = "openai/gpt-5.6-sol";
620
+ function resolveCodexCatalogCreateSession(config, requestedAgentId) {
621
+ if (!config) return;
622
+ const agentId = requestedAgentId ?? resolveDefaultAgentId(config);
623
+ const defaultModel = resolveDefaultModelForAgent({
624
+ cfg: config,
625
+ agentId
626
+ });
627
+ return "error" in resolveAllowedModelRef({
628
+ cfg: config,
629
+ catalog: [],
630
+ raw: CODEX_CATALOG_DEFAULT_MODEL_REF,
631
+ defaultProvider: defaultModel.provider,
632
+ defaultModel: defaultModel.model,
633
+ agentId
634
+ }) ? void 0 : {
635
+ model: CODEX_CATALOG_DEFAULT_MODEL_REF,
636
+ agentRuntime: CODEX_AGENT_RUNTIME_ID
637
+ };
638
+ }
639
+ //#endregion
614
640
  //#region extensions/codex/src/session-catalog-parsing.ts
615
641
  const DEFAULT_PAGE_LIMIT = 50;
616
642
  const CODEX_APP_SERVER_THREADS_CAPABILITY = "codex-app-server-threads";
@@ -624,6 +650,7 @@ const MAX_CURSOR_COUNT = 100;
624
650
  const MAX_HOST_ID_LENGTH = 256;
625
651
  const MAX_CWD_LENGTH = 4096;
626
652
  const MAX_SESSION_NAME_LENGTH = 500;
653
+ const MAX_SESSION_PREVIEW_LENGTH = 500;
627
654
  const MAX_SESSION_KEY_LENGTH = 1024;
628
655
  const MAX_METADATA_LENGTH = 500;
629
656
  const MAX_ACTIVE_FLAGS = 16;
@@ -641,6 +668,10 @@ function boundedCatalogString(value, maxLength, overflow = "omit") {
641
668
  if (normalized.length <= maxLength) return normalized;
642
669
  return overflow === "truncate" ? truncateUtf16Safe(normalized, maxLength) : void 0;
643
670
  }
671
+ function catalogPreview(value) {
672
+ if (typeof value !== "string") return;
673
+ return boundedCatalogString(sanitizeTerminalText(value.replace(/\s+/g, " ")), MAX_SESSION_PREVIEW_LENGTH, "truncate");
674
+ }
644
675
  function normalizeInteractiveThreadSource(source) {
645
676
  if (CODEX_INTERACTIVE_THREAD_SOURCE_KINDS.some((kind) => kind === source) || CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES.some((kind) => kind === source)) return source;
646
677
  if (isRecord(source) && CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES.some((kind) => kind === source.custom)) return source.custom;
@@ -661,6 +692,7 @@ function toCatalogSession(thread, archived) {
661
692
  const gitInfo = isRecord(record.gitInfo) ? record.gitInfo : void 0;
662
693
  const sessionId = boundedCatalogString(thread.sessionId, 256);
663
694
  const name = boundedCatalogString(thread.name, MAX_SESSION_NAME_LENGTH, "truncate");
695
+ const fallbackName = name ? void 0 : catalogPreview(thread.preview);
664
696
  const cwd = boundedCatalogString(thread.cwd, MAX_CWD_LENGTH);
665
697
  const modelProvider = boundedCatalogString(record.modelProvider, MAX_METADATA_LENGTH, "truncate");
666
698
  const cliVersion = boundedCatalogString(record.cliVersion, MAX_METADATA_LENGTH, "truncate");
@@ -671,6 +703,7 @@ function toCatalogSession(thread, archived) {
671
703
  archived,
672
704
  ...sessionId ? { sessionId } : {},
673
705
  ...thread.name === null ? { name: null } : name ? { name } : {},
706
+ ...fallbackName ? { fallbackName } : {},
674
707
  ...cwd ? { cwd } : {},
675
708
  ...activeFlags?.length ? { activeFlags } : {},
676
709
  ...typeof thread.createdAt === "number" && Number.isFinite(thread.createdAt) ? { createdAt: thread.createdAt } : {},
@@ -789,12 +822,13 @@ function parseCatalogSession(value, options = {}) {
789
822
  }) : void 0;
790
823
  const sessionId = parseOptionalCatalogString(value.sessionId, "session id", 256);
791
824
  const name = value.name === null ? null : parseOptionalCatalogString(value.name, "session name", MAX_SESSION_NAME_LENGTH);
825
+ const fallbackName = parseOptionalCatalogString(value.fallbackName, "session fallback name", MAX_SESSION_PREVIEW_LENGTH);
792
826
  const cwd = parseOptionalCatalogString(value.cwd, "cwd", MAX_CWD_LENGTH);
793
827
  const source = parseOptionalCatalogString(value.source, "source", MAX_METADATA_LENGTH);
794
828
  const modelProvider = parseOptionalCatalogString(value.modelProvider, "model provider", MAX_METADATA_LENGTH);
795
829
  const cliVersion = parseOptionalCatalogString(value.cliVersion, "CLI version", MAX_METADATA_LENGTH);
796
830
  const gitBranch = parseOptionalCatalogString(value.gitBranch, "Git branch", MAX_METADATA_LENGTH);
797
- const openClawSessionKey = options.allowOpenClawSessionKey ? parseOptionalCatalogString(value.openClawSessionKey, "OpenClaw session key", MAX_SESSION_KEY_LENGTH) : void 0;
831
+ const sessionKey = options.allowSessionKey ? parseOptionalCatalogString(value.sessionKey, "OpenClaw session key", MAX_SESSION_KEY_LENGTH) : void 0;
798
832
  const createdAt = readFiniteNumber(value.createdAt);
799
833
  const updatedAt = readFiniteNumber(value.updatedAt);
800
834
  const recencyAt = value.recencyAt === null ? null : readFiniteNumber(value.recencyAt);
@@ -804,6 +838,7 @@ function parseCatalogSession(value, options = {}) {
804
838
  archived: value.archived,
805
839
  ...sessionId !== void 0 ? { sessionId } : {},
806
840
  ...name !== void 0 ? { name } : {},
841
+ ...fallbackName !== void 0 ? { fallbackName } : {},
807
842
  ...cwd !== void 0 ? { cwd } : {},
808
843
  ...activeFlags && activeFlags.length > 0 ? { activeFlags } : {},
809
844
  ...createdAt !== void 0 ? { createdAt } : {},
@@ -813,7 +848,7 @@ function parseCatalogSession(value, options = {}) {
813
848
  ...modelProvider !== void 0 ? { modelProvider } : {},
814
849
  ...cliVersion !== void 0 ? { cliVersion } : {},
815
850
  ...gitBranch !== void 0 ? { gitBranch } : {},
816
- ...openClawSessionKey !== void 0 ? { openClawSessionKey } : {}
851
+ ...sessionKey !== void 0 ? { sessionKey } : {}
817
852
  };
818
853
  }
819
854
  function parseCatalogPage(value, options = {}) {
@@ -930,7 +965,10 @@ function readNodeSessionMarker(entry) {
930
965
  }
931
966
  function listNodeAdoptedSessionEntries(params) {
932
967
  const adopted = /* @__PURE__ */ new Map();
933
- for (const agentId of listSupervisionAgentIds(params.config ?? {})) for (const { entry, sessionKey } of params.runtime.agent.session.listSessionEntries({ agentId })) {
968
+ for (const agentId of listSupervisionAgentIds(params.config ?? {})) for (const { entry, sessionKey } of params.runtime.agent.session.listSessionEntries({
969
+ agentId,
970
+ readOnly: true
971
+ })) {
934
972
  const marker = readNodeSessionMarker(entry);
935
973
  const sessionId = entry.sessionId?.trim();
936
974
  if (!marker || marker.initializing === true && params.includeInitializing !== true || entry.initializationPending === true || entry.agentHarnessId !== "codex" || entry.modelSelectionLocked !== true || !sessionId || adoptionSessionKeyRest(sessionKey) !== nodeAdoptionSessionKey(marker.sourceHostId, marker.sourceThreadId) || marker.sourceHostId !== `node:${marker.nodeId}`) continue;
@@ -1063,6 +1101,7 @@ const CODEX_NODE_CONTINUE_COMMANDS = [
1063
1101
  CODEX_APP_SERVER_THREAD_TURNS_LIST_COMMAND,
1064
1102
  CODEX_CLI_SESSION_RESUME_COMMAND
1065
1103
  ];
1104
+ const NODE_CATALOG_LIST_RESPONSE_TIMEOUT_MS = 8e3;
1066
1105
  function nodeLabel(node) {
1067
1106
  return node.displayName?.trim() || node.remoteIp?.trim() || node.nodeId;
1068
1107
  }
@@ -1085,16 +1124,20 @@ async function listPairedNode(params) {
1085
1124
  nodeId: params.node.nodeId,
1086
1125
  canContinueCodex: canContinueCodexOnNode(params.node)
1087
1126
  };
1088
- if (params.node.connected !== true) return {
1089
- ...common,
1090
- connected: false,
1091
- sessions: [],
1092
- error: {
1093
- code: "NODE_OFFLINE",
1094
- message: "Paired node is offline"
1095
- }
1096
- };
1097
- try {
1127
+ if (params.node.connected !== true) {
1128
+ const host = {
1129
+ ...common,
1130
+ connected: false,
1131
+ sessions: [],
1132
+ error: {
1133
+ code: "NODE_OFFLINE",
1134
+ message: "Paired node is offline"
1135
+ }
1136
+ };
1137
+ params.onHost?.(host);
1138
+ return host;
1139
+ }
1140
+ const eventualHost = Promise.resolve().then(async () => {
1098
1141
  const page = filterCatalogPageByTitle(parseCatalogPage(unwrapNodeInvokePayload(await params.runtime.nodes.invoke({
1099
1142
  nodeId: params.node.nodeId,
1100
1143
  command: CODEX_APP_SERVER_THREADS_LIST_COMMAND,
@@ -1112,9 +1155,18 @@ async function listPairedNode(params) {
1112
1155
  ...page,
1113
1156
  sessions: page.sessions.map((session) => {
1114
1157
  const adopted = params.adoptedSessions.get(adoptedSourceKey(hostId, session.threadId));
1115
- return adopted ? Object.assign({}, session, { openClawSessionKey: adopted.key }) : session;
1158
+ return adopted ? Object.assign({}, session, { sessionKey: adopted.key }) : session;
1116
1159
  })
1117
1160
  };
1161
+ }).catch((error) => ({
1162
+ ...common,
1163
+ connected: true,
1164
+ sessions: [],
1165
+ error: catalogError("NODE_INVOKE_FAILED", error)
1166
+ }));
1167
+ if (params.onHost) eventualHost.then(params.onHost).catch(() => void 0);
1168
+ try {
1169
+ return await withTimeout(eventualHost, NODE_CATALOG_LIST_RESPONSE_TIMEOUT_MS, "paired node Codex session catalog timed out");
1118
1170
  } catch (error) {
1119
1171
  return {
1120
1172
  ...common,
@@ -1560,56 +1612,12 @@ function createChecker(params) {
1560
1612
  });
1561
1613
  }
1562
1614
  //#endregion
1563
- //#region extensions/codex/src/session-upstream-marker.ts
1564
- function lastIdentifiableTurn(thread, normalizeTurnId) {
1565
- for (let index = (thread.turns?.length ?? 0) - 1; index >= 0; index -= 1) {
1566
- const turn = thread.turns?.[index];
1567
- const turnId = normalizeTurnId(turn?.id);
1568
- if (turn && turnId) return {
1569
- ...turn,
1570
- id: turnId
1571
- };
1572
- }
1573
- }
1574
- function codexUpstreamBaseline(thread, normalizeTurnId) {
1575
- const turn = lastIdentifiableTurn(thread, normalizeTurnId);
1576
- return {
1577
- turnId: turn?.id ?? null,
1578
- userMessageCount: turn?.items.filter((item) => item.type === "userMessage").length ?? 0
1579
- };
1580
- }
1581
- function codexLastTerminalTurnId(thread, normalizeTurnId) {
1582
- for (let index = (thread.turns?.length ?? 0) - 1; index >= 0; index -= 1) {
1583
- const turn = thread.turns?.[index];
1584
- const turnId = normalizeTurnId(turn?.id);
1585
- if (!turn || !turnId) continue;
1586
- if (turn.status === "completed" || turn.status === "interrupted" || turn.status === "failed") return turnId;
1587
- }
1588
- }
1589
- /** Build the upstream link seed for a continued Codex session, if a baseline exists. */
1590
- function codexUpstreamContinueResult(sessionKey, threadId, baseline) {
1591
- if (!baseline) return { sessionKey };
1592
- return {
1593
- sessionKey,
1594
- upstream: {
1595
- kind: "codex-app-server",
1596
- ref: {
1597
- connectionFingerprint: baseline.connectionFingerprint,
1598
- threadId
1599
- },
1600
- marker: {
1601
- turnId: baseline.turnId,
1602
- userMessageCount: baseline.userMessageCount
1603
- }
1604
- }
1605
- };
1606
- }
1607
- //#endregion
1608
1615
  //#region extensions/codex/src/session-catalog.ts
1609
1616
  const boundCatalogSessionId = (value) => boundedCatalogString(value, 256);
1610
1617
  const CODEX_SUPERVISION_SESSION_KEY_PREFIX = "harness:codex:supervision:";
1611
1618
  function createCodexSessionCatalogControlFromRequests(params) {
1612
1619
  return {
1620
+ ...params.clientId ? { clientId: params.clientId } : {},
1613
1621
  ...params.connectionFingerprint ? { connectionFingerprint: params.connectionFingerprint } : {},
1614
1622
  withPinnedConnection: params.withPinnedConnection,
1615
1623
  async listPage(pageParams) {
@@ -1632,7 +1640,7 @@ function createCodexSessionCatalogControlFromRequests(params) {
1632
1640
  archived: false,
1633
1641
  limit: remaining,
1634
1642
  modelProviders: [],
1635
- sortKey: "recency_at",
1643
+ sortKey: "updated_at",
1636
1644
  sortDirection: "desc",
1637
1645
  ...cwd ? { cwd } : {},
1638
1646
  ...cursor ? { cursor } : {}
@@ -1664,6 +1672,9 @@ function createCodexSessionCatalogControlFromRequests(params) {
1664
1672
  async listTurnPage(listParams) {
1665
1673
  return await params.createRequestSnapshot().listThreadTurns(listParams);
1666
1674
  },
1675
+ async forkThread(forkParams) {
1676
+ return await params.createRequestSnapshot().forkThread(forkParams);
1677
+ },
1667
1678
  async archiveThread(threadId) {
1668
1679
  await params.createRequestSnapshot().archiveThread(threadId);
1669
1680
  }
@@ -1691,6 +1702,7 @@ function createCodexSessionCatalogControl(params) {
1691
1702
  includeTurns
1692
1703
  }, requestOptions)).thread,
1693
1704
  listThreadTurns: async (listParams) => await codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.listThreadTurns, listParams, requestOptions),
1705
+ forkThread: async (forkParams) => await codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.forkThread, assertCodexThreadForkParams(forkParams), requestOptions),
1694
1706
  archiveThread: async (threadId) => {
1695
1707
  await codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.archiveThread, { threadId }, requestOptions);
1696
1708
  }
@@ -1731,6 +1743,13 @@ function createCodexSessionCatalogControl(params) {
1731
1743
  config: runtimeConfig,
1732
1744
  timeoutMs: runtime.requestTimeoutMs
1733
1745
  }),
1746
+ forkThread: async (forkParams) => await requestCodexAppServerClientJson({
1747
+ client,
1748
+ method: CODEX_CONTROL_METHODS.forkThread,
1749
+ requestParams: assertCodexThreadForkParams(forkParams),
1750
+ config: runtimeConfig,
1751
+ timeoutMs: runtime.requestTimeoutMs
1752
+ }),
1734
1753
  archiveThread: async (threadId) => {
1735
1754
  await requestCodexAppServerClientJson({
1736
1755
  client,
@@ -1742,6 +1761,7 @@ function createCodexSessionCatalogControl(params) {
1742
1761
  }
1743
1762
  };
1744
1763
  const pinnedControl = createCodexSessionCatalogControlFromRequests({
1764
+ clientId: resolveCodexAppServerClientInstanceId(client),
1745
1765
  connectionFingerprint: buildCodexAppServerConnectionFingerprint(runtime, resolveDefaultAgentDir(runtimeConfig ?? {})),
1746
1766
  createRequestSnapshot: () => requests,
1747
1767
  now,
@@ -1778,7 +1798,7 @@ async function listGatewayHost(params) {
1778
1798
  ...page,
1779
1799
  sessions: page.sessions.map((session) => {
1780
1800
  const adopted = adoptedSessions.get(session.threadId);
1781
- return adopted ? Object.assign({}, session, { openClawSessionKey: adopted.key }) : session;
1801
+ return adopted ? Object.assign({}, session, { sessionKey: adopted.key }) : session;
1782
1802
  })
1783
1803
  };
1784
1804
  } catch (error) {
@@ -1803,19 +1823,22 @@ async function listCodexSessionCatalog(params) {
1803
1823
  query,
1804
1824
  runtime: params.runtime
1805
1825
  })] : [];
1826
+ for (const host of localHosts) if (params.onHost) host.then(params.onHost).catch(() => void 0);
1806
1827
  if (!(!requestedHostIds || query.hostIds?.some((hostId) => hostId.startsWith("node:")))) return { hosts: await Promise.all(localHosts) };
1807
1828
  let nodes;
1808
1829
  try {
1809
1830
  nodes = (await params.runtime.nodes.list()).nodes.filter((node) => node.commands?.includes("codex.appServer.threads.list.v1") && (!requestedHostIds || requestedHostIds.has(`node:${node.nodeId}`))).slice(0, 100 - localHosts.length);
1810
1831
  } catch (error) {
1811
- return { hosts: [...await Promise.all(localHosts), {
1832
+ const registryHost = {
1812
1833
  hostId: "node:registry",
1813
1834
  label: "Paired nodes",
1814
1835
  kind: "node",
1815
1836
  connected: false,
1816
1837
  sessions: [],
1817
1838
  error: catalogError("NODE_LIST_FAILED", error)
1818
- }] };
1839
+ };
1840
+ params.onHost?.(registryHost);
1841
+ return { hosts: [...await Promise.all(localHosts), registryHost] };
1819
1842
  }
1820
1843
  const adoptedNodeSessions = listNodeAdoptedSessionEntries({
1821
1844
  config: params.config,
@@ -1826,7 +1849,8 @@ async function listCodexSessionCatalog(params) {
1826
1849
  runtime: params.runtime,
1827
1850
  node,
1828
1851
  query,
1829
- adoptedSessions: adoptedNodeSessions
1852
+ adoptedSessions: adoptedNodeSessions,
1853
+ ...params.onHost ? { onHost: params.onHost } : {}
1830
1854
  });
1831
1855
  return Object.assign(host, codexNodeTerminalCapability(node));
1832
1856
  });
@@ -1955,7 +1979,10 @@ function isAdoptionSessionKeyForThread(sessionKey, threadId) {
1955
1979
  }
1956
1980
  async function listAdoptedSessionEntries(params) {
1957
1981
  const adopted = /* @__PURE__ */ new Map();
1958
- for (const agentId of listSupervisionAgentIds(params.config ?? {})) for (const { entry, sessionKey } of params.runtime.agent.session.listSessionEntries({ agentId })) {
1982
+ for (const agentId of listSupervisionAgentIds(params.config ?? {})) for (const { entry, sessionKey } of params.runtime.agent.session.listSessionEntries({
1983
+ agentId,
1984
+ readOnly: true
1985
+ })) {
1959
1986
  const sessionKeyRest = adoptionSessionKeyRest(sessionKey);
1960
1987
  if (!sessionKeyRest.startsWith(CODEX_SUPERVISION_SESSION_KEY_PREFIX) || entry.initializationPending === true || entry.agentHarnessId !== "codex" || entry.modelSelectionLocked !== true) continue;
1961
1988
  const sessionId = entry.sessionId?.trim();
@@ -2069,17 +2096,17 @@ async function createOrReuseAdoptedSession(params) {
2069
2096
  let createdBindingIdentity;
2070
2097
  let createdPendingBinding;
2071
2098
  try {
2072
- const label = params.sourceThread.name?.trim() || void 0;
2073
2099
  const spawnedCwd = params.sourceThread.cwd?.trim() || void 0;
2074
2100
  const pendingLastTurnId = codexLastTerminalTurnId(params.sourceThread, boundCatalogSessionId);
2075
2101
  const marker = { sourceThreadId: params.sourceThread.id };
2076
- const created = await params.api.runtime.agent.session.createSessionEntry({
2077
- cfg: params.config,
2102
+ const created = await createImportedCodexSession({
2103
+ runtime: params.api.runtime,
2104
+ config: params.config,
2078
2105
  key: adoptionSessionKey(params.sourceThread.id),
2079
2106
  agentId: resolveDefaultAgentId(params.config),
2107
+ thread: params.sourceThread,
2108
+ throughTurnId: pendingLastTurnId ?? null,
2080
2109
  recoverMatchingInitialEntry: true,
2081
- ...label ? { label } : {},
2082
- ...spawnedCwd ? { spawnedCwd } : {},
2083
2110
  initialEntry: {
2084
2111
  agentHarnessId: "codex",
2085
2112
  modelSelectionLocked: true,
@@ -2089,24 +2116,12 @@ async function createOrReuseAdoptedSession(params) {
2089
2116
  modelLocked: true
2090
2117
  } } }
2091
2118
  },
2092
- afterCreate: async (entry) => {
2119
+ afterImport: async (entry) => {
2093
2120
  createdBindingIdentity = sessionBindingIdentity({
2094
2121
  sessionId: entry.sessionId,
2095
2122
  sessionKey: entry.key,
2096
2123
  config: params.config
2097
2124
  });
2098
- const storePath = resolveStorePath(params.config.session?.store, { agentId: entry.agentId });
2099
- await importCodexThreadHistoryToTranscript({
2100
- thread: params.sourceThread,
2101
- throughTurnId: pendingLastTurnId ?? null,
2102
- storePath,
2103
- sessionId: entry.sessionId,
2104
- sessionKey: entry.key,
2105
- agentId: entry.agentId,
2106
- ...spawnedCwd ? { cwd: spawnedCwd } : {},
2107
- modelProvider: params.sourceThread.modelProvider,
2108
- config: params.config
2109
- });
2110
2125
  createdPendingBinding = {
2111
2126
  sourceThreadId: params.sourceThread.id,
2112
2127
  connectionFingerprint: params.connectionFingerprint,
@@ -2233,7 +2248,10 @@ async function continueLocalCodexSession(params) {
2233
2248
  }
2234
2249
  }
2235
2250
  async function assertNoPendingSupervisionBranch(params) {
2236
- const adoptedEntries = listSupervisionAgentIds(params.config).flatMap((agentId) => params.runtime.agent.session.listSessionEntries({ agentId })).filter((candidate) => isAdoptionSessionKeyForThread(candidate.sessionKey, params.threadId));
2251
+ const adoptedEntries = listSupervisionAgentIds(params.config).flatMap((agentId) => params.runtime.agent.session.listSessionEntries({
2252
+ agentId,
2253
+ readOnly: true
2254
+ })).filter((candidate) => isAdoptionSessionKeyForThread(candidate.sessionKey, params.threadId));
2237
2255
  for (const adopted of adoptedEntries) {
2238
2256
  if (adopted.entry.initializationPending === true) throw new CatalogParamsError("Codex session cannot be archived while its OpenClaw branch is initializing");
2239
2257
  const sessionId = adopted.entry.sessionId?.trim();
@@ -2302,9 +2320,10 @@ function toGenericCatalogHost(host, localTerminalAvailable) {
2302
2320
  const canContinue = (local || host.canContinueCodex === true) && continuableStatus && isInteractiveThreadSource(session.source);
2303
2321
  const canArchive = local && continuableStatus && isInteractiveThreadSource(session.source);
2304
2322
  const canOpenTerminal = isInteractiveThreadSource(session.source) && (local ? localTerminalAvailable : host.canOpenTerminalCodex === true);
2323
+ const name = session.name ?? session.fallbackName;
2305
2324
  return {
2306
2325
  threadId: session.threadId,
2307
- ...session.name != null ? { name: session.name } : {},
2326
+ ...name ? { name } : {},
2308
2327
  ...session.cwd ? { cwd: session.cwd } : {},
2309
2328
  status: session.status,
2310
2329
  ...session.createdAt != null ? { createdAt: session.createdAt } : {},
@@ -2315,7 +2334,7 @@ function toGenericCatalogHost(host, localTerminalAvailable) {
2315
2334
  ...session.cliVersion ? { cliVersion: session.cliVersion } : {},
2316
2335
  ...session.gitBranch ? { gitBranch: session.gitBranch } : {},
2317
2336
  archived: session.archived,
2318
- ...session.openClawSessionKey ? { openClawSessionKey: session.openClawSessionKey } : {},
2337
+ ...session.sessionKey ? { sessionKey: session.sessionKey } : {},
2319
2338
  canContinue,
2320
2339
  canArchive,
2321
2340
  canOpenTerminal
@@ -2329,15 +2348,19 @@ function registerCodexSessionCatalog(params) {
2329
2348
  const provider = {
2330
2349
  id: "codex",
2331
2350
  label: "Codex",
2351
+ resolveCreateSession: ({ agentId }) => resolveCodexCatalogCreateSession(params.getRuntimeConfig() ?? params.api.config, agentId),
2332
2352
  list: async (query) => {
2333
2353
  const localTerminalAvailable = resolveLocalCodexTerminalExecutable() !== void 0;
2354
+ const { onHost, ...gatewayQuery } = query;
2355
+ const mapHost = (host) => toGenericCatalogHost(host, localTerminalAvailable);
2334
2356
  return (await listCodexSessionCatalog({
2335
2357
  bindingStore: params.bindingStore,
2336
2358
  config: params.getRuntimeConfig(),
2337
2359
  runtime: params.api.runtime,
2338
2360
  control: params.control,
2339
- query
2340
- })).hosts.map((host) => toGenericCatalogHost(host, localTerminalAvailable));
2361
+ query: gatewayQuery,
2362
+ ...onHost ? { onHost: (host) => onHost(mapHost(host)) } : {}
2363
+ })).hosts.map(mapHost);
2341
2364
  },
2342
2365
  read: async (request) => {
2343
2366
  const page = await readCodexSessionTranscript({
@@ -1,8 +1,8 @@
1
- import { a as CODEX_LOCAL_SESSION_HOST_ID } from "./session-catalog-CEvoXWHA.js";
1
+ import { a as CODEX_LOCAL_SESSION_HOST_ID } from "./session-catalog-DsKaezgR.js";
2
2
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
3
3
  import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
4
- import { addGatewayClientOptions, callGatewayFromCli } from "openclaw/plugin-sdk/gateway-runtime";
5
4
  import { sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
5
+ import { addGatewayClientOptions, callGatewayFromCli } from "openclaw/plugin-sdk/gateway-runtime";
6
6
  //#region extensions/codex/src/session-cli.ts
7
7
  const CODEX_SESSION_CATALOG_CLI_TIMEOUT_MS = 75e3;
8
8
  function writeLine(value = "") {
@@ -0,0 +1,82 @@
1
+ import { r as importCodexThreadHistoryToTranscript } from "./transcript-mirror-2p7kl6e4.js";
2
+ import { resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
3
+ //#region extensions/codex/src/app-server/session-history-import.ts
4
+ /** Creates a session whose transcript is derived from one verified Codex thread snapshot. */
5
+ async function createImportedCodexSession(params) {
6
+ const label = params.thread.name?.trim() || void 0;
7
+ const spawnedCwd = params.thread.cwd?.trim() || void 0;
8
+ const createParams = {
9
+ cfg: params.config,
10
+ key: params.key,
11
+ agentId: params.agentId,
12
+ ...label ? { label } : {},
13
+ ...spawnedCwd ? { spawnedCwd } : {},
14
+ initialEntry: params.initialEntry,
15
+ afterCreate: async (entry) => {
16
+ const storePath = resolveStorePath(params.config.session?.store, { agentId: entry.agentId });
17
+ await importCodexThreadHistoryToTranscript({
18
+ thread: params.thread,
19
+ throughTurnId: params.throughTurnId,
20
+ storePath,
21
+ sessionId: entry.sessionId,
22
+ sessionKey: entry.key,
23
+ agentId: entry.agentId,
24
+ ...spawnedCwd ? { cwd: spawnedCwd } : {},
25
+ modelProvider: params.thread.modelProvider,
26
+ config: params.config
27
+ });
28
+ return await params.afterImport(entry);
29
+ }
30
+ };
31
+ return params.recoverMatchingInitialEntry ? await params.runtime.agent.session.createSessionEntry({
32
+ ...createParams,
33
+ recoverMatchingInitialEntry: true
34
+ }) : await params.runtime.agent.session.createSessionEntry(createParams);
35
+ }
36
+ //#endregion
37
+ //#region extensions/codex/src/session-upstream-marker.ts
38
+ function lastIdentifiableTurn(thread, normalizeTurnId) {
39
+ for (let index = (thread.turns?.length ?? 0) - 1; index >= 0; index -= 1) {
40
+ const turn = thread.turns?.[index];
41
+ const turnId = normalizeTurnId(turn?.id);
42
+ if (turn && turnId) return {
43
+ ...turn,
44
+ id: turnId
45
+ };
46
+ }
47
+ }
48
+ function codexUpstreamBaseline(thread, normalizeTurnId) {
49
+ const turn = lastIdentifiableTurn(thread, normalizeTurnId);
50
+ return {
51
+ turnId: turn?.id ?? null,
52
+ userMessageCount: turn?.items.filter((item) => item.type === "userMessage").length ?? 0
53
+ };
54
+ }
55
+ function codexLastTerminalTurnId(thread, normalizeTurnId) {
56
+ for (let index = (thread.turns?.length ?? 0) - 1; index >= 0; index -= 1) {
57
+ const turn = thread.turns?.[index];
58
+ const turnId = normalizeTurnId(turn?.id);
59
+ if (!turn || !turnId) continue;
60
+ if (turn.status === "completed" || turn.status === "interrupted" || turn.status === "failed") return turnId;
61
+ }
62
+ }
63
+ /** Build the upstream link seed for a continued Codex session, if a baseline exists. */
64
+ function codexUpstreamContinueResult(sessionKey, threadId, baseline) {
65
+ if (!baseline) return { sessionKey };
66
+ return {
67
+ sessionKey,
68
+ upstream: {
69
+ kind: "codex-app-server",
70
+ ref: {
71
+ connectionFingerprint: baseline.connectionFingerprint,
72
+ threadId
73
+ },
74
+ marker: {
75
+ turnId: baseline.turnId,
76
+ userMessageCount: baseline.userMessageCount
77
+ }
78
+ }
79
+ };
80
+ }
81
+ //#endregion
82
+ export { createImportedCodexSession as i, codexUpstreamBaseline as n, codexUpstreamContinueResult as r, codexLastTerminalTurnId as t };