@openclaw/codex 2026.8.1 → 2026.8.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 (54) hide show
  1. package/dist/api.js +2 -2
  2. package/dist/{attempt-client-cleanup-CVPvp9dL.js → attempt-client-cleanup-CpVfwctT.js} +1 -1
  3. package/dist/{binding-connection-CCQFs8lf.js → binding-connection-CF7BmrDk.js} +2 -2
  4. package/dist/{bounded-turn-rq5tiSXk.js → bounded-turn-DRC3hcjm.js} +10 -9
  5. package/dist/{capabilities-CGm_94eL.js → capabilities-D6m_TdVy.js} +1 -1
  6. package/dist/cli-metadata.js +1 -1
  7. package/dist/{command-formatters-C54Yg3eA.js → command-formatters--UToCokS.js} +4 -3
  8. package/dist/{command-handlers-BvOAHTrA.js → command-handlers-CLFx2Ypa.js} +41 -33
  9. package/dist/{compact-Hd7SAc0N.js → compact-5xqW1oCh.js} +13 -11
  10. package/dist/{config-Cxw3Cl3k.js → config-CcYL77O6.js} +6 -4
  11. package/dist/{conversation-binding-data-CW2GuupV.js → conversation-binding-data-BiodpIzq.js} +2 -1
  12. package/dist/doctor-contract-api.js +8 -4
  13. package/dist/{dynamic-tools-BFoUcRdx.js → dynamic-tools-BmeXjwNZ.js} +103 -106
  14. package/dist/{effective-mcp-catalog-BTJHnDSx.js → effective-mcp-catalog-XXQKgK1U.js} +2 -2
  15. package/dist/{event-projector-usage-D3PHFFXh.js → event-projector-usage-B2r5vhWH.js} +7 -12
  16. package/dist/{harness-DVfUQBlQ.js → harness-BgeB7LnD.js} +13 -13
  17. package/dist/harness.js +1 -1
  18. package/dist/index.js +56 -37
  19. package/dist/{isolated-completion-Cbbx_5Ed.js → isolated-completion-CxTus3vZ.js} +3 -3
  20. package/dist/media-understanding-provider.js +1 -1
  21. package/dist/{model-catalog-o6Cgjoss.js → model-catalog-DULBcniB.js} +5 -5
  22. package/dist/{models-DgFWSuxA.js → models-DaWfETQk.js} +4 -3
  23. package/dist/{native-subagent-monitor-CwFyoylz.js → native-subagent-monitor-vXYUZH37.js} +24 -104
  24. package/dist/{node-exec-server.runtime-DXrqpw1c.js → node-exec-server.runtime-DirKVZ5h.js} +2 -2
  25. package/dist/{plugin-approval-roundtrip-D80UZiJ_.js → plugin-approval-roundtrip-CCWQGlAI.js} +2 -1
  26. package/dist/{plugin-marketplace-discovery-mdmScYOj.js → plugin-marketplace-discovery-BXjIFEiw.js} +14 -13
  27. package/dist/{plugin-metadata-cache-CulOABwu.js → plugin-metadata-cache-DQQm4gWT.js} +5 -5
  28. package/dist/{rate-limits-hFtzt2Up.js → rate-limits-BqHEHXQJ.js} +3 -2
  29. package/dist/{request-CCm4LaED.js → request-BWxweEdK.js} +2 -2
  30. package/dist/{run-attempt-BwNQDH2u.js → run-attempt-BVLE4Gbi.js} +133 -182
  31. package/dist/{runtime-artifact-DeBvleJw.js → runtime-artifact-D9pYp4zL.js} +3 -3
  32. package/dist/{session-binding-q2WSTVmC.js → session-binding-D0zinCP1.js} +1 -1
  33. package/dist/{session-catalog-C2Tae4rI.js → session-catalog-eMhVm0Ql.js} +232 -204
  34. package/dist/{session-catalog-home-id-DAKUrm3C.js → session-catalog-home-id-Dt2GiG5o.js} +3 -3
  35. package/dist/{session-cli-BuDjm5Ou.js → session-cli-B2lyjJA0.js} +1 -1
  36. package/dist/session-history-C5J1AKzG.js +87 -0
  37. package/dist/{session-permission-policy-gLm40Vtq.js → session-permission-policy-ScnAyG90.js} +1 -1
  38. package/dist/{session-retirement-CdkI0bvb.js → session-retirement-CtUtUTr9.js} +4 -4
  39. package/dist/{session-upstream-marker-Bcy33kam.js → session-upstream-marker-gqrYIRHk.js} +1 -1
  40. package/dist/settled-turn-context-Bk3IUwod.js +290 -0
  41. package/dist/settled-turn-finalizer-BXLN9PfJ.js +104 -0
  42. package/dist/{shared-client-kNkljY-R.js → shared-client-B1tT5U6r.js} +33 -35
  43. package/dist/{side-question-GwD73tX6.js → side-question-CZ-mCw-t.js} +18 -15
  44. package/dist/{thread-lifecycle-Ss-uwnC4.js → thread-lifecycle-CGGKP720.js} +206 -163
  45. package/dist/{thread-ownership-CeYBqg_4.js → thread-ownership-RkaoZCmQ.js} +2 -2
  46. package/dist/{thread-resume-DF54hagX.js → thread-resume-BFt1-ZDa.js} +7 -6
  47. package/dist/{transcript-mirror-CkEQIna-.js → transcript-mirror-1ep4XjzF.js} +14 -7
  48. package/dist/{transport-stdio-C7-s9TLG.js → transport-stdio-NT_Dpd9V.js} +40 -24
  49. package/dist/{upstream-prompt-provenance-CFmsKwr9.js → upstream-prompt-provenance-LphB8slG.js} +8 -4
  50. package/dist/{upstream-session-fork-BACGlOFa.js → upstream-session-fork-Dc8BFExw.js} +13 -19
  51. package/dist/{usage-C2l8Mils.js → usage-DUhd58gI.js} +3 -3
  52. package/dist/{web-search-provider.runtime-B2XgRdFv.js → web-search-provider.runtime-BEmlE7ov.js} +3 -3
  53. package/package.json +5 -5
  54. package/dist/settled-turn-finalizer-B8JJcxCi.js +0 -329
