@openclaw/acpx 2026.9.8 → 2026.10.1-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.
@@ -1,4 +1,3 @@
1
- import { o as splitCommandParts } from "./command-line-B72femaL.mjs";
2
1
  import { createRequire } from "node:module";
3
2
  import { z } from "zod";
4
3
  import fs from "node:fs";
@@ -6,7 +5,7 @@ import path from "node:path";
6
5
  import { fileURLToPath } from "node:url";
7
6
  import { formatPluginConfigIssue } from "openclaw/plugin-sdk/extension-shared";
8
7
  import { resolveStateDir } from "openclaw/plugin-sdk/state-paths";
9
- import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
8
+ import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
10
9
  //#region extensions/acpx/src/config-schema.ts
11
10
  /**
12
11
  * ACPX plugin configuration schema and public config types. Runtime setup uses
@@ -57,6 +56,135 @@ const AcpxPluginConfigSchema = z.strictObject({
57
56
  })).optional()
58
57
  });
59
58
  //#endregion
59
+ //#region extensions/acpx/src/codex-adapter.ts
60
+ const CODEX_ACP_PACKAGE = "@agentclientprotocol/codex-acp";
61
+ const CODEX_ACP_BIN = "codex-acp";
62
+ const LEGACY_CODEX_ACP_PACKAGE = "@zed-industries/codex-acp";
63
+ const OPENCLAW_CODEX_CONFIG_ARG = "--openclaw-codex-config";
64
+ //#endregion
65
+ //#region extensions/acpx/src/command-line.ts
66
+ /** Match ACPX's persisted argv identity; scalar records keep their original bytes. */
67
+ function renderAgentCommand(command) {
68
+ return typeof command === "string" ? command : command.map((part) => /^[A-Za-z0-9_@%+=:,./^~-]+$/.test(part) ? part : JSON.stringify(part)).join(" ");
69
+ }
70
+ /** Split a command string into argv-like parts using simple quote/backslash rules. */
71
+ function splitCommandParts(value) {
72
+ if (Array.isArray(value)) return value;
73
+ const windows = process.platform === "win32";
74
+ const parts = [];
75
+ let current = "";
76
+ let quote = null;
77
+ let escaping = false;
78
+ let hasPart = false;
79
+ for (const ch of value) {
80
+ if (escaping) {
81
+ current += ch;
82
+ escaping = false;
83
+ hasPart = true;
84
+ continue;
85
+ }
86
+ if (ch === "\\" && quote !== "'" && !windows) {
87
+ escaping = true;
88
+ hasPart = true;
89
+ continue;
90
+ }
91
+ if (windows && ch === "\"" && quote !== "'") {
92
+ const backslashes = current.match(/\\+$/)?.[0].length ?? 0;
93
+ current = current.slice(0, current.length - backslashes) + "\\".repeat(Math.floor(backslashes / 2));
94
+ if (backslashes % 2 === 1) {
95
+ current += "\"";
96
+ continue;
97
+ }
98
+ }
99
+ if (quote) {
100
+ if (ch === quote) quote = null;
101
+ else current += ch;
102
+ continue;
103
+ }
104
+ if (ch === "'" || ch === "\"") {
105
+ quote = ch;
106
+ hasPart = true;
107
+ continue;
108
+ }
109
+ if (/\s/.test(ch)) {
110
+ if (hasPart) {
111
+ parts.push(current);
112
+ current = "";
113
+ hasPart = false;
114
+ }
115
+ continue;
116
+ }
117
+ current += ch;
118
+ hasPart = true;
119
+ }
120
+ if (escaping) current += "\\";
121
+ if (quote) throw new Error("Invalid agent command: unterminated quote");
122
+ if (hasPart) parts.push(current);
123
+ return parts;
124
+ }
125
+ function basename(value) {
126
+ return value.split(/[\\/]/).pop() ?? value;
127
+ }
128
+ function isEnvAssignment(value) {
129
+ return /^[A-Za-z_][A-Za-z0-9_]*=/.test(value);
130
+ }
131
+ function unwrapEnvCommand(parts) {
132
+ const command = parts.at(0);
133
+ if (!command || basename(command) !== "env") return parts;
134
+ let index = 1;
135
+ while (true) {
136
+ const part = parts.at(index);
137
+ if (!part || !isEnvAssignment(part)) break;
138
+ index += 1;
139
+ }
140
+ return parts.slice(index);
141
+ }
142
+ function matchesExecutableName(value, executableName) {
143
+ const normalized = basename(value).toLowerCase();
144
+ return normalized === executableName || normalized === `${executableName}.exe`;
145
+ }
146
+ function matchesPackageSpec(value, packageName) {
147
+ const normalized = value.trim().toLowerCase();
148
+ return normalized === packageName || normalized.startsWith(`${packageName}@`);
149
+ }
150
+ function stripModuleExtension(value) {
151
+ return value.replace(/\.[cm]?js$/i, "").toLowerCase();
152
+ }
153
+ function isAcpCommand(command, params) {
154
+ if (!command) return false;
155
+ const parts = unwrapEnvCommand(splitCommandParts(command));
156
+ if (!parts.length) return false;
157
+ if (parts.some((part) => matchesPackageSpec(part, params.packageName))) return true;
158
+ const commandName = basename(parts[0] ?? "");
159
+ if (matchesExecutableName(commandName, params.executableName)) return true;
160
+ if (!matchesExecutableName(commandName, "node")) return false;
161
+ const scriptName = stripModuleExtension(basename(parts[1] ?? ""));
162
+ return scriptName === params.executableName || scriptName === `${params.executableName}-wrapper`;
163
+ }
164
+ function isOpenClawBridgeCommand(command) {
165
+ const [executable = "", ...args] = command ? unwrapEnvCommand(splitCommandParts(command)) : [];
166
+ const runtime = basename(executable) !== "openclaw" && (executable === process.execPath || /^(?:node|bun)(?:\.exe)?$/i.test(basename(executable)));
167
+ const scriptName = basename(runtime ? args[0] ?? "" : executable);
168
+ return (runtime ? /^openclaw(?:\.[cm]?js)?$/i.test(scriptName) : scriptName === "openclaw") && args[runtime ? 1 : 0] === "acp";
169
+ }
170
+ function isCodexAcpCommand(command) {
171
+ return isAcpCommand(command, {
172
+ packageName: CODEX_ACP_PACKAGE,
173
+ executableName: "codex-acp"
174
+ });
175
+ }
176
+ function isClaudeAcpCommand(command) {
177
+ return isAcpCommand(command, {
178
+ packageName: "@agentclientprotocol/claude-agent-acp",
179
+ executableName: "claude-agent-acp"
180
+ });
181
+ }
182
+ function resolveAgentCommand(params) {
183
+ const normalizedAgentName = normalizeOptionalLowercaseString(params.agentName);
184
+ if (!normalizedAgentName) return;
185
+ return splitCommandParts(params.agentRegistry.resolve(normalizedAgentName));
186
+ }
187
+ //#endregion
60
188
  //#region extensions/acpx/src/config.ts
