(input: {
port: number;
hostname: string;
allowedHosts: ReadonlyArray<string>;
})
| 1298 | // command is idempotent: re-running while a daemon is already up should report success |
| 1299 | // (matching the auto-start behaviour) rather than fail or spawn a duplicate. |
| 1300 | const runBackgroundDaemonStart = (input: { |
| 1301 | port: number; |
| 1302 | hostname: string; |
| 1303 | allowedHosts: ReadonlyArray<string>; |
| 1304 | }): Effect.Effect<void, Error, FileSystem.FileSystem | PlatformPath.Path> => |
| 1305 | Effect.gen(function* () { |
| 1306 | const host = canonicalDaemonHost(input.hostname); |
| 1307 | const requestedUrl = daemonBaseUrl(host, input.port); |
| 1308 | const target = yield* resolveDaemonTarget(requestedUrl); |
| 1309 | |
| 1310 | if (yield* isServerReachable(target.baseUrl)) { |
| 1311 | console.log(`Daemon already running at ${target.baseUrl}.`); |
| 1312 | return; |
| 1313 | } |
| 1314 | |
| 1315 | if (!canAutoStartLocalDaemonForHost(host)) { |
| 1316 | return yield* Effect.fail( |
| 1317 | new Error( |
| 1318 | [ |
| 1319 | `Cannot background a daemon for non-local host ${host}.`, |
| 1320 | `Use --foreground or bind to localhost / 127.0.0.1.`, |
| 1321 | ].join("\n"), |
| 1322 | ), |
| 1323 | ); |
| 1324 | } |
| 1325 | |
| 1326 | const startBaseUrl = yield* spawnAndWaitForDaemon({ |
| 1327 | host, |
| 1328 | scopeId: target.scopeId, |
| 1329 | preferredPort: input.port, |
| 1330 | allowedHosts: input.allowedHosts, |
| 1331 | }); |
| 1332 | |
| 1333 | console.log(`Daemon ready on ${startBaseUrl}`); |
| 1334 | }).pipe(Effect.mapError(toError)); |
| 1335 | |
| 1336 | // --------------------------------------------------------------------------- |
| 1337 | // Stdio MCP session: a pure stdio <-> HTTP bridge to the owning local daemon. |
no test coverage detected