@openclaw/acpx 2026.5.4-beta.1 → 2026.5.4-beta.3

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.
@@ -4,7 +4,7 @@ const ACPX_BACKEND_ID = "acpx";
4
4
  const ENABLE_STARTUP_PROBE_ENV = "OPENCLAW_ACPX_RUNTIME_STARTUP_PROBE";
5
5
  let serviceModulePromise = null;
6
6
  function loadServiceModule() {
7
- serviceModulePromise ??= import("./service-YhcC786_.js");
7
+ serviceModulePromise ??= import("./service-DXpBsJTq.js");
8
8
  return serviceModulePromise;
9
9
  }
10
10
  function shouldRunStartupProbe(env = process.env) {
@@ -4,20 +4,226 @@ import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtim
4
4
  import fs from "node:fs/promises";
5
5
  import { inspect } from "node:util";
6
6
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
7
+ import fsSync from "node:fs";
7
8
  import path from "node:path";
8
- import fs$1 from "node:fs";
9
9
  import { fileURLToPath } from "node:url";
10
10
  import { formatPluginConfigIssue } from "openclaw/plugin-sdk/extension-shared";
11
11
  import { z } from "openclaw/plugin-sdk/zod";
12
+ //#region extensions/acpx/src/config-schema.ts
13
+ const ACPX_PERMISSION_MODES = [
14
+ "approve-all",
15
+ "approve-reads",
16
+ "deny-all"
17
+ ];
18
+ const ACPX_NON_INTERACTIVE_POLICIES = ["deny", "fail"];
19
+ const nonEmptyTrimmedString = (message) => z.string({ error: message }).trim().min(1, { error: message });
20
+ const McpServerConfigSchema = z.object({
21
+ command: nonEmptyTrimmedString("command must be a non-empty string").describe("Command to run the MCP server"),
22
+ args: z.array(z.string({ error: "args must be an array of strings" }), { error: "args must be an array of strings" }).optional().describe("Arguments to pass to the command"),
23
+ env: z.record(z.string(), z.string({ error: "env values must be strings" }), { error: "env must be an object of strings" }).optional().describe("Environment variables for the MCP server")
24
+ });
25
+ const AcpxPluginConfigSchema = z.strictObject({
26
+ cwd: nonEmptyTrimmedString("cwd must be a non-empty string").optional(),
27
+ stateDir: nonEmptyTrimmedString("stateDir must be a non-empty string").optional(),
28
+ probeAgent: nonEmptyTrimmedString("probeAgent must be a non-empty string").optional(),
29
+ permissionMode: z.enum(ACPX_PERMISSION_MODES, { error: `permissionMode must be one of: ${ACPX_PERMISSION_MODES.join(", ")}` }).optional(),
30
+ nonInteractivePermissions: z.enum(ACPX_NON_INTERACTIVE_POLICIES, { error: `nonInteractivePermissions must be one of: ${ACPX_NON_INTERACTIVE_POLICIES.join(", ")}` }).optional(),
31
+ pluginToolsMcpBridge: z.boolean({ error: "pluginToolsMcpBridge must be a boolean" }).optional(),
32
+ openClawToolsMcpBridge: z.boolean({ error: "openClawToolsMcpBridge must be a boolean" }).optional(),
33
+ strictWindowsCmdWrapper: z.boolean({ error: "strictWindowsCmdWrapper must be a boolean" }).optional(),
34
+ timeoutSeconds: z.number({ error: "timeoutSeconds must be a number >= 0.001" }).min(.001, { error: "timeoutSeconds must be a number >= 0.001" }).default(120),
35
+ queueOwnerTtlSeconds: z.number({ error: "queueOwnerTtlSeconds must be a number >= 0" }).min(0, { error: "queueOwnerTtlSeconds must be a number >= 0" }).optional(),
36
+ mcpServers: z.record(z.string(), McpServerConfigSchema).optional(),
37
+ agents: z.record(z.string(), z.strictObject({ command: nonEmptyTrimmedString("agents.<id>.command must be a non-empty string") })).optional()
38
+ });
39
+ //#endregion
40
+ //#region extensions/acpx/src/config.ts
41
+ const ACPX_PLUGIN_TOOLS_MCP_SERVER_NAME = "openclaw-plugin-tools";
42
+ const ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME = "openclaw-tools";
43
+ const requireFromHere$1 = createRequire(import.meta.url);
44
+ function isAcpxPluginRoot(dir) {
45
+ return fsSync.existsSync(path.join(dir, "openclaw.plugin.json")) && fsSync.existsSync(path.join(dir, "package.json"));
46
+ }
47
+ function resolveNearestAcpxPluginRoot(moduleUrl) {
48
+ let cursor = path.dirname(fileURLToPath(moduleUrl));
49
+ for (let i = 0; i < 3; i += 1) {
50
+ if (isAcpxPluginRoot(cursor)) return cursor;
51
+ const parent = path.dirname(cursor);
52
+ if (parent === cursor) break;
53
+ cursor = parent;
54
+ }
55
+ return path.resolve(path.dirname(fileURLToPath(moduleUrl)), "..");
56
+ }
57
+ function resolveWorkspaceAcpxPluginRoot(currentRoot) {
58
+ if (path.basename(currentRoot) !== "acpx" || path.basename(path.dirname(currentRoot)) !== "extensions" || path.basename(path.dirname(path.dirname(currentRoot))) !== "dist") return null;
59
+ const workspaceRoot = path.resolve(currentRoot, "..", "..", "..", "extensions", "acpx");
60
+ return isAcpxPluginRoot(workspaceRoot) ? workspaceRoot : null;
61
+ }
62
+ function resolveRepoAcpxPluginRoot(currentRoot) {
63
+ const workspaceRoot = path.join(currentRoot, "extensions", "acpx");
64
+ return isAcpxPluginRoot(workspaceRoot) ? workspaceRoot : null;
65
+ }
66
+ function resolveAcpxPluginRootFromOpenClawLayout(moduleUrl) {
67
+ let cursor = path.dirname(fileURLToPath(moduleUrl));
68
+ for (let i = 0; i < 5; i += 1) {
69
+ const candidates = [
70
+ path.join(cursor, "extensions", "acpx"),
71
+ path.join(cursor, "dist", "extensions", "acpx"),
72
+ path.join(cursor, "dist-runtime", "extensions", "acpx")
73
+ ];
74
+ for (const candidate of candidates) if (isAcpxPluginRoot(candidate)) return candidate;
75
+ const parent = path.dirname(cursor);
76
+ if (parent === cursor) break;
77
+ cursor = parent;
78
+ }
79
+ return null;
80
+ }
81
+ function resolveAcpxPluginRoot(moduleUrl = import.meta.url) {
82
+ const resolvedRoot = resolveNearestAcpxPluginRoot(moduleUrl);
83
+ return resolveWorkspaceAcpxPluginRoot(resolvedRoot) ?? resolveRepoAcpxPluginRoot(resolvedRoot) ?? resolveAcpxPluginRootFromOpenClawLayout(moduleUrl) ?? resolvedRoot;
84
+ }
85
+ const DEFAULT_PERMISSION_MODE = "approve-reads";
86
+ const DEFAULT_NON_INTERACTIVE_POLICY = "fail";
87
+ const DEFAULT_QUEUE_OWNER_TTL_SECONDS = .1;
88
+ const DEFAULT_STRICT_WINDOWS_CMD_WRAPPER = true;
89
+ function parseAcpxPluginConfig(value) {
90
+ if (value === void 0) return {
91
+ ok: true,
92
+ value: void 0
93
+ };
94
+ const parsed = AcpxPluginConfigSchema.safeParse(value);
95
+ if (!parsed.success) return {
96
+ ok: false,
97
+ message: formatPluginConfigIssue(parsed.error.issues[0])
98
+ };
99
+ return {
100
+ ok: true,
101
+ value: parsed.data
102
+ };
103
+ }
104
+ function resolveOpenClawRoot(currentRoot) {
105
+ if (path.basename(currentRoot) === "acpx" && path.basename(path.dirname(currentRoot)) === "extensions") {
106
+ const parent = path.dirname(path.dirname(currentRoot));
107
+ if (path.basename(parent) === "dist") return path.dirname(parent);
108
+ return parent;
109
+ }
110
+ return path.resolve(currentRoot, "..");
111
+ }
112
+ function resolveTsxImportSpecifier() {
113
+ try {
114
+ return requireFromHere$1.resolve("tsx");
115
+ } catch {
116
+ return "tsx";
117
+ }
118
+ }
119
+ function resolvePluginToolsMcpServerConfig(moduleUrl = import.meta.url) {
120
+ const openClawRoot = resolveOpenClawRoot(resolveAcpxPluginRoot(moduleUrl));
121
+ const distEntry = path.join(openClawRoot, "dist", "mcp", "plugin-tools-serve.js");
122
+ if (fsSync.existsSync(distEntry)) return {
123
+ command: process.execPath,
124
+ args: [distEntry]
125
+ };
126
+ const sourceEntry = path.join(openClawRoot, "src", "mcp", "plugin-tools-serve.ts");
127
+ return {
128
+ command: process.execPath,
129
+ args: [
130
+ "--import",
131
+ resolveTsxImportSpecifier(),
132
+ sourceEntry
133
+ ]
134
+ };
135
+ }
136
+ function resolveOpenClawToolsMcpServerConfig(moduleUrl = import.meta.url) {
137
+ const openClawRoot = resolveOpenClawRoot(resolveAcpxPluginRoot(moduleUrl));
138
+ const distEntry = path.join(openClawRoot, "dist", "mcp", "openclaw-tools-serve.js");
139
+ if (fsSync.existsSync(distEntry)) return {
140
+ command: process.execPath,
141
+ args: [distEntry]
142
+ };
143
+ const sourceEntry = path.join(openClawRoot, "src", "mcp", "openclaw-tools-serve.ts");
144
+ return {
145
+ command: process.execPath,
146
+ args: [
147
+ "--import",
148
+ resolveTsxImportSpecifier(),
149
+ sourceEntry
150
+ ]
151
+ };
152
+ }
153
+ function resolveConfiguredMcpServers(params) {
154
+ const resolved = { ...params.mcpServers };
155
+ 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`);
156
+ 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`);
157
+ if (params.pluginToolsMcpBridge) resolved[ACPX_PLUGIN_TOOLS_MCP_SERVER_NAME] = resolvePluginToolsMcpServerConfig(params.moduleUrl);
158
+ if (params.openClawToolsMcpBridge) resolved[ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME] = resolveOpenClawToolsMcpServerConfig(params.moduleUrl);
159
+ return resolved;
160
+ }
161
+ function toAcpMcpServers(mcpServers) {
162
+ return Object.entries(mcpServers).map(([name, server]) => ({
163
+ name,
164
+ command: server.command,
165
+ args: [...server.args ?? []],
166
+ env: Object.entries(server.env ?? {}).map(([envName, value]) => ({
167
+ name: envName,
168
+ value
169
+ }))
170
+ }));
171
+ }
172
+ function resolveAcpxPluginConfig(params) {
173
+ const parsed = parseAcpxPluginConfig(params.rawConfig);
174
+ if (!parsed.ok) throw new Error(parsed.message);
175
+ const normalized = parsed.value ?? {};
176
+ const workspaceDir = params.workspaceDir?.trim() || process.cwd();
177
+ const fallbackCwd = workspaceDir;
178
+ const cwd = path.resolve(normalized.cwd?.trim() || fallbackCwd);
179
+ const stateDir = path.resolve(normalized.stateDir?.trim() || path.join(workspaceDir, "state"));
180
+ const pluginToolsMcpBridge = normalized.pluginToolsMcpBridge === true;
181
+ const openClawToolsMcpBridge = normalized.openClawToolsMcpBridge === true;
182
+ const mcpServers = resolveConfiguredMcpServers({
183
+ mcpServers: normalized.mcpServers,
184
+ pluginToolsMcpBridge,
185
+ openClawToolsMcpBridge,
186
+ moduleUrl: params.moduleUrl
187
+ });
188
+ const agents = Object.fromEntries(Object.entries(normalized.agents ?? {}).map(([name, entry]) => [normalizeLowercaseStringOrEmpty(name), entry.command.trim()]));
189
+ return {
190
+ cwd,
191
+ stateDir,
192
+ probeAgent: normalizeLowercaseStringOrEmpty(normalized.probeAgent) || void 0,
193
+ permissionMode: normalized.permissionMode ?? DEFAULT_PERMISSION_MODE,
194
+ nonInteractivePermissions: normalized.nonInteractivePermissions ?? DEFAULT_NON_INTERACTIVE_POLICY,
195
+ pluginToolsMcpBridge,
196
+ openClawToolsMcpBridge,
197
+ strictWindowsCmdWrapper: normalized.strictWindowsCmdWrapper ?? DEFAULT_STRICT_WINDOWS_CMD_WRAPPER,
198
+ timeoutSeconds: normalized.timeoutSeconds ?? 120,
199
+ queueOwnerTtlSeconds: normalized.queueOwnerTtlSeconds ?? DEFAULT_QUEUE_OWNER_TTL_SECONDS,
200
+ legacyCompatibilityConfig: {
201
+ strictWindowsCmdWrapper: normalized.strictWindowsCmdWrapper,
202
+ queueOwnerTtlSeconds: normalized.queueOwnerTtlSeconds
203
+ },
204
+ mcpServers,
205
+ agents
206
+ };
207
+ }
208
+ //#endregion
12
209
  //#region extensions/acpx/src/codex-auth-bridge.ts
