@codeworksh/cli 0.5.0-canary.69.1.g5be1ef81 → 0.5.0-canary.71.1.g8233e4eb
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -2
- package/{acp-BCeZqkaQ.mjs → acp-BTtByOlX.mjs} +92 -42
- package/acp-BTtByOlX.mjs.map +1 -0
- package/{add-Dzsv-fKd.mjs → add-Dm3RaxB1.mjs} +5 -5
- package/add-Dm3RaxB1.mjs.map +1 -0
- package/{catalog-C1G3pzHZ.mjs → catalog-Do2eDgti.mjs} +2 -2
- package/{catalog-C1G3pzHZ.mjs.map → catalog-Do2eDgti.mjs.map} +1 -1
- package/{check-DhojkK_E.mjs → check-BdfxwBaL.mjs} +4 -4
- package/{check-DhojkK_E.mjs.map → check-BdfxwBaL.mjs.map} +1 -1
- package/{entries-KpYvZdpi.mjs → entries-C6AeEOS1.mjs} +3 -3
- package/{entries-KpYvZdpi.mjs.map → entries-C6AeEOS1.mjs.map} +1 -1
- package/{error-BMI81XvR.mjs → error-CSeYCa9R.mjs} +195 -89
- package/error-CSeYCa9R.mjs.map +1 -0
- package/fork-CAu8PdA3.mjs +32 -0
- package/fork-CAu8PdA3.mjs.map +1 -0
- package/{identity-BfTAc3aC.mjs → identity-CpsvMaTx.mjs} +2 -2
- package/{identity-BfTAc3aC.mjs.map → identity-CpsvMaTx.mjs.map} +1 -1
- package/index.mjs +32 -25
- package/index.mjs.map +1 -1
- package/{install-BLRDBzp1.mjs → install-D5kkATcv.mjs} +4 -4
- package/{install-BLRDBzp1.mjs.map → install-D5kkATcv.mjs.map} +1 -1
- package/{link--UnM2qnT.mjs → link-CsfmcRa8.mjs} +3 -3
- package/{link--UnM2qnT.mjs.map → link-CsfmcRa8.mjs.map} +1 -1
- package/list-C60d6ifJ.mjs +36 -0
- package/list-C60d6ifJ.mjs.map +1 -0
- package/{list-9fVqelid.mjs → list-CHIzxyZx.mjs} +4 -4
- package/{list-9fVqelid.mjs.map → list-CHIzxyZx.mjs.map} +1 -1
- package/{list-BE4xSEe3.mjs → list-CakHFl9C.mjs} +4 -4
- package/{list-BE4xSEe3.mjs.map → list-CakHFl9C.mjs.map} +1 -1
- package/{login-CRwxi5WD.mjs → login-BaUYCO2G.mjs} +4 -4
- package/{login-CRwxi5WD.mjs.map → login-BaUYCO2G.mjs.map} +1 -1
- package/{logout-C89X0B9M.mjs → logout-BAks2xS7.mjs} +4 -4
- package/{logout-C89X0B9M.mjs.map → logout-BAks2xS7.mjs.map} +1 -1
- package/package-CmagAGZz.mjs +6 -0
- package/package-CmagAGZz.mjs.map +1 -0
- package/package.json +4 -4
- package/{providers-BrXJvY2P.mjs → providers-DVh6hhLU.mjs} +4 -4
- package/{providers-BrXJvY2P.mjs.map → providers-DVh6hhLU.mjs.map} +1 -1
- package/{refresh-D0wBP2Go.mjs → refresh-CNQBX5NK.mjs} +4 -4
- package/{refresh-D0wBP2Go.mjs.map → refresh-CNQBX5NK.mjs.map} +1 -1
- package/{refresh--j0Pj4Cw.mjs → refresh-tj3xbNRY.mjs} +4 -4
- package/{refresh--j0Pj4Cw.mjs.map → refresh-tj3xbNRY.mjs.map} +1 -1
- package/relink-BlRMYOra.mjs +23 -0
- package/relink-BlRMYOra.mjs.map +1 -0
- package/{reload-DgPawyzr.mjs → reload-h_2WARQN.mjs} +3 -3
- package/{reload-DgPawyzr.mjs.map → reload-h_2WARQN.mjs.map} +1 -1
- package/{remove-DfFme5w2.mjs → remove-CVbXLNTb.mjs} +4 -4
- package/{remove-DfFme5w2.mjs.map → remove-CVbXLNTb.mjs.map} +1 -1
- package/{restart-JPAbjFUh.mjs → restart-B0XSXYtj.mjs} +4 -4
- package/{restart-JPAbjFUh.mjs.map → restart-B0XSXYtj.mjs.map} +1 -1
- package/{run-CVRkm_Iz.mjs → run-CRV3jJ2d.mjs} +26 -17
- package/run-CRV3jJ2d.mjs.map +1 -0
- package/{runtime-B43doHjV.mjs → runtime-Bg4mc9BB.mjs} +59 -3
- package/runtime-Bg4mc9BB.mjs.map +1 -0
- package/{serve-DT8-nVCx.mjs → serve-XrW3PuIZ.mjs} +101 -73
- package/serve-XrW3PuIZ.mjs.map +1 -0
- package/{service-Cv-MLS-9.mjs → service-D_vwPPPh.mjs} +3 -3
- package/{service-Cv-MLS-9.mjs.map → service-D_vwPPPh.mjs.map} +1 -1
- package/{settings-BfmoL27m.mjs → settings-DcwstDUm.mjs} +2 -2
- package/{settings-BfmoL27m.mjs.map → settings-DcwstDUm.mjs.map} +1 -1
- package/{shared-CnuCjvcG.mjs → shared-D_3E8bu_.mjs} +3 -3
- package/{shared-CnuCjvcG.mjs.map → shared-D_3E8bu_.mjs.map} +1 -1
- package/{start-Qb1Ea9oT.mjs → start-CJ4XeLwV.mjs} +4 -4
- package/{start-Qb1Ea9oT.mjs.map → start-CJ4XeLwV.mjs.map} +1 -1
- package/{status-VGKqsdkQ.mjs → status-6NyZu0f_.mjs} +4 -4
- package/{status-VGKqsdkQ.mjs.map → status-6NyZu0f_.mjs.map} +1 -1
- package/{status-DVzFDoek.mjs → status-DBzQVkL2.mjs} +4 -4
- package/{status-DVzFDoek.mjs.map → status-DBzQVkL2.mjs.map} +1 -1
- package/{stop-mO7eg0nG.mjs → stop-BY1c7cUX.mjs} +4 -4
- package/{stop-mO7eg0nG.mjs.map → stop-BY1c7cUX.mjs.map} +1 -1
- package/thread-CEYjLavT.mjs +15 -0
- package/thread-CEYjLavT.mjs.map +1 -0
- package/{tui-DVVaevMF.mjs → tui-CBUtCHzR.mjs} +5 -5
- package/{tui-DVVaevMF.mjs.map → tui-CBUtCHzR.mjs.map} +1 -1
- package/{update-D0XPVfJu.mjs → update-CORsF38E.mjs} +4 -4
- package/{update-D0XPVfJu.mjs.map → update-CORsF38E.mjs.map} +1 -1
- package/acp-BCeZqkaQ.mjs.map +0 -1
- package/add-Dzsv-fKd.mjs.map +0 -1
- package/error-BMI81XvR.mjs.map +0 -1
- package/package-D9XCaBr1.mjs +0 -6
- package/package-D9XCaBr1.mjs.map +0 -1
- package/run-CVRkm_Iz.mjs.map +0 -1
- package/runtime-B43doHjV.mjs.map +0 -1
- package/serve-DT8-nVCx.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-Bg4mc9BB.mjs","names":["Spec.make","Otel.layer"],"sources":["../../src/framework/spec.ts","../../src/cli/cmd/cmd.ts","../../src/framework/otel.ts","../../src/framework/runtime.ts"],"sourcesContent":["import { Command } from \"effect/cli\";\n\n/**\n * A declarative command tree. Specs carry only the shape of a command -- its\n * name, parameters, description, and children -- so the whole CLI surface can\n * be read in one file. Handlers are attached separately by {@link Runtime}, which\n * keeps their imports (and the harness they pull in) off the startup path.\n */\n\nexport interface Example {\n\treadonly command: string;\n\treadonly description: string;\n}\n\ninterface Options<\n\tConfig extends Command.Command.Config,\n\tShared extends Command.Command.FlagConfig,\n\tCommands extends ReadonlyArray<Any>,\n> {\n\treadonly description?: string;\n\treadonly params?: Config;\n\t/** Flags declared here are also parsed by every descendant command. */\n\treadonly shared?: Shared;\n\treadonly examples?: ReadonlyArray<Example>;\n\treadonly commands?: Commands;\n}\n\nexport interface Node<\n\tName extends string,\n\t// The tree is heterogeneous, so a node has to accept any command shape here.\n\t// Concrete types are recovered per-command through `Runtime.Input`.\n\t// biome-ignore lint/suspicious/noExplicitAny: heterogeneous command tree\n\tSpec extends Command.Command<Name, any, any, any, any>,\n\tCommands extends Children,\n> {\n\treadonly name: Name;\n\treadonly spec: Spec;\n\treadonly commands: Commands;\n}\n\n// The command name is invariant on `Command`, so the erased node type has to\n// admit any name for concrete nodes to be assignable to it.\n// biome-ignore lint/suspicious/noExplicitAny: heterogeneous command tree\nexport type Any = Node<string, Command.Command<any, any, any, any, any>, Children>;\nexport type Children = Readonly<Record<string, Any>>;\n\ntype ChildrenOf<Commands extends ReadonlyArray<Any>> = {\n\treadonly [Node in Commands[number] as Node[\"name\"]]: Node;\n};\n\nexport function make<\n\tconst Name extends string,\n\tconst Config extends Command.Command.Config = {},\n\tconst Shared extends Command.Command.FlagConfig = {},\n\tconst Commands extends ReadonlyArray<Any> = [],\n>(name: Name, options: Options<Config, Shared, Commands> = {}) {\n\tlet spec = Command.make(name, options.params ?? ({} as Config)).pipe(\n\t\tCommand.withSharedFlags(options.shared ?? ({} as Shared)),\n\t);\n\tif (options.description !== undefined) spec = spec.pipe(Command.withDescription(options.description));\n\tif (options.examples !== undefined) spec = spec.pipe(Command.withExamples(options.examples));\n\treturn {\n\t\tname,\n\t\tspec,\n\t\tcommands: Object.fromEntries(\n\t\t\t(options.commands ?? []).map((command) => [command.name, command]),\n\t\t) as ChildrenOf<Commands>,\n\t};\n}\n\nexport * as Spec from \"./spec.ts\";\n","import { Model } from \"@codeworksh/aikit\";\nimport { Schema } from \"effect\";\nimport { Argument, Flag } from \"effect/cli\";\nimport { Spec } from \"../../framework/spec.ts\";\n\n/**\n * The full command surface of the `codework` CLI. Declarations only -- each\n * command's behaviour lives in `./handlers`, wired up in `src/index.ts`.\n */\n\nexport const thinkingLevels = Object.values(Model.ThinkingLevelEnum);\n\n/**\n * Every `auth` subcommand answers the same three questions: which provider,\n * whose credentials, and where they live. Only `login` needs anything more.\n */\nconst AuthParams = {\n\topenaiCodex: Flag.Boolean(\"openai-codex\").pipe(\n\t\tFlag.withDescription(\"Use OpenAI Codex OAuth\"),\n\t\tFlag.withDefault(false),\n\t),\n\tgithubCopilot: Flag.Boolean(\"github-copilot\").pipe(\n\t\tFlag.withDescription(\"Use GitHub Copilot OAuth (device flow)\"),\n\t\tFlag.withDefault(false),\n\t),\n\tserver: Flag.String(\"server\").pipe(Flag.withDescription(\"RPC server URL (ws://host:port/rpc/v1)\"), Flag.optional),\n\tauthFile: Flag.String(\"auth-file\").pipe(\n\t\tFlag.withDescription(\"Credential file (defaults to <home>/aikit/auth.json)\"),\n\t\tFlag.optional,\n\t),\n};\n\n/** Where the background server binds when `tui` or `service` has to start one. */\nconst ServerAddress = {\n\thost: Flag.String(\"host\").pipe(\n\t\tFlag.withDescription(\"Host interface the background server binds\"),\n\t\tFlag.withDefault(\"127.0.0.1\"),\n\t),\n\tport: Flag.Int(\"port\").pipe(\n\t\tFlag.withSchema(Schema.Int.check(Schema.isBetween({ minimum: 0, maximum: 65535 }))),\n\t\tFlag.withDescription(\"Port the background server listens on\"),\n\t\tFlag.withDefault(7433),\n\t),\n};\n\n/** For commands that only talk to a server that is already running. */\nconst RunningServer = Flag.String(\"server\").pipe(\n\tFlag.withDescription(\"Base URL of the running codework server\"),\n\tFlag.withDefault(\"http://127.0.0.1:7433\"),\n);\n\nconst JsonFlag = Flag.Boolean(\"json\").pipe(\n\tFlag.withDescription(\"Print machine-readable output\"),\n\tFlag.withDefault(false),\n);\n\nexport const Cmd = Spec.make(\"codework\", {\n\tdescription: \"CodeWork Command Line Interface\",\n\tshared: {\n\t\tuserConfigDir: Flag.String(\"user-config-dir\").pipe(\n\t\t\tFlag.withDescription(\"Directory whose settings.jsonc replaces the user settings in --home\"),\n\t\t\tFlag.optional,\n\t\t),\n\t\thome: Flag.String(\"home\").pipe(\n\t\t\tFlag.withDescription(\"CodeWork home: user settings, credentials, cache and data (default: ~/.codework)\"),\n\t\t\tFlag.optional,\n\t\t),\n\t\tdatabase: Flag.String(\"database\").pipe(Flag.withDescription(\"SQLite database path or :memory:\"), Flag.optional),\n\t},\n\tcommands: [\n\t\tSpec.make(\"auth\", {\n\t\t\tdescription: \"Manage OAuth credentials\",\n\t\t\tcommands: [\n\t\t\t\tSpec.make(\"login\", {\n\t\t\t\t\tdescription: \"Sign in to a provider\",\n\t\t\t\t\tparams: {\n\t\t\t\t\t\t...AuthParams,\n\t\t\t\t\t\tbrowser: Flag.Boolean(\"browser\").pipe(\n\t\t\t\t\t\t\tFlag.withDescription(\"Open the authorization URL in the default browser\"),\n\t\t\t\t\t\t\tFlag.withDefault(true),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tdevice: Flag.Boolean(\"device\").pipe(\n\t\t\t\t\t\t\tFlag.withDescription(\"Use the device-code flow instead of a localhost browser callback\"),\n\t\t\t\t\t\t\tFlag.withDefault(false),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tenterprise: Flag.String(\"enterprise\").pipe(\n\t\t\t\t\t\t\tFlag.withDescription(\"GitHub Enterprise domain for GitHub Copilot login\"),\n\t\t\t\t\t\t\tFlag.optional,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tenableModels: Flag.Boolean(\"enable-models\").pipe(\n\t\t\t\t\t\t\tFlag.withDescription(\"Enable unconfigured Copilot catalog models after login\"),\n\t\t\t\t\t\t\tFlag.withDefault(false),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tjson: JsonFlag,\n\t\t\t\t\t},\n\t\t\t\t\texamples: [\n\t\t\t\t\t\t{ command: \"codework auth login --openai-codex\", description: \"Sign in with ChatGPT\" },\n\t\t\t\t\t\t{ command: \"codework auth login --github-copilot\", description: \"Sign in with GitHub Copilot\" },\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommand: \"codework auth login --openai-codex --device\",\n\t\t\t\t\t\t\tdescription: \"Sign in with a device code, no local port\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommand: \"codework auth login --openai-codex --server ws://127.0.0.1:7433/rpc/v1\",\n\t\t\t\t\t\t\tdescription: \"Sign in the running server\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t\t\tSpec.make(\"status\", {\n\t\t\t\t\tdescription: \"Show a stored login without refreshing it\",\n\t\t\t\t\tparams: { ...AuthParams, json: JsonFlag },\n\t\t\t\t\texamples: [{ command: \"codework auth status --openai-codex\", description: \"Show the stored login\" }],\n\t\t\t\t}),\n\t\t\t\tSpec.make(\"refresh\", {\n\t\t\t\t\tdescription: \"Refresh a stored login if it has expired\",\n\t\t\t\t\tparams: { ...AuthParams, json: JsonFlag },\n\t\t\t\t\texamples: [{ command: \"codework auth refresh --openai-codex\", description: \"Renew an expired login\" }],\n\t\t\t\t}),\n\t\t\t\tSpec.make(\"logout\", {\n\t\t\t\t\tdescription: \"Clear a stored login\",\n\t\t\t\t\tparams: AuthParams,\n\t\t\t\t\texamples: [{ command: \"codework auth logout --github-copilot\", description: \"Clear the stored login\" }],\n\t\t\t\t}),\n\t\t\t],\n\t\t}),\n\t\tSpec.make(\"run\", {\n\t\t\tdescription: \"Start or continue an agent session\",\n\t\t\tparams: {\n\t\t\t\tserver: Flag.String(\"server\").pipe(\n\t\t\t\t\tFlag.withDescription(\"RPC server URL (ws://host:port/rpc/v1)\"),\n\t\t\t\t\tFlag.optional,\n\t\t\t\t),\n\t\t\t\tprompt: Argument.String(\"prompt\").pipe(Argument.withDescription(\"Prompt for the agent\")),\n\t\t\t\tsession: Flag.String(\"session\").pipe(\n\t\t\t\t\tFlag.withAlias(\"s\"),\n\t\t\t\t\tFlag.withDescription(\"Continue an existing session\"),\n\t\t\t\t\tFlag.optional,\n\t\t\t\t),\n\t\t\t\tthread: Flag.String(\"thread\").pipe(\n\t\t\t\t\tFlag.withDescription(\"Thread of --session to continue: a thread ID, or main (default)\"),\n\t\t\t\t\tFlag.optional,\n\t\t\t\t),\n\t\t\t\tcwd: Flag.String(\"cwd\").pipe(\n\t\t\t\t\tFlag.withAlias(\"C\"),\n\t\t\t\t\tFlag.withDescription(\"Working directory for a new session\"),\n\t\t\t\t\tFlag.optional,\n\t\t\t\t),\n\t\t\t\tsandboxDriver: Flag.String(\"sandbox-driver\").pipe(\n\t\t\t\t\tFlag.withDescription(\"Sandbox driver for a new session (default: local)\"),\n\t\t\t\t\tFlag.optional,\n\t\t\t\t),\n\t\t\t\tsandboxId: Flag.String(\"sandbox-id\").pipe(\n\t\t\t\t\tFlag.withDescription(\"Reuse an existing sandbox instance\"),\n\t\t\t\t\tFlag.optional,\n\t\t\t\t),\n\t\t\t\tsandboxProviderId: Flag.String(\"sandbox-provider-id\").pipe(\n\t\t\t\t\tFlag.withDescription(\"Provider ID of an existing remote sandbox\"),\n\t\t\t\t\tFlag.optional,\n\t\t\t\t),\n\t\t\t\tprovider: Flag.String(\"provider\").pipe(Flag.withDescription(\"Model catalog provider ID\"), Flag.optional),\n\t\t\t\tmodel: Flag.String(\"model\").pipe(Flag.withDescription(\"Model ID\"), Flag.optional),\n\t\t\t\tthinking: Flag.Literals(\"thinking\", thinkingLevels).pipe(\n\t\t\t\t\tFlag.withDescription(\"Reasoning effort the model uses before answering\"),\n\t\t\t\t\tFlag.optional,\n\t\t\t\t),\n\t\t\t},\n\t\t\texamples: [\n\t\t\t\t{ command: 'codework run \"Inspect the failing tests\"', description: \"Create a session\" },\n\t\t\t\t{\n\t\t\t\t\tcommand: 'codework run --provider openai --model gpt-5.5 --thinking high \"Inspect the failing tests\"',\n\t\t\t\t\tdescription: \"Create a session with an explicit model\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tcommand: 'codework run --sandbox-driver daytona \"Inspect the repository\"',\n\t\t\t\t\tdescription: \"Create a Daytona sandbox and session\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tcommand: 'codework run --sandbox-driver daytona --sandbox-provider-id <id> \"Inspect the repository\"',\n\t\t\t\t\tdescription: \"Use an existing remote sandbox\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tcommand: 'codework run --session <id> --provider openai --model gpt-5.6-luna \"Now fix them\"',\n\t\t\t\t\tdescription: \"Continue a session with explicit model bindings\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tcommand: 'codework run --session <id> --thread <thread-id> \"Try OAuth instead\"',\n\t\t\t\t\tdescription: \"Continue one of the session's threads\",\n\t\t\t\t},\n\t\t\t],\n\t\t}),\n\t\tSpec.make(\"tui\", {\n\t\t\tdescription: \"Launch the CodeWork terminal UI against the background server\",\n\t\t\tparams: {\n\t\t\t\tserver: Flag.String(\"server\").pipe(\n\t\t\t\t\tFlag.withDescription(\"RPC server URL to use instead of the background server (ws://host:port/rpc/v1)\"),\n\t\t\t\t\tFlag.optional,\n\t\t\t\t),\n\t\t\t\t...ServerAddress,\n\t\t\t\targs: Argument.variadic(\n\t\t\t\t\tArgument.String(\"args\").pipe(Argument.withDescription(\"Arguments forwarded to the terminal UI\")),\n\t\t\t\t),\n\t\t\t},\n\t\t\texamples: [\n\t\t\t\t{ command: \"codework tui\", description: \"Start or reuse the local server and open the terminal UI\" },\n\t\t\t\t{\n\t\t\t\t\tcommand: \"codework tui --server ws://127.0.0.1:7433/rpc/v1\",\n\t\t\t\t\tdescription: \"Attach the terminal UI to a server you started yourself\",\n\t\t\t\t},\n\t\t\t],\n\t\t}),\n\t\tSpec.make(\"serve\", {\n\t\t\tdescription: \"Start the CodeWork RPC server\",\n\t\t\tparams: {\n\t\t\t\thost: Flag.String(\"host\").pipe(\n\t\t\t\t\tFlag.withDescription(\"Host interface to bind\"),\n\t\t\t\t\tFlag.withDefault(\"127.0.0.1\"),\n\t\t\t\t),\n\t\t\t\tport: Flag.Int(\"port\").pipe(\n\t\t\t\t\tFlag.withSchema(Schema.Int.check(Schema.isBetween({ minimum: 0, maximum: 65535 }))),\n\t\t\t\t\tFlag.withDescription(\"Port to listen on (0 for an ephemeral port)\"),\n\t\t\t\t\tFlag.withDefault(7433),\n\t\t\t\t),\n\t\t\t\tservice: Flag.Boolean(\"service\").pipe(\n\t\t\t\t\tFlag.withDescription(\n\t\t\t\t\t\t\"Run as the background server `codework tui` manages, logging to <home>/log/server.log\",\n\t\t\t\t\t),\n\t\t\t\t\tFlag.withDefault(false),\n\t\t\t\t),\n\t\t\t},\n\t\t\texamples: [\n\t\t\t\t{ command: \"codework serve\", description: \"Start the RPC server on 127.0.0.1:7433\" },\n\t\t\t\t{ command: \"codework serve --port 0\", description: \"Choose an available local port\" },\n\t\t\t],\n\t\t}),\n\t\tSpec.make(\"service\", {\n\t\t\tdescription: \"Manage the background server\",\n\t\t\tcommands: [\n\t\t\t\tSpec.make(\"start\", { description: \"Start the background server\", params: ServerAddress }),\n\t\t\t\tSpec.make(\"restart\", { description: \"Restart the background server\", params: ServerAddress }),\n\t\t\t\tSpec.make(\"status\", { description: \"Show background server status\" }),\n\t\t\t\tSpec.make(\"stop\", { description: \"Stop the background server\" }),\n\t\t\t],\n\t\t}),\n\t\tSpec.make(\"session\", {\n\t\t\tdescription: \"Manage sessions\",\n\t\t\tcommands: [\n\t\t\t\tSpec.make(\"link\", {\n\t\t\t\t\tdescription: \"Anchor a session to a host directory\",\n\t\t\t\t\tparams: {\n\t\t\t\t\t\tsession: Argument.String(\"session-id\").pipe(Argument.withDescription(\"The session to link\")),\n\t\t\t\t\t\tpath: Argument.String(\"path\").pipe(\n\t\t\t\t\t\t\t// The anchor is not a configuration mechanism, but `.codework` is the landmark\n\t\t\t\t\t\t\t// a person recognises, so the help names it to make the directory concrete.\n\t\t\t\t\t\t\tArgument.withDescription(\n\t\t\t\t\t\t\t\t\"Host directory to anchor to — typically the directory holding your .codework configuration; defaults to the shell's\",\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tArgument.optional,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tunlink: Flag.Boolean(\"unlink\").pipe(\n\t\t\t\t\t\t\tFlag.withDescription(\"Clear the anchor, leaving the session with no host directory\"),\n\t\t\t\t\t\t\tFlag.withDefault(false),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tserver: RunningServer,\n\t\t\t\t\t},\n\t\t\t\t\texamples: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommand: \"codework session link ses_01h9\",\n\t\t\t\t\t\t\tdescription: \"Link it to the directory you are standing in\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommand: \"codework session link ses_01h9 ~/work/api\",\n\t\t\t\t\t\t\tdescription: \"Link it to a project elsewhere on this machine\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommand: \"codework session link ses_01h9 --unlink\",\n\t\t\t\t\t\t\tdescription: \"Clear the anchor\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t\t\tSpec.make(\"relink\", {\n\t\t\t\t\tdescription: \"Move where a session's work, or one thread's, happens\",\n\t\t\t\t\tparams: {\n\t\t\t\t\t\tsession: Argument.String(\"session-id\").pipe(Argument.withDescription(\"The session to move\")),\n\t\t\t\t\t\tthread: Flag.String(\"thread\").pipe(\n\t\t\t\t\t\t\tFlag.withDescription(\n\t\t\t\t\t\t\t\t\"Move only this thread: a thread ID, or main; omitted moves the session's default\",\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tFlag.optional,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tdirectory: Flag.String(\"directory\").pipe(\n\t\t\t\t\t\t\tFlag.withAlias(\"C\"),\n\t\t\t\t\t\t\tFlag.withDescription(\n\t\t\t\t\t\t\t\t\"Checkout to move into; the work keeps its position under it when that path exists there\",\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tFlag.optional,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tsandboxId: Flag.String(\"sandbox-id\").pipe(\n\t\t\t\t\t\t\tFlag.withDescription(\"Sandbox instance to move to (default: local)\"),\n\t\t\t\t\t\t\tFlag.optional,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tjson: JsonFlag,\n\t\t\t\t\t\tserver: RunningServer,\n\t\t\t\t\t},\n\t\t\t\t\texamples: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommand: \"codework session relink ses_01h9 -C ~/work/api\",\n\t\t\t\t\t\t\tdescription: \"Move the session to a local checkout\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommand: \"codework session relink ses_01h9 --thread thr_01ja --sandbox-id sbx_01k2\",\n\t\t\t\t\t\t\tdescription: \"Run one thread in a sandbox, leaving the others where they are\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t\t],\n\t\t}),\n\t\tSpec.make(\"thread\", {\n\t\t\tdescription: \"Manage a session's threads\",\n\t\t\tcommands: [\n\t\t\t\tSpec.make(\"list\", {\n\t\t\t\t\tdescription: \"List a session's threads, newest first\",\n\t\t\t\t\tparams: {\n\t\t\t\t\t\tsession: Argument.String(\"session-id\").pipe(Argument.withDescription(\"The session\")),\n\t\t\t\t\t\tjson: JsonFlag,\n\t\t\t\t\t\tserver: RunningServer,\n\t\t\t\t\t},\n\t\t\t\t\texamples: [{ command: \"codework thread list ses_01h9\", description: \"List the session's threads\" }],\n\t\t\t\t}),\n\t\t\t\tSpec.make(\"fork\", {\n\t\t\t\t\tdescription: \"Start a new thread from a committed entry of a thread's history\",\n\t\t\t\t\tparams: {\n\t\t\t\t\t\tsession: Argument.String(\"session-id\").pipe(Argument.withDescription(\"The session\")),\n\t\t\t\t\t\tthread: Flag.String(\"thread\").pipe(\n\t\t\t\t\t\t\tFlag.withDescription(\"Thread to fork: a thread ID, or main (default)\"),\n\t\t\t\t\t\t\tFlag.optional,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tat: Flag.String(\"at\").pipe(Flag.withDescription(\"Keep history through this entry\"), Flag.optional),\n\t\t\t\t\t\tbefore: Flag.String(\"before\").pipe(\n\t\t\t\t\t\t\tFlag.withDescription(\"Keep history up to this user entry, and print its text to edit\"),\n\t\t\t\t\t\t\tFlag.optional,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tjson: JsonFlag,\n\t\t\t\t\t\tserver: RunningServer,\n\t\t\t\t\t},\n\t\t\t\t\texamples: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommand: \"codework thread fork ses_01h9 --at 01jb\",\n\t\t\t\t\t\t\tdescription: \"Continue the main thread's history through an entry in a new thread\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommand: \"codework thread fork ses_01h9 --thread thr_01ja --before 01jc\",\n\t\t\t\t\t\t\tdescription: \"Branch just before a prompt, to send it again differently\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t\t],\n\t\t}),\n\t\tSpec.make(\"plugin\", {\n\t\t\tdescription: \"Manage plugins\",\n\t\t\tcommands: [\n\t\t\t\tSpec.make(\"add\", {\n\t\t\t\t\tdescription: \"Install a plugin and add it to a settings file\",\n\t\t\t\t\tparams: {\n\t\t\t\t\t\tpackage: Argument.String(\"package\").pipe(\n\t\t\t\t\t\t\tArgument.withDescription(\"Package spec, path, or file: URL\"),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tglobal: Flag.Boolean(\"global\").pipe(\n\t\t\t\t\t\t\tFlag.withAlias(\"g\"),\n\t\t\t\t\t\t\tFlag.withDescription(\"Write the user-wide settings file instead of this project's\"),\n\t\t\t\t\t\t\tFlag.withDefault(false),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tsession: Flag.String(\"session\").pipe(\n\t\t\t\t\t\t\tFlag.withDescription(\"Write the project a session is linked to, rather than this directory's\"),\n\t\t\t\t\t\t\tFlag.optional,\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t\texamples: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommand: \"codework plugin add @acme/codework-tool-proc@1.2.0\",\n\t\t\t\t\t\t\tdescription: \"Install a published plugin into this project's settings\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommand: \"codework plugin add @acme/codework-tool-proc --session ses_01h9\",\n\t\t\t\t\t\t\tdescription: \"Write the project that session is linked to, from anywhere\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommand: \"codework plugin add @acme/codework-tool-proc -g\",\n\t\t\t\t\t\t\tdescription: \"Install it for every project this user runs\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t\t\tSpec.make(\"install\", {\n\t\t\t\t\tdescription: \"Install every plugin the settings files name\",\n\t\t\t\t\tparams: {},\n\t\t\t\t\texamples: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommand: \"codework plugin install\",\n\t\t\t\t\t\t\tdescription: \"Materialise what a fresh checkout already declares\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t\t\tSpec.make(\"list\", {\n\t\t\t\t\tdescription: \"List configured plugins and what each one resolved to\",\n\t\t\t\t\tparams: {\n\t\t\t\t\t\tverbose: Flag.Boolean(\"verbose\").pipe(\n\t\t\t\t\t\t\tFlag.withDescription(\"Show the message behind a failure, not only its reason\"),\n\t\t\t\t\t\t\tFlag.withDefault(false),\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t\texamples: [{ command: \"codework plugin list\", description: \"Show every configured plugin\" }],\n\t\t\t\t}),\n\t\t\t\tSpec.make(\"check\", {\n\t\t\t\t\tdescription: \"Report which configured plugins have a newer revision available\",\n\t\t\t\t\tparams: {\n\t\t\t\t\t\tspec: Argument.String(\"spec\").pipe(\n\t\t\t\t\t\t\tArgument.withDescription(\"Only this configured plugin: a package name or spec, git spec, or path\"),\n\t\t\t\t\t\t\tArgument.optional,\n\t\t\t\t\t\t),\n\t\t\t\t\t\t// An answer is reused for an hour, which is right for a command someone may\n\t\t\t\t\t\t// run repeatedly and wrong for the minute after they pushed a plugin. Without\n\t\t\t\t\t\t// this there is no way to say \"ask again\", and `check` reports a moving branch\n\t\t\t\t\t\t// as current while `update` — which always refreshes — moves it.\n\t\t\t\t\t\trefresh: Flag.Boolean(\"refresh\").pipe(\n\t\t\t\t\t\t\tFlag.withDescription(\"Ask the remote again instead of reusing a recent answer\"),\n\t\t\t\t\t\t\tFlag.withDefault(false),\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t\texamples: [\n\t\t\t\t\t\t{ command: \"codework plugin check\", description: \"Ask the registry what has moved\" },\n\t\t\t\t\t\t{ command: \"codework plugin check @acme/codework-tool-proc\", description: \"Ask about one plugin\" },\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommand: \"codework plugin check --refresh\",\n\t\t\t\t\t\t\tdescription: \"Ignore the cached answer, after pushing a plugin\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t\t\tSpec.make(\"update\", {\n\t\t\t\t\tdescription: \"Fetch a newer revision of every plugin that has one\",\n\t\t\t\t\tparams: {\n\t\t\t\t\t\tspec: Argument.String(\"spec\").pipe(\n\t\t\t\t\t\t\tArgument.withDescription(\"Only this configured plugin: a package name or spec, git spec, or path\"),\n\t\t\t\t\t\t\tArgument.optional,\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t\texamples: [\n\t\t\t\t\t\t{ command: \"codework plugin update\", description: \"Take whatever `check` found\" },\n\t\t\t\t\t\t{ command: \"codework plugin update @acme/codework-tool-proc\", description: \"Update one plugin\" },\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t\t\tSpec.make(\"reload\", {\n\t\t\t\t\tdescription: \"Re-import configured plugins in a running server\",\n\t\t\t\t\tparams: {\n\t\t\t\t\t\tserver: RunningServer,\n\t\t\t\t\t},\n\t\t\t\t\texamples: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommand: \"codework plugin reload\",\n\t\t\t\t\t\t\tdescription: \"Pick up edits to a local plugin without restarting\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t\t\tSpec.make(\"remove\", {\n\t\t\t\t\tdescription: \"Remove a plugin from a settings file\",\n\t\t\t\t\tparams: {\n\t\t\t\t\t\tpackage: Argument.String(\"package\").pipe(\n\t\t\t\t\t\t\tArgument.withDescription(\"Configured package spec, path, or plugin ID\"),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tglobal: Flag.Boolean(\"global\").pipe(\n\t\t\t\t\t\t\tFlag.withAlias(\"g\"),\n\t\t\t\t\t\t\tFlag.withDescription(\"Edit the user-wide settings file instead of this project's\"),\n\t\t\t\t\t\t\tFlag.withDefault(false),\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t\texamples: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommand: \"codework plugin remove @acme/codework-tool-proc\",\n\t\t\t\t\t\t\tdescription: \"Drop a plugin and any configuration written against it\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t\t],\n\t\t}),\n\t\tSpec.make(\"models\", {\n\t\t\tdescription: \"List or refresh the model catalog\",\n\t\t\tparams: {\n\t\t\t\tprovider: Flag.String(\"provider\").pipe(Flag.withDescription(\"Model catalog provider ID\"), Flag.optional),\n\t\t\t},\n\t\t\texamples: [\n\t\t\t\t{ command: \"codework models\", description: \"List all models from all providers\" },\n\t\t\t\t{\n\t\t\t\t\tcommand: \"codework models --provider openai\",\n\t\t\t\t\tdescription: \"List models for a specific provider\",\n\t\t\t\t},\n\t\t\t\t{ command: \"codework models providers\", description: \"List all available provider IDs\" },\n\t\t\t],\n\t\t\tcommands: [\n\t\t\t\tSpec.make(\"providers\", {\n\t\t\t\t\tdescription: \"List available model providers in the catalog\",\n\t\t\t\t}),\n\t\t\t\tSpec.make(\"refresh\", {\n\t\t\t\t\tdescription: \"Download the model catalog into the home if it is stale\",\n\t\t\t\t\tparams: {\n\t\t\t\t\t\tforce: Flag.Boolean(\"force\").pipe(\n\t\t\t\t\t\t\tFlag.withDescription(\"Download it even if it is still fresh\"),\n\t\t\t\t\t\t\tFlag.withDefault(false),\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t\texamples: [\n\t\t\t\t\t\t{ command: \"codework models refresh\", description: \"Refresh a catalog older than 15 minutes\" },\n\t\t\t\t\t\t{ command: \"codework models refresh --force\", description: \"Download the catalog now\" },\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t\t],\n\t\t}),\n\t\tSpec.make(\"acp\", {\n\t\t\tdescription: \"Start the CodeWork Agent Client Protocol (ACP) server over stdio\",\n\t\t\texamples: [{ command: \"codework acp\", description: \"Start the ACP server on stdio\" }],\n\t\t}),\n\t],\n});\n","import { Config, ConfigProvider, Effect, Layer, Metric, Option, References, Schema } from \"effect\";\nimport { FetchHttpClient } from \"effect/http\";\nimport { OtlpMetrics, OtlpSerialization, OtlpTracer } from \"effect/observability\";\nimport { uuidv7 } from \"uuidv7\";\n\n// Configured by the standard `OTEL_*` variables alone. A configuration that fails\n// to build runs the command without export rather than failing it.\n\n// The OTel spec defaults `OTEL_{TRACES,METRICS}_EXPORTER` to `otlp`; Effect reads an\n// unset list as none, so an endpoint alone would export nothing.\nconst exporterDefaults = ConfigProvider.layerAdd(\n\tConfigProvider.fromUnknown({ OTEL_TRACES_EXPORTER: [\"otlp\"], OTEL_METRICS_EXPORTER: [\"otlp\"] }),\n);\n\n// Effect's fiber metrics hook every fiber start and end, so they follow metrics export.\nconst metricsEnabled = Config.all({\n\tdisabled: Config.Boolean(\"OTEL_SDK_DISABLED\").pipe(Config.withDefault(false)),\n\tendpoint: Config.String(\"OTEL_EXPORTER_OTLP_METRICS_ENDPOINT\").pipe(\n\t\tConfig.orElse(() => Config.String(\"OTEL_EXPORTER_OTLP_ENDPOINT\")),\n\t\tConfig.option,\n\t),\n\texporters: Config.Array(Schema.String, \"OTEL_METRICS_EXPORTER\"),\n}).pipe(\n\tConfig.map(\n\t\t({ disabled, endpoint, exporters }) =>\n\t\t\t!disabled && Option.isSome(endpoint) && exporters.some((exporter) => exporter.trim().toLowerCase() === \"otlp\"),\n\t),\n);\n\nconst fiberMetrics = Layer.unwrap(\n\tEffect.gen(function* () {\n\t\treturn (yield* metricsEnabled) ? Metric.enableRuntimeMetricsLayer : Layer.empty;\n\t}),\n);\n\n// Only spans marked `level: \"Info\"` are exported; the rest, Effect's own `sql.*`\n// among them, default to `Debug`. Effect drops a span's children with it, so every\n// span on the path from a command to a model or tool call must be `Info`.\nconst levels = { all: \"All\", trace: \"Trace\", debug: \"Debug\", info: \"Info\", warn: \"Warn\", error: \"Error\" } as const;\n\nconst traceLevels = Layer.unwrap(\n\tEffect.gen(function* () {\n\t\tconst name = yield* Config.String(\"CODEWORK_TRACE_LEVEL\").pipe(Config.withDefault(\"info\"));\n\t\tconst minimum = levels[name.trim().toLowerCase() as keyof typeof levels] ?? \"Info\";\n\t\treturn Layer.mergeAll(\n\t\t\tLayer.succeed(References.CurrentTraceLevel, \"Debug\"),\n\t\t\tLayer.succeed(References.MinimumTraceLevel, minimum),\n\t\t);\n\t}),\n);\n\ninterface OtlpResource {\n\treadonly serviceName: string;\n\treadonly serviceVersion: string;\n\treadonly attributes: Record<string, string>;\n}\n\n// Effect has no gRPC exporter: `grpc` exports nothing rather than sending HTTP to a gRPC port.\nconst exporters = (resource: OtlpResource) =>\n\tLayer.unwrap(\n\t\tEffect.gen(function* () {\n\t\t\tconst protocol = yield* Config.String(\"OTEL_EXPORTER_OTLP_PROTOCOL\").pipe(Config.withDefault(\"http/protobuf\"));\n\t\t\tconst format = {\n\t\t\t\t\"http/json\": OtlpSerialization.layerJson,\n\t\t\t\t\"http/protobuf\": OtlpSerialization.layerProtobuf,\n\t\t\t}[protocol.trim().toLowerCase()];\n\t\t\tif (format === undefined) return Layer.empty;\n\t\t\treturn Layer.mergeAll(\n\t\t\t\tOtlpTracer.layerFromConfig({ resource }),\n\t\t\t\tOtlpMetrics.layerFromConfig({ resource }),\n\t\t\t).pipe(Layer.provide(format));\n\t\t}),\n\t);\n\nconst channel = (version: string) =>\n\tversion.includes(\"-canary.\") ? \"canary\" : version.includes(\"-dev.\") ? \"dev\" : \"latest\";\n\nconst instanceId = uuidv7();\n\nexport const layer = (options: { readonly version: string; readonly command: string }) => {\n\tconst resource: OtlpResource = {\n\t\tserviceName: \"codework\",\n\t\tserviceVersion: options.version,\n\t\tattributes: {\n\t\t\t\"service.instance.id\": instanceId,\n\t\t\t\"deployment.environment.name\": channel(options.version),\n\t\t\t\"codework.command\": options.command,\n\t\t},\n\t};\n\treturn Layer.mergeAll(exporters(resource), fiberMetrics, traceLevels).pipe(\n\t\tLayer.provide(FetchHttpClient.layer),\n\t\tLayer.provide(exporterDefaults),\n\t\tLayer.catchCause(() => Layer.empty),\n\t);\n};\n\nexport * as Otel from \"./otel.ts\";\n","import { Effect } from \"effect\";\nimport { Command } from \"effect/cli\";\nimport type { CommandError } from \"../cli/error.ts\";\nimport { Otel } from \"./otel.ts\";\nimport { Spec } from \"./spec.ts\";\n\n/**\n * Binds handlers to a {@link Spec} tree. Handlers are loaded through dynamic\n * imports so that starting the process -- or printing `--help` -- never pulls in\n * the harness, its sandbox drivers, or the model catalog.\n */\n\n/** Recovers the parsed input type of a spec node, for typing its handler. */\nexport type Input<Value> =\n\tValue extends Spec.Node<infer _Name, infer Spec, infer _Commands>\n\t\t? Input<Spec>\n\t\t: Value extends Command.Command<infer _Name, infer Parsed, infer _Context, infer _Error, infer _Requirements>\n\t\t\t? Parsed\n\t\t\t: never;\n\n/**\n * A handler may yield an ancestor's spec to read its shared flags, which shows up\n * as a `CommandContext` requirement; `withSubcommands` discharges it when the tree\n * is assembled.\n */\ntype Requirements = Command.Environment | Command.CommandContext<string>;\ntype Run<Parsed> = (input: Parsed) => Effect.Effect<void, CommandError, Requirements>;\ntype Loader<Node extends Spec.Any> = () => Promise<{ readonly default: Run<Input<Node>> }>;\n\n/**\n * The handler registry for a spec tree: a loader per leaf, mirroring the shape of\n * the tree. A parent with children takes its own handler under `$`.\n */\nexport type Handlers<Node extends Spec.Any> = keyof Node[\"commands\"] extends never\n\t? Loader<Node>\n\t: { readonly $?: Loader<Node> } & { readonly [Key in keyof Node[\"commands\"]]: Handlers<Node[\"commands\"][Key]> };\n\ninterface LazyHandler {\n\treadonly spec: Command.Command.Any;\n\t// biome-ignore lint/suspicious/noExplicitAny: input is recovered per-command by `Input`\n\treadonly load: () => Promise<{ readonly default: Run<any> }>;\n}\n\ntype LazyHandlers = LazyHandler[\"load\"] | { readonly [key: string]: LazyHandlers | undefined };\n\ntype ProvidedCommand = Command.Command<string, unknown, unknown, CommandError, Command.Environment>;\n\n/** Type-checks a handler against the spec node it implements. */\nexport function handler<const Node extends Spec.Any>(_node: Node, run: Run<Input<Node>>) {\n\treturn run;\n}\n\nexport function handlers<const Root extends Spec.Any>(\n\troot: Root,\n\thandlers: Handlers<Root>,\n): ReadonlyArray<LazyHandler> {\n\tconst result: LazyHandler[] = [];\n\n\tfunction add(node: Spec.Any, value: LazyHandlers) {\n\t\tif (typeof value === \"function\") {\n\t\t\tresult.push({ spec: node.spec, load: value });\n\t\t\treturn;\n\t\t}\n\t\tif (value.$ !== undefined) result.push({ spec: node.spec, load: value.$ as LazyHandler[\"load\"] });\n\t\tfor (const [name, child] of Object.entries(node.commands)) {\n\t\t\tconst nested = value[name];\n\t\t\tif (nested !== undefined) add(child, nested);\n\t\t}\n\t}\n\n\tadd(root, handlers as LazyHandlers);\n\treturn result;\n}\n\nexport function run(root: Spec.Any, handlers: ReadonlyArray<LazyHandler>, options: { readonly version: string }) {\n\treturn Command.run(provide(root, handlers, { version: options.version, path: [] }), options);\n}\n\nfunction provide(\n\tnode: Spec.Any,\n\thandlers: ReadonlyArray<LazyHandler>,\n\tcontext: { readonly version: string; readonly path: ReadonlyArray<string> },\n): ProvidedCommand {\n\tconst found = handlers.find((entry) => entry.spec === node.spec);\n\tconst command = context.path.length === 0 ? node.name : context.path.join(\" \");\n\tconst spec = found\n\t\t? node.spec.pipe(\n\t\t\t\tCommand.withHandler((input) =>\n\t\t\t\t\tEffect.promise(found.load).pipe(\n\t\t\t\t\t\tEffect.flatMap((module) => module.default(input)),\n\t\t\t\t\t\tEffect.provide(Otel.layer({ version: context.version, command })),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t)\n\t\t: node.spec;\n\tconst children = Object.values(node.commands);\n\tif (children.length === 0) return spec as ProvidedCommand;\n\treturn spec.pipe(\n\t\tCommand.withSubcommands(\n\t\t\tchildren.map((child) => provide(child, handlers, { ...context, path: [...context.path, child.name] })),\n\t\t),\n\t) as ProvidedCommand;\n}\n\nexport * as Runtime from \"./runtime.ts\";\n"],"mappings":"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"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { i as Cmd, t as handler } from "./runtime-
|
|
2
|
-
import {
|
|
1
|
+
import { i as Cmd, t as handler } from "./runtime-Bg4mc9BB.mjs";
|
|
2
|
+
import { C as encode, S as Core, _ as OAuthError, b as decode, g as Api, r as renderError, u as writeError, w as ofThread, x as Connected, y as path } from "./error-CSeYCa9R.mjs";
|
|
3
3
|
import { t as harnessOptions } from "./harness-6d8TlAVk.mjs";
|
|
4
|
-
import { c as register, r as layer$4, s as log, t as Service$2 } from "./identity-
|
|
4
|
+
import { c as register, r as layer$4, s as log, t as Service$2 } from "./identity-CpsvMaTx.mjs";
|
|
5
5
|
import { Cause, Context, DateTime, Effect, FileSystem, Layer, Logger, Option, Queue, Stream } from "effect";
|
|
6
6
|
import { Model } from "@codeworksh/aikit";
|
|
7
7
|
import { HttpRouter, HttpServer } from "effect/http";
|
|
8
|
-
import { Control, Event, EventRegistry, EventSchema, Global, Harness, ModelCatalog, Project, PromptSchema, Sandbox, Session, SessionStore, Settings, State } from "@codeworksh/harness/effect";
|
|
8
|
+
import { Control, Event, EventList, EventRegistry, EventSchema, Global, Harness, ModelCatalog, Project, PromptSchema, Sandbox, Session, SessionStore, Settings, State, ThreadSchema, ThreadStore } from "@codeworksh/harness/effect";
|
|
9
9
|
import { NodeHttpServer } from "@effect/platform-node";
|
|
10
10
|
import { RpcSerialization, RpcServer } from "effect/rpc";
|
|
11
11
|
import { summarizeGitHubCopilot, summarizeOpenAICodex } from "@codeworksh/aikit/oauth/summary";
|
|
@@ -131,25 +131,30 @@ const toSandboxInfo = (info) => ({
|
|
|
131
131
|
});
|
|
132
132
|
const toSessionInfo = (info) => ({
|
|
133
133
|
id: info.id,
|
|
134
|
-
title: info.title,
|
|
135
134
|
directory: info.directory,
|
|
136
135
|
...info.hostDir === void 0 ? {} : { hostDir: info.hostDir },
|
|
137
136
|
...info.sandbox === void 0 ? {} : { sandbox: toSandboxInfo(info.sandbox) },
|
|
138
137
|
...info.project === void 0 ? {} : { project: info.project },
|
|
139
138
|
updatedAt: info.updatedAt,
|
|
139
|
+
mainThreadId: info.mainThreadId
|
|
140
|
+
});
|
|
141
|
+
const toThreadInfo = (info) => ({
|
|
142
|
+
id: info.id,
|
|
143
|
+
origin: info.origin,
|
|
144
|
+
...info.title === void 0 ? {} : { title: info.title },
|
|
145
|
+
updatedAt: info.updatedAt,
|
|
140
146
|
...info.model === void 0 ? {} : { model: info.model },
|
|
141
147
|
...info.thinkingLevel === void 0 ? {} : { thinkingLevel: info.thinkingLevel },
|
|
142
|
-
...info.
|
|
148
|
+
...info.placement === void 0 ? {} : { placement: info.placement },
|
|
149
|
+
...info.parked ? { parked: true } : {},
|
|
150
|
+
usage: info.usage,
|
|
151
|
+
session: toSessionInfo(info.session)
|
|
143
152
|
});
|
|
144
153
|
const runtimeInput = (runtime) => ({
|
|
145
|
-
...runtime?.model
|
|
146
|
-
...runtime?.thinkingLevel
|
|
147
|
-
});
|
|
148
|
-
const sessionInfo = Effect.fn("Server.sessionInfo")(function* (sessionId) {
|
|
149
|
-
const found = yield* Session.get(sessionId);
|
|
150
|
-
if (Option.isNone(found)) return yield* new SessionStore.SessionNotFoundError({ sessionId });
|
|
151
|
-
return toSessionInfo(yield* found.value.info);
|
|
154
|
+
...runtime?.model == null ? {} : { model: runtime.model },
|
|
155
|
+
...runtime?.thinkingLevel == null ? {} : { thinkingLevel: runtime.thinkingLevel }
|
|
152
156
|
});
|
|
157
|
+
const threadInfo = (threadId) => Session.threadInfo(threadId).pipe(Effect.map(toThreadInfo));
|
|
153
158
|
const exported = (name, self) => self.pipe(Effect.withSpan(name, {
|
|
154
159
|
level: "Info",
|
|
155
160
|
root: true
|
|
@@ -161,6 +166,8 @@ const layer$1 = Api.toLayer(Effect.gen(function* () {
|
|
|
161
166
|
const control = yield* Control.Service;
|
|
162
167
|
const feed = yield* Service$1;
|
|
163
168
|
const sessions = yield* SessionStore.Service;
|
|
169
|
+
const threads = yield* ThreadStore.Service;
|
|
170
|
+
const resolve = (ref) => control.resolve(ref).pipe(Effect.map((thread) => ThreadSchema.ID.make(thread.id)));
|
|
164
171
|
const state = yield* State.Service;
|
|
165
172
|
const oauth = yield* Service;
|
|
166
173
|
const identity = yield* Service$2;
|
|
@@ -186,7 +193,7 @@ const layer$1 = Api.toLayer(Effect.gen(function* () {
|
|
|
186
193
|
...project === void 0 ? {} : { project },
|
|
187
194
|
...runtimeInput(runtime)
|
|
188
195
|
}).pipe(Effect.onError(() => releaseOnFailure(selection)));
|
|
189
|
-
return
|
|
196
|
+
return toThreadInfo(yield* handle.main.info);
|
|
190
197
|
}),
|
|
191
198
|
"model.list": Effect.fnUntraced(function* ({ hostDir }) {
|
|
192
199
|
const filter = hostDir === void 0 ? {} : { hostDir };
|
|
@@ -232,24 +239,74 @@ const layer$1 = Api.toLayer(Effect.gen(function* () {
|
|
|
232
239
|
"plugin.reload": Effect.fnUntraced(function* () {
|
|
233
240
|
return yield* state.reload;
|
|
234
241
|
}),
|
|
235
|
-
"session.
|
|
236
|
-
const
|
|
237
|
-
return yield* Effect.forEach(rows, (row) => sessionInfo(row.id).pipe(Effect.orDie));
|
|
238
|
-
}),
|
|
239
|
-
"session.configure": Effect.fnUntraced(function* ({ sessionId, runtime }) {
|
|
240
|
-
const handle = yield* Session.attach({
|
|
242
|
+
"session.link": Effect.fnUntraced(function* ({ sessionId, hostDir }) {
|
|
243
|
+
const handle = yield* Session.link({
|
|
241
244
|
sessionId,
|
|
242
|
-
|
|
245
|
+
hostDir: hostDir ?? null
|
|
243
246
|
});
|
|
244
247
|
return toSessionInfo(yield* handle.info);
|
|
245
248
|
}),
|
|
246
|
-
"session.
|
|
247
|
-
|
|
249
|
+
"session.relink": Effect.fnUntraced(function* ({ sessionId, threadId, sandbox, directory }) {
|
|
250
|
+
const selection = sandbox === void 0 ? void 0 : yield* exported("Server.session.relink", Sandbox.resolve(sandbox));
|
|
251
|
+
const selected = selection?.info;
|
|
252
|
+
const thread = yield* (yield* Session.relink({
|
|
253
|
+
sessionId,
|
|
254
|
+
...threadId === void 0 ? {} : { threadId },
|
|
255
|
+
...selected === void 0 ? {} : { sandbox: selected },
|
|
256
|
+
...directory === void 0 ? {} : { directory }
|
|
257
|
+
}).pipe(Effect.onError(() => releaseOnFailure(selection)))).thread(threadId ?? ThreadSchema.MAIN);
|
|
258
|
+
return toThreadInfo(yield* thread.info);
|
|
259
|
+
}),
|
|
260
|
+
"session.delete": Effect.fnUntraced(function* ({ sessionId }) {
|
|
261
|
+
return { deleted: yield* Session.remove(sessionId) };
|
|
262
|
+
}),
|
|
263
|
+
"session.interrupt": Effect.fnUntraced(function* ({ sessionId }) {
|
|
264
|
+
return { interrupted: yield* control.interruptSession(sessionId, { reason: "user" }) };
|
|
248
265
|
}),
|
|
249
|
-
"session.
|
|
266
|
+
"session.log": ({ sessionId, threadId, after, follow }) => Stream.unwrap(Effect.gen(function* () {
|
|
250
267
|
if (Option.isNone(yield* sessions.get(sessionId))) return yield* new SessionStore.SessionNotFoundError({ sessionId });
|
|
251
|
-
return
|
|
268
|
+
return events.log({
|
|
269
|
+
aggregateId: sessionId,
|
|
270
|
+
follow: follow ?? false,
|
|
271
|
+
...after === void 0 ? {} : { after }
|
|
272
|
+
}).pipe(Stream.filter((item) => threadId === void 0 || Event.isSynced(item) || ofThread(threadId)(item)), Stream.mapEffect(toLogItem(registry.get)));
|
|
273
|
+
})),
|
|
274
|
+
"thread.list": Effect.fnUntraced(function* ({ sessionId }) {
|
|
275
|
+
const rows = yield* threads.list(sessionId);
|
|
276
|
+
return yield* Effect.forEach(rows, (row) => threadInfo(ThreadSchema.ID.make(row.id)).pipe(Effect.orDie));
|
|
277
|
+
}),
|
|
278
|
+
"thread.info": Effect.fnUntraced(function* (ref) {
|
|
279
|
+
return yield* threadInfo(yield* resolve(ref));
|
|
280
|
+
}),
|
|
281
|
+
"thread.configure": Effect.fnUntraced(function* ({ runtime, ...ref }) {
|
|
282
|
+
const threadId = yield* resolve(ref);
|
|
283
|
+
const change = {
|
|
284
|
+
...runtime.model === void 0 ? {} : { model: runtime.model },
|
|
285
|
+
...runtime.thinkingLevel === void 0 ? {} : { thinkingLevel: runtime.thinkingLevel }
|
|
286
|
+
};
|
|
287
|
+
if (Object.keys(change).length > 0) yield* events.publish(EventList.ThreadConfigured, {
|
|
288
|
+
sessionId: ref.sessionId,
|
|
289
|
+
threadId,
|
|
290
|
+
timestamp: yield* DateTime.now,
|
|
291
|
+
change
|
|
292
|
+
});
|
|
293
|
+
return yield* threadInfo(threadId);
|
|
294
|
+
}),
|
|
295
|
+
"thread.fork": Effect.fnUntraced(function* ({ entryId, mode, ...ref }) {
|
|
296
|
+
const forked = yield* threads.fork({
|
|
297
|
+
threadId: yield* resolve(ref),
|
|
298
|
+
entryId,
|
|
299
|
+
...mode === void 0 ? {} : { mode }
|
|
300
|
+
});
|
|
301
|
+
return {
|
|
302
|
+
thread: yield* threadInfo(ThreadSchema.ID.make(forked.thread.id)),
|
|
303
|
+
...forked.text === void 0 ? {} : { text: forked.text }
|
|
304
|
+
};
|
|
305
|
+
}),
|
|
306
|
+
"thread.history": Effect.fnUntraced(function* (ref) {
|
|
307
|
+
return { entries: (yield* threads.line(yield* resolve(ref))).flatMap(({ entry, parts }) => entry.type === "user" || entry.type === "assistant" ? [{
|
|
252
308
|
id: entry.id,
|
|
309
|
+
threadId: entry.threadId,
|
|
253
310
|
seq: entry.seq,
|
|
254
311
|
role: entry.type,
|
|
255
312
|
state: entry.state,
|
|
@@ -258,68 +315,39 @@ const layer$1 = Api.toLayer(Effect.gen(function* () {
|
|
|
258
315
|
parts: parts.flatMap((part) => Option.toArray(decode(part.data)))
|
|
259
316
|
}] : []) };
|
|
260
317
|
}),
|
|
261
|
-
"
|
|
262
|
-
|
|
263
|
-
return { entries: (yield* control.pending(sessionId)).map((input) => ({
|
|
318
|
+
"thread.queue": Effect.fnUntraced(function* (ref) {
|
|
319
|
+
return { entries: (yield* control.pending(yield* resolve(ref))).map((input) => ({
|
|
264
320
|
id: input.id,
|
|
265
321
|
delivery: input.delivery,
|
|
266
322
|
text: PromptSchema.Prompt.text(input.prompt),
|
|
267
323
|
createdAt: DateTime.toEpochMillis(input.timeCreated)
|
|
268
324
|
})) };
|
|
269
325
|
}),
|
|
270
|
-
"
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
aggregateId: sessionId,
|
|
274
|
-
follow: follow ?? false,
|
|
275
|
-
...after === void 0 ? {} : { after }
|
|
276
|
-
}).pipe(Stream.mapEffect(toLogItem(registry.get)));
|
|
277
|
-
})),
|
|
278
|
-
"session.link": Effect.fnUntraced(function* ({ sessionId, hostDir }) {
|
|
279
|
-
const handle = yield* Session.link({
|
|
280
|
-
sessionId,
|
|
281
|
-
hostDir: hostDir ?? null
|
|
282
|
-
});
|
|
283
|
-
return toSessionInfo(yield* handle.info);
|
|
284
|
-
}),
|
|
285
|
-
"session.relink": Effect.fnUntraced(function* ({ sessionId, sandbox, directory }) {
|
|
286
|
-
const selection = sandbox === void 0 ? void 0 : yield* exported("Server.session.relink", Sandbox.resolve(sandbox));
|
|
287
|
-
const selected = selection?.info;
|
|
288
|
-
const handle = yield* Session.relink({
|
|
289
|
-
sessionId,
|
|
290
|
-
...selected === void 0 ? {} : { sandbox: selected },
|
|
291
|
-
...directory === void 0 ? {} : { directory }
|
|
292
|
-
}).pipe(Effect.onError(() => releaseOnFailure(selection)));
|
|
293
|
-
return toSessionInfo(yield* handle.info);
|
|
294
|
-
}),
|
|
295
|
-
"session.prompt": Effect.fnUntraced(function* ({ sessionId, text, delivery, id }) {
|
|
296
|
-
yield* control.prompt({
|
|
297
|
-
sessionId,
|
|
326
|
+
"thread.prompt": Effect.fnUntraced(function* ({ text, delivery, id, ...ref }) {
|
|
327
|
+
return { threadId: (yield* control.prompt({
|
|
328
|
+
...ref,
|
|
298
329
|
prompt: PromptSchema.Prompt.fromText(text),
|
|
299
330
|
...delivery === void 0 ? {} : { delivery },
|
|
300
331
|
...id === void 0 ? {} : { id }
|
|
301
|
-
});
|
|
332
|
+
})).threadId };
|
|
302
333
|
}),
|
|
303
|
-
"
|
|
304
|
-
return { interrupted: yield* control.interrupt(
|
|
334
|
+
"thread.interrupt": Effect.fnUntraced(function* (ref) {
|
|
335
|
+
return { interrupted: yield* control.interrupt(yield* resolve(ref), { reason: "user" }) };
|
|
305
336
|
}),
|
|
306
|
-
"
|
|
307
|
-
|
|
308
|
-
return { cancelled: yield* control.cancel(sessionId, messageId) };
|
|
337
|
+
"thread.cancel": Effect.fnUntraced(function* ({ messageId, ...ref }) {
|
|
338
|
+
return { cancelled: yield* control.cancel(yield* resolve(ref), messageId) };
|
|
309
339
|
}),
|
|
310
|
-
"
|
|
311
|
-
|
|
312
|
-
return { updated: yield* control.update(sessionId, messageId, {
|
|
340
|
+
"thread.update": Effect.fnUntraced(function* ({ messageId, delivery, text, ...ref }) {
|
|
341
|
+
return { updated: yield* control.update(yield* resolve(ref), messageId, {
|
|
313
342
|
...delivery === void 0 ? {} : { delivery },
|
|
314
343
|
...text === void 0 ? {} : { prompt: PromptSchema.Prompt.fromText(text) }
|
|
315
344
|
}) };
|
|
316
345
|
}),
|
|
317
|
-
"
|
|
318
|
-
|
|
319
|
-
return { found: Option.isSome(found) && found.value.entry.sessionId === sessionId };
|
|
346
|
+
"thread.message": Effect.fnUntraced(function* ({ messageId, ...ref }) {
|
|
347
|
+
return { found: (yield* threads.line(yield* resolve(ref))).some(({ entry }) => entry.id === messageId) };
|
|
320
348
|
}),
|
|
321
|
-
"
|
|
322
|
-
yield* control.wait(
|
|
349
|
+
"thread.wait": Effect.fnUntraced(function* (ref) {
|
|
350
|
+
yield* control.wait(yield* resolve(ref));
|
|
323
351
|
}),
|
|
324
352
|
"sandbox.drivers": Effect.fnUntraced(function* () {
|
|
325
353
|
return (yield* Sandbox.drivers()).map(({ name, kind }) => ({
|
|
@@ -342,11 +370,11 @@ const layer$1 = Api.toLayer(Effect.gen(function* () {
|
|
|
342
370
|
"sandbox.stop": Effect.fnUntraced(function* ({ sandboxId }) {
|
|
343
371
|
yield* Sandbox.stop(sandboxId);
|
|
344
372
|
}),
|
|
345
|
-
"event.subscribe": () => Stream.unwrap(feed.subscribe.pipe(Effect.map((events) => Stream.make({
|
|
373
|
+
"event.subscribe": ({ threadId }) => Stream.unwrap(feed.subscribe.pipe(Effect.map((events) => Stream.make({
|
|
346
374
|
id: EventSchema.ID.create(),
|
|
347
375
|
type: Connected.type,
|
|
348
376
|
data: {}
|
|
349
|
-
}).pipe(Stream.concat(events)))))
|
|
377
|
+
}).pipe(Stream.concat(threadId === void 0 ? events : events.pipe(Stream.filter(ofThread(threadId))))))))
|
|
350
378
|
});
|
|
351
379
|
}));
|
|
352
380
|
//#endregion
|
|
@@ -438,4 +466,4 @@ var serve_default = handler(Cmd.commands.serve, Effect.fn("CLI.serve", { level:
|
|
|
438
466
|
//#endregion
|
|
439
467
|
export { serve_default as default };
|
|
440
468
|
|
|
441
|
-
//# sourceMappingURL=serve-
|
|
469
|
+
//# sourceMappingURL=serve-XrW3PuIZ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve-XrW3PuIZ.mjs","names":["Service","Envelope.Core","Envelope.encode","layer","layer","Contract.OAuthError","Envelope.encode","layer","EventFeed.Service","OAuth.Service","Identity.Service","Envelope.ofThread","MessagePart.decode","Identity.Service","Contract.path","Registration.register","Contract.Api","EventFeed.layer","OAuth.layer","Identity.layer","Runtime.handler","Server.layer","Registration.log"],"sources":["../../src/server/feed.ts","../../src/server/oauth.ts","../../src/server/handlers.ts","../../src/server/server.ts","../../src/cli/cmd/handlers/serve.ts"],"sourcesContent":["import { Event, EventRegistry, EventSchema } from \"@codeworksh/harness/effect\";\nimport { Cause, Context, Effect, Layer, Queue, Scope, Stream } from \"effect\";\nimport { EncodingError, type EventEnvelope, Envelope } from \"./envelope.ts\";\n\nexport const SubscriberCapacity = 4096;\n\nexport type Error = Event.SubscriptionOverflowError | EncodingError;\n\nexport interface Interface {\n\t/** A live envelope stream for one client; releasing the scope unregisters it. */\n\treadonly subscribe: Effect.Effect<Stream.Stream<EventEnvelope, Error>, never, Scope.Scope>;\n}\n\nexport class Service extends Context.Service<Service, Interface>()(\"@codeworksh/cli/server/feed/Service\") {}\n\n/**\n * Fan-out for `event.subscribe`. One listener on the event bus encodes each\n * event once and hands the same envelope to every client, rather than every\n * client re-encoding the same payload.\n *\n * Failure is per-cause, not per-feed: a client that cannot keep up fails alone\n * with its own overflow, while an event that cannot be encoded is a server bug\n * that disconnects everyone currently attached -- the feed stays usable for\n * whoever connects next. Types outside the server's registry are dropped\n * before they can consume a client's capacity.\n */\nexport const make = Effect.fn(\"EventFeed.make\")(function* (\n\tlisten: (subscriber: Event.Subscriber) => Effect.Effect<Event.Unsubscribe>,\n\toptions?: { readonly capacity?: number; readonly registry?: Envelope.Registry },\n) {\n\tconst capacity = options?.capacity ?? SubscriberCapacity;\n\t// Whatever this server knows how to describe, plugin registrations included.\n\tconst registry = options?.registry ?? Envelope.Core;\n\tconst subscribers = new Set<Queue.Queue<EventEnvelope, Error>>();\n\n\tconst failAll = (error: Error) =>\n\t\tEffect.sync(() => {\n\t\t\tconst current = Array.from(subscribers);\n\t\t\tsubscribers.clear();\n\t\t\tfor (const subscriber of current) Queue.failCauseUnsafe(subscriber, Cause.fail(error));\n\t\t});\n\n\tconst deliver = Effect.fnUntraced(function* (event: EventSchema.Payload) {\n\t\tif (subscribers.size === 0) return;\n\t\t// Dropped here rather than after the queue: a burst of events this server\n\t\t// cannot describe must not spend a client's capacity on its way to nowhere.\n\t\tif (registry(event.type) === undefined) return;\n\t\tconst envelope = yield* Envelope.encode(event, registry);\n\t\tfor (const subscriber of subscribers) {\n\t\t\tif (Queue.offerUnsafe(subscriber, envelope)) continue;\n\t\t\tsubscribers.delete(subscriber);\n\t\t\tQueue.failCauseUnsafe(subscriber, Cause.fail(new Event.SubscriptionOverflowError({ capacity })));\n\t\t}\n\t});\n\n\tconst publish = (event: EventSchema.Payload) =>\n\t\tdeliver(event).pipe(\n\t\t\tEffect.catchTags({\n\t\t\t\tEventEncodingError: (error) =>\n\t\t\t\t\tEffect.logError(\"Failed to encode public event\", { type: error.type, cause: error.cause }).pipe(\n\t\t\t\t\t\tEffect.andThen(failAll(error)),\n\t\t\t\t\t),\n\t\t\t\t// The registry guard in `deliver` already returned for unknown types.\n\t\t\t\tUnknownEventTypeError: Effect.die,\n\t\t\t}),\n\t\t);\n\n\tconst unsubscribe = yield* listen(publish);\n\tyield* Effect.addFinalizer(() => unsubscribe);\n\n\treturn Service.of({\n\t\tsubscribe: Effect.acquireRelease(\n\t\t\tQueue.dropping<EventEnvelope, Error>(capacity).pipe(\n\t\t\t\tEffect.tap((queue) => Effect.sync(() => subscribers.add(queue))),\n\t\t\t),\n\t\t\t(queue) => Effect.sync(() => subscribers.delete(queue)).pipe(Effect.andThen(Queue.shutdown(queue))),\n\t\t).pipe(Effect.map(Stream.fromQueue)),\n\t});\n});\n\nexport const layer = Layer.effect(\n\tService,\n\tEffect.gen(function* () {\n\t\tconst events = yield* Event.Service;\n\t\tconst registered = yield* EventRegistry.Service;\n\t\treturn yield* make(events.listen, { registry: registered.get });\n\t}),\n);\n\nexport * as EventFeed from \"./feed.ts\";\n","/**\n * Server-side OAuth credential storage.\n *\n * The CLI runs the interactive part of every login locally — a browser\n * callback or a device code cannot travel over RPC — and sends the resulting\n * credentials here, so this service only ever reads, writes, refreshes and\n * clears the server home's `auth.json`.\n */\nimport {\n\tGitHubCopilotOAuthClient,\n\tJsonGitHubCopilotAuthStorage,\n\ttype GitHubCopilotOAuthCredentials,\n} from \"@codeworksh/aikit/oauth/github/copilot\";\nimport {\n\tJsonOpenAICodexAuthStorage,\n\tOpenAICodexOAuthClient,\n\ttype OpenAICodexOAuthCredentials,\n} from \"@codeworksh/aikit/oauth/openai/codex\";\nimport { summarizeGitHubCopilot, summarizeOpenAICodex } from \"@codeworksh/aikit/oauth/summary\";\nimport { Global } from \"@codeworksh/harness/effect\";\nimport { Context, Effect, Layer } from \"effect\";\nimport { Contract } from \"./contract.ts\";\n\ninterface Interface {\n\treadonly save: (credentials: Contract.OAuthCredentials) => Effect.Effect<Contract.OAuthInfo, Contract.OAuthError>;\n\treadonly status: (provider: Contract.OAuthProvider) => Effect.Effect<Contract.OAuthInfo | null, Contract.OAuthError>;\n\treadonly refresh: (\n\t\tprovider: Contract.OAuthProvider,\n\t) => Effect.Effect<Contract.OAuthInfo | null, Contract.OAuthError>;\n\treadonly logout: (provider: Contract.OAuthProvider) => Effect.Effect<void, Contract.OAuthError>;\n}\n\nexport class Service extends Context.Service<Service, Interface>()(\"@codeworksh/cli/server/oauth/Service\") {}\n\nconst message = (cause: unknown): string =>\n\tcause instanceof Error && cause.message.trim().length > 0 ? cause.message : String(cause);\n\n/**\n * Re-exported so the server, the CLI and aikit all describe a login the same\n * way; `Contract.OAuthInfo` is the wire shape of {@link OAuthSummary}.\n */\nexport const codexInfo = summarizeOpenAICodex;\nexport const copilotInfo = summarizeGitHubCopilot;\n\nexport const layer = (options: { readonly home?: string | undefined } = {}) =>\n\tLayer.effect(\n\t\tService,\n\t\tEffect.gen(function* () {\n\t\t\tconst global = yield* Global.Service;\n\t\t\tconst authFile = Global.authFile(options.home === undefined ? undefined : global.home);\n\t\t\tconst file = authFile === undefined ? {} : { path: authFile };\n\t\t\tconst codex = new OpenAICodexOAuthClient({ storage: new JsonOpenAICodexAuthStorage(file) });\n\t\t\tconst copilot = new GitHubCopilotOAuthClient({ storage: new JsonGitHubCopilotAuthStorage(file) });\n\t\t\tconst attempt = <A>(run: () => Promise<A>) =>\n\t\t\t\tEffect.tryPromise({\n\t\t\t\t\ttry: run,\n\t\t\t\t\tcatch: (cause) => new Contract.OAuthError({ message: message(cause) }),\n\t\t\t\t});\n\t\t\tconst optional = <A>(run: () => Promise<A | undefined>, info: (value: A) => Contract.OAuthInfo) =>\n\t\t\t\tattempt(run).pipe(Effect.map((value) => (value === undefined ? null : info(value))));\n\n\t\t\treturn Service.of({\n\t\t\t\t// The `provider` tag is routing, not a credential: it never reaches disk.\n\t\t\t\tsave: (wire) => {\n\t\t\t\t\tif (wire.provider === \"openai-codex\") {\n\t\t\t\t\t\tconst credentials: OpenAICodexOAuthCredentials = {\n\t\t\t\t\t\t\taccess: wire.access,\n\t\t\t\t\t\t\trefresh: wire.refresh,\n\t\t\t\t\t\t\texpires: wire.expires,\n\t\t\t\t\t\t\taccountId: wire.accountId,\n\t\t\t\t\t\t};\n\t\t\t\t\t\treturn attempt(() => codex.storage.set(credentials)).pipe(Effect.as(codexInfo(credentials)));\n\t\t\t\t\t}\n\t\t\t\t\tconst credentials: GitHubCopilotOAuthCredentials = {\n\t\t\t\t\t\taccess: wire.access,\n\t\t\t\t\t\trefresh: wire.refresh,\n\t\t\t\t\t\texpires: wire.expires,\n\t\t\t\t\t\t...(wire.enterpriseUrl === undefined ? {} : { enterpriseUrl: wire.enterpriseUrl }),\n\t\t\t\t\t\t...(wire.apiEndpoint === undefined ? {} : { apiEndpoint: wire.apiEndpoint }),\n\t\t\t\t\t\t...(wire.availableModelIds === undefined ? {} : { availableModelIds: [...wire.availableModelIds] }),\n\t\t\t\t\t};\n\t\t\t\t\treturn attempt(() => copilot.storage.set(credentials)).pipe(Effect.as(copilotInfo(credentials)));\n\t\t\t\t},\n\t\t\t\tstatus: (provider) =>\n\t\t\t\t\tprovider === \"openai-codex\"\n\t\t\t\t\t\t? optional(() => codex.storage.get(), codexInfo)\n\t\t\t\t\t\t: optional(() => copilot.storage.get(), copilotInfo),\n\t\t\t\t// GitHub OAuth tokens never expire, so a Copilot \"refresh\" is a read.\n\t\t\t\trefresh: (provider) =>\n\t\t\t\t\tprovider === \"openai-codex\"\n\t\t\t\t\t\t? optional(() => codex.getCredentials(), codexInfo)\n\t\t\t\t\t\t: optional(() => copilot.getCredentials(), copilotInfo),\n\t\t\t\tlogout: (provider) => attempt(() => (provider === \"openai-codex\" ? codex.logout() : copilot.logout())),\n\t\t\t});\n\t\t}),\n\t);\n\nexport * as OAuth from \"./oauth.ts\";\n","import { Model } from \"@codeworksh/aikit\";\nimport {\n\tControl,\n\tEvent,\n\tEventList,\n\tEventRegistry,\n\tEventSchema,\n\tModelCatalog,\n\tProject,\n\tPromptSchema,\n\tSandbox,\n\tSession,\n\tSessionStore,\n\tSettings,\n\tState,\n\tThreadSchema,\n\tThreadStore,\n} from \"@codeworksh/harness/effect\";\nimport { DateTime, Effect, Option, Stream } from \"effect\";\nimport {\n\tContract,\n\ttype HistoryEntry,\n\ttype LogSynced,\n\ttype RuntimeConfig,\n\ttype SandboxInfo,\n\ttype SessionInfo,\n\ttype ThreadInfo,\n} from \"./contract.ts\";\nimport { type EncodingError, Envelope, type EventEnvelope } from \"./envelope.ts\";\nimport { EventFeed } from \"./feed.ts\";\nimport { Identity } from \"./identity.ts\";\nimport { OAuth } from \"./oauth.ts\";\nimport { MessagePart } from \"./part.ts\";\n\nconst toSandboxInfo = (info: Sandbox.Info): SandboxInfo => ({\n\tid: info.id,\n\tdriver: info.driver,\n\tkind: info.kind,\n\tproviderResourceId: info.providerResourceId,\n\townership: info.ownership,\n\tstatus: info.status,\n\tusage: info.usage,\n\trefCount: info.refCount,\n\tcreatedAt: info.createdAt,\n\tupdatedAt: info.updatedAt,\n});\n\nconst toSessionInfo = (info: Session.Info): SessionInfo => ({\n\tid: info.id,\n\tdirectory: info.directory,\n\t...(info.hostDir === undefined ? {} : { hostDir: info.hostDir }),\n\t...(info.sandbox === undefined ? {} : { sandbox: toSandboxInfo(info.sandbox) }),\n\t...(info.project === undefined ? {} : { project: info.project }),\n\tupdatedAt: info.updatedAt,\n\tmainThreadId: info.mainThreadId,\n});\n\nconst toThreadInfo = (info: Session.ThreadInfo): ThreadInfo => ({\n\tid: info.id,\n\torigin: info.origin,\n\t...(info.title === undefined ? {} : { title: info.title }),\n\tupdatedAt: info.updatedAt,\n\t...(info.model === undefined ? {} : { model: info.model }),\n\t...(info.thinkingLevel === undefined ? {} : { thinkingLevel: info.thinkingLevel }),\n\t...(info.placement === undefined ? {} : { placement: info.placement }),\n\t...(info.parked ? { parked: true } : {}),\n\tusage: info.usage,\n\tsession: toSessionInfo(info.session),\n});\n\n// Wire configs name only the keys they set, so `undefined` never reaches the harness under\n// exactOptionalPropertyTypes. Creating takes choices only; `null` clears nothing there.\nconst runtimeInput = (runtime: RuntimeConfig | undefined): Session.RuntimeInput => ({\n\t...(runtime?.model == null ? {} : { model: runtime.model }),\n\t...(runtime?.thinkingLevel == null ? {} : { thinkingLevel: runtime.thinkingLevel }),\n});\n\nconst threadInfo = (threadId: ThreadSchema.ID) => Session.threadInfo(threadId).pipe(Effect.map(toThreadInfo));\n\n// RpcServer's request span has no level, so it is Debug and drops every Info span under it.\n// Provisioning a sandbox is worth exporting, so it starts a trace of its own.\nconst exported = <A, E, R>(name: string, self: Effect.Effect<A, E, R>) =>\n\tself.pipe(Effect.withSpan(name, { level: \"Info\", root: true }));\n\nconst releaseOnFailure = (selection: Effect.Success<ReturnType<typeof Sandbox.resolve>> | undefined) =>\n\tselection?.created && selection.info !== undefined\n\t\t? Sandbox.stop(selection.info.id).pipe(Effect.catchCause(Effect.logError))\n\t\t: Effect.void;\n\n/** A `session.log` item for the wire: a stored event as its envelope, or the replay marker. */\nconst toLogItem =\n\t(registry: Envelope.Registry) =>\n\t(item: Event.LogItem): Effect.Effect<EventEnvelope | LogSynced, EncodingError> =>\n\t\tEvent.isSynced(item)\n\t\t\t? Effect.succeed(item)\n\t\t\t: Envelope.encode(item, registry).pipe(\n\t\t\t\t\t// Every stored type is a kernel durable one, which the registry always knows.\n\t\t\t\t\tEffect.catchTag(\"UnknownEventTypeError\", Effect.die),\n\t\t\t\t);\n\nexport const layer = Contract.Api.toLayer(\n\tEffect.gen(function* () {\n\t\tconst control = yield* Control.Service;\n\t\tconst feed = yield* EventFeed.Service;\n\t\tconst sessions = yield* SessionStore.Service;\n\t\tconst threads = yield* ThreadStore.Service;\n\t\tconst resolve = (ref: Control.ThreadRef) =>\n\t\t\tcontrol.resolve(ref).pipe(Effect.map((thread) => ThreadSchema.ID.make(thread.id)));\n\t\tconst state = yield* State.Service;\n\t\tconst oauth = yield* OAuth.Service;\n\t\tconst identity = yield* Identity.Service;\n\t\tconst events = yield* Event.Service;\n\t\tconst registry = yield* EventRegistry.Service;\n\n\t\treturn Contract.Api.of({\n\t\t\t\"server.info\": () => Effect.succeed({ pid: identity.pid, version: identity.version }),\n\t\t\t\"auth.save\": ({ credentials }) => oauth.save(credentials),\n\t\t\t\"auth.status\": ({ provider }) => oauth.status(provider),\n\t\t\t\"auth.refresh\": ({ provider }) => oauth.refresh(provider),\n\t\t\t\"auth.logout\": ({ provider }) => oauth.logout(provider),\n\t\t\t\"session.create\": Effect.fnUntraced(function* ({ title, directory, hostDir, sandbox, runtime, project }) {\n\t\t\t\tconst selection =\n\t\t\t\t\tsandbox === undefined ? undefined : yield* exported(\"Server.session.create\", Sandbox.resolve(sandbox));\n\t\t\t\tconst selected = selection?.info;\n\t\t\t\tconst handle = yield* Session.create({\n\t\t\t\t\t...(title === undefined ? {} : { title }),\n\t\t\t\t\t...(directory === undefined ? {} : { directory }),\n\t\t\t\t\t// Passed through as given, never defaulted to the server's own directory: a\n\t\t\t\t\t// session the client did not place has no project, which is a normal state.\n\t\t\t\t\t...(hostDir === undefined ? {} : { hostDir }),\n\t\t\t\t\t...(selected === undefined ? {} : { sandbox: selected }),\n\t\t\t\t\t...(project === undefined ? {} : { project }),\n\t\t\t\t\t...runtimeInput(runtime),\n\t\t\t\t}).pipe(Effect.onError(() => releaseOnFailure(selection)));\n\t\t\t\treturn toThreadInfo(yield* handle.main.info);\n\t\t\t}),\n\t\t\t\"model.list\": Effect.fnUntraced(function* ({ hostDir }) {\n\t\t\t\tconst filter = hostDir === undefined ? {} : { hostDir };\n\t\t\t\tconst settings = yield* Settings.Service;\n\t\t\t\tconst loaded = yield* settings.load(hostDir);\n\t\t\t\tconst { model } = loaded;\n\t\t\t\tconst providers = yield* ModelCatalog.available(filter);\n\t\t\t\t// Named from the whole catalog, so a default without credentials still reads as itself.\n\t\t\t\tconst entry = (yield* ModelCatalog.effective(loaded.models))[model.provider]?.[model.id];\n\t\t\t\treturn {\n\t\t\t\t\tproviders: providers.flatMap((provider) => {\n\t\t\t\t\t\tconst models = Object.values(provider.models);\n\t\t\t\t\t\tconst first = models[0];\n\t\t\t\t\t\treturn first === undefined\n\t\t\t\t\t\t\t? []\n\t\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tid: provider.id,\n\t\t\t\t\t\t\t\t\t\tname: first.provider.name,\n\t\t\t\t\t\t\t\t\t\tmodels: models.map((info) => ({\n\t\t\t\t\t\t\t\t\t\t\tid: info.id,\n\t\t\t\t\t\t\t\t\t\t\tname: info.name,\n\t\t\t\t\t\t\t\t\t\t\tthinkingLevels: Model.getSupportedThinkingLevels(info),\n\t\t\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t];\n\t\t\t\t\t}),\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tprovider: model.provider,\n\t\t\t\t\t\tid: model.id,\n\t\t\t\t\t\tthinkingLevel: model.thinkingLevel,\n\t\t\t\t\t\t...(entry === undefined ? {} : { name: entry.name, providerName: entry.provider.name }),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}),\n\t\t\t\"project.rename\": Effect.fnUntraced(function* ({ projectId, name }) {\n\t\t\t\tconst renamed = yield* Project.rename({ projectId, name });\n\t\t\t\treturn { id: renamed.id, name: renamed.name };\n\t\t\t}),\n\t\t\t\"plugin.reload\": Effect.fnUntraced(function* () {\n\t\t\t\treturn yield* state.reload;\n\t\t\t}),\n\t\t\t\"session.link\": Effect.fnUntraced(function* ({ sessionId, hostDir }) {\n\t\t\t\tconst handle = yield* Session.link({ sessionId, hostDir: hostDir ?? null });\n\t\t\t\treturn toSessionInfo(yield* handle.info);\n\t\t\t}),\n\t\t\t\"session.relink\": Effect.fnUntraced(function* ({ sessionId, threadId, sandbox, directory }) {\n\t\t\t\tconst selection =\n\t\t\t\t\tsandbox === undefined ? undefined : yield* exported(\"Server.session.relink\", Sandbox.resolve(sandbox));\n\t\t\t\tconst selected = selection?.info;\n\t\t\t\tconst handle = yield* Session.relink({\n\t\t\t\t\tsessionId,\n\t\t\t\t\t...(threadId === undefined ? {} : { threadId }),\n\t\t\t\t\t...(selected === undefined ? {} : { sandbox: selected }),\n\t\t\t\t\t...(directory === undefined ? {} : { directory }),\n\t\t\t\t}).pipe(Effect.onError(() => releaseOnFailure(selection)));\n\t\t\t\tconst thread = yield* handle.thread(threadId ?? ThreadSchema.MAIN);\n\t\t\t\treturn toThreadInfo(yield* thread.info);\n\t\t\t}),\n\t\t\t\"session.delete\": Effect.fnUntraced(function* ({ sessionId }) {\n\t\t\t\treturn { deleted: yield* Session.remove(sessionId) };\n\t\t\t}),\n\t\t\t\"session.interrupt\": Effect.fnUntraced(function* ({ sessionId }) {\n\t\t\t\t// Ack only: the wire answers \"was there work to stop\", and the caller\n\t\t\t\t// uses `thread.wait` when it needs cleanup to have finished.\n\t\t\t\treturn { interrupted: yield* control.interruptSession(sessionId, { reason: \"user\" }) };\n\t\t\t}),\n\t\t\t\"session.log\": ({ sessionId, threadId, after, follow }) =>\n\t\t\t\tStream.unwrap(\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tif (Option.isNone(yield* sessions.get(sessionId))) {\n\t\t\t\t\t\t\treturn yield* new SessionStore.SessionNotFoundError({ sessionId });\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn events\n\t\t\t\t\t\t\t.log({\n\t\t\t\t\t\t\t\taggregateId: sessionId,\n\t\t\t\t\t\t\t\tfollow: follow ?? false,\n\t\t\t\t\t\t\t\t...(after === undefined ? {} : { after }),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.pipe(\n\t\t\t\t\t\t\t\tStream.filter(\n\t\t\t\t\t\t\t\t\t(item) =>\n\t\t\t\t\t\t\t\t\t\tthreadId === undefined || Event.isSynced(item) || Envelope.ofThread(threadId)(item),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tStream.mapEffect(toLogItem(registry.get)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\"thread.list\": Effect.fnUntraced(function* ({ sessionId }) {\n\t\t\t\tconst rows = yield* threads.list(sessionId);\n\t\t\t\treturn yield* Effect.forEach(rows, (row) => threadInfo(ThreadSchema.ID.make(row.id)).pipe(Effect.orDie));\n\t\t\t}),\n\t\t\t\"thread.info\": Effect.fnUntraced(function* (ref) {\n\t\t\t\treturn yield* threadInfo(yield* resolve(ref));\n\t\t\t}),\n\t\t\t\"thread.configure\": Effect.fnUntraced(function* ({ runtime, ...ref }) {\n\t\t\t\tconst threadId = yield* resolve(ref);\n\t\t\t\tconst change = {\n\t\t\t\t\t...(runtime.model === undefined ? {} : { model: runtime.model }),\n\t\t\t\t\t...(runtime.thinkingLevel === undefined ? {} : { thinkingLevel: runtime.thinkingLevel }),\n\t\t\t\t};\n\t\t\t\tif (Object.keys(change).length > 0) {\n\t\t\t\t\tyield* events.publish(EventList.ThreadConfigured, {\n\t\t\t\t\t\tsessionId: ref.sessionId,\n\t\t\t\t\t\tthreadId,\n\t\t\t\t\t\ttimestamp: yield* DateTime.now,\n\t\t\t\t\t\tchange,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn yield* threadInfo(threadId);\n\t\t\t}),\n\t\t\t\"thread.fork\": Effect.fnUntraced(function* ({ entryId, mode, ...ref }) {\n\t\t\t\tconst forked = yield* threads.fork({\n\t\t\t\t\tthreadId: yield* resolve(ref),\n\t\t\t\t\tentryId,\n\t\t\t\t\t...(mode === undefined ? {} : { mode }),\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tthread: yield* threadInfo(ThreadSchema.ID.make(forked.thread.id)),\n\t\t\t\t\t...(forked.text === undefined ? {} : { text: forked.text }),\n\t\t\t\t};\n\t\t\t}),\n\t\t\t\"thread.history\": Effect.fnUntraced(function* (ref) {\n\t\t\t\tconst line = yield* threads.line(yield* resolve(ref));\n\t\t\t\tconst entries = line.flatMap(({ entry, parts }): ReadonlyArray<HistoryEntry> =>\n\t\t\t\t\tentry.type === \"user\" || entry.type === \"assistant\"\n\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tid: entry.id,\n\t\t\t\t\t\t\t\t\tthreadId: entry.threadId,\n\t\t\t\t\t\t\t\t\tseq: entry.seq,\n\t\t\t\t\t\t\t\t\trole: entry.type,\n\t\t\t\t\t\t\t\t\tstate: entry.state,\n\t\t\t\t\t\t\t\t\tcreatedAt: DateTime.toEpochMillis(entry.createdAt),\n\t\t\t\t\t\t\t\t\tupdatedAt: DateTime.toEpochMillis(entry.updatedAt),\n\t\t\t\t\t\t\t\t\t// A part this schema does not render (a future aikit type) is skipped, not fatal.\n\t\t\t\t\t\t\t\t\tparts: parts.flatMap((part) => Option.toArray(MessagePart.decode(part.data))),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t: [],\n\t\t\t\t);\n\t\t\t\treturn { entries };\n\t\t\t}),\n\t\t\t\"thread.queue\": Effect.fnUntraced(function* (ref) {\n\t\t\t\tconst pending = yield* control.pending(yield* resolve(ref));\n\t\t\t\treturn {\n\t\t\t\t\tentries: pending.map((input) => ({\n\t\t\t\t\t\tid: input.id,\n\t\t\t\t\t\tdelivery: input.delivery,\n\t\t\t\t\t\ttext: PromptSchema.Prompt.text(input.prompt),\n\t\t\t\t\t\tcreatedAt: DateTime.toEpochMillis(input.timeCreated),\n\t\t\t\t\t})),\n\t\t\t\t};\n\t\t\t}),\n\t\t\t\"thread.prompt\": Effect.fnUntraced(function* ({ text, delivery, id, ...ref }) {\n\t\t\t\tconst admitted = yield* control.prompt({\n\t\t\t\t\t...ref,\n\t\t\t\t\tprompt: PromptSchema.Prompt.fromText(text),\n\t\t\t\t\t...(delivery === undefined ? {} : { delivery }),\n\t\t\t\t\t...(id === undefined ? {} : { id }),\n\t\t\t\t});\n\t\t\t\treturn { threadId: admitted.threadId };\n\t\t\t}),\n\t\t\t\"thread.interrupt\": Effect.fnUntraced(function* (ref) {\n\t\t\t\t// Ack only: the wire answers \"was there work to stop\", and the caller\n\t\t\t\t// uses `thread.wait` when it needs cleanup to have finished.\n\t\t\t\treturn { interrupted: yield* control.interrupt(yield* resolve(ref), { reason: \"user\" }) };\n\t\t\t}),\n\t\t\t\"thread.cancel\": Effect.fnUntraced(function* ({ messageId, ...ref }) {\n\t\t\t\treturn { cancelled: yield* control.cancel(yield* resolve(ref), messageId) };\n\t\t\t}),\n\t\t\t\"thread.update\": Effect.fnUntraced(function* ({ messageId, delivery, text, ...ref }) {\n\t\t\t\tconst updated = yield* control.update(yield* resolve(ref), messageId, {\n\t\t\t\t\t...(delivery === undefined ? {} : { delivery }),\n\t\t\t\t\t...(text === undefined ? {} : { prompt: PromptSchema.Prompt.fromText(text) }),\n\t\t\t\t});\n\t\t\t\treturn { updated };\n\t\t\t}),\n\t\t\t\"thread.message\": Effect.fnUntraced(function* ({ messageId, ...ref }) {\n\t\t\t\t// Scoped to the thread's line: an entry id is global, and a client should not learn\n\t\t\t\t// about conversations it did not ask for. An inherited prompt is in the thread's.\n\t\t\t\tconst line = yield* threads.line(yield* resolve(ref));\n\t\t\t\treturn { found: line.some(({ entry }) => entry.id === messageId) };\n\t\t\t}),\n\t\t\t\"thread.wait\": Effect.fnUntraced(function* (ref) {\n\t\t\t\tyield* control.wait(yield* resolve(ref));\n\t\t\t}),\n\t\t\t\"sandbox.drivers\": Effect.fnUntraced(function* () {\n\t\t\t\tconst drivers = yield* Sandbox.drivers();\n\t\t\t\treturn drivers.map(({ name, kind }) => ({ name, kind }));\n\t\t\t}),\n\t\t\t\"sandbox.list\": Effect.fnUntraced(function* () {\n\t\t\t\treturn (yield* Sandbox.list()).map(toSandboxInfo);\n\t\t\t}),\n\t\t\t\"sandbox.create\": Effect.fnUntraced(function* ({ driver }) {\n\t\t\t\treturn toSandboxInfo(yield* exported(\"Server.sandbox.create\", Sandbox.create({ driver })));\n\t\t\t}),\n\t\t\t\"sandbox.register\": Effect.fnUntraced(function* ({ driver, providerResourceId }) {\n\t\t\t\treturn toSandboxInfo(yield* Sandbox.register({ driver, providerResourceId }));\n\t\t\t}),\n\t\t\t\"sandbox.stop\": Effect.fnUntraced(function* ({ sandboxId }) {\n\t\t\t\tyield* Sandbox.stop(sandboxId);\n\t\t\t}),\n\t\t\t// Acquiring the feed subscription is the readiness barrier: `server.connected`\n\t\t\t// is only emitted once this client is registered, so a prompt admitted after\n\t\t\t// it cannot land in the gap.\n\t\t\t\"event.subscribe\": ({ threadId }) =>\n\t\t\t\tStream.unwrap(\n\t\t\t\t\tfeed.subscribe.pipe(\n\t\t\t\t\t\tEffect.map((events) =>\n\t\t\t\t\t\t\tStream.make({ id: EventSchema.ID.create(), type: Envelope.Connected.type, data: {} }).pipe(\n\t\t\t\t\t\t\t\tStream.concat(\n\t\t\t\t\t\t\t\t\tthreadId === undefined ? events : events.pipe(Stream.filter(Envelope.ofThread(threadId))),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t});\n\t}),\n);\n\nexport * as Handlers from \"./handlers.ts\";\n","import { Control, Global, Harness, Sandbox } from \"@codeworksh/harness/effect\";\nimport { NodeHttpServer } from \"@effect/platform-node\";\nimport { Effect, Layer } from \"effect\";\nimport { HttpRouter, HttpServer } from \"effect/http\";\nimport * as NetAddress from \"effect/net/NetAddress\";\nimport { RpcSerialization, RpcServer } from \"effect/rpc\";\n/* @effect-diagnostics nodeBuiltinImport:off -- the RPC listener needs a raw node server. */\nimport { createServer } from \"node:http\";\nimport { Contract } from \"./contract.ts\";\nimport { EventFeed } from \"./feed.ts\";\nimport { Handlers } from \"./handlers.ts\";\nimport { Identity } from \"./identity.ts\";\nimport { OAuth } from \"./oauth.ts\";\nimport { Registration } from \"./registration.ts\";\n\n// Managed instances outlive any single RPC; the serve scope is what stops them.\nconst managedShutdown = Layer.unwrap(\n\tEffect.gen(function* () {\n\t\tconst control = yield* Control.Service;\n\t\tyield* Effect.addFinalizer(() =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\t// Release drain leases before stopping the server's managed sandboxes.\n\t\t\t\t// Both phases are best effort and bounded so a provider cannot prevent\n\t\t\t\t// process shutdown; an interrupted stop is persisted as faulted and can\n\t\t\t\t// recover the next time that sandbox is mounted.\n\t\t\t\tyield* Effect.forEach(\n\t\t\t\t\tyield* control.active,\n\t\t\t\t\t(id) =>\n\t\t\t\t\t\tcontrol\n\t\t\t\t\t\t\t.interrupt(id, { reason: \"shutdown\", awaitSettlement: true })\n\t\t\t\t\t\t\t.pipe(Effect.timeout(\"10 seconds\"), Effect.ignore),\n\t\t\t\t\t{ concurrency: \"unbounded\", discard: true },\n\t\t\t\t);\n\t\t\t\tconst infos = yield* Sandbox.list();\n\t\t\t\tyield* Effect.forEach(\n\t\t\t\t\tinfos.filter((info) => info.ownership === \"managed\"),\n\t\t\t\t\t(info) =>\n\t\t\t\t\t\tSandbox.stop(info.id).pipe(\n\t\t\t\t\t\t\tEffect.timeout(\"10 seconds\"),\n\t\t\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\t\t\tEffect.logError(\"Failed to stop managed sandbox during shutdown\", cause).pipe(\n\t\t\t\t\t\t\t\t\tEffect.annotateLogs({ sandboxInstanceId: info.id }),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t{ concurrency: \"unbounded\", discard: true },\n\t\t\t\t);\n\t\t\t}),\n\t\t);\n\t\treturn Layer.empty;\n\t}),\n);\n\n/**\n * Resumes the runs the last server left unfinished, whether it crashed or shut down: the session\n * table records them as they start, so this needs nothing from the previous process.\n */\nconst resumeUnfinished = Layer.effectDiscard(\n\tEffect.gen(function* () {\n\t\tconst control = yield* Control.Service;\n\t\tyield* Effect.forkScoped(control.resumeUnfinished);\n\t}),\n);\n\n/**\n * Advertises the listener once it has an address: logs the endpoint and files\n * the registration later invocations discover it through.\n */\nconst announce = Layer.unwrap(\n\tEffect.gen(function* () {\n\t\tconst server = yield* HttpServer.HttpServer;\n\t\tconst global = yield* Global.Service;\n\t\tconst identity = yield* Identity.Service;\n\t\t// A ws server always binds TCP; the guard keeps the logger honest if that ever changes.\n\t\tconst address = server.address;\n\t\tconst url = `${NetAddress.formatUrlUnsafe(address, \"ws\")}${Contract.path}`;\n\t\tyield* Effect.log(`codework serve listening on ${url}`);\n\t\tif (!NetAddress.isInetAddress(address)) return Layer.empty;\n\t\treturn Registration.register({\n\t\t\thome: global.home,\n\t\t\tinfo: { pid: identity.pid, version: identity.version, url, port: address.port },\n\t\t});\n\t}),\n);\n\nexport const layer = (options: { host: string; port: number; harness: Harness.Options }) => {\n\tconst rpc = RpcServer.layerHttp({ group: Contract.Api, path: Contract.path, protocol: \"websocket\" }).pipe(\n\t\tLayer.provide(Handlers.layer.pipe(Layer.provide(EventFeed.layer))),\n\t);\n\tconst app = HttpRouter.serve(rpc, { disableListenLog: true }).pipe(\n\t\tLayer.provideMerge(managedShutdown),\n\t\tLayer.provideMerge(resumeUnfinished),\n\t\tLayer.provide(OAuth.layer(options.harness.home === undefined ? {} : { home: options.harness.home })),\n\t);\n\treturn app.pipe(\n\t\tLayer.provideMerge(announce),\n\t\tLayer.provideMerge(NodeHttpServer.layer(createServer, { host: options.host, port: options.port })),\n\t\tLayer.provide(RpcSerialization.layerNdjson),\n\t\tLayer.provide(Identity.layer),\n\t\tLayer.provide(Harness.layer(options.harness)),\n\t);\n};\n\nexport * as Server from \"./server.ts\";\n","import { Global } from \"@codeworksh/harness/effect\";\nimport { Effect, FileSystem, Layer, Logger } from \"effect\";\nimport { Runtime } from \"../../../framework/runtime.ts\";\nimport { Registration } from \"../../../server/registration.ts\";\nimport { Server } from \"../../../server/server.ts\";\nimport { renderError } from \"../../error.ts\";\nimport { harnessOptions } from \"../../harness.ts\";\nimport { writeError } from \"../../output.ts\";\nimport { Cmd } from \"../cmd.ts\";\n\nconst failed = Effect.sync(() => {\n\tprocess.exitCode = 1;\n});\n\nconst report = (error: unknown) => writeError(renderError(error)).pipe(Effect.andThen(failed));\n\nexport default Runtime.handler(\n\tCmd.commands.serve,\n\tEffect.fn(\"CLI.serve\", { level: \"Info\" })(function* ({ host, port, service }) {\n\t\tconst shared = yield* Cmd.spec;\n\t\tconst harness = { ...harnessOptions(shared), watchModels: true };\n\t\tconst serve = Layer.launch(Server.layer({ host, port, harness }));\n\t\tif (!service) return yield* serve.pipe(Effect.catch(report));\n\n\t\t// A background server has no terminal: its log, and the reason it stopped, go to a\n\t\t// file the CLI that started it reads back when startup fails.\n\t\tconst background = Effect.gen(function* () {\n\t\t\tconst paths = yield* Global.resolve(harness.home === undefined ? {} : { home: harness.home });\n\t\t\tconst fs = yield* FileSystem.FileSystem;\n\t\t\tyield* fs.makeDirectory(paths.log, { recursive: true });\n\t\t\tconst logger = Logger.formatSimple.pipe(Logger.toFile(Registration.log(paths.log), { flag: \"w\" }));\n\t\t\tyield* serve.pipe(\n\t\t\t\tEffect.catch((error) => Effect.logError(renderError(error).trim()).pipe(Effect.andThen(failed))),\n\t\t\t\tEffect.provide(Logger.layer([logger])),\n\t\t\t);\n\t\t});\n\t\tyield* background.pipe(Effect.catch(report));\n\t}),\n);\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as file, i as command, n as current, o as infoJson, s as log } from "./identity-
|
|
1
|
+
import { m as make, p as layer } from "./error-CSeYCa9R.mjs";
|
|
2
|
+
import { a as file, i as command, n as current, o as infoJson, s as log } from "./identity-CpsvMaTx.mjs";
|
|
3
3
|
import { Effect, FileSystem, Layer, Option, Ref, Schedule, Schema } from "effect";
|
|
4
4
|
import { Global } from "@codeworksh/harness/effect";
|
|
5
5
|
import { ChildProcess, ChildProcessSpawner } from "effect/process";
|
|
@@ -219,4 +219,4 @@ const options = (shared, server) => home(shared).pipe(Effect.map((paths) => ({
|
|
|
219
219
|
//#endregion
|
|
220
220
|
export { keepAlive as a, ensure as i, options as n, stop as o, discover as r, probe as s, home as t };
|
|
221
221
|
|
|
222
|
-
//# sourceMappingURL=service-
|
|
222
|
+
//# sourceMappingURL=service-D_vwPPPh.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-Cv-MLS-9.mjs","names":["Client.layer","Client.make","Registration.infoJson","Health.probe","Registration.file","log","Registration.log","Registration.command"],"sources":["../../src/server/health.ts","../../src/server/discovery.ts","../../src/cli/service.ts"],"sourcesContent":["import { Effect, Layer } from \"effect\";\nimport { Client } from \"./client.ts\";\n\n/**\n * One `server.info` call, with the answer normalized to `undefined` for every\n * way a server can fail to answer: unreachable, slow, or speaking a different\n * protocol. A health check that throws where it should say \"no\" would make\n * every caller wrap it in a catch.\n */\nexport const probe = (url: string) =>\n\tEffect.gen(function* () {\n\t\tconst context = yield* Layer.build(Client.layer(url)).pipe(Effect.orElseSucceed(() => undefined));\n\t\tif (context === undefined) return undefined;\n\t\treturn yield* Effect.gen(function* () {\n\t\t\tconst rpc = yield* Client.make;\n\t\t\treturn yield* rpc[\"server.info\"]({}).pipe(Effect.timeout(\"1 second\"));\n\t\t}).pipe(\n\t\t\tEffect.provideContext(context),\n\t\t\tEffect.orElseSucceed(() => undefined),\n\t\t);\n\t}).pipe(Effect.scoped);\n\nexport * as Health from \"./health.ts\";\n","import { type Duration, Effect, FileSystem, Option, Ref, Schedule, Schema } from \"effect\";\nimport { ChildProcess, ChildProcessSpawner } from \"effect/process\";\nimport { Health } from \"./health.ts\";\nimport { Identity } from \"./identity.ts\";\nimport { Registration } from \"./registration.ts\";\n\n/** A server a client can connect to, and the process and port behind it. */\nexport interface Endpoint {\n\treadonly url: string;\n\treadonly pid: number;\n\treadonly port: number;\n}\n\n/** A managed server could not be produced, in the words the CLI prints. */\nexport class ServerStartError extends Schema.TaggedError<ServerStartError>()(\"Discovery.ServerStartError\", {\n\tmessage: Schema.String,\n}) {}\n\nexport interface Options {\n\t/** The CodeWork home whose `service.json` names the server. */\n\treadonly home: string;\n\t/** The home's log directory, where a background server writes `server.log`. */\n\treadonly log: string;\n\treadonly host: string;\n\treadonly port: number;\n\t/** Server-owned flags placed before `serve`. */\n\treadonly args: ReadonlyArray<string>;\n}\n\nconst START_TIMEOUT = \"20 seconds\";\nconst RACE_GRACE = \"2 seconds\";\nconst STOP_TIMEOUT = \"5 seconds\";\n\nconst decode = Schema.decodeUnknownEffect(Registration.infoJson);\n\nconst read = (path: string) =>\n\tEffect.gen(function* () {\n\t\tconst fs = yield* FileSystem.FileSystem;\n\t\tconst text = yield* fs.readFileString(path).pipe(Effect.option);\n\t\tif (Option.isNone(text)) return undefined;\n\t\treturn yield* decode(text.value).pipe(Effect.option, Effect.map(Option.getOrUndefined));\n\t});\n\nconst remove = (path: string) =>\n\tEffect.gen(function* () {\n\t\tconst fs = yield* FileSystem.FileSystem;\n\t\tyield* fs.remove(path);\n\t}).pipe(Effect.ignore);\n\n/** Whether `pid` is a running process. EPERM means it exists but belongs to someone else. */\nconst alive = (pid: number) =>\n\tEffect.try({ try: () => process.kill(pid, 0), catch: (error) => (error as NodeJS.ErrnoException).code }).pipe(\n\t\tEffect.as(true),\n\t\tEffect.catch((code) => Effect.succeed(code === \"EPERM\")),\n\t);\n\n/** Whether `pid` exits within `timeout`. */\nconst exits = (pid: number, timeout: typeof STOP_TIMEOUT) =>\n\talive(pid).pipe(\n\t\tEffect.repeat({ while: (running) => running, schedule: Schedule.spaced(\"50 millis\") }),\n\t\tEffect.timeoutOption(timeout),\n\t\tEffect.map(Option.isSome),\n\t);\n\n/**\n * The registered server, with `live` set when the process answering its endpoint\n * is the one that registered. The file is a hint, never proof: a different server\n * on a reused port must not pass for it.\n */\nconst registered = (path: string) =>\n\tEffect.gen(function* () {\n\t\tconst info = yield* read(path);\n\t\tif (info === undefined) return undefined;\n\t\tconst live = yield* Health.probe(info.url);\n\t\treturn { info, live: live?.pid === info.pid ? live : undefined };\n\t});\n\nconst endpoint = (info: Registration.Info): Endpoint => ({ url: info.url, pid: info.pid, port: info.port });\n\n/** The running server registered for `home`, with the build it reports. */\nexport const discover = (home: string) =>\n\tregistered(Registration.file(home)).pipe(\n\t\tEffect.map((found) =>\n\t\t\tfound?.live === undefined ? undefined : { ...endpoint(found.info), version: found.live.version },\n\t\t),\n\t);\n\n/**\n * Stop the server registered for `home`, returning it, or undefined when none\n * answers. Only a server that confirms it is the registrant is signalled: a pid\n * on file may since have been reused by an unrelated process.\n */\nexport const stop = (home: string) =>\n\tEffect.gen(function* () {\n\t\tconst path = Registration.file(home);\n\t\tconst found = yield* registered(path);\n\t\tif (found === undefined) return undefined;\n\t\tif (found.live === undefined) {\n\t\t\tif (!(yield* alive(found.info.pid))) yield* remove(path);\n\t\t\treturn undefined;\n\t\t}\n\t\tyield* terminate(path, found.info.pid);\n\t\treturn endpoint(found.info);\n\t});\n\n/**\n * Ensure a healthy local server for `home`: reuse the registered one, replace it\n * when `replace` is set and it runs a different build, or start a background one.\n *\n * The background server is detached and outlives this caller, so the next\n * invocation reuses it. When two callers race, only the contender that binds the\n * port registers; the loser exits and both adopt the winner, because a caller\n * only ever believes a registration it can confirm over the wire.\n */\nexport const ensure = (\n\toptions: Options & {\n\t\treadonly replace: boolean;\n\t\treadonly onStart?: (reason: \"missing\" | \"version-mismatch\") => void;\n\t},\n) =>\n\tEffect.gen(function* () {\n\t\tconst path = Registration.file(options.home);\n\t\tconst found = yield* registered(path);\n\t\tif (found?.live !== undefined) {\n\t\t\tif (!options.replace || found.live.version === Identity.current.version) return endpoint(found.info);\n\t\t\tyield* Effect.sync(() => options.onStart?.(\"version-mismatch\"));\n\t\t\tyield* terminate(path, found.info.pid);\n\t\t} else {\n\t\t\t// A file nothing answers for, left by a crash, must not mislead the next caller.\n\t\t\tif (found !== undefined && !(yield* alive(found.info.pid))) yield* remove(path);\n\t\t\tyield* Effect.sync(() => options.onStart?.(\"missing\"));\n\t\t}\n\t\treturn yield* start(path, options);\n\t});\n\n/** The registered server once it answers, polled every 200ms for up to `timeout`. */\nconst ready = (path: string, timeout: Duration.Input, pending: Effect.Effect<boolean>) =>\n\tEffect.gen(function* () {\n\t\tconst next = yield* registered(path);\n\t\tif (next?.live !== undefined) return Option.some(endpoint(next.info));\n\t\t// A live registrant that does not answer yet is another caller's server starting up.\n\t\tconst waiting = (yield* pending) || (next !== undefined && (yield* alive(next.info.pid)));\n\t\treturn waiting ? Option.none() : yield* Effect.fail(\"exited\" as const);\n\t}).pipe(\n\t\tEffect.repeat({ until: Option.isSome, schedule: Schedule.spaced(\"200 millis\") }),\n\t\tEffect.timeoutOption(timeout),\n\t\tEffect.map(Option.flatten),\n\t\tEffect.orElseSucceed(() => Option.none<Endpoint>()),\n\t);\n\n/**\n * Start a background server and wait for it to register, quoting the reason\n * from its log when it cannot.\n *\n * The contender stays tied to this scope until it is the server adopted: a\n * timeout, an interrupt, or another caller winning the race stops it rather than\n * leaving an unmanaged server behind.\n */\nconst start = (path: string, options: Options) =>\n\tEffect.gen(function* () {\n\t\tconst contender = yield* spawn(options);\n\t\tconst won = yield* ready(path, START_TIMEOUT, contender.isRunning.pipe(Effect.orElseSucceed(() => false)));\n\t\t// A contender that lost the bind race exits before the winner may have filed its\n\t\t// registration; give the winner a moment before calling the start a failure.\n\t\tconst server = Option.isSome(won) ? won : yield* ready(path, RACE_GRACE, Effect.succeed(true));\n\t\tif (Option.isSome(server)) {\n\t\t\tif (server.value.pid === contender.pid) yield* contender.unref.pipe(Effect.asVoid);\n\t\t\treturn server.value;\n\t\t}\n\n\t\tconst log = Registration.log(options.log);\n\t\tconst reason = yield* lastLine(log);\n\t\treturn yield* new ServerStartError({\n\t\t\tmessage: [\n\t\t\t\t`could not start a CodeWork server on ${options.host}:${options.port}`,\n\t\t\t\t...(reason === undefined ? [] : [`reason: ${reason}`]),\n\t\t\t\t`log: ${log}`,\n\t\t\t\t\"hint: pass --port to use another port, or point `codework tui --server` at a running server\",\n\t\t\t].join(\"\\n\"),\n\t\t});\n\t}).pipe(Effect.scoped);\n\n/**\n * Keep the session's server running for as long as the caller lives.\n *\n * The TUI only reconnects; it cannot start a server. If the one it uses goes\n * away, this brings one back on the same port so the reconnect lands. It never\n * replaces a running server: another invocation may have just upgraded it.\n */\nexport const keepAlive = (initial: Endpoint, options: Options) =>\n\tEffect.gen(function* () {\n\t\tconst current = yield* Ref.make(initial);\n\t\tyield* Effect.gen(function* () {\n\t\t\tconst server = yield* Ref.get(current);\n\t\t\tif (yield* alive(server.pid)) return;\n\t\t\tconst next = yield* ensure({ ...options, port: server.port, replace: false }).pipe(\n\t\t\t\tEffect.orElseSucceed(() => server),\n\t\t\t);\n\t\t\tyield* Ref.set(current, next);\n\t\t}).pipe(Effect.repeat(Schedule.spaced(\"1 second\")));\n\t});\n\n/** Ask `pid` to shut down, escalating to SIGKILL, and retire its registration. */\nconst terminate = (path: string, pid: number) =>\n\tEffect.gen(function* () {\n\t\tconst signal = (name: NodeJS.Signals) => Effect.try(() => process.kill(pid, name)).pipe(Effect.ignore);\n\t\tyield* signal(\"SIGTERM\");\n\t\tif (!(yield* exits(pid, STOP_TIMEOUT))) {\n\t\t\tyield* signal(\"SIGKILL\");\n\t\t\tyield* exits(pid, STOP_TIMEOUT);\n\t\t}\n\t\t// A server removes its own file on a clean exit; this covers the SIGKILL path.\n\t\tconst info = yield* read(path);\n\t\tif (info?.pid === pid) yield* remove(path);\n\t});\n\nconst lastLine = (path: string) =>\n\tEffect.gen(function* () {\n\t\tconst fs = yield* FileSystem.FileSystem;\n\t\tconst text = yield* fs.readFileString(path).pipe(Effect.orElseSucceed(() => \"\"));\n\t\treturn text\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => line.trim())\n\t\t\t.findLast((line) => line.length > 0);\n\t});\n\n/**\n * Spawn `codework serve --service` detached, inheriting this environment so it\n * resolves the same home, catalog and credentials. It writes its own log, so no\n * stdio is tied to this short-lived caller. It stays referenced, and so stopped\n * with the scope, until `start` adopts it.\n */\nconst spawn = (options: Options) =>\n\tEffect.gen(function* () {\n\t\tconst [file, ...base] = Registration.command();\n\t\tif (file === undefined) return yield* Effect.die(new Error(\"could not resolve the codework entrypoint\"));\n\t\tconst spawner = yield* ChildProcessSpawner.ChildProcessSpawner;\n\t\tconst handle = yield* spawner.spawn(\n\t\t\tChildProcess.make(\n\t\t\t\tfile,\n\t\t\t\t[...base, ...options.args, \"serve\", \"--service\", \"--host\", options.host, \"--port\", String(options.port)],\n\t\t\t\t{ detached: true, stdin: \"ignore\", stdout: \"ignore\", stderr: \"ignore\" },\n\t\t\t),\n\t\t);\n\t\treturn handle;\n\t});\n\nexport * as Discovery from \"./discovery.ts\";\n","import { Global } from \"@codeworksh/harness/effect\";\nimport { Effect, Option } from \"effect\";\nimport type { Discovery } from \"../server/discovery.ts\";\n\ninterface Shared {\n\treadonly userConfigDir: Option.Option<string>;\n\treadonly home: Option.Option<string>;\n\treadonly database: Option.Option<string>;\n}\n\n/** The CodeWork home the shared flags name, resolved the way the harness resolves it. */\nexport const home = (shared: Shared) => Global.resolve(Option.isSome(shared.home) ? { home: shared.home.value } : {});\n\n/**\n * How `tui` and `service` find or start the background server: the home whose\n * `service.json` names it, and the server-owned flags it is started with, in the\n * order `serve` parses them.\n */\nexport const options = (shared: Shared, server: { readonly host: string; readonly port: number }) =>\n\thome(shared).pipe(\n\t\tEffect.map((paths): Discovery.Options => ({\n\t\t\thome: paths.home,\n\t\t\tlog: paths.log,\n\t\t\t...server,\n\t\t\targs: [\n\t\t\t\t...(Option.isSome(shared.home) ? [\"--home\", shared.home.value] : []),\n\t\t\t\t...(Option.isSome(shared.database) ? [\"--database\", shared.database.value] : []),\n\t\t\t\t...(Option.isSome(shared.userConfigDir) ? [\"--user-config-dir\", shared.userConfigDir.value] : []),\n\t\t\t],\n\t\t})),\n\t);\n\nexport * as Service from \"./service.ts\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service-D_vwPPPh.mjs","names":["Client.layer","Client.make","Registration.infoJson","Health.probe","Registration.file","log","Registration.log","Registration.command"],"sources":["../../src/server/health.ts","../../src/server/discovery.ts","../../src/cli/service.ts"],"sourcesContent":["import { Effect, Layer } from \"effect\";\nimport { Client } from \"./client.ts\";\n\n/**\n * One `server.info` call, with the answer normalized to `undefined` for every\n * way a server can fail to answer: unreachable, slow, or speaking a different\n * protocol. A health check that throws where it should say \"no\" would make\n * every caller wrap it in a catch.\n */\nexport const probe = (url: string) =>\n\tEffect.gen(function* () {\n\t\tconst context = yield* Layer.build(Client.layer(url)).pipe(Effect.orElseSucceed(() => undefined));\n\t\tif (context === undefined) return undefined;\n\t\treturn yield* Effect.gen(function* () {\n\t\t\tconst rpc = yield* Client.make;\n\t\t\treturn yield* rpc[\"server.info\"]({}).pipe(Effect.timeout(\"1 second\"));\n\t\t}).pipe(\n\t\t\tEffect.provideContext(context),\n\t\t\tEffect.orElseSucceed(() => undefined),\n\t\t);\n\t}).pipe(Effect.scoped);\n\nexport * as Health from \"./health.ts\";\n","import { type Duration, Effect, FileSystem, Option, Ref, Schedule, Schema } from \"effect\";\nimport { ChildProcess, ChildProcessSpawner } from \"effect/process\";\nimport { Health } from \"./health.ts\";\nimport { Identity } from \"./identity.ts\";\nimport { Registration } from \"./registration.ts\";\n\n/** A server a client can connect to, and the process and port behind it. */\nexport interface Endpoint {\n\treadonly url: string;\n\treadonly pid: number;\n\treadonly port: number;\n}\n\n/** A managed server could not be produced, in the words the CLI prints. */\nexport class ServerStartError extends Schema.TaggedError<ServerStartError>()(\"Discovery.ServerStartError\", {\n\tmessage: Schema.String,\n}) {}\n\nexport interface Options {\n\t/** The CodeWork home whose `service.json` names the server. */\n\treadonly home: string;\n\t/** The home's log directory, where a background server writes `server.log`. */\n\treadonly log: string;\n\treadonly host: string;\n\treadonly port: number;\n\t/** Server-owned flags placed before `serve`. */\n\treadonly args: ReadonlyArray<string>;\n}\n\nconst START_TIMEOUT = \"20 seconds\";\nconst RACE_GRACE = \"2 seconds\";\nconst STOP_TIMEOUT = \"5 seconds\";\n\nconst decode = Schema.decodeUnknownEffect(Registration.infoJson);\n\nconst read = (path: string) =>\n\tEffect.gen(function* () {\n\t\tconst fs = yield* FileSystem.FileSystem;\n\t\tconst text = yield* fs.readFileString(path).pipe(Effect.option);\n\t\tif (Option.isNone(text)) return undefined;\n\t\treturn yield* decode(text.value).pipe(Effect.option, Effect.map(Option.getOrUndefined));\n\t});\n\nconst remove = (path: string) =>\n\tEffect.gen(function* () {\n\t\tconst fs = yield* FileSystem.FileSystem;\n\t\tyield* fs.remove(path);\n\t}).pipe(Effect.ignore);\n\n/** Whether `pid` is a running process. EPERM means it exists but belongs to someone else. */\nconst alive = (pid: number) =>\n\tEffect.try({ try: () => process.kill(pid, 0), catch: (error) => (error as NodeJS.ErrnoException).code }).pipe(\n\t\tEffect.as(true),\n\t\tEffect.catch((code) => Effect.succeed(code === \"EPERM\")),\n\t);\n\n/** Whether `pid` exits within `timeout`. */\nconst exits = (pid: number, timeout: typeof STOP_TIMEOUT) =>\n\talive(pid).pipe(\n\t\tEffect.repeat({ while: (running) => running, schedule: Schedule.spaced(\"50 millis\") }),\n\t\tEffect.timeoutOption(timeout),\n\t\tEffect.map(Option.isSome),\n\t);\n\n/**\n * The registered server, with `live` set when the process answering its endpoint\n * is the one that registered. The file is a hint, never proof: a different server\n * on a reused port must not pass for it.\n */\nconst registered = (path: string) =>\n\tEffect.gen(function* () {\n\t\tconst info = yield* read(path);\n\t\tif (info === undefined) return undefined;\n\t\tconst live = yield* Health.probe(info.url);\n\t\treturn { info, live: live?.pid === info.pid ? live : undefined };\n\t});\n\nconst endpoint = (info: Registration.Info): Endpoint => ({ url: info.url, pid: info.pid, port: info.port });\n\n/** The running server registered for `home`, with the build it reports. */\nexport const discover = (home: string) =>\n\tregistered(Registration.file(home)).pipe(\n\t\tEffect.map((found) =>\n\t\t\tfound?.live === undefined ? undefined : { ...endpoint(found.info), version: found.live.version },\n\t\t),\n\t);\n\n/**\n * Stop the server registered for `home`, returning it, or undefined when none\n * answers. Only a server that confirms it is the registrant is signalled: a pid\n * on file may since have been reused by an unrelated process.\n */\nexport const stop = (home: string) =>\n\tEffect.gen(function* () {\n\t\tconst path = Registration.file(home);\n\t\tconst found = yield* registered(path);\n\t\tif (found === undefined) return undefined;\n\t\tif (found.live === undefined) {\n\t\t\tif (!(yield* alive(found.info.pid))) yield* remove(path);\n\t\t\treturn undefined;\n\t\t}\n\t\tyield* terminate(path, found.info.pid);\n\t\treturn endpoint(found.info);\n\t});\n\n/**\n * Ensure a healthy local server for `home`: reuse the registered one, replace it\n * when `replace` is set and it runs a different build, or start a background one.\n *\n * The background server is detached and outlives this caller, so the next\n * invocation reuses it. When two callers race, only the contender that binds the\n * port registers; the loser exits and both adopt the winner, because a caller\n * only ever believes a registration it can confirm over the wire.\n */\nexport const ensure = (\n\toptions: Options & {\n\t\treadonly replace: boolean;\n\t\treadonly onStart?: (reason: \"missing\" | \"version-mismatch\") => void;\n\t},\n) =>\n\tEffect.gen(function* () {\n\t\tconst path = Registration.file(options.home);\n\t\tconst found = yield* registered(path);\n\t\tif (found?.live !== undefined) {\n\t\t\tif (!options.replace || found.live.version === Identity.current.version) return endpoint(found.info);\n\t\t\tyield* Effect.sync(() => options.onStart?.(\"version-mismatch\"));\n\t\t\tyield* terminate(path, found.info.pid);\n\t\t} else {\n\t\t\t// A file nothing answers for, left by a crash, must not mislead the next caller.\n\t\t\tif (found !== undefined && !(yield* alive(found.info.pid))) yield* remove(path);\n\t\t\tyield* Effect.sync(() => options.onStart?.(\"missing\"));\n\t\t}\n\t\treturn yield* start(path, options);\n\t});\n\n/** The registered server once it answers, polled every 200ms for up to `timeout`. */\nconst ready = (path: string, timeout: Duration.Input, pending: Effect.Effect<boolean>) =>\n\tEffect.gen(function* () {\n\t\tconst next = yield* registered(path);\n\t\tif (next?.live !== undefined) return Option.some(endpoint(next.info));\n\t\t// A live registrant that does not answer yet is another caller's server starting up.\n\t\tconst waiting = (yield* pending) || (next !== undefined && (yield* alive(next.info.pid)));\n\t\treturn waiting ? Option.none() : yield* Effect.fail(\"exited\" as const);\n\t}).pipe(\n\t\tEffect.repeat({ until: Option.isSome, schedule: Schedule.spaced(\"200 millis\") }),\n\t\tEffect.timeoutOption(timeout),\n\t\tEffect.map(Option.flatten),\n\t\tEffect.orElseSucceed(() => Option.none<Endpoint>()),\n\t);\n\n/**\n * Start a background server and wait for it to register, quoting the reason\n * from its log when it cannot.\n *\n * The contender stays tied to this scope until it is the server adopted: a\n * timeout, an interrupt, or another caller winning the race stops it rather than\n * leaving an unmanaged server behind.\n */\nconst start = (path: string, options: Options) =>\n\tEffect.gen(function* () {\n\t\tconst contender = yield* spawn(options);\n\t\tconst won = yield* ready(path, START_TIMEOUT, contender.isRunning.pipe(Effect.orElseSucceed(() => false)));\n\t\t// A contender that lost the bind race exits before the winner may have filed its\n\t\t// registration; give the winner a moment before calling the start a failure.\n\t\tconst server = Option.isSome(won) ? won : yield* ready(path, RACE_GRACE, Effect.succeed(true));\n\t\tif (Option.isSome(server)) {\n\t\t\tif (server.value.pid === contender.pid) yield* contender.unref.pipe(Effect.asVoid);\n\t\t\treturn server.value;\n\t\t}\n\n\t\tconst log = Registration.log(options.log);\n\t\tconst reason = yield* lastLine(log);\n\t\treturn yield* new ServerStartError({\n\t\t\tmessage: [\n\t\t\t\t`could not start a CodeWork server on ${options.host}:${options.port}`,\n\t\t\t\t...(reason === undefined ? [] : [`reason: ${reason}`]),\n\t\t\t\t`log: ${log}`,\n\t\t\t\t\"hint: pass --port to use another port, or point `codework tui --server` at a running server\",\n\t\t\t].join(\"\\n\"),\n\t\t});\n\t}).pipe(Effect.scoped);\n\n/**\n * Keep the session's server running for as long as the caller lives.\n *\n * The TUI only reconnects; it cannot start a server. If the one it uses goes\n * away, this brings one back on the same port so the reconnect lands. It never\n * replaces a running server: another invocation may have just upgraded it.\n */\nexport const keepAlive = (initial: Endpoint, options: Options) =>\n\tEffect.gen(function* () {\n\t\tconst current = yield* Ref.make(initial);\n\t\tyield* Effect.gen(function* () {\n\t\t\tconst server = yield* Ref.get(current);\n\t\t\tif (yield* alive(server.pid)) return;\n\t\t\tconst next = yield* ensure({ ...options, port: server.port, replace: false }).pipe(\n\t\t\t\tEffect.orElseSucceed(() => server),\n\t\t\t);\n\t\t\tyield* Ref.set(current, next);\n\t\t}).pipe(Effect.repeat(Schedule.spaced(\"1 second\")));\n\t});\n\n/** Ask `pid` to shut down, escalating to SIGKILL, and retire its registration. */\nconst terminate = (path: string, pid: number) =>\n\tEffect.gen(function* () {\n\t\tconst signal = (name: NodeJS.Signals) => Effect.try(() => process.kill(pid, name)).pipe(Effect.ignore);\n\t\tyield* signal(\"SIGTERM\");\n\t\tif (!(yield* exits(pid, STOP_TIMEOUT))) {\n\t\t\tyield* signal(\"SIGKILL\");\n\t\t\tyield* exits(pid, STOP_TIMEOUT);\n\t\t}\n\t\t// A server removes its own file on a clean exit; this covers the SIGKILL path.\n\t\tconst info = yield* read(path);\n\t\tif (info?.pid === pid) yield* remove(path);\n\t});\n\nconst lastLine = (path: string) =>\n\tEffect.gen(function* () {\n\t\tconst fs = yield* FileSystem.FileSystem;\n\t\tconst text = yield* fs.readFileString(path).pipe(Effect.orElseSucceed(() => \"\"));\n\t\treturn text\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => line.trim())\n\t\t\t.findLast((line) => line.length > 0);\n\t});\n\n/**\n * Spawn `codework serve --service` detached, inheriting this environment so it\n * resolves the same home, catalog and credentials. It writes its own log, so no\n * stdio is tied to this short-lived caller. It stays referenced, and so stopped\n * with the scope, until `start` adopts it.\n */\nconst spawn = (options: Options) =>\n\tEffect.gen(function* () {\n\t\tconst [file, ...base] = Registration.command();\n\t\tif (file === undefined) return yield* Effect.die(new Error(\"could not resolve the codework entrypoint\"));\n\t\tconst spawner = yield* ChildProcessSpawner.ChildProcessSpawner;\n\t\tconst handle = yield* spawner.spawn(\n\t\t\tChildProcess.make(\n\t\t\t\tfile,\n\t\t\t\t[...base, ...options.args, \"serve\", \"--service\", \"--host\", options.host, \"--port\", String(options.port)],\n\t\t\t\t{ detached: true, stdin: \"ignore\", stdout: \"ignore\", stderr: \"ignore\" },\n\t\t\t),\n\t\t);\n\t\treturn handle;\n\t});\n\nexport * as Discovery from \"./discovery.ts\";\n","import { Global } from \"@codeworksh/harness/effect\";\nimport { Effect, Option } from \"effect\";\nimport type { Discovery } from \"../server/discovery.ts\";\n\ninterface Shared {\n\treadonly userConfigDir: Option.Option<string>;\n\treadonly home: Option.Option<string>;\n\treadonly database: Option.Option<string>;\n}\n\n/** The CodeWork home the shared flags name, resolved the way the harness resolves it. */\nexport const home = (shared: Shared) => Global.resolve(Option.isSome(shared.home) ? { home: shared.home.value } : {});\n\n/**\n * How `tui` and `service` find or start the background server: the home whose\n * `service.json` names it, and the server-owned flags it is started with, in the\n * order `serve` parses them.\n */\nexport const options = (shared: Shared, server: { readonly host: string; readonly port: number }) =>\n\thome(shared).pipe(\n\t\tEffect.map((paths): Discovery.Options => ({\n\t\t\thome: paths.home,\n\t\t\tlog: paths.log,\n\t\t\t...server,\n\t\t\targs: [\n\t\t\t\t...(Option.isSome(shared.home) ? [\"--home\", shared.home.value] : []),\n\t\t\t\t...(Option.isSome(shared.database) ? [\"--database\", shared.database.value] : []),\n\t\t\t\t...(Option.isSome(shared.userConfigDir) ? [\"--user-config-dir\", shared.userConfigDir.value] : []),\n\t\t\t],\n\t\t})),\n\t);\n\nexport * as Service from \"./service.ts\";\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as InvalidInputError } from "./error-
|
|
1
|
+
import { t as InvalidInputError } from "./error-CSeYCa9R.mjs";
|
|
2
2
|
import { Effect, FileSystem, Option, Path } from "effect";
|
|
3
3
|
import { Global, Plugin, Settings } from "@codeworksh/harness/effect";
|
|
4
4
|
import { applyEdits, modify, parse } from "jsonc-parser";
|
|
@@ -218,4 +218,4 @@ const resolveTarget = Effect.fn("CLI.plugin.resolveTarget")(function* (shared, g
|
|
|
218
218
|
//#endregion
|
|
219
219
|
export { resolveTarget as a, withPluginsLock as c, readPlugins as i, writePlugins as l, matches as n, spellings as o, matching as r, userLayer as s, identify as t, written as u };
|
|
220
220
|
|
|
221
|
-
//# sourceMappingURL=settings-
|
|
221
|
+
//# sourceMappingURL=settings-DcwstDUm.mjs.map
|