@openclaw/acpx 2026.5.22 → 2026.5.24-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,7 +1,68 @@
1
- import { getAcpRuntimeBackend, unregisterAcpRuntimeBackend } from "openclaw/plugin-sdk/acp-runtime-backend";
1
+ import { getAcpRuntimeBackend, registerAcpRuntimeBackend, unregisterAcpRuntimeBackend } from "openclaw/plugin-sdk/acp-runtime-backend";
2
2
  //#region extensions/acpx/register.runtime.ts
3
3
  const ACPX_BACKEND_ID = "acpx";
4
4
  let serviceModulePromise = null;
5
+ function createDeferredResult() {
6
+ let resolve;
7
+ let reject;
8
+ return {
9
+ promise: new Promise((resolvePromise, rejectPromise) => {
10
+ resolve = resolvePromise;
11
+ reject = rejectPromise;
12
+ }),
13
+ resolve,
14
+ reject
15
+ };
16
+ }
17
+ var LegacyRunTurnEventQueue = class {
18
+ constructor() {
19
+ this.items = [];
20
+ this.waits = [];
21
+ this.closed = false;
22
+ }
23
+ push(item) {
24
+ if (this.closed) return;
25
+ const waiter = this.waits.shift();
26
+ if (waiter) {
27
+ waiter.resolve(item);
28
+ return;
29
+ }
30
+ this.items.push(item);
31
+ }
32
+ clear() {
33
+ this.items.length = 0;
34
+ }
35
+ close() {
36
+ if (this.closed) return;
37
+ this.closed = true;
38
+ for (const waiter of this.waits.splice(0)) waiter.resolve(null);
39
+ }
40
+ fail(error) {
41
+ if (this.closed) return;
42
+ this.error = error;
43
+ this.closed = true;
44
+ for (const waiter of this.waits.splice(0)) waiter.reject(error);
45
+ }
46
+ async next() {
47
+ const item = this.items.shift();
48
+ if (item) return item;
49
+ if (this.error) throw this.error;
50
+ if (this.closed) return null;
51
+ return await new Promise((resolve, reject) => {
52
+ this.waits.push({
53
+ resolve,
54
+ reject
55
+ });
56
+ });
57
+ }
58
+ async *iterate() {
59
+ for (;;) {
60
+ const item = await this.next();
61
+ if (!item) return;
62
+ yield item;
63
+ }
64
+ }
65
+ };
5
66
  function loadServiceModule() {
6
67
  serviceModulePromise ??= import("./service-CwnfaUP9.js");
7
68
  return serviceModulePromise;
@@ -19,7 +80,137 @@ async function startRealService(state) {
19
80
  state.realRuntime = backend.runtime;
20
81
  return state.realRuntime;
21
82
  })();