@@ -1,4 +1,4 @@
1
- import { n as resolveCodexAppServerSpawnEnv } from "./transport-stdio-C7-s9TLG.js";
1
+ import { n as resolveCodexAppServerSpawnEnv } from "./transport-stdio-NT_Dpd9V.js";
2
2
  import fs from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { createHash } from "node:crypto";
@@ -9,14 +9,14 @@ import { isPathInside } from "openclaw/plugin-sdk/file-access-runtime";
9
9
  /** Exact local runtime artifact identity for verified Codex setup turns. */
10
10
  const ARTIFACT_ID_PREFIX = "codex-app-server:v1:";
11
11
  const ARTIFACT_HASH_DOMAIN = "openclaw-codex-app-server-runtime-artifact-v1\0";
12
- const MAX_ARTIFACT_ID_BYTES = 32 * 1024;
12
+ const MAX_ARTIFACT_ID_BYTES = 32768;
13
13
  const MAX_ARTIFACT_PATH_BYTES = 4096;
14
14
  const MAX_ARTIFACT_INVOCATION_PATHS = 8;
15
15
  const MAX_ARTIFACT_DEPTH = 64;
16
16
  const MAX_ARTIFACT_ENTRIES = 32768;
17
17
  const MAX_ARTIFACT_FILES = 8192;
18
18
  const MAX_ARTIFACT_TOTAL_BYTES = 1024n * 1024n * 1024n;
19
- const READ_CHUNK_BYTES = 64 * 1024;
19
+ const READ_CHUNK_BYTES = 65536;
20
20
  const CODE_MODE_HOST_PATH_ENV = "CODEX_CODE_MODE_HOST_PATH";
21
21
  const SAFE_NODE_OPTIONS_BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
22
22
  "--enable-network-family-autoselection",
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
- import { A as normalizeCodexServiceTier, N as CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN } from "./config-Cxw3Cl3k.js";
2
+ import { A as normalizeCodexServiceTier, N as CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN } from "./config-CcYL77O6.js";
3
3
  import { n as CODEX_APP_SERVER_BINDING_NAMESPACE, t as CODEX_APP_SERVER_BINDING_MAX_ENTRIES } from "./session-binding-meta-B7aEMU7g.js";