13
210
  const CODEX_ACP_PACKAGE = "@zed-industries/codex-acp";
14
- const CODEX_ACP_PACKAGE_RANGE = "^0.12.0";
15
211
  const CODEX_ACP_BIN = "codex-acp";
16
212
  const CLAUDE_ACP_PACKAGE = "@agentclientprotocol/claude-agent-acp";
17
- const CLAUDE_ACP_PACKAGE_VERSION = "0.31.4";
18
213
  const CLAUDE_ACP_BIN = "claude-agent-acp";
19
214
  const RUN_CONFIGURED_COMMAND_SENTINEL = "--openclaw-run-configured";
20
- const requireFromHere$1 = createRequire(import.meta.url);
215
+ const requireFromHere = createRequire(import.meta.url);
216
+ function readSelfManifest() {
217
+ const manifestPath = path.join(resolveAcpxPluginRoot(import.meta.url), "package.json");
218
+ return JSON.parse(fsSync.readFileSync(manifestPath, "utf8"));
219
+ }
220
+ function readManifestDependencyVersion(packageName) {
221
+ const version = readSelfManifest().dependencies?.[packageName];
222
+ if (typeof version !== "string" || version.trim() === "") throw new Error(`Missing ${packageName} dependency version in @openclaw/acpx manifest`);
223
+ return version;
224
+ }
225
+ const CODEX_ACP_PACKAGE_VERSION = readManifestDependencyVersion(CODEX_ACP_PACKAGE);
226
+ const CLAUDE_ACP_PACKAGE_VERSION = readManifestDependencyVersion(CLAUDE_ACP_PACKAGE);
21
227
  function quoteCommandPart(value) {
22
228
  return JSON.stringify(value);
23
229
  }
