@openclaw/acpx 2026.8.1 → 2026.8.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.
@@ -1,511 +0,0 @@
1
- import { t as AcpxPluginConfigSchema } from "./config-schema-DN_uAi4R.js";
2
- import { u as readAcpxProcessLeaseIdentity, v as splitCommandParts } from "./process-lease-Cwvj7WGe.js";
3
- import { createRequire } from "node:module";
4
- import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
5
- import fs from "node:fs";
6
- import path from "node:path";
7
- import { isPidAlive, runExec } from "openclaw/plugin-sdk/process-runtime";
8
- import { fileURLToPath } from "node:url";
9
- import { formatPluginConfigIssue } from "openclaw/plugin-sdk/extension-shared";
10
- //#region extensions/acpx/src/codex-adapter.ts
11
- const CODEX_ACP_PACKAGE = "@agentclientprotocol/codex-acp";
12
- const CODEX_ACP_BIN = "codex-acp";
13
- const LEGACY_CODEX_ACP_PACKAGE = "@zed-industries/codex-acp";
14
- const OPENCLAW_CODEX_CONFIG_ARG = "--openclaw-codex-config";
15
- //#endregion
16
- //#region extensions/acpx/src/config.ts
17
- /**
18
- * Resolves ACPX plugin config from raw user configuration. It locates the
19
- * plugin root, injects optional MCP bridge servers, and applies runtime defaults.
20
- */
21
- const ACPX_PLUGIN_TOOLS_MCP_SERVER_NAME = "openclaw-plugin-tools";
22
- const ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME = "openclaw-tools";
23
- const requireFromHere$1 = createRequire(import.meta.url);
24
- function isAcpxPluginRoot(dir) {
25
- return fs.existsSync(path.join(dir, "openclaw.plugin.json")) && fs.existsSync(path.join(dir, "package.json"));
26
- }
27
- function resolveNearestAcpxPluginRoot(moduleUrl) {
28
- let cursor = path.dirname(fileURLToPath(moduleUrl));
29
- for (let i = 0; i < 3; i += 1) {
30
- if (isAcpxPluginRoot(cursor)) return cursor;
31
- const parent = path.dirname(cursor);
32
- if (parent === cursor) break;
33
- cursor = parent;
34
- }
35
- return path.resolve(path.dirname(fileURLToPath(moduleUrl)), "..");
36
- }
37
- function resolveWorkspaceAcpxPluginRoot(currentRoot) {
38
- if (path.basename(currentRoot) !== "acpx" || path.basename(path.dirname(currentRoot)) !== "extensions" || path.basename(path.dirname(path.dirname(currentRoot))) !== "dist") return null;
39
- const workspaceRoot = path.resolve(currentRoot, "..", "..", "..", "extensions", "acpx");
40
- return isAcpxPluginRoot(workspaceRoot) ? workspaceRoot : null;
41
- }
42
- function resolveRepoAcpxPluginRoot(currentRoot) {
43
- const workspaceRoot = path.join(currentRoot, "extensions", "acpx");
44
- return isAcpxPluginRoot(workspaceRoot) ? workspaceRoot : null;
45
- }
46
- function resolveAcpxPluginRootFromOpenClawLayout(moduleUrl) {
47
- let cursor = path.dirname(fileURLToPath(moduleUrl));
48
- for (let i = 0; i < 5; i += 1) {
49
- const candidates = [
50
- path.join(cursor, "extensions", "acpx"),
51
- path.join(cursor, "dist", "extensions", "acpx"),
52
- path.join(cursor, "dist-runtime", "extensions", "acpx")
53
- ];
54
- for (const candidate of candidates) if (isAcpxPluginRoot(candidate)) return candidate;
55
- const parent = path.dirname(cursor);
56
- if (parent === cursor) break;
57
- cursor = parent;
58
- }
59
- return null;
60
- }
61
- /** Resolve the ACPX plugin root across source, dist, and dist-runtime layouts. */
62
- function resolveAcpxPluginRoot(moduleUrl = import.meta.url) {
63
- const resolvedRoot = resolveNearestAcpxPluginRoot(moduleUrl);
64
- return resolveWorkspaceAcpxPluginRoot(resolvedRoot) ?? resolveRepoAcpxPluginRoot(resolvedRoot) ?? resolveAcpxPluginRootFromOpenClawLayout(moduleUrl) ?? resolvedRoot;
65
- }
66
- const DEFAULT_PERMISSION_MODE = "approve-reads";
67
- const DEFAULT_NON_INTERACTIVE_POLICY = "fail";
68
- function parseAcpxPluginConfig(value) {
69
- if (value === void 0) return {
70
- ok: true,
71
- value: void 0
72
- };
73
- const parsed = AcpxPluginConfigSchema.safeParse(value);
74
- if (!parsed.success) return {
75
- ok: false,
76
- message: formatPluginConfigIssue(parsed.error.issues[0])
77
- };
78
- return {
79
- ok: true,
80
- value: parsed.data
81
- };
82
- }
83
- function resolveOpenClawRoot(currentRoot) {
84
- if (path.basename(currentRoot) === "acpx" && path.basename(path.dirname(currentRoot)) === "extensions") {
85
- const parent = path.dirname(path.dirname(currentRoot));
86
- if (path.basename(parent) === "dist") return path.dirname(parent);
87
- return parent;
88
- }
89
- return path.resolve(currentRoot, "..");
90
- }
91
- function resolveTsxImportSpecifier() {
92
- try {
93
- return requireFromHere$1.resolve("tsx");
94
- } catch {
95
- return "tsx";
96
- }
97
- }
98
- function shellQuoteCommandArg(arg) {
99
- if (!/[\s'"\\$|&;<>{}()*?[\]~`]/.test(arg)) return arg;
100
- return `'${arg.replace(/'/g, "'\"'\"'")}'`;
101
- }
102
- function resolvePluginToolsMcpServerConfig(moduleUrl = import.meta.url) {
103
- const openClawRoot = resolveOpenClawRoot(resolveAcpxPluginRoot(moduleUrl));
104
- const distEntry = path.join(openClawRoot, "dist", "mcp", "plugin-tools-serve.js");
105
- if (fs.existsSync(distEntry)) return {
106
- command: process.execPath,
107
- args: [distEntry]
108
- };
109
- const sourceEntry = path.join(openClawRoot, "src", "mcp", "plugin-tools-serve.ts");
110
- return {
111
- command: process.execPath,
112
- args: [
113
- "--import",
114
- resolveTsxImportSpecifier(),
115
- sourceEntry
116
- ]
117
- };
118
- }
119
- function resolveOpenClawToolsMcpServerConfig(moduleUrl = import.meta.url) {
120
- const openClawRoot = resolveOpenClawRoot(resolveAcpxPluginRoot(moduleUrl));
121
- const distEntry = path.join(openClawRoot, "dist", "mcp", "openclaw-tools-serve.js");
122
- if (fs.existsSync(distEntry)) return {
123
- command: process.execPath,
124
- args: [distEntry]
125
- };
126
- const sourceEntry = path.join(openClawRoot, "src", "mcp", "openclaw-tools-serve.ts");
127
- return {
128
- command: process.execPath,
129
- args: [
130
- "--import",
131
- resolveTsxImportSpecifier(),
132
- sourceEntry
133
- ]
134
- };
135
- }
136
- function resolveConfiguredMcpServers(params) {
137
- const resolved = { ...params.mcpServers };
138
- if (params.pluginToolsMcpBridge && resolved[ACPX_PLUGIN_TOOLS_MCP_SERVER_NAME]) throw new Error(`mcpServers.${ACPX_PLUGIN_TOOLS_MCP_SERVER_NAME} is reserved when pluginToolsMcpBridge=true`);
139
- if (params.openClawToolsMcpBridge && resolved[ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME]) throw new Error(`mcpServers.${ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME} is reserved when openClawToolsMcpBridge=true`);
140
- if (params.pluginToolsMcpBridge) resolved[ACPX_PLUGIN_TOOLS_MCP_SERVER_NAME] = resolvePluginToolsMcpServerConfig(params.moduleUrl);
141
- if (params.openClawToolsMcpBridge) resolved[ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME] = resolveOpenClawToolsMcpServerConfig(params.moduleUrl);
142
- return resolved;
143
- }
144
- /** Convert OpenClaw MCP server config into ACPX runtime MCP server entries. */
145
- function toAcpMcpServers(mcpServers) {
146
- return Object.entries(mcpServers).map(([name, server]) => ({
147
- name,
148
- command: server.command,
149
- args: [...server.args ?? []],
150
- env: Object.entries(server.env ?? {}).map(([envName, value]) => ({
151
- name: envName,
152
- value
153
- }))
154
- }));
155
- }
156
- /** Validate and normalize raw ACPX plugin config for runtime startup. */
157
- function resolveAcpxPluginConfig(params) {
158
- const parsed = parseAcpxPluginConfig(params.rawConfig);
159
- if (!parsed.ok) throw new Error(parsed.message);
160
- const normalized = parsed.value ?? {};
161
- const workspaceDir = params.workspaceDir?.trim() || process.cwd();
162
- const fallbackCwd = workspaceDir;
163
- const cwd = path.resolve(normalized.cwd?.trim() || fallbackCwd);
164
- const stateDir = path.resolve(normalized.stateDir?.trim() || path.join(workspaceDir, "state"));
165
- const pluginToolsMcpBridge = normalized.pluginToolsMcpBridge === true;
166
- const openClawToolsMcpBridge = normalized.openClawToolsMcpBridge === true;
167
- const mcpServers = resolveConfiguredMcpServers({
168
- mcpServers: normalized.mcpServers,
169
- pluginToolsMcpBridge,
170
- openClawToolsMcpBridge,
171
- moduleUrl: params.moduleUrl
172
- });
173
- const agents = Object.fromEntries(Object.entries(normalized.agents ?? {}).map(([name, entry]) => {
174
- const cmd = entry.command.trim();
175
- const cmdArgs = entry.args ?? [];
176
- const fullCommand = cmdArgs.length > 0 ? `${cmd} ${cmdArgs.map(shellQuoteCommandArg).join(" ")}` : cmd;
177
- return [normalizeLowercaseStringOrEmpty(name), fullCommand];
178
- }));
179
- return {
180
- cwd,
181
- stateDir,
182
- probeAgent: normalized.probeAgent,
183
- permissionMode: normalized.permissionMode ?? DEFAULT_PERMISSION_MODE,
184
- nonInteractivePermissions: normalized.nonInteractivePermissions ?? DEFAULT_NON_INTERACTIVE_POLICY,
185
- pluginToolsMcpBridge,
186
- openClawToolsMcpBridge,
187
- timeoutSeconds: normalized.timeoutSeconds ?? 120,
188
- mcpServers,
189
- agents
190
- };
191
- }
192
- //#endregion
193
- //#region extensions/acpx/src/process-reaper.ts
194
- /**
195
- * ACPX process ownership checks and cleanup. The reaper only terminates
196
- * OpenClaw-owned wrapper trees after validating paths, packages, and lease ids.
197
- */
198
- const requireFromHere = createRequire(import.meta.url);
199
- const GENERATED_WRAPPER_BASENAMES = /* @__PURE__ */ new Set(["codex-acp-wrapper.mjs", "claude-agent-acp-wrapper.mjs"]);
200
- const OPENCLAW_PLUGIN_DEPS_MARKER = "/plugin-runtime-deps/";
201
- const ACPX_PROCESS_LIST_TIMEOUT_MS = 2e3;
202
- const OWNED_ACP_PACKAGE_NAMES = [
203
- CODEX_ACP_PACKAGE,
204
- LEGACY_CODEX_ACP_PACKAGE,
205
- "@zed-industries/codex-acp-darwin-arm64",
206
- "@zed-industries/codex-acp-darwin-x64",
207
- "@zed-industries/codex-acp-linux-arm64",
208
- "@zed-industries/codex-acp-linux-x64",
209
- "@zed-industries/codex-acp-win32-arm64",
210
- "@zed-industries/codex-acp-win32-x64",
211
- "@agentclientprotocol/claude-agent-acp",
212
- "acpx"
213
- ];
214
- const PLUGIN_DEPS_CODEX_PACKAGE_NAMES = [
215
- "@openai/codex",
216
- "@openai/codex-darwin-arm64",
217
- "@openai/codex-darwin-x64",
218
- "@openai/codex-linux-arm64",
219
- "@openai/codex-linux-x64",
220
- "@openai/codex-win32-arm64",
221
- "@openai/codex-win32-x64"
222
- ];
223
- const ACP_PACKAGE_MARKERS = [
224
- ...OWNED_ACP_PACKAGE_NAMES.map((packageName) => `/node_modules/${packageName}/`),
225
- ...PLUGIN_DEPS_CODEX_PACKAGE_NAMES.map((packageName) => `/node_modules/${packageName}/`),
226
- "/acpx/dist/"
227
- ];
228
- function normalizePathLike(value) {
229
- return value.replaceAll("\\", "/");
230
- }
231
- function resolvePackageRoot(packageName) {
232
- try {
233
- return normalizePathLike(path.dirname(requireFromHere.resolve(`${packageName}/package.json`)));
234
- } catch {
235
- return;
236
- }
237
- }
238
- function resolveOpenClawInstallRoot(pluginRoot) {
239
- if (path.basename(pluginRoot) === "acpx" && path.basename(path.dirname(pluginRoot)) === "extensions") {
240
- const parent = path.dirname(path.dirname(pluginRoot));
241
- return path.basename(parent) === "dist" ? path.dirname(parent) : parent;
242
- }
243
- return path.resolve(pluginRoot, "..");
244
- }
245
- function resolveOwnedAcpPackageRootCandidates(packageName) {
246
- const pluginRoot = resolveAcpxPluginRoot(import.meta.url);
247
- const openClawRoot = resolveOpenClawInstallRoot(pluginRoot);
248
- return [
249
- resolvePackageRoot(packageName),
250
- path.join(pluginRoot, "node_modules", packageName),
251
- path.join(openClawRoot, "node_modules", packageName)
252
- ].flatMap((root) => root ? [normalizePathLike(root)] : []);
253
- }
254
- const OWNED_ACP_PACKAGE_ROOTS = Array.from(new Set(OWNED_ACP_PACKAGE_NAMES.flatMap(resolveOwnedAcpPackageRootCandidates)));
255
- function commandBelongsToResolvedAcpPackage(command) {
256
- return OWNED_ACP_PACKAGE_ROOTS.some((root) => command.includes(`${root}/`));
257
- }
258
- function commandMentionsGeneratedWrapper(command) {
259
- return Array.from(GENERATED_WRAPPER_BASENAMES).some((basename) => command.includes(basename));
260
- }
261
- function commandWrapperBelongsToRoot(command, wrapperRoot) {
262
- if (!wrapperRoot) return true;
263
- const normalizedCommand = normalizePathLike(command);
264
- const normalizedRoot = normalizePathLike(wrapperRoot).replace(/\/+$/, "");
265
- return Array.from(GENERATED_WRAPPER_BASENAMES).some((basename) => normalizedCommand.includes(`${normalizedRoot}/${basename}`));
266
- }
267
- function commandContainsExactWrapperPath(command, wrapperPath) {
268
- const expectedPath = normalizePathLike(wrapperPath);
269
- return splitCommandParts(command).some((part) => normalizePathLike(part) === expectedPath);
270
- }
271
- function wrapperPathBelongsToRoot(wrapperPath, wrapperRoot) {
272
- const normalizedPath = normalizePathLike(wrapperPath);
273
- const normalizedRoot = normalizePathLike(wrapperRoot).replace(/\/+$/, "");
274
- return GENERATED_WRAPPER_BASENAMES.has(path.posix.basename(normalizedPath)) && normalizedPath.startsWith(`${normalizedRoot}/`);
275
- }
276
- /** Check whether a command references an OpenClaw-generated ACPX wrapper path. */
277
- function isOpenClawLeaseAwareAcpxProcessCommand(params) {
278
- const command = params.command?.trim();
279
- if (!command) return false;
280
- const normalized = normalizePathLike(command);
281
- return commandMentionsGeneratedWrapper(normalized) && commandWrapperBelongsToRoot(normalized, params.wrapperRoot);
282
- }
283
- function commandsReferToSameRootCommand(liveCommand, storedCommand) {
284
- if (!storedCommand?.trim()) return true;
285
- return normalizePathLike(liveCommand).trim() === normalizePathLike(storedCommand).trim();
286
- }
287
- function commandOptionEquals(parts, option, expected) {
288
- if (!expected) return true;
289
- const index = parts.indexOf(option);
290
- return index >= 0 && parts[index + 1] === expected;
291
- }
292
- function liveCommandMatchesLeaseIdentity(params) {
293
- if (!params.expectedLeaseId && !params.expectedGatewayInstanceId) return true;
294
- const parts = splitCommandParts(params.command ?? "");
295
- return commandOptionEquals(parts, "--openclaw-acpx-lease-id", params.expectedLeaseId) && commandOptionEquals(parts, "--openclaw-gateway-instance-id", params.expectedGatewayInstanceId);
296
- }
297
- /** Check whether a command is owned by OpenClaw ACPX runtime packages or wrappers. */
298
- function isOpenClawOwnedAcpxProcessCommand(params) {
299
- const command = params.command?.trim();
300
- if (!command) return false;
301
- const normalized = normalizePathLike(command);
302
- if (isOpenClawLeaseAwareAcpxProcessCommand({
303
- command: normalized,
304
- wrapperRoot: params.wrapperRoot
305
- })) return true;
306
- if (commandBelongsToResolvedAcpPackage(normalized)) return true;
307
- if (!normalized.includes(OPENCLAW_PLUGIN_DEPS_MARKER)) return false;
308
- return ACP_PACKAGE_MARKERS.some((marker) => normalized.includes(marker));
309
- }
310
- function parseProcessList(stdout) {
311
- const processes = [];
312
- for (const line of stdout.split(/\r?\n/)) {
313
- const match = /^\s*(?<pid>\d+)\s+(?<ppid>\d+)\s+(?<command>.+?)\s*$/.exec(line);
314
- const pid = match?.groups?.pid;
315
- const ppid = match?.groups?.ppid;
316
- const command = match?.groups?.command;
317
- if (!pid || !ppid || !command) continue;
318
- processes.push({
319
- pid: Number.parseInt(pid, 10),
320
- ppid: Number.parseInt(ppid, 10),
321
- command
322
- });
323
- }
324
- return processes;
325
- }
326
- /** List host processes in the compact shape needed by ACPX cleanup. */
327
- async function listPlatformProcesses() {
328
- if (process.platform === "win32") return [];
329
- const { stdout } = await runExec("ps", ["-axo", "pid=,ppid=,command="], {
330
- logOutput: false,
331
- maxBuffer: 8 * 1024 * 1024,
332
- timeoutMs: ACPX_PROCESS_LIST_TIMEOUT_MS
333
- });
334
- return parseProcessList(stdout);
335
- }
336
- function collectProcessTree(processes, rootPid) {
337
- const childrenByParent = /* @__PURE__ */ new Map();
338
- for (const processInfo of processes) {
339
- const children = childrenByParent.get(processInfo.ppid) ?? [];
340
- children.push(processInfo);
341
- childrenByParent.set(processInfo.ppid, children);
342
- }
343
- const root = new Map(processes.map((processInfo) => [processInfo.pid, processInfo])).get(rootPid);
344
- const collected = [];
345
- if (root) collected.push(root);
346
- const queue = [...childrenByParent.get(rootPid) ?? []];
347
- while (queue.length > 0) {
348
- const next = queue.shift();
349
- if (!next || collected.some((processInfo) => processInfo.pid === next.pid)) continue;
350
- collected.push(next);
351
- queue.push(...childrenByParent.get(next.pid) ?? []);
352
- }
353
- return collected;
354
- }
355
- function uniquePids(processes) {
356
- return Array.from(new Set(processes.map((processInfo) => processInfo.pid).filter((pid) => Number.isInteger(pid) && pid > 0 && pid !== process.pid)));
357
- }
358
- async function terminatePids(pids, deps) {
359
- const killProcess = deps?.killProcess ?? ((pid, signal) => process.kill(pid, signal));
360
- const sleep = deps?.sleep ?? ((ms) => new Promise((resolve) => {
361
- setTimeout(resolve, ms);
362
- }));
363
- const terminated = [];
364
- for (const pid of pids) try {
365
- killProcess(pid, "SIGTERM");
366
- terminated.push(pid);
367
- } catch {}
368
- if (terminated.length === 0) return terminated;
369
- await sleep(750);
370
- for (const pid of terminated) if (deps?.killProcess || isPidAlive(pid)) try {
371
- killProcess(pid, "SIGKILL");
372
- } catch {}
373
- return terminated;
374
- }
375
- /** Terminate one validated OpenClaw-owned ACPX wrapper process tree. */
376
- async function cleanupOpenClawOwnedAcpxProcessTree(params) {
377
- const rootPid = params.rootPid;
378
- if (!rootPid || rootPid <= 0 || rootPid === process.pid) return {
379
- inspectedPids: [],
380
- terminatedPids: [],
381
- skippedReason: "missing-root"
382
- };
383
- if ((params.deps?.platform ?? process.platform) === "win32") return {
384
- inspectedPids: [],
385
- terminatedPids: [],
386
- skippedReason: "unsupported-platform"
387
- };
388
- let processes;
389
- try {
390
- processes = await (params.deps?.listProcesses ?? listPlatformProcesses)();
391
- } catch {
392
- return {
393
- inspectedPids: [],
394
- terminatedPids: [],
395
- skippedReason: "process-list-unavailable"
396
- };
397
- }
398
- const listedTree = collectProcessTree(processes, rootPid);
399
- if (listedTree.length === 0) return {
400
- inspectedPids: [],
401
- terminatedPids: [],
402
- skippedReason: "unverified-root"
403
- };
404
- const rootCommand = listedTree[0]?.command ?? params.rootCommand;
405
- const liveCommandWasGeneratedWrapper = commandMentionsGeneratedWrapper(normalizePathLike(rootCommand ?? ""));
406
- const storedCommandWasGeneratedWrapper = commandMentionsGeneratedWrapper(normalizePathLike(params.rootCommand ?? ""));
407
- if (!liveCommandWasGeneratedWrapper && storedCommandWasGeneratedWrapper) return {
408
- inspectedPids: listedTree.map((processInfo) => processInfo.pid),
409
- terminatedPids: [],
410
- skippedReason: "not-openclaw-owned"
411
- };
412
- if (!liveCommandWasGeneratedWrapper && !commandsReferToSameRootCommand(rootCommand ?? "", params.rootCommand)) return {
413
- inspectedPids: listedTree.map((processInfo) => processInfo.pid),
414
- terminatedPids: [],
415
- skippedReason: "not-openclaw-owned"
416
- };
417
- if (!isOpenClawOwnedAcpxProcessCommand({
418
- command: rootCommand,
419
- wrapperRoot: params.wrapperRoot
420
- })) return {
421
- inspectedPids: listedTree.map((processInfo) => processInfo.pid),
422
- terminatedPids: [],
423
- skippedReason: "not-openclaw-owned"
424
- };
425
- if (!liveCommandMatchesLeaseIdentity({
426
- command: rootCommand,
427
- expectedLeaseId: params.expectedLeaseId,
428
- expectedGatewayInstanceId: params.expectedGatewayInstanceId
429
- })) return {
430
- inspectedPids: listedTree.map((processInfo) => processInfo.pid),
431
- terminatedPids: [],
432
- skippedReason: "not-openclaw-owned"
433
- };
434
- const pids = uniquePids(listedTree.toReversed());
435
- return {
436
- inspectedPids: uniquePids(listedTree),
437
- terminatedPids: await terminatePids(pids, params.deps)
438
- };
439
- }
440
- /** Recover a pending lease by matching its exact live wrapper identity. */
441
- async function cleanupOpenClawOwnedAcpxPendingLease(params) {
442
- if ((params.deps?.platform ?? process.platform) === "win32") return {
443
- inspectedPids: [],
444
- terminatedPids: [],
445
- skippedReason: "unsupported-platform"
446
- };
447
- if (!params.wrapperPath || !wrapperPathBelongsToRoot(params.wrapperPath, params.wrapperRoot)) return {
448
- inspectedPids: [],
449
- terminatedPids: [],
450
- skippedReason: "unverified-root"
451
- };
452
- let processes;
453
- try {
454
- processes = await (params.deps?.listProcesses ?? listPlatformProcesses)();
455
- } catch {
456
- return {
457
- inspectedPids: [],
458
- terminatedPids: [],
459
- skippedReason: "process-list-unavailable"
460
- };
461
- }
462
- const matchingRoots = processes.filter((processInfo) => commandContainsExactWrapperPath(processInfo.command, params.wrapperPath) && liveCommandMatchesLeaseIdentity({
463
- command: processInfo.command,
464
- expectedLeaseId: params.leaseId,
465
- expectedGatewayInstanceId: params.gatewayInstanceId
466
- }));
467
- if (matchingRoots.length === 0) return {
468
- inspectedPids: [],
469
- terminatedPids: [],
470
- skippedReason: "missing-root"
471
- };
472
- if (matchingRoots.length > 1) return {
473
- inspectedPids: uniquePids(matchingRoots),
474
- terminatedPids: [],
475
- skippedReason: "ambiguous-root"
476
- };
477
- const listedTree = collectProcessTree(processes, matchingRoots[0].pid);
478
- const pids = uniquePids(listedTree.toReversed());
479
- return {
480
- inspectedPids: uniquePids(listedTree),
481
- terminatedPids: await terminatePids(pids, params.deps)
482
- };
483
- }
484
- /** Reap orphaned OpenClaw-owned ACPX wrapper trees during runtime startup. */
485
- async function reapStaleOpenClawOwnedAcpxOrphans(params) {
486
- if ((params.deps?.platform ?? process.platform) === "win32") return {
487
- inspectedPids: [],
488
- terminatedPids: [],
489
- skippedReason: "unsupported-platform"
490
- };
491
- let processes;
492
- try {
493
- processes = await (params.deps?.listProcesses ?? listPlatformProcesses)();
494
- } catch {
495
- return {
496
- inspectedPids: [],
497
- terminatedPids: [],
498
- skippedReason: "process-list-unavailable"
499
- };
500
- }
501
- const orphanTrees = processes.filter((processInfo) => processInfo.ppid === 1 && !readAcpxProcessLeaseIdentity(processInfo.command) && isOpenClawOwnedAcpxProcessCommand({
502
- command: processInfo.command,
503
- wrapperRoot: params.wrapperRoot
504
- })).map((orphan) => collectProcessTree(processes, orphan.pid));
505
- return {
506
- inspectedPids: uniquePids(orphanTrees.flat()),
507
- terminatedPids: await terminatePids(uniquePids(orphanTrees.flatMap((tree) => tree.toReversed())), params.deps)
508
- };
509
- }
510
- //#endregion
511
- export { resolveAcpxPluginConfig as a, CODEX_ACP_BIN as c, OPENCLAW_CODEX_CONFIG_ARG as d, reapStaleOpenClawOwnedAcpxOrphans as i, CODEX_ACP_PACKAGE as l, cleanupOpenClawOwnedAcpxProcessTree as n, resolveAcpxPluginRoot as o, isOpenClawLeaseAwareAcpxProcessCommand as r, toAcpMcpServers as s, cleanupOpenClawOwnedAcpxPendingLease as t, LEGACY_CODEX_ACP_PACKAGE as u };