(input: { readonly elicitationMode: "browser" | "model" })
| 1416 | }; |
| 1417 | |
| 1418 | const runStdioMcpSession = (input: { readonly elicitationMode: "browser" | "model" }) => |
| 1419 | Effect.gen(function* () { |
| 1420 | // `executor mcp` never owns the local database. If a local server is already |
| 1421 | // running, bridge this stdio client to it; otherwise ensure a durable |
| 1422 | // background daemon is up and bridge to that. ensureDaemon is the race-safe |
| 1423 | // election: concurrent cold starts elect one owner and the losers wait for |
| 1424 | // its manifest (waitForDaemonStartupTarget) rather than failing. Bridging |
| 1425 | // means many MCP clients, the web UI, and the desktop app share one owner, |
| 1426 | // and that owner's lifetime is never tied to a transient MCP client. |
| 1427 | const active = yield* readActiveLocalServerManifest(); |
| 1428 | if (active) { |
| 1429 | yield* Effect.promise(() => |
| 1430 | runMcpHttpBridge({ manifest: active, elicitationMode: input.elicitationMode }), |
| 1431 | ); |
| 1432 | return; |
| 1433 | } |
| 1434 | |
| 1435 | // No reachable owner yet: ensure one. If we lose the election (another |
| 1436 | // process became owner first), ensureDaemon may fail, but the winner's |
| 1437 | // manifest is then reachable, so re-read it and bridge to that instead. |
| 1438 | const elected = yield* ensureDaemon(DEFAULT_BASE_URL).pipe( |
| 1439 | Effect.flatMap(() => readActiveLocalServerManifest()), |
| 1440 | Effect.catch((error) => |
| 1441 | readActiveLocalServerManifest().pipe( |
| 1442 | Effect.flatMap((manifest) => (manifest ? Effect.succeed(manifest) : Effect.fail(error))), |
| 1443 | ), |
| 1444 | ), |
| 1445 | ); |
| 1446 | if (!elected) { |
| 1447 | return yield* Effect.fail( |
| 1448 | new Error("The local Executor daemon started but did not advertise a reachable manifest."), |
| 1449 | ); |
| 1450 | } |
| 1451 | yield* Effect.promise(() => |
| 1452 | runMcpHttpBridge({ manifest: elected, elicitationMode: input.elicitationMode }), |
| 1453 | ); |
| 1454 | }); |
| 1455 | |
| 1456 | const scope = Options.string("scope").pipe( |
| 1457 | Options.optional, |
no test coverage detected