@@ -69,7 +275,7 @@ function resolvePackageBinPath(packageJsonPath, manifest, binName) {
69
275
  }
70
276
  async function resolveInstalledAcpPackageBinPath(packageName, binName) {
71
277
  try {
72
- const packageJsonPath = requireFromHere$1.resolve(`${packageName}/package.json`);
278
+ const packageJsonPath = requireFromHere.resolve(`${packageName}/package.json`);
73
279
  const manifest = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
74
280
  if (manifest.name !== packageName) return;
75
281
  const binPath = resolvePackageBinPath(packageJsonPath, manifest, binName);
@@ -163,7 +369,7 @@ child.on("exit", (code, signal) => {
163
369
  function buildCodexAcpWrapperScript(installedBinPath) {
164
370
  return buildAdapterWrapperScript({
165
371
  displayName: "Codex",
166
- packageSpec: `${CODEX_ACP_PACKAGE}@${CODEX_ACP_PACKAGE_RANGE}`,
372
+ packageSpec: `${CODEX_ACP_PACKAGE}@${CODEX_ACP_PACKAGE_VERSION}`,
167
373
  binName: CODEX_ACP_BIN,
168
374
  installedBinPath,
169
375
  envSetup: `const codexHome = fileURLToPath(new URL("./codex-home/", import.meta.url));
@@ -282,203 +488,6 @@ async function prepareAcpxCodexAuthConfig(params) {
282
488
  };
283
489
  }
284
490
  //#endregion
285
- //#region extensions/acpx/src/config-schema.ts
286
- const ACPX_PERMISSION_MODES = [
287
- "approve-all",
288
- "approve-reads",
289
- "deny-all"
290
- ];
291
- const ACPX_NON_INTERACTIVE_POLICIES = ["deny", "fail"];
292
- const nonEmptyTrimmedString = (message) => z.string({ error: message }).trim().min(1, { error: message });
293
- const McpServerConfigSchema = z.object({
294
- command: nonEmptyTrimmedString("command must be a non-empty string").describe("Command to run the MCP server"),
295
- args: z.array(z.string({ error: "args must be an array of strings" }), { error: "args must be an array of strings" }).optional().describe("Arguments to pass to the command"),
296
- env: z.record(z.string(), z.string({ error: "env values must be strings" }), { error: "env must be an object of strings" }).optional().describe("Environment variables for the MCP server")
297
- });
298
- const AcpxPluginConfigSchema = z.strictObject({
299
- cwd: nonEmptyTrimmedString("cwd must be a non-empty string").optional(),
300
- stateDir: nonEmptyTrimmedString("stateDir must be a non-empty string").optional(),
301
- probeAgent: nonEmptyTrimmedString("probeAgent must be a non-empty string").optional(),
302
- permissionMode: z.enum(ACPX_PERMISSION_MODES, { error: `permissionMode must be one of: ${ACPX_PERMISSION_MODES.join(", ")}` }).optional(),
303
- nonInteractivePermissions: z.enum(ACPX_NON_INTERACTIVE_POLICIES, { error: `nonInteractivePermissions must be one of: ${ACPX_NON_INTERACTIVE_POLICIES.join(", ")}` }).optional(),
304
- pluginToolsMcpBridge: z.boolean({ error: "pluginToolsMcpBridge must be a boolean" }).optional(),
305
- openClawToolsMcpBridge: z.boolean({ error: "openClawToolsMcpBridge must be a boolean" }).optional(),
306
- strictWindowsCmdWrapper: z.boolean({ error: "strictWindowsCmdWrapper must be a boolean" }).optional(),
307
- timeoutSeconds: z.number({ error: "timeoutSeconds must be a number >= 0.001" }).min(.001, { error: "timeoutSeconds must be a number >= 0.001" }).default(120),
308
- queueOwnerTtlSeconds: z.number({ error: "queueOwnerTtlSeconds must be a number >= 0" }).min(0, { error: "queueOwnerTtlSeconds must be a number >= 0" }).optional(),
309
- mcpServers: z.record(z.string(), McpServerConfigSchema).optional(),
310
- agents: z.record(z.string(), z.strictObject({ command: nonEmptyTrimmedString("agents.<id>.command must be a non-empty string") })).optional()
311
- });
312
- //#endregion
313
- //#region extensions/acpx/src/config.ts
314
- const ACPX_PLUGIN_TOOLS_MCP_SERVER_NAME = "openclaw-plugin-tools";
315
- const ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME = "openclaw-tools";
316
- const requireFromHere = createRequire(import.meta.url);
317
- function isAcpxPluginRoot(dir) {
318
- return fs$1.existsSync(path.join(dir, "openclaw.plugin.json")) && fs$1.existsSync(path.join(dir, "package.json"));
319
- }
320
- function resolveNearestAcpxPluginRoot(moduleUrl) {
321
- let cursor = path.dirname(fileURLToPath(moduleUrl));
322
- for (let i = 0; i < 3; i += 1) {
323
- if (isAcpxPluginRoot(cursor)) return cursor;
324
- const parent = path.dirname(cursor);
325
- if (parent === cursor) break;
326
- cursor = parent;
327
- }
328
- return path.resolve(path.dirname(fileURLToPath(moduleUrl)), "..");
329
- }
330
- function resolveWorkspaceAcpxPluginRoot(currentRoot) {
331
- if (path.basename(currentRoot) !== "acpx" || path.basename(path.dirname(currentRoot)) !== "extensions" || path.basename(path.dirname(path.dirname(currentRoot))) !== "dist") return null;
332
- const workspaceRoot = path.resolve(currentRoot, "..", "..", "..", "extensions", "acpx");
333
- return isAcpxPluginRoot(workspaceRoot) ? workspaceRoot : null;
334
- }
335
- function resolveRepoAcpxPluginRoot(currentRoot) {
336
- const workspaceRoot = path.join(currentRoot, "extensions", "acpx");
337
- return isAcpxPluginRoot(workspaceRoot) ? workspaceRoot : null;
338
- }
339
- function resolveAcpxPluginRootFromOpenClawLayout(moduleUrl) {
340
- let cursor = path.dirname(fileURLToPath(moduleUrl));
341
- for (let i = 0; i < 5; i += 1) {
342
- const candidates = [
343
- path.join(cursor, "extensions", "acpx"),
344
- path.join(cursor, "dist", "extensions", "acpx"),
345
- path.join(cursor, "dist-runtime", "extensions", "acpx")
346
- ];
347
- for (const candidate of candidates) if (isAcpxPluginRoot(candidate)) return candidate;
348
- const parent = path.dirname(cursor);
349
- if (parent === cursor) break;
350
- cursor = parent;
351
- }
352
- return null;
353
- }
354
- function resolveAcpxPluginRoot(moduleUrl = import.meta.url) {
355
- const resolvedRoot = resolveNearestAcpxPluginRoot(moduleUrl);
356
- return resolveWorkspaceAcpxPluginRoot(resolvedRoot) ?? resolveRepoAcpxPluginRoot(resolvedRoot) ?? resolveAcpxPluginRootFromOpenClawLayout(moduleUrl) ?? resolvedRoot;
357
- }
358
- const DEFAULT_PERMISSION_MODE = "approve-reads";
359
- const DEFAULT_NON_INTERACTIVE_POLICY = "fail";
360
- const DEFAULT_QUEUE_OWNER_TTL_SECONDS = .1;
361
- const DEFAULT_STRICT_WINDOWS_CMD_WRAPPER = true;
362
- function parseAcpxPluginConfig(value) {
363
- if (value === void 0) return {
364
- ok: true,
365
- value: void 0
366
- };
367
- const parsed = AcpxPluginConfigSchema.safeParse(value);
368
- if (!parsed.success) return {
369
- ok: false,
370
- message: formatPluginConfigIssue(parsed.error.issues[0])
371
- };
372
- return {
373
- ok: true,
374
- value: parsed.data
375
- };
376
- }
377
- function resolveOpenClawRoot(currentRoot) {
378
- if (path.basename(currentRoot) === "acpx" && path.basename(path.dirname(currentRoot)) === "extensions") {
379
- const parent = path.dirname(path.dirname(currentRoot));
380
- if (path.basename(parent) === "dist") return path.dirname(parent);
381
- return parent;
382
- }
383
- return path.resolve(currentRoot, "..");
384
- }
385
- function resolveTsxImportSpecifier() {
386
- try {
387
- return requireFromHere.resolve("tsx");
388
- } catch {
389
- return "tsx";
390
- }
391
- }
392
- function resolvePluginToolsMcpServerConfig(moduleUrl = import.meta.url) {
393
- const openClawRoot = resolveOpenClawRoot(resolveAcpxPluginRoot(moduleUrl));
394
- const distEntry = path.join(openClawRoot, "dist", "mcp", "plugin-tools-serve.js");
395
- if (fs$1.existsSync(distEntry)) return {
396
- command: process.execPath,
397
- args: [distEntry]
398
- };
399
- const sourceEntry = path.join(openClawRoot, "src", "mcp", "plugin-tools-serve.ts");
400
- return {
401
- command: process.execPath,
402
- args: [
403
- "--import",
404
- resolveTsxImportSpecifier(),
405
- sourceEntry
406
- ]
407
- };
408
- }
409
- function resolveOpenClawToolsMcpServerConfig(moduleUrl = import.meta.url) {
410
- const openClawRoot = resolveOpenClawRoot(resolveAcpxPluginRoot(moduleUrl));
411
- const distEntry = path.join(openClawRoot, "dist", "mcp", "openclaw-tools-serve.js");
412
- if (fs$1.existsSync(distEntry)) return {
413
- command: process.execPath,
414
- args: [distEntry]
415
- };
416
- const sourceEntry = path.join(openClawRoot, "src", "mcp", "openclaw-tools-serve.ts");
417
- return {
418
- command: process.execPath,
419
- args: [
420
- "--import",
421
- resolveTsxImportSpecifier(),
422
- sourceEntry
423
- ]
424
- };
425
- }
426
- function resolveConfiguredMcpServers(params) {
427
- const resolved = { ...params.mcpServers };
428
- 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`);
429
- 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`);
430
- if (params.pluginToolsMcpBridge) resolved[ACPX_PLUGIN_TOOLS_MCP_SERVER_NAME] = resolvePluginToolsMcpServerConfig(params.moduleUrl);
431
- if (params.openClawToolsMcpBridge) resolved[ACPX_OPENCLAW_TOOLS_MCP_SERVER_NAME] = resolveOpenClawToolsMcpServerConfig(params.moduleUrl);
432
- return resolved;
433
- }
434
- function toAcpMcpServers(mcpServers) {
435
- return Object.entries(mcpServers).map(([name, server]) => ({
436
- name,
437
- command: server.command,
438
- args: [...server.args ?? []],
439
- env: Object.entries(server.env ?? {}).map(([envName, value]) => ({
440
- name: envName,
441
- value
442
- }))
443
- }));
444
- }
445
- function resolveAcpxPluginConfig(params) {
446
- const parsed = parseAcpxPluginConfig(params.rawConfig);
447
- if (!parsed.ok) throw new Error(parsed.message);
448
- const normalized = parsed.value ?? {};
449
- const workspaceDir = params.workspaceDir?.trim() || process.cwd();
450
- const fallbackCwd = workspaceDir;
451
- const cwd = path.resolve(normalized.cwd?.trim() || fallbackCwd);
452
- const stateDir = path.resolve(normalized.stateDir?.trim() || path.join(workspaceDir, "state"));
453
- const pluginToolsMcpBridge = normalized.pluginToolsMcpBridge === true;
454
- const openClawToolsMcpBridge = normalized.openClawToolsMcpBridge === true;
455
- const mcpServers = resolveConfiguredMcpServers({
456
- mcpServers: normalized.mcpServers,
457
- pluginToolsMcpBridge,
458
- openClawToolsMcpBridge,
459
- moduleUrl: params.moduleUrl
460
- });
461
- const agents = Object.fromEntries(Object.entries(normalized.agents ?? {}).map(([name, entry]) => [normalizeLowercaseStringOrEmpty(name), entry.command.trim()]));
462
- return {
463
- cwd,
464
- stateDir,
465
- probeAgent: normalizeLowercaseStringOrEmpty(normalized.probeAgent) || void 0,
466
- permissionMode: normalized.permissionMode ?? DEFAULT_PERMISSION_MODE,
467
- nonInteractivePermissions: normalized.nonInteractivePermissions ?? DEFAULT_NON_INTERACTIVE_POLICY,
468
- pluginToolsMcpBridge,
469
- openClawToolsMcpBridge,
470
- strictWindowsCmdWrapper: normalized.strictWindowsCmdWrapper ?? DEFAULT_STRICT_WINDOWS_CMD_WRAPPER,
471
- timeoutSeconds: normalized.timeoutSeconds ?? 120,
472
- queueOwnerTtlSeconds: normalized.queueOwnerTtlSeconds ?? DEFAULT_QUEUE_OWNER_TTL_SECONDS,
473
- legacyCompatibilityConfig: {
474
- strictWindowsCmdWrapper: normalized.strictWindowsCmdWrapper,
475
- queueOwnerTtlSeconds: normalized.queueOwnerTtlSeconds
476
- },
477
- mcpServers,
478
- agents
479
- };
480
- }
481
- //#endregion
482
491
  //#region extensions/acpx/src/service.ts
483
492
  const ENABLE_STARTUP_PROBE_ENV = "OPENCLAW_ACPX_RUNTIME_STARTUP_PROBE";
484
493
  const ACPX_BACKEND_ID = "acpx";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/acpx",
3
- "version": "2026.5.4-beta.1",
3
+ "version": "2026.5.4-beta.3",
4
4
  "description": "OpenClaw ACP runtime backend",
5
5
  "repository": {
6
6
  "type": "git",
@@ -8,8 +8,8 @@
8
8
  },
9
9
  "type": "module",
10
10
  "dependencies": {
11
- "@agentclientprotocol/claude-agent-acp": "0.31.4",
12
- "@zed-industries/codex-acp": "0.12.0",
11
+ "@agentclientprotocol/claude-agent-acp": "0.32.0",
12
+ "@zed-industries/codex-acp": "0.13.0",
13
13
  "acpx": "0.6.1"
14
14
  },
15
15
  "devDependencies": {
@@ -25,10 +25,10 @@
25
25
  "minHostVersion": ">=2026.4.25"
26
26
  },
27
27
  "compat": {
28
- "pluginApi": ">=2026.5.4-beta.1"
28
+ "pluginApi": ">=2026.5.4-beta.3"
29
29
  },
30
30
  "build": {
31
- "openclawVersion": "2026.5.4-beta.1",
31
+ "openclawVersion": "2026.5.4-beta.3",
32
32
  "staticAssets": [
33
33
  {
34
34
  "source": "./src/runtime-internals/mcp-proxy.mjs",
@@ -58,7 +58,7 @@
58
58
  "skills/**"
59
59
  ],
60
60
  "peerDependencies": {
61
- "openclaw": ">=2026.5.4-beta.1"
61
+ "openclaw": ">=2026.5.4-beta.3"
62
62
  },
63
63
  "peerDependenciesMeta": {
64
64
  "openclaw": {
@@ -211,8 +211,8 @@ ${ACPX_CMD} codex sessions close oc-codex-<conversationId>
211
211
  Defaults are:
212
212
 
213
213
  - `openclaw -> openclaw acp`
214
- - `claude -> npx -y @agentclientprotocol/claude-agent-acp@^0.31.0`
215
- - `codex -> bundled @zed-industries/codex-acp@0.12.0 through OpenClaw's isolated CODEX_HOME wrapper`
214
+ - `claude -> bundled @agentclientprotocol/claude-agent-acp@0.32.0`
215
+ - `codex -> bundled @zed-industries/codex-acp@0.13.0 through OpenClaw's isolated CODEX_HOME wrapper`
216
216
  - `copilot -> copilot --acp --stdio`
217
217
  - `cursor -> cursor-agent acp`
218
218
  - `droid -> droid exec --output-format acp`