@openclaw/codex 2026.8.2 → 2026.9.1
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 +3 -3
- package/dist/{attempt-client-cleanup-CpVfwctT.js → attempt-client-cleanup-DYHcRQAa.js} +6 -43
- package/dist/attempt-context-DmQUNWwT.js +634 -0
- package/dist/{binding-connection-CF7BmrDk.js → binding-connection-E6uDsPlx.js} +2 -2
- package/dist/{bounded-turn-DRC3hcjm.js → bounded-turn-wzJrwKKe.js} +8 -9
- package/dist/{capabilities-D6m_TdVy.js → capabilities-dIjNVCYH.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters--UToCokS.js → command-formatters-CLHhEB1Q.js} +3 -3
- package/dist/{command-handlers-CLFx2Ypa.js → command-handlers-CTGb2csu.js} +54 -55
- package/dist/{compact-5xqW1oCh.js → compact-_t0HQrUS.js} +33 -25
- package/dist/{config-CcYL77O6.js → config-BhmfC1s6.js} +12 -8
- package/dist/{context-compaction-activity-BOeJf7yo.js → context-compaction-activity-CMla5FPJ.js} +4 -1
- package/dist/doctor-contract-api.js +31 -4
- package/dist/{dynamic-tools-BmeXjwNZ.js → dynamic-tools-BU9tmlYm.js} +448 -457
- package/dist/{effective-mcp-catalog-XXQKgK1U.js → effective-mcp-catalog-DzYBW4h1.js} +2 -2
- package/dist/{event-projector-assistant-message-C5-Ds8mA.js → event-projector-assistant-message-DHRFXKbS.js} +4 -4
- package/dist/{event-projector-usage-B2r5vhWH.js → event-projector-usage-C5mcrGjp.js} +9 -137
- package/dist/{harness-BgeB7LnD.js → harness-DXVZ5II5.js} +13 -13
- package/dist/harness.js +1 -1
- package/dist/index.js +323 -313
- package/dist/{isolated-completion-CxTus3vZ.js → isolated-completion-kg9kv4iH.js} +4 -4
- package/dist/{launch-args-sXOAg0SX.js → launch-args-RXQwn8zV.js} +7 -1
- package/dist/{managed-binary-ZkGodW19.js → managed-binary-4-Vjz5GH.js} +14 -9
- package/dist/media-understanding-provider.js +1 -1
- package/dist/{model-catalog-DULBcniB.js → model-catalog-CUM68Hkl.js} +11 -11
- package/dist/{models-DaWfETQk.js → models-sYnEc0gd.js} +3 -3
- package/dist/{native-subagent-monitor-vXYUZH37.js → native-subagent-monitor-CnH147jH.js} +3 -3
- package/dist/{node-exec-server.runtime-DirKVZ5h.js → node-exec-server.runtime-CstNHCmC.js} +2 -2
- package/dist/{plugin-approval-roundtrip-CCWQGlAI.js → plugin-approval-roundtrip-CNe-Xrjx.js} +29 -3
- package/dist/{plugin-marketplace-discovery-BXjIFEiw.js → plugin-marketplace-discovery-CfFlKqDl.js} +6 -6
- package/dist/{plugin-metadata-cache-DQQm4gWT.js → plugin-metadata-cache-BFrPhb2c.js} +5 -5
- package/dist/provider-capabilities-DW5p4k9w.js +101 -0
- package/dist/{rate-limits-BqHEHXQJ.js → rate-limits-CawQJfUS.js} +1 -1
- package/dist/{request-BWxweEdK.js → request-DYAI5FQE.js} +18 -6
- package/dist/{run-attempt-BVLE4Gbi.js → run-attempt-D1hJO4fX.js} +483 -1865
- package/dist/{runtime-artifact-D9pYp4zL.js → runtime-artifact-C3jVimFn.js} +19 -12
- package/dist/{session-binding-D0zinCP1.js → session-binding-BHuTCRZQ.js} +8 -10
- package/dist/{session-catalog-eMhVm0Ql.js → session-catalog-yyvTWFOw.js} +138 -116
- package/dist/{session-cli-B2lyjJA0.js → session-cli-CmFEXMAM.js} +1 -1
- package/dist/session-initialization-BeWzjGiR.js +74 -0
- package/dist/{session-permission-policy-ScnAyG90.js → session-permission-policy-DeWVTCMj.js} +2 -2
- package/dist/{session-retirement-CtUtUTr9.js → session-retirement-BujDjXVF.js} +16 -9
- package/dist/{session-upstream-marker-gqrYIRHk.js → session-upstream-marker-C351-5Qw.js} +18 -2
- package/dist/{settled-turn-context-Bk3IUwod.js → settled-turn-context-D3SNWtUn.js} +6 -28
- package/dist/{settled-turn-finalizer-BXLN9PfJ.js → settled-turn-finalizer-BVJx4yoc.js} +5 -5
- package/dist/{shared-client-B1tT5U6r.js → shared-client-DxcfF9KX.js} +2748 -101
- package/dist/{side-question-CZ-mCw-t.js → side-question-BTZAII4l.js} +97 -63
- package/dist/{thread-lifecycle-CGGKP720.js → thread-lifecycle-DAcEJ_Om.js} +2039 -1487
- package/dist/{thread-ownership-RkaoZCmQ.js → thread-ownership-zGokd8i1.js} +10 -9
- package/dist/thread-policy-g4KbJPzp.js +54 -0
- package/dist/{thread-resume-BFt1-ZDa.js → thread-resume-C7pyVKeW.js} +15 -7
- package/dist/{transcript-mirror-1ep4XjzF.js → transcript-mirror-DTUxFWa_.js} +47 -10
- package/dist/{transport-stdio-NT_Dpd9V.js → transport-stdio-CyPldczm.js} +3 -1
- package/dist/upstream-session-fork-CYlBIGVt.js +966 -0
- package/dist/{usage-DUhd58gI.js → usage-Bj-rrzkR.js} +3 -3
- package/dist/{web-search-provider.runtime-BEmlE7ov.js → web-search-provider.runtime-D2FWSK4w.js} +3 -3
- package/openclaw.plugin.json +0 -30
- package/package.json +5 -5
- package/dist/protocol-validators-Bg5rpNxk.js +0 -2542
- package/dist/session-catalog-home-id-Dt2GiG5o.js +0 -112
- package/dist/upstream-session-fork-Dc8BFExw.js +0 -312
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as resolvePackagedCodexNativeCommand } from "./managed-binary-4-Vjz5GH.js";
|
|
2
|
+
import { n as resolveCodexAppServerSpawnEnv } from "./transport-stdio-CyPldczm.js";
|
|
2
3
|
import fs from "node:fs/promises";
|
|
3
4
|
import path from "node:path";
|
|
5
|
+
import { isPathInside } from "openclaw/plugin-sdk/file-access-runtime";
|
|
4
6
|
import { createHash } from "node:crypto";
|
|
5
7
|
import { constants } from "node:fs";
|
|
6
8
|
import { resolveWindowsExecutablePath, resolveWindowsSpawnProgram } from "openclaw/plugin-sdk/windows-spawn";
|
|
7
|
-
import { isPathInside } from "openclaw/plugin-sdk/file-access-runtime";
|
|
8
9
|
//#region extensions/codex/src/app-server/runtime-artifact.ts
|
|
9
10
|
/** Exact local runtime artifact identity for verified Codex setup turns. */
|
|
10
11
|
const ARTIFACT_ID_PREFIX = "codex-app-server:v1:";
|
|
@@ -363,6 +364,8 @@ async function captureFilesystemDescriptor(params) {
|
|
|
363
364
|
const spawnCwd = path.resolve(params.startOptions.cwd ?? process.cwd());
|
|
364
365
|
const commandPath = await resolveCommandPath(params.startOptions.command, env, spawnCwd);
|
|
365
366
|
const commandRealPath = await fs.realpath(commandPath);
|
|
367
|
+
let nativeCommand = params.spawnIdentity.nativeCommand;
|
|
368
|
+
let nativeCandidate = commandRealPath;
|
|
366
369
|
let invocationPaths;
|
|
367
370
|
if (process.platform === "win32") {
|
|
368
371
|
const program = resolveWindowsSpawnProgram({
|
|
@@ -372,7 +375,10 @@ async function captureFilesystemDescriptor(params) {
|
|
|
372
375
|
execPath: process.execPath,
|
|
373
376
|
packageName: "@openai/codex"
|
|
374
377
|
});
|
|
375
|
-
|
|
378
|
+
const entrypoint = program.leadingArgv[0];
|
|
379
|
+
if (program.resolution === "node-entrypoint" && entrypoint && !nativeCommand) nativeCommand = resolvePackagedCodexNativeCommand(await fs.realpath(entrypoint));
|
|
380
|
+
if (program.resolution === "node-entrypoint" && !nativeCommand) throw new Error("Codex runtime cannot attest a custom Node launcher without its native target");
|
|
381
|
+
nativeCandidate = program.command;
|
|
376
382
|
const invocationCandidates = [
|
|
377
383
|
commandRealPath,
|
|
378
384
|
program.command,
|
|
@@ -383,17 +389,18 @@ async function captureFilesystemDescriptor(params) {
|
|
|
383
389
|
const resolved = await resolveCommandPath(candidate, env, spawnCwd);
|
|
384
390
|
invocationPaths.push(await fs.realpath(resolved));
|
|
385
391
|
}
|
|
386
|
-
} else
|
|
387
|
-
commandRealPath
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
+
} else {
|
|
393
|
+
nativeCommand ??= resolvePackagedCodexNativeCommand(commandRealPath);
|
|
394
|
+
invocationPaths = await resolvePosixInvocationPaths({
|
|
395
|
+
commandRealPath,
|
|
396
|
+
env,
|
|
397
|
+
cwd: spawnCwd,
|
|
398
|
+
nativeCommand
|
|
399
|
+
});
|
|
400
|
+
}
|
|
392
401
|
invocationPaths = [...new Set(invocationPaths)].toSorted(compareArtifactNames);
|
|
393
402
|
if (invocationPaths.length > MAX_ARTIFACT_INVOCATION_PATHS) throw new Error("Codex runtime launcher exceeds the bounded invocation file count");
|
|
394
|
-
const
|
|
395
|
-
if (!nativeCandidate) throw new Error("Codex runtime did not resolve a native executable");
|
|
396
|
-
const nativePath = await fs.realpath(await resolveCommandPath(nativeCandidate, env, spawnCwd));
|
|
403
|
+
const nativePath = await fs.realpath(await resolveCommandPath(nativeCommand ?? nativeCandidate, env, spawnCwd));
|
|
397
404
|
const packageRoot = await resolvePackageRoot(nativePath);
|
|
398
405
|
const configuredCodeModeHost = readEffectiveSpawnEnvironmentValue(env, CODE_MODE_HOST_PATH_ENV)?.trim();
|
|
399
406
|
const adjacentCodeModeHost = path.join(path.dirname(nativePath), process.platform === "win32" ? "codex-code-mode-host.exe" : "codex-code-mode-host");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
|
|
2
|
-
import {
|
|
2
|
+
import { P as CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN, j as normalizeCodexServiceTier } from "./config-BhmfC1s6.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";
|
|
@@ -31,7 +31,8 @@ var session_binding_exports = /* @__PURE__ */ __exportAll({
|
|
|
31
31
|
reclaimCurrentCodexSessionGeneration: () => reclaimCurrentCodexSessionGeneration,
|
|
32
32
|
resolveCodexRunSessionBindingAuthority: () => resolveCodexRunSessionBindingAuthority,
|
|
33
33
|
scopeCodexRunBindingStore: () => scopeCodexRunBindingStore,
|
|
34
|
-
sessionBindingIdentity: () => sessionBindingIdentity
|
|
34
|
+
sessionBindingIdentity: () => sessionBindingIdentity,
|
|
35
|
+
validateBindingForWrite: () => validateBindingForWrite
|
|
35
36
|
});
|
|
36
37
|
const CODEX_APP_SERVER_NATIVE_AUTH_PROVIDER = "openai";
|
|
37
38
|
const PUBLIC_OPENAI_MODEL_PROVIDER = "openai";
|
|
@@ -333,9 +334,11 @@ function scopeCodexRunBindingStore(params) {
|
|
|
333
334
|
}
|
|
334
335
|
/** Lets the authoritative OpenClaw session generation claim a stale stable binding row. */
|
|
335
336
|
async function reclaimCurrentCodexSessionGeneration(params) {
|
|
337
|
+
params.assertCurrent?.();
|
|
336
338
|
const sessionKey = params.identity.sessionKey?.trim();
|
|
337
339
|
if (!sessionKey) return true;
|
|
338
340
|
const plan = await params.bindingStore.prepareSessionGenerationReclaim(params.identity);
|
|
341
|
+
params.assertCurrent?.();
|
|
339
342
|
if (plan.kind === "resolved") return plan.result;
|
|
340
343
|
try {
|
|
341
344
|
const storePath = params.storePath?.trim() || resolveStorePath(params.config?.session?.store, { agentId: params.identity.agentId });
|
|
@@ -352,7 +355,7 @@ async function reclaimCurrentCodexSessionGeneration(params) {
|
|
|
352
355
|
return await params.bindingStore.mutate(params.identity, {
|
|
353
356
|
kind: "reclaim-generation",
|
|
354
357
|
expectedPreviousSessionId: plan.expectedPreviousSessionId
|
|
355
|
-
});
|
|
358
|
+
}, params.assertCurrent);
|
|
356
359
|
}
|
|
357
360
|
/** Creates the single binding facade owned by the Codex plugin runtime. */
|
|
358
361
|
function createCodexAppServerBindingStore(state) {
|
|
@@ -640,9 +643,8 @@ function createCodexAppServerBindingStore(state) {
|
|
|
640
643
|
const active = ownsGeneration ? storedActive : void 0;
|
|
641
644
|
const retiredGeneration = current?.state === "cleared" && current.retired === true && ownsGeneration;
|
|
642
645
|
const preservesSupervisionOwner = mutation.kind === "set" && active?.binding.connectionScope === "supervision" && isSameSupervisionOwner(active.binding, mutation.binding);
|
|
643
|
-
const clearsPendingSupervisionOwner = mutation.kind === "clear" && matchesPendingSupervisionClear(active?.binding, mutation.threadId, mutation.expectedPendingSupervisionBranch);
|
|
644
646
|
const replacesExpectedOrdinaryOwner = mutation.kind === "replace-thread" && active?.binding.threadId === mutation.expectedThreadId && active.binding.connectionScope !== "supervision" && mutation.binding.connectionScope !== "supervision" && mutation.binding.threadId !== mutation.expectedThreadId;
|
|
645
|
-
if (mutation.kind === "set" && (mutation.if?.kind === "absent" && storedActive || current !== void 0 && !ownsGeneration || retiredGeneration || active?.binding.connectionScope === "supervision" && !preservesSupervisionOwner) || mutation.kind === "patch" && active?.binding.threadId !== mutation.threadId || mutation.kind === "replace-thread" && !replacesExpectedOrdinaryOwner || (mutation.kind === "patch-pending-supervision-branch" || mutation.kind === "commit-pending-supervision-branch") && !matchesPendingSupervisionBranch(active?.binding, mutation.expected) || mutation.kind === "clear" && (!ownsGeneration ||
|
|
647
|
+
if (mutation.kind === "set" && (mutation.if?.kind === "absent" && storedActive || current !== void 0 && !ownsGeneration || retiredGeneration || active?.binding.connectionScope === "supervision" && !preservesSupervisionOwner) || mutation.kind === "patch" && active?.binding.threadId !== mutation.threadId || mutation.kind === "replace-thread" && !replacesExpectedOrdinaryOwner || (mutation.kind === "patch-pending-supervision-branch" || mutation.kind === "commit-pending-supervision-branch") && !matchesPendingSupervisionBranch(active?.binding, mutation.expected) || mutation.kind === "clear" && (!ownsGeneration || mutation.threadId !== void 0 && active?.binding.threadId !== mutation.threadId || active?.binding.connectionScope === "supervision")) return { result: false };
|
|
646
648
|
if (mutation.kind === "clear" && retiredGeneration) return { result: true };
|
|
647
649
|
if (mutation.kind === "clear") return {
|
|
648
650
|
result: true,
|
|
@@ -798,10 +800,6 @@ function matchesPendingSupervisionBranch(binding, expected) {
|
|
|
798
800
|
function isSameSupervisionOwner(current, replacement) {
|
|
799
801
|
return replacement.connectionScope === "supervision" && replacement.threadId === current.threadId && replacement.supervisionSourceThreadId === current.supervisionSourceThreadId;
|
|
800
802
|
}
|
|
801
|
-
function matchesPendingSupervisionClear(binding, threadId, expected) {
|
|
802
|
-
if (!expected || threadId !== expected.sourceThreadId) return false;
|
|
803
|
-
return !binding || binding.connectionScope === "supervision" && binding.supervisionSourceThreadId === expected.sourceThreadId && matchesPendingSupervisionBranch(binding, expected);
|
|
804
|
-
}
|
|
805
803
|
/** Stable plugin-state key for one current binding owner. */
|
|
806
804
|
function bindingStoreKey(identity) {
|
|
807
805
|
if (identity.kind === "session") {
|
|
@@ -944,4 +942,4 @@ function normalizeCodexAppServerBindingModelProvider(params) {
|
|
|
944
942
|
return modelProvider;
|
|
945
943
|
}
|
|
946
944
|
//#endregion
|
|
947
|
-
export { hashCodexAppServerBindingFingerprint as a, reclaimCurrentCodexSessionGeneration as c, sessionBindingIdentity as d, session_binding_exports as f, createCodexSessionGenerationSupersededError as i, resolveCodexRunSessionBindingAuthority as l, assertCodexBindingMayBeReplaced as n, isCodexAppServerNativeAuthProfile as o, bindingStoreKey as r, normalizeCodexAppServerBindingModelProvider as s, CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS as t, scopeCodexRunBindingStore as u };
|
|
945
|
+
export { hashCodexAppServerBindingFingerprint as a, reclaimCurrentCodexSessionGeneration as c, sessionBindingIdentity as d, session_binding_exports as f, createCodexSessionGenerationSupersededError as i, resolveCodexRunSessionBindingAuthority as l, assertCodexBindingMayBeReplaced as n, isCodexAppServerNativeAuthProfile as o, validateBindingForWrite as p, bindingStoreKey as r, normalizeCodexAppServerBindingModelProvider as s, CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS as t, scopeCodexRunBindingStore as u };
|
|
@@ -1,24 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity } from "./session-binding-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { n as
|
|
7
|
-
import {
|
|
8
|
-
import { i as
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
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";
|
|
1
|
+
import { $t as isJsonObject, Jt as readCodexSessionMeta, K as resolveCodexAppServerClientInstanceId, Nt as withTimeout, Vt as resolveCodexAppServerAuthProfileStore, Wt as resolveCodexAppServerPreparedAuthHandoff, Xt as CODEX_INTERACTIVE_THREAD_SOURCE_KINDS, Yt as CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES, Z as assertCodexThreadForkParams, c as getLeasedSharedCodexAppServerClient, h as releaseLeasedSharedCodexAppServerClient, q as CodexAppServerRpcError, qt as isOpenClawManagedCodexThread, y as retireSharedCodexAppServerClientIfCurrent, zt as resolveCodexAppServerAuthProfileId } from "./shared-client-DxcfF9KX.js";
|
|
2
|
+
import { E as readCodexPluginConfig, F as resolveCodexAppServerHomeDir, I as resolveCodexAppServerLocalHomeDir, L as resolveCodexAppServerUserHomeDir, i as resolveCodexAppServerRuntimeOptions, s as resolveCodexSupervisionAppServerRuntimeOptions } from "./config-BhmfC1s6.js";
|
|
3
|
+
import { c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity } from "./session-binding-BHuTCRZQ.js";
|
|
4
|
+
import { a as closeCodexStartupClientBestEffort } from "./attempt-client-cleanup-DYHcRQAa.js";
|
|
5
|
+
import { n as listCodexAppServerModels } from "./models-sYnEc0gd.js";
|
|
6
|
+
import { a as replaceCodexCatalogConnectionHomes, n as buildCodexAppServerConnectionFingerprint, t as resumeCodexAppServerThread } from "./thread-resume-C7pyVKeW.js";
|
|
7
|
+
import { g as codexCatalogHomeId, h as canonicalCodexCatalogHome, m as projectCodexUserItemText, r as importCodexThreadHistoryToTranscript } from "./transcript-mirror-DTUxFWa_.js";
|
|
8
|
+
import { i as requestCodexAppServerJson, o as withCodexAppServerJsonClient, r as requestCodexAppServerClientJson } from "./request-DYAI5FQE.js";
|
|
9
|
+
import { n as describeControlFailure, t as CODEX_CONTROL_METHODS } from "./capabilities-dIjNVCYH.js";
|
|
10
|
+
import { a as formatCodexDisplayText } from "./command-formatters-CLHhEB1Q.js";
|
|
13
11
|
import { n as createCodexCliNodeConversationBindingData } from "./conversation-binding-data-BiodpIzq.js";
|
|
14
12
|
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-
|
|
13
|
+
import { i as createImportedCodexSession, n as codexUpstreamBaseline, r as codexUpstreamContinueResult, t as codexLastTerminalTurnId } from "./session-upstream-marker-C351-5Qw.js";
|
|
16
14
|
import { asFiniteNumber, isRecord, normalizeBoundedOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
17
15
|
import fs from "node:fs/promises";
|
|
18
16
|
import path from "node:path";
|
|
19
17
|
import { timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
|
|
20
18
|
import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/temp-path";
|
|
21
19
|
import { prepareAgentRuntimeAuth } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
20
|
+
import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
|
|
22
21
|
import fsSync from "node:fs";
|
|
23
22
|
import os from "node:os";
|
|
24
23
|
import { listAgentIds, resolveAgentDir as resolveAgentDir$1, resolveAgentWorkspaceDir, resolveAllowedModelRef, resolveDefaultAgentDir, resolveDefaultAgentId, resolveDefaultModelForAgent } from "openclaw/plugin-sdk/agent-runtime";
|
|
@@ -34,8 +33,7 @@ import process$1 from "node:process";
|
|
|
34
33
|
import { resolveSessionModelRef } from "openclaw/plugin-sdk/model-session-runtime";
|
|
35
34
|
import { resolveApiKeyForProvider } from "openclaw/plugin-sdk/provider-auth-runtime";
|
|
36
35
|
import { createSessionCatalogAdoptionCoordinator, listSessionCatalogEntries, sessionCatalogAdoptedSessionKey, sessionCatalogAdoptedSourceKey } from "openclaw/plugin-sdk/session-catalog";
|
|
37
|
-
import { decodeNodePtyResumeParams, resolveNodeHostExecutable, runNodePtyCommand } from "openclaw/plugin-sdk/node-host";
|
|
38
|
-
import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
|
|
36
|
+
import { decodeNodePtyResumeParams, decodeNodePtyStartParams, resolveNodeHostExecutable, runNodePtyCommand } from "openclaw/plugin-sdk/node-host";
|
|
39
37
|
//#region extensions/codex/src/jsonl-lines.ts
|
|
40
38
|
const JSONL_STREAM_THRESHOLD_BYTES = 4194304;
|
|
41
39
|
const JSONL_READ_CHUNK_BYTES = 1048576;
|
|
@@ -650,6 +648,7 @@ async function codexControlRequest(pluginConfig, method, requestParams, options
|
|
|
650
648
|
const auth = await prepareControlAuth(options, startOptions);
|
|
651
649
|
const controlRequestOptions = {
|
|
652
650
|
timeoutMs: options.timeoutMs ?? runtime.requestTimeoutMs,
|
|
651
|
+
assertCurrent: options.assertCurrent,
|
|
653
652
|
startOptions,
|
|
654
653
|
config: options.config,
|
|
655
654
|
sessionKey: options.sessionKey,
|
|
@@ -659,7 +658,7 @@ async function codexControlRequest(pluginConfig, method, requestParams, options
|
|
|
659
658
|
...auth.clientOptions
|
|
660
659
|
};
|
|
661
660
|
if (options.onResponse || options.beforeRequest) return await withCodexAppServerJsonClient(controlRequestOptions, async (request, client, scope) => {
|
|
662
|
-
await options.beforeRequest?.(request);
|
|
661
|
+
await options.beforeRequest?.(request, client, scope);
|
|
663
662
|
scope.assertCurrent();
|
|
664
663
|
let response;
|
|
665
664
|
if (method === "thread/resume") {
|
|
@@ -1297,54 +1296,26 @@ async function findAdoptedSessionEntry(params) {
|
|
|
1297
1296
|
const adopted = await listAdoptedSessionEntries(params);
|
|
1298
1297
|
return adopted.get(sessionCatalogAdoptedSourceKey(params.sourceHomeId ?? "gateway:local", params.threadId)) ?? (params.sourceHomeId && params.allowLegacy === true ? adopted.get(sessionCatalogAdoptedSourceKey("gateway:local", params.threadId)) : void 0);
|
|
1299
1298
|
}
|
|
1300
|
-
async function clearCreatedAdoptionBinding(params) {
|
|
1301
|
-
let cleared = false;
|
|
1302
|
-
let clearError;
|
|
1303
|
-
try {
|
|
1304
|
-
cleared = await params.bindingStore.mutate(params.identity, {
|
|
1305
|
-
kind: "clear",
|
|
1306
|
-
threadId: params.sourceThreadId,
|
|
1307
|
-
expectedPendingSupervisionBranch: params.expectedPending
|
|
1308
|
-
});
|
|
1309
|
-
} catch (error) {
|
|
1310
|
-
clearError = error;
|
|
1311
|
-
}
|
|
1312
|
-
if (cleared) return;
|
|
1313
|
-
let current;
|
|
1314
|
-
try {
|
|
1315
|
-
current = await params.bindingStore.read(params.identity);
|
|
1316
|
-
} catch (readError) {
|
|
1317
|
-
throw new AggregateError([
|
|
1318
|
-
params.cause,
|
|
1319
|
-
...clearError ? [clearError] : [],
|
|
1320
|
-
readError
|
|
1321
|
-
], `OpenClaw session creation failed and the Codex binding could not be verified for ${params.sourceThreadId}`, { cause: readError });
|
|
1322
|
-
}
|
|
1323
|
-
if (!matchesPendingSupervisionOwner(current, params.expectedPending)) return;
|
|
1324
|
-
throw new AggregateError([params.cause, ...clearError ? [clearError] : []], `OpenClaw session creation failed and the Codex binding could not be cleared for ${params.sourceThreadId}`, { cause: params.cause });
|
|
1325
|
-
}
|
|
1326
1299
|
function matchesPendingAdoptionBinding(binding, expected) {
|
|
1327
1300
|
const historyCoveredThrough = binding?.historyCoveredThrough;
|
|
1328
1301
|
return binding?.threadId === expected.sourceThreadId && binding.connectionScope === "supervision" && binding.supervisionSourceThreadId === expected.sourceThreadId && binding.cwd === expected.cwd && binding.conversationSourceTransferComplete === true && binding.preserveNativeModel === true && binding.pendingSupervisionBranch?.sourceThreadId === expected.sourceThreadId && binding.pendingSupervisionBranch.connectionFingerprint === expected.connectionFingerprint && binding.pendingSupervisionBranch.lastTurnId === expected.lastTurnId && (binding.pendingSupervisionBranch.cleanupThreadIds?.length ?? 0) === 0 && typeof historyCoveredThrough === "string" && Number.isFinite(Date.parse(historyCoveredThrough));
|
|
1329
1302
|
}
|
|
1330
|
-
function matchesPendingSupervisionOwner(binding, expected) {
|
|
1331
|
-
const pending = binding?.pendingSupervisionBranch;
|
|
1332
|
-
const cleanupThreadIds = pending?.cleanupThreadIds ?? [];
|
|
1333
|
-
const expectedCleanupThreadIds = expected.cleanupThreadIds ?? [];
|
|
1334
|
-
return binding?.threadId === expected.sourceThreadId && binding.connectionScope === "supervision" && binding.supervisionSourceThreadId === expected.sourceThreadId && pending?.sourceThreadId === expected.sourceThreadId && pending.connectionFingerprint === expected.connectionFingerprint && pending.lastTurnId === expected.lastTurnId && cleanupThreadIds.length === expectedCleanupThreadIds.length && cleanupThreadIds.every((threadId, index) => threadId === expectedCleanupThreadIds[index]);
|
|
1335
|
-
}
|
|
1336
1303
|
async function ensurePendingAdoptionBinding(params) {
|
|
1337
1304
|
const pending = {
|
|
1338
1305
|
sourceThreadId: params.sourceThreadId,
|
|
1339
1306
|
connectionFingerprint: params.connectionFingerprint,
|
|
1340
1307
|
...params.lastTurnId ? { lastTurnId: params.lastTurnId } : {}
|
|
1341
1308
|
};
|
|
1342
|
-
|
|
1309
|
+
const ownsGeneration = await reclaimCurrentCodexSessionGeneration({
|
|
1310
|
+
assertCurrent: params.initialization.assertCurrent,
|
|
1343
1311
|
bindingStore: params.bindingStore,
|
|
1344
1312
|
identity: params.identity,
|
|
1345
1313
|
config: params.config
|
|
1346
|
-
})
|
|
1314
|
+
});
|
|
1315
|
+
params.initialization.assertCurrent();
|
|
1316
|
+
if (!ownsGeneration) throw new Error(`failed to claim the OpenClaw session generation for ${params.sourceThreadId}`);
|
|
1347
1317
|
const existing = await params.bindingStore.read(params.identity);
|
|
1318
|
+
params.initialization.assertCurrent();
|
|
1348
1319
|
if (existing) {
|
|
1349
1320
|
if (matchesPendingAdoptionBinding(existing, params)) return;
|
|
1350
1321
|
throw new Error(`OpenClaw session is already bound to Codex thread ${existing.threadId}`);
|
|
@@ -1359,19 +1330,7 @@ async function ensurePendingAdoptionBinding(params) {
|
|
|
1359
1330
|
preserveNativeModel: true,
|
|
1360
1331
|
pendingSupervisionBranch: pending
|
|
1361
1332
|
};
|
|
1362
|
-
|
|
1363
|
-
try {
|
|
1364
|
-
stored = await params.bindingStore.mutate(params.identity, {
|
|
1365
|
-
kind: "set",
|
|
1366
|
-
if: { kind: "absent" },
|
|
1367
|
-
binding
|
|
1368
|
-
});
|
|
1369
|
-
} catch (error) {
|
|
1370
|
-
if (matchesPendingAdoptionBinding(await params.bindingStore.read(params.identity), params)) return;
|
|
1371
|
-
throw error;
|
|
1372
|
-
}
|
|
1373
|
-
if (stored) return;
|
|
1374
|
-
if (!matchesPendingAdoptionBinding(await params.bindingStore.read(params.identity), params)) throw new Error(`failed to bind OpenClaw session to Codex thread ${params.sourceThreadId}`);
|
|
1333
|
+
await params.initialization.bind(binding);
|
|
1375
1334
|
}
|
|
1376
1335
|
async function createOrReuseAdoptedSession(params) {
|
|
1377
1336
|
const runtime = params.api.runtime;
|
|
@@ -1382,8 +1341,6 @@ async function createOrReuseAdoptedSession(params) {
|
|
|
1382
1341
|
};
|
|
1383
1342
|
const existing = await findAdoptedSessionEntry(lookup);
|
|
1384
1343
|
if (existing) return existing;
|
|
1385
|
-
let createdBindingIdentity;
|
|
1386
|
-
let createdPendingBinding;
|
|
1387
1344
|
try {
|
|
1388
1345
|
const spawnedCwd = params.sourceThread.cwd?.trim() || void 0;
|
|
1389
1346
|
const pendingLastTurnId = codexLastTerminalTurnId(params.sourceThread, boundCatalogSessionId);
|
|
@@ -1393,6 +1350,7 @@ async function createOrReuseAdoptedSession(params) {
|
|
|
1393
1350
|
};
|
|
1394
1351
|
const created = await createImportedCodexSession({
|
|
1395
1352
|
runtime: params.api.runtime,
|
|
1353
|
+
bindingStore: params.bindingStore,
|
|
1396
1354
|
config: params.config,
|
|
1397
1355
|
key: adoptionSessionKey(params.sourceThread.id, params.sourceHomeId),
|
|
1398
1356
|
agentId: params.agentId,
|
|
@@ -1409,21 +1367,17 @@ async function createOrReuseAdoptedSession(params) {
|
|
|
1409
1367
|
modelLocked: true
|
|
1410
1368
|
} } }
|
|
1411
1369
|
},
|
|
1412
|
-
afterImport: async (entry) => {
|
|
1413
|
-
|
|
1370
|
+
afterImport: async (entry, initialization) => {
|
|
1371
|
+
const identity = sessionBindingIdentity({
|
|
1414
1372
|
sessionId: entry.sessionId,
|
|
1415
1373
|
sessionKey: entry.key,
|
|
1416
1374
|
config: params.config
|
|
1417
1375
|
});
|
|
1418
|
-
createdPendingBinding = {
|
|
1419
|
-
sourceThreadId: params.sourceThread.id,
|
|
1420
|
-
connectionFingerprint: params.connectionFingerprint,
|
|
1421
|
-
...pendingLastTurnId ? { lastTurnId: pendingLastTurnId } : {}
|
|
1422
|
-
};
|
|
1423
1376
|
await ensurePendingAdoptionBinding({
|
|
1424
1377
|
bindingStore: params.bindingStore,
|
|
1425
1378
|
config: params.config,
|
|
1426
|
-
identity
|
|
1379
|
+
identity,
|
|
1380
|
+
initialization,
|
|
1427
1381
|
sourceThreadId: params.sourceThread.id,
|
|
1428
1382
|
connectionFingerprint: params.connectionFingerprint,
|
|
1429
1383
|
cwd: spawnedCwd ?? "",
|
|
@@ -1442,19 +1396,8 @@ async function createOrReuseAdoptedSession(params) {
|
|
|
1442
1396
|
boundThreadId: params.sourceThread.id
|
|
1443
1397
|
};
|
|
1444
1398
|
} catch (error) {
|
|
1445
|
-
|
|
1399
|
+
const raced = await findAdoptedSessionEntry(lookup);
|
|
1446
1400
|
if (raced) return raced;
|
|
1447
|
-
if (createdBindingIdentity && createdPendingBinding) {
|
|
1448
|
-
await clearCreatedAdoptionBinding({
|
|
1449
|
-
bindingStore: params.bindingStore,
|
|
1450
|
-
identity: createdBindingIdentity,
|
|
1451
|
-
sourceThreadId: params.sourceThread.id,
|
|
1452
|
-
expectedPending: createdPendingBinding,
|
|
1453
|
-
cause: error
|
|
1454
|
-
});
|
|
1455
|
-
raced = await findAdoptedSessionEntry(lookup);
|
|
1456
|
-
if (raced) return raced;
|
|
1457
|
-
}
|
|
1458
1401
|
throw error;
|
|
1459
1402
|
}
|
|
1460
1403
|
}
|
|
@@ -1627,7 +1570,8 @@ async function listPairedNode(params) {
|
|
|
1627
1570
|
label: nodeLabel(params.node),
|
|
1628
1571
|
kind: "node",
|
|
1629
1572
|
nodeId: params.node.nodeId,
|
|
1630
|
-
canContinueCodex: canContinueCodexOnNode(params.node)
|
|
1573
|
+
canContinueCodex: canContinueCodexOnNode(params.node),
|
|
1574
|
+
...params.terminalCapabilities
|
|
1631
1575
|
};
|
|
1632
1576
|
if (params.node.connected !== true) {
|
|
1633
1577
|
const host = {
|
|
@@ -1642,6 +1586,15 @@ async function listPairedNode(params) {
|
|
|
1642
1586
|
params.onHost?.(host);
|
|
1643
1587
|
return host;
|
|
1644
1588
|
}
|
|
1589
|
+
if (!params.node.commands?.includes("codex.appServer.threads.list.v1")) {
|
|
1590
|
+
const host = {
|
|
1591
|
+
...common,
|
|
1592
|
+
connected: true,
|
|
1593
|
+
sessions: []
|
|
1594
|
+
};
|
|
1595
|
+
params.onHost?.(host);
|
|
1596
|
+
return host;
|
|
1597
|
+
}
|
|
1645
1598
|
const eventualHost = Promise.resolve().then(async () => {
|
|
1646
1599
|
const page = filterCatalogPageByTitle(parseCatalogPage(unwrapNodeInvokePayload(await params.runtime.nodes.invoke({
|
|
1647
1600
|
nodeId: params.node.nodeId,
|
|
@@ -1839,6 +1792,33 @@ async function continueNodeCodexSession(params) {
|
|
|
1839
1792
|
//#endregion
|
|
1840
1793
|
//#region extensions/codex/src/session-catalog-terminal.ts
|
|
1841
1794
|
const CODEX_TERMINAL_RESUME_COMMAND = "codex.terminal.resume.v1";
|
|
1795
|
+
const CODEX_TERMINAL_START_COMMAND = "codex.terminal.start.v1";
|
|
1796
|
+
function createCodexTerminalStartNodeHostCommand() {
|
|
1797
|
+
return {
|
|
1798
|
+
command: CODEX_TERMINAL_START_COMMAND,
|
|
1799
|
+
cap: CODEX_APP_SERVER_THREADS_CAPABILITY,
|
|
1800
|
+
dangerous: false,
|
|
1801
|
+
duplex: true,
|
|
1802
|
+
isAvailable: ({ env }) => Boolean(resolveNodeHostExecutable("codex", {
|
|
1803
|
+
env,
|
|
1804
|
+
strategy: "direct"
|
|
1805
|
+
})),
|
|
1806
|
+
handle: async (paramsJSON, io) => {
|
|
1807
|
+
if (!io) throw new Error("Codex terminal command requires duplex transport");
|
|
1808
|
+
const params = decodeNodePtyStartParams(paramsJSON);
|
|
1809
|
+
const resolution = resolveNodeHostExecutable("codex", { strategy: "direct" });
|
|
1810
|
+
if (!resolution) throw new Error("Codex CLI is unavailable; install codex on this node and reconnect");
|
|
1811
|
+
return JSON.stringify(await runNodePtyCommand({
|
|
1812
|
+
file: resolution.executable,
|
|
1813
|
+
args: params.initialMessage !== void 0 ? ["--", params.initialMessage] : [],
|
|
1814
|
+
cwd: params.cwd,
|
|
1815
|
+
requiredCwd: true,
|
|
1816
|
+
cols: params.cols,
|
|
1817
|
+
rows: params.rows
|
|
1818
|
+
}, io));
|
|
1819
|
+
}
|
|
1820
|
+
};
|
|
1821
|
+
}
|
|
1842
1822
|
function resolveCodexCatalogTerminalHome(sources) {
|
|
1843
1823
|
const runtimeConfig = sources.getRuntimeConfig();
|
|
1844
1824
|
if (!runtimeConfig) throw new Error("OpenClaw runtime config is unavailable");
|
|
@@ -1858,7 +1838,10 @@ function resolveLocalCodexTerminalResolution(env = process.env) {
|
|
|
1858
1838
|
}
|
|
1859
1839
|
function codexNodeTerminalCapability(node) {
|
|
1860
1840
|
const commands = node.invocableCommands ?? node.commands;
|
|
1861
|
-
return
|
|
1841
|
+
return {
|
|
1842
|
+
canOpenTerminalCodex: node.connected === true && commands?.includes("codex.terminal.resume.v1") === true,
|
|
1843
|
+
canStartTerminal: node.connected === true && node.invocableCommands?.includes("codex.terminal.start.v1") === true
|
|
1844
|
+
};
|
|
1862
1845
|
}
|
|
1863
1846
|
function createCodexTerminalNodeHostCommand(bindRequest, configSources) {
|
|
1864
1847
|
return {
|
|
@@ -1972,7 +1955,17 @@ async function openCodexCatalogTerminal(params) {
|
|
|
1972
1955
|
};
|
|
1973
1956
|
}
|
|
1974
1957
|
async function startCodexCatalogTerminal(params) {
|
|
1975
|
-
if (params.nodeId)
|
|
1958
|
+
if (params.nodeId) return {
|
|
1959
|
+
kind: "node",
|
|
1960
|
+
nodeId: params.nodeId,
|
|
1961
|
+
command: CODEX_TERMINAL_START_COMMAND,
|
|
1962
|
+
paramsJSON: JSON.stringify({
|
|
1963
|
+
cwd: params.cwd,
|
|
1964
|
+
initialMessage: params.initialMessage
|
|
1965
|
+
}),
|
|
1966
|
+
cwd: params.cwd,
|
|
1967
|
+
title: "codex"
|
|
1968
|
+
};
|
|
1976
1969
|
const resolution = resolveLocalCodexTerminalResolution();
|
|
1977
1970
|
if (!resolution) throw new CatalogParamsError("Codex CLI is unavailable; install Codex or add codex to PATH, then try again");
|
|
1978
1971
|
return {
|
|
@@ -2107,13 +2100,14 @@ async function listCodexSessionCatalog(params) {
|
|
|
2107
2100
|
if (!(!requestedHostIds || query.hostIds?.some((hostId) => hostId.startsWith("node:")))) return { hosts: await Promise.all(localHosts) };
|
|
2108
2101
|
let nodes;
|
|
2109
2102
|
try {
|
|
2110
|
-
nodes = (await (params.listNodes?.() ?? params.runtime.nodes.list())).nodes.filter((node) => node.gatewayLocal !== true && node.commands?.includes("codex.appServer.threads.list.v1") && (!requestedHostIds || requestedHostIds.has(`node:${node.nodeId}`))).slice(0, 100 - localHosts.length);
|
|
2103
|
+
nodes = (await (params.listNodes?.() ?? params.runtime.nodes.list())).nodes.filter((node) => node.gatewayLocal !== true && (node.commands?.includes("codex.appServer.threads.list.v1") || codexNodeTerminalCapability(node).canStartTerminal) && (!requestedHostIds || requestedHostIds.has(`node:${node.nodeId}`))).slice(0, 100 - localHosts.length);
|
|
2111
2104
|
} catch (error) {
|
|
2112
2105
|
const registryHost = {
|
|
2113
2106
|
hostId: "node:registry",
|
|
2114
2107
|
label: "Paired nodes",
|
|
2115
2108
|
kind: "node",
|
|
2116
2109
|
connected: false,
|
|
2110
|
+
canStartTerminal: false,
|
|
2117
2111
|
sessions: [],
|
|
2118
2112
|
error: catalogError("NODE_LIST_FAILED", error)
|
|
2119
2113
|
};
|
|
@@ -2126,17 +2120,15 @@ async function listCodexSessionCatalog(params) {
|
|
|
2126
2120
|
runtime: params.runtime,
|
|
2127
2121
|
sessionEntries: params.sessionEntries
|
|
2128
2122
|
});
|
|
2129
|
-
const nodeHosts = nodes.toSorted(compareNodeLabels).map(
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
return Object.assign(host, codexNodeTerminalCapability(node));
|
|
2139
|
-
});
|
|
2123
|
+
const nodeHosts = nodes.toSorted(compareNodeLabels).map((node) => listPairedNode({
|
|
2124
|
+
agentId,
|
|
2125
|
+
runtime: params.runtime,
|
|
2126
|
+
node,
|
|
2127
|
+
query,
|
|
2128
|
+
adoptedSessions: adoptedNodeSessions,
|
|
2129
|
+
terminalCapabilities: codexNodeTerminalCapability(node),
|
|
2130
|
+
...params.onHost ? { onHost: params.onHost } : {}
|
|
2131
|
+
}));
|
|
2140
2132
|
return { hosts: await Promise.all([...localHosts, ...nodeHosts]) };
|
|
2141
2133
|
}
|
|
2142
2134
|
/** Builds the node-local read-only Codex app-server catalog command. */
|
|
@@ -2218,7 +2210,8 @@ function createCodexSessionCatalogNodeHostCommands(controlFactory, configSources
|
|
|
2218
2210
|
}
|
|
2219
2211
|
}
|
|
2220
2212
|
},
|
|
2221
|
-
createCodexTerminalNodeHostCommand(bindRequest, configSources)
|
|
2213
|
+
createCodexTerminalNodeHostCommand(bindRequest, configSources),
|
|
2214
|
+
createCodexTerminalStartNodeHostCommand()
|
|
2222
2215
|
];
|
|
2223
2216
|
}
|
|
2224
2217
|
function readNodeTranscriptParams(value) {
|
|
@@ -2586,18 +2579,19 @@ function createCodexCatalogRequestSnapshot(requestTimeoutMs, request) {
|
|
|
2586
2579
|
requestTimeoutMs,
|
|
2587
2580
|
listThreads: (params, timeoutMs) => request(CODEX_CONTROL_METHODS.listThreads, params, timeoutMs),
|
|
2588
2581
|
listThreadTurns: (params) => request(CODEX_CONTROL_METHODS.listThreadTurns, params),
|
|
2589
|
-
forkThread: (params) => request(CODEX_CONTROL_METHODS.forkThread, assertCodexThreadForkParams(params)),
|
|
2582
|
+
forkThread: (params, assertCurrent) => request(CODEX_CONTROL_METHODS.forkThread, assertCodexThreadForkParams(params), void 0, assertCurrent),
|
|
2590
2583
|
readThread: async (threadId, includeTurns, timeoutMs) => (await request(CODEX_CONTROL_METHODS.readThread, {
|
|
2591
2584
|
threadId,
|
|
2592
2585
|
includeTurns
|
|
2593
2586
|
}, timeoutMs)).thread,
|
|
2594
|
-
archiveThread: async (threadId) => {
|
|
2595
|
-
await request(CODEX_CONTROL_METHODS.archiveThread, { threadId });
|
|
2587
|
+
archiveThread: async (threadId, assertCurrent) => {
|
|
2588
|
+
await request(CODEX_CONTROL_METHODS.archiveThread, { threadId }, void 0, assertCurrent);
|
|
2596
2589
|
}
|
|
2597
2590
|
};
|
|
2598
2591
|
}
|
|
2599
2592
|
function createCodexSessionCatalogControlFromRequests(params) {
|
|
2600
2593
|
return {
|
|
2594
|
+
forkContext: params.forkContext,
|
|
2601
2595
|
...params.clientId ? { clientId: params.clientId } : {},
|
|
2602
2596
|
...params.connectionFingerprint ? { connectionFingerprint: params.connectionFingerprint } : {},
|
|
2603
2597
|
withPinnedConnection: params.withPinnedConnection,
|
|
@@ -2653,6 +2647,7 @@ function createCodexSessionCatalogControlFromRequests(params) {
|
|
|
2653
2647
|
};
|
|
2654
2648
|
return await withTimeout(verify(), requests.requestTimeoutMs, "Codex session eligibility could not be verified", unverified);
|
|
2655
2649
|
},
|
|
2650
|
+
retireConnection: params.retireConnection,
|
|
2656
2651
|
async listPage(pageParams) {
|
|
2657
2652
|
const limit = normalizeLimit(pageParams.limit, "limit");
|
|
2658
2653
|
const search = pageParams.searchTerm?.trim().toLocaleLowerCase() || void 0;
|
|
@@ -2714,11 +2709,11 @@ function createCodexSessionCatalogControlFromRequests(params) {
|
|
|
2714
2709
|
async listTurnPage(listParams) {
|
|
2715
2710
|
return await params.createRequestSnapshot().listThreadTurns(listParams);
|
|
2716
2711
|
},
|
|
2717
|
-
async forkThread(forkParams) {
|
|
2718
|
-
return await params.createRequestSnapshot().forkThread(forkParams);
|
|
2712
|
+
async forkThread(forkParams, assertCurrent) {
|
|
2713
|
+
return await params.createRequestSnapshot().forkThread(forkParams, assertCurrent);
|
|
2719
2714
|
},
|
|
2720
|
-
async archiveThread(threadId) {
|
|
2721
|
-
await params.createRequestSnapshot().archiveThread(threadId);
|
|
2715
|
+
async archiveThread(threadId, assertCurrent) {
|
|
2716
|
+
await params.createRequestSnapshot().archiveThread(threadId, assertCurrent);
|
|
2722
2717
|
}
|
|
2723
2718
|
};
|
|
2724
2719
|
}
|
|
@@ -2763,8 +2758,9 @@ function createCodexSessionCatalogControl(params) {
|
|
|
2763
2758
|
const pluginConfig = getPluginConfig();
|
|
2764
2759
|
const runtime = source?.appServer ?? resolveCodexSupervisionAppServerRuntimeOptions({ pluginConfig });
|
|
2765
2760
|
const requestOptions = resolveRequestOptions(runtime.start, agentId, source);
|
|
2766
|
-
return createCodexCatalogRequestSnapshot(runtime.requestTimeoutMs, async (method, requestParams, timeoutMs) => await codexControlRequest(pluginConfig, method, requestParams, {
|
|
2761
|
+
return createCodexCatalogRequestSnapshot(runtime.requestTimeoutMs, async (method, requestParams, timeoutMs, assertCurrent) => await codexControlRequest(pluginConfig, method, requestParams, {
|
|
2767
2762
|
...requestOptions,
|
|
2763
|
+
assertCurrent,
|
|
2768
2764
|
...timeoutMs === void 0 ? {} : { timeoutMs }
|
|
2769
2765
|
}));
|
|
2770
2766
|
};
|
|
@@ -2780,15 +2776,26 @@ function createCodexSessionCatalogControl(params) {
|
|
|
2780
2776
|
timeoutMs: runtime.requestTimeoutMs
|
|
2781
2777
|
});
|
|
2782
2778
|
try {
|
|
2783
|
-
const requests = createCodexCatalogRequestSnapshot(runtime.requestTimeoutMs, async (method, requestParams, timeoutMs) => await requestCodexAppServerClientJson({
|
|
2779
|
+
const requests = createCodexCatalogRequestSnapshot(runtime.requestTimeoutMs, async (method, requestParams, timeoutMs, assertCurrent) => await requestCodexAppServerClientJson({
|
|
2784
2780
|
client,
|
|
2785
2781
|
method,
|
|
2786
2782
|
requestParams,
|
|
2787
2783
|
config: runtimeConfig,
|
|
2788
|
-
timeoutMs: timeoutMs ?? runtime.requestTimeoutMs
|
|
2784
|
+
timeoutMs: timeoutMs ?? runtime.requestTimeoutMs,
|
|
2785
|
+
assertCurrent
|
|
2789
2786
|
}));
|
|
2790
2787
|
const pinnedControl = createCodexSessionCatalogControlFromRequests({
|
|
2788
|
+
forkContext: {
|
|
2789
|
+
client,
|
|
2790
|
+
appServer: runtime,
|
|
2791
|
+
pluginConfig,
|
|
2792
|
+
agentDir,
|
|
2793
|
+
localSessionsRoot: source?.localSessionsRoot
|
|
2794
|
+
},
|
|
2791
2795
|
clientId: resolveCodexAppServerClientInstanceId(client),
|
|
2796
|
+
retireConnection: () => {
|
|
2797
|
+
retireSharedCodexAppServerClientIfCurrent(client);
|
|
2798
|
+
},
|
|
2792
2799
|
connectionFingerprint: buildCodexAppServerConnectionFingerprint(runtime, agentDir),
|
|
2793
2800
|
createRequestSnapshot: () => requests,
|
|
2794
2801
|
...source?.localSessionsRoot ? { localSessionsRoot: source.localSessionsRoot } : {},
|
|
@@ -2884,14 +2891,21 @@ function createCodexSessionCatalogNodeInvokePolicies() {
|
|
|
2884
2891
|
commands: [
|
|
2885
2892
|
CODEX_APP_SERVER_THREADS_LIST_COMMAND,
|
|
2886
2893
|
CODEX_APP_SERVER_THREAD_TURNS_LIST_COMMAND,
|
|
2887
|
-
CODEX_TERMINAL_RESUME_COMMAND
|
|
2894
|
+
CODEX_TERMINAL_RESUME_COMMAND,
|
|
2895
|
+
CODEX_TERMINAL_START_COMMAND
|
|
2888
2896
|
],
|
|
2889
2897
|
defaultPlatforms: [
|
|
2890
2898
|
"macos",
|
|
2891
2899
|
"linux",
|
|
2892
2900
|
"windows"
|
|
2893
2901
|
],
|
|
2894
|
-
handle: (context) =>
|
|
2902
|
+
handle: (context) => {
|
|
2903
|
+
if (context.command === "codex.terminal.start.v1") return context.client?.scopes?.includes("operator.admin") && context.config.gateway?.cliAgents?.enabled === true && context.config.gateway?.terminal?.enabled !== false ? { ok: true } : {
|
|
2904
|
+
ok: false,
|
|
2905
|
+
message: "Native terminal start requires operator.admin and enabled CLI agents and terminals"
|
|
2906
|
+
};
|
|
2907
|
+
return context.command === "codex.terminal.resume.v1" ? { ok: true } : context.invokeNode();
|
|
2908
|
+
}
|
|
2895
2909
|
}];
|
|
2896
2910
|
}
|
|
2897
2911
|
function toGenericCatalogHost(host, localTerminalAvailable) {
|
|
@@ -2981,8 +2995,11 @@ function registerCodexSessionCatalog(params) {
|
|
|
2981
2995
|
const localTerminalAvailable = resolveLocalCodexTerminalExecutable() !== void 0;
|
|
2982
2996
|
const { agentId: requestedAgentId, allowProcessHomeFallback, listNodes, onHost, sessionEntries, ...gatewayQuery } = query;
|
|
2983
2997
|
const agentId = resolveRequestAgentId(requestedAgentId);
|
|
2984
|
-
const mapHost = (host) => toGenericCatalogHost(host, localTerminalAvailable);
|
|
2985
2998
|
const localHomes = [...catalogHomes(agentId, allowProcessHomeFallback)];
|
|
2999
|
+
const mapHost = (host) => ({
|
|
3000
|
+
...toGenericCatalogHost(host, localTerminalAvailable),
|
|
3001
|
+
canStartTerminal: host.kind === "gateway" ? localTerminalAvailable && localHomes.some((home) => home.hostId === host.hostId && home.appServer.start.transport === "stdio") : host.canStartTerminal === true
|
|
3002
|
+
});
|
|
2986
3003
|
return (await listCodexSessionCatalog({
|
|
2987
3004
|
agentId,
|
|
2988
3005
|
bindingStore: params.bindingStore,
|
|
@@ -3077,11 +3094,16 @@ function registerCodexSessionCatalog(params) {
|
|
|
3077
3094
|
});
|
|
3078
3095
|
},
|
|
3079
3096
|
startTerminalSession: async (request) => {
|
|
3080
|
-
|
|
3097
|
+
const source = request.nodeId ? void 0 : resolveLocalCatalogHomeForThread({
|
|
3098
|
+
homes: [...catalogHomes(request.agentId, request.allowProcessHomeFallback)],
|
|
3099
|
+
hostId: request.hostId ?? "gateway:local"
|
|
3100
|
+
});
|
|
3101
|
+
if (source && source.appServer.start.transport !== "stdio") throw new CatalogParamsError("Native terminal start requires a local Codex source");
|
|
3081
3102
|
return await startCodexCatalogTerminal({
|
|
3082
3103
|
getPluginConfig: params.getPluginConfig,
|
|
3083
3104
|
getRuntimeConfig: params.getRuntimeConfig,
|
|
3084
|
-
...request
|
|
3105
|
+
...request,
|
|
3106
|
+
source
|
|
3085
3107
|
});
|
|
3086
3108
|
}
|
|
3087
3109
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./session-catalog-
|
|
1
|
+
import "./session-catalog-yyvTWFOw.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";
|