@openclaw/acpx 2026.9.7 → 2026.9.9
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/README.md +6 -0
- package/assets/icon.png +0 -0
- package/dist/.setup/{command-line-CPBLOiZM.mjs → command-line-B72femaL.mjs} +3 -6
- package/dist/.setup/{config-CdPsIued.mjs → config-Blz15uwJ.mjs} +15 -15
- package/dist/.setup/{pi-session-catalog-runtime-UhiQSaDw.mjs → pi-session-catalog-runtime-IKEanK3s.mjs} +20 -55
- package/dist/.setup/process-lease-n38HFGdp.mjs +311 -0
- package/dist/.setup/{register.runtime-Bm4HrMCp.mjs → register.runtime-DByczkH_.mjs} +15 -38
- package/dist/.setup/{service-DMae5pPH.mjs → service-D5hGWl5U.mjs} +78 -117
- package/dist/.setup/{session-owner-migration-CdJSYRk1.mjs → session-owner-migration-DsGrYq7Y.mjs} +132 -20
- package/dist/.setup/{session-resource-BaJ6bs5d.mjs → session-resource-B-4yPr-j.mjs} +1 -13
- package/dist/doctor-contract-api.js +13 -17
- package/dist/index.js +40 -20
- package/dist/register.runtime.js +1 -1
- package/package.json +7 -6
- package/skills/acp-router/SKILL.md +2 -2
- package/dist/.setup/process-lease-C3dNPtu8.mjs +0 -138
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getAcpRuntimeBackend, registerAcpRuntimeBackend, unregisterAcpRuntimeBackend } from "openclaw/plugin-sdk/acp-runtime-backend";
|
|
2
|
-
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
2
|
+
import { createLazyRuntimeMethodBinder, createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
3
3
|
//#region extensions/acpx/src/runtime-proxy.ts
|
|
4
4
|
/** Start an ACP turn through a lazy runtime resolver without awaiting resolution up front. */
|
|
5
5
|
function lazyStartRuntimeTurn(resolveRuntime, input) {
|
|
@@ -23,50 +23,27 @@ function lazyStartRuntimeTurn(resolveRuntime, input) {
|
|
|
23
23
|
}
|
|
24
24
|
/** Create an ACP runtime facade backed by an async runtime resolver. */
|
|
25
25
|
function createLazyAcpRuntimeProxy(resolveRuntime) {
|
|
26
|
+
const bind = createLazyRuntimeMethodBinder(resolveRuntime);
|
|
26
27
|
return {
|
|
27
28
|
ownerAwareSessions: 1,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
async shutdown() {
|
|
32
|
-
await (await resolveRuntime()).shutdown();
|
|
33
|
-
},
|
|
34
|
-
async ensureSession(input) {
|
|
35
|
-
return await (await resolveRuntime()).ensureSession(input);
|
|
36
|
-
},
|
|
29
|
+
findSession: bind((runtime) => runtime.findSession.bind(runtime)),
|
|
30
|
+
shutdown: bind((runtime) => runtime.shutdown.bind(runtime)),
|
|
31
|
+
ensureSession: bind((runtime) => runtime.ensureSession.bind(runtime)),
|
|
37
32
|
startTurn(input) {
|
|
38
33
|
return lazyStartRuntimeTurn(resolveRuntime, input);
|
|
39
34
|
},
|
|
40
35
|
async *runTurn(input) {
|
|
41
36
|
yield* (await resolveRuntime()).runTurn(input);
|
|
42
37
|
},
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
async setModel(input) {
|
|
53
|
-
await (await resolveRuntime()).setModel(input);
|
|
54
|
-
},
|
|
55
|
-
async setConfigOption(input) {
|
|
56
|
-
return await (await resolveRuntime()).setConfigOption(input);
|
|
57
|
-
},
|
|
58
|
-
async doctor() {
|
|
59
|
-
return await (await resolveRuntime()).doctor();
|
|
60
|
-
},
|
|
61
|
-
async prepareFreshSession(input) {
|
|
62
|
-
await (await resolveRuntime()).prepareFreshSession(input);
|
|
63
|
-
},
|
|
64
|
-
async cancel(input) {
|
|
65
|
-
await (await resolveRuntime()).cancel(input);
|
|
66
|
-
},
|
|
67
|
-
async close(input) {
|
|
68
|
-
await (await resolveRuntime()).close(input);
|
|
69
|
-
}
|
|
38
|
+
getCapabilities: bind((runtime) => runtime.getCapabilities.bind(runtime)),
|
|
39
|
+
getStatus: bind((runtime) => runtime.getStatus.bind(runtime)),
|
|
40
|
+
setMode: bind((runtime) => runtime.setMode.bind(runtime)),
|
|
41
|
+
setModel: bind((runtime) => runtime.setModel.bind(runtime)),
|
|
42
|
+
setConfigOption: bind((runtime) => runtime.setConfigOption.bind(runtime)),
|
|
43
|
+
doctor: bind((runtime) => runtime.doctor.bind(runtime)),
|
|
44
|
+
prepareFreshSession: bind((runtime) => runtime.prepareFreshSession.bind(runtime)),
|
|
45
|
+
cancel: bind((runtime) => runtime.cancel.bind(runtime)),
|
|
46
|
+
close: bind((runtime) => runtime.close.bind(runtime))
|
|
70
47
|
};
|
|
71
48
|
}
|
|
72
49
|
//#endregion
|
|
@@ -76,7 +53,7 @@ function createLazyAcpRuntimeProxy(resolveRuntime) {
|
|
|
76
53
|
* immediately, then imports the heavier service only when a session needs it.
|
|
77
54
|
*/
|
|
78
55
|
const ACPX_BACKEND_ID = "acpx";
|
|
79
|
-
const loadServiceModule = createLazyRuntimeModule(() => import("./service-
|
|
56
|
+
const loadServiceModule = createLazyRuntimeModule(() => import("./service-D5hGWl5U.mjs"));
|
|
80
57
|
function unregisterOwnedRuntime(runtime) {
|
|
81
58
|
if (runtime && getAcpRuntimeBackend(ACPX_BACKEND_ID)?.runtime === runtime) unregisterAcpRuntimeBackend(ACPX_BACKEND_ID);
|
|
82
59
|
}
|
|
@@ -1,31 +1,29 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import { i as toAcpMcpServers, n as resolveAcpxPluginRoot, r as resolveOpenClawRoot, t as resolveAcpxPluginConfig } from "./config-
|
|
3
|
-
import { a as
|
|
4
|
-
import { a as hashAcpxProcessCommand, c as openAcpxProcessLeaseStateStore, d as ACPX_GATEWAY_INSTANCE_KEY, f as ACPX_GATEWAY_INSTANCE_NAMESPACE, h as normalizeAcpxGatewayInstanceRecord, i as createAcpxProcessLeaseStore, l as readAcpxProcessLeaseIdentity, n as OPENCLAW_ACPX_LEASE_ID_ARG, r as OPENCLAW_GATEWAY_INSTANCE_ID_ARG, t as ACPX_PROBE_LEASE_SESSION_KEY, u as withAcpxLeaseArgs } from "./process-lease-C3dNPtu8.mjs";
|
|
1
|
+
import { a as hashAcpxProcessCommand, c as openAcpxProcessLeaseStateStore, d as ACPX_GATEWAY_INSTANCE_KEY, f as ACPX_GATEWAY_INSTANCE_NAMESPACE, h as normalizeAcpxGatewayInstanceRecord, i as createAcpxProcessLeaseStore, l as readAcpxProcessLeaseIdentity, n as OPENCLAW_ACPX_LEASE_ID_ARG, r as OPENCLAW_GATEWAY_INSTANCE_ID_ARG, t as ACPX_PROBE_LEASE_SESSION_KEY, u as withAcpxLeaseArgs } from "./process-lease-n38HFGdp.mjs";
|
|
2
|
+
import { i as toAcpMcpServers, n as resolveAcpxPluginRoot, r as resolveOpenClawRoot, t as resolveAcpxPluginConfig } from "./config-Blz15uwJ.mjs";
|
|
3
|
+
import { a as resolveAgentCommand, c as CODEX_ACP_PACKAGE, i as renderAgentCommand, l as LEGACY_CODEX_ACP_PACKAGE, n as isCodexAcpCommand, o as splitCommandParts, r as isOpenClawBridgeCommand, s as CODEX_ACP_BIN, t as isClaudeAcpCommand, u as OPENCLAW_CODEX_CONFIG_ARG } from "./command-line-B72femaL.mjs";
|
|
5
4
|
import { AcpRuntimeError } from "../runtime-api.js";
|
|
5
|
+
import { t as resolveAcpxSessionResource } from "./session-resource-B-4yPr-j.mjs";
|
|
6
|
+
import { adoptAcpxStateDirectory } from "./session-owner-migration-DsGrYq7Y.mjs";
|
|
6
7
|
import { createRequire } from "node:module";
|
|
7
8
|
import { AcpxRuntime, createAgentRegistry, createFileSessionStore, decodeAcpxRuntimeHandleState, isRequestedModelUnsupportedError } from "acpx/runtime";
|
|
8
9
|
import { finiteSecondsToTimerSafeMilliseconds, parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
9
10
|
import fs from "node:fs";
|
|
10
11
|
import path, { resolve } from "node:path";
|
|
11
|
-
import { isRecord, normalizeLowercaseStringOrEmpty, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
12
|
+
import { asOptionalObjectRecord, isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
12
13
|
import os, { availableParallelism } from "node:os";
|
|
13
14
|
import fs$1 from "node:fs/promises";
|
|
14
15
|
import { randomUUID } from "node:crypto";
|
|
15
16
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
16
17
|
import { escapeRegExp, sliceUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
17
|
-
import {
|
|
18
|
+
import { tryReadJson } from "@openclaw/fs-safe/json";
|
|
18
19
|
import { parse, stringify } from "smol-toml";
|
|
20
|
+
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
19
21
|
import { isPidAlive, runExec } from "openclaw/plugin-sdk/process-runtime";
|
|
20
22
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
21
23
|
import { isDeepStrictEqual } from "node:util";
|
|
22
24
|
import { redactSensitiveText } from "openclaw/plugin-sdk/security-runtime";
|
|
23
25
|
import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
|
|
24
26
|
//#region extensions/acpx/src/codex-trust-config.ts
|
|
25
|
-
/**
|
|
26
|
-
* Builds isolated Codex config for ACPX sessions. It preserves safe inherited
|
|
27
|
-
* runtime options while rendering only trusted project entries for the session.
|
|
28
|
-
*/
|
|
29
27
|
function stripTomlComment(line) {
|
|
30
28
|
let quote = null;
|
|
31
29
|
let escaping = false;
|
|
@@ -97,10 +95,8 @@ function parseTomlDottedKey(value) {
|
|
|
97
95
|
return parts.map((part) => parseTomlString(part) ?? part);
|
|
98
96
|
}
|
|
99
97
|
function parseProjectHeader(line) {
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
const parts = parseTomlDottedKey(trimmed.slice(1, -1));
|
|
103
|
-
return parts.length === 2 && parts[0] === "projects" ? parts[1] : void 0;
|
|
98
|
+
const parts = parseTableHeader(line);
|
|
99
|
+
return parts?.length === 2 && parts[0] === "projects" ? parts[1] : void 0;
|
|
104
100
|
}
|
|
105
101
|
function parseTrustedInlineProjectEntries(value) {
|
|
106
102
|
const trusted = [];
|
|
@@ -113,7 +109,6 @@ function parseTrustedInlineProjectEntries(value) {
|
|
|
113
109
|
}
|
|
114
110
|
return trusted;
|
|
115
111
|
}
|
|
116
|
-
/** Extract trusted project paths from Codex TOML config. */
|
|
117
112
|
function extractTrustedCodexProjectPaths(configToml) {
|
|
118
113
|
const trusted = /* @__PURE__ */ new Set();
|
|
119
114
|
let currentProjectPath;
|
|
@@ -211,7 +206,6 @@ function extractInheritedCodexRuntimeConfig(configToml) {
|
|
|
211
206
|
while (inheritedLines.length > 0 && inheritedLines[inheritedLines.length - 1] === "") inheritedLines.pop();
|
|
212
207
|
return inheritedLines.join("\n");
|
|
213
208
|
}
|
|
214
|
-
/** Render a session-local Codex config with inherited runtime settings and trust entries. */
|
|
215
209
|
function renderIsolatedCodexConfig(params) {
|
|
216
210
|
const normalized = Array.from(new Set(params.projectPaths.map((projectPath) => projectPath.trim()).filter(Boolean).map((projectPath) => path.resolve(projectPath)))).toSorted((left, right) => left.localeCompare(right));
|
|
217
211
|
return [
|
|
@@ -258,8 +252,8 @@ function resolvePackageBinPath(packageJsonPath, manifest, binName) {
|
|
|
258
252
|
async function resolveInstalledAcpPackageBinPath(packageName, binName) {
|
|
259
253
|
try {
|
|
260
254
|
const packageJsonPath = requireFromHere$1.resolve(`${packageName}/package.json`);
|
|
261
|
-
const
|
|
262
|
-
if (manifest
|
|
255
|
+
const manifest = await tryReadJson(packageJsonPath);
|
|
256
|
+
if (manifest?.name !== packageName) return;
|
|
263
257
|
const binPath = resolvePackageBinPath(packageJsonPath, manifest, binName);
|
|
264
258
|
if (!binPath) return;
|
|
265
259
|
await fs$1.access(binPath);
|
|
@@ -268,12 +262,6 @@ async function resolveInstalledAcpPackageBinPath(packageName, binName) {
|
|
|
268
262
|
return;
|
|
269
263
|
}
|
|
270
264
|
}
|
|
271
|
-
async function resolveInstalledCodexAcpBinPath() {
|
|
272
|
-
return await resolveInstalledAcpPackageBinPath(CODEX_ACP_PACKAGE, CODEX_ACP_BIN);
|
|
273
|
-
}
|
|
274
|
-
async function resolveInstalledClaudeAcpBinPath() {
|
|
275
|
-
return await resolveInstalledAcpPackageBinPath(CLAUDE_ACP_PACKAGE, CLAUDE_ACP_BIN);
|
|
276
|
-
}
|
|
277
265
|
const DIAGNOSTIC_REDACTION_RULES = [
|
|
278
266
|
{
|
|
279
267
|
source: String.raw`(authorization\s*[:=]\s*bearer\s+)[^\s'"<>]+`,
|
|
@@ -595,7 +583,9 @@ const npmCliPath = resolveNpmCliPath();
|
|
|
595
583
|
const installedBinPath = ${params.installedBinPath ? JSON.stringify(params.installedBinPath) : "undefined"};
|
|
596
584
|
let defaultCommand;
|
|
597
585
|
let defaultArgs;
|
|
598
|
-
|
|
586
|
+
// Plugin capture/install directories are disposable: a durable wrapper can
|
|
587
|
+
// outlive the path it captured, so re-check the target before trusting it.
|
|
588
|
+
if (installedBinPath && existsSync(installedBinPath)) {
|
|
599
589
|
defaultCommand = process.execPath;
|
|
600
590
|
defaultArgs = [installedBinPath];
|
|
601
591
|
} else if (npmCliPath) {
|
|
@@ -858,13 +848,11 @@ function buildWrapperCommand(wrapperPath, args = []) {
|
|
|
858
848
|
];
|
|
859
849
|
}
|
|
860
850
|
function isAcpPackageSpec(value, packageName) {
|
|
861
|
-
|
|
862
|
-
return new RegExp(`^${escapedPackageName}(?:@.+)?$`, "i").test(value.trim());
|
|
851
|
+
return new RegExp(`^${escapeRegExp(packageName)}(?:@.+)?$`, "i").test(value.trim());
|
|
863
852
|
}
|
|
864
853
|
function isAcpBinName(value, binName) {
|
|
865
854
|
const commandName = basename(value);
|
|
866
|
-
|
|
867
|
-
return new RegExp(`^${escapedBinName}(?:\\.exe|\\.[cm]?js)?$`, "i").test(commandName);
|
|
855
|
+
return new RegExp(`^${escapeRegExp(binName)}(?:\\.exe|\\.[cm]?js)?$`, "i").test(commandName);
|
|
868
856
|
}
|
|
869
857
|
function isPackageRunnerCommand(value) {
|
|
870
858
|
return /^(?:npx|npm|pnpm|bunx)(?:\.cmd|\.exe)?$/i.test(basename(value));
|
|
@@ -974,7 +962,6 @@ function buildClaudeAcpWrapperCommand(wrapperPath, configuredCommand) {
|
|
|
974
962
|
}
|
|
975
963
|
/** Prepare ACPX agent commands and isolated auth homes for Codex/Claude adapters. */
|
|
976
964
|
async function prepareAcpxCodexAuthConfig(params) {
|
|
977
|
-
params.logger;
|
|
978
965
|
const codexBaseDir = path.join(params.stateDir, "acpx");
|
|
979
966
|
const configuredCodexCommand = params.pluginConfig.agents.codex;
|
|
980
967
|
const configuredClaudeCommand = params.pluginConfig.agents.claude;
|
|
@@ -986,8 +973,8 @@ async function prepareAcpxCodexAuthConfig(params) {
|
|
|
986
973
|
}),
|
|
987
974
|
migratedConfig: codexLaunch?.migratedConfig
|
|
988
975
|
});
|
|
989
|
-
const installedCodexBinPath = await (params.resolveInstalledCodexAcpBinPath
|
|
990
|
-
const installedClaudeBinPath = await (params.resolveInstalledClaudeAcpBinPath
|
|
976
|
+
const installedCodexBinPath = await (params.resolveInstalledCodexAcpBinPath ? params.resolveInstalledCodexAcpBinPath() : resolveInstalledAcpPackageBinPath(CODEX_ACP_PACKAGE, CODEX_ACP_BIN));
|
|
977
|
+
const installedClaudeBinPath = await (params.resolveInstalledClaudeAcpBinPath ? params.resolveInstalledClaudeAcpBinPath() : resolveInstalledAcpPackageBinPath(CLAUDE_ACP_PACKAGE, CLAUDE_ACP_BIN));
|
|
991
978
|
const wrapperPath = await writeAdapterWrapper(codexBaseDir, "codex-acp-wrapper.mjs", buildCodexAcpWrapperScript(installedCodexBinPath));
|
|
992
979
|
const claudeWrapperPath = await writeAdapterWrapper(codexBaseDir, "claude-agent-acp-wrapper.mjs", buildClaudeAcpWrapperScript(installedClaudeBinPath));
|
|
993
980
|
return {
|
|
@@ -1114,7 +1101,6 @@ function parseProcessList(stdout) {
|
|
|
1114
1101
|
}
|
|
1115
1102
|
return processes;
|
|
1116
1103
|
}
|
|
1117
|
-
/** List host processes in the compact shape needed by ACPX cleanup. */
|
|
1118
1104
|
async function listPlatformProcesses() {
|
|
1119
1105
|
if (process.platform === "win32") return [];
|
|
1120
1106
|
const { stdout } = await runExec("ps", ["-axo", "pid=,ppid=,command="], {
|
|
@@ -1148,9 +1134,7 @@ function uniquePids(processes) {
|
|
|
1148
1134
|
}
|
|
1149
1135
|
async function terminatePids(pids, deps) {
|
|
1150
1136
|
const killProcess = deps?.killProcess ?? ((pid, signal) => process.kill(pid, signal));
|
|
1151
|
-
const sleep = deps?.sleep ??
|
|
1152
|
-
setTimeout(resolve, ms);
|
|
1153
|
-
}));
|
|
1137
|
+
const sleep = deps?.sleep ?? setTimeout$1;
|
|
1154
1138
|
const terminated = [];
|
|
1155
1139
|
for (const pid of pids) {
|
|
1156
1140
|
deps?.assertCurrent?.();
|
|
@@ -1369,7 +1353,7 @@ var AcpxGenerationRegistry = class {
|
|
|
1369
1353
|
return generation.delegate;
|
|
1370
1354
|
}
|
|
1371
1355
|
currentGeneration(resource) {
|
|
1372
|
-
|
|
1356
|
+
this.assertRunning();
|
|
1373
1357
|
let generation = this.generations.get(resource);
|
|
1374
1358
|
if (!generation) {
|
|
1375
1359
|
const fresh = this.sessionStore.isFresh(resource);
|
|
@@ -1512,40 +1496,28 @@ function captureGenerationRecord(generation, record) {
|
|
|
1512
1496
|
const acpxGenerationKey = Symbol("openclaw.acpxGeneration");
|
|
1513
1497
|
const acpxOperationScope = new AsyncLocalStorage();
|
|
1514
1498
|
function readSessionRecordName(record) {
|
|
1515
|
-
|
|
1516
|
-
const { name } = record;
|
|
1517
|
-
return typeof name === "string" ? name.trim() : "";
|
|
1499
|
+
return normalizeOptionalString(asOptionalObjectRecord(record)?.name) ?? "";
|
|
1518
1500
|
}
|
|
1519
1501
|
function readRecordAgentCommand(record) {
|
|
1520
1502
|
return record?.agentArgv ?? record?.agentCommand;
|
|
1521
1503
|
}
|
|
1522
1504
|
function readRecordCwd(record) {
|
|
1523
|
-
|
|
1524
|
-
const { cwd } = record;
|
|
1525
|
-
return typeof cwd === "string" ? cwd.trim() || void 0 : void 0;
|
|
1505
|
+
return normalizeOptionalString(asOptionalObjectRecord(record)?.cwd);
|
|
1526
1506
|
}
|
|
1527
1507
|
function readRecordResetOnNextEnsure(record) {
|
|
1528
|
-
|
|
1529
|
-
const { acpx } = record;
|
|
1530
|
-
if (typeof acpx !== "object" || acpx === null) return false;
|
|
1531
|
-
return acpx.reset_on_next_ensure === true;
|
|
1508
|
+
return asOptionalObjectRecord(asOptionalObjectRecord(record)?.acpx)?.reset_on_next_ensure === true;
|
|
1532
1509
|
}
|
|
1533
1510
|
function readRecordAgentPid(record) {
|
|
1534
|
-
|
|
1535
|
-
const { pid, processId } = record;
|
|
1511
|
+
const { pid, processId } = asOptionalObjectRecord(record) ?? {};
|
|
1536
1512
|
const rawPid = pid ?? processId;
|
|
1537
1513
|
const numericPid = typeof rawPid === "number" ? rawPid : typeof rawPid === "string" ? parseStrictPositiveInteger(rawPid) : void 0;
|
|
1538
1514
|
return numericPid && Number.isInteger(numericPid) && numericPid > 0 ? numericPid : void 0;
|
|
1539
1515
|
}
|
|
1540
1516
|
function readOpenClawLeaseIdFromRecord(record) {
|
|
1541
|
-
|
|
1542
|
-
const { openclawLeaseId } = record;
|
|
1543
|
-
return typeof openclawLeaseId === "string" ? openclawLeaseId.trim() || void 0 : void 0;
|
|
1517
|
+
return normalizeOptionalString(asOptionalObjectRecord(record)?.openclawLeaseId);
|
|
1544
1518
|
}
|
|
1545
1519
|
function readOpenClawGatewayInstanceIdFromRecord(record) {
|
|
1546
|
-
|
|
1547
|
-
const { openclawGatewayInstanceId } = record;
|
|
1548
|
-
return typeof openclawGatewayInstanceId === "string" ? openclawGatewayInstanceId.trim() || void 0 : void 0;
|
|
1520
|
+
return normalizeOptionalString(asOptionalObjectRecord(record)?.openclawGatewayInstanceId);
|
|
1549
1521
|
}
|
|
1550
1522
|
function extractGeneratedWrapperPath(command) {
|
|
1551
1523
|
return splitCommandParts(command ?? "").find((part) => (part.split(/[\\/]/).pop() ?? "") === "codex-acp-wrapper.mjs" || (part.split(/[\\/]/).pop() ?? "") === "claude-agent-acp-wrapper.mjs") ?? "";
|
|
@@ -1569,27 +1541,24 @@ function createResetAwareSessionStore(baseStore, params) {
|
|
|
1569
1541
|
const resource = scope?.generation.resource ?? sessionId.trim();
|
|
1570
1542
|
const pending = pendingWrites.get(sessionId.trim());
|
|
1571
1543
|
if (pending && (scope?.generation.awaitPriorWrites || freshSessionKeys.has(resource))) await Promise.allSettled(pending);
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
return leasedRecord;
|
|
1591
|
-
};
|
|
1592
|
-
return await load();
|
|
1544
|
+
if (scope?.generation.retired) return;
|
|
1545
|
+
const normalized = sessionId.trim();
|
|
1546
|
+
if (normalized && freshSessionKeys.has(normalized)) return;
|
|
1547
|
+
const record = await baseStore.load(sessionId);
|
|
1548
|
+
if (scope?.generation.retired || freshSessionKeys.has(scope?.generation.resource ?? normalized)) return;
|
|
1549
|
+
if (scope && record) captureGenerationRecord(scope.generation, record);
|
|
1550
|
+
if (!record || !params?.leaseStore || !params.gatewayInstanceId) return record;
|
|
1551
|
+
const sessionName = readSessionRecordName(record) || normalized;
|
|
1552
|
+
const lease = selectCurrentSessionLease({
|
|
1553
|
+
leases: await params.leaseStore.listOpen(params.gatewayInstanceId),
|
|
1554
|
+
sessionKeys: [sessionName, normalized],
|
|
1555
|
+
rootPid: readRecordAgentPid(record)
|
|
1556
|
+
});
|
|
1557
|
+
if (!lease) return record;
|
|
1558
|
+
if (scope?.generation.retired) return;
|
|
1559
|
+
const leasedRecord = withOpenClawLeaseSessionMetadata(record, lease);
|
|
1560
|
+
if (scope) captureGenerationRecord(scope.generation, leasedRecord);
|
|
1561
|
+
return leasedRecord;
|
|
1593
1562
|
},
|
|
1594
1563
|
async save(record) {
|
|
1595
1564
|
const scope = acpxOperationScope.getStore();
|
|
@@ -1791,11 +1760,11 @@ function readAgentFromSessionKey(sessionKey) {
|
|
|
1791
1760
|
const normalized = sessionKey?.trim();
|
|
1792
1761
|
if (!normalized) return;
|
|
1793
1762
|
const match = /^agent:(?<agent>[^:]+):/i.exec(normalized);
|
|
1794
|
-
return
|
|
1763
|
+
return normalizeOptionalLowercaseString(match?.groups?.agent);
|
|
1795
1764
|
}
|
|
1796
1765
|
function readAgentFromHandle(handle) {
|
|
1797
1766
|
const decoded = decodeAcpxRuntimeHandleState(handle.runtimeSessionName);
|
|
1798
|
-
return
|
|
1767
|
+
return normalizeOptionalLowercaseString(decoded?.agent) ?? readAgentFromSessionKey(handle.sessionKey);
|
|
1799
1768
|
}
|
|
1800
1769
|
function failUnsupportedCodexAcpModel(rawModel) {
|
|
1801
1770
|
throw new AcpRuntimeError("ACP_INVALID_RUNTIME_OPTION", `Codex ACP model "${rawModel}" is not supported. Use openai/<model> or <model>/<reasoning-effort>.`);
|
|
@@ -1933,7 +1902,7 @@ var AcpxRuntime$1 = class {
|
|
|
1933
1902
|
this.scopedAgentRegistry = {
|
|
1934
1903
|
resolve: (agentName) => {
|
|
1935
1904
|
const launch = this.launchCommandScope.getStore();
|
|
1936
|
-
return launch && launch.agent ===
|
|
1905
|
+
return launch && launch.agent === normalizeOptionalLowercaseString(agentName) && launch.command ? launch.command : this.agentRegistry.resolve(agentName);
|
|
1937
1906
|
},
|
|
1938
1907
|
list: () => this.agentRegistry.list()
|
|
1939
1908
|
};
|
|
@@ -1981,7 +1950,7 @@ var AcpxRuntime$1 = class {
|
|
|
1981
1950
|
this.delegate = createDelegate();
|
|
1982
1951
|
this.generationRegistry = new AcpxGenerationRegistry(this.sessionStore, this.delegate, createDelegate);
|
|
1983
1952
|
this.probe = new AcpxRuntimeProbe({
|
|
1984
|
-
getAgent: () =>
|
|
1953
|
+
getAgent: () => normalizeOptionalLowercaseString(options.getProbeAgent?.() ?? options.probeAgent) ?? "codex",
|
|
1985
1954
|
createRuntime: createDelegate,
|
|
1986
1955
|
assertRunning: () => this.generationRegistry.assertRunning(),
|
|
1987
1956
|
runWithLease: (agent, run) => this.runWithLaunchLease({
|
|
@@ -2076,7 +2045,7 @@ var AcpxRuntime$1 = class {
|
|
|
2076
2045
|
command: params.command,
|
|
2077
2046
|
wrapperRoot: this.wrapperRoot
|
|
2078
2047
|
})) return await this.launchCommandScope.run({
|
|
2079
|
-
agent:
|
|
2048
|
+
agent: normalizeOptionalLowercaseString(params.agent) ?? params.agent,
|
|
2080
2049
|
command: params.reusableCommand ?? params.command
|
|
2081
2050
|
}, params.run);
|
|
2082
2051
|
const reusableIdentity = readAcpxProcessLeaseIdentity(params.reusableCommand);
|
|
@@ -2095,7 +2064,7 @@ var AcpxRuntime$1 = class {
|
|
|
2095
2064
|
leasedCommand
|
|
2096
2065
|
};
|
|
2097
2066
|
const result = await this.launchLeaseScope.run(launch, () => this.launchCommandScope.run({
|
|
2098
|
-
agent:
|
|
2067
|
+
agent: normalizeOptionalLowercaseString(params.agent) ?? params.agent,
|
|
2099
2068
|
command: launch.resolvedCommand
|
|
2100
2069
|
}, params.run));
|
|
2101
2070
|
if (params.finalizeCompletedProbe) await cleanupOpenClawOwnedAcpxPendingLease({
|
|
@@ -2209,7 +2178,7 @@ var AcpxRuntime$1 = class {
|
|
|
2209
2178
|
...logicalInput,
|
|
2210
2179
|
sessionKey: resolveAcpxSessionResource(logicalInput)
|
|
2211
2180
|
};
|
|
2212
|
-
const isCodexAcp =
|
|
2181
|
+
const isCodexAcp = normalizeOptionalLowercaseString(input.agent) === CODEX_ACP_AGENT_ID && isCodexAcpCommand(command);
|
|
2213
2182
|
const dropInheritedCodexMax = isCodexAcp && input.thinking === "max" && input.thinkingExplicit === false;
|
|
2214
2183
|
const effectiveInput = dropInheritedCodexMax ? { ...input } : input;
|
|
2215
2184
|
if (dropInheritedCodexMax) delete effectiveInput.thinking;
|
|
@@ -2476,10 +2445,6 @@ var AcpxRuntime$1 = class {
|
|
|
2476
2445
|
};
|
|
2477
2446
|
//#endregion
|
|
2478
2447
|
//#region extensions/acpx/src/service.ts
|
|
2479
|
-
/**
|
|
2480
|
-
* ACPX plugin service lifecycle. It resolves config, prepares isolated adapter
|
|
2481
|
-
* wrappers, registers the ACP backend, and manages startup/cleanup probes.
|
|
2482
|
-
*/
|
|
2483
2448
|
const ENABLE_STARTUP_PROBE_ENV = "OPENCLAW_ACPX_RUNTIME_STARTUP_PROBE";
|
|
2484
2449
|
const SKIP_RUNTIME_PROBE_ENV = "OPENCLAW_SKIP_ACPX_RUNTIME_PROBE";
|
|
2485
2450
|
const MAX_ACPX_TOKIO_WORKER_THREADS = 8;
|
|
@@ -2545,14 +2510,11 @@ async function withStartupProbeTimeout(params) {
|
|
|
2545
2510
|
if (timeout) clearTimeout(timeout);
|
|
2546
2511
|
}
|
|
2547
2512
|
}
|
|
2548
|
-
function
|
|
2549
|
-
|
|
2513
|
+
async function resolveGatewayInstanceId(openKeyedStore) {
|
|
2514
|
+
const store = openKeyedStore({
|
|
2550
2515
|
namespace: ACPX_GATEWAY_INSTANCE_NAMESPACE,
|
|
2551
2516
|
maxEntries: 1
|
|
2552
2517
|
});
|
|
2553
|
-
}
|
|
2554
|
-
async function resolveGatewayInstanceId(openKeyedStore) {
|
|
2555
|
-
const store = openGatewayInstanceStateStore(openKeyedStore);
|
|
2556
2518
|
const existing = normalizeAcpxGatewayInstanceRecord(await store.lookup(ACPX_GATEWAY_INSTANCE_KEY));
|
|
2557
2519
|
if (existing) return existing.instanceId;
|
|
2558
2520
|
const next = randomUUID();
|
|
@@ -2576,29 +2538,18 @@ async function reapOpenAcpxProcessLeases(params) {
|
|
|
2576
2538
|
const terminatedPids = [];
|
|
2577
2539
|
const legacyWrapperRoots = /* @__PURE__ */ new Set();
|
|
2578
2540
|
for (const lease of leases) {
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
assertCurrent();
|
|
2582
|
-
await params.leaseStore.markState(lease.leaseId, "closing");
|
|
2583
|
-
assertCurrent();
|
|
2584
|
-
const result = await cleanupOpenClawOwnedAcpxPendingLease({
|
|
2585
|
-
leaseId: lease.leaseId,
|
|
2586
|
-
gatewayInstanceId: lease.gatewayInstanceId,
|
|
2587
|
-
wrapperRoot: lease.wrapperRoot,
|
|
2588
|
-
wrapperPath: lease.wrapperPath,
|
|
2589
|
-
deps
|
|
2590
|
-
});
|
|
2591
|
-
inspectedPids.push(...result.inspectedPids);
|
|
2592
|
-
terminatedPids.push(...result.terminatedPids);
|
|
2593
|
-
const retryableEvidenceFailure = result.skippedReason === "ambiguous-root" || result.skippedReason === "process-list-unavailable" || result.skippedReason === "unsupported-platform" || result.skippedReason === "unverified-root" || lease.sessionKey === "openclaw:acpx:probe" && result.skippedReason === "missing-root";
|
|
2594
|
-
assertCurrent();
|
|
2595
|
-
await params.leaseStore.markState(lease.leaseId, retryableEvidenceFailure ? "open" : result.terminatedPids.length > 0 ? "closed" : "lost");
|
|
2596
|
-
continue;
|
|
2597
|
-
}
|
|
2541
|
+
const pending = lease.rootPid <= 0;
|
|
2542
|
+
if (pending) legacyWrapperRoots.add(lease.wrapperRoot);
|
|
2598
2543
|
assertCurrent();
|
|
2599
2544
|
await params.leaseStore.markState(lease.leaseId, "closing");
|
|
2600
2545
|
assertCurrent();
|
|
2601
|
-
const result = await
|
|
2546
|
+
const result = pending ? await cleanupOpenClawOwnedAcpxPendingLease({
|
|
2547
|
+
leaseId: lease.leaseId,
|
|
2548
|
+
gatewayInstanceId: lease.gatewayInstanceId,
|
|
2549
|
+
wrapperRoot: lease.wrapperRoot,
|
|
2550
|
+
wrapperPath: lease.wrapperPath,
|
|
2551
|
+
deps
|
|
2552
|
+
}) : await cleanupOpenClawOwnedAcpxProcessTree({
|
|
2602
2553
|
rootPid: lease.rootPid,
|
|
2603
2554
|
expectedLeaseId: lease.leaseId,
|
|
2604
2555
|
expectedGatewayInstanceId: lease.gatewayInstanceId,
|
|
@@ -2607,8 +2558,9 @@ async function reapOpenAcpxProcessLeases(params) {
|
|
|
2607
2558
|
});
|
|
2608
2559
|
inspectedPids.push(...result.inspectedPids);
|
|
2609
2560
|
terminatedPids.push(...result.terminatedPids);
|
|
2561
|
+
const retryableEvidenceFailure = result.skippedReason === "process-list-unavailable" || result.skippedReason === "unsupported-platform" || pending && (result.skippedReason === "ambiguous-root" || result.skippedReason === "unverified-root" || lease.sessionKey === "openclaw:acpx:probe" && result.skippedReason === "missing-root");
|
|
2610
2562
|
assertCurrent();
|
|
2611
|
-
await params.leaseStore.markState(lease.leaseId,
|
|
2563
|
+
await params.leaseStore.markState(lease.leaseId, retryableEvidenceFailure ? "open" : result.terminatedPids.length > 0 ? "closed" : "lost");
|
|
2612
2564
|
}
|
|
2613
2565
|
for (const wrapperRoot of legacyWrapperRoots) {
|
|
2614
2566
|
assertCurrent();
|
|
@@ -2624,7 +2576,6 @@ async function reapOpenAcpxProcessLeases(params) {
|
|
|
2624
2576
|
terminatedPids
|
|
2625
2577
|
};
|
|
2626
2578
|
}
|
|
2627
|
-
/** Create the ACPX plugin service that owns runtime registration and cleanup. */
|
|
2628
2579
|
function createAcpxRuntimeService(params) {
|
|
2629
2580
|
let runtime = null;
|
|
2630
2581
|
let recoverProcesses;
|
|
@@ -2659,12 +2610,22 @@ function createAcpxRuntimeService(params) {
|
|
|
2659
2610
|
if (!openKeyedStore) throw new Error("ACPX runtime service requires plugin keyed state");
|
|
2660
2611
|
const basePluginConfig = await measureAcpxStartup(ctx, "config.resolve", () => resolveAcpxPluginConfig({
|
|
2661
2612
|
rawConfig: params.pluginConfig,
|
|
2662
|
-
workspaceDir: ctx.workspaceDir
|
|
2613
|
+
workspaceDir: ctx.workspaceDir,
|
|
2614
|
+
stateDir: ctx.stateDir
|
|
2615
|
+
}));
|
|
2616
|
+
const adoption = await measureAcpxStartup(ctx, "state.adopt", () => adoptAcpxStateDirectory({
|
|
2617
|
+
rawConfig: params.pluginConfig,
|
|
2618
|
+
workspaceDir: ctx.workspaceDir,
|
|
2619
|
+
stateDir: basePluginConfig.stateDir,
|
|
2620
|
+
openKeyedStore,
|
|
2621
|
+
assertCurrent: params.assertCurrent
|
|
2663
2622
|
}));
|
|
2623
|
+
basePluginConfig.stateDir = adoption.stateDir;
|
|
2624
|
+
for (const change of adoption.changes) ctx.logger.info(change);
|
|
2625
|
+
for (const warning of adoption.warnings) ctx.logger.warn(warning);
|
|
2664
2626
|
const pluginConfig = await measureAcpxStartup(ctx, "config.prepare-codex-auth", () => prepareAcpxCodexAuthConfig({
|
|
2665
2627
|
pluginConfig: basePluginConfig,
|
|
2666
|
-
stateDir: ctx.stateDir
|
|
2667
|
-
logger: ctx.logger
|
|
2628
|
+
stateDir: ctx.stateDir
|
|
2668
2629
|
}));
|
|
2669
2630
|
const wrapperRoot = path.join(ctx.stateDir, "acpx");
|
|
2670
2631
|
await measureAcpxStartup(ctx, "filesystem.prepare", async () => {
|