Files
routstrd/tests/integrations/onboard-wait.test.ts
redshift 7d95a12f84 fix(onboard): wait for models and warn instead of aborting
`startDaemon` only waits for `/health`, so onboarding reached the
integration step before models were loaded. On a cold start `/models`
blocks while providers bootstrap, and can still come back empty when
relays are slow. Since the installers now throw, that ended onboarding
with a failure after the daemon and API key were already created.

- Wait for a non-empty `/models` before installing OpenCode, OpenClaw and
  Pi (the integrations whose config embeds the model list), retrying for
  up to 5 min with a progress line every 10s.
- Catch installer failures during onboarding and print a warning that
  points at `routstrd refresh`, so onboarding still reports completion.
  The installers keep throwing, so scheduled/bulk refresh still counts
  real failures.
2026-10-13 19:58:41 +08:00

48 lines
1.5 KiB
TypeScript

import { describe, expect, it } from "bun:test";
import { waitForModels } from "../../src/integrations";
function fakeClock() {
let t = 0;
return { now: () => t, sleep: async (ms: number) => { t += ms; } };
}
describe("waitForModels (onboarding)", () => {
it("retries empty and failing /models responses until models load", async () => {
const clock = fakeClock();
const responses = [
{ output: { models: [] } },
{ error: "bootstrapping" },
{ output: { models: [{ id: "a" }, { id: "b" }] } },
];
let calls = 0;
const logs: string[] = [];
const result = await waitForModels({
...clock,
callDaemon: async () => responses[calls++]!,
log: (m) => logs.push(m),
retryDelayMs: 1_000,
});
expect(result).toEqual({ ok: true, count: 2 });
expect(calls).toBe(3);
expect(logs.at(-1)).toContain("Loaded 2 models");
});
it("gives up with the last reason after the timeout instead of throwing", async () => {
const clock = fakeClock();
let calls = 0;
const result = await waitForModels({
...clock,
callDaemon: async () => { calls++; throw new Error("Daemon request timed out"); },
log: () => {},
timeoutMs: 10_000,
retryDelayMs: 3_000,
});
expect(result.ok).toBe(false);
if (!result.ok) {
expect(result.reason).toContain("within 10s");
expect(result.reason).toContain("Daemon request timed out");
}
expect(calls).toBe(4); // attempts at 0, 3, 6, 9s; a 12s retry would exceed 10s
});
});