@openclaw/acpx 2026.9.8 → 2026.10.1-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-Blz15uwJ.mjs → config-76krYh6C.mjs} +131 -3
- package/dist/.setup/{register.runtime-DByczkH_.mjs → register.runtime-C0nVOTzT.mjs} +1 -1
- package/dist/.setup/{process-lease-n38HFGdp.mjs → runtime-doctor-migrations-hxP-CXX7.mjs} +9 -129
- package/dist/.setup/{service-D5hGWl5U.mjs → service-BXgGdE56.mjs} +41 -74
- package/dist/.setup/{session-owner-migration-DsGrYq7Y.mjs → session-owner-migration-C73lfijV.mjs} +121 -5
- package/dist/.setup/{session-resource-B-4yPr-j.mjs → session-resource-DKJsUJPu.mjs} +1 -1
- package/dist/doctor-contract-api.js +4 -94
- package/dist/index.js +6 -5
- package/dist/register.runtime.js +1 -1
- package/openclaw.plugin.json +0 -1
- package/package.json +5 -15
- package/dist/.setup/command-line-B72femaL.mjs +0 -135
- package/dist/mcp-command-line.mjs +0 -128
- package/dist/mcp-proxy.mjs +0 -159
- package/dist/.setup/{pi-session-catalog-runtime-IKEanK3s.mjs → pi-session-catalog-runtime-7jc50ZJ4.mjs} +1 -1
|
@@ -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 {
|
|
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-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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-
|
|
6
|
-
import { adoptAcpxStateDirectory } from "./session-owner-migration-
|
|
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
|
|
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,
|
|
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
|
-
|
|
1136
|
+
assertCurrent?.();
|
|
1141
1137
|
try {
|
|
1142
|
-
|
|
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
|
|
1143
|
+
await setTimeout(750);
|
|
1148
1144
|
for (const pid of terminated) {
|
|
1149
|
-
|
|
1150
|
-
if (
|
|
1151
|
-
|
|
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 (
|
|
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
|
|
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.
|
|
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 (
|
|
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
|
|
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.
|
|
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 (
|
|
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
|
|
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.
|
|
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
|
|
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
|
-
},
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
2670
|
-
|
|
2671
|
-
|
|
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]]);
|