@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.
- package/dist/api.js +6 -6
- package/dist/{attempt-client-cleanup-DYHcRQAa.js → attempt-client-cleanup-Bp1ZOnk2.js} +76 -32
- package/dist/{attempt-context-DmQUNWwT.js → attempt-context-CSazkWns.js} +6 -6
- package/dist/{bounded-turn-wzJrwKKe.js → bounded-turn-DxGJRYbY.js} +46 -45
- package/dist/{capabilities-dIjNVCYH.js → capabilities-B1mgvpP8.js} +2 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-CLHhEB1Q.js → command-formatters-DSbGMXA0.js} +2 -2
- package/dist/{command-handlers-CTGb2csu.js → command-handlers-DOJvGv6-.js} +146 -74
- package/dist/{compact-_t0HQrUS.js → compact-Y_xBqrHN.js} +83 -48
- package/dist/{config-BhmfC1s6.js → config-CyapYSji.js} +47 -105
- package/dist/config-utils-C57JiJrU.js +69 -0
- package/dist/doctor-contract-api.js +4 -5
- package/dist/{dynamic-tools-BU9tmlYm.js → dynamic-tools-BwpvTxaX.js} +678 -638
- package/dist/{effective-mcp-catalog-DzYBW4h1.js → effective-mcp-catalog-CY9Jn4bA.js} +4 -3
- package/dist/{event-projector-assistant-message-DHRFXKbS.js → event-projector-assistant-message-B9kp6iGC.js} +11 -2
- package/dist/{event-projector-usage-C5mcrGjp.js → event-projector-usage-ZqEVbAEY.js} +30 -13
- package/dist/{harness-DXVZ5II5.js → harness-Czh2Sdoc.js} +36 -13
- package/dist/harness.js +1 -1
- package/dist/{image-payload-sanitizer-CnfoUPCE.js → image-payload-sanitizer-tupAr-2o.js} +29 -15
- package/dist/index.js +68 -84
- package/dist/{isolated-completion-kg9kv4iH.js → isolated-completion-CRh-51AK.js} +9 -21
- package/dist/{managed-binary-4-Vjz5GH.js → managed-binary-DcpnJF9x.js} +105 -73
- package/dist/media-understanding-provider.js +1 -1
- package/dist/{model-catalog-CUM68Hkl.js → model-catalog-DT5vo6qo.js} +5 -5
- package/dist/{models-sYnEc0gd.js → models-CcrgSMQR.js} +4 -4
- package/dist/{native-subagent-monitor-CnH147jH.js → native-subagent-monitor-B3bvQGcg.js} +12 -11
- package/dist/{node-exec-server.runtime-CstNHCmC.js → node-exec-server.runtime-nfbUOtUB.js} +3 -3
- package/dist/{plugin-approval-roundtrip-CNe-Xrjx.js → plugin-approval-roundtrip-aQVdyL5g.js} +1 -1
- package/dist/{plugin-marketplace-discovery-CfFlKqDl.js → plugin-marketplace-discovery-B7gHXJ3d.js} +35 -22
- package/dist/{plugin-metadata-cache-BFrPhb2c.js → plugin-metadata-cache-BwCLTY_U.js} +5 -5
- package/dist/{provider-capabilities-DW5p4k9w.js → provider-capabilities-BpG9Ltc5.js} +2 -2
- package/dist/{rate-limits-CawQJfUS.js → rate-limits-Fx_l4eNa.js} +1 -1
- package/dist/{request-DYAI5FQE.js → request-C8H22rPi.js} +2 -2
- package/dist/{run-attempt-D1hJO4fX.js → run-attempt-BzthFQSM.js} +977 -723
- package/dist/{runtime-artifact-C3jVimFn.js → runtime-artifact-Bh_gf6-t.js} +3 -3
- package/dist/{session-binding-BHuTCRZQ.js → session-binding-4Ki04sW-.js} +94 -282
- package/dist/session-binding-record-CyaXZvTe.js +270 -0
- package/dist/{session-catalog-yyvTWFOw.js → session-catalog-B47uwekb.js} +266 -114
- package/dist/{session-cli-CmFEXMAM.js → session-cli-BjLhpmS1.js} +1 -1
- package/dist/session-history-DWmMqiqW.js +93 -0
- package/dist/session-history-read-LHldwvyh.js +36 -0
- package/dist/session-history-worker-runtime.js +48 -0
- package/dist/{settled-turn-context-D3SNWtUn.js → session-history.worker-zZVcx0ME.js} +30 -31
- package/dist/session-history.worker.js +2 -0
- package/dist/{session-initialization-BeWzjGiR.js → session-initialization-BCFVnLL4.js} +2 -1
- package/dist/{session-permission-policy-DeWVTCMj.js → session-permission-policy-BaueHmSj.js} +1 -1
- package/dist/{session-retirement-BujDjXVF.js → session-retirement-DNdmYdFc.js} +7 -7
- package/dist/{session-upstream-marker-C351-5Qw.js → session-upstream-marker-DReTpGz6.js} +4 -3
- package/dist/settled-turn-context-BOM3Y1pl.js +45 -0
- package/dist/{settled-turn-finalizer-BVJx4yoc.js → settled-turn-finalizer-BI-b1sry.js} +53 -42
- package/dist/{shared-client-DxcfF9KX.js → shared-client-CKhX2kFt.js} +279 -268
- package/dist/{side-question-BTZAII4l.js → side-question-B6DWAw1A.js} +85 -36
- package/dist/{thread-lifecycle-DAcEJ_Om.js → thread-lifecycle-DPK30jad.js} +382 -388
- package/dist/{thread-ownership-zGokd8i1.js → thread-ownership-CbucAmmp.js} +5 -5
- package/dist/thread-policy-CTalhWFy.js +105 -0
- package/dist/{thread-resume-C7pyVKeW.js → thread-resume-BLgqkUc1.js} +7 -7
- package/dist/{transcript-mirror-DTUxFWa_.js → transcript-mirror-_njEB84z.js} +67 -125
- package/dist/transcript-mirror-attestation-Byl34PC-.js +76 -0
- package/dist/{transport-stdio-CyPldczm.js → transport-stdio-CzTngV0j.js} +10 -8
- package/dist/{upstream-session-fork-CYlBIGVt.js → upstream-session-fork-1fwbNKzQ.js} +85 -165
- package/dist/{usage-Bj-rrzkR.js → usage-i9fv5-4m.js} +3 -3
- package/dist/{web-search-provider.runtime-D2FWSK4w.js → web-search-provider.runtime-DKQn67A7.js} +3 -3
- package/package.json +6 -6
- package/dist/binding-connection-E6uDsPlx.js +0 -45
- package/dist/launch-args-RXQwn8zV.js +0 -90
- package/dist/session-history-C5J1AKzG.js +0 -87
- package/dist/thread-policy-g4KbJPzp.js +0 -54
|
@@ -1,30 +1,32 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { c as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
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-
|
|
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$
|
|
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
|
|
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$
|
|
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:
|
|
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") >
|
|
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 {
|
|
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 =
|
|
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 =
|
|
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 {
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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$
|
|
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)
|
|
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
|
-
|
|
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
|
|
2245
|
-
const listParams = {
|
|
2430
|
+
const page = await readCodexCatalogTranscriptPage(params.control, {
|
|
2246
2431
|
threadId: params.threadId,
|
|
2247
|
-
limit
|
|
2248
|
-
|
|
2249
|
-
|
|
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
|
-
|
|
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
|
|
2445
|
+
const invoke = async (command, request) => unwrapNodeInvokePayload(await params.runtime.nodes.invoke({
|
|
2266
2446
|
nodeId,
|
|
2267
|
-
command
|
|
2447
|
+
command,
|
|
2268
2448
|
params: {
|
|
2269
2449
|
agentId: params.agentId,
|
|
2270
2450
|
threadId: params.threadId,
|
|
2271
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 (
|
|
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 =
|
|
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 =
|
|
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$
|
|
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$
|
|
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$
|
|
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
|
-
|
|
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();
|