@openclaw/acpx 2026.10.10-beta.5 → 2026.11.5-beta.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/.setup/{config-D0ATuiVJ.mjs → config-Cplh34lQ.mjs} +19 -31
- package/dist/.setup/{harness-attempt-lu4_bMfd.mjs → harness-attempt-Co9oLpPg.mjs} +6 -6
- package/dist/.setup/{pi-session-catalog-runtime-BAM1pEMw.mjs → pi-session-catalog-runtime-DgzkbadO.mjs} +39 -65
- package/dist/.setup/{pi-session-paths-CIvyk6KB.mjs → pi-session-paths-pUr6hnVA.mjs} +4 -6
- package/dist/.setup/{runtime-doctor-migrations-hxP-CXX7.mjs → runtime-doctor-migrations-CSvRANPN.mjs} +5 -10
- package/dist/.setup/{service-c789tPe9.mjs → service-DmgP1gPb.mjs} +147 -397
- package/dist/.setup/{session-owner-migration-duvwZfxk.mjs → session-owner-migration-CQA7L68K.mjs} +17 -17
- package/dist/.setup/{session-resource-DKJsUJPu.mjs → session-resource-D_tXKvcv.mjs} +4 -5
- package/dist/.source-module-urls/9369b1b274d2ba70ea21d859abb3415ad8d63d0a1022a301763b953a5798469e.json +1 -0
- package/dist/doctor-contract-api.js +19 -14
- package/dist/index.js +210 -29
- package/dist/setup-api.js +1 -2
- package/openclaw.plugin.json +28 -1
- package/package.json +10 -10
- package/dist/.setup/register.runtime-CVKZRCrC.mjs +0 -197
- package/dist/.source-module-urls/78a9d561eb54d4bf1ca0db6e6d12bb5688647241f2c0b289c611a0effb44d715.json +0 -1
- package/dist/register.runtime.js +0 -1
|
@@ -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-Cplh34lQ.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-D_tXKvcv.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-CQA7L68K.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,12 +18,11 @@ 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";
|
|
24
24
|
import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
|
|
25
|
-
|
|
25
|
+
// extensions/acpx/src/adapter-wrapper-script.ts
|
|
26
26
|
const RUN_CONFIGURED_COMMAND_SENTINEL = "--openclaw-run-configured";
|
|
27
27
|
const DIAGNOSTIC_REDACTION_RULES = [
|
|
28
28
|
{
|
|
@@ -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
|
});
|
|
@@ -489,123 +485,7 @@ child.on("close", () => {
|
|
|
489
485
|
main();
|
|
490
486
|
`;
|
|
491
487
|
}
|
|
492
|
-
|
|
493
|
-
//#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
|
-
}
|
|
488
|
+
// extensions/acpx/src/codex-trust-config.ts
|
|
609
489
|
const INHERITED_TOP_LEVEL_CODEX_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
610
490
|
"model",
|
|
611
491
|
"model_provider",
|
|
@@ -623,61 +503,30 @@ const INHERITED_MODEL_PROVIDER_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
623
503
|
"stream_max_retries",
|
|
624
504
|
"stream_idle_timeout_ms"
|
|
625
505
|
]);
|
|
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
506
|
function renderIsolatedCodexConfig(params) {
|
|
676
|
-
|
|
507
|
+
let source = {};
|
|
508
|
+
if (params.sourceConfigToml) try {
|
|
509
|
+
source = parse(params.sourceConfigToml, { integersAsBigInt: true });
|
|
510
|
+
} catch {
|
|
511
|
+
throw new Error("Codex config.toml must be valid TOML before starting an ACP session.");
|
|
512
|
+
}
|
|
513
|
+
const providers = /* @__PURE__ */ new Map();
|
|
514
|
+
if (isRecord(source.model_providers)) for (const [name, provider] of Object.entries(source.model_providers)) {
|
|
515
|
+
if (!isRecord(provider)) continue;
|
|
516
|
+
const config = Object.fromEntries(Object.entries(provider).filter(([key]) => INHERITED_MODEL_PROVIDER_CONFIG_KEYS.has(key)));
|
|
517
|
+
if (Object.keys(config).length) providers.set(name, config);
|
|
518
|
+
}
|
|
519
|
+
const inherited = {
|
|
520
|
+
...Object.fromEntries(Object.entries(source).filter(([key]) => INHERITED_TOP_LEVEL_CODEX_CONFIG_KEYS.has(key))),
|
|
521
|
+
...providers.size ? { model_providers: Object.fromEntries(providers) } : {},
|
|
522
|
+
...params.mcpServers ? { mcp_servers: params.mcpServers } : {}
|
|
523
|
+
};
|
|
524
|
+
const trustedProjects = isRecord(source.projects) ? Object.entries(source.projects).filter(([, project]) => isRecord(project) && project.trust_level === "trusted").map(([projectPath]) => projectPath) : [];
|
|
525
|
+
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
526
|
return [
|
|
678
527
|
"# Generated by OpenClaw for Codex ACP sessions.",
|
|
679
|
-
|
|
680
|
-
...
|
|
528
|
+
stringify(inherited, { numbersAsFloat: true }).trimEnd(),
|
|
529
|
+
...projectPaths.flatMap((projectPath) => [
|
|
681
530
|
"",
|
|
682
531
|
`[projects.${JSON.stringify(projectPath)}]`,
|
|
683
532
|
"trust_level = \"trusted\""
|
|
@@ -685,8 +534,7 @@ function renderIsolatedCodexConfig(params) {
|
|
|
685
534
|
""
|
|
686
535
|
].filter((line, index, lines) => !(line === "" && lines[index - 1] === "")).join("\n");
|
|
687
536
|
}
|
|
688
|
-
|
|
689
|
-
//#region extensions/acpx/src/codex-auth-bridge.ts
|
|
537
|
+
// extensions/acpx/src/codex-auth-bridge.ts
|
|
690
538
|
/**
|
|
691
539
|
* Prepares isolated Codex and Claude ACP wrapper commands for ACPX. The bridge
|
|
692
540
|
* copies safe auth/config state into plugin-owned homes and redacts diagnostics.
|
|
@@ -846,17 +694,15 @@ async function readSourceCodexConfig(codexHome) {
|
|
|
846
694
|
}
|
|
847
695
|
async function prepareIsolatedCodexHome(params) {
|
|
848
696
|
const sourceConfig = await readSourceCodexConfig(process.env.CODEX_HOME || path.join(os.homedir(), ".codex"));
|
|
849
|
-
const trustedProjectPaths = [...sourceConfig ? extractTrustedCodexProjectPaths(sourceConfig) : [], params.workspaceDir];
|
|
850
697
|
const codexHome = path.join(params.baseDir, "codex-home");
|
|
851
698
|
await fs$1.mkdir(codexHome, { recursive: true });
|
|
852
699
|
await fs$1.writeFile(path.join(codexHome, "config.toml"), renderIsolatedCodexConfig({
|
|
853
700
|
sourceConfigToml: sourceConfig,
|
|
854
|
-
projectPaths:
|
|
701
|
+
projectPaths: [params.workspaceDir],
|
|
702
|
+
mcpServers: isRecord(params.migratedConfig?.mcp_servers) ? params.migratedConfig.mcp_servers : void 0
|
|
855
703
|
}), "utf8");
|
|
856
|
-
return codexHome;
|
|
857
704
|
}
|
|
858
705
|
async function writeAdapterWrapper(baseDir, fileName, script) {
|
|
859
|
-
await fs$1.mkdir(baseDir, { recursive: true });
|
|
860
706
|
const wrapperPath = path.join(baseDir, fileName);
|
|
861
707
|
await fs$1.writeFile(wrapperPath, script, { encoding: "utf8" });
|
|
862
708
|
try {
|
|
@@ -968,13 +814,6 @@ function resolveCodexAdapterLaunch(configuredCommand) {
|
|
|
968
814
|
if (!maintainedAdapterArgs) return;
|
|
969
815
|
return { args: maintainedAdapterArgs };
|
|
970
816
|
}
|
|
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
817
|
function buildClaudeAcpWrapperCommand(wrapperPath, configuredCommand) {
|
|
979
818
|
const configuredAdapterArgs = extractConfiguredAdapterArgs({
|
|
980
819
|
configuredCommand,
|
|
@@ -990,17 +829,15 @@ async function prepareAcpxCodexAuthConfig(params) {
|
|
|
990
829
|
const configuredCodexCommand = params.pluginConfig.agents.codex;
|
|
991
830
|
const configuredClaudeCommand = params.pluginConfig.agents.claude;
|
|
992
831
|
const codexLaunch = resolveCodexAdapterLaunch(configuredCodexCommand);
|
|
993
|
-
await
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
workspaceDir: params.pluginConfig.cwd
|
|
997
|
-
}),
|
|
832
|
+
await prepareIsolatedCodexHome({
|
|
833
|
+
baseDir: codexBaseDir,
|
|
834
|
+
workspaceDir: params.pluginConfig.cwd,
|
|
998
835
|
migratedConfig: codexLaunch?.migratedConfig
|
|
999
836
|
});
|
|
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(
|
|
837
|
+
const codexBinPath = await resolveInstalledAcpPackageBinPath(CODEX_ACP_PACKAGE, CODEX_ACP_BIN);
|
|
838
|
+
const claudeBinPath = await resolveInstalledAcpPackageBinPath(CLAUDE_ACP_PACKAGE, CLAUDE_ACP_BIN);
|
|
839
|
+
const wrapperPath = await writeAdapterWrapper(codexBaseDir, "codex-acp-wrapper.mjs", buildCodexAcpWrapperScript(codexBinPath));
|
|
840
|
+
const claudeWrapperPath = await writeAdapterWrapper(codexBaseDir, "claude-agent-acp-wrapper.mjs", buildClaudeAcpWrapperScript(claudeBinPath));
|
|
1004
841
|
return {
|
|
1005
842
|
...params.pluginConfig,
|
|
1006
843
|
agents: {
|
|
@@ -1010,8 +847,7 @@ async function prepareAcpxCodexAuthConfig(params) {
|
|
|
1010
847
|
}
|
|
1011
848
|
};
|
|
1012
849
|
}
|
|
1013
|
-
|
|
1014
|
-
//#region extensions/acpx/src/process-reaper.ts
|
|
850
|
+
// extensions/acpx/src/process-reaper.ts
|
|
1015
851
|
/**
|
|
1016
852
|
* ACPX process ownership checks and cleanup. The reaper only terminates
|
|
1017
853
|
* OpenClaw-owned wrapper trees after validating paths, packages, and lease ids.
|
|
@@ -1127,12 +963,16 @@ function parseProcessList(stdout) {
|
|
|
1127
963
|
}
|
|
1128
964
|
async function listPlatformProcesses() {
|
|
1129
965
|
if (process.platform === "win32") return [];
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
966
|
+
try {
|
|
967
|
+
const { stdout } = await runExec("ps", ["-axo", "pid=,ppid=,command="], {
|
|
968
|
+
logOutput: false,
|
|
969
|
+
maxBuffer: 8388608,
|
|
970
|
+
timeoutMs: ACPX_PROCESS_LIST_TIMEOUT_MS
|
|
971
|
+
});
|
|
972
|
+
return parseProcessList(stdout);
|
|
973
|
+
} catch {
|
|
974
|
+
return;
|
|
975
|
+
}
|
|
1136
976
|
}
|
|
1137
977
|
function collectProcessTree(processes, rootPid) {
|
|
1138
978
|
const childrenByParent = /* @__PURE__ */ new Map();
|
|
@@ -1141,7 +981,7 @@ function collectProcessTree(processes, rootPid) {
|
|
|
1141
981
|
children.push(processInfo);
|
|
1142
982
|
childrenByParent.set(processInfo.ppid, children);
|
|
1143
983
|
}
|
|
1144
|
-
const root =
|
|
984
|
+
const root = processes.find((processInfo) => processInfo.pid === rootPid);
|
|
1145
985
|
const collected = [];
|
|
1146
986
|
if (root) collected.push(root);
|
|
1147
987
|
const queue = [...childrenByParent.get(rootPid) ?? []];
|
|
@@ -1179,28 +1019,20 @@ async function terminatePids(pids, assertCurrent) {
|
|
|
1179
1019
|
async function cleanupOpenClawOwnedAcpxProcessTree(params) {
|
|
1180
1020
|
const rootPid = params.rootPid;
|
|
1181
1021
|
if (!rootPid || rootPid <= 0 || rootPid === process.pid) return {
|
|
1182
|
-
inspectedPids: [],
|
|
1183
1022
|
terminatedPids: [],
|
|
1184
1023
|
skippedReason: "missing-root"
|
|
1185
1024
|
};
|
|
1186
1025
|
if (process.platform === "win32") return {
|
|
1187
|
-
inspectedPids: [],
|
|
1188
1026
|
terminatedPids: [],
|
|
1189
1027
|
skippedReason: "unsupported-platform"
|
|
1190
1028
|
};
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
inspectedPids: [],
|
|
1197
|
-
terminatedPids: [],
|
|
1198
|
-
skippedReason: "process-list-unavailable"
|
|
1199
|
-
};
|
|
1200
|
-
}
|
|
1029
|
+
const processes = await listPlatformProcesses();
|
|
1030
|
+
if (!processes) return {
|
|
1031
|
+
terminatedPids: [],
|
|
1032
|
+
skippedReason: "process-list-unavailable"
|
|
1033
|
+
};
|
|
1201
1034
|
const listedTree = collectProcessTree(processes, rootPid);
|
|
1202
1035
|
if (listedTree.length === 0) return {
|
|
1203
|
-
inspectedPids: [],
|
|
1204
1036
|
terminatedPids: [],
|
|
1205
1037
|
skippedReason: "unverified-root"
|
|
1206
1038
|
};
|
|
@@ -1215,88 +1047,58 @@ async function cleanupOpenClawOwnedAcpxProcessTree(params) {
|
|
|
1215
1047
|
expectedLeaseId: params.expectedLeaseId,
|
|
1216
1048
|
expectedGatewayInstanceId: params.expectedGatewayInstanceId
|
|
1217
1049
|
})) return {
|
|
1218
|
-
inspectedPids: listedTree.map((processInfo) => processInfo.pid),
|
|
1219
1050
|
terminatedPids: [],
|
|
1220
1051
|
skippedReason: "not-openclaw-owned"
|
|
1221
1052
|
};
|
|
1222
|
-
|
|
1223
|
-
return {
|
|
1224
|
-
inspectedPids: uniquePids(listedTree),
|
|
1225
|
-
terminatedPids: await terminatePids(pids, params.assertCurrent)
|
|
1226
|
-
};
|
|
1053
|
+
return { terminatedPids: await terminatePids(uniquePids(listedTree.toReversed()), params.assertCurrent) };
|
|
1227
1054
|
}
|
|
1228
1055
|
/** Recover a pending lease by matching its exact live wrapper identity. */
|
|
1229
1056
|
async function cleanupOpenClawOwnedAcpxPendingLease(params) {
|
|
1230
1057
|
if (process.platform === "win32") return {
|
|
1231
|
-
inspectedPids: [],
|
|
1232
1058
|
terminatedPids: [],
|
|
1233
1059
|
skippedReason: "unsupported-platform"
|
|
1234
1060
|
};
|
|
1235
1061
|
if (!params.wrapperPath || !wrapperPathBelongsToRoot(params.wrapperPath, params.wrapperRoot)) return {
|
|
1236
|
-
inspectedPids: [],
|
|
1237
1062
|
terminatedPids: [],
|
|
1238
1063
|
skippedReason: "unverified-root"
|
|
1239
1064
|
};
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
inspectedPids: [],
|
|
1246
|
-
terminatedPids: [],
|
|
1247
|
-
skippedReason: "process-list-unavailable"
|
|
1248
|
-
};
|
|
1249
|
-
}
|
|
1065
|
+
const processes = await listPlatformProcesses();
|
|
1066
|
+
if (!processes) return {
|
|
1067
|
+
terminatedPids: [],
|
|
1068
|
+
skippedReason: "process-list-unavailable"
|
|
1069
|
+
};
|
|
1250
1070
|
const matchingRoots = processes.filter((processInfo) => commandContainsExactWrapperPath(processInfo.command, params.wrapperPath) && liveCommandMatchesLeaseIdentity({
|
|
1251
1071
|
command: processInfo.command,
|
|
1252
1072
|
expectedLeaseId: params.leaseId,
|
|
1253
1073
|
expectedGatewayInstanceId: params.gatewayInstanceId
|
|
1254
1074
|
}));
|
|
1255
1075
|
if (matchingRoots.length === 0) return {
|
|
1256
|
-
inspectedPids: [],
|
|
1257
1076
|
terminatedPids: [],
|
|
1258
1077
|
skippedReason: "missing-root"
|
|
1259
1078
|
};
|
|
1260
1079
|
if (matchingRoots.length > 1) return {
|
|
1261
|
-
inspectedPids: uniquePids(matchingRoots),
|
|
1262
1080
|
terminatedPids: [],
|
|
1263
1081
|
skippedReason: "ambiguous-root"
|
|
1264
1082
|
};
|
|
1265
|
-
|
|
1266
|
-
const pids = uniquePids(listedTree.toReversed());
|
|
1267
|
-
return {
|
|
1268
|
-
inspectedPids: uniquePids(listedTree),
|
|
1269
|
-
terminatedPids: await terminatePids(pids, params.assertCurrent)
|
|
1270
|
-
};
|
|
1083
|
+
return { terminatedPids: await terminatePids(uniquePids(collectProcessTree(processes, matchingRoots[0].pid).toReversed()), params.assertCurrent) };
|
|
1271
1084
|
}
|
|
1272
1085
|
/** Reap orphaned OpenClaw-owned ACPX wrapper trees during runtime startup. */
|
|
1273
1086
|
async function reapStaleOpenClawOwnedAcpxOrphans(params) {
|
|
1274
1087
|
if (process.platform === "win32") return {
|
|
1275
|
-
inspectedPids: [],
|
|
1276
1088
|
terminatedPids: [],
|
|
1277
1089
|
skippedReason: "unsupported-platform"
|
|
1278
1090
|
};
|
|
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({
|
|
1091
|
+
const processes = await listPlatformProcesses();
|
|
1092
|
+
if (!processes) return {
|
|
1093
|
+
terminatedPids: [],
|
|
1094
|
+
skippedReason: "process-list-unavailable"
|
|
1095
|
+
};
|
|
1096
|
+
return { terminatedPids: await terminatePids(uniquePids(processes.filter((processInfo) => processInfo.ppid === 1 && !readAcpxProcessLeaseIdentity(processInfo.command) && isOpenClawOwnedAcpxProcessCommand({
|
|
1290
1097
|
command: processInfo.command,
|
|
1291
1098
|
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
|
-
};
|
|
1099
|
+
})).map((orphan) => collectProcessTree(processes, orphan.pid)).flatMap((tree) => tree.toReversed())), params.assertCurrent) };
|
|
1297
1100
|
}
|
|
1298
|
-
|
|
1299
|
-
//#region extensions/acpx/src/model-ref.ts
|
|
1101
|
+
// extensions/acpx/src/model-ref.ts
|
|
1300
1102
|
function withAcpxSessionOptions(input) {
|
|
1301
1103
|
const model = input.model?.trim() || input.sessionOptions?.model;
|
|
1302
1104
|
const sessionOptions = model ? {
|
|
@@ -1335,8 +1137,7 @@ async function ensureSessionWithModelRef(ensureSession, input) {
|
|
|
1335
1137
|
};
|
|
1336
1138
|
}
|
|
1337
1139
|
}
|
|
1338
|
-
|
|
1339
|
-
//#region extensions/acpx/src/runtime-generations.ts
|
|
1140
|
+
// extensions/acpx/src/runtime-generations.ts
|
|
1340
1141
|
var AcpxGenerationRegistry = class {
|
|
1341
1142
|
constructor(sessionStore, delegate, createDelegate) {
|
|
1342
1143
|
this.sessionStore = sessionStore;
|
|
@@ -1461,8 +1262,7 @@ var AcpxGenerationRegistry = class {
|
|
|
1461
1262
|
this.isolatedSessionResources.clear();
|
|
1462
1263
|
}
|
|
1463
1264
|
};
|
|
1464
|
-
|
|
1465
|
-
//#region extensions/acpx/src/runtime-probe.ts
|
|
1265
|
+
// extensions/acpx/src/runtime-probe.ts
|
|
1466
1266
|
var AcpxRuntimeProbe = class {
|
|
1467
1267
|
constructor(params) {
|
|
1468
1268
|
this.params = params;
|
|
@@ -1495,8 +1295,7 @@ var AcpxRuntimeProbe = class {
|
|
|
1495
1295
|
await this.tail;
|
|
1496
1296
|
}
|
|
1497
1297
|
};
|
|
1498
|
-
|
|
1499
|
-
//#region extensions/acpx/src/runtime-session-store.ts
|
|
1298
|
+
// extensions/acpx/src/runtime-session-store.ts
|
|
1500
1299
|
/** Generation-bound persistence and process-lease metadata for ACPX resets. */
|
|
1501
1300
|
function withOpenClawLeaseSessionMetadata(record, lease) {
|
|
1502
1301
|
return {
|
|
@@ -1511,30 +1310,9 @@ function captureGenerationRecord(generation, record) {
|
|
|
1511
1310
|
}
|
|
1512
1311
|
const acpxGenerationKey = Symbol("openclaw.acpxGeneration");
|
|
1513
1312
|
const acpxOperationScope = new AsyncLocalStorage();
|
|
1514
|
-
function readSessionRecordName(record) {
|
|
1515
|
-
return normalizeOptionalString(asOptionalObjectRecord(record)?.name) ?? "";
|
|
1516
|
-
}
|
|
1517
1313
|
function readRecordAgentCommand(record) {
|
|
1518
1314
|
return record?.agentArgv ?? record?.agentCommand;
|
|
1519
1315
|
}
|
|
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
1316
|
function extractGeneratedWrapperPath(command) {
|
|
1539
1317
|
return splitCommandParts(command ?? "").find((part) => (part.split(/[\\/]/).pop() ?? "") === "codex-acp-wrapper.mjs" || (part.split(/[\\/]/).pop() ?? "") === "claude-agent-acp-wrapper.mjs") ?? "";
|
|
1540
1318
|
}
|
|
@@ -1563,11 +1341,11 @@ function createResetAwareSessionStore(baseStore, params) {
|
|
|
1563
1341
|
const record = await baseStore.load(sessionId);
|
|
1564
1342
|
if (scope && record) captureGenerationRecord(scope.generation, record);
|
|
1565
1343
|
if (!record || !params?.leaseStore || !params.gatewayInstanceId) return record;
|
|
1566
|
-
const sessionName =
|
|
1344
|
+
const sessionName = record.name || normalized;
|
|
1567
1345
|
const lease = selectCurrentSessionLease({
|
|
1568
1346
|
leases: await params.leaseStore.listOpen(params.gatewayInstanceId),
|
|
1569
1347
|
sessionKeys: [sessionName, normalized],
|
|
1570
|
-
rootPid:
|
|
1348
|
+
rootPid: record.pid
|
|
1571
1349
|
});
|
|
1572
1350
|
if (!lease) return record;
|
|
1573
1351
|
const leasedRecord = withOpenClawLeaseSessionMetadata(record, lease);
|
|
@@ -1589,7 +1367,7 @@ function createResetAwareSessionStore(baseStore, params) {
|
|
|
1589
1367
|
}
|
|
1590
1368
|
let recordToSave = record;
|
|
1591
1369
|
const launch = params?.launchScope?.getStore();
|
|
1592
|
-
const sessionName =
|
|
1370
|
+
const sessionName = record.name;
|
|
1593
1371
|
const agentCommand = readRecordAgentCommand(record);
|
|
1594
1372
|
const leasedCommand = launch?.leasedCommand ?? agentCommand;
|
|
1595
1373
|
const leaseIdentity = launch ?? readAcpxProcessLeaseIdentity(leasedCommand);
|
|
@@ -1638,17 +1416,16 @@ function createResetAwareSessionStore(baseStore, params) {
|
|
|
1638
1416
|
}
|
|
1639
1417
|
};
|
|
1640
1418
|
}
|
|
1641
|
-
|
|
1642
|
-
//#region extensions/acpx/src/runtime-process-cleanup.ts
|
|
1419
|
+
// extensions/acpx/src/runtime-process-cleanup.ts
|
|
1643
1420
|
/** Capture OpenClaw wrapper cleanup ownership before a backend close can yield. */
|
|
1644
1421
|
async function prepareAcpxProcessCleanup(params) {
|
|
1645
1422
|
const { leaseStore, gatewayInstanceId, wrapperRoot } = params;
|
|
1646
|
-
const rootPid =
|
|
1423
|
+
const rootPid = params.record?.pid;
|
|
1647
1424
|
const rootCommand = params.command ? renderAgentCommand(params.command) : void 0;
|
|
1648
1425
|
const identity = readAcpxProcessLeaseIdentity(params.command);
|
|
1649
|
-
const leaseId =
|
|
1650
|
-
const expectedGatewayInstanceId =
|
|
1651
|
-
const sessionKeys = [params.sessionKey,
|
|
1426
|
+
const leaseId = params.record?.openclawLeaseId ?? identity?.leaseId;
|
|
1427
|
+
const expectedGatewayInstanceId = params.record?.openclawGatewayInstanceId ?? identity?.gatewayInstanceId;
|
|
1428
|
+
const sessionKeys = [params.sessionKey, params.record?.name ?? ""];
|
|
1652
1429
|
const openLeases = rootPid && gatewayInstanceId && leaseStore ? await leaseStore.listOpen(gatewayInstanceId) : [];
|
|
1653
1430
|
const selectedLease = rootPid ? selectCurrentSessionLease({
|
|
1654
1431
|
leases: openLeases,
|
|
@@ -1656,8 +1433,7 @@ async function prepareAcpxProcessCleanup(params) {
|
|
|
1656
1433
|
rootPid
|
|
1657
1434
|
}) : void 0;
|
|
1658
1435
|
const loadedLease = leaseId ? await leaseStore?.load(leaseId) : void 0;
|
|
1659
|
-
const
|
|
1660
|
-
const lease = ownedLease ? { ...ownedLease } : void 0;
|
|
1436
|
+
const lease = selectedLease ?? (loadedLease && loadedLease.gatewayInstanceId === gatewayInstanceId && (!rootPid || loadedLease.rootPid === rootPid) && sessionKeys.includes(loadedLease.sessionKey) ? loadedLease : void 0);
|
|
1661
1437
|
return async () => {
|
|
1662
1438
|
if (lease && lease.gatewayInstanceId === gatewayInstanceId) {
|
|
1663
1439
|
await leaseStore?.markState(lease.leaseId, "closing");
|
|
@@ -1686,8 +1462,7 @@ async function prepareAcpxProcessCleanup(params) {
|
|
|
1686
1462
|
});
|
|
1687
1463
|
};
|
|
1688
1464
|
}
|
|
1689
|
-
|
|
1690
|
-
//#region extensions/acpx/src/session-owner.ts
|
|
1465
|
+
// extensions/acpx/src/session-owner.ts
|
|
1691
1466
|
function requireAcpxOwnerMigration(sessionKey) {
|
|
1692
1467
|
throw new AcpRuntimeError("ACP_SESSION_INIT_FAILED", `ACP session "${sessionKey}" has an unqualified or unverifiable backend locator. Stop the Gateway and run "openclaw doctor --fix" to migrate ownership without losing history, then restart.`, { detailCode: "SESSION_OWNER_MIGRATION_REQUIRED" });
|
|
1693
1468
|
}
|
|
@@ -1716,8 +1491,7 @@ function toAcpxResourceInput(input) {
|
|
|
1716
1491
|
}
|
|
1717
1492
|
};
|
|
1718
1493
|
}
|
|
1719
|
-
|
|
1720
|
-
//#region extensions/acpx/src/runtime.ts
|
|
1494
|
+
// extensions/acpx/src/runtime.ts
|
|
1721
1495
|
/**
|
|
1722
1496
|
* OpenClaw ACPX runtime adapter. It wraps the upstream acpx runtime with
|
|
1723
1497
|
* OpenClaw session metadata, lease tracking, model scoping, and cleanup policy.
|
|
@@ -1857,35 +1631,9 @@ function appendCodexAcpConfigOverrides(command, override) {
|
|
|
1857
1631
|
JSON.stringify(config)
|
|
1858
1632
|
];
|
|
1859
1633
|
}
|
|
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
1634
|
function resolveBridgeSession(handle) {
|
|
1886
1635
|
return handle.bridgeSession === void 0 ? handle : handle.bridgeSession;
|
|
1887
1636
|
}
|
|
1888
|
-
/** OpenClaw-managed ACP runtime implementation backed by the upstream acpx runtime. */
|
|
1889
1637
|
var AcpxRuntime$1 = class {
|
|
1890
1638
|
constructor(options, testOptions) {
|
|
1891
1639
|
this.ownerAwareSessions = 1;
|
|
@@ -1935,12 +1683,29 @@ var AcpxRuntime$1 = class {
|
|
|
1935
1683
|
if (target === null) return [];
|
|
1936
1684
|
if (!this.managedToolsMcpBridgeEnabled) return servers;
|
|
1937
1685
|
if (!target) throw new AcpRuntimeError("ACP_SESSION_INIT_FAILED", "ACP tool bridge has no session owner");
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1686
|
+
const sessionKey = target.sessionKey.trim();
|
|
1687
|
+
if (!this.pluginToolsMcpBridgeEnabled && !this.openclawToolsMcpBridgeEnabled || !sessionKey || !servers?.length) return servers;
|
|
1688
|
+
let changed = false;
|
|
1689
|
+
const nextServers = servers.map((server) => {
|
|
1690
|
+
const isManagedPluginTools = this.pluginToolsMcpBridgeEnabled && server.name === ACPX_PLUGIN_TOOLS_MCP_SERVER_NAME;
|
|
1691
|
+
const isManagedOpenClawTools = this.openclawToolsMcpBridgeEnabled && server.name === ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME;
|
|
1692
|
+
if (!isManagedPluginTools && !isManagedOpenClawTools || !("command" in server)) return server;
|
|
1693
|
+
changed = true;
|
|
1694
|
+
const env = [...server.env.filter((entry) => entry.name !== OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY_ENV), {
|
|
1695
|
+
name: OPENCLAW_TOOLS_MCP_AGENT_SESSION_KEY_ENV,
|
|
1696
|
+
value: sessionKey
|
|
1697
|
+
}];
|
|
1698
|
+
return {
|
|
1699
|
+
...server,
|
|
1700
|
+
env,
|
|
1701
|
+
args: target.agentId ? [
|
|
1702
|
+
...server.args,
|
|
1703
|
+
"--openclaw-agent-id",
|
|
1704
|
+
target.agentId
|
|
1705
|
+
] : server.args
|
|
1706
|
+
};
|
|
1943
1707
|
});
|
|
1708
|
+
return changed ? nextServers : servers;
|
|
1944
1709
|
},
|
|
1945
1710
|
processLifecycle: {
|
|
1946
1711
|
onBeforeSpawn: async (launch) => {
|
|
@@ -2033,9 +1798,9 @@ var AcpxRuntime$1 = class {
|
|
|
2033
1798
|
const recordId = oneShot ? persistedHandle?.acpxRecordId : sessionKey;
|
|
2034
1799
|
if (!recordId) return;
|
|
2035
1800
|
const record = await this.sessionStore.load(recordId);
|
|
2036
|
-
if (!record ||
|
|
2037
|
-
if (oneShot && (record.acpxRecordId !== recordId ||
|
|
2038
|
-
const recordCwd =
|
|
1801
|
+
if (!record || record.acpx?.reset_on_next_ensure === true) return;
|
|
1802
|
+
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;
|
|
1803
|
+
const recordCwd = record.cwd?.trim();
|
|
2039
1804
|
const recordCommand = readRecordAgentCommand(record);
|
|
2040
1805
|
if (!recordCwd || !recordCommand || path.resolve(recordCwd) !== path.resolve(input.cwd?.trim() || this.cwd) || !oneShot && resumeSessionId && record.acpSessionId !== resumeSessionId) return;
|
|
2041
1806
|
const lease = readAcpxProcessLeaseIdentity(recordCommand);
|
|
@@ -2126,7 +1891,7 @@ var AcpxRuntime$1 = class {
|
|
|
2126
1891
|
const record = await this.sessionStore.load(params.handle.acpxRecordId ?? resolveAcpxSessionResource(params.handle));
|
|
2127
1892
|
return readCodexWrapperStderrTail({
|
|
2128
1893
|
wrapperRoot: this.wrapperRoot,
|
|
2129
|
-
leaseId:
|
|
1894
|
+
leaseId: record?.openclawLeaseId
|
|
2130
1895
|
});
|
|
2131
1896
|
}
|
|
2132
1897
|
async findSession(input) {
|
|
@@ -2454,8 +2219,7 @@ var AcpxRuntime$1 = class {
|
|
|
2454
2219
|
});
|
|
2455
2220
|
}
|
|
2456
2221
|
};
|
|
2457
|
-
|
|
2458
|
-
//#region extensions/acpx/src/service.ts
|
|
2222
|
+
// extensions/acpx/src/service.ts
|
|
2459
2223
|
const ENABLE_STARTUP_PROBE_ENV = "OPENCLAW_ACPX_RUNTIME_STARTUP_PROBE";
|
|
2460
2224
|
const SKIP_RUNTIME_PROBE_ENV = "OPENCLAW_SKIP_ACPX_RUNTIME_PROBE";
|
|
2461
2225
|
const MAX_ACPX_TOKIO_WORKER_THREADS = 8;
|
|
@@ -2467,36 +2231,6 @@ function resolveAgentProcessEnv() {
|
|
|
2467
2231
|
if (process.env.TOKIO_WORKER_THREADS?.trim()) return;
|
|
2468
2232
|
return { TOKIO_WORKER_THREADS: String(Math.min(availableParallelism(), MAX_ACPX_TOKIO_WORKER_THREADS)) };
|
|
2469
2233
|
}
|
|
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
2234
|
function formatDoctorFailureMessage(report) {
|
|
2501
2235
|
const detailText = report.details?.map((detail) => detail.trim()).filter(Boolean).join("; ");
|
|
2502
2236
|
return detailText ? `${report.message} (${detailText})` : report.message;
|
|
@@ -2524,7 +2258,6 @@ async function resolveGatewayInstanceId(openKeyedStore) {
|
|
|
2524
2258
|
async function reapOpenAcpxProcessLeases(params) {
|
|
2525
2259
|
const { assertCurrent } = params;
|
|
2526
2260
|
const leases = await params.leaseStore.listOpen(params.gatewayInstanceId);
|
|
2527
|
-
const inspectedPids = [];
|
|
2528
2261
|
const terminatedPids = [];
|
|
2529
2262
|
const legacyWrapperRoots = /* @__PURE__ */ new Set();
|
|
2530
2263
|
for (const lease of leases) {
|
|
@@ -2544,7 +2277,6 @@ async function reapOpenAcpxProcessLeases(params) {
|
|
|
2544
2277
|
wrapperRoot: lease.wrapperRoot,
|
|
2545
2278
|
assertCurrent
|
|
2546
2279
|
});
|
|
2547
|
-
inspectedPids.push(...result.inspectedPids);
|
|
2548
2280
|
terminatedPids.push(...result.terminatedPids);
|
|
2549
2281
|
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
2282
|
await params.leaseStore.markState(lease.leaseId, retryableEvidenceFailure ? "open" : result.terminatedPids.length > 0 ? "closed" : "lost");
|
|
@@ -2554,13 +2286,9 @@ async function reapOpenAcpxProcessLeases(params) {
|
|
|
2554
2286
|
wrapperRoot,
|
|
2555
2287
|
assertCurrent
|
|
2556
2288
|
});
|
|
2557
|
-
inspectedPids.push(...legacyResult.inspectedPids);
|
|
2558
2289
|
terminatedPids.push(...legacyResult.terminatedPids);
|
|
2559
2290
|
}
|
|
2560
|
-
return {
|
|
2561
|
-
inspectedPids,
|
|
2562
|
-
terminatedPids
|
|
2563
|
-
};
|
|
2291
|
+
return { terminatedPids };
|
|
2564
2292
|
}
|
|
2565
2293
|
function createAcpxRuntimeService(params) {
|
|
2566
2294
|
let runtime = null;
|
|
@@ -2591,7 +2319,6 @@ function createAcpxRuntimeService(params) {
|
|
|
2591
2319
|
return;
|
|
2592
2320
|
}
|
|
2593
2321
|
const openKeyedStore = params.openKeyedStore;
|
|
2594
|
-
if (!openKeyedStore) throw new Error("ACPX runtime service requires plugin keyed state");
|
|
2595
2322
|
const basePluginConfig = await measureAcpxStartup(ctx, "config.resolve", () => resolveAcpxPluginConfig({
|
|
2596
2323
|
rawConfig: params.pluginConfig,
|
|
2597
2324
|
workspaceDir: ctx.workspaceDir,
|
|
@@ -2626,14 +2353,38 @@ function createAcpxRuntimeService(params) {
|
|
|
2626
2353
|
if (params.startupPurpose !== "inspection") await promote(ctx);
|
|
2627
2354
|
const getAllowedAgents = params.getAllowedAgents ?? (() => ctx.config.acp?.allowedAgents);
|
|
2628
2355
|
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
|
-
|
|
2356
|
+
const startedRuntime = await measureAcpxStartup(ctx, "runtime.create", async () => {
|
|
2357
|
+
const names = await fs$1.readdir(path.join(pluginConfig.stateDir, "sessions")).catch((error) => {
|
|
2358
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") return [];
|
|
2359
|
+
throw error;
|
|
2360
|
+
});
|
|
2361
|
+
const legacyBareSessionKeys = /* @__PURE__ */ new Set();
|
|
2362
|
+
for (const name of names) {
|
|
2363
|
+
if (!name.endsWith(".json")) continue;
|
|
2364
|
+
const recordId = decodeURIComponent(name.slice(0, -5));
|
|
2365
|
+
if (!recordId.startsWith("agent:") && !recordId.startsWith(".openclaw-owner-") && !recordId.includes(":oneshot:")) legacyBareSessionKeys.add(recordId.toLowerCase());
|
|
2366
|
+
}
|
|
2367
|
+
return new AcpxRuntime$1({
|
|
2368
|
+
cwd: pluginConfig.cwd,
|
|
2369
|
+
agentProcessEnv: resolveAgentProcessEnv(),
|
|
2370
|
+
agentProcessEnvAllow: pluginConfig.agentProcessEnvAllow,
|
|
2371
|
+
agentProcessEnvBlock: pluginConfig.agentProcessEnvBlock,
|
|
2372
|
+
openclawLegacyBareSessionKeys: legacyBareSessionKeys,
|
|
2373
|
+
openclawGatewayInstanceId: gatewayInstanceId,
|
|
2374
|
+
openclawProcessLeaseStore: processLeaseStore,
|
|
2375
|
+
openclawWrapperRoot: wrapperRoot,
|
|
2376
|
+
sessionStore: createFileSessionStore({ stateDir: pluginConfig.stateDir }),
|
|
2377
|
+
agentRegistry: createAgentRegistry({ overrides: pluginConfig.agents }),
|
|
2378
|
+
getProbeAgent,
|
|
2379
|
+
mcpServers: toAcpMcpServers(pluginConfig.mcpServers),
|
|
2380
|
+
pluginToolsMcpBridgeEnabled: pluginConfig.pluginToolsMcpBridge,
|
|
2381
|
+
openclawToolsMcpBridgeEnabled: pluginConfig.openClawToolsMcpBridge,
|
|
2382
|
+
permissionMode: pluginConfig.permissionMode,
|
|
2383
|
+
nonInteractivePermissions: pluginConfig.nonInteractivePermissions,
|
|
2384
|
+
elicitationModes: ["form", "url"],
|
|
2385
|
+
timeoutMs: resolveAcpxTimerTimeoutMs(pluginConfig.timeoutSeconds)
|
|
2386
|
+
});
|
|
2387
|
+
});
|
|
2637
2388
|
runtime = startedRuntime;
|
|
2638
2389
|
const shouldProbeRuntime = params.probeAtStartup !== false && shouldProbeRuntimeAtStartup();
|
|
2639
2390
|
ctx.startupTrace?.detail?.("probe-policy", [["startupProbeEnabledCount", shouldProbeRuntime ? 1 : 0], ["probeAgent", getProbeAgent() ?? "default"]]);
|
|
@@ -2676,5 +2427,4 @@ function createAcpxRuntimeService(params) {
|
|
|
2676
2427
|
}
|
|
2677
2428
|
};
|
|
2678
2429
|
}
|
|
2679
|
-
//#endregion
|
|
2680
2430
|
export { createAcpxRuntimeService };
|