61
189
  const MANAGED_MCP_BRIDGES = [[
62
190
  "pluginToolsMcpBridge",
@@ -196,4 +324,4 @@ function resolveAcpxPluginConfig(params) {
196
324
  };
197
325
  }
198
326
  //#endregion
199
- export { ACPX_NATIVE_AGENT_IDS as a, toAcpMcpServers as i, resolveAcpxPluginRoot as n, AcpxNativeAgentsSchema as o, resolveOpenClawRoot as r, resolveAcpxPluginConfig as t };
327
+ export { isClaudeAcpCommand as a, renderAgentCommand as c, CODEX_ACP_BIN as d, CODEX_ACP_PACKAGE as f, AcpxNativeAgentsSchema as g, ACPX_NATIVE_AGENT_IDS as h, toAcpMcpServers as i, resolveAgentCommand as l, OPENCLAW_CODEX_CONFIG_ARG as m, resolveAcpxPluginRoot as n, isCodexAcpCommand as o, LEGACY_CODEX_ACP_PACKAGE as p, resolveOpenClawRoot as r, isOpenClawBridgeCommand as s, resolveAcpxPluginConfig as t, splitCommandParts as u };
@@ -53,7 +53,7 @@ function createLazyAcpRuntimeProxy(resolveRuntime) {
53
53
  * immediately, then imports the heavier service only when a session needs it.
54
54
  */
55
55
  const ACPX_BACKEND_ID = "acpx";
56
- const loadServiceModule = createLazyRuntimeModule(() => import("./service-D5hGWl5U.mjs"));
56
+ const loadServiceModule = createLazyRuntimeModule(() => import("./service-BXgGdE56.mjs"));
57
57
  function unregisterOwnedRuntime(runtime) {
58
58
  if (runtime && getAcpRuntimeBackend(ACPX_BACKEND_ID)?.runtime === runtime) unregisterAcpRuntimeBackend(ACPX_BACKEND_ID);
59
59
  }
@@ -1,7 +1,4 @@
1
- import { i as renderAgentCommand, o as splitCommandParts } from "./command-line-B72femaL.mjs";
2
1
  import "node:module";
3
- import { asFiniteNumber, asOptionalObjectRecord, asRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
4
- import { createHash } from "node:crypto";
5
2
  //#region \0rolldown/runtime.js
6
3
  var __defProp = Object.defineProperty;
7
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -30,12 +27,12 @@ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "defau
30
27
  //#endregion
31
28
  //#region packages/normalization-core/src/record-coerce.ts
32
29
  /** Type guard for non-array object records at browser-safe boundaries. */
33
- function isRecord$1(value) {
30
+ function isRecord(value) {
34
31
  return value !== null && typeof value === "object" && !Array.isArray(value);
35
32
  }
36
33
  /** Returns a non-array record or null. */
37
34
  function asNullableRecord(value) {
38
- return isRecord$1(value) ? value : null;
35
+ return isRecord(value) ? value : null;
39
36
  }
40
37
  //#endregion
41
38
  //#region src/config/channel-config-normalization.ts
@@ -128,6 +125,12 @@ function createLegacyWebhookListenerDoctorContract(params) {
128
125
  };
129
126
  const prefix = `channels.${params.channelKey}`;
130
127
  return {
128
+ historicalWebhookListener: {
129
+ channelId: params.channelKey,
130
+ port: params.defaultPort,
131
+ preserveAuthoredActivation: params.preserveAuthoredActivation,
132
+ ...params.defaultHost === void 0 ? {} : { host: params.defaultHost }
133
+ },
131
134
  legacyConfigRules: [{
132
135
  path: ["channels", params.channelKey],
133
136
  message: `${prefix} webhook listeners moved to Gateway routes. Run "openclaw doctor --fix" to preserve explicitly configured listener settings as legacyWebhook.`,
@@ -185,127 +188,4 @@ var runtime_doctor_migrations_exports = /* @__PURE__ */ __exportAll({ createLega
185
188
  import * as import_openclaw_plugin_sdk_runtime_doctor_migrations from "openclaw/plugin-sdk/runtime-doctor-migrations";
186
189
  __reExport(runtime_doctor_migrations_exports, import_openclaw_plugin_sdk_runtime_doctor_migrations);
187
190
  //#endregion
188
- //#region extensions/acpx/src/state.ts
189
- const ACPX_PROCESS_LEASE_NAMESPACE = "process-leases";
190
- const ACPX_PROCESS_LEASE_MAX_ENTRIES = 4096;
191
- const ACPX_LEGACY_PROCESS_LEASE_FILE = "process-leases.json";
192
- const ACPX_GATEWAY_INSTANCE_NAMESPACE = "gateway-instance";
193
- const ACPX_GATEWAY_INSTANCE_KEY = "current";
194
- const ACPX_LEGACY_GATEWAY_INSTANCE_FILE = "gateway-instance-id";
195
- function normalizeAcpxGatewayInstanceRecord(value) {
196
- const record = asOptionalObjectRecord(value);
197
- const instanceId = normalizeOptionalString(record?.instanceId);
198
- if (!instanceId) return;
199
- return {
200
- instanceId,
201
- createdAt: Math.trunc(asFiniteNumber(record?.createdAt) ?? 0)
202
- };
203
- }
204
- //#endregion
205
- //#region extensions/acpx/src/process-lease.ts
206
- const OPENCLAW_ACPX_LEASE_ID_ARG = "--openclaw-acpx-lease-id";
207
- const OPENCLAW_GATEWAY_INSTANCE_ID_ARG = "--openclaw-gateway-instance-id";
208
- /** Synthetic session identity for generated-wrapper health probes. */
209
- const ACPX_PROBE_LEASE_SESSION_KEY = "openclaw:acpx:probe";
210
- function readAcpxProcessLeaseIdentity(command) {
211
- const parts = typeof command === "string" ? Array.from(command.matchAll(/(?:^|\s)(--openclaw-(?:acpx-lease-id|gateway-instance-id))\s+(?:"([^"]*)"|'([^']*)'|(\S+))(?=\s|$)/g)).flatMap((match) => [match[1], match[2] ?? match[3] ?? match[4]]) : command ?? [];
212
- const leaseIndex = parts.lastIndexOf(OPENCLAW_ACPX_LEASE_ID_ARG);
213
- const gatewayIndex = parts.lastIndexOf(OPENCLAW_GATEWAY_INSTANCE_ID_ARG);
214
- const leaseId = leaseIndex >= 0 ? parts[leaseIndex + 1]?.trim() : "";
215
- const gatewayInstanceId = gatewayIndex >= 0 ? parts[gatewayIndex + 1]?.trim() : "";
216
- if (!leaseId || !gatewayInstanceId) return;
217
- return {
218
- leaseId,
219
- gatewayInstanceId
220
- };
221
- }
222
- function normalizeAcpxProcessLease(value) {
223
- const record = asOptionalObjectRecord(value);
224
- if (!record || typeof record.leaseId !== "string" || typeof record.gatewayInstanceId !== "string" || typeof record.sessionKey !== "string" || typeof record.wrapperRoot !== "string" || typeof record.wrapperPath !== "string" || typeof record.rootPid !== "number" || typeof record.commandHash !== "string" || typeof record.startedAt !== "number" || ![
225
- "open",
226
- "closing",
227
- "closed",
228
- "lost"
229
- ].includes(String(record.state))) return;
230
- return {
231
- leaseId: record.leaseId,
232
- gatewayInstanceId: record.gatewayInstanceId,
233
- sessionKey: record.sessionKey,
234
- wrapperRoot: record.wrapperRoot,
235
- wrapperPath: record.wrapperPath,
236
- rootPid: record.rootPid,
237
- ...typeof record.processGroupId === "number" ? { processGroupId: record.processGroupId } : {},
238
- commandHash: record.commandHash,
239
- startedAt: record.startedAt,
240
- state: record.state
241
- };
242
- }
243
- function normalizeAcpxProcessLeaseFile(value) {
244
- const root = asRecord(value);
245
- return {
246
- version: 1,
247
- leases: Array.isArray(root.leases) ? root.leases.map(normalizeAcpxProcessLease).filter((lease) => Boolean(lease)) : []
248
- };
249
- }
250
- function openAcpxProcessLeaseStateStore(openKeyedStore) {
251
- return openKeyedStore({
252
- namespace: ACPX_PROCESS_LEASE_NAMESPACE,
253
- maxEntries: ACPX_PROCESS_LEASE_MAX_ENTRIES,
254
- overflowPolicy: "reject-new"
255
- });
256
- }
257
- function createAcpxProcessLeaseStore(params) {
258
- let updateQueue = Promise.resolve();
259
- async function update(mutator) {
260
- const run = updateQueue.then(mutator);
261
- updateQueue = run.catch(() => {});
262
- await run;
263
- }
264
- async function readCurrent() {
265
- await updateQueue;
266
- return (await params.store.entries()).map((entry) => normalizeAcpxProcessLease(entry.value)).filter((lease) => Boolean(lease));
267
- }
268
- return {
269
- async load(leaseId) {
270
- await updateQueue;
271
- return normalizeAcpxProcessLease(await params.store.lookup(leaseId));
272
- },
273
- async listOpen(gatewayInstanceId) {
274
- return (await readCurrent()).filter((lease) => (lease.state === "open" || lease.state === "closing") && (!gatewayInstanceId || lease.gatewayInstanceId === gatewayInstanceId));
275
- },
276
- async save(lease) {
277
- await update(async () => {
278
- await params.store.register(lease.leaseId, lease);
279
- });
280
- },
281
- async markState(leaseId, state) {
282
- await update(async () => {
283
- if (state === "closed" || state === "lost") {
284
- await params.store.delete(leaseId);
285
- return;
286
- }
287
- const lease = normalizeAcpxProcessLease(await params.store.lookup(leaseId));
288
- if (lease) await params.store.register(leaseId, {
289
- ...lease,
290
- state
291
- });
292
- });
293
- }
294
- };
295
- }
296
- /** Hash a wrapper command so process leases can detect command drift. */
297
- function hashAcpxProcessCommand(command) {
298
- return createHash("sha256").update(renderAgentCommand(command)).digest("hex");
299
- }
300
- /** Append portable wrapper arguments without changing the executable or argument bytes. */
301
- function withAcpxLeaseArgs(params) {
302
- return [
303
- ...splitCommandParts(params.command),
304
- OPENCLAW_ACPX_LEASE_ID_ARG,
305
- params.leaseId,
306
- OPENCLAW_GATEWAY_INSTANCE_ID_ARG,
307
- params.gatewayInstanceId
308
- ];
309
- }
310
- //#endregion
311
- export { __exportAll as _, hashAcpxProcessCommand as a, openAcpxProcessLeaseStateStore as c, ACPX_GATEWAY_INSTANCE_KEY as d, ACPX_GATEWAY_INSTANCE_NAMESPACE as f, runtime_doctor_migrations_exports as g, normalizeAcpxGatewayInstanceRecord as h, createAcpxProcessLeaseStore as i, readAcpxProcessLeaseIdentity as l, ACPX_LEGACY_PROCESS_LEASE_FILE as m, OPENCLAW_ACPX_LEASE_ID_ARG as n, normalizeAcpxProcessLease as o, ACPX_LEGACY_GATEWAY_INSTANCE_FILE as p, OPENCLAW_GATEWAY_INSTANCE_ID_ARG as r, normalizeAcpxProcessLeaseFile as s, ACPX_PROBE_LEASE_SESSION_KEY as t, withAcpxLeaseArgs as u };
191
+ export { __exportAll as n, runtime_doctor_migrations_exports as t };
@@ -1,9 +1,7 @@
1
- import { a as hashAcpxProcessCommand, c as openAcpxProcessLeaseStateStore, d as ACPX_GATEWAY_INSTANCE_KEY, f as ACPX_GATEWAY_INSTANCE_NAMESPACE, h as normalizeAcpxGatewayInstanceRecord, i as createAcpxProcessLeaseStore, l as readAcpxProcessLeaseIdentity, n as OPENCLAW_ACPX_LEASE_ID_ARG, r as OPENCLAW_GATEWAY_INSTANCE_ID_ARG, t as ACPX_PROBE_LEASE_SESSION_KEY, u as withAcpxLeaseArgs } from "./process-lease-n38HFGdp.mjs";
2
- import { i as toAcpMcpServers, n as resolveAcpxPluginRoot, r as resolveOpenClawRoot, t as resolveAcpxPluginConfig } from "./config-Blz15uwJ.mjs";
3
- import { a as resolveAgentCommand, c as CODEX_ACP_PACKAGE, i as renderAgentCommand, l as LEGACY_CODEX_ACP_PACKAGE, n as isCodexAcpCommand, o as splitCommandParts, r as isOpenClawBridgeCommand, s as CODEX_ACP_BIN, t as isClaudeAcpCommand, u as OPENCLAW_CODEX_CONFIG_ARG } from "./command-line-B72femaL.mjs";
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-76krYh6C.mjs";
4
2
  import { AcpRuntimeError } from "../runtime-api.js";
5
- import { t as resolveAcpxSessionResource } from "./session-resource-B-4yPr-j.mjs";
6
- import { adoptAcpxStateDirectory } from "./session-owner-migration-DsGrYq7Y.mjs";
3
+ import { t as resolveAcpxSessionResource } from "./session-resource-DKJsUJPu.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-C73lfijV.mjs";
7
5
  import { createRequire } from "node:module";
8
6
  import { AcpxRuntime, createAgentRegistry, createFileSessionStore, decodeAcpxRuntimeHandleState, isRequestedModelUnsupportedError } from "acpx/runtime";
9
7
  import { finiteSecondsToTimerSafeMilliseconds, parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
@@ -11,13 +9,14 @@ import fs from "node:fs";
11
9
  import path, { resolve } from "node:path";
12
10
  import { asOptionalObjectRecord, isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
13
11
  import os, { availableParallelism } from "node:os";
14
- import fs$1 from "node:fs/promises";
15
12
  import { randomUUID } from "node:crypto";
16
13
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
17
14
  import { escapeRegExp, sliceUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
15
+ import fs$1 from "node:fs/promises";
16
+ import { raceWithTimeout } from "openclaw/plugin-sdk/time-runtime";
18
17
  import { tryReadJson } from "@openclaw/fs-safe/json";
19
18
  import { parse, stringify } from "smol-toml";
20
- import { setTimeout as setTimeout$1 } from "node:timers/promises";
19
+ import { setTimeout } from "node:timers/promises";
21
20
  import { isPidAlive, runExec } from "openclaw/plugin-sdk/process-runtime";
22
21
  import { AsyncLocalStorage } from "node:async_hooks";
23
22
  import { isDeepStrictEqual } from "node:util";
@@ -203,7 +202,6 @@ function extractInheritedCodexRuntimeConfig(configToml) {
203
202
  if (!INHERITED_TOP_LEVEL_CODEX_CONFIG_KEYS.has(key)) continue;
204
203
  inheritedLines.push(rawLine.trimEnd());
205
204
  }
206
- while (inheritedLines.length > 0 && inheritedLines[inheritedLines.length - 1] === "") inheritedLines.pop();
207
205
  return inheritedLines.join("\n");
208
206
  }
209
207
  function renderIsolatedCodexConfig(params) {
@@ -1132,23 +1130,21 @@ function collectProcessTree(processes, rootPid) {
1132
1130
  function uniquePids(processes) {
1133
1131
  return Array.from(new Set(processes.map((processInfo) => processInfo.pid).filter((pid) => Number.isInteger(pid) && pid > 0 && pid !== process.pid)));
1134
1132
  }
1135
- async function terminatePids(pids, deps) {
1136
- const killProcess = deps?.killProcess ?? ((pid, signal) => process.kill(pid, signal));
1137
- const sleep = deps?.sleep ?? setTimeout$1;
1133
+ async function terminatePids(pids, assertCurrent) {
1138
1134
  const terminated = [];
1139
1135
  for (const pid of pids) {
1140
- deps?.assertCurrent?.();
1136
+ assertCurrent?.();
1141
1137
  try {
1142
- killProcess(pid, "SIGTERM");
1138
+ process.kill(pid, "SIGTERM");
1143
1139
  terminated.push(pid);
1144
1140
  } catch {}
1145
1141
  }
1146
1142
  if (terminated.length === 0) return terminated;
1147
- await sleep(750);
1143
+ await setTimeout(750);
1148
1144
  for (const pid of terminated) {
1149
- deps?.assertCurrent?.();
1150
- if (deps?.killProcess || isPidAlive(pid)) try {
1151
- killProcess(pid, "SIGKILL");
1145
+ assertCurrent?.();
1146
+ if (isPidAlive(pid)) try {
1147
+ process.kill(pid, "SIGKILL");
1152
1148
  } catch {}
1153
1149
  }
1154
1150
  return terminated;
@@ -1161,14 +1157,14 @@ async function cleanupOpenClawOwnedAcpxProcessTree(params) {
1161
1157
  terminatedPids: [],
1162
1158
  skippedReason: "missing-root"
1163
1159
  };
1164
- if ((params.deps?.platform ?? process.platform) === "win32") return {
1160
+ if (process.platform === "win32") return {
1165
1161
  inspectedPids: [],
1166
1162
  terminatedPids: [],
1167
1163
  skippedReason: "unsupported-platform"
1168
1164
  };
1169
1165
  let processes;
1170
1166
  try {
1171
- processes = await (params.deps?.listProcesses ?? listPlatformProcesses)();
1167
+ processes = await listPlatformProcesses();
1172
1168
  } catch {
1173
1169
  return {
1174
1170
  inspectedPids: [],
@@ -1200,12 +1196,12 @@ async function cleanupOpenClawOwnedAcpxProcessTree(params) {
1200
1196
  const pids = uniquePids(listedTree.toReversed());
1201
1197
  return {
1202
1198
  inspectedPids: uniquePids(listedTree),
1203
- terminatedPids: await terminatePids(pids, params.deps)
1199
+ terminatedPids: await terminatePids(pids, params.assertCurrent)
1204
1200
  };
1205
1201
  }
1206
1202
  /** Recover a pending lease by matching its exact live wrapper identity. */
1207
1203
  async function cleanupOpenClawOwnedAcpxPendingLease(params) {
1208
- if ((params.deps?.platform ?? process.platform) === "win32") return {
1204
+ if (process.platform === "win32") return {
1209
1205
  inspectedPids: [],
1210
1206
  terminatedPids: [],
1211
1207
  skippedReason: "unsupported-platform"
@@ -1217,7 +1213,7 @@ async function cleanupOpenClawOwnedAcpxPendingLease(params) {
1217
1213
  };
1218
1214
  let processes;
1219
1215
  try {
1220
- processes = await (params.deps?.listProcesses ?? listPlatformProcesses)();
1216
+ processes = await listPlatformProcesses();
1221
1217
  } catch {
1222
1218
  return {
1223
1219
  inspectedPids: [],
@@ -1244,19 +1240,19 @@ async function cleanupOpenClawOwnedAcpxPendingLease(params) {
1244
1240
  const pids = uniquePids(listedTree.toReversed());
1245
1241
  return {
1246
1242
  inspectedPids: uniquePids(listedTree),
1247
- terminatedPids: await terminatePids(pids, params.deps)
1243
+ terminatedPids: await terminatePids(pids, params.assertCurrent)
1248
1244
  };
1249
1245
  }
1250
1246
  /** Reap orphaned OpenClaw-owned ACPX wrapper trees during runtime startup. */
1251
1247
  async function reapStaleOpenClawOwnedAcpxOrphans(params) {
1252
- if ((params.deps?.platform ?? process.platform) === "win32") return {
1248
+ if (process.platform === "win32") return {
1253
1249
  inspectedPids: [],
1254
1250
  terminatedPids: [],
1255
1251
  skippedReason: "unsupported-platform"
1256
1252
  };
1257
1253
  let processes;
1258
1254
  try {
1259
- processes = await (params.deps?.listProcesses ?? listPlatformProcesses)();
1255
+ processes = await listPlatformProcesses();
1260
1256
  } catch {
1261
1257
  return {
1262
1258
  inspectedPids: [],
@@ -1270,7 +1266,7 @@ async function reapStaleOpenClawOwnedAcpxOrphans(params) {
1270
1266
  })).map((orphan) => collectProcessTree(processes, orphan.pid));
1271
1267
  return {
1272
1268
  inspectedPids: uniquePids(orphanTrees.flat()),
1273
- terminatedPids: await terminatePids(uniquePids(orphanTrees.flatMap((tree) => tree.toReversed())), params.deps)
1269
+ terminatedPids: await terminatePids(uniquePids(orphanTrees.flatMap((tree) => tree.toReversed())), params.assertCurrent)
1274
1270
  };
1275
1271
  }
1276
1272
  //#endregion
@@ -1629,7 +1625,7 @@ function createResetAwareSessionStore(baseStore, params) {
1629
1625
  //#region extensions/acpx/src/runtime-process-cleanup.ts
1630
1626
  /** Capture OpenClaw wrapper cleanup ownership before a backend close can yield. */
1631
1627
  async function prepareAcpxProcessCleanup(params) {
1632
- const { leaseStore, gatewayInstanceId, wrapperRoot, deps } = params;
1628
+ const { leaseStore, gatewayInstanceId, wrapperRoot } = params;
1633
1629
  const rootPid = readRecordAgentPid(params.record);
1634
1630
  const rootCommand = params.command ? renderAgentCommand(params.command) : void 0;
1635
1631
  const identity = readAcpxProcessLeaseIdentity(params.command);
@@ -1653,14 +1649,12 @@ async function prepareAcpxProcessCleanup(params) {
1653
1649
  rootCommand,
1654
1650
  expectedLeaseId: lease.leaseId,
1655
1651
  expectedGatewayInstanceId: lease.gatewayInstanceId,
1656
- wrapperRoot: lease.wrapperRoot,
1657
- deps
1652
+ wrapperRoot: lease.wrapperRoot
1658
1653
  }) : await cleanupOpenClawOwnedAcpxPendingLease({
1659
1654
  leaseId: lease.leaseId,
1660
1655
  gatewayInstanceId: lease.gatewayInstanceId,
1661
1656
  wrapperRoot: lease.wrapperRoot,
1662
- wrapperPath: lease.wrapperPath,
1663
- deps
1657
+ wrapperPath: lease.wrapperPath
1664
1658
  });
1665
1659
  await leaseStore?.markState(lease.leaseId, result.skippedReason === "process-list-unavailable" || result.skippedReason === "unsupported-platform" || lease.rootPid <= 0 && (result.skippedReason === "ambiguous-root" || result.skippedReason === "unverified-root") ? "open" : result.terminatedPids.length > 0 || result.skippedReason === "missing-root" ? "closed" : "lost");
1666
1660
  return;
@@ -1671,8 +1665,7 @@ async function prepareAcpxProcessCleanup(params) {
1671
1665
  rootCommand,
1672
1666
  ...leaseId ? { expectedLeaseId: leaseId } : {},
1673
1667
  ...expectedGatewayInstanceId ? { expectedGatewayInstanceId } : {},
1674
- wrapperRoot,
1675
- deps
1668
+ wrapperRoot
1676
1669
  });
1677
1670
  };
1678
1671
  }
@@ -1883,8 +1876,6 @@ var AcpxRuntime$1 = class {
1883
1876
  this.sessionScope = new AsyncLocalStorage();
1884
1877
  this.launchLeaseScope = new AsyncLocalStorage();
1885
1878
  this.legacyBareSessionKeys = new Set(options.openclawLegacyBareSessionKeys);
1886
- const { openclawProcessCleanup, ...delegateTestOptions } = testOptions ?? {};
1887
- this.processCleanupDeps = openclawProcessCleanup;
1888
1879
  this.wrapperRoot = options.openclawWrapperRoot;
1889
1880
  this.gatewayInstanceId = options.openclawGatewayInstanceId;
1890
1881
  this.processLeaseStore = options.openclawProcessLeaseStore;
@@ -1946,7 +1937,7 @@ var AcpxRuntime$1 = class {
1946
1937
  onSpawnFailed: options.processLifecycle?.onSpawnFailed,
1947
1938
  onExit: options.processLifecycle?.onExit
1948
1939
  }
1949
- }, delegateTestOptions);
1940
+ }, testOptions);
1950
1941
  this.delegate = createDelegate();
1951
1942
  this.generationRegistry = new AcpxGenerationRegistry(this.sessionStore, this.delegate, createDelegate);
1952
1943
  this.probe = new AcpxRuntimeProbe({
@@ -2071,8 +2062,7 @@ var AcpxRuntime$1 = class {
2071
2062
  leaseId,
2072
2063
  gatewayInstanceId: launch.gatewayInstanceId,
2073
2064
  wrapperRoot: launch.wrapperRoot,
2074
- wrapperPath: extractGeneratedWrapperPath(leasedCommand),
2075
- deps: this.processCleanupDeps
2065
+ wrapperPath: extractGeneratedWrapperPath(leasedCommand)
2076
2066
  });
2077
2067
  return result;
2078
2068
  }
@@ -2421,8 +2411,7 @@ var AcpxRuntime$1 = class {
2421
2411
  sessionKey: resolveAcpxSessionResource(input.handle),
2422
2412
  gatewayInstanceId: this.gatewayInstanceId,
2423
2413
  wrapperRoot: this.wrapperRoot,
2424
- leaseStore: this.processLeaseStore,
2425
- deps: this.processCleanupDeps
2414
+ leaseStore: this.processLeaseStore
2426
2415
  }).catch((error) => async () => {
2427
2416
  throw error;
2428
2417
  });
@@ -2496,20 +2485,6 @@ async function measureAcpxStartup(ctx, name, run) {
2496
2485
  function shouldProbeRuntimeAtStartup(env = process.env) {
2497
2486
  return env[ENABLE_STARTUP_PROBE_ENV] !== "0" && env[SKIP_RUNTIME_PROBE_ENV] !== "1";
2498
2487
  }
2499
- async function withStartupProbeTimeout(params) {
2500
- let timeout;
2501
- const timeoutMs = resolveAcpxTimerTimeoutMs(params.timeoutSeconds) ?? 1;
2502
- try {
2503
- return await Promise.race([params.promise, new Promise((_, reject) => {
2504
- timeout = setTimeout(() => {
2505
- reject(/* @__PURE__ */ new Error(`embedded acpx runtime backend startup probe timed out after ${params.timeoutSeconds}s`));
2506
- }, timeoutMs);
2507
- timeout.unref?.();
2508
- })]);
2509
- } finally {
2510
- if (timeout) clearTimeout(timeout);
2511
- }
2512
- }
2513
2488
  async function resolveGatewayInstanceId(openKeyedStore) {
2514
2489
  const store = openKeyedStore({
2515
2490
  namespace: ACPX_GATEWAY_INSTANCE_NAMESPACE,
@@ -2525,14 +2500,7 @@ async function resolveGatewayInstanceId(openKeyedStore) {
2525
2500
  return next;
2526
2501
  }
2527
2502
  async function reapOpenAcpxProcessLeases(params) {
2528
- const assertCurrent = () => {
2529
- params.assertCurrent?.();
2530
- params.deps?.assertCurrent?.();
2531
- };
2532
- const deps = {
2533
- ...params.deps,
2534
- assertCurrent
2535
- };
2503
+ const { assertCurrent } = params;
2536
2504
  const leases = await params.leaseStore.listOpen(params.gatewayInstanceId);
2537
2505
  const inspectedPids = [];
2538
2506
  const terminatedPids = [];
@@ -2540,33 +2508,33 @@ async function reapOpenAcpxProcessLeases(params) {
2540
2508
  for (const lease of leases) {
2541
2509
  const pending = lease.rootPid <= 0;
2542
2510
  if (pending) legacyWrapperRoots.add(lease.wrapperRoot);
2543
- assertCurrent();
2511
+ assertCurrent?.();
2544
2512
  await params.leaseStore.markState(lease.leaseId, "closing");
2545
- assertCurrent();
2513
+ assertCurrent?.();
2546
2514
  const result = pending ? await cleanupOpenClawOwnedAcpxPendingLease({
2547
2515
  leaseId: lease.leaseId,
2548
2516
  gatewayInstanceId: lease.gatewayInstanceId,
2549
2517
  wrapperRoot: lease.wrapperRoot,
2550
2518
  wrapperPath: lease.wrapperPath,
2551
- deps
2519
+ assertCurrent
2552
2520
  }) : await cleanupOpenClawOwnedAcpxProcessTree({
2553
2521
  rootPid: lease.rootPid,
2554
2522
  expectedLeaseId: lease.leaseId,
2555
2523
  expectedGatewayInstanceId: lease.gatewayInstanceId,
2556
2524
  wrapperRoot: lease.wrapperRoot,
2557
- deps
2525
+ assertCurrent
2558
2526
  });
2559
2527
  inspectedPids.push(...result.inspectedPids);
2560
2528
  terminatedPids.push(...result.terminatedPids);
2561
2529
  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");
2562
- assertCurrent();
2530
+ assertCurrent?.();
2563
2531
  await params.leaseStore.markState(lease.leaseId, retryableEvidenceFailure ? "open" : result.terminatedPids.length > 0 ? "closed" : "lost");
2564
2532
  }
2565
2533
  for (const wrapperRoot of legacyWrapperRoots) {
2566
- assertCurrent();
2534
+ assertCurrent?.();
2567
2535
  const legacyResult = await reapStaleOpenClawOwnedAcpxOrphans({
2568
2536
  wrapperRoot,
2569
- deps
2537
+ assertCurrent
2570
2538
  });
2571
2539
  inspectedPids.push(...legacyResult.inspectedPids);
2572
2540
  terminatedPids.push(...legacyResult.terminatedPids);
@@ -2637,7 +2605,6 @@ function createAcpxRuntimeService(params) {
2637
2605
  recoverProcesses = (assertCurrent) => reapOpenAcpxProcessLeases({
2638
2606
  gatewayInstanceId,
2639
2607
  leaseStore: processLeaseStore,
2640
- deps: params.processCleanupDeps,
2641
2608
  assertCurrent
2642
2609
  });
2643
2610
  if (params.startupPurpose !== "inspection") await promote(ctx);
@@ -2666,10 +2633,10 @@ function createAcpxRuntimeService(params) {
2666
2633
  lifecycleRevision += 1;
2667
2634
  const currentRevision = lifecycleRevision;
2668
2635
  try {
2669
- const doctorReport = await measureAcpxStartup(ctx, "probe.availability", () => withStartupProbeTimeout({
2670
- promise: startedRuntime.doctor(),
2671
- timeoutSeconds: pluginConfig.timeoutSeconds ?? 120
2672
- }));
2636
+ const timeoutSeconds = pluginConfig.timeoutSeconds ?? 120;
2637
+ const doctorReport = await measureAcpxStartup(ctx, "probe.availability", () => raceWithTimeout(startedRuntime.doctor(), resolveAcpxTimerTimeoutMs(timeoutSeconds) ?? 1, () => {
2638
+ throw new Error(`embedded acpx runtime backend startup probe timed out after ${timeoutSeconds}s`);
2639
+ }, { ref: false }));
2673
2640
  if (currentRevision !== lifecycleRevision) return;
2674
2641
  if (doctorReport.ok) {
2675
2642
  ctx.startupTrace?.detail?.("probe.result", [["healthyCount", 1]]);