@openclaw/acpx 2026.11.3 → 2026.11.5-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.
- package/dist/.setup/{config-D0ATuiVJ.mjs → config-DZaY96RI.mjs} +15 -23
- package/dist/.setup/{harness-attempt-lu4_bMfd.mjs → harness-attempt-CR7gvC_C.mjs} +5 -4
- package/dist/.setup/{pi-session-catalog-runtime-BAM1pEMw.mjs → pi-session-catalog-runtime-hFy095NF.mjs} +35 -57
- package/dist/.setup/{pi-session-paths-CIvyk6KB.mjs → pi-session-paths-Cn5bsvi0.mjs} +2 -2
- package/dist/.setup/{service-D_e2JAUG.mjs → service-By25n8eI.mjs} +135 -373
- package/dist/.setup/{session-owner-migration-BA3DJKb2.mjs → session-owner-migration-BmfOUj9h.mjs} +3 -3
- package/dist/.setup/{session-resource-DKJsUJPu.mjs → session-resource-BI93OF1C.mjs} +2 -2
- package/dist/.source-module-urls/9369b1b274d2ba70ea21d859abb3415ad8d63d0a1022a301763b953a5798469e.json +1 -0
- package/dist/doctor-contract-api.js +17 -11
- package/dist/index.js +207 -21
- package/openclaw.plugin.json +28 -1
- package/package.json +9 -9
- package/dist/.setup/register.runtime-D685iYx-.mjs +0 -197
- package/dist/register.runtime.js +0 -2
package/dist/.setup/{session-owner-migration-BA3DJKb2.mjs → session-owner-migration-BmfOUj9h.mjs}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as runtime_doctor_migrations_exports } from "./runtime-doctor-migrations-hxP-CXX7.mjs";
|
|
2
|
-
import { c as renderAgentCommand, t as resolveAcpxPluginConfig, u as splitCommandParts } from "./config-
|
|
2
|
+
import { c as renderAgentCommand, t as resolveAcpxPluginConfig, u as splitCommandParts } from "./config-DZaY96RI.mjs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { asFiniteNumber, asOptionalObjectRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
@@ -230,7 +230,7 @@ async function legacyRecords(input, directory = sessionDirectory(input)) {
|
|
|
230
230
|
directory,
|
|
231
231
|
ids
|
|
232
232
|
};
|
|
233
|
-
const { resolveAcpxSessionResource } = await import("./session-resource-
|
|
233
|
+
const { resolveAcpxSessionResource } = await import("./session-resource-BI93OF1C.mjs").then((n) => n.n);
|
|
234
234
|
const evidence = await input.context.inspectAcpSessionClaims?.();
|
|
235
235
|
const { decodeAcpxRuntimeHandleState } = await import("acpx/runtime");
|
|
236
236
|
return {
|
|
@@ -273,7 +273,7 @@ async function migrateRecord(input, directory, oldId, claims, changes, warnings)
|
|
|
273
273
|
const raw = (0, runtime_doctor_migrations_exports.asObjectRecord)(JSON.parse((0, runtime_doctor_migrations_exports.decodeUtf8Input)(sourceBytes, `ACP record ${sourcePath}`)));
|
|
274
274
|
if (!raw || raw.acpx_record_id !== oldId || typeof raw.name !== "string" || !raw.name.trim() || raw.name !== oldId && !oldId.startsWith(`${raw.name}:oneshot:`)) throw new Error("record ID/name is not a recognized ACPX locator");
|
|
275
275
|
requireStoppedPid(raw.pid);
|
|
276
|
-
const { resolveAcpxSessionResource } = await import("./session-resource-
|
|
276
|
+
const { resolveAcpxSessionResource } = await import("./session-resource-BI93OF1C.mjs").then((n) => n.n);
|
|
277
277
|
const { createFileSessionStore, decodeAcpxRuntimeHandleState, encodeAcpxRuntimeHandleState } = await import("acpx/runtime");
|
|
278
278
|
const candidates = claims.filter((claim) => matchesClaimRecord(claim, raw, oldId, resolveAcpxSessionResource(claim), decodeAcpxRuntimeHandleState));
|
|
279
279
|
if (candidates.length !== 1) throw new Error("exactly one current owner claim is required");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as __exportAll } from "./runtime-doctor-migrations-hxP-CXX7.mjs";
|
|
2
2
|
import { AcpRuntimeError } from "../runtime-api.js";
|
|
3
|
-
import {
|
|
3
|
+
import { sha256Hex } from "openclaw/plugin-sdk/node-crypto-runtime";
|
|
4
4
|
import { normalizeAgentId, parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
|
|
5
5
|
//#region extensions/acpx/src/session-resource.ts
|
|
6
6
|
var session_resource_exports = /* @__PURE__ */ __exportAll({ resolveAcpxSessionResource: () => resolveAcpxSessionResource });
|
|
@@ -11,7 +11,7 @@ function resolveAcpxSessionResource(target) {
|
|
|
11
11
|
const agentId = target.agentId?.trim() ? normalizeAgentId(target.agentId) : encodedOwner;
|
|
12
12
|
if (!sessionKey || encodedOwner && agentId !== encodedOwner || !encodedOwner && !agentId) throw new AcpRuntimeError("ACP_SESSION_INIT_FAILED", "ACP session owner is missing or disagrees with its logical key. Pass the OpenClaw agentId that owns this session.", { detailCode: "SESSION_OWNER_UNSUPPORTED" });
|
|
13
13
|
if (encodedOwner) return sessionKey;
|
|
14
|
-
return `openclaw-owner-v1-${
|
|
14
|
+
return `openclaw-owner-v1-${sha256Hex(JSON.stringify([agentId, sessionKey]))}`;
|
|
15
15
|
}
|
|
16
16
|
//#endregion
|
|
17
17
|
export { session_resource_exports as n, resolveAcpxSessionResource as t };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"entries":[{"output":"doctor-contract-api.js","source":"extensions/acpx/doctor-contract-api.ts"},{"output":"index.js","source":"extensions/acpx/index.ts"},{"output":"runtime-api.js","source":"extensions/acpx/runtime-api.ts"},{"output":"setup-api.js","source":"extensions/acpx/setup-api.ts"}],"chunks":[{"output":".setup/config-DZaY96RI.mjs","sha256":"625fd5fe477dc20fbbc1575bd943359c360285d90e66f28f35637a094c6a554b","facadeSource":null,"sources":["extensions/acpx/src/codex-adapter.ts","extensions/acpx/src/command-line.ts","extensions/acpx/src/config-schema.ts","extensions/acpx/src/config.ts"]},{"output":".setup/harness-attempt-CR7gvC_C.mjs","sha256":"25d8bb8a268da63e16b5f97c09d3e79ea591d84cbf5fe60f5c90a7482aca31b8","facadeSource":"extensions/acpx/src/harness-attempt.ts","sources":["extensions/acpx/src/harness-attempt.ts"]},{"output":".setup/pi-session-catalog-runtime-hFy095NF.mjs","sha256":"053d9f772cbb8ceebbf14c2f34975da0bb9cb718a7381c0a97d306ef790152e9","facadeSource":"extensions/acpx/src/pi-session-catalog-runtime.ts","sources":["extensions/acpx/src/pi-session-catalog-runtime.ts","extensions/acpx/src/pi-session-catalog.ts","extensions/acpx/src/pi-session-store.ts","extensions/acpx/src/pi-session-upstream-activity.ts"]},{"output":".setup/pi-session-paths-Cn5bsvi0.mjs","sha256":"08a8154298de4f15b938f1a2658e89c0cb4523781ae16ff14eb8e6314d343173","facadeSource":null,"sources":["extensions/acpx/src/pi-session-catalog-shared.ts","extensions/acpx/src/pi-session-paths.ts"]},{"output":".setup/runtime-doctor-migrations-hxP-CXX7.mjs","sha256":"5e20ed323f11ae0bd7d3a940409f89b15f676828463579f8ea705f5153368d1f","facadeSource":null,"sources":["packages/normalization-core/src/record-coerce.ts","src/config/channel-config-normalization.ts","src/plugin-sdk/legacy-webhook-listener-migration.ts"]},{"output":".setup/service-By25n8eI.mjs","sha256":"e89a981a4ca99e013f81b82982d6bfc1273d5483ff2cdbcc322618dffde2ba18","facadeSource":"extensions/acpx/src/service.ts","sources":["extensions/acpx/src/adapter-wrapper-script.ts","extensions/acpx/src/codex-auth-bridge.ts","extensions/acpx/src/codex-trust-config.ts","extensions/acpx/src/model-ref.ts","extensions/acpx/src/process-reaper.ts","extensions/acpx/src/runtime-generations.ts","extensions/acpx/src/runtime-probe.ts","extensions/acpx/src/runtime-process-cleanup.ts","extensions/acpx/src/runtime-session-store.ts","extensions/acpx/src/runtime.ts","extensions/acpx/src/service.ts","extensions/acpx/src/session-owner.ts"]},{"output":".setup/session-owner-migration-BmfOUj9h.mjs","sha256":"776a69a9374ae1fc991fe4338a3974a979f4abe7628fb95979f62983c01be73d","facadeSource":"extensions/acpx/src/session-owner-migration.ts","sources":["extensions/acpx/src/process-lease.ts","extensions/acpx/src/session-owner-migration.ts","extensions/acpx/src/state.ts"]},{"output":".setup/session-resource-BI93OF1C.mjs","sha256":"d0778cae638d2d0301b339f02487c17e85bd610b74e7ed16727dd8369c3cb789","facadeSource":null,"sources":["extensions/acpx/src/session-resource.ts"]},{"output":"doctor-contract-api.js","sha256":"c860218ced54e76883f4f3a71e6d24a1fa3bc6b5927a605755f66626a7a57bb4","facadeSource":"extensions/acpx/doctor-contract-api.ts","sources":["extensions/acpx/doctor-contract-api.ts"]},{"output":"index.js","sha256":"ec8d13ac6177d11fb9fe90e6964887ef4a4de5ec4de1d518f8da1d49d595b948","facadeSource":"extensions/acpx/index.ts","sources":["extensions/acpx/index.ts","extensions/acpx/src/harness.ts","extensions/acpx/src/native-agents.ts","extensions/acpx/src/pi-session-catalog-plugin.ts","extensions/acpx/src/runtime-proxy.ts"]},{"output":"runtime-api.js","sha256":"fc9734d9dfabafe7281fca6ede1415215a44ac03bd0aa798fce919d11ae68605","facadeSource":"extensions/acpx/runtime-api.ts","sources":[]},{"output":"setup-api.js","sha256":"325620704c2d29397d30e6df9e239a8390e0372a3e6ab4c9c2b29182173a6af8","facadeSource":"extensions/acpx/setup-api.ts","sources":["extensions/acpx/setup-api.ts"]}],"unrenderedSources":["extensions/acpx/runtime-api.ts"]}
|
|
@@ -21,16 +21,22 @@ function normalizeCompatibilityConfig({ cfg }) {
|
|
|
21
21
|
config: cfg,
|
|
22
22
|
changes: []
|
|
23
23
|
};
|
|
24
|
-
const
|
|
25
|
-
const nextEntry = (0, runtime_doctor_migrations_exports.asObjectRecord)(nextConfig.plugins?.entries?.acpx);
|
|
26
|
-
const nextPluginConfig = (0, runtime_doctor_migrations_exports.asObjectRecord)(nextEntry?.config);
|
|
27
|
-
if (!nextPluginConfig) return {
|
|
28
|
-
config: cfg,
|
|
29
|
-
changes: []
|
|
30
|
-
};
|
|
24
|
+
const nextPluginConfig = { ...pluginConfig };
|
|
31
25
|
for (const key of retiredKeys) delete nextPluginConfig[key];
|
|
32
26
|
return {
|
|
33
|
-
config:
|
|
27
|
+
config: {
|
|
28
|
+
...cfg,
|
|
29
|
+
plugins: {
|
|
30
|
+
...cfg.plugins,
|
|
31
|
+
entries: {
|
|
32
|
+
...cfg.plugins?.entries,
|
|
33
|
+
acpx: {
|
|
34
|
+
...entry,
|
|
35
|
+
config: nextPluginConfig
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
34
40
|
changes: [`Removed retired ACPX plugin config: ${retiredKeys.map((key) => [...ACPX_CONFIG_PATH, key].join(".")).join(", ")}.`]
|
|
35
41
|
};
|
|
36
42
|
}
|
|
@@ -40,13 +46,13 @@ const stateMigrations = [{
|
|
|
40
46
|
doctorOnly: true,
|
|
41
47
|
phase: "after-session-repair",
|
|
42
48
|
async collectBackupResources(input) {
|
|
43
|
-
return (await import("./.setup/session-owner-migration-
|
|
49
|
+
return (await import("./.setup/session-owner-migration-BmfOUj9h.mjs")).acpxSessionOwnerMigration.collectBackupResources(input);
|
|
44
50
|
},
|
|
45
51
|
async detectLegacyState(input) {
|
|
46
|
-
return (await import("./.setup/session-owner-migration-
|
|
52
|
+
return (await import("./.setup/session-owner-migration-BmfOUj9h.mjs")).acpxSessionOwnerMigration.detectLegacyState(input);
|
|
47
53
|
},
|
|
48
54
|
async migrateLegacyState(input) {
|
|
49
|
-
return (await import("./.setup/session-owner-migration-
|
|
55
|
+
return (await import("./.setup/session-owner-migration-BmfOUj9h.mjs")).acpxSessionOwnerMigration.migrateLegacyState(input);
|
|
50
56
|
}
|
|
51
57
|
}];
|
|
52
58
|
//#endregion
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import {
|
|
3
|
-
import { a as PI_SESSIONS_CAPABILITY, c as PI_SESSION_READ_COMMAND, l as PI_TERMINAL_RESUME_COMMAND, o as PI_SESSIONS_LIST_COMMAND, r as piSessionStoreAvailable, s as PI_SESSION_ID_PATTERN } from "./.setup/pi-session-paths-CIvyk6KB.mjs";
|
|
1
|
+
import { g as AcpxNativeAgentsSchema, h as ACPX_NATIVE_AGENT_IDS, t as resolveAcpxPluginConfig } from "./.setup/config-DZaY96RI.mjs";
|
|
2
|
+
import { a as PI_SESSIONS_CAPABILITY, c as PI_SESSION_READ_COMMAND, l as PI_TERMINAL_RESUME_COMMAND, o as PI_SESSIONS_LIST_COMMAND, r as piSessionStoreAvailable, s as PI_SESSION_ID_PATTERN } from "./.setup/pi-session-paths-Cn5bsvi0.mjs";
|
|
4
3
|
import { createAgentRegistry } from "acpx/agent-registry";
|
|
5
|
-
import { tryDispatchAcpReplyHook } from "openclaw/plugin-sdk/acp-runtime-backend";
|
|
6
|
-
import { createLazyRuntimeModule, createLazyRuntimeSurface } from "openclaw/plugin-sdk/lazy-runtime";
|
|
4
|
+
import { getAcpRuntimeBackend, registerAcpRuntimeBackend, requireAcpRuntimeBackend, tryDispatchAcpReplyHook, unregisterAcpRuntimeBackend } from "openclaw/plugin-sdk/acp-runtime-backend";
|
|
5
|
+
import { createLazyRuntimeMethodBinder, createLazyRuntimeModule, createLazyRuntimeSurface } from "openclaw/plugin-sdk/lazy-runtime";
|
|
7
6
|
import { finiteSecondsToTimerSafeMilliseconds } from "openclaw/plugin-sdk/number-runtime";
|
|
8
7
|
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
9
8
|
import { resolveNodeHostExecutable } from "openclaw/plugin-sdk/node-host";
|
|
@@ -169,6 +168,8 @@ function createAcpAgentHarness(params) {
|
|
|
169
168
|
agentCommand: inspection.launch.argv,
|
|
170
169
|
cwd: input.workspaceDir ?? config.cwd,
|
|
171
170
|
signal: generation.signal,
|
|
171
|
+
agentProcessEnvAllow: config.agentProcessEnvAllow,
|
|
172
|
+
agentProcessEnvBlock: config.agentProcessEnvBlock,
|
|
172
173
|
timeoutMs: config.timeoutSeconds === void 0 ? void 0 : finiteSecondsToTimerSafeMilliseconds(config.timeoutSeconds) ?? 1
|
|
173
174
|
});
|
|
174
175
|
generation.signal.throwIfAborted();
|
|
@@ -204,7 +205,7 @@ function createAcpAgentHarness(params) {
|
|
|
204
205
|
if (inspection?.launch.kind !== "installed") throw new Error(`${params.label} is not installed; refresh the model catalog`);
|
|
205
206
|
const runtime = await runtimeFor(input.workspaceDir);
|
|
206
207
|
generation.signal.throwIfAborted();
|
|
207
|
-
const { runAcpHarnessAttempt } = await import("./.setup/harness-attempt-
|
|
208
|
+
const { runAcpHarnessAttempt } = await import("./.setup/harness-attempt-CR7gvC_C.mjs");
|
|
208
209
|
return await runAcpHarnessAttempt({
|
|
209
210
|
input,
|
|
210
211
|
runtime,
|
|
@@ -246,7 +247,7 @@ function createAcpAgentHarness(params) {
|
|
|
246
247
|
}
|
|
247
248
|
//#endregion
|
|
248
249
|
//#region extensions/acpx/src/pi-session-catalog-plugin.ts
|
|
249
|
-
const loadPiSessionCatalogModule = createLazyRuntimeModule(() => import("./.setup/pi-session-catalog-runtime-
|
|
250
|
+
const loadPiSessionCatalogModule = createLazyRuntimeModule(() => import("./.setup/pi-session-catalog-runtime-hFy095NF.mjs"));
|
|
250
251
|
function fullConfigCatalogEnabled(config) {
|
|
251
252
|
if (!isRecord(config) || !isRecord(config.plugins) || !isRecord(config.plugins.entries)) return true;
|
|
252
253
|
const entry = config.plugins.entries.acpx;
|
|
@@ -309,22 +310,211 @@ function registerPiSessionCatalog(api) {
|
|
|
309
310
|
for (const policy of nodeHost.policies) api.registerNodeInvokePolicy(policy);
|
|
310
311
|
}
|
|
311
312
|
//#endregion
|
|
313
|
+
//#region extensions/acpx/src/runtime-proxy.ts
|
|
314
|
+
/** Start an ACP turn through a lazy runtime resolver without awaiting resolution up front. */
|
|
315
|
+
function lazyStartRuntimeTurn(resolveRuntime, input) {
|
|
316
|
+
const turnPromise = resolveRuntime().then((runtime) => runtime.startTurn(input));
|
|
317
|
+
return {
|
|
318
|
+
requestId: input.requestId,
|
|
319
|
+
get promptStarted() {
|
|
320
|
+
return turnPromise.then((turn) => turn.promptStarted);
|
|
321
|
+
},
|
|
322
|
+
events: { async *[Symbol.asyncIterator]() {
|
|
323
|
+
yield* (await turnPromise).events;
|
|
324
|
+
} },
|
|
325
|
+
result: turnPromise.then((turn) => turn.result),
|
|
326
|
+
cancel(inputArgs) {
|
|
327
|
+
return turnPromise.then((turn) => turn.cancel(inputArgs));
|
|
328
|
+
},
|
|
329
|
+
closeStream(inputArgs) {
|
|
330
|
+
return turnPromise.then((turn) => turn.closeStream(inputArgs));
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
/** Create an ACP runtime facade backed by an async runtime resolver. */
|
|
335
|
+
function createLazyAcpRuntimeProxy(resolveRuntime) {
|
|
336
|
+
const bind = createLazyRuntimeMethodBinder(resolveRuntime);
|
|
337
|
+
return {
|
|
338
|
+
ownerAwareSessions: 1,
|
|
339
|
+
findSession: bind((runtime) => runtime.findSession.bind(runtime)),
|
|
340
|
+
shutdown: bind((runtime) => runtime.shutdown.bind(runtime)),
|
|
341
|
+
ensureSession: bind((runtime) => runtime.ensureSession.bind(runtime)),
|
|
342
|
+
startTurn(input) {
|
|
343
|
+
return lazyStartRuntimeTurn(resolveRuntime, input);
|
|
344
|
+
},
|
|
345
|
+
async *runTurn(input) {
|
|
346
|
+
yield* (await resolveRuntime()).runTurn(input);
|
|
347
|
+
},
|
|
348
|
+
getCapabilities: bind((runtime) => runtime.getCapabilities.bind(runtime)),
|
|
349
|
+
getStatus: bind((runtime) => runtime.getStatus.bind(runtime)),
|
|
350
|
+
setMode: bind((runtime) => runtime.setMode.bind(runtime)),
|
|
351
|
+
setModel: bind((runtime) => runtime.setModel.bind(runtime)),
|
|
352
|
+
setConfigOption: bind((runtime) => runtime.setConfigOption.bind(runtime)),
|
|
353
|
+
doctor: bind((runtime) => runtime.doctor.bind(runtime)),
|
|
354
|
+
prepareFreshSession: bind((runtime) => runtime.prepareFreshSession.bind(runtime)),
|
|
355
|
+
cancel: bind((runtime) => runtime.cancel.bind(runtime)),
|
|
356
|
+
close: bind((runtime) => runtime.close.bind(runtime))
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
//#endregion
|
|
312
360
|
//#region extensions/acpx/index.ts
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
361
|
+
const ACPX_BACKEND_ID = "acpx";
|
|
362
|
+
const loadServiceModule = createLazyRuntimeModule(() => import("./.setup/service-By25n8eI.mjs"));
|
|
363
|
+
function unregisterOwnedRuntime(runtime) {
|
|
364
|
+
if (runtime && getAcpRuntimeBackend(ACPX_BACKEND_ID)?.runtime === runtime) unregisterAcpRuntimeBackend(ACPX_BACKEND_ID);
|
|
365
|
+
}
|
|
317
366
|
const plugin = {
|
|
318
367
|
id: "acpx",
|
|
319
368
|
name: "ACPX Runtime",
|
|
320
369
|
description: "Embedded ACP runtime backend with plugin-owned session and transport management.",
|
|
321
370
|
register(api) {
|
|
322
371
|
registerPiSessionCatalog(api);
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
372
|
+
const pluginConfig = api.pluginConfig;
|
|
373
|
+
let ctx = null;
|
|
374
|
+
let published = false;
|
|
375
|
+
let lifecycleRevision = 0;
|
|
376
|
+
let ownedRuntime = null;
|
|
377
|
+
let realService = null;
|
|
378
|
+
let startPromise = null;
|
|
379
|
+
let stopPromise = null;
|
|
380
|
+
async function startRealService(expectedRevision, deferredRuntime, purpose = "gateway", probeAtStartup = purpose === "gateway") {
|
|
381
|
+
if (lifecycleRevision !== expectedRevision || !ctx) throw new Error("ACPX runtime service is not started");
|
|
382
|
+
if (startPromise) return await startPromise;
|
|
383
|
+
const activeContext = ctx;
|
|
384
|
+
let starting = true;
|
|
385
|
+
startPromise = (async () => {
|
|
386
|
+
let publishedRuntime = null;
|
|
387
|
+
const { createAcpxRuntimeService: createAcpxRuntimeServiceLocal } = await loadServiceModule();
|
|
388
|
+
const activeService = createAcpxRuntimeServiceLocal({
|
|
389
|
+
pluginConfig,
|
|
390
|
+
getAllowedAgents: () => api.runtime.config.current().acp?.allowedAgents,
|
|
391
|
+
openKeyedStore: (options) => api.runtime.state.openKeyedStoreV2(options),
|
|
392
|
+
probeAtStartup,
|
|
393
|
+
startupPurpose: purpose,
|
|
394
|
+
assertCurrent: () => {
|
|
395
|
+
if (lifecycleRevision !== expectedRevision || ctx !== activeContext || published && getAcpRuntimeBackend(ACPX_BACKEND_ID)?.runtime !== ownedRuntime) throw new Error("ACPX runtime service lost recovery ownership");
|
|
396
|
+
},
|
|
397
|
+
backendLifecycle: {
|
|
398
|
+
publish(backend) {
|
|
399
|
+
if (lifecycleRevision !== expectedRevision || ctx !== activeContext) throw new Error("ACPX runtime service stopped during activation");
|
|
400
|
+
if (published && getAcpRuntimeBackend(ACPX_BACKEND_ID)?.runtime !== deferredRuntime) throw new Error("ACPX runtime service lost registry ownership during activation");
|
|
401
|
+
if (published) {
|
|
402
|
+
const { healthy } = backend;
|
|
403
|
+
registerAcpRuntimeBackend({
|
|
404
|
+
id: ACPX_BACKEND_ID,
|
|
405
|
+
...backend,
|
|
406
|
+
runtime: deferredRuntime,
|
|
407
|
+
...healthy ? { healthy: () => starting || healthy() } : {}
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
publishedRuntime = backend.runtime;
|
|
411
|
+
},
|
|
412
|
+
retract() {}
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
realService = activeService;
|
|
416
|
+
await activeService.start(activeContext);
|
|
417
|
+
if (lifecycleRevision !== expectedRevision || ctx !== activeContext) throw new Error("ACPX runtime service stopped during activation");
|
|
418
|
+
if (!publishedRuntime) throw new Error("ACPX runtime service did not register an ACP backend");
|
|
419
|
+
if (published && getAcpRuntimeBackend(ACPX_BACKEND_ID)?.runtime !== deferredRuntime) throw new Error("ACPX runtime service lost registry ownership during activation");
|
|
420
|
+
return publishedRuntime;
|
|
421
|
+
})().finally(() => {
|
|
422
|
+
starting = false;
|
|
423
|
+
});
|
|
424
|
+
try {
|
|
425
|
+
return await startPromise;
|
|
426
|
+
} catch (error) {
|
|
427
|
+
if (lifecycleRevision === expectedRevision) {
|
|
428
|
+
startPromise = null;
|
|
429
|
+
realService = null;
|
|
430
|
+
}
|
|
431
|
+
throw error;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
function createDeferredRuntime(expectedRevision) {
|
|
435
|
+
const deferredRuntime = {
|
|
436
|
+
...createLazyAcpRuntimeProxy(() => startRealService(expectedRevision, deferredRuntime)),
|
|
437
|
+
async ensureSession(input) {
|
|
438
|
+
const runtime = await startRealService(expectedRevision, deferredRuntime);
|
|
439
|
+
requireAcpRuntimeBackend(ACPX_BACKEND_ID);
|
|
440
|
+
return await runtime.ensureSession(input);
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
return deferredRuntime;
|
|
444
|
+
}
|
|
445
|
+
const service = {
|
|
446
|
+
id: "acpx-runtime",
|
|
447
|
+
async getRuntime(serviceContext) {
|
|
448
|
+
if (stopPromise) await stopPromise;
|
|
449
|
+
if (!ctx) {
|
|
450
|
+
ctx = serviceContext;
|
|
451
|
+
lifecycleRevision += 1;
|
|
452
|
+
ownedRuntime = createDeferredRuntime(lifecycleRevision);
|
|
453
|
+
}
|
|
454
|
+
if (!ownedRuntime) throw new Error("ACPX runtime service lost its runtime owner");
|
|
455
|
+
return await startRealService(lifecycleRevision, ownedRuntime, published ? "gateway" : "inspection", false);
|
|
456
|
+
},
|
|
457
|
+
async start(serviceContext) {
|
|
458
|
+
if (process.env.OPENCLAW_SKIP_ACPX_RUNTIME === "1") {
|
|
459
|
+
serviceContext.logger.info("skipping embedded acpx runtime backend (OPENCLAW_SKIP_ACPX_RUNTIME=1)");
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
if (stopPromise) await stopPromise;
|
|
463
|
+
if (ctx && ownedRuntime) {
|
|
464
|
+
const revision = lifecycleRevision;
|
|
465
|
+
const previous = getAcpRuntimeBackend(ACPX_BACKEND_ID)?.runtime;
|
|
466
|
+
const assertCurrent = () => {
|
|
467
|
+
const current = getAcpRuntimeBackend(ACPX_BACKEND_ID)?.runtime;
|
|
468
|
+
if (lifecycleRevision !== revision || !ctx || current !== previous && current !== ownedRuntime) throw new Error("ACPX runtime service lost promotion ownership");
|
|
469
|
+
};
|
|
470
|
+
await startPromise;
|
|
471
|
+
assertCurrent();
|
|
472
|
+
await realService?.promote(serviceContext, assertCurrent);
|
|
473
|
+
assertCurrent();
|
|
474
|
+
published = true;
|
|
475
|
+
registerAcpRuntimeBackend({
|
|
476
|
+
id: ACPX_BACKEND_ID,
|
|
477
|
+
runtime: ownedRuntime
|
|
478
|
+
});
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
published = true;
|
|
482
|
+
lifecycleRevision += 1;
|
|
483
|
+
ctx = serviceContext;
|
|
484
|
+
const deferredRuntime = createDeferredRuntime(lifecycleRevision);
|
|
485
|
+
ownedRuntime = deferredRuntime;
|
|
486
|
+
registerAcpRuntimeBackend({
|
|
487
|
+
id: ACPX_BACKEND_ID,
|
|
488
|
+
runtime: deferredRuntime
|
|
489
|
+
});
|
|
490
|
+
serviceContext.logger.info("embedded acpx runtime backend registered lazily");
|
|
491
|
+
},
|
|
492
|
+
async stop(serviceContext) {
|
|
493
|
+
if (stopPromise) return await stopPromise;
|
|
494
|
+
lifecycleRevision += 1;
|
|
495
|
+
ctx = null;
|
|
496
|
+
published = false;
|
|
497
|
+
const stoppingRuntime = ownedRuntime;
|
|
498
|
+
unregisterOwnedRuntime(stoppingRuntime);
|
|
499
|
+
const startingPromise = startPromise;
|
|
500
|
+
stopPromise = (async () => {
|
|
501
|
+
await startingPromise?.catch(() => void 0);
|
|
502
|
+
try {
|
|
503
|
+
await realService?.stop?.(serviceContext);
|
|
504
|
+
} finally {
|
|
505
|
+
unregisterOwnedRuntime(stoppingRuntime);
|
|
506
|
+
ownedRuntime = null;
|
|
507
|
+
realService = null;
|
|
508
|
+
startPromise = null;
|
|
509
|
+
}
|
|
510
|
+
})();
|
|
511
|
+
try {
|
|
512
|
+
await stopPromise;
|
|
513
|
+
} finally {
|
|
514
|
+
stopPromise = null;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
};
|
|
328
518
|
api.registerService(service);
|
|
329
519
|
const currentConfig = () => api.runtime.config.current().plugins?.entries?.acpx?.config;
|
|
330
520
|
const registry = createAgentRegistry();
|
|
@@ -337,11 +527,7 @@ const plugin = {
|
|
|
337
527
|
isEnabled: () => isAcpxNativeAgentEnabled(currentConfig()?.nativeAgents, agentId),
|
|
338
528
|
api,
|
|
339
529
|
getRuntime: service.getRuntime,
|
|
340
|
-
shutdown: () => service.stop?.(
|
|
341
|
-
config: api.config,
|
|
342
|
-
stateDir: api.runtime.state.resolveStateDir(),
|
|
343
|
-
logger: api.logger
|
|
344
|
-
})
|
|
530
|
+
shutdown: () => stopPromise ?? (ctx ? service.stop?.(ctx) : void 0)
|
|
345
531
|
}));
|
|
346
532
|
return {
|
|
347
533
|
id: agentId,
|
package/openclaw.plugin.json
CHANGED
|
@@ -36,7 +36,16 @@
|
|
|
36
36
|
"id": "agent-runtime",
|
|
37
37
|
"title": "Agent runtime",
|
|
38
38
|
"order": 10,
|
|
39
|
-
"properties": [
|
|
39
|
+
"properties": [
|
|
40
|
+
"cwd",
|
|
41
|
+
"stateDir",
|
|
42
|
+
"probeAgent",
|
|
43
|
+
"agents",
|
|
44
|
+
"timeoutSeconds",
|
|
45
|
+
"nativeAgents",
|
|
46
|
+
"agentProcessEnvAllow",
|
|
47
|
+
"agentProcessEnvBlock"
|
|
48
|
+
]
|
|
40
49
|
},
|
|
41
50
|
{
|
|
42
51
|
"id": "permissions",
|
|
@@ -92,6 +101,14 @@
|
|
|
92
101
|
"minimum": 0.001,
|
|
93
102
|
"default": 120
|
|
94
103
|
},
|
|
104
|
+
"agentProcessEnvAllow": {
|
|
105
|
+
"type": "array",
|
|
106
|
+
"items": { "type": "string", "pattern": "^[^=\\s]+$" }
|
|
107
|
+
},
|
|
108
|
+
"agentProcessEnvBlock": {
|
|
109
|
+
"type": "array",
|
|
110
|
+
"items": { "type": "string", "pattern": "^[^=\\s]+$" }
|
|
111
|
+
},
|
|
95
112
|
"piSessionCatalog": {
|
|
96
113
|
"type": "object",
|
|
97
114
|
"additionalProperties": false,
|
|
@@ -189,6 +206,16 @@
|
|
|
189
206
|
"help": "Timeout for embedded ACP runtime startup and control operations. ACP turns use OpenClaw agent/run timeouts.",
|
|
190
207
|
"advanced": true
|
|
191
208
|
},
|
|
209
|
+
"agentProcessEnvAllow": {
|
|
210
|
+
"label": "Agent Environment Allowlist",
|
|
211
|
+
"help": "Default unset (agents inherit the Gateway environment). When set, ACP agents, their command probes, and terminals inherit only process essentials (PATH, HOME, locale, temp, XDG_*), these names, and ACPX_AUTH_* grants.",
|
|
212
|
+
"advanced": true
|
|
213
|
+
},
|
|
214
|
+
"agentProcessEnvBlock": {
|
|
215
|
+
"label": "Agent Environment Blocklist",
|
|
216
|
+
"help": "Default unset. Gateway environment variable names that ACP agents, their command probes, and terminals do not inherit, for example OPENCLAW_GATEWAY_TOKEN. Applied after the allowlist; explicit grants such as ACPX_AUTH_* still apply.",
|
|
217
|
+
"advanced": true
|
|
218
|
+
},
|
|
192
219
|
"piSessionCatalog.enabled": {
|
|
193
220
|
"label": "Pi Session Catalog",
|
|
194
221
|
"help": "Auto-detect Pi sessions on the Gateway and paired nodes, then show them in the sessions sidebar."
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/acpx",
|
|
3
|
-
"version": "2026.11.
|
|
3
|
+
"version": "2026.11.5-beta.2",
|
|
4
4
|
"description": "OpenClaw ACP runtime backend with plugin-owned session and transport management.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
"type": "module",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@agentclientprotocol/claude-agent-acp": "0.95.0",
|
|
12
|
-
"@agentclientprotocol/codex-acp": "2.
|
|
13
|
-
"@openclaw/fs-safe": "0.26.
|
|
14
|
-
"acpx": "0.
|
|
15
|
-
"smol-toml": "1.9.
|
|
16
|
-
"zod": "4.6.
|
|
12
|
+
"@agentclientprotocol/codex-acp": "2.2.2",
|
|
13
|
+
"@openclaw/fs-safe": "0.26.13",
|
|
14
|
+
"acpx": "0.21.0",
|
|
15
|
+
"smol-toml": "1.9.1",
|
|
16
|
+
"zod": "4.6.7"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@openclaw/plugin-sdk": "workspace:*"
|
|
@@ -45,10 +45,10 @@
|
|
|
45
45
|
]
|
|
46
46
|
},
|
|
47
47
|
"compat": {
|
|
48
|
-
"pluginApi": ">=2026.11.
|
|
48
|
+
"pluginApi": ">=2026.11.5-beta.2"
|
|
49
49
|
},
|
|
50
50
|
"build": {
|
|
51
|
-
"openclawVersion": "2026.11.
|
|
51
|
+
"openclawVersion": "2026.11.5-beta.2"
|
|
52
52
|
},
|
|
53
53
|
"release": {
|
|
54
54
|
"publishToClawHub": true,
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"skills/**"
|
|
69
69
|
],
|
|
70
70
|
"peerDependencies": {
|
|
71
|
-
"openclaw": ">=2026.11.
|
|
71
|
+
"openclaw": ">=2026.11.5-beta.2"
|
|
72
72
|
},
|
|
73
73
|
"peerDependenciesMeta": {
|
|
74
74
|
"openclaw": {
|