@openclaw/acpx 2026.11.3 → 2026.11.5-beta.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/.setup/{config-D0ATuiVJ.mjs → config-DZaY96RI.mjs} +15 -23
- package/dist/.setup/{harness-attempt-lu4_bMfd.mjs → harness-attempt-CR7gvC_C.mjs} +5 -4
- package/dist/.setup/{pi-session-catalog-runtime-BAM1pEMw.mjs → pi-session-catalog-runtime-hFy095NF.mjs} +35 -57
- package/dist/.setup/{pi-session-paths-CIvyk6KB.mjs → pi-session-paths-Cn5bsvi0.mjs} +2 -2
- package/dist/.setup/{service-D_e2JAUG.mjs → service-By25n8eI.mjs} +135 -373
- package/dist/.setup/{session-owner-migration-BA3DJKb2.mjs → session-owner-migration-BmfOUj9h.mjs} +3 -3
- package/dist/.setup/{session-resource-DKJsUJPu.mjs → session-resource-BI93OF1C.mjs} +2 -2
- package/dist/.source-module-urls/9369b1b274d2ba70ea21d859abb3415ad8d63d0a1022a301763b953a5798469e.json +1 -0
- package/dist/doctor-contract-api.js +17 -11
- package/dist/index.js +207 -21
- package/openclaw.plugin.json +28 -1
- package/package.json +9 -9
- package/dist/.setup/register.runtime-D685iYx-.mjs +0 -197
- package/dist/register.runtime.js +0 -2
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { a as isClaudeAcpCommand, c as renderAgentCommand, d as CODEX_ACP_BIN, f as CODEX_ACP_PACKAGE, i as toAcpMcpServers, l as resolveAgentCommand, m as OPENCLAW_CODEX_CONFIG_ARG, n as resolveAcpxPluginRoot, o as isCodexAcpCommand, p as LEGACY_CODEX_ACP_PACKAGE, r as resolveOpenClawRoot, s as isOpenClawBridgeCommand, t as resolveAcpxPluginConfig, u as splitCommandParts } from "./config-
|
|
1
|
+
import { a as isClaudeAcpCommand, c as renderAgentCommand, d as CODEX_ACP_BIN, f as CODEX_ACP_PACKAGE, i as toAcpMcpServers, l as resolveAgentCommand, m as OPENCLAW_CODEX_CONFIG_ARG, n as resolveAcpxPluginRoot, o as isCodexAcpCommand, p as LEGACY_CODEX_ACP_PACKAGE, r as resolveOpenClawRoot, s as isOpenClawBridgeCommand, t as resolveAcpxPluginConfig, u as splitCommandParts } from "./config-DZaY96RI.mjs";
|
|
2
2
|
import { AcpRuntimeError } from "../runtime-api.js";
|
|
3
|
-
import { t as resolveAcpxSessionResource } from "./session-resource-
|
|
4
|
-
import { a as hashAcpxProcessCommand, adoptAcpxStateDirectory, c as withAcpxLeaseArgs, d as normalizeAcpxGatewayInstanceRecord, i as createAcpxProcessLeaseStore, l as ACPX_GATEWAY_INSTANCE_KEY, n as OPENCLAW_ACPX_LEASE_ID_ARG, o as openAcpxProcessLeaseStateStore, r as OPENCLAW_GATEWAY_INSTANCE_ID_ARG, s as readAcpxProcessLeaseIdentity, t as ACPX_PROBE_LEASE_SESSION_KEY, u as ACPX_GATEWAY_INSTANCE_NAMESPACE } from "./session-owner-migration-
|
|
3
|
+
import { t as resolveAcpxSessionResource } from "./session-resource-BI93OF1C.mjs";
|
|
4
|
+
import { a as hashAcpxProcessCommand, adoptAcpxStateDirectory, c as withAcpxLeaseArgs, d as normalizeAcpxGatewayInstanceRecord, i as createAcpxProcessLeaseStore, l as ACPX_GATEWAY_INSTANCE_KEY, n as OPENCLAW_ACPX_LEASE_ID_ARG, o as openAcpxProcessLeaseStateStore, r as OPENCLAW_GATEWAY_INSTANCE_ID_ARG, s as readAcpxProcessLeaseIdentity, t as ACPX_PROBE_LEASE_SESSION_KEY, u as ACPX_GATEWAY_INSTANCE_NAMESPACE } from "./session-owner-migration-BmfOUj9h.mjs";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
|
-
import { finiteSecondsToTimerSafeMilliseconds
|
|
6
|
+
import { finiteSecondsToTimerSafeMilliseconds } from "openclaw/plugin-sdk/number-runtime";
|
|
7
7
|
import fs from "node:fs";
|
|
8
8
|
import path from "node:path";
|
|
9
|
-
import {
|
|
9
|
+
import { isPidAlive, runExec } from "openclaw/plugin-sdk/process-runtime";
|
|
10
|
+
import { isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
10
11
|
import os, { availableParallelism } from "node:os";
|
|
11
12
|
import { randomUUID } from "node:crypto";
|
|
12
13
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
@@ -17,7 +18,6 @@ import { raceWithTimeout } from "openclaw/plugin-sdk/time-runtime";
|
|
|
17
18
|
import { tryReadJson } from "@openclaw/fs-safe/json";
|
|
18
19
|
import { parse, stringify } from "smol-toml";
|
|
19
20
|
import { setTimeout } from "node:timers/promises";
|
|
20
|
-
import { isPidAlive, runExec } from "openclaw/plugin-sdk/process-runtime";
|
|
21
21
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
22
22
|
import { isDeepStrictEqual } from "node:util";
|
|
23
23
|
import { redactSensitiveText } from "openclaw/plugin-sdk/security-runtime";
|
|
@@ -441,9 +441,7 @@ const parentWatcher =
|
|
|
441
441
|
return;
|
|
442
442
|
}
|
|
443
443
|
orphanCleanupStarted = true;
|
|
444
|
-
|
|
445
|
-
clearInterval(parentWatcher);
|
|
446
|
-
}
|
|
444
|
+
clearInterval(parentWatcher);
|
|
447
445
|
killChildTree("SIGTERM");
|
|
448
446
|
// Keep the wrapper alive long enough for stubborn adapters to receive
|
|
449
447
|
// a forced fallback signal after SIGTERM.
|
|
@@ -479,9 +477,7 @@ child.on("exit", (code, signal) => {
|
|
|
479
477
|
|
|
480
478
|
child.on("close", () => {
|
|
481
479
|
finishStderrLog();
|
|
482
|
-
|
|
483
|
-
clearInterval(parentWatcher);
|
|
484
|
-
}
|
|
480
|
+
clearInterval(parentWatcher);
|
|
485
481
|
childClosed = true;
|
|
486
482
|
finishWrapper();
|
|
487
483
|
});
|
|
@@ -491,121 +487,6 @@ main();
|
|
|
491
487
|
}
|
|
492
488
|
//#endregion
|
|
493
489
|
//#region extensions/acpx/src/codex-trust-config.ts
|
|
494
|
-
function stripTomlComment(line) {
|
|
495
|
-
let quote = null;
|
|
496
|
-
let escaping = false;
|
|
497
|
-
for (let index = 0; index < line.length; index += 1) {
|
|
498
|
-
const ch = line[index];
|
|
499
|
-
if (escaping) {
|
|
500
|
-
escaping = false;
|
|
501
|
-
continue;
|
|
502
|
-
}
|
|
503
|
-
if (quote === "\"" && ch === "\\") {
|
|
504
|
-
escaping = true;
|
|
505
|
-
continue;
|
|
506
|
-
}
|
|
507
|
-
if (quote) {
|
|
508
|
-
if (ch === quote) quote = null;
|
|
509
|
-
continue;
|
|
510
|
-
}
|
|
511
|
-
if (ch === "'" || ch === "\"") {
|
|
512
|
-
quote = ch;
|
|
513
|
-
continue;
|
|
514
|
-
}
|
|
515
|
-
if (ch === "#") return line.slice(0, index);
|
|
516
|
-
}
|
|
517
|
-
return line;
|
|
518
|
-
}
|
|
519
|
-
function parseTomlString(value) {
|
|
520
|
-
const trimmed = value.trim();
|
|
521
|
-
if (trimmed.startsWith("\"") && trimmed.endsWith("\"")) try {
|
|
522
|
-
return JSON.parse(trimmed);
|
|
523
|
-
} catch {
|
|
524
|
-
return;
|
|
525
|
-
}
|
|
526
|
-
if (trimmed.startsWith("'") && trimmed.endsWith("'")) return trimmed.slice(1, -1);
|
|
527
|
-
}
|
|
528
|
-
function parseTomlDottedKey(value) {
|
|
529
|
-
const parts = [];
|
|
530
|
-
let current = "";
|
|
531
|
-
let quote = null;
|
|
532
|
-
let escaping = false;
|
|
533
|
-
for (const ch of value.trim()) {
|
|
534
|
-
if (escaping) {
|
|
535
|
-
current += ch;
|
|
536
|
-
escaping = false;
|
|
537
|
-
continue;
|
|
538
|
-
}
|
|
539
|
-
if (quote === "\"" && ch === "\\") {
|
|
540
|
-
current += ch;
|
|
541
|
-
escaping = true;
|
|
542
|
-
continue;
|
|
543
|
-
}
|
|
544
|
-
if (quote) {
|
|
545
|
-
current += ch;
|
|
546
|
-
if (ch === quote) quote = null;
|
|
547
|
-
continue;
|
|
548
|
-
}
|
|
549
|
-
if (ch === "'" || ch === "\"") {
|
|
550
|
-
quote = ch;
|
|
551
|
-
current += ch;
|
|
552
|
-
continue;
|
|
553
|
-
}
|
|
554
|
-
if (ch === ".") {
|
|
555
|
-
parts.push(current.trim());
|
|
556
|
-
current = "";
|
|
557
|
-
continue;
|
|
558
|
-
}
|
|
559
|
-
current += ch;
|
|
560
|
-
}
|
|
561
|
-
if (current.trim()) parts.push(current.trim());
|
|
562
|
-
return parts.map((part) => parseTomlString(part) ?? part);
|
|
563
|
-
}
|
|
564
|
-
function parseProjectHeader(line) {
|
|
565
|
-
const parts = parseTableHeader(line);
|
|
566
|
-
return parts?.length === 2 && parts[0] === "projects" ? parts[1] : void 0;
|
|
567
|
-
}
|
|
568
|
-
function parseTrustedInlineProjectEntries(value) {
|
|
569
|
-
const trusted = [];
|
|
570
|
-
for (const match of value.matchAll(/(?<key>"(?:\\.|[^"\\])*"|'[^']*'|[A-Za-z0-9_\-/.~:]+)\s*=\s*\{(?<body>[^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/g)) {
|
|
571
|
-
const key = match.groups?.key;
|
|
572
|
-
const body = match.groups?.body;
|
|
573
|
-
if (!key || !body || !/\btrust_level\s*=\s*["']trusted["']/.test(body)) continue;
|
|
574
|
-
const projectPath = parseTomlString(key) ?? key.trim();
|
|
575
|
-
if (projectPath) trusted.push(projectPath);
|
|
576
|
-
}
|
|
577
|
-
return trusted;
|
|
578
|
-
}
|
|
579
|
-
function extractTrustedCodexProjectPaths(configToml) {
|
|
580
|
-
const trusted = /* @__PURE__ */ new Set();
|
|
581
|
-
let currentProjectPath;
|
|
582
|
-
let inProjectsTable = false;
|
|
583
|
-
for (const rawLine of configToml.split(/\r?\n/)) {
|
|
584
|
-
const line = stripTomlComment(rawLine).trim();
|
|
585
|
-
if (!line) continue;
|
|
586
|
-
if (line.startsWith("[")) {
|
|
587
|
-
currentProjectPath = parseProjectHeader(line);
|
|
588
|
-
inProjectsTable = line === "[projects]";
|
|
589
|
-
continue;
|
|
590
|
-
}
|
|
591
|
-
if (currentProjectPath && /^trust_level\s*=\s*["']trusted["']\s*$/.test(line)) {
|
|
592
|
-
trusted.add(currentProjectPath);
|
|
593
|
-
continue;
|
|
594
|
-
}
|
|
595
|
-
const assignment = /^(?<key>"(?:\\.|[^"\\])*"|'[^']*'|[A-Za-z0-9_\-/.~:]+)\s*=\s*(?<value>.+)$/.exec(line);
|
|
596
|
-
const rawKey = assignment?.groups?.key;
|
|
597
|
-
const rawValue = assignment?.groups?.value;
|
|
598
|
-
if (!rawKey || rawValue === void 0) continue;
|
|
599
|
-
const key = parseTomlString(rawKey) ?? rawKey;
|
|
600
|
-
const value = rawValue.trim();
|
|
601
|
-
if (inProjectsTable && /^\{.*\}$/.test(value)) {
|
|
602
|
-
if (/\btrust_level\s*=\s*["']trusted["']/.test(value) && key) trusted.add(key);
|
|
603
|
-
continue;
|
|
604
|
-
}
|
|
605
|
-
if (key === "projects" || inProjectsTable) for (const projectPath of parseTrustedInlineProjectEntries(value)) trusted.add(projectPath);
|
|
606
|
-
}
|
|
607
|
-
return Array.from(trusted);
|
|
608
|
-
}
|
|
609
490
|
const INHERITED_TOP_LEVEL_CODEX_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
610
491
|
"model",
|
|
611
492
|
"model_provider",
|
|
@@ -623,61 +504,30 @@ const INHERITED_MODEL_PROVIDER_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
623
504
|
"stream_max_retries",
|
|
624
505
|
"stream_idle_timeout_ms"
|
|
625
506
|
]);
|
|
626
|
-
function parseTableHeader(line) {
|
|
627
|
-
const trimmed = line.trim();
|
|
628
|
-
if (!trimmed.startsWith("[") || !trimmed.endsWith("]") || trimmed.startsWith("[[")) return;
|
|
629
|
-
return parseTomlDottedKey(trimmed.slice(1, -1));
|
|
630
|
-
}
|
|
631
|
-
function isInheritedModelProviderTable(parts) {
|
|
632
|
-
return parts?.[0] === "model_providers" && parts.length === 2;
|
|
633
|
-
}
|
|
634
|
-
function parseTopLevelAssignmentKey(line) {
|
|
635
|
-
return /^(?<key>[A-Za-z0-9_-]+)\s*=\s*(?<value>.+)$/.exec(line)?.groups?.key;
|
|
636
|
-
}
|
|
637
|
-
function extractInheritedCodexRuntimeConfig(configToml) {
|
|
638
|
-
const inheritedLines = [];
|
|
639
|
-
let inAnyTable = false;
|
|
640
|
-
let inInheritedTable = false;
|
|
641
|
-
let pendingInheritedTableHeader = "";
|
|
642
|
-
function flushInheritedTableHeader() {
|
|
643
|
-
if (!pendingInheritedTableHeader) return;
|
|
644
|
-
if (inheritedLines.length > 0 && inheritedLines[inheritedLines.length - 1] !== "") inheritedLines.push("");
|
|
645
|
-
inheritedLines.push(pendingInheritedTableHeader);
|
|
646
|
-
pendingInheritedTableHeader = "";
|
|
647
|
-
}
|
|
648
|
-
for (const rawLine of configToml.split(/\r?\n/)) {
|
|
649
|
-
const trimmedLine = rawLine.trim();
|
|
650
|
-
const semanticLine = stripTomlComment(rawLine).trim();
|
|
651
|
-
if (trimmedLine.startsWith("[")) {
|
|
652
|
-
const tableParts = parseTableHeader(trimmedLine);
|
|
653
|
-
inAnyTable = true;
|
|
654
|
-
inInheritedTable = isInheritedModelProviderTable(tableParts);
|
|
655
|
-
if (inInheritedTable) pendingInheritedTableHeader = rawLine.trimEnd();
|
|
656
|
-
else pendingInheritedTableHeader = "";
|
|
657
|
-
continue;
|
|
658
|
-
}
|
|
659
|
-
if (inInheritedTable) {
|
|
660
|
-
if (!semanticLine) continue;
|
|
661
|
-
const key = parseTopLevelAssignmentKey(semanticLine);
|
|
662
|
-
if (!key || !INHERITED_MODEL_PROVIDER_CONFIG_KEYS.has(key)) continue;
|
|
663
|
-
flushInheritedTableHeader();
|
|
664
|
-
inheritedLines.push(rawLine.trimEnd());
|
|
665
|
-
continue;
|
|
666
|
-
}
|
|
667
|
-
if (inAnyTable) continue;
|
|
668
|
-
const key = parseTopLevelAssignmentKey(semanticLine);
|
|
669
|
-
if (!key) continue;
|
|
670
|
-
if (!INHERITED_TOP_LEVEL_CODEX_CONFIG_KEYS.has(key)) continue;
|
|
671
|
-
inheritedLines.push(rawLine.trimEnd());
|
|
672
|
-
}
|
|
673
|
-
return inheritedLines.join("\n");
|
|
674
|
-
}
|
|
675
507
|
function renderIsolatedCodexConfig(params) {
|
|
676
|
-
|
|
508
|
+
let source = {};
|
|
509
|
+
if (params.sourceConfigToml) try {
|
|
510
|
+
source = parse(params.sourceConfigToml, { integersAsBigInt: true });
|
|
511
|
+
} catch {
|
|
512
|
+
throw new Error("Codex config.toml must be valid TOML before starting an ACP session.");
|
|
513
|
+
}
|
|
514
|
+
const providers = /* @__PURE__ */ new Map();
|
|
515
|
+
if (isRecord(source.model_providers)) for (const [name, provider] of Object.entries(source.model_providers)) {
|
|
516
|
+
if (!isRecord(provider)) continue;
|
|
517
|
+
const config = Object.fromEntries(Object.entries(provider).filter(([key]) => INHERITED_MODEL_PROVIDER_CONFIG_KEYS.has(key)));
|
|
518
|
+
if (Object.keys(config).length) providers.set(name, config);
|
|
519
|
+
}
|
|
520
|
+
const inherited = {
|
|
521
|
+
...Object.fromEntries(Object.entries(source).filter(([key]) => INHERITED_TOP_LEVEL_CODEX_CONFIG_KEYS.has(key))),
|
|
522
|
+
...providers.size ? { model_providers: Object.fromEntries(providers) } : {},
|
|
523
|
+
...params.mcpServers ? { mcp_servers: params.mcpServers } : {}
|
|
524
|
+
};
|
|
525
|
+
const trustedProjects = isRecord(source.projects) ? Object.entries(source.projects).filter(([, project]) => isRecord(project) && project.trust_level === "trusted").map(([projectPath]) => projectPath) : [];
|
|
526
|
+
const projectPaths = Array.from(new Set([...params.projectPaths, ...trustedProjects].map((projectPath) => projectPath.trim()).filter(Boolean).map((projectPath) => path.resolve(projectPath)))).toSorted((left, right) => left.localeCompare(right));
|
|
677
527
|
return [
|
|
678
528
|
"# Generated by OpenClaw for Codex ACP sessions.",
|
|
679
|
-
|
|
680
|
-
...
|
|
529
|
+
stringify(inherited, { numbersAsFloat: true }).trimEnd(),
|
|
530
|
+
...projectPaths.flatMap((projectPath) => [
|
|
681
531
|
"",
|
|
682
532
|
`[projects.${JSON.stringify(projectPath)}]`,
|
|
683
533
|
"trust_level = \"trusted\""
|
|
@@ -846,17 +696,15 @@ async function readSourceCodexConfig(codexHome) {
|
|
|
846
696
|
}
|
|
847
697
|
async function prepareIsolatedCodexHome(params) {
|
|
848
698
|
const sourceConfig = await readSourceCodexConfig(process.env.CODEX_HOME || path.join(os.homedir(), ".codex"));
|
|
849
|
-
const trustedProjectPaths = [...sourceConfig ? extractTrustedCodexProjectPaths(sourceConfig) : [], params.workspaceDir];
|
|
850
699
|
const codexHome = path.join(params.baseDir, "codex-home");
|
|
851
700
|
await fs$1.mkdir(codexHome, { recursive: true });
|
|
852
701
|
await fs$1.writeFile(path.join(codexHome, "config.toml"), renderIsolatedCodexConfig({
|
|
853
702
|
sourceConfigToml: sourceConfig,
|
|
854
|
-
projectPaths:
|
|
703
|
+
projectPaths: [params.workspaceDir],
|
|
704
|
+
mcpServers: isRecord(params.migratedConfig?.mcp_servers) ? params.migratedConfig.mcp_servers : void 0
|
|
855
705
|
}), "utf8");
|
|
856
|
-
return codexHome;
|
|
857
706
|
}
|
|
858
707
|
async function writeAdapterWrapper(baseDir, fileName, script) {
|
|
859
|
-
await fs$1.mkdir(baseDir, { recursive: true });
|
|
860
708
|
const wrapperPath = path.join(baseDir, fileName);
|
|
861
709
|
await fs$1.writeFile(wrapperPath, script, { encoding: "utf8" });
|
|
862
710
|
try {
|
|
@@ -968,13 +816,6 @@ function resolveCodexAdapterLaunch(configuredCommand) {
|
|
|
968
816
|
if (!maintainedAdapterArgs) return;
|
|
969
817
|
return { args: maintainedAdapterArgs };
|
|
970
818
|
}
|
|
971
|
-
async function persistMigratedCodexMcpConfig(params) {
|
|
972
|
-
const mcpServers = params.migratedConfig?.mcp_servers;
|
|
973
|
-
if (!isRecord(mcpServers)) return;
|
|
974
|
-
const configPath = path.join(params.codexHome, "config.toml");
|
|
975
|
-
const merged = mergeConfigRecords(parse(await fs$1.readFile(configPath, "utf8")), { mcp_servers: mcpServers });
|
|
976
|
-
await fs$1.writeFile(configPath, stringify(merged), "utf8");
|
|
977
|
-
}
|
|
978
819
|
function buildClaudeAcpWrapperCommand(wrapperPath, configuredCommand) {
|
|
979
820
|
const configuredAdapterArgs = extractConfiguredAdapterArgs({
|
|
980
821
|
configuredCommand,
|
|
@@ -990,17 +831,15 @@ async function prepareAcpxCodexAuthConfig(params) {
|
|
|
990
831
|
const configuredCodexCommand = params.pluginConfig.agents.codex;
|
|
991
832
|
const configuredClaudeCommand = params.pluginConfig.agents.claude;
|
|
992
833
|
const codexLaunch = resolveCodexAdapterLaunch(configuredCodexCommand);
|
|
993
|
-
await
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
workspaceDir: params.pluginConfig.cwd
|
|
997
|
-
}),
|
|
834
|
+
await prepareIsolatedCodexHome({
|
|
835
|
+
baseDir: codexBaseDir,
|
|
836
|
+
workspaceDir: params.pluginConfig.cwd,
|
|
998
837
|
migratedConfig: codexLaunch?.migratedConfig
|
|
999
838
|
});
|
|
1000
|
-
const
|
|
1001
|
-
const
|
|
1002
|
-
const wrapperPath = await writeAdapterWrapper(codexBaseDir, "codex-acp-wrapper.mjs", buildCodexAcpWrapperScript(
|
|
1003
|
-
const claudeWrapperPath = await writeAdapterWrapper(codexBaseDir, "claude-agent-acp-wrapper.mjs", buildClaudeAcpWrapperScript(
|
|
839
|
+
const codexBinPath = await resolveInstalledAcpPackageBinPath(CODEX_ACP_PACKAGE, CODEX_ACP_BIN);
|
|
840
|
+
const claudeBinPath = await resolveInstalledAcpPackageBinPath(CLAUDE_ACP_PACKAGE, CLAUDE_ACP_BIN);
|
|
841
|
+
const wrapperPath = await writeAdapterWrapper(codexBaseDir, "codex-acp-wrapper.mjs", buildCodexAcpWrapperScript(codexBinPath));
|
|
842
|
+
const claudeWrapperPath = await writeAdapterWrapper(codexBaseDir, "claude-agent-acp-wrapper.mjs", buildClaudeAcpWrapperScript(claudeBinPath));
|
|
1004
843
|
return {
|
|
1005
844
|
...params.pluginConfig,
|
|
1006
845
|
agents: {
|
|
@@ -1127,12 +966,16 @@ function parseProcessList(stdout) {
|
|
|
1127
966
|
}
|
|
1128
967
|
async function listPlatformProcesses() {
|
|
1129
968
|
if (process.platform === "win32") return [];
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
969
|
+
try {
|
|
970
|
+
const { stdout } = await runExec("ps", ["-axo", "pid=,ppid=,command="], {
|
|
971
|
+
logOutput: false,
|
|
972
|
+
maxBuffer: 8388608,
|
|
973
|
+
timeoutMs: ACPX_PROCESS_LIST_TIMEOUT_MS
|
|
974
|
+
});
|
|
975
|
+
return parseProcessList(stdout);
|
|
976
|
+
} catch {
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
1136
979
|
}
|
|
1137
980
|
function collectProcessTree(processes, rootPid) {
|
|
1138
981
|
const childrenByParent = /* @__PURE__ */ new Map();
|
|
@@ -1141,7 +984,7 @@ function collectProcessTree(processes, rootPid) {
|
|
|
1141
984
|
children.push(processInfo);
|
|
1142
985
|
childrenByParent.set(processInfo.ppid, children);
|
|
1143
986
|
}
|
|
1144
|
-
const root =
|
|
987
|
+
const root = processes.find((processInfo) => processInfo.pid === rootPid);
|
|
1145
988
|
const collected = [];
|
|
1146
989
|
if (root) collected.push(root);
|
|
1147
990
|
const queue = [...childrenByParent.get(rootPid) ?? []];
|
|
@@ -1179,28 +1022,20 @@ async function terminatePids(pids, assertCurrent) {
|
|
|
1179
1022
|
async function cleanupOpenClawOwnedAcpxProcessTree(params) {
|
|
1180
1023
|
const rootPid = params.rootPid;
|
|
1181
1024
|
if (!rootPid || rootPid <= 0 || rootPid === process.pid) return {
|
|
1182
|
-
inspectedPids: [],
|
|
1183
1025
|
terminatedPids: [],
|
|
1184
1026
|
skippedReason: "missing-root"
|
|
1185
1027
|
};
|
|
1186
1028
|
if (process.platform === "win32") return {
|
|
1187
|
-
inspectedPids: [],
|
|
1188
1029
|
terminatedPids: [],
|
|
1189
1030
|
skippedReason: "unsupported-platform"
|
|
1190
1031
|
};
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
inspectedPids: [],
|
|
1197
|
-
terminatedPids: [],
|
|
1198
|
-
skippedReason: "process-list-unavailable"
|
|
1199
|
-
};
|
|
1200
|
-
}
|
|
1032
|
+
const processes = await listPlatformProcesses();
|
|
1033
|
+
if (!processes) return {
|
|
1034
|
+
terminatedPids: [],
|
|
1035
|
+
skippedReason: "process-list-unavailable"
|
|
1036
|
+
};
|
|
1201
1037
|
const listedTree = collectProcessTree(processes, rootPid);
|
|
1202
1038
|
if (listedTree.length === 0) return {
|
|
1203
|
-
inspectedPids: [],
|
|
1204
1039
|
terminatedPids: [],
|
|
1205
1040
|
skippedReason: "unverified-root"
|
|
1206
1041
|
};
|
|
@@ -1215,85 +1050,56 @@ async function cleanupOpenClawOwnedAcpxProcessTree(params) {
|
|
|
1215
1050
|
expectedLeaseId: params.expectedLeaseId,
|
|
1216
1051
|
expectedGatewayInstanceId: params.expectedGatewayInstanceId
|
|
1217
1052
|
})) return {
|
|
1218
|
-
inspectedPids: listedTree.map((processInfo) => processInfo.pid),
|
|
1219
1053
|
terminatedPids: [],
|
|
1220
1054
|
skippedReason: "not-openclaw-owned"
|
|
1221
1055
|
};
|
|
1222
|
-
|
|
1223
|
-
return {
|
|
1224
|
-
inspectedPids: uniquePids(listedTree),
|
|
1225
|
-
terminatedPids: await terminatePids(pids, params.assertCurrent)
|
|
1226
|
-
};
|
|
1056
|
+
return { terminatedPids: await terminatePids(uniquePids(listedTree.toReversed()), params.assertCurrent) };
|
|
1227
1057
|
}
|
|
1228
1058
|
/** Recover a pending lease by matching its exact live wrapper identity. */
|
|
1229
1059
|
async function cleanupOpenClawOwnedAcpxPendingLease(params) {
|
|
1230
1060
|
if (process.platform === "win32") return {
|
|
1231
|
-
inspectedPids: [],
|
|
1232
1061
|
terminatedPids: [],
|
|
1233
1062
|
skippedReason: "unsupported-platform"
|
|
1234
1063
|
};
|
|
1235
1064
|
if (!params.wrapperPath || !wrapperPathBelongsToRoot(params.wrapperPath, params.wrapperRoot)) return {
|
|
1236
|
-
inspectedPids: [],
|
|
1237
1065
|
terminatedPids: [],
|
|
1238
1066
|
skippedReason: "unverified-root"
|
|
1239
1067
|
};
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
inspectedPids: [],
|
|
1246
|
-
terminatedPids: [],
|
|
1247
|
-
skippedReason: "process-list-unavailable"
|
|
1248
|
-
};
|
|
1249
|
-
}
|
|
1068
|
+
const processes = await listPlatformProcesses();
|
|
1069
|
+
if (!processes) return {
|
|
1070
|
+
terminatedPids: [],
|
|
1071
|
+
skippedReason: "process-list-unavailable"
|
|
1072
|
+
};
|
|
1250
1073
|
const matchingRoots = processes.filter((processInfo) => commandContainsExactWrapperPath(processInfo.command, params.wrapperPath) && liveCommandMatchesLeaseIdentity({
|
|
1251
1074
|
command: processInfo.command,
|
|
1252
1075
|
expectedLeaseId: params.leaseId,
|
|
1253
1076
|
expectedGatewayInstanceId: params.gatewayInstanceId
|
|
1254
1077
|
}));
|
|
1255
1078
|
if (matchingRoots.length === 0) return {
|
|
1256
|
-
inspectedPids: [],
|
|
1257
1079
|
terminatedPids: [],
|
|
1258
1080
|
skippedReason: "missing-root"
|
|
1259
1081
|
};
|
|
1260
1082
|
if (matchingRoots.length > 1) return {
|
|
1261
|
-
inspectedPids: uniquePids(matchingRoots),
|
|
1262
1083
|
terminatedPids: [],
|
|
1263
1084
|
skippedReason: "ambiguous-root"
|
|
1264
1085
|
};
|
|
1265
|
-
|
|
1266
|
-
const pids = uniquePids(listedTree.toReversed());
|
|
1267
|
-
return {
|
|
1268
|
-
inspectedPids: uniquePids(listedTree),
|
|
1269
|
-
terminatedPids: await terminatePids(pids, params.assertCurrent)
|
|
1270
|
-
};
|
|
1086
|
+
return { terminatedPids: await terminatePids(uniquePids(collectProcessTree(processes, matchingRoots[0].pid).toReversed()), params.assertCurrent) };
|
|
1271
1087
|
}
|
|
1272
1088
|
/** Reap orphaned OpenClaw-owned ACPX wrapper trees during runtime startup. */
|
|
1273
1089
|
async function reapStaleOpenClawOwnedAcpxOrphans(params) {
|
|
1274
1090
|
if (process.platform === "win32") return {
|
|
1275
|
-
inspectedPids: [],
|
|
1276
1091
|
terminatedPids: [],
|
|
1277
1092
|
skippedReason: "unsupported-platform"
|
|
1278
1093
|
};
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
terminatedPids: [],
|
|
1286
|
-
skippedReason: "process-list-unavailable"
|
|
1287
|
-
};
|
|
1288
|
-
}
|
|
1289
|
-
const orphanTrees = processes.filter((processInfo) => processInfo.ppid === 1 && !readAcpxProcessLeaseIdentity(processInfo.command) && isOpenClawOwnedAcpxProcessCommand({
|
|
1094
|
+
const processes = await listPlatformProcesses();
|
|
1095
|
+
if (!processes) return {
|
|
1096
|
+
terminatedPids: [],
|
|
1097
|
+
skippedReason: "process-list-unavailable"
|
|
1098
|
+
};
|
|
1099
|
+
return { terminatedPids: await terminatePids(uniquePids(processes.filter((processInfo) => processInfo.ppid === 1 && !readAcpxProcessLeaseIdentity(processInfo.command) && isOpenClawOwnedAcpxProcessCommand({
|
|
1290
1100
|
command: processInfo.command,
|
|
1291
1101
|
wrapperRoot: params.wrapperRoot
|
|
1292
|
-
})).map((orphan) => collectProcessTree(processes, orphan.pid));
|
|
1293
|
-
return {
|
|
1294
|
-
inspectedPids: uniquePids(orphanTrees.flat()),
|
|
1295
|
-
terminatedPids: await terminatePids(uniquePids(orphanTrees.flatMap((tree) => tree.toReversed())), params.assertCurrent)
|
|
1296
|
-
};
|
|
1102
|
+
})).map((orphan) => collectProcessTree(processes, orphan.pid)).flatMap((tree) => tree.toReversed())), params.assertCurrent) };
|
|
1297
1103
|
}
|
|
1298
1104
|
//#endregion
|
|
1299
1105
|
//#region extensions/acpx/src/model-ref.ts
|
|
@@ -1511,30 +1317,9 @@ function captureGenerationRecord(generation, record) {
|
|
|
1511
1317
|
}
|
|
1512
1318
|
const acpxGenerationKey = Symbol("openclaw.acpxGeneration");
|
|
1513
1319
|
const acpxOperationScope = new AsyncLocalStorage();
|
|
1514
|
-
function readSessionRecordName(record) {
|
|
1515
|
-
return normalizeOptionalString(asOptionalObjectRecord(record)?.name) ?? "";
|
|
1516
|
-
}
|
|
1517
1320
|
function readRecordAgentCommand(record) {
|
|
1518
1321
|
return record?.agentArgv ?? record?.agentCommand;
|
|
1519
1322
|
}
|
|
1520
|
-
function readRecordCwd(record) {
|
|
1521
|
-
return normalizeOptionalString(asOptionalObjectRecord(record)?.cwd);
|
|
1522
|
-
}
|
|
1523
|
-
function readRecordResetOnNextEnsure(record) {
|
|
1524
|
-
return asOptionalObjectRecord(asOptionalObjectRecord(record)?.acpx)?.reset_on_next_ensure === true;
|
|
1525
|
-
}
|
|
1526
|
-
function readRecordAgentPid(record) {
|
|
1527
|
-
const { pid, processId } = asOptionalObjectRecord(record) ?? {};
|
|
1528
|
-
const rawPid = pid ?? processId;
|
|
1529
|
-
const numericPid = typeof rawPid === "number" ? rawPid : typeof rawPid === "string" ? parseStrictPositiveInteger(rawPid) : void 0;
|
|
1530
|
-
return numericPid && Number.isInteger(numericPid) && numericPid > 0 ? numericPid : void 0;
|
|
1531
|
-
}
|
|
1532
|
-
function readOpenClawLeaseIdFromRecord(record) {
|
|
1533
|
-
return normalizeOptionalString(asOptionalObjectRecord(record)?.openclawLeaseId);
|
|
1534
|
-
}
|
|
1535
|
-
function readOpenClawGatewayInstanceIdFromRecord(record) {
|
|
1536
|
-
return normalizeOptionalString(asOptionalObjectRecord(record)?.openclawGatewayInstanceId);
|
|
1537
|
-
}
|
|
1538
1323
|
function extractGeneratedWrapperPath(command) {
|
|
1539
1324
|
return splitCommandParts(command ?? "").find((part) => (part.split(/[\\/]/).pop() ?? "") === "codex-acp-wrapper.mjs" || (part.split(/[\\/]/).pop() ?? "") === "claude-agent-acp-wrapper.mjs") ?? "";
|
|
1540
1325
|
}
|
|
@@ -1563,11 +1348,11 @@ function createResetAwareSessionStore(baseStore, params) {
|
|
|
1563
1348
|
const record = await baseStore.load(sessionId);
|
|
1564
1349
|
if (scope && record) captureGenerationRecord(scope.generation, record);
|
|
1565
1350
|
if (!record || !params?.leaseStore || !params.gatewayInstanceId) return record;
|
|
1566
|
-
const sessionName =
|
|
1351
|
+
const sessionName = record.name || normalized;
|
|
1567
1352
|
const lease = selectCurrentSessionLease({
|
|
1568
1353
|
leases: await params.leaseStore.listOpen(params.gatewayInstanceId),
|
|
1569
1354
|
sessionKeys: [sessionName, normalized],
|
|
1570
|
-
rootPid:
|
|
1355
|
+
rootPid: record.pid
|
|
1571
1356
|
});
|
|
1572
1357
|
if (!lease) return record;
|
|
1573
1358
|
const leasedRecord = withOpenClawLeaseSessionMetadata(record, lease);
|
|
@@ -1589,7 +1374,7 @@ function createResetAwareSessionStore(baseStore, params) {
|
|
|
1589
1374
|
}
|
|
1590
1375
|
let recordToSave = record;
|
|
1591
1376
|
const launch = params?.launchScope?.getStore();
|
|
1592
|
-
const sessionName =
|
|
1377
|
+
const sessionName = record.name;
|
|
1593
1378
|
const agentCommand = readRecordAgentCommand(record);
|
|
1594
1379
|
const leasedCommand = launch?.leasedCommand ?? agentCommand;
|
|
1595
1380
|
const leaseIdentity = launch ?? readAcpxProcessLeaseIdentity(leasedCommand);
|
|
@@ -1643,12 +1428,12 @@ function createResetAwareSessionStore(baseStore, params) {
|
|
|
1643
1428
|
/** Capture OpenClaw wrapper cleanup ownership before a backend close can yield. */
|
|
1644
1429
|
async function prepareAcpxProcessCleanup(params) {
|
|
1645
1430
|
const { leaseStore, gatewayInstanceId, wrapperRoot } = params;
|
|
1646
|
-
const rootPid =
|
|
1431
|
+
const rootPid = params.record?.pid;
|
|
1647
1432
|
const rootCommand = params.command ? renderAgentCommand(params.command) : void 0;
|
|
1648
1433
|
const identity = readAcpxProcessLeaseIdentity(params.command);
|
|
1649
|
-
const leaseId =
|
|
1650
|
-
const expectedGatewayInstanceId =
|
|
1651
|
-
const sessionKeys = [params.sessionKey,
|
|
1434
|
+
const leaseId = params.record?.openclawLeaseId ?? identity?.leaseId;
|
|
1435
|
+
const expectedGatewayInstanceId = params.record?.openclawGatewayInstanceId ?? identity?.gatewayInstanceId;
|
|
1436
|
+
const sessionKeys = [params.sessionKey, params.record?.name ?? ""];
|
|
1652
1437
|
const openLeases = rootPid && gatewayInstanceId && leaseStore ? await leaseStore.listOpen(gatewayInstanceId) : [];
|
|
1653
1438
|
const selectedLease = rootPid ? selectCurrentSessionLease({
|
|
1654
1439
|
leases: openLeases,
|
|
@@ -1656,8 +1441,7 @@ async function prepareAcpxProcessCleanup(params) {
|
|
|
1656
1441
|
rootPid
|
|
1657
1442
|
}) : void 0;
|
|
1658
1443
|
const loadedLease = leaseId ? await leaseStore?.load(leaseId) : void 0;
|
|
1659
|
-
const
|
|
1660
|
-
const lease = ownedLease ? { ...ownedLease } : void 0;
|
|
1444
|
+
const lease = selectedLease ?? (loadedLease && loadedLease.gatewayInstanceId === gatewayInstanceId && (!rootPid || loadedLease.rootPid === rootPid) && sessionKeys.includes(loadedLease.sessionKey) ? loadedLease : void 0);
|
|
1661
1445
|
return async () => {
|
|
1662
1446
|
if (lease && lease.gatewayInstanceId === gatewayInstanceId) {
|
|
1663
1447
|
await leaseStore?.markState(lease.leaseId, "closing");
|
|
@@ -1857,35 +1641,9 @@ function appendCodexAcpConfigOverrides(command, override) {
|
|
|
1857
1641
|
JSON.stringify(config)
|
|
1858
1642
|
];
|
|
1859
1643
|
}
|
|
1860
|
-
function withManagedToolsMcpSessionEnv(params) {
|
|
1861
|
-
const sessionKey = params.sessionKey.trim();
|
|
1862
|
-
if (!params.pluginToolsEnabled && !params.openclawToolsEnabled || !sessionKey || !params.mcpServers?.length) return params.mcpServers;
|
|
1863
|
-
let changed = false;
|
|
1864
|
-
const nextServers = params.mcpServers.map((server) => {
|
|
1865
|
-
const isManagedPluginTools = params.pluginToolsEnabled && server.name === ACPX_PLUGIN_TOOLS_MCP_SERVER_NAME;
|
|
1866
|
-
const isManagedOpenClawTools = params.openclawToolsEnabled && server.name === ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME;
|
|
1867
|
-
if (!isManagedPluginTools && !isManagedOpenClawTools || !("command" in server)) return server;
|
|
1868
|
-
changed = true;
|
|
1869
|
-
const env = [...server.env.filter((entry) => entry.name !== OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY_ENV), {
|
|
1870
|
-
name: OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY_ENV,
|
|
1871
|
-
value: sessionKey
|
|
1872
|
-
}];
|
|
1873
|
-
return {
|
|
1874
|
-
...server,
|
|
1875
|
-
env,
|
|
1876
|
-
args: params.agentId ? [
|
|
1877
|
-
...server.args,
|
|
1878
|
-
"--openclaw-agent-id",
|
|
1879
|
-
params.agentId
|
|
1880
|
-
] : server.args
|
|
1881
|
-
};
|
|
1882
|
-
});
|
|
1883
|
-
return changed ? nextServers : params.mcpServers;
|
|
1884
|
-
}
|
|
1885
1644
|
function resolveBridgeSession(handle) {
|
|
1886
1645
|
return handle.bridgeSession === void 0 ? handle : handle.bridgeSession;
|
|
1887
1646
|
}
|
|
1888
|
-
/** OpenClaw-managed ACP runtime implementation backed by the upstream acpx runtime. */
|
|
1889
1647
|
var AcpxRuntime$1 = class {
|
|
1890
1648
|
constructor(options, testOptions) {
|
|
1891
1649
|
this.ownerAwareSessions = 1;
|
|
@@ -1935,12 +1693,29 @@ var AcpxRuntime$1 = class {
|
|
|
1935
1693
|
if (target === null) return [];
|
|
1936
1694
|
if (!this.managedToolsMcpBridgeEnabled) return servers;
|
|
1937
1695
|
if (!target) throw new AcpRuntimeError("ACP_SESSION_INIT_FAILED", "ACP tool bridge has no session owner");
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1696
|
+
const sessionKey = target.sessionKey.trim();
|
|
1697
|
+
if (!this.pluginToolsMcpBridgeEnabled && !this.openclawToolsMcpBridgeEnabled || !sessionKey || !servers?.length) return servers;
|
|
1698
|
+
let changed = false;
|
|
1699
|
+
const nextServers = servers.map((server) => {
|
|
1700
|
+
const isManagedPluginTools = this.pluginToolsMcpBridgeEnabled && server.name === ACPX_PLUGIN_TOOLS_MCP_SERVER_NAME;
|
|
1701
|
+
const isManagedOpenClawTools = this.openclawToolsMcpBridgeEnabled && server.name === ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME;
|
|
1702
|
+
if (!isManagedPluginTools && !isManagedOpenClawTools || !("command" in server)) return server;
|
|
1703
|
+
changed = true;
|
|
1704
|
+
const env = [...server.env.filter((entry) => entry.name !== OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY_ENV), {
|
|
1705
|
+
name: OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY_ENV,
|
|
1706
|
+
value: sessionKey
|
|
1707
|
+
}];
|
|
1708
|
+
return {
|
|
1709
|
+
...server,
|
|
1710
|
+
env,
|
|
1711
|
+
args: target.agentId ? [
|
|
1712
|
+
...server.args,
|
|
1713
|
+
"--openclaw-agent-id",
|
|
1714
|
+
target.agentId
|
|
1715
|
+
] : server.args
|
|
1716
|
+
};
|
|
1943
1717
|
});
|
|
1718
|
+
return changed ? nextServers : servers;
|
|
1944
1719
|
},
|
|
1945
1720
|
processLifecycle: {
|
|
1946
1721
|
onBeforeSpawn: async (launch) => {
|
|
@@ -2033,9 +1808,9 @@ var AcpxRuntime$1 = class {
|
|
|
2033
1808
|
const recordId = oneShot ? persistedHandle?.acpxRecordId : sessionKey;
|
|
2034
1809
|
if (!recordId) return;
|
|
2035
1810
|
const record = await this.sessionStore.load(recordId);
|
|
2036
|
-
if (!record ||
|
|
2037
|
-
if (oneShot && (record.acpxRecordId !== recordId ||
|
|
2038
|
-
const recordCwd =
|
|
1811
|
+
if (!record || record.acpx?.reset_on_next_ensure === true) return;
|
|
1812
|
+
if (oneShot && (record.acpxRecordId !== recordId || record.name !== sessionKey || record.acpSessionId !== (persistedHandle?.backendSessionId ?? decoded?.backendSessionId) || !record.agentCapabilities?.loadSession && !record.agentCapabilities?.sessionCapabilities?.resume || record.lastPromptAt !== void 0 || record.messages.some((message) => typeof message !== "string" && "User" in message))) return;
|
|
1813
|
+
const recordCwd = record.cwd?.trim();
|
|
2039
1814
|
const recordCommand = readRecordAgentCommand(record);
|
|
2040
1815
|
if (!recordCwd || !recordCommand || path.resolve(recordCwd) !== path.resolve(input.cwd?.trim() || this.cwd) || !oneShot && resumeSessionId && record.acpSessionId !== resumeSessionId) return;
|
|
2041
1816
|
const lease = readAcpxProcessLeaseIdentity(recordCommand);
|
|
@@ -2126,7 +1901,7 @@ var AcpxRuntime$1 = class {
|
|
|
2126
1901
|
const record = await this.sessionStore.load(params.handle.acpxRecordId ?? resolveAcpxSessionResource(params.handle));
|
|
2127
1902
|
return readCodexWrapperStderrTail({
|
|
2128
1903
|
wrapperRoot: this.wrapperRoot,
|
|
2129
|
-
leaseId:
|
|
1904
|
+
leaseId: record?.openclawLeaseId
|
|
2130
1905
|
});
|
|
2131
1906
|
}
|
|
2132
1907
|
async findSession(input) {
|
|
@@ -2467,36 +2242,6 @@ function resolveAgentProcessEnv() {
|
|
|
2467
2242
|
if (process.env.TOKIO_WORKER_THREADS?.trim()) return;
|
|
2468
2243
|
return { TOKIO_WORKER_THREADS: String(Math.min(availableParallelism(), MAX_ACPX_TOKIO_WORKER_THREADS)) };
|
|
2469
2244
|
}
|
|
2470
|
-
async function createDefaultRuntime(params) {
|
|
2471
|
-
const names = await fs$1.readdir(path.join(params.pluginConfig.stateDir, "sessions")).catch((error) => {
|
|
2472
|
-
if (error instanceof Error && "code" in error && error.code === "ENOENT") return [];
|
|
2473
|
-
throw error;
|
|
2474
|
-
});
|
|
2475
|
-
const legacyBareSessionKeys = /* @__PURE__ */ new Set();
|
|
2476
|
-
for (const name of names) {
|
|
2477
|
-
if (!name.endsWith(".json")) continue;
|
|
2478
|
-
const recordId = decodeURIComponent(name.slice(0, -5));
|
|
2479
|
-
if (!recordId.startsWith("agent:") && !recordId.startsWith(".openclaw-owner-") && !recordId.includes(":oneshot:")) legacyBareSessionKeys.add(recordId.toLowerCase());
|
|
2480
|
-
}
|
|
2481
|
-
return new AcpxRuntime$1({
|
|
2482
|
-
cwd: params.pluginConfig.cwd,
|
|
2483
|
-
agentProcessEnv: resolveAgentProcessEnv(),
|
|
2484
|
-
openclawLegacyBareSessionKeys: legacyBareSessionKeys,
|
|
2485
|
-
openclawGatewayInstanceId: params.gatewayInstanceId,
|
|
2486
|
-
openclawProcessLeaseStore: params.processLeaseStore,
|
|
2487
|
-
openclawWrapperRoot: params.wrapperRoot,
|
|
2488
|
-
sessionStore: createFileSessionStore({ stateDir: params.pluginConfig.stateDir }),
|
|
2489
|
-
agentRegistry: createAgentRegistry({ overrides: params.pluginConfig.agents }),
|
|
2490
|
-
getProbeAgent: params.getProbeAgent,
|
|
2491
|
-
mcpServers: toAcpMcpServers(params.pluginConfig.mcpServers),
|
|
2492
|
-
pluginToolsMcpBridgeEnabled: params.pluginConfig.pluginToolsMcpBridge,
|
|
2493
|
-
openclawToolsMcpBridgeEnabled: params.pluginConfig.openClawToolsMcpBridge,
|
|
2494
|
-
permissionMode: params.pluginConfig.permissionMode,
|
|
2495
|
-
nonInteractivePermissions: params.pluginConfig.nonInteractivePermissions,
|
|
2496
|
-
elicitationModes: ["form", "url"],
|
|
2497
|
-
timeoutMs: resolveAcpxTimerTimeoutMs(params.pluginConfig.timeoutSeconds)
|
|
2498
|
-
});
|
|
2499
|
-
}
|
|
2500
2245
|
function formatDoctorFailureMessage(report) {
|
|
2501
2246
|
const detailText = report.details?.map((detail) => detail.trim()).filter(Boolean).join("; ");
|
|
2502
2247
|
return detailText ? `${report.message} (${detailText})` : report.message;
|
|
@@ -2524,7 +2269,6 @@ async function resolveGatewayInstanceId(openKeyedStore) {
|
|
|
2524
2269
|
async function reapOpenAcpxProcessLeases(params) {
|
|
2525
2270
|
const { assertCurrent } = params;
|
|
2526
2271
|
const leases = await params.leaseStore.listOpen(params.gatewayInstanceId);
|
|
2527
|
-
const inspectedPids = [];
|
|
2528
2272
|
const terminatedPids = [];
|
|
2529
2273
|
const legacyWrapperRoots = /* @__PURE__ */ new Set();
|
|
2530
2274
|
for (const lease of leases) {
|
|
@@ -2544,7 +2288,6 @@ async function reapOpenAcpxProcessLeases(params) {
|
|
|
2544
2288
|
wrapperRoot: lease.wrapperRoot,
|
|
2545
2289
|
assertCurrent
|
|
2546
2290
|
});
|
|
2547
|
-
inspectedPids.push(...result.inspectedPids);
|
|
2548
2291
|
terminatedPids.push(...result.terminatedPids);
|
|
2549
2292
|
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");
|
|
2550
2293
|
await params.leaseStore.markState(lease.leaseId, retryableEvidenceFailure ? "open" : result.terminatedPids.length > 0 ? "closed" : "lost");
|
|
@@ -2554,13 +2297,9 @@ async function reapOpenAcpxProcessLeases(params) {
|
|
|
2554
2297
|
wrapperRoot,
|
|
2555
2298
|
assertCurrent
|
|
2556
2299
|
});
|
|
2557
|
-
inspectedPids.push(...legacyResult.inspectedPids);
|
|
2558
2300
|
terminatedPids.push(...legacyResult.terminatedPids);
|
|
2559
2301
|
}
|
|
2560
|
-
return {
|
|
2561
|
-
inspectedPids,
|
|
2562
|
-
terminatedPids
|
|
2563
|
-
};
|
|
2302
|
+
return { terminatedPids };
|
|
2564
2303
|
}
|
|
2565
2304
|
function createAcpxRuntimeService(params) {
|
|
2566
2305
|
let runtime = null;
|
|
@@ -2591,7 +2330,6 @@ function createAcpxRuntimeService(params) {
|
|
|
2591
2330
|
return;
|
|
2592
2331
|
}
|
|
2593
2332
|
const openKeyedStore = params.openKeyedStore;
|
|
2594
|
-
if (!openKeyedStore) throw new Error("ACPX runtime service requires plugin keyed state");
|
|
2595
2333
|
const basePluginConfig = await measureAcpxStartup(ctx, "config.resolve", () => resolveAcpxPluginConfig({
|
|
2596
2334
|
rawConfig: params.pluginConfig,
|
|
2597
2335
|
workspaceDir: ctx.workspaceDir,
|
|
@@ -2626,14 +2364,38 @@ function createAcpxRuntimeService(params) {
|
|
|
2626
2364
|
if (params.startupPurpose !== "inspection") await promote(ctx);
|
|
2627
2365
|
const getAllowedAgents = params.getAllowedAgents ?? (() => ctx.config.acp?.allowedAgents);
|
|
2628
2366
|
const getProbeAgent = () => pluginConfig.probeAgent ?? getAllowedAgents()?.map(normalizeLowercaseStringOrEmpty).find(Boolean);
|
|
2629
|
-
const startedRuntime = await measureAcpxStartup(ctx, "runtime.create", () =>
|
|
2630
|
-
pluginConfig,
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2367
|
+
const startedRuntime = await measureAcpxStartup(ctx, "runtime.create", async () => {
|
|
2368
|
+
const names = await fs$1.readdir(path.join(pluginConfig.stateDir, "sessions")).catch((error) => {
|
|
2369
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") return [];
|
|
2370
|
+
throw error;
|
|
2371
|
+
});
|
|
2372
|
+
const legacyBareSessionKeys = /* @__PURE__ */ new Set();
|
|
2373
|
+
for (const name of names) {
|
|
2374
|
+
if (!name.endsWith(".json")) continue;
|
|
2375
|
+
const recordId = decodeURIComponent(name.slice(0, -5));
|
|
2376
|
+
if (!recordId.startsWith("agent:") && !recordId.startsWith(".openclaw-owner-") && !recordId.includes(":oneshot:")) legacyBareSessionKeys.add(recordId.toLowerCase());
|
|
2377
|
+
}
|
|
2378
|
+
return new AcpxRuntime$1({
|
|
2379
|
+
cwd: pluginConfig.cwd,
|
|
2380
|
+
agentProcessEnv: resolveAgentProcessEnv(),
|
|
2381
|
+
agentProcessEnvAllow: pluginConfig.agentProcessEnvAllow,
|
|
2382
|
+
agentProcessEnvBlock: pluginConfig.agentProcessEnvBlock,
|
|
2383
|
+
openclawLegacyBareSessionKeys: legacyBareSessionKeys,
|
|
2384
|
+
openclawGatewayInstanceId: gatewayInstanceId,
|
|
2385
|
+
openclawProcessLeaseStore: processLeaseStore,
|
|
2386
|
+
openclawWrapperRoot: wrapperRoot,
|
|
2387
|
+
sessionStore: createFileSessionStore({ stateDir: pluginConfig.stateDir }),
|
|
2388
|
+
agentRegistry: createAgentRegistry({ overrides: pluginConfig.agents }),
|
|
2389
|
+
getProbeAgent,
|
|
2390
|
+
mcpServers: toAcpMcpServers(pluginConfig.mcpServers),
|
|
2391
|
+
pluginToolsMcpBridgeEnabled: pluginConfig.pluginToolsMcpBridge,
|
|
2392
|
+
openclawToolsMcpBridgeEnabled: pluginConfig.openClawToolsMcpBridge,
|
|
2393
|
+
permissionMode: pluginConfig.permissionMode,
|
|
2394
|
+
nonInteractivePermissions: pluginConfig.nonInteractivePermissions,
|
|
2395
|
+
elicitationModes: ["form", "url"],
|
|
2396
|
+
timeoutMs: resolveAcpxTimerTimeoutMs(pluginConfig.timeoutSeconds)
|
|
2397
|
+
});
|
|
2398
|
+
});
|
|
2637
2399
|
runtime = startedRuntime;
|
|
2638
2400
|
const shouldProbeRuntime = params.probeAtStartup !== false && shouldProbeRuntimeAtStartup();
|
|
2639
2401
|
ctx.startupTrace?.detail?.("probe-policy", [["startupProbeEnabledCount", shouldProbeRuntime ? 1 : 0], ["probeAgent", getProbeAgent() ?? "default"]]);
|