(input: { readonly elicitationMode: "browser" | "model" })
| 1439 | }; |
| 1440 | |
| 1441 | const runStdioMcpSession = (input: { readonly elicitationMode: "browser" | "model" }) => |
| 1442 | Effect.gen(function* () { |
| 1443 | // `executor mcp` never owns the local database. If a local server is already |
| 1444 | // running, bridge this stdio client to it; otherwise ensure a durable |
| 1445 | // background daemon is up and bridge to that. ensureDaemon is the race-safe |
| 1446 | // election: concurrent cold starts elect one owner and the losers wait for |
| 1447 | // its manifest (waitForDaemonStartupTarget) rather than failing. Bridging |
| 1448 | // means many MCP clients, the web UI, and the desktop app share one owner, |
| 1449 | // and that owner's lifetime is never tied to a transient MCP client. |
| 1450 | const active = yield* readActiveLocalServerManifest(); |
| 1451 | if (active) { |
| 1452 | yield* Effect.promise(() => |
| 1453 | runMcpHttpBridge({ manifest: active, elicitationMode: input.elicitationMode }), |
| 1454 | ); |
| 1455 | return; |
| 1456 | } |
| 1457 | |
| 1458 | // No reachable owner yet: ensure one. If we lose the election (another |
| 1459 | // process became owner first), ensureDaemon may fail, but the winner's |
| 1460 | // manifest is then reachable, so re-read it and bridge to that instead. |
| 1461 | const elected = yield* ensureDaemon(DEFAULT_BASE_URL).pipe( |
| 1462 | Effect.flatMap(() => readActiveLocalServerManifest()), |
| 1463 | Effect.catch((error) => |
| 1464 | readActiveLocalServerManifest().pipe( |
| 1465 | Effect.flatMap((manifest) => (manifest ? Effect.succeed(manifest) : Effect.fail(error))), |
| 1466 | ), |
| 1467 | ), |
| 1468 | ); |
| 1469 | if (!elected) { |
| 1470 | return yield* Effect.fail( |
| 1471 | new Error("The local Executor daemon started but did not advertise a reachable manifest."), |
| 1472 | ); |
| 1473 | } |
| 1474 | yield* Effect.promise(() => |
| 1475 | runMcpHttpBridge({ manifest: elected, elicitationMode: input.elicitationMode }), |
| 1476 | ); |
| 1477 | }); |
| 1478 | |
| 1479 | const scope = Options.string("scope").pipe( |
| 1480 | Options.optional, |
no test coverage detected