4
4
  import { asOptionalRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  import { AgentHarnessSessionSupersededError, embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
@@ -1,18 +1,18 @@
1
- import { F as resolveCodexAppServerLocalHomeDir, I as resolveCodexAppServerUserHomeDir, P as resolveCodexAppServerHomeDir, T as readCodexPluginConfig, i as resolveCodexAppServerRuntimeOptions, s as resolveCodexSupervisionAppServerRuntimeOptions } from "./config-Cxw3Cl3k.js";
2
- import { $ as CodexAppServerRpcError, Et as withTimeout, Ht as isJsonObject, Lt as resolveCodexAppServerPreparedAuthHandoff, Mt as resolveCodexAppServerAuthProfileId, Pt as resolveCodexAppServerAuthProfileStore, Q as resolveCodexAppServerClientInstanceId, Rt as CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES, c as getLeasedSharedCodexAppServerClient, h as releaseLeasedSharedCodexAppServerClient, zt as CODEX_INTERACTIVE_THREAD_SOURCE_KINDS } from "./shared-client-kNkljY-R.js";
3
- import { c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity } from "./session-binding-q2WSTVmC.js";
1
+ import { F as resolveCodexAppServerLocalHomeDir, I as resolveCodexAppServerUserHomeDir, P as resolveCodexAppServerHomeDir, T as readCodexPluginConfig, i as resolveCodexAppServerRuntimeOptions, s as resolveCodexSupervisionAppServerRuntimeOptions } from "./config-CcYL77O6.js";
2
+ import { $ as CodexAppServerRpcError, Et as withTimeout, Ht as isJsonObject, Lt as resolveCodexAppServerPreparedAuthHandoff, Mt as resolveCodexAppServerAuthProfileId, Pt as resolveCodexAppServerAuthProfileStore, Q as resolveCodexAppServerClientInstanceId, Rt as CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES, c as getLeasedSharedCodexAppServerClient, h as releaseLeasedSharedCodexAppServerClient, zt as CODEX_INTERACTIVE_THREAD_SOURCE_KINDS } from "./shared-client-B1tT5U6r.js";
3
+ import { c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity } from "./session-binding-D0zinCP1.js";
4
4
  import { i as assertCodexThreadForkParams } from "./protocol-validators-Bg5rpNxk.js";
5
- import { a as closeCodexStartupClientBestEffort } from "./attempt-client-cleanup-CVPvp9dL.js";
6
- import { n as listCodexAppServerModels } from "./models-DgFWSuxA.js";
7
- import { a as replaceCodexCatalogConnectionHomes, n as buildCodexAppServerConnectionFingerprint, t as resumeCodexAppServerThread } from "./thread-resume-DF54hagX.js";
8
- import { n as codexCatalogHomeId, r as isOpenClawManagedCodexThread, t as canonicalCodexCatalogHome } from "./session-catalog-home-id-DAKUrm3C.js";
9
- import { i as requestCodexAppServerJson, o as withCodexAppServerJsonClient, r as requestCodexAppServerClientJson } from "./request-CCm4LaED.js";
10
- import { p as projectCodexUserItemText, r as importCodexThreadHistoryToTranscript } from "./transcript-mirror-CkEQIna-.js";
11
- import { n as describeControlFailure, t as CODEX_CONTROL_METHODS } from "./capabilities-CGm_94eL.js";
12
- import { r as formatCodexDisplayText } from "./command-formatters-C54Yg3eA.js";
13
- import { n as createCodexCliNodeConversationBindingData } from "./conversation-binding-data-CW2GuupV.js";
5
+ import { a as closeCodexStartupClientBestEffort } from "./attempt-client-cleanup-CpVfwctT.js";
6
+ import { n as listCodexAppServerModels } from "./models-DaWfETQk.js";
7
+ import { a as replaceCodexCatalogConnectionHomes, n as buildCodexAppServerConnectionFingerprint, t as resumeCodexAppServerThread } from "./thread-resume-BFt1-ZDa.js";
8
+ import { i as readCodexSessionMeta, n as codexCatalogHomeId, r as isOpenClawManagedCodexThread, t as canonicalCodexCatalogHome } from "./session-catalog-home-id-Dt2GiG5o.js";
9
+ import { i as requestCodexAppServerJson, o as withCodexAppServerJsonClient, r as requestCodexAppServerClientJson } from "./request-BWxweEdK.js";
10
+ import { m as projectCodexUserItemText, r as importCodexThreadHistoryToTranscript } from "./transcript-mirror-1ep4XjzF.js";
11
+ import { n as describeControlFailure, t as CODEX_CONTROL_METHODS } from "./capabilities-D6m_TdVy.js";
12
+ import { r as formatCodexDisplayText } from "./command-formatters--UToCokS.js";
13
+ import { n as createCodexCliNodeConversationBindingData } from "./conversation-binding-data-BiodpIzq.js";
14
14
  import { n as prepareCodexAppServerAuthBinding } from "./auth-binding-Ds_QVm-X.js";
15
- import { i as createImportedCodexSession, n as codexUpstreamBaseline, r as codexUpstreamContinueResult, t as codexLastTerminalTurnId } from "./session-upstream-marker-Bcy33kam.js";
15
+ import { i as createImportedCodexSession, n as codexUpstreamBaseline, r as codexUpstreamContinueResult, t as codexLastTerminalTurnId } from "./session-upstream-marker-gqrYIRHk.js";
16
16
  import { asFiniteNumber, isRecord, normalizeBoundedOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
17
17
  import fs from "node:fs/promises";
18
18
  import path from "node:path";
@@ -37,8 +37,8 @@ import { createSessionCatalogAdoptionCoordinator, listSessionCatalogEntries, ses
37
37
  import { decodeNodePtyResumeParams, resolveNodeHostExecutable, runNodePtyCommand } from "openclaw/plugin-sdk/node-host";
38
38
  import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
39
39
  //#region extensions/codex/src/jsonl-lines.ts
40
- const JSONL_STREAM_THRESHOLD_BYTES = 4 * 1024 * 1024;
41
- const JSONL_READ_CHUNK_BYTES = 1024 * 1024;
40
+ const JSONL_STREAM_THRESHOLD_BYTES = 4194304;
41
+ const JSONL_READ_CHUNK_BYTES = 1048576;
42
42
  async function visitJsonlLines(file, visitor, chunkBytes = JSONL_READ_CHUNK_BYTES) {
43
43
  let size;
44
44
  try {
@@ -138,7 +138,7 @@ const CODEX_CLI_SESSIONS_LIST_COMMAND = "codex.cli.sessions.list";
138
138
  const CODEX_CLI_SESSION_RESUME_COMMAND = "codex.cli.session.resume";
139
139
  const DEFAULT_SESSION_LIMIT = 10;
140
140
  const MAX_SESSION_LIMIT = 50;
141
- const DEFAULT_RESUME_TIMEOUT_MS = 20 * 6e4;
141
+ const DEFAULT_RESUME_TIMEOUT_MS = 12e5;
142
142
  const SESSION_ID_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/;
143
143
  const activeResumeSessions = /* @__PURE__ */ new Set();
144
144
  function createCodexCliSessionNodeHostCommands() {
@@ -529,7 +529,7 @@ function normalizeLimit$1(value) {
529
529
  return typeof value === "number" && Number.isFinite(value) ? Math.min(MAX_SESSION_LIMIT, Math.max(1, Math.floor(value))) : DEFAULT_SESSION_LIMIT;
530
530
  }
531
531
  function normalizeTimeoutMs(value) {
532
- return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.min(60 * 6e4, Math.floor(value)) : DEFAULT_RESUME_TIMEOUT_MS;
532
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.min(36e5, Math.floor(value)) : DEFAULT_RESUME_TIMEOUT_MS;
533
533
  }
534
534
  function truncateText(value, max) {
535
535
  if (value.length <= max) return value;
@@ -808,7 +808,7 @@ const MAX_SESSION_PREVIEW_LENGTH = 500;
808
808
  const MAX_SESSION_KEY_LENGTH = 1024;
809
809
  const MAX_METADATA_LENGTH = 500;
810
810
  const MAX_ACTIVE_FLAGS = 16;
811
- const MAX_TRANSCRIPT_PAGE_BYTES = 20 * 1024 * 1024;
811
+ const MAX_TRANSCRIPT_PAGE_BYTES = 20971520;
812
812
  var CatalogParamsError = class extends Error {};
813
813
  function readControlCursor(value, label) {
814
814
  if (value === void 0 || value === null) return;
@@ -1235,182 +1235,6 @@ async function createOrReuseNodeAdoptedSession(params) {
1235
1235
  }
1236
1236
  }
1237
1237
  //#endregion
1238
- //#region extensions/codex/src/session-catalog-terminal.ts
1239
- const CODEX_TERMINAL_RESUME_COMMAND = "codex.terminal.resume.v1";
1240
- function resolveCodexCatalogTerminalHome(sources) {
1241
- const runtimeConfig = sources.getRuntimeConfig();
1242
- if (!runtimeConfig) throw new Error("OpenClaw runtime config is unavailable");
1243
- const agentDir = sources.source?.agentDir ?? (sources.agentId ? resolveAgentDir$1(runtimeConfig, sources.agentId) : resolveDefaultAgentDir(runtimeConfig));
1244
- return resolveCodexAppServerLocalHomeDir(sources.source?.appServer.start ?? resolveCodexSupervisionAppServerRuntimeOptions({ pluginConfig: sources.getPluginConfig() }).start, agentDir);
1245
- }
1246
- function resolveLocalCodexTerminalExecutable(env = process.env) {
1247
- return resolveLocalCodexTerminalResolution(env)?.executable;
1248
- }
1249
- function resolveLocalCodexTerminalResolution(env = process.env) {
1250
- return resolveNodeHostExecutable("codex", {
1251
- env,
1252
- pathEnv: env.PATH ?? env.Path ?? "",
1253
- strategy: "fallback"
1254
- });
1255
- }
1256
- function codexNodeTerminalCapability(node) {
1257
- const commands = node.invocableCommands ?? node.commands;
1258
- return node.connected === true && commands?.includes("codex.terminal.resume.v1") === true ? { canOpenTerminalCodex: true } : {};
1259
- }
1260
- async function requireCatalogEligibleThread(control, threadId) {
1261
- const cached = await findCatalogEligibleThread(control, threadId, false);
1262
- if (cached) return cached;
1263
- const refreshed = await findCatalogEligibleThread(control, threadId, true);
1264
- if (refreshed) return refreshed;
1265
- throw new CatalogParamsError("Codex session is not a non-archived interactive Codex session");
1266
- }
1267
- async function findCatalogEligibleThread(control, threadId, forceRefresh) {
1268
- let cursor;
1269
- const seenCursors = /* @__PURE__ */ new Set();
1270
- for (let pageIndex = 0; pageIndex < 100; pageIndex += 1) {
1271
- const page = await control.listPage({
1272
- limit: 100,
1273
- ...cursor ? { cursor } : {},
1274
- ...forceRefresh ? { forceRefresh: true } : {}
1275
- });
1276
- const candidate = page.sessions.find((session) => session.threadId === threadId);
1277
- if (candidate) {
1278
- if (isInteractiveThreadSource(candidate.source)) return candidate;
1279
- throw new CatalogParamsError("Codex session is not a non-archived interactive Codex session");
1280
- }
1281
- const nextCursor = page.nextCursor?.trim();
1282
- if (!nextCursor) return;
1283
- if (seenCursors.has(nextCursor)) throw new CatalogParamsError("Codex session eligibility could not be verified");
1284
- seenCursors.add(nextCursor);
1285
- cursor = nextCursor;
1286
- }
1287
- throw new CatalogParamsError("Codex session eligibility could not be verified");
1288
- }
1289
- function createCodexTerminalNodeHostCommand(bindRequest, configSources) {
1290
- return {
1291
- command: CODEX_TERMINAL_RESUME_COMMAND,
1292
- cap: CODEX_APP_SERVER_THREADS_CAPABILITY,
1293
- dangerous: false,
1294
- duplex: true,
1295
- isAvailable: ({ env }) => Boolean(resolveNodeHostExecutable("codex", {
1296
- env,
1297
- pathEnv: env.PATH ?? env.Path ?? "",
1298
- strategy: "direct"
1299
- })),
1300
- handle: async (paramsJSON, io) => {
1301
- if (!io) throw new Error("Codex terminal command requires duplex transport");
1302
- const request = bindRequest(paramsJSON);
1303
- const resume = decodeNodePtyResumeParams(request.paramsJSON, (value) => {
1304
- if (typeof value !== "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu.test(value)) throw new CatalogParamsError("threadId must be a UUID");
1305
- return value;
1306
- });
1307
- const record = await requireCatalogEligibleThread(request.control, resume.threadId);
1308
- const resolution = resolveNodeHostExecutable("codex", {
1309
- env: process.env,
1310
- pathEnv: process.env.PATH ?? process.env.Path ?? "",
1311
- strategy: "direct"
1312
- });
1313
- if (!resolution) throw new Error("Codex CLI is unavailable");
1314
- return JSON.stringify(await runNodePtyCommand({
1315
- file: resolution.executable,
1316
- args: ["resume", resume.threadId],
1317
- cwd: record.cwd,
1318
- env: { CODEX_HOME: resolveCodexCatalogTerminalHome({
1319
- ...configSources,
1320
- agentId: request.agentId
1321
- }) },
1322
- cols: resume.cols,
1323
- rows: resume.rows
1324
- }, io));
1325
- }
1326
- };
1327
- }
1328
- async function resolveNodeCatalogEligibleThread(params) {
1329
- let cursor;
1330
- const seenCursors = /* @__PURE__ */ new Set();
1331
- for (let pageIndex = 0; pageIndex < 100; pageIndex += 1) {
1332
- const raw = await params.runtime.nodes.invoke({
1333
- nodeId: params.nodeId,
1334
- command: CODEX_APP_SERVER_THREADS_LIST_COMMAND,
1335
- params: {
1336
- agentId: params.agentId,
1337
- limit: 100,
1338
- ...cursor ? { cursor } : {}
1339
- },
1340
- timeoutMs: NODE_INVOKE_TIMEOUT_MS,
1341
- scopes: ["operator.write"]
1342
- });
1343
- const page = params.parseCatalogPage(unwrapNodeInvokePayload(raw));
1344
- const record = page.sessions.find((candidate) => candidate.threadId === params.threadId);
1345
- if (record) {
1346
- if (isInteractiveThreadSource(record.source)) return record;
1347
- break;
1348
- }
1349
- const nextCursor = page.nextCursor?.trim();
1350
- if (!nextCursor || seenCursors.has(nextCursor)) break;
1351
- seenCursors.add(nextCursor);
1352
- cursor = nextCursor;
1353
- }
1354
- throw new CatalogParamsError("Codex session is not a non-archived interactive Codex session");
1355
- }
1356
- async function openCodexCatalogTerminal(params) {
1357
- const title = `codex resume ${params.threadId.slice(0, 8)}…`;
1358
- if (params.hostId === "gateway:local" || params.hostId.startsWith(`gateway:local:`)) {
1359
- const record = await requireCatalogEligibleThread(params.control, params.threadId);
1360
- const resolution = resolveLocalCodexTerminalResolution();
1361
- if (!resolution) throw new CatalogParamsError("Codex CLI is unavailable");
1362
- return {
1363
- kind: "local",
1364
- argv: [
1365
- resolution.executable,
1366
- "resume",
1367
- params.threadId
1368
- ],
1369
- ...record.cwd ? { cwd: record.cwd } : {},
1370
- env: { CODEX_HOME: resolveCodexCatalogTerminalHome(params) },
1371
- ...resolution.pathEnv ? { pathEnv: resolution.pathEnv } : {},
1372
- title
1373
- };
1374
- }
1375
- if (!params.hostId.startsWith("node:")) throw new CatalogParamsError("hostId is invalid");
1376
- const nodeId = params.hostId.slice(5);
1377
- if (!(await params.api.runtime.nodes.list()).nodes.find((candidate) => {
1378
- const commands = candidate.invocableCommands ?? candidate.commands;
1379
- return candidate.nodeId === nodeId && candidate.connected === true && commands?.includes("codex.appServer.threads.list.v1") === true && commands.includes("codex.terminal.resume.v1");
1380
- })) throw new CatalogParamsError("paired-node Codex terminal is unavailable");
1381
- const record = await resolveNodeCatalogEligibleThread({
1382
- agentId: params.agentId,
1383
- runtime: params.api.runtime,
1384
- nodeId,
1385
- threadId: params.threadId,
1386
- parseCatalogPage: params.parseCatalogPage
1387
- });
1388
- return {
1389
- kind: "node",
1390
- nodeId,
1391
- command: CODEX_TERMINAL_RESUME_COMMAND,
1392
- paramsJSON: JSON.stringify({
1393
- agentId: params.agentId,
1394
- threadId: params.threadId
1395
- }),
1396
- ...record.cwd ? { cwd: record.cwd } : {},
1397
- title
1398
- };
1399
- }
1400
- async function startCodexCatalogTerminal(params) {
1401
- if (params.nodeId) throw new CatalogParamsError("Paired-node Codex terminal start is unavailable; omit hostId to start on the gateway host");
1402
- const resolution = resolveLocalCodexTerminalResolution();
1403
- if (!resolution) throw new CatalogParamsError("Codex CLI is unavailable; install Codex or add codex to PATH, then try again");
1404
- return {
1405
- kind: "local",
1406
- argv: [resolution.executable, ...params.initialMessage !== void 0 ? ["--", params.initialMessage] : []],
1407
- cwd: params.cwd,
1408
- env: { CODEX_HOME: resolveCodexCatalogTerminalHome(params) },
1409
- ...resolution.pathEnv ? { pathEnv: resolution.pathEnv } : {},
1410
- title: "codex"
1411
- };
1412
- }
1413
- //#endregion
1414
1238
  //#region extensions/codex/src/session-catalog-adoption.ts
1415
1239
  const CODEX_SUPERVISION_SESSION_KEY_PREFIX = "harness:codex:supervision:";
1416
1240
  const boundCatalogSessionId = (value) => boundedCatalogString(value, 256);
@@ -1635,7 +1459,7 @@ async function createOrReuseAdoptedSession(params) {
1635
1459
  }
1636
1460
  }
1637
1461
  async function continueLocalCodexSessionInner(params) {
1638
- await requireCatalogEligibleThread(params.control, params.threadId);
1462
+ await params.control.requireEligibleThread(params.threadId);
1639
1463
  const existing = await findAdoptedSessionEntry({
1640
1464
  ...params,
1641
1465
  runtime: params.api.runtime
@@ -1728,8 +1552,8 @@ async function archiveLocalCodexSession(params) {
1728
1552
  return await runSessionActionExclusive(sessionCatalogAdoptedSourceKey(params.hostId ?? "gateway:local", params.threadId), async () => {
1729
1553
  return await params.bindingStore.withThreadArchiveFence(async () => {
1730
1554
  const run = async (control) => {
1731
- await requireCatalogEligibleThread(control, params.threadId);
1732
1555
  await assertNoPendingSupervisionBranch(params);
1556
+ await control.requireEligibleThread(params.threadId);
1733
1557
  const thread = await control.readThread(params.threadId, false);
1734
1558
  if (thread.id !== params.threadId) throw new Error("Codex app-server returned a different thread than requested");
1735
1559
  requireIdleThread(thread, "archive");
@@ -2013,6 +1837,154 @@ async function continueNodeCodexSession(params) {
2013
1837
  });
2014
1838
  }
2015
1839
  //#endregion
1840
+ //#region extensions/codex/src/session-catalog-terminal.ts
1841
+ const CODEX_TERMINAL_RESUME_COMMAND = "codex.terminal.resume.v1";
1842
+ function resolveCodexCatalogTerminalHome(sources) {
1843
+ const runtimeConfig = sources.getRuntimeConfig();
1844
+ if (!runtimeConfig) throw new Error("OpenClaw runtime config is unavailable");
1845
+ const agentDir = sources.source?.agentDir ?? (sources.agentId ? resolveAgentDir$1(runtimeConfig, sources.agentId) : resolveDefaultAgentDir(runtimeConfig));
1846
+ const startOptions = sources.source?.appServer.start ?? resolveCodexSupervisionAppServerRuntimeOptions({ pluginConfig: sources.getPluginConfig() }).start;
1847
+ return resolveCodexAppServerLocalHomeDir(startOptions, agentDir);
1848
+ }
1849
+ function resolveLocalCodexTerminalExecutable(env = process.env) {
1850
+ return resolveLocalCodexTerminalResolution(env)?.executable;
1851
+ }
1852
+ function resolveLocalCodexTerminalResolution(env = process.env) {
1853
+ return resolveNodeHostExecutable("codex", {
1854
+ env,
1855
+ pathEnv: env.PATH ?? env.Path ?? "",
1856
+ strategy: "fallback"
1857
+ });
1858
+ }
1859
+ function codexNodeTerminalCapability(node) {
1860
+ const commands = node.invocableCommands ?? node.commands;
1861
+ return node.connected === true && commands?.includes("codex.terminal.resume.v1") === true ? { canOpenTerminalCodex: true } : {};
1862
+ }
1863
+ function createCodexTerminalNodeHostCommand(bindRequest, configSources) {
1864
+ return {
1865
+ command: CODEX_TERMINAL_RESUME_COMMAND,
1866
+ cap: CODEX_APP_SERVER_THREADS_CAPABILITY,
1867
+ dangerous: false,
1868
+ duplex: true,
1869
+ isAvailable: ({ env }) => Boolean(resolveNodeHostExecutable("codex", {
1870
+ env,
1871
+ pathEnv: env.PATH ?? env.Path ?? "",
1872
+ strategy: "direct"
1873
+ })),
1874
+ handle: async (paramsJSON, io) => {
1875
+ if (!io) throw new Error("Codex terminal command requires duplex transport");
1876
+ const request = bindRequest(paramsJSON);
1877
+ const resume = decodeNodePtyResumeParams(request.paramsJSON, (value) => {
1878
+ if (typeof value !== "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu.test(value)) throw new CatalogParamsError("threadId must be a UUID");
1879
+ return value;
1880
+ });
1881
+ const record = await request.control.requireEligibleThread(resume.threadId);
1882
+ const resolution = resolveNodeHostExecutable("codex", {
1883
+ env: process.env,
1884
+ pathEnv: process.env.PATH ?? process.env.Path ?? "",
1885
+ strategy: "direct"
1886
+ });
1887
+ if (!resolution) throw new Error("Codex CLI is unavailable");
1888
+ return JSON.stringify(await runNodePtyCommand({
1889
+ file: resolution.executable,
1890
+ args: ["resume", resume.threadId],
1891
+ ...record.cwd ? { cwd: record.cwd } : {},
1892
+ env: { CODEX_HOME: resolveCodexCatalogTerminalHome({
1893
+ ...configSources,
1894
+ agentId: request.agentId
1895
+ }) },
1896
+ cols: resume.cols,
1897
+ rows: resume.rows
1898
+ }, io));
1899
+ }
1900
+ };
1901
+ }
1902
+ async function resolveNodeCatalogEligibleThread(params) {
1903
+ let cursor;
1904
+ const seenCursors = /* @__PURE__ */ new Set();
1905
+ for (let pageIndex = 0; pageIndex < 100; pageIndex += 1) {
1906
+ const raw = await params.runtime.nodes.invoke({
1907
+ nodeId: params.nodeId,
1908
+ command: CODEX_APP_SERVER_THREADS_LIST_COMMAND,
1909
+ params: {
1910
+ agentId: params.agentId,
1911
+ limit: 100,
1912
+ ...cursor ? { cursor } : {}
1913
+ },
1914
+ timeoutMs: NODE_INVOKE_TIMEOUT_MS,
1915
+ scopes: ["operator.write"]
1916
+ });
1917
+ const page = params.parseCatalogPage(unwrapNodeInvokePayload(raw));
1918
+ const record = page.sessions.find((candidate) => candidate.threadId === params.threadId);
1919
+ if (record) {
1920
+ if (isInteractiveThreadSource(record.source)) return record;
1921
+ break;
1922
+ }
1923
+ const nextCursor = page.nextCursor?.trim();
1924
+ if (!nextCursor || seenCursors.has(nextCursor)) break;
1925
+ seenCursors.add(nextCursor);
1926
+ cursor = nextCursor;
1927
+ }
1928
+ throw new CatalogParamsError("Codex session is not a non-archived interactive Codex session");
1929
+ }
1930
+ async function openCodexCatalogTerminal(params) {
1931
+ const title = `codex resume ${params.threadId.slice(0, 8)}…`;
1932
+ if (params.hostId === "gateway:local" || params.hostId.startsWith(`gateway:local:`)) {
1933
+ const record = await params.control.requireEligibleThread(params.threadId);
1934
+ const resolution = resolveLocalCodexTerminalResolution();
1935
+ if (!resolution) throw new CatalogParamsError("Codex CLI is unavailable");
1936
+ return {
1937
+ kind: "local",
1938
+ argv: [
1939
+ resolution.executable,
1940
+ "resume",
1941
+ params.threadId
1942
+ ],
1943
+ ...record.cwd ? { cwd: record.cwd } : {},
1944
+ env: { CODEX_HOME: resolveCodexCatalogTerminalHome(params) },
1945
+ ...resolution.pathEnv ? { pathEnv: resolution.pathEnv } : {},
1946
+ title
1947
+ };
1948
+ }
1949
+ if (!params.hostId.startsWith("node:")) throw new CatalogParamsError("hostId is invalid");
1950
+ const nodeId = params.hostId.slice(5);
1951
+ if (!(await params.api.runtime.nodes.list()).nodes.find((candidate) => {
1952
+ const commands = candidate.invocableCommands ?? candidate.commands;
1953
+ return candidate.nodeId === nodeId && candidate.connected === true && commands?.includes("codex.appServer.threads.list.v1") === true && commands.includes("codex.terminal.resume.v1");
1954
+ })) throw new CatalogParamsError("paired-node Codex terminal is unavailable");
1955
+ const record = await resolveNodeCatalogEligibleThread({
1956
+ agentId: params.agentId,
1957
+ runtime: params.api.runtime,
1958
+ nodeId,
1959
+ threadId: params.threadId,
1960
+ parseCatalogPage: params.parseCatalogPage
1961
+ });
1962
+ return {
1963
+ kind: "node",
1964
+ nodeId,
1965
+ command: CODEX_TERMINAL_RESUME_COMMAND,
1966
+ paramsJSON: JSON.stringify({
1967
+ agentId: params.agentId,
1968
+ threadId: params.threadId
1969
+ }),
1970
+ ...record.cwd ? { cwd: record.cwd } : {},
1971
+ title
1972
+ };
1973
+ }
1974
+ async function startCodexCatalogTerminal(params) {
1975
+ if (params.nodeId) throw new CatalogParamsError("Paired-node Codex terminal start is unavailable; omit hostId to start on the gateway host");
1976
+ const resolution = resolveLocalCodexTerminalResolution();
1977
+ if (!resolution) throw new CatalogParamsError("Codex CLI is unavailable; install Codex or add codex to PATH, then try again");
1978
+ return {
1979
+ kind: "local",
1980
+ argv: [resolution.executable, ...params.initialMessage !== void 0 ? ["--", params.initialMessage] : []],
1981
+ cwd: params.cwd,
1982
+ env: { CODEX_HOME: resolveCodexCatalogTerminalHome(params) },
1983
+ ...resolution.pathEnv ? { pathEnv: resolution.pathEnv } : {},
1984
+ title: "codex"
1985
+ };
1986
+ }
1987
+ //#endregion
2016
1988
  //#region extensions/codex/src/session-catalog-listing.ts
2017
1989
  async function listVisiblePage(params) {
2018
1990
  const excluded = params.excludedThreadIds;
@@ -2231,7 +2203,7 @@ function createCodexSessionCatalogNodeHostCommands(controlFactory, configSources
2231
2203
  const request = bindRequest(paramsJSON);
2232
2204
  const action = readNodeTranscriptParams(request.params);
2233
2205
  try {
2234
- await requireCatalogEligibleThread(request.control, action.threadId);
2206
+ await request.control.requireEligibleThread(action.threadId);
2235
2207
  const page = parseTranscriptPage(await request.control.listTurnPage({
2236
2208
  threadId: action.threadId,
2237
2209
  limit: action.limit,
@@ -2276,7 +2248,7 @@ function flattenTranscriptPageDesc(page) {
2276
2248
  /** Reads the persisted transcript for a Gateway-local or paired-node Codex session. */
2277
2249
  async function readCodexSessionTranscript(params) {
2278
2250
  if (params.source || params.hostId === "gateway:local") {
2279
- await requireCatalogEligibleThread(params.control, params.threadId);
2251
+ await params.control.requireEligibleThread(params.threadId);
2280
2252
  const listParams = {
2281
2253
  threadId: params.threadId,
2282
2254
  limit: params.limit,
@@ -2615,10 +2587,10 @@ function createCodexCatalogRequestSnapshot(requestTimeoutMs, request) {
2615
2587
  listThreads: (params, timeoutMs) => request(CODEX_CONTROL_METHODS.listThreads, params, timeoutMs),
2616
2588
  listThreadTurns: (params) => request(CODEX_CONTROL_METHODS.listThreadTurns, params),
2617
2589
  forkThread: (params) => request(CODEX_CONTROL_METHODS.forkThread, assertCodexThreadForkParams(params)),
2618
- readThread: async (threadId, includeTurns) => (await request(CODEX_CONTROL_METHODS.readThread, {
2590
+ readThread: async (threadId, includeTurns, timeoutMs) => (await request(CODEX_CONTROL_METHODS.readThread, {
2619
2591
  threadId,
2620
2592
  includeTurns
2621
- })).thread,
2593
+ }, timeoutMs)).thread,
2622
2594
  archiveThread: async (threadId) => {
2623
2595
  await request(CODEX_CONTROL_METHODS.archiveThread, { threadId });
2624
2596
  }
@@ -2629,6 +2601,58 @@ function createCodexSessionCatalogControlFromRequests(params) {
2629
2601
  ...params.clientId ? { clientId: params.clientId } : {},
2630
2602
  ...params.connectionFingerprint ? { connectionFingerprint: params.connectionFingerprint } : {},
2631
2603
  withPinnedConnection: params.withPinnedConnection,
2604
+ async requireEligibleThread(threadId) {
2605
+ const requests = params.createRequestSnapshot();
2606
+ const deadline = params.now() + requests.requestTimeoutMs;
2607
+ const unverified = () => new CatalogParamsError("Codex session eligibility could not be verified. Refresh the catalog and verify the session in its native Codex home before retrying.");
2608
+ const remaining = () => {
2609
+ const timeoutMs = Math.ceil(deadline - params.now());
2610
+ if (timeoutMs <= 0) throw unverified();
2611
+ return timeoutMs;
2612
+ };
2613
+ const verify = async () => {
2614
+ if (params.sourceHomeId && await params.managedThreads?.has(params.sourceHomeId, threadId)) throw unverified();
2615
+ const root = params.localSessionsRoot;
2616
+ const thread = root ? await requests.readThread(threadId, false, remaining()) : void 0;
2617
+ if (root && (!thread || thread.id !== threadId || !isInteractiveThreadSource(thread.source))) throw unverified();
2618
+ let cursor;
2619
+ const seenCursors = /* @__PURE__ */ new Set();
2620
+ for (let pageIndex = 0; pageIndex < 100; pageIndex += 1) {
2621
+ const page = await requests.listThreads({
2622
+ archived: false,
2623
+ limit: 100,
2624
+ modelProviders: [],
2625
+ sortKey: root ? "recency_at" : "updated_at",
2626
+ sortDirection: "desc",
2627
+ ...root ? {
2628
+ useStateDbOnly: true,
2629
+ ...thread?.cwd ? { cwd: thread.cwd } : {}
2630
+ } : {},
2631
+ ...cursor ? { cursor } : {}
2632
+ }, remaining());
2633
+ remaining();
2634
+ const candidate = page.data.find((value) => value.id === threadId);
2635
+ if (candidate) {
2636
+ if (!isInteractiveThreadSource(candidate.source)) throw unverified();
2637
+ if (root && thread) {
2638
+ const rolloutPath = thread.path;
2639
+ if (!rolloutPath || !candidate.path || rolloutPath.replace(/\.zst$/u, "") !== candidate.path.replace(/\.zst$/u, "")) throw unverified();
2640
+ const metadata = await readCodexSessionMeta(root, rolloutPath, threadId);
2641
+ remaining();
2642
+ if (!metadata || !isInteractiveThreadSource(metadata.source) || metadata.originator === "openclaw") throw unverified();
2643
+ return thread;
2644
+ }
2645
+ return candidate;
2646
+ }
2647
+ const nextCursor = readControlCursor(page.nextCursor, "next response");
2648
+ if (!nextCursor || seenCursors.has(nextCursor)) throw unverified();
2649
+ seenCursors.add(nextCursor);
2650
+ cursor = nextCursor;
2651
+ }
2652
+ throw unverified();
2653
+ };
2654
+ return await withTimeout(verify(), requests.requestTimeoutMs, "Codex session eligibility could not be verified", unverified);
2655
+ },
2632
2656
  async listPage(pageParams) {
2633
2657
  const limit = normalizeLimit(pageParams.limit, "limit");
2634
2658
  const search = pageParams.searchTerm?.trim().toLocaleLowerCase() || void 0;
@@ -2768,6 +2792,8 @@ function createCodexSessionCatalogControl(params) {
2768
2792
  connectionFingerprint: buildCodexAppServerConnectionFingerprint(runtime, agentDir),
2769
2793
  createRequestSnapshot: () => requests,
2770
2794
  ...source?.localSessionsRoot ? { localSessionsRoot: source.localSessionsRoot } : {},
2795
+ sourceHomeId: source?.sourceHomeId,
2796
+ managedThreads: params.managedThreads,
2771
2797
  now,
2772
2798
  withPinnedConnection: async (nestedRun) => await nestedRun(pinnedControl)
2773
2799
  });
@@ -2784,6 +2810,7 @@ function createCodexSessionCatalogControl(params) {
2784
2810
  });
2785
2811
  return {
2786
2812
  ...control,
2813
+ requireEligibleThread: (threadId) => withPinnedConnection((pinned) => pinned.requireEligibleThread(threadId)),
2787
2814
  async listPage(pageParams) {
2788
2815
  const runtimeConfig = params.getRuntimeConfig();
2789
2816
  if (!runtimeConfig) return await control.listPage(pageParams);
@@ -2794,7 +2821,7 @@ function createCodexSessionCatalogControl(params) {
2794
2821
  }
2795
2822
  const key = codexCatalogPageCacheKey(pageParams, agentId, source);
2796
2823
  const cached = cache.get(key);
2797
- if (pageParams.forceRefresh !== true && cached) {
2824
+ if (cached) {
2798
2825
  cache.delete(key);
2799
2826
  cache.set(key, cached);
2800
2827
  if (cached.expiresAt > now()) return cached.value ?? await cached.page;
@@ -2825,7 +2852,7 @@ function createCodexSessionCatalogControl(params) {
2825
2852
  });
2826
2853
  else cache.delete(key);
2827
2854
  };
2828
- if (pageParams.forceRefresh !== true && staleValue) {
2855
+ if (staleValue) {
2829
2856
  page.then(settle, restore);
2830
2857
  return staleValue;
2831
2858
  }
@@ -3000,7 +3027,7 @@ function registerCodexSessionCatalog(params) {
3000
3027
  if (!isLocalCodexCatalogHost(request.hostId)) throw new CatalogParamsError("Codex session catalog hostId is invalid");
3001
3028
  const { agentId, source, control } = bindLocalRequest(request);
3002
3029
  let upstreamBaseline;
3003
- return codexUpstreamContinueResult((await continueLocalCodexSession({
3030
+ const continued = await continueLocalCodexSession({
3004
3031
  agentId,
3005
3032
  api: params.api,
3006
3033
  bindingStore: params.bindingStore,
@@ -3013,7 +3040,8 @@ function registerCodexSessionCatalog(params) {
3013
3040
  onContinued: (baseline) => {
3014
3041
  upstreamBaseline = baseline;
3015
3042
  }
3016
- })).sessionKey, request.threadId, upstreamBaseline);
3043
+ });
3044
+ return codexUpstreamContinueResult(continued.sessionKey, request.threadId, upstreamBaseline);
3017
3045
  },
3018
3046
  checkUpstreamActivity: (probes, policy) => checkUpstreamActivity(probes.filter((probe) => !isLocalCodexCatalogHost(probe.hostId) || policy?.allowProcessHomeFallback !== false || catalogHomes(probe.agentId, false).some((home) => home.hostId === probe.hostId))),
3019
3047
  archive: async (request) => {
@@ -1,12 +1,12 @@
1
- import { Ht as isJsonObject } from "./shared-client-kNkljY-R.js";
1
+ import { Ht as isJsonObject } from "./shared-client-B1tT5U6r.js";
2
2
  import path from "node:path";
3
3
  import { createHash } from "node:crypto";
4
4
  import fsSync from "node:fs";
5
5
  import { root } from "openclaw/plugin-sdk/file-access-runtime";
6
6
  import { createZstdDecompress } from "node:zlib";
7
7
  //#region extensions/codex/src/session-catalog-provenance.ts
8
- const MAX_SESSION_META_BYTES = 1024 * 1024;
9
- const SESSION_META_READ_CHUNK_BYTES = 64 * 1024;
8
+ const MAX_SESSION_META_BYTES = 1048576;
9
+ const SESSION_META_READ_CHUNK_BYTES = 65536;
10
10
  const MAX_PROVENANCE_CACHE_ENTRIES = 2e4;
11
11
  const provenanceByPath = /* @__PURE__ */ new Map();
12
12
  function cacheProvenance(key, value) {
@@ -1,4 +1,4 @@
1
- import "./session-catalog-C2Tae4rI.js";
1
+ import "./session-catalog-eMhVm0Ql.js";
2
2
  import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
4
4
  import { sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";