

























@@ -174,7 +174,8 @@ describe("createAcpxRuntimeService", () => {
174174expect(getAcpRuntimeBackend("acpx")).toBeUndefined();
175175});
176176177-it("creates the embedded runtime state directory without probing at startup by default", async () => {
177+it("skips the startup probe and defers acpx backend health reporting when explicitly opted out", async () => {
178+process.env.OPENCLAW_ACPX_RUNTIME_STARTUP_PROBE = "0";
178179const workspaceDir = await makeTempDir();
179180const stateDir = path.join(workspaceDir, "custom-state");
180181const ctx = createServiceContext(workspaceDir);
@@ -200,6 +201,47 @@ describe("createAcpxRuntimeService", () => {
200201await service.stop?.(ctx);
201202});
202203204+it("waits for the embedded runtime startup probe before resolving", async () => {
205+const workspaceDir = await makeTempDir();
206+const ctx = createServiceContext(workspaceDir);
207+let releaseProbe!: () => void;
208+const probeStarted = vi.fn();
209+const probeAvailability = vi.fn(
210+() =>
211+new Promise<void>((resolve) => {
212+probeStarted();
213+releaseProbe = resolve;
214+}),
215+);
216+const runtime = createMockRuntime({
217+ probeAvailability,
218+isHealthy: () => true,
219+});
220+const service = createAcpxRuntimeService({
221+runtimeFactory: () => runtime as never,
222+});
223+224+const startPromise = service.start(ctx) as Promise<void>;
225+await vi.waitFor(() => {
226+expect(probeStarted).toHaveBeenCalledOnce();
227+});
228+229+let resolved = false;
230+void startPromise.then(() => {
231+resolved = true;
232+});
233+await Promise.resolve();
234+235+expect(resolved).toBe(false);
236+releaseProbe();
237+await startPromise;
238+239+expect(resolved).toBe(true);
240+expect(ctx.logger.info).toHaveBeenCalledWith("embedded acpx runtime backend ready");
241+242+await service.stop?.(ctx);
243+});
244+203245it("reaps stale ACPX process leases from the generated wrapper root at startup", async () => {
204246const workspaceDir = await makeTempDir();
205247const ctx = createServiceContext(workspaceDir);
@@ -317,7 +359,8 @@ describe("createAcpxRuntimeService", () => {
317359await service.stop?.(ctx);
318360});
319361320-it("registers the default backend without importing ACPX runtime until first use", async () => {
362+it("registers the default backend lazily without importing ACPX runtime when startup probing is opted out", async () => {
363+process.env.OPENCLAW_ACPX_RUNTIME_STARTUP_PROBE = "0";
321364const workspaceDir = await makeTempDir();
322365const ctx = createServiceContext(workspaceDir);
323366const service = createAcpxRuntimeService();
@@ -344,8 +387,7 @@ describe("createAcpxRuntimeService", () => {
344387await service.stop?.(ctx);
345388});
346389347-it("can run the embedded runtime probe at startup when explicitly enabled", async () => {
348-process.env.OPENCLAW_ACPX_RUNTIME_STARTUP_PROBE = "1";
390+it("runs the embedded runtime probe at startup by default and reports health", async () => {
349391const workspaceDir = await makeTempDir();
350392const ctx = createServiceContext(workspaceDir);
351393const probeAvailability = vi.fn(async () => {});
@@ -365,6 +407,30 @@ describe("createAcpxRuntimeService", () => {
365407await service.stop?.(ctx);
366408});
367409410+it("bounds the embedded runtime startup probe wait with the configured timeout", async () => {
411+const workspaceDir = await makeTempDir();
412+const ctx = createServiceContext(workspaceDir);
413+const probeAvailability = vi.fn(() => new Promise<void>(() => {}));
414+const runtime = createMockRuntime({
415+ probeAvailability,
416+isHealthy: () => false,
417+});
418+const service = createAcpxRuntimeService({
419+pluginConfig: { timeoutSeconds: 0.001 },
420+runtimeFactory: () => runtime as never,
421+});
422+423+await service.start(ctx);
424+425+expect(probeAvailability).toHaveBeenCalledOnce();
426+expect(getAcpRuntimeBackend("acpx")?.healthy?.()).toBe(false);
427+expect(ctx.logger.warn).toHaveBeenCalledWith(
428+"embedded acpx runtime setup failed: embedded acpx runtime backend startup probe timed out after 0.001s",
429+);
430+431+await service.stop?.(ctx);
432+});
433+368434it("passes the default runtime timeout to the embedded runtime factory", async () => {
369435const workspaceDir = await makeTempDir();
370436const ctx = createServiceContext(workspaceDir);
@@ -497,7 +563,6 @@ describe("createAcpxRuntimeService", () => {
497563});
498564499565it("can skip the embedded runtime probe via env", async () => {
500-process.env.OPENCLAW_ACPX_RUNTIME_STARTUP_PROBE = "1";
501566process.env.OPENCLAW_SKIP_ACPX_RUNTIME_PROBE = "1";
502567const workspaceDir = await makeTempDir();
503568const ctx = createServiceContext(workspaceDir);
@@ -517,12 +582,12 @@ describe("createAcpxRuntimeService", () => {
517582expect(getAcpRuntimeBackend("acpx")).toMatchObject({
518583runtime: expect.any(Object),
519584});
585+expect(getAcpRuntimeBackend("acpx")?.healthy).toBeUndefined();
520586521587await service.stop?.(ctx);
522588});
523589524590it("formats non-string doctor details without losing object payloads", async () => {
525-process.env.OPENCLAW_ACPX_RUNTIME_STARTUP_PROBE = "1";
526591const workspaceDir = await makeTempDir();
527592const ctx = createServiceContext(workspaceDir);
528593const runtime = createMockRuntime({
@@ -539,11 +604,9 @@ describe("createAcpxRuntimeService", () => {
539604540605await service.start(ctx);
541606542-await vi.waitFor(() => {
543-expect(ctx.logger.warn).toHaveBeenCalledWith(
544-'embedded acpx runtime backend probe failed: probe failed ({"code":"ACP_CLOSED","agent":"codex"}; stdin closed)',
545-);
546-});
607+expect(ctx.logger.warn).toHaveBeenCalledWith(
608+'embedded acpx runtime backend probe failed: probe failed ({"code":"ACP_CLOSED","agent":"codex"}; stdin closed)',
609+);
547610548611await service.stop?.(ctx);
549612});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。