@openclaw/acpx 2026.5.2-beta.2 → 2026.5.3-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/index.js +14 -0
- package/dist/register.runtime.js +108 -0
- package/dist/runtime-B3LWev_t.js +357 -0
- package/dist/runtime-api.js +4 -0
- package/dist/service-YhcC786_.js +665 -0
- package/dist/setup-api.js +16 -0
- package/package.json +33 -3
- package/AGENTS.md +0 -54
- package/index.test.ts +0 -119
- package/index.ts +0 -19
- package/register.runtime.ts +0 -154
- package/runtime-api.ts +0 -46
- package/setup-api.ts +0 -18
- package/src/acpx-runtime-compat.d.ts +0 -62
- package/src/claude-agent-acp-completion.test.ts +0 -129
- package/src/codex-auth-bridge.test.ts +0 -448
- package/src/codex-auth-bridge.ts +0 -385
- package/src/config-schema.ts +0 -117
- package/src/config.test.ts +0 -144
- package/src/config.ts +0 -273
- package/src/manifest.test.ts +0 -20
- package/src/runtime-internals/mcp-command-line.test.ts +0 -59
- package/src/runtime-internals/mcp-proxy.test.ts +0 -114
- package/src/runtime.test.ts +0 -816
- package/src/runtime.ts +0 -613
- package/src/service.test.ts +0 -401
- package/src/service.ts +0 -278
- package/tsconfig.json +0 -16
- /package/{src/runtime-internals → dist}/error-format.mjs +0 -0
- /package/{src/runtime-internals → dist}/mcp-command-line.mjs +0 -0
- /package/{src/runtime-internals → dist}/mcp-proxy.mjs +0 -0
package/src/runtime.test.ts
DELETED
|
@@ -1,816 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { AcpRuntimeError, type AcpRuntime } from "../runtime-api.js";
|
|
3
|
-
import { AcpxRuntime, __testing } from "./runtime.js";
|
|
4
|
-
|
|
5
|
-
type TestSessionStore = {
|
|
6
|
-
load(sessionId: string): Promise<Record<string, unknown> | undefined>;
|
|
7
|
-
save(record: Record<string, unknown>): Promise<void>;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
const DOCUMENTED_OPENCLAW_BRIDGE_COMMAND =
|
|
11
|
-
"env OPENCLAW_HIDE_BANNER=1 OPENCLAW_SUPPRESS_NOTES=1 openclaw acp --url ws://127.0.0.1:18789 --token-file ~/.openclaw/gateway.token --session agent:main:main";
|
|
12
|
-
const CODEX_ACP_COMMAND = "npx @zed-industries/codex-acp@^0.12.0";
|
|
13
|
-
const CODEX_ACP_WRAPPER_COMMAND = `node "/tmp/openclaw/acpx/codex-acp-wrapper.mjs"`;
|
|
14
|
-
|
|
15
|
-
function makeRuntime(
|
|
16
|
-
baseStore: TestSessionStore,
|
|
17
|
-
options: Partial<ConstructorParameters<typeof AcpxRuntime>[0]> = {},
|
|
18
|
-
): {
|
|
19
|
-
runtime: AcpxRuntime;
|
|
20
|
-
wrappedStore: TestSessionStore & { markFresh: (sessionKey: string) => void };
|
|
21
|
-
delegate: {
|
|
22
|
-
close: AcpRuntime["close"];
|
|
23
|
-
ensureSession: AcpRuntime["ensureSession"];
|
|
24
|
-
getStatus: NonNullable<AcpRuntime["getStatus"]>;
|
|
25
|
-
setConfigOption: NonNullable<AcpRuntime["setConfigOption"]>;
|
|
26
|
-
isHealthy(): boolean;
|
|
27
|
-
probeAvailability(): Promise<void>;
|
|
28
|
-
};
|
|
29
|
-
bridgeSafeDelegate: {
|
|
30
|
-
close: AcpRuntime["close"];
|
|
31
|
-
ensureSession: AcpRuntime["ensureSession"];
|
|
32
|
-
getStatus: NonNullable<AcpRuntime["getStatus"]>;
|
|
33
|
-
setConfigOption: NonNullable<AcpRuntime["setConfigOption"]>;
|
|
34
|
-
isHealthy(): boolean;
|
|
35
|
-
probeAvailability(): Promise<void>;
|
|
36
|
-
};
|
|
37
|
-
} {
|
|
38
|
-
const runtime = new AcpxRuntime({
|
|
39
|
-
cwd: "/tmp",
|
|
40
|
-
sessionStore: baseStore,
|
|
41
|
-
agentRegistry: {
|
|
42
|
-
resolve: (agentName: string) => (agentName === "openclaw" ? "openclaw acp" : agentName),
|
|
43
|
-
list: () => ["codex", "openclaw"],
|
|
44
|
-
},
|
|
45
|
-
permissionMode: "approve-reads",
|
|
46
|
-
...options,
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
runtime,
|
|
51
|
-
wrappedStore: (
|
|
52
|
-
runtime as unknown as {
|
|
53
|
-
sessionStore: TestSessionStore & { markFresh: (sessionKey: string) => void };
|
|
54
|
-
}
|
|
55
|
-
).sessionStore,
|
|
56
|
-
delegate: (
|
|
57
|
-
runtime as unknown as {
|
|
58
|
-
delegate: {
|
|
59
|
-
close: AcpRuntime["close"];
|
|
60
|
-
ensureSession: AcpRuntime["ensureSession"];
|
|
61
|
-
getStatus: NonNullable<AcpRuntime["getStatus"]>;
|
|
62
|
-
setConfigOption: NonNullable<AcpRuntime["setConfigOption"]>;
|
|
63
|
-
isHealthy(): boolean;
|
|
64
|
-
probeAvailability(): Promise<void>;
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
).delegate,
|
|
68
|
-
bridgeSafeDelegate: (
|
|
69
|
-
runtime as unknown as {
|
|
70
|
-
bridgeSafeDelegate: {
|
|
71
|
-
close: AcpRuntime["close"];
|
|
72
|
-
ensureSession: AcpRuntime["ensureSession"];
|
|
73
|
-
getStatus: NonNullable<AcpRuntime["getStatus"]>;
|
|
74
|
-
setConfigOption: NonNullable<AcpRuntime["setConfigOption"]>;
|
|
75
|
-
isHealthy(): boolean;
|
|
76
|
-
probeAvailability(): Promise<void>;
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
).bridgeSafeDelegate,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
describe("AcpxRuntime fresh reset wrapper", () => {
|
|
84
|
-
beforeEach(() => {
|
|
85
|
-
vi.restoreAllMocks();
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it("rejects unsupported runtime session modes with a clear AcpRuntimeError (issue #73071)", async () => {
|
|
89
|
-
const baseStore: TestSessionStore = {
|
|
90
|
-
load: vi.fn(async () => undefined),
|
|
91
|
-
save: vi.fn(async () => {}),
|
|
92
|
-
};
|
|
93
|
-
const { runtime, delegate } = makeRuntime(baseStore);
|
|
94
|
-
const ensureSpy = vi.spyOn(delegate, "ensureSession").mockResolvedValue({
|
|
95
|
-
sessionKey: "agent:claude:acp:test",
|
|
96
|
-
backend: "acpx",
|
|
97
|
-
runtimeSessionName: "claude",
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
for (const badMode of ["run", "session", "", undefined, null, 0]) {
|
|
101
|
-
await expect(
|
|
102
|
-
runtime.ensureSession({
|
|
103
|
-
sessionKey: "agent:claude:acp:test",
|
|
104
|
-
agent: "claude",
|
|
105
|
-
mode: badMode as never,
|
|
106
|
-
}),
|
|
107
|
-
).rejects.toMatchObject({
|
|
108
|
-
name: "AcpRuntimeError",
|
|
109
|
-
code: "ACP_INVALID_RUNTIME_OPTION",
|
|
110
|
-
message: expect.stringContaining("Unsupported ACP runtime session mode"),
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
expect(ensureSpy).not.toHaveBeenCalled();
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it("exposes assertSupportedRuntimeSessionMode as a typed guard", () => {
|
|
118
|
-
expect(() => __testing.assertSupportedRuntimeSessionMode("persistent")).not.toThrow();
|
|
119
|
-
expect(() => __testing.assertSupportedRuntimeSessionMode("oneshot")).not.toThrow();
|
|
120
|
-
expect(() => __testing.assertSupportedRuntimeSessionMode("run" as never)).toThrow(
|
|
121
|
-
AcpRuntimeError,
|
|
122
|
-
);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it("normalizes OpenClaw Codex model ids for ACP startup", async () => {
|
|
126
|
-
const baseStore: TestSessionStore = {
|
|
127
|
-
load: vi.fn(async () => undefined),
|
|
128
|
-
save: vi.fn(async () => {}),
|
|
129
|
-
};
|
|
130
|
-
const { runtime, delegate } = makeRuntime(baseStore, {
|
|
131
|
-
agentRegistry: {
|
|
132
|
-
resolve: (agentName: string) => (agentName === "codex" ? CODEX_ACP_COMMAND : agentName),
|
|
133
|
-
list: () => ["codex", "openclaw"],
|
|
134
|
-
},
|
|
135
|
-
});
|
|
136
|
-
const ensure = vi.spyOn(delegate, "ensureSession").mockResolvedValue({
|
|
137
|
-
sessionKey: "agent:codex:acp:test",
|
|
138
|
-
backend: "acpx",
|
|
139
|
-
runtimeSessionName: "codex",
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
await runtime.ensureSession({
|
|
143
|
-
sessionKey: "agent:codex:acp:test",
|
|
144
|
-
agent: "codex",
|
|
145
|
-
mode: "persistent",
|
|
146
|
-
model: "openai-codex/gpt-5.4",
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
expect(ensure).toHaveBeenCalledWith(
|
|
150
|
-
expect.objectContaining({
|
|
151
|
-
model: "gpt-5.4",
|
|
152
|
-
}),
|
|
153
|
-
);
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it("leaves Codex ACP startup defaults alone when no model or thinking is provided", async () => {
|
|
157
|
-
const baseStore: TestSessionStore = {
|
|
158
|
-
load: vi.fn(async () => undefined),
|
|
159
|
-
save: vi.fn(async () => {}),
|
|
160
|
-
};
|
|
161
|
-
const { runtime, delegate } = makeRuntime(baseStore, {
|
|
162
|
-
agentRegistry: {
|
|
163
|
-
resolve: (agentName: string) => (agentName === "codex" ? CODEX_ACP_COMMAND : agentName),
|
|
164
|
-
list: () => ["codex", "openclaw"],
|
|
165
|
-
},
|
|
166
|
-
});
|
|
167
|
-
const ensure = vi.spyOn(delegate, "ensureSession").mockResolvedValue({
|
|
168
|
-
sessionKey: "agent:codex:acp:test",
|
|
169
|
-
backend: "acpx",
|
|
170
|
-
runtimeSessionName: "codex",
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
await runtime.ensureSession({
|
|
174
|
-
sessionKey: "agent:codex:acp:test",
|
|
175
|
-
agent: "codex",
|
|
176
|
-
mode: "persistent",
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
expect(ensure).toHaveBeenCalledWith(
|
|
180
|
-
expect.objectContaining({
|
|
181
|
-
agent: "codex",
|
|
182
|
-
}),
|
|
183
|
-
);
|
|
184
|
-
expect(ensure.mock.calls[0]?.[0]).not.toHaveProperty("model");
|
|
185
|
-
expect(ensure.mock.calls[0]?.[0]).not.toHaveProperty("thinking");
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
it("does not normalize model startup for non-Codex ACP agents", async () => {
|
|
189
|
-
const baseStore: TestSessionStore = {
|
|
190
|
-
load: vi.fn(async () => undefined),
|
|
191
|
-
save: vi.fn(async () => {}),
|
|
192
|
-
};
|
|
193
|
-
const { runtime, delegate } = makeRuntime(baseStore, {
|
|
194
|
-
agentRegistry: {
|
|
195
|
-
resolve: (agentName: string) => (agentName === "main" ? CODEX_ACP_COMMAND : agentName),
|
|
196
|
-
list: () => ["main", "codex", "openclaw"],
|
|
197
|
-
},
|
|
198
|
-
});
|
|
199
|
-
const ensure = vi.spyOn(delegate, "ensureSession").mockResolvedValue({
|
|
200
|
-
sessionKey: "agent:main:acp:test",
|
|
201
|
-
backend: "acpx",
|
|
202
|
-
runtimeSessionName: "main",
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
await runtime.ensureSession({
|
|
206
|
-
sessionKey: "agent:main:acp:test",
|
|
207
|
-
agent: "main",
|
|
208
|
-
mode: "persistent",
|
|
209
|
-
model: "openai-codex/gpt-5.5",
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
expect(ensure).toHaveBeenCalledWith(
|
|
213
|
-
expect.objectContaining({
|
|
214
|
-
agent: "main",
|
|
215
|
-
model: "openai-codex/gpt-5.5",
|
|
216
|
-
}),
|
|
217
|
-
);
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
it("injects Codex ACP startup config into the scoped registry", () => {
|
|
221
|
-
expect(__testing.isCodexAcpCommand(CODEX_ACP_COMMAND)).toBe(true);
|
|
222
|
-
expect(__testing.isCodexAcpCommand(CODEX_ACP_WRAPPER_COMMAND)).toBe(true);
|
|
223
|
-
expect(
|
|
224
|
-
__testing.appendCodexAcpConfigOverrides(CODEX_ACP_COMMAND, {
|
|
225
|
-
model: "gpt-5.4",
|
|
226
|
-
reasoningEffort: "medium",
|
|
227
|
-
}),
|
|
228
|
-
).toBe(
|
|
229
|
-
"npx @zed-industries/codex-acp@^0.12.0 -c model=gpt-5.4 -c model_reasoning_effort=medium",
|
|
230
|
-
);
|
|
231
|
-
expect(__testing.isCodexAcpCommand("openclaw acp")).toBe(false);
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
it("passes gpt-5.5 Codex ACP startup through instead of blocking it", async () => {
|
|
235
|
-
const baseStore: TestSessionStore = {
|
|
236
|
-
load: vi.fn(async () => undefined),
|
|
237
|
-
save: vi.fn(async () => {}),
|
|
238
|
-
};
|
|
239
|
-
const { runtime, delegate } = makeRuntime(baseStore, {
|
|
240
|
-
agentRegistry: {
|
|
241
|
-
resolve: (agentName: string) => (agentName === "codex" ? CODEX_ACP_COMMAND : agentName),
|
|
242
|
-
list: () => ["codex", "openclaw"],
|
|
243
|
-
},
|
|
244
|
-
});
|
|
245
|
-
const ensure = vi.spyOn(delegate, "ensureSession").mockResolvedValue({
|
|
246
|
-
sessionKey: "agent:codex:acp:test",
|
|
247
|
-
backend: "acpx",
|
|
248
|
-
runtimeSessionName: "codex",
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
await runtime.ensureSession({
|
|
252
|
-
sessionKey: "agent:codex:acp:test",
|
|
253
|
-
agent: "codex",
|
|
254
|
-
mode: "persistent",
|
|
255
|
-
model: "openai-codex/gpt-5.5",
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
expect(ensure).toHaveBeenCalledWith(
|
|
259
|
-
expect.objectContaining({
|
|
260
|
-
model: "gpt-5.5",
|
|
261
|
-
}),
|
|
262
|
-
);
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
it("maps explicit Codex ACP thinking to startup reasoning effort", async () => {
|
|
266
|
-
const baseStore: TestSessionStore = {
|
|
267
|
-
load: vi.fn(async () => undefined),
|
|
268
|
-
save: vi.fn(async () => {}),
|
|
269
|
-
};
|
|
270
|
-
const { runtime, delegate } = makeRuntime(baseStore, {
|
|
271
|
-
agentRegistry: {
|
|
272
|
-
resolve: (agentName: string) => (agentName === "codex" ? CODEX_ACP_COMMAND : agentName),
|
|
273
|
-
list: () => ["codex", "openclaw"],
|
|
274
|
-
},
|
|
275
|
-
});
|
|
276
|
-
const ensure = vi.spyOn(delegate, "ensureSession").mockResolvedValue({
|
|
277
|
-
sessionKey: "agent:codex:acp:test",
|
|
278
|
-
backend: "acpx",
|
|
279
|
-
runtimeSessionName: "codex",
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
await runtime.ensureSession({
|
|
283
|
-
sessionKey: "agent:codex:acp:test",
|
|
284
|
-
agent: "codex",
|
|
285
|
-
mode: "persistent",
|
|
286
|
-
model: "openai-codex/gpt-5.4",
|
|
287
|
-
thinking: "x-high",
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
expect(ensure).toHaveBeenCalledWith(
|
|
291
|
-
expect.objectContaining({
|
|
292
|
-
model: "gpt-5.4/xhigh",
|
|
293
|
-
}),
|
|
294
|
-
);
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
it("normalizes Codex ACP model config controls to adapter ids", async () => {
|
|
298
|
-
const baseStore: TestSessionStore = {
|
|
299
|
-
load: vi.fn(async () => ({
|
|
300
|
-
acpxRecordId: "agent:codex:acp:test",
|
|
301
|
-
agentCommand: CODEX_ACP_COMMAND,
|
|
302
|
-
})),
|
|
303
|
-
save: vi.fn(async () => {}),
|
|
304
|
-
};
|
|
305
|
-
const { runtime, delegate } = makeRuntime(baseStore);
|
|
306
|
-
const setConfigOption = vi.spyOn(delegate, "setConfigOption").mockResolvedValue(undefined);
|
|
307
|
-
const handle: Parameters<NonNullable<AcpRuntime["setConfigOption"]>>[0]["handle"] = {
|
|
308
|
-
sessionKey: "agent:codex:acp:test",
|
|
309
|
-
backend: "acpx",
|
|
310
|
-
runtimeSessionName: "agent:codex:acp:test",
|
|
311
|
-
acpxRecordId: "agent:codex:acp:test",
|
|
312
|
-
};
|
|
313
|
-
|
|
314
|
-
await runtime.setConfigOption({
|
|
315
|
-
handle,
|
|
316
|
-
key: "model",
|
|
317
|
-
value: "openai-codex/gpt-5.4",
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
expect(setConfigOption).toHaveBeenNthCalledWith(1, {
|
|
321
|
-
handle,
|
|
322
|
-
key: "model",
|
|
323
|
-
value: "gpt-5.4",
|
|
324
|
-
});
|
|
325
|
-
expect(setConfigOption).toHaveBeenCalledOnce();
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
it("normalizes Codex ACP slash reasoning suffixes to config controls", async () => {
|
|
329
|
-
const baseStore: TestSessionStore = {
|
|
330
|
-
load: vi.fn(async () => ({
|
|
331
|
-
acpxRecordId: "agent:codex:acp:test",
|
|
332
|
-
agentCommand: CODEX_ACP_COMMAND,
|
|
333
|
-
})),
|
|
334
|
-
save: vi.fn(async () => {}),
|
|
335
|
-
};
|
|
336
|
-
const { runtime, delegate } = makeRuntime(baseStore);
|
|
337
|
-
const setConfigOption = vi.spyOn(delegate, "setConfigOption").mockResolvedValue(undefined);
|
|
338
|
-
const handle: Parameters<NonNullable<AcpRuntime["setConfigOption"]>>[0]["handle"] = {
|
|
339
|
-
sessionKey: "agent:codex:acp:test",
|
|
340
|
-
backend: "acpx",
|
|
341
|
-
runtimeSessionName: "agent:codex:acp:test",
|
|
342
|
-
acpxRecordId: "agent:codex:acp:test",
|
|
343
|
-
};
|
|
344
|
-
|
|
345
|
-
await runtime.setConfigOption({
|
|
346
|
-
handle,
|
|
347
|
-
key: "model",
|
|
348
|
-
value: "openai-codex/gpt-5.4/high",
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
expect(setConfigOption).toHaveBeenNthCalledWith(1, {
|
|
352
|
-
handle,
|
|
353
|
-
key: "model",
|
|
354
|
-
value: "gpt-5.4",
|
|
355
|
-
});
|
|
356
|
-
expect(setConfigOption).toHaveBeenNthCalledWith(2, {
|
|
357
|
-
handle,
|
|
358
|
-
key: "reasoning_effort",
|
|
359
|
-
value: "high",
|
|
360
|
-
});
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
it("normalizes Codex ACP thinking config controls to reasoning effort", async () => {
|
|
364
|
-
const baseStore: TestSessionStore = {
|
|
365
|
-
load: vi.fn(async () => ({
|
|
366
|
-
acpxRecordId: "agent:codex:acp:test",
|
|
367
|
-
agentCommand: CODEX_ACP_COMMAND,
|
|
368
|
-
})),
|
|
369
|
-
save: vi.fn(async () => {}),
|
|
370
|
-
};
|
|
371
|
-
const { runtime, delegate } = makeRuntime(baseStore);
|
|
372
|
-
const setConfigOption = vi.spyOn(delegate, "setConfigOption").mockResolvedValue(undefined);
|
|
373
|
-
const handle: Parameters<NonNullable<AcpRuntime["setConfigOption"]>>[0]["handle"] = {
|
|
374
|
-
sessionKey: "agent:codex:acp:test",
|
|
375
|
-
backend: "acpx",
|
|
376
|
-
runtimeSessionName: "agent:codex:acp:test",
|
|
377
|
-
acpxRecordId: "agent:codex:acp:test",
|
|
378
|
-
};
|
|
379
|
-
|
|
380
|
-
await runtime.setConfigOption({
|
|
381
|
-
handle,
|
|
382
|
-
key: "thinking",
|
|
383
|
-
value: "minimal",
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
expect(setConfigOption).toHaveBeenCalledWith({
|
|
387
|
-
handle,
|
|
388
|
-
key: "reasoning_effort",
|
|
389
|
-
value: "low",
|
|
390
|
-
});
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
it("ignores unsupported Codex ACP timeout config controls", async () => {
|
|
394
|
-
const baseStore: TestSessionStore = {
|
|
395
|
-
load: vi.fn(async () => ({
|
|
396
|
-
acpxRecordId: "agent:codex:acp:test",
|
|
397
|
-
agentCommand: CODEX_ACP_COMMAND,
|
|
398
|
-
})),
|
|
399
|
-
save: vi.fn(async () => {}),
|
|
400
|
-
};
|
|
401
|
-
const { runtime, delegate } = makeRuntime(baseStore);
|
|
402
|
-
const setConfigOption = vi.spyOn(delegate, "setConfigOption").mockResolvedValue(undefined);
|
|
403
|
-
const handle: Parameters<NonNullable<AcpRuntime["setConfigOption"]>>[0]["handle"] = {
|
|
404
|
-
sessionKey: "agent:codex:acp:test",
|
|
405
|
-
backend: "acpx",
|
|
406
|
-
runtimeSessionName: "agent:codex:acp:test",
|
|
407
|
-
acpxRecordId: "agent:codex:acp:test",
|
|
408
|
-
};
|
|
409
|
-
|
|
410
|
-
await runtime.setConfigOption({
|
|
411
|
-
handle,
|
|
412
|
-
key: "timeout",
|
|
413
|
-
value: "60000",
|
|
414
|
-
});
|
|
415
|
-
await runtime.setConfigOption({
|
|
416
|
-
handle,
|
|
417
|
-
key: "Timeout_Seconds",
|
|
418
|
-
value: "60",
|
|
419
|
-
});
|
|
420
|
-
|
|
421
|
-
expect(setConfigOption).not.toHaveBeenCalled();
|
|
422
|
-
});
|
|
423
|
-
|
|
424
|
-
it("forwards timeout config controls for non-Codex ACP agents", async () => {
|
|
425
|
-
const baseStore: TestSessionStore = {
|
|
426
|
-
load: vi.fn(async () => ({
|
|
427
|
-
acpxRecordId: "agent:claude:acp:test",
|
|
428
|
-
agentCommand: "npx @agentclientprotocol/claude-agent-acp",
|
|
429
|
-
})),
|
|
430
|
-
save: vi.fn(async () => {}),
|
|
431
|
-
};
|
|
432
|
-
const { runtime, delegate } = makeRuntime(baseStore);
|
|
433
|
-
const setConfigOption = vi.spyOn(delegate, "setConfigOption").mockResolvedValue(undefined);
|
|
434
|
-
const handle: Parameters<NonNullable<AcpRuntime["setConfigOption"]>>[0]["handle"] = {
|
|
435
|
-
sessionKey: "agent:claude:acp:test",
|
|
436
|
-
backend: "acpx",
|
|
437
|
-
runtimeSessionName: "agent:claude:acp:test",
|
|
438
|
-
acpxRecordId: "agent:claude:acp:test",
|
|
439
|
-
};
|
|
440
|
-
|
|
441
|
-
await runtime.setConfigOption({
|
|
442
|
-
handle,
|
|
443
|
-
key: "timeout",
|
|
444
|
-
value: "60",
|
|
445
|
-
});
|
|
446
|
-
|
|
447
|
-
expect(setConfigOption).toHaveBeenCalledOnce();
|
|
448
|
-
expect(setConfigOption).toHaveBeenCalledWith({
|
|
449
|
-
handle,
|
|
450
|
-
key: "timeout",
|
|
451
|
-
value: "60",
|
|
452
|
-
});
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
it("keeps stale persistent loads hidden until a fresh record is saved", async () => {
|
|
456
|
-
const baseStore: TestSessionStore = {
|
|
457
|
-
load: vi.fn(async () => ({ acpxRecordId: "stale" }) as never),
|
|
458
|
-
save: vi.fn(async () => {}),
|
|
459
|
-
};
|
|
460
|
-
|
|
461
|
-
const { runtime, wrappedStore } = makeRuntime(baseStore);
|
|
462
|
-
|
|
463
|
-
expect(await wrappedStore.load("agent:codex:acp:binding:test")).toEqual({
|
|
464
|
-
acpxRecordId: "stale",
|
|
465
|
-
});
|
|
466
|
-
expect(baseStore.load).toHaveBeenCalledTimes(1);
|
|
467
|
-
|
|
468
|
-
await runtime.prepareFreshSession({
|
|
469
|
-
sessionKey: "agent:codex:acp:binding:test",
|
|
470
|
-
});
|
|
471
|
-
|
|
472
|
-
expect(await wrappedStore.load("agent:codex:acp:binding:test")).toBeUndefined();
|
|
473
|
-
expect(baseStore.load).toHaveBeenCalledTimes(1);
|
|
474
|
-
expect(await wrappedStore.load("agent:codex:acp:binding:test")).toBeUndefined();
|
|
475
|
-
expect(baseStore.load).toHaveBeenCalledTimes(1);
|
|
476
|
-
|
|
477
|
-
await wrappedStore.save({
|
|
478
|
-
acpxRecordId: "fresh-record",
|
|
479
|
-
name: "agent:codex:acp:binding:test",
|
|
480
|
-
} as never);
|
|
481
|
-
|
|
482
|
-
expect(await wrappedStore.load("agent:codex:acp:binding:test")).toEqual({
|
|
483
|
-
acpxRecordId: "stale",
|
|
484
|
-
});
|
|
485
|
-
expect(baseStore.load).toHaveBeenCalledTimes(2);
|
|
486
|
-
});
|
|
487
|
-
|
|
488
|
-
it("marks the session fresh after discardPersistentState close", async () => {
|
|
489
|
-
const baseStore: TestSessionStore = {
|
|
490
|
-
load: vi.fn(async () => ({ acpxRecordId: "stale" }) as never),
|
|
491
|
-
save: vi.fn(async () => {}),
|
|
492
|
-
};
|
|
493
|
-
|
|
494
|
-
const { runtime, wrappedStore, delegate } = makeRuntime(baseStore);
|
|
495
|
-
const close = vi.spyOn(delegate, "close").mockResolvedValue(undefined);
|
|
496
|
-
|
|
497
|
-
await runtime.close({
|
|
498
|
-
handle: {
|
|
499
|
-
sessionKey: "agent:codex:acp:binding:test",
|
|
500
|
-
backend: "acpx",
|
|
501
|
-
runtimeSessionName: "agent:codex:acp:binding:test",
|
|
502
|
-
},
|
|
503
|
-
reason: "new-in-place-reset",
|
|
504
|
-
discardPersistentState: true,
|
|
505
|
-
});
|
|
506
|
-
|
|
507
|
-
expect(close).toHaveBeenCalledWith({
|
|
508
|
-
handle: {
|
|
509
|
-
sessionKey: "agent:codex:acp:binding:test",
|
|
510
|
-
backend: "acpx",
|
|
511
|
-
runtimeSessionName: "agent:codex:acp:binding:test",
|
|
512
|
-
},
|
|
513
|
-
reason: "new-in-place-reset",
|
|
514
|
-
discardPersistentState: true,
|
|
515
|
-
});
|
|
516
|
-
expect(await wrappedStore.load("agent:codex:acp:binding:test")).toBeUndefined();
|
|
517
|
-
expect(baseStore.load).toHaveBeenCalledOnce();
|
|
518
|
-
});
|
|
519
|
-
|
|
520
|
-
it("routes openclaw ensureSession through the bridge-safe delegate when MCP servers are configured", async () => {
|
|
521
|
-
const baseStore: TestSessionStore = {
|
|
522
|
-
load: vi.fn(async () => undefined),
|
|
523
|
-
save: vi.fn(async () => {}),
|
|
524
|
-
};
|
|
525
|
-
|
|
526
|
-
const { runtime, delegate, bridgeSafeDelegate } = makeRuntime(baseStore, {
|
|
527
|
-
mcpServers: [{ name: "tools", command: "mcp-tools" }] as never,
|
|
528
|
-
});
|
|
529
|
-
const defaultEnsure = vi.spyOn(delegate, "ensureSession").mockResolvedValue({
|
|
530
|
-
sessionKey: "agent:codex:acp:test",
|
|
531
|
-
backend: "acpx",
|
|
532
|
-
runtimeSessionName: "default",
|
|
533
|
-
});
|
|
534
|
-
const bridgeEnsure = vi.spyOn(bridgeSafeDelegate, "ensureSession").mockResolvedValue({
|
|
535
|
-
sessionKey: "agent:openclaw:acp:test",
|
|
536
|
-
backend: "acpx",
|
|
537
|
-
runtimeSessionName: "bridge",
|
|
538
|
-
});
|
|
539
|
-
|
|
540
|
-
const result = await runtime.ensureSession({
|
|
541
|
-
sessionKey: "agent:openclaw:acp:test",
|
|
542
|
-
agent: "openclaw",
|
|
543
|
-
mode: "persistent",
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
expect(result.runtimeSessionName).toBe("bridge");
|
|
547
|
-
expect(bridgeEnsure).toHaveBeenCalledOnce();
|
|
548
|
-
expect(defaultEnsure).not.toHaveBeenCalled();
|
|
549
|
-
});
|
|
550
|
-
|
|
551
|
-
it("routes non-openclaw sessions through the default delegate", async () => {
|
|
552
|
-
const baseStore: TestSessionStore = {
|
|
553
|
-
load: vi.fn(async () => undefined),
|
|
554
|
-
save: vi.fn(async () => {}),
|
|
555
|
-
};
|
|
556
|
-
|
|
557
|
-
const { runtime, delegate, bridgeSafeDelegate } = makeRuntime(baseStore, {
|
|
558
|
-
mcpServers: [{ name: "tools", command: "mcp-tools" }] as never,
|
|
559
|
-
});
|
|
560
|
-
const defaultEnsure = vi.spyOn(delegate, "ensureSession").mockResolvedValue({
|
|
561
|
-
sessionKey: "agent:codex:acp:test",
|
|
562
|
-
backend: "acpx",
|
|
563
|
-
runtimeSessionName: "default",
|
|
564
|
-
});
|
|
565
|
-
const bridgeEnsure = vi.spyOn(bridgeSafeDelegate, "ensureSession").mockResolvedValue({
|
|
566
|
-
sessionKey: "agent:openclaw:acp:test",
|
|
567
|
-
backend: "acpx",
|
|
568
|
-
runtimeSessionName: "bridge",
|
|
569
|
-
});
|
|
570
|
-
|
|
571
|
-
const result = await runtime.ensureSession({
|
|
572
|
-
sessionKey: "agent:codex:acp:test",
|
|
573
|
-
agent: "codex",
|
|
574
|
-
mode: "persistent",
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
expect(result.runtimeSessionName).toBe("default");
|
|
578
|
-
expect(defaultEnsure).toHaveBeenCalledOnce();
|
|
579
|
-
expect(bridgeEnsure).not.toHaveBeenCalled();
|
|
580
|
-
});
|
|
581
|
-
|
|
582
|
-
it("routes handle-based follow-up calls for openclaw sessions through the bridge-safe delegate", async () => {
|
|
583
|
-
const baseStore: TestSessionStore = {
|
|
584
|
-
load: vi.fn(async () => undefined),
|
|
585
|
-
save: vi.fn(async () => {}),
|
|
586
|
-
};
|
|
587
|
-
|
|
588
|
-
const { runtime, delegate, bridgeSafeDelegate } = makeRuntime(baseStore, {
|
|
589
|
-
mcpServers: [{ name: "tools", command: "mcp-tools" }] as never,
|
|
590
|
-
});
|
|
591
|
-
const defaultStatus = vi.spyOn(delegate, "getStatus").mockResolvedValue({
|
|
592
|
-
summary: "default",
|
|
593
|
-
});
|
|
594
|
-
const bridgeStatus = vi.spyOn(bridgeSafeDelegate, "getStatus").mockResolvedValue({
|
|
595
|
-
summary: "bridge",
|
|
596
|
-
});
|
|
597
|
-
const handle: Parameters<NonNullable<AcpRuntime["getStatus"]>>[0]["handle"] = {
|
|
598
|
-
sessionKey: "agent:openclaw:acp:test",
|
|
599
|
-
backend: "acpx",
|
|
600
|
-
runtimeSessionName: "openclaw-session-handle",
|
|
601
|
-
};
|
|
602
|
-
|
|
603
|
-
const status = await runtime.getStatus({ handle });
|
|
604
|
-
|
|
605
|
-
expect(status.summary).toBe("bridge");
|
|
606
|
-
expect(bridgeStatus).toHaveBeenCalledWith({ handle });
|
|
607
|
-
expect(defaultStatus).not.toHaveBeenCalled();
|
|
608
|
-
});
|
|
609
|
-
|
|
610
|
-
it("keeps MCP-enabled routing when the openclaw agent is overridden to a non-bridge adapter", async () => {
|
|
611
|
-
const baseStore: TestSessionStore = {
|
|
612
|
-
load: vi.fn(async () => undefined),
|
|
613
|
-
save: vi.fn(async () => {}),
|
|
614
|
-
};
|
|
615
|
-
|
|
616
|
-
const { runtime, delegate, bridgeSafeDelegate } = makeRuntime(baseStore, {
|
|
617
|
-
mcpServers: [{ name: "tools", command: "mcp-tools" }] as never,
|
|
618
|
-
agentRegistry: {
|
|
619
|
-
resolve: (agentName: string) => (agentName === "openclaw" ? "codex" : agentName),
|
|
620
|
-
list: () => ["codex", "openclaw"],
|
|
621
|
-
},
|
|
622
|
-
});
|
|
623
|
-
const defaultEnsure = vi.spyOn(delegate, "ensureSession").mockResolvedValue({
|
|
624
|
-
sessionKey: "agent:openclaw:acp:test",
|
|
625
|
-
backend: "acpx",
|
|
626
|
-
runtimeSessionName: "default",
|
|
627
|
-
});
|
|
628
|
-
const bridgeEnsure = vi.spyOn(bridgeSafeDelegate, "ensureSession").mockResolvedValue({
|
|
629
|
-
sessionKey: "agent:openclaw:acp:test",
|
|
630
|
-
backend: "acpx",
|
|
631
|
-
runtimeSessionName: "bridge",
|
|
632
|
-
});
|
|
633
|
-
|
|
634
|
-
const result = await runtime.ensureSession({
|
|
635
|
-
sessionKey: "agent:openclaw:acp:test",
|
|
636
|
-
agent: "openclaw",
|
|
637
|
-
mode: "persistent",
|
|
638
|
-
});
|
|
639
|
-
|
|
640
|
-
expect(result.runtimeSessionName).toBe("default");
|
|
641
|
-
expect(defaultEnsure).toHaveBeenCalledOnce();
|
|
642
|
-
expect(bridgeEnsure).not.toHaveBeenCalled();
|
|
643
|
-
});
|
|
644
|
-
|
|
645
|
-
it("uses the bridge-safe delegate for any agent mapped to the openclaw bridge command", async () => {
|
|
646
|
-
const baseStore: TestSessionStore = {
|
|
647
|
-
load: vi.fn(async () => undefined),
|
|
648
|
-
save: vi.fn(async () => {}),
|
|
649
|
-
};
|
|
650
|
-
|
|
651
|
-
const { runtime, delegate, bridgeSafeDelegate } = makeRuntime(baseStore, {
|
|
652
|
-
mcpServers: [{ name: "tools", command: "mcp-tools" }] as never,
|
|
653
|
-
agentRegistry: {
|
|
654
|
-
resolve: (agentName: string) => (agentName === "codex" ? "openclaw acp" : agentName),
|
|
655
|
-
list: () => ["codex", "openclaw"],
|
|
656
|
-
},
|
|
657
|
-
});
|
|
658
|
-
const defaultEnsure = vi.spyOn(delegate, "ensureSession").mockResolvedValue({
|
|
659
|
-
sessionKey: "agent:codex:acp:test",
|
|
660
|
-
backend: "acpx",
|
|
661
|
-
runtimeSessionName: "default",
|
|
662
|
-
});
|
|
663
|
-
const bridgeEnsure = vi.spyOn(bridgeSafeDelegate, "ensureSession").mockResolvedValue({
|
|
664
|
-
sessionKey: "agent:codex:acp:test",
|
|
665
|
-
backend: "acpx",
|
|
666
|
-
runtimeSessionName: "bridge",
|
|
667
|
-
});
|
|
668
|
-
|
|
669
|
-
const result = await runtime.ensureSession({
|
|
670
|
-
sessionKey: "agent:codex:acp:test",
|
|
671
|
-
agent: "codex",
|
|
672
|
-
mode: "persistent",
|
|
673
|
-
});
|
|
674
|
-
|
|
675
|
-
expect(result.runtimeSessionName).toBe("bridge");
|
|
676
|
-
expect(bridgeEnsure).toHaveBeenCalledOnce();
|
|
677
|
-
expect(defaultEnsure).not.toHaveBeenCalled();
|
|
678
|
-
});
|
|
679
|
-
|
|
680
|
-
it("uses the bridge-safe delegate for documented env-wrapped openclaw bridge commands", async () => {
|
|
681
|
-
const baseStore: TestSessionStore = {
|
|
682
|
-
load: vi.fn(async () => undefined),
|
|
683
|
-
save: vi.fn(async () => {}),
|
|
684
|
-
};
|
|
685
|
-
|
|
686
|
-
const { runtime, delegate, bridgeSafeDelegate } = makeRuntime(baseStore, {
|
|
687
|
-
mcpServers: [{ name: "tools", command: "mcp-tools" }] as never,
|
|
688
|
-
agentRegistry: {
|
|
689
|
-
resolve: (agentName: string) =>
|
|
690
|
-
agentName === "openclaw" ? DOCUMENTED_OPENCLAW_BRIDGE_COMMAND : agentName,
|
|
691
|
-
list: () => ["codex", "openclaw"],
|
|
692
|
-
},
|
|
693
|
-
});
|
|
694
|
-
const defaultEnsure = vi.spyOn(delegate, "ensureSession").mockResolvedValue({
|
|
695
|
-
sessionKey: "agent:openclaw:acp:test",
|
|
696
|
-
backend: "acpx",
|
|
697
|
-
runtimeSessionName: "default",
|
|
698
|
-
});
|
|
699
|
-
const bridgeEnsure = vi.spyOn(bridgeSafeDelegate, "ensureSession").mockResolvedValue({
|
|
700
|
-
sessionKey: "agent:openclaw:acp:test",
|
|
701
|
-
backend: "acpx",
|
|
702
|
-
runtimeSessionName: "bridge",
|
|
703
|
-
});
|
|
704
|
-
|
|
705
|
-
const result = await runtime.ensureSession({
|
|
706
|
-
sessionKey: "agent:openclaw:acp:test",
|
|
707
|
-
agent: "openclaw",
|
|
708
|
-
mode: "persistent",
|
|
709
|
-
});
|
|
710
|
-
|
|
711
|
-
expect(result.runtimeSessionName).toBe("bridge");
|
|
712
|
-
expect(bridgeEnsure).toHaveBeenCalledOnce();
|
|
713
|
-
expect(defaultEnsure).not.toHaveBeenCalled();
|
|
714
|
-
});
|
|
715
|
-
|
|
716
|
-
it("uses the bridge-safe delegate for local node openclaw entrypoints", async () => {
|
|
717
|
-
const baseStore: TestSessionStore = {
|
|
718
|
-
load: vi.fn(async () => undefined),
|
|
719
|
-
save: vi.fn(async () => {}),
|
|
720
|
-
};
|
|
721
|
-
|
|
722
|
-
const { runtime, delegate, bridgeSafeDelegate } = makeRuntime(baseStore, {
|
|
723
|
-
mcpServers: [{ name: "tools", command: "mcp-tools" }] as never,
|
|
724
|
-
agentRegistry: {
|
|
725
|
-
resolve: (agentName: string) =>
|
|
726
|
-
agentName === "openclaw" ? "env OPENCLAW_HIDE_BANNER=1 node openclaw.mjs acp" : agentName,
|
|
727
|
-
list: () => ["codex", "openclaw"],
|
|
728
|
-
},
|
|
729
|
-
});
|
|
730
|
-
const defaultEnsure = vi.spyOn(delegate, "ensureSession").mockResolvedValue({
|
|
731
|
-
sessionKey: "agent:openclaw:acp:test",
|
|
732
|
-
backend: "acpx",
|
|
733
|
-
runtimeSessionName: "default",
|
|
734
|
-
});
|
|
735
|
-
const bridgeEnsure = vi.spyOn(bridgeSafeDelegate, "ensureSession").mockResolvedValue({
|
|
736
|
-
sessionKey: "agent:openclaw:acp:test",
|
|
737
|
-
backend: "acpx",
|
|
738
|
-
runtimeSessionName: "bridge",
|
|
739
|
-
});
|
|
740
|
-
|
|
741
|
-
const result = await runtime.ensureSession({
|
|
742
|
-
sessionKey: "agent:openclaw:acp:test",
|
|
743
|
-
agent: "openclaw",
|
|
744
|
-
mode: "persistent",
|
|
745
|
-
});
|
|
746
|
-
|
|
747
|
-
expect(result.runtimeSessionName).toBe("bridge");
|
|
748
|
-
expect(bridgeEnsure).toHaveBeenCalledOnce();
|
|
749
|
-
expect(defaultEnsure).not.toHaveBeenCalled();
|
|
750
|
-
});
|
|
751
|
-
|
|
752
|
-
it("routes follow-up calls by persisted agent command before current config", async () => {
|
|
753
|
-
const baseStore: TestSessionStore = {
|
|
754
|
-
load: vi.fn(async () => ({
|
|
755
|
-
acpxRecordId: "agent:openclaw:acp:test",
|
|
756
|
-
agentCommand: DOCUMENTED_OPENCLAW_BRIDGE_COMMAND,
|
|
757
|
-
})),
|
|
758
|
-
save: vi.fn(async () => {}),
|
|
759
|
-
};
|
|
760
|
-
|
|
761
|
-
const { runtime, delegate, bridgeSafeDelegate } = makeRuntime(baseStore, {
|
|
762
|
-
mcpServers: [{ name: "tools", command: "mcp-tools" }] as never,
|
|
763
|
-
agentRegistry: {
|
|
764
|
-
resolve: (agentName: string) => (agentName === "openclaw" ? "codex" : agentName),
|
|
765
|
-
list: () => ["codex", "openclaw"],
|
|
766
|
-
},
|
|
767
|
-
});
|
|
768
|
-
const defaultStatus = vi.spyOn(delegate, "getStatus").mockResolvedValue({
|
|
769
|
-
summary: "default",
|
|
770
|
-
});
|
|
771
|
-
const bridgeStatus = vi.spyOn(bridgeSafeDelegate, "getStatus").mockResolvedValue({
|
|
772
|
-
summary: "bridge",
|
|
773
|
-
});
|
|
774
|
-
|
|
775
|
-
const status = await runtime.getStatus({
|
|
776
|
-
handle: {
|
|
777
|
-
sessionKey: "agent:openclaw:acp:test",
|
|
778
|
-
backend: "acpx",
|
|
779
|
-
runtimeSessionName: "agent:openclaw:acp:test",
|
|
780
|
-
},
|
|
781
|
-
});
|
|
782
|
-
|
|
783
|
-
expect(status.summary).toBe("bridge");
|
|
784
|
-
expect(bridgeStatus).toHaveBeenCalledOnce();
|
|
785
|
-
expect(defaultStatus).not.toHaveBeenCalled();
|
|
786
|
-
});
|
|
787
|
-
|
|
788
|
-
it("probes through the bridge-safe delegate when probeAgent resolves to openclaw bridge", async () => {
|
|
789
|
-
const baseStore: TestSessionStore = {
|
|
790
|
-
load: vi.fn(async () => undefined),
|
|
791
|
-
save: vi.fn(async () => {}),
|
|
792
|
-
};
|
|
793
|
-
|
|
794
|
-
const { runtime, delegate, bridgeSafeDelegate } = makeRuntime(baseStore, {
|
|
795
|
-
mcpServers: [{ name: "tools", command: "mcp-tools" }] as never,
|
|
796
|
-
probeAgent: "openclaw",
|
|
797
|
-
agentRegistry: {
|
|
798
|
-
resolve: (agentName: string) =>
|
|
799
|
-
agentName === "openclaw" ? DOCUMENTED_OPENCLAW_BRIDGE_COMMAND : agentName,
|
|
800
|
-
list: () => ["codex", "openclaw"],
|
|
801
|
-
},
|
|
802
|
-
});
|
|
803
|
-
const defaultProbe = vi.spyOn(delegate, "probeAvailability").mockResolvedValue(undefined);
|
|
804
|
-
const bridgeProbe = vi
|
|
805
|
-
.spyOn(bridgeSafeDelegate, "probeAvailability")
|
|
806
|
-
.mockResolvedValue(undefined);
|
|
807
|
-
vi.spyOn(delegate, "isHealthy").mockReturnValue(false);
|
|
808
|
-
vi.spyOn(bridgeSafeDelegate, "isHealthy").mockReturnValue(true);
|
|
809
|
-
|
|
810
|
-
await runtime.probeAvailability();
|
|
811
|
-
|
|
812
|
-
expect(runtime.isHealthy()).toBe(true);
|
|
813
|
-
expect(bridgeProbe).toHaveBeenCalledOnce();
|
|
814
|
-
expect(defaultProbe).not.toHaveBeenCalled();
|
|
815
|
-
});
|
|
816
|
-
});
|