(input: {
readonly requestedBaseUrl: string;
})
| 481 | }); |
| 482 | |
| 483 | const waitForDaemonStartupTarget = (input: { |
| 484 | readonly requestedBaseUrl: string; |
| 485 | }): Effect.Effect<string | null, never, FileSystem.FileSystem | PlatformPath.Path> => |
| 486 | Effect.gen(function* () { |
| 487 | let readyBaseUrl: string | null = null; |
| 488 | let requestedFallbackBaseUrl: string | null = null; |
| 489 | const ready = yield* waitForReachable({ |
| 490 | check: Effect.gen(function* () { |
| 491 | // Prefer the manifest: it is written after the server has opened the |
| 492 | // owned DB and started serving, and it carries the bearer token the next |
| 493 | // API call needs. A bare health response on the requested URL is only a |
| 494 | // last-ditch fallback; keep polling for the manifest so tool calls do |
| 495 | // not race ahead without auth. |
| 496 | const manifest = yield* readReachableLocalServerHint(); |
| 497 | if (manifest) { |
| 498 | readyBaseUrl = manifest.connection.origin; |
| 499 | return true; |
| 500 | } |
| 501 | |
| 502 | if (yield* isServerReachable(input.requestedBaseUrl)) { |
| 503 | requestedFallbackBaseUrl = input.requestedBaseUrl; |
| 504 | } |
| 505 | |
| 506 | return false; |
| 507 | }), |
| 508 | timeoutMs: DAEMON_BOOT_TIMEOUT_MS, |
| 509 | intervalMs: DAEMON_BOOT_POLL_MS, |
| 510 | }); |
| 511 | |
| 512 | return ready ? readyBaseUrl : requestedFallbackBaseUrl; |
| 513 | }); |
| 514 | |
| 515 | // Serialize daemon startup behind a filesystem lock so concurrent CLI invocations don't |
| 516 | // each spawn their own daemon. The post-lock pointer recheck catches the case where |
no test coverage detected