| 36 | } |
| 37 | |
| 38 | async function waitForReady(baseUrl: string, timeoutMs = 15_000): Promise<void> { |
| 39 | const deadline = Date.now() + timeoutMs; |
| 40 | while (Date.now() < deadline) { |
| 41 | try { |
| 42 | const resp = await fetch(`${baseUrl}/health`, { |
| 43 | signal: AbortSignal.timeout(1000), |
| 44 | }); |
| 45 | if (resp.ok) return; |
| 46 | } catch { |
| 47 | // not ready yet |
| 48 | } |
| 49 | await new Promise(r => setTimeout(r, 200)); |
| 50 | } |
| 51 | throw new Error(`Daemon did not become ready within ${timeoutMs}ms`); |
| 52 | } |
| 53 | |
| 54 | async function spawnDaemon(): Promise<DaemonHandle> { |
| 55 | const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pair-agent-e2e-')); |