22
- return await state.startPromise;
83
+ try {
84
+ return await state.startPromise;
85
+ } catch (error) {
86
+ state.startPromise = null;
87
+ state.realService = null;
88
+ throw error;
89
+ }
90
+ }
91
+ function lazyStartTurn(resolveRuntime, input) {
92
+ const turnPromise = resolveRuntime().then((runtime) => {
93
+ if (runtime.startTurn) return runtime.startTurn(input);
94
+ return legacyRunTurnAsStartTurn(runtime, input);
95
+ });
96
+ return {
97
+ requestId: input.requestId,
98
+ events: { async *[Symbol.asyncIterator]() {
99
+ yield* (await turnPromise).events;
100
+ } },
101
+ result: turnPromise.then((turn) => turn.result),
102
+ cancel(inputArgs) {
103
+ return turnPromise.then((turn) => turn.cancel(inputArgs));
104
+ },
105
+ closeStream(inputArgs) {
106
+ return turnPromise.then((turn) => turn.closeStream(inputArgs));
107
+ }
108
+ };
109
+ }
110
+ function legacyRunTurnAsStartTurn(runtime, input) {
111
+ const result = createDeferredResult();
112
+ result.promise.catch(() => {});
113
+ const queue = new LegacyRunTurnEventQueue();
114
+ let resultSettled = false;
115
+ const settleResult = (next) => {
116
+ if (resultSettled) return;
117
+ resultSettled = true;
118
+ result.resolve(next);
119
+ };
120
+ (async () => {
121
+ try {
122
+ for await (const event of runtime.runTurn(input)) {
123
+ if (event.type === "done") {
124
+ settleResult({
125
+ status: "completed",
126
+ ...event.stopReason ? { stopReason: event.stopReason } : {}
127
+ });
128
+ continue;
129
+ }
130
+ if (event.type === "error") {
131
+ settleResult({
132
+ status: "failed",
133
+ error: {
134
+ message: event.message,
135
+ ...event.code ? { code: event.code } : {},
136
+ ...event.detailCode ? { detailCode: event.detailCode } : {},
137
+ ...event.retryable === void 0 ? {} : { retryable: event.retryable }
138
+ }
139
+ });
140
+ continue;
141
+ }
142
+ queue.push(event);
143
+ }
144
+ settleResult({
145
+ status: "failed",
146
+ error: {
147
+ code: "ACP_TURN_FAILED",
148
+ message: "ACP turn ended without a terminal done event."
149
+ }
150
+ });
151
+ } catch (error) {
152
+ result.reject(error);
153
+ queue.fail(error);
154
+ return;
155
+ }
156
+ queue.close();
157
+ })();
158
+ return {
159
+ requestId: input.requestId,
160
+ events: queue.iterate(),
161
+ result: result.promise,
162
+ async cancel(inputArgs) {
163
+ await runtime.cancel({
164
+ handle: input.handle,
165
+ reason: inputArgs?.reason
166
+ });
167
+ },
168
+ async closeStream() {
169
+ queue.clear();
170
+ queue.close();
171
+ }
172
+ };
173
+ }
174
+ function createDeferredRuntime(state) {
175
+ const resolveRuntime = () => startRealService(state);
176
+ return {
177
+ async ensureSession(input) {
178
+ return await (await resolveRuntime()).ensureSession(input);
179
+ },
180
+ startTurn(input) {
181
+ return lazyStartTurn(resolveRuntime, input);
182
+ },
183
+ async *runTurn(input) {
184
+ yield* (await resolveRuntime()).runTurn(input);
185
+ },
186
+ async getCapabilities(input) {
187
+ return await (await resolveRuntime()).getCapabilities?.(input) ?? { controls: [] };
188
+ },
189
+ async getStatus(input) {
190
+ return await (await resolveRuntime()).getStatus?.(input) ?? {};
191
+ },
192
+ async setMode(input) {
193
+ await (await resolveRuntime()).setMode?.(input);
194
+ },
195
+ async setConfigOption(input) {
196
+ await (await resolveRuntime()).setConfigOption?.(input);
197
+ },
198
+ async doctor() {
199
+ return await (await resolveRuntime()).doctor?.() ?? {
200
+ ok: true,
201
+ message: "ok"
202
+ };
203
+ },
204
+ async prepareFreshSession(input) {
205
+ await (await resolveRuntime()).prepareFreshSession?.(input);
206
+ },
207
+ async cancel(input) {
208
+ await (await resolveRuntime()).cancel(input);
209
+ },
210
+ async close(input) {
211
+ await (await resolveRuntime()).close(input);
212
+ }
213
+ };
23
214
  }
24
215
  function createAcpxRuntimeService(params = {}) {
25
216
  const state = {
@@ -37,7 +228,11 @@ function createAcpxRuntimeService(params = {}) {
37
228
  return;
38
229
  }
39
230
  state.ctx = ctx;
40
- await startRealService(state);
231
+ registerAcpRuntimeBackend({
232
+ id: ACPX_BACKEND_ID,
233
+ runtime: createDeferredRuntime(state)
234
+ });
235
+ ctx.logger.info("embedded acpx runtime backend registered lazily");
41
236
  },
42
237
  async stop(ctx) {
43
238
  if (state.realService) await state.realService.stop?.(ctx);
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@openclaw/acpx",
3
- "version": "2026.5.22",
3
+ "version": "2026.5.24-beta.2",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/acpx",
9
- "version": "2026.5.22",
9
+ "version": "2026.5.24-beta.2",
10
10
  "dependencies": {
11
11
  "@agentclientprotocol/claude-agent-acp": "0.36.1",
12
12
  "@zed-industries/codex-acp": "0.14.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/acpx",
3
- "version": "2026.5.22",
3
+ "version": "2026.5.24-beta.2",
4
4
  "description": "OpenClaw ACP runtime backend",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,10 +26,10 @@
26
26
  "minHostVersion": ">=2026.4.25"
27
27
  },
28
28
  "compat": {
29
- "pluginApi": ">=2026.5.22"
29
+ "pluginApi": ">=2026.5.24-beta.2"
30
30
  },
31
31
  "build": {
32
- "openclawVersion": "2026.5.22",
32
+ "openclawVersion": "2026.5.24-beta.2",
33
33
  "staticAssets": [
34
34
  {
35
35
  "source": "./src/runtime-internals/mcp-proxy.mjs",
@@ -61,7 +61,7 @@
61
61
  "skills/**"
62
62
  ],
63
63
  "peerDependencies": {
64
- "openclaw": ">=2026.5.22"
64
+ "openclaw": ">=2026.5.24-beta.2"
65
65
  },
66
66
  "peerDependenciesMeta": {
67
67
  "openclaw": {