@codeworksh/cli 0.0.1-dev.20260925125202 → 0.0.1-dev.20260925163815
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/{add-CIQSfxan.mjs → add-BPuCxrRi.mjs} +12 -11
- package/add-BPuCxrRi.mjs.map +1 -0
- package/{catalog-C5fDCgtx.mjs → catalog-DyQXd30n.mjs} +4 -4
- package/catalog-DyQXd30n.mjs.map +1 -0
- package/{check-B7bP5lRI.mjs → check-CKi11Mtm.mjs} +5 -4
- package/check-CKi11Mtm.mjs.map +1 -0
- package/{entries-CSY5N6jH.mjs → entries-BXBULTVt.mjs} +15 -14
- package/entries-BXBULTVt.mjs.map +1 -0
- package/error-CxoEKg-4.mjs +610 -0
- package/error-CxoEKg-4.mjs.map +1 -0
- package/{harness-DXAwGk0B.mjs → harness-6d8TlAVk.mjs} +4 -3
- package/harness-6d8TlAVk.mjs.map +1 -0
- package/index.mjs +17 -17
- package/{install-B02SIXwF.mjs → install-C2QXwvU6.mjs} +6 -5
- package/install-C2QXwvU6.mjs.map +1 -0
- package/{link-CA9XdPwj.mjs → link-D5uOUo0m.mjs} +5 -4
- package/{link-CA9XdPwj.mjs.map → link-D5uOUo0m.mjs.map} +1 -1
- package/{list-Bbo4XnG_.mjs → list-B7wmE2Hz.mjs} +10 -9
- package/list-B7wmE2Hz.mjs.map +1 -0
- package/{list-Ce1Ry4JN.mjs → list-CEDVgkex.mjs} +5 -4
- package/list-CEDVgkex.mjs.map +1 -0
- package/{login-CagARGqW.mjs → login-DD5n0PHg.mjs} +3 -3
- package/{login-CagARGqW.mjs.map → login-DD5n0PHg.mjs.map} +1 -1
- package/{logout-CYYtjZL3.mjs → logout--lzv9ftF.mjs} +3 -3
- package/{logout-CYYtjZL3.mjs.map → logout--lzv9ftF.mjs.map} +1 -1
- package/package.json +7 -33
- package/{providers-CoYj1SYv.mjs → providers-CO0ERtiv.mjs} +5 -4
- package/providers-CO0ERtiv.mjs.map +1 -0
- package/{refresh-D2a1ikea.mjs → refresh-BcI6iAiQ.mjs} +5 -4
- package/refresh-BcI6iAiQ.mjs.map +1 -0
- package/{refresh-8_nfeYNZ.mjs → refresh-DKBOk5RX.mjs} +3 -3
- package/{refresh-8_nfeYNZ.mjs.map → refresh-DKBOk5RX.mjs.map} +1 -1
- package/{reload-C5ysPM58.mjs → reload-L4NyTZaU.mjs} +2 -2
- package/{reload-C5ysPM58.mjs.map → reload-L4NyTZaU.mjs.map} +1 -1
- package/{remove-BkbspSED.mjs → remove-CpLi76Ah.mjs} +5 -4
- package/remove-CpLi76Ah.mjs.map +1 -0
- package/{run-CnxjZIGy.mjs → run-D7h83L_m.mjs} +16 -15
- package/run-D7h83L_m.mjs.map +1 -0
- package/{serve-DaD7Eijz.mjs → serve-BGrH_Wr6.mjs} +34 -33
- package/serve-BGrH_Wr6.mjs.map +1 -0
- package/{settings-BZXmb54m.mjs → settings-aqM_b9UE.mjs} +12 -11
- package/settings-aqM_b9UE.mjs.map +1 -0
- package/{shared-BaTfajJ2.mjs → shared-IycfDUnF.mjs} +4 -3
- package/shared-IycfDUnF.mjs.map +1 -0
- package/{status-qJImmv6V.mjs → status-CCj71RVv.mjs} +3 -3
- package/{status-qJImmv6V.mjs.map → status-CCj71RVv.mjs.map} +1 -1
- package/{update-CxcNv_t0.mjs → update-C-RdaEiC.mjs} +6 -5
- package/update-C-RdaEiC.mjs.map +1 -0
- package/add-CIQSfxan.mjs.map +0 -1
- package/catalog-C5fDCgtx.mjs.map +0 -1
- package/check-B7bP5lRI.mjs.map +0 -1
- package/entries-CSY5N6jH.mjs.map +0 -1
- package/error-D0C5K2Av.mjs +0 -10376
- package/error-D0C5K2Av.mjs.map +0 -1
- package/harness-DXAwGk0B.mjs.map +0 -1
- package/index.d.mts +0 -24
- package/install-B02SIXwF.mjs.map +0 -1
- package/list-Bbo4XnG_.mjs.map +0 -1
- package/list-Ce1Ry4JN.mjs.map +0 -1
- package/providers-CoYj1SYv.mjs.map +0 -1
- package/refresh-D2a1ikea.mjs.map +0 -1
- package/remove-BkbspSED.mjs.map +0 -1
- package/run-CnxjZIGy.mjs.map +0 -1
- package/serve-DaD7Eijz.mjs.map +0 -1
- package/settings-BZXmb54m.mjs.map +0 -1
- package/shared-BaTfajJ2.mjs.map +0 -1
- package/update-CxcNv_t0.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh-
|
|
1
|
+
{"version":3,"file":"refresh-DKBOk5RX.mjs","names":["Runtime.handler","Client.make"],"sources":["../../src/cli/cmd/handlers/auth/refresh.ts"],"sourcesContent":["import { formatOAuthSummary, oauthNotice, oauthRefreshIssue } from \"@codeworksh/aikit/oauth/summary\";\nimport { Effect, Option } from \"effect\";\nimport { Runtime } from \"../../../../framework/runtime.ts\";\nimport { InvalidInputError, OAuthError, reportFailure } from \"../../../error.ts\";\nimport { writeError, writeOut } from \"../../../output.ts\";\nimport { Cmd } from \"../../cmd.ts\";\nimport {\n\tassertServerScope,\n\tattempt,\n\tClient,\n\tlocalOps,\n\toauthProviderLabel,\n\tselectProvider,\n\twithServer,\n} from \"./shared.ts\";\n\nexport default Runtime.handler(\n\tCmd.commands.auth.commands.refresh,\n\tEffect.fn(\"CLI.auth.refresh\")(function* ({ server, openaiCodex, githubCopilot, authFile, json }) {\n\t\tconst program = Effect.gen(function* () {\n\t\t\tconst provider = yield* selectProvider({ openaiCodex, githubCopilot });\n\t\t\tconst blocked = oauthRefreshIssue(provider);\n\t\t\tif (blocked !== undefined) return yield* new InvalidInputError({ message: blocked });\n\n\t\t\tconst name = oauthProviderLabel(provider);\n\n\t\t\tif (Option.isSome(server)) {\n\t\t\t\tyield* assertServerScope(authFile);\n\t\t\t\treturn yield* withServer(\n\t\t\t\t\tserver.value,\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tconst rpc = yield* Client.make;\n\t\t\t\t\t\tconst info = yield* rpc[\"auth.refresh\"]({ provider });\n\t\t\t\t\t\tif (info === null) {\n\t\t\t\t\t\t\treturn yield* new OAuthError({ message: oauthNotice(\"missing\", provider, \"the server\") });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tyield* writeError(`${oauthNotice(\"refreshed\", provider, \"the server\")}\\n`);\n\t\t\t\t\t\tyield* writeOut(formatOAuthSummary(info, { json }));\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst ops = yield* localOps(provider, authFile);\n\t\t\tconst summary = yield* attempt(`failed to read ${name} credentials`, () => ops.refreshed());\n\t\t\tif (summary === undefined) {\n\t\t\t\treturn yield* new OAuthError({ message: oauthNotice(\"missing\", provider, ops.path) });\n\t\t\t}\n\t\t\tyield* writeError(`${oauthNotice(\"refreshed\", provider, ops.path)}\\n`);\n\t\t\tyield* writeOut(formatOAuthSummary(summary, { json }));\n\t\t});\n\n\t\treturn yield* program.pipe(Effect.catch(reportFailure));\n\t}),\n);\n"],"mappings":";;;;;;AAgBA,IAAA,kBAAeA,QACd,IAAI,SAAS,KAAK,SAAS,SAC3B,OAAO,GAAG,kBAAkB,CAAC,CAAC,WAAW,EAAE,QAAQ,aAAa,eAAe,UAAU,QAAQ;CAiChG,OAAO,OAhCS,OAAO,IAAI,aAAa;EACvC,MAAM,WAAW,OAAO,eAAe;GAAE;GAAa;EAAc,CAAC;EACrE,MAAM,UAAU,kBAAkB,QAAQ;EAC1C,IAAI,YAAY,KAAA,GAAW,OAAO,OAAO,IAAI,kBAAkB,EAAE,SAAS,QAAQ,CAAC;EAEnF,MAAM,OAAO,mBAAmB,QAAQ;EAExC,IAAI,OAAO,OAAO,MAAM,GAAG;GAC1B,OAAO,kBAAkB,QAAQ;GACjC,OAAO,OAAO,WACb,OAAO,OACP,OAAO,IAAI,aAAa;IAEvB,MAAM,OAAO,QAAO,OADDC,KAAAA,CACK,eAAe,CAAC,EAAE,SAAS,CAAC;IACpD,IAAI,SAAS,MACZ,OAAO,OAAO,IAAI,WAAW,EAAE,SAAS,YAAY,WAAW,UAAU,YAAY,EAAE,CAAC;IAEzF,OAAO,WAAW,GAAG,YAAY,aAAa,UAAU,YAAY,EAAE,GAAG;IACzE,OAAO,SAAS,mBAAmB,MAAM,EAAE,KAAK,CAAC,CAAC;GACnD,CAAC,CACF;EACD;EAEA,MAAM,MAAM,OAAO,SAAS,UAAU,QAAQ;EAC9C,MAAM,UAAU,OAAO,QAAQ,kBAAkB,KAAK,qBAAqB,IAAI,UAAU,CAAC;EAC1F,IAAI,YAAY,KAAA,GACf,OAAO,OAAO,IAAI,WAAW,EAAE,SAAS,YAAY,WAAW,UAAU,IAAI,IAAI,EAAE,CAAC;EAErF,OAAO,WAAW,GAAG,YAAY,aAAa,UAAU,IAAI,IAAI,EAAE,GAAG;EACrE,OAAO,SAAS,mBAAmB,SAAS,EAAE,KAAK,CAAC,CAAC;CACtD,CAEoB,CAAC,CAAC,KAAK,OAAO,MAAM,aAAa,CAAC;AACvD,CAAC,CACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as writeOut, f as layer, i as reportFailure, p as make } from "./error-D0C5K2Av.mjs";
|
|
2
1
|
import { i as Cmd, t as handler } from "./runtime-B3dlWGfs.mjs";
|
|
2
|
+
import { d as writeOut, f as layer, i as reportFailure, p as make } from "./error-CxoEKg-4.mjs";
|
|
3
3
|
import { Effect } from "effect";
|
|
4
4
|
//#region src/cli/cmd/handlers/plugin/reload.ts
|
|
5
5
|
/**
|
|
@@ -23,4 +23,4 @@ var reload_default = handler(Cmd.commands.plugin.commands.reload, Effect.fn("CLI
|
|
|
23
23
|
//#endregion
|
|
24
24
|
export { reload_default as default };
|
|
25
25
|
|
|
26
|
-
//# sourceMappingURL=reload-
|
|
26
|
+
//# sourceMappingURL=reload-L4NyTZaU.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reload-
|
|
1
|
+
{"version":3,"file":"reload-L4NyTZaU.mjs","names":["Runtime.handler","Client.make","Client.layer"],"sources":["../../src/cli/cmd/handlers/plugin/reload.ts"],"sourcesContent":["import { Effect } from \"effect\";\nimport { Runtime } from \"../../../../framework/runtime.ts\";\nimport { reportFailure } from \"../../../error.ts\";\nimport { writeOut } from \"../../../output.ts\";\nimport { Client } from \"../../../../server/client.ts\";\nimport { Cmd } from \"../../cmd.ts\";\n\n/**\n * Re-import every configured plugin in a running server.\n *\n * It exists for exactly one case: a **local** plugin edited in place. Nothing in settings changed\n * and no generation moved -- a local source is never copied into the store, so it has none -- and\n * the module registry holds the old module against an unchanged URL. Everything else the runtime\n * notices for itself at the next exchange.\n *\n * There is no local form, and that is not an omission. In a CLI every run is a fresh process, so\n * the load pass happens at startup and a reload would have nothing to do.\n */\nexport default Runtime.handler(\n\tCmd.commands.plugin.commands.reload,\n\tEffect.fn(\"CLI.plugin.reload\")(function* ({ server }) {\n\t\tconst program = Effect.gen(function* () {\n\t\t\tconst rpc = yield* Client.make;\n\t\t\tconst result = yield* rpc[\"plugin.reload\"]({});\n\t\t\t// A reload that failed still reports the set that stayed loaded: the server kept\n\t\t\t// working, which is the whole point of not failing it.\n\t\t\tyield* writeOut(\n\t\t\t\tresult.failure === undefined\n\t\t\t\t\t? `Reloaded ${result.plugins} plugin${result.plugins === 1 ? \"\" : \"s\"}.\\n`\n\t\t\t\t\t: `Reload failed, keeping ${result.plugins} loaded: ${result.failure}\\n`,\n\t\t\t);\n\t\t\tif (result.failure !== undefined) process.exitCode = 1;\n\t\t});\n\n\t\treturn yield* program.pipe(Effect.provide(Client.layer(server)), Effect.scoped, Effect.catch(reportFailure));\n\t}),\n);\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,IAAA,iBAAeA,QACd,IAAI,SAAS,OAAO,SAAS,QAC7B,OAAO,GAAG,mBAAmB,CAAC,CAAC,WAAW,EAAE,UAAU;CAcrD,OAAO,OAbS,OAAO,IAAI,aAAa;EAEvC,MAAM,SAAS,QAAO,OADHC,KAAAA,CACO,gBAAgB,CAAC,CAAC,CAAC;EAG7C,OAAO,SACN,OAAO,YAAY,KAAA,IAChB,YAAY,OAAO,QAAQ,SAAS,OAAO,YAAY,IAAI,KAAK,IAAI,OACpE,0BAA0B,OAAO,QAAQ,WAAW,OAAO,QAAQ,GACvE;EACA,IAAI,OAAO,YAAY,KAAA,GAAW,QAAQ,WAAW;CACtD,CAEoB,CAAC,CAAC,KAAK,OAAO,QAAQC,MAAa,MAAM,CAAC,GAAG,OAAO,QAAQ,OAAO,MAAM,aAAa,CAAC;AAC5G,CAAC,CACF"}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { Et as resolve, d as writeOut, i as reportFailure } from "./error-D0C5K2Av.mjs";
|
|
2
1
|
import { i as Cmd, t as handler } from "./runtime-B3dlWGfs.mjs";
|
|
3
|
-
import {
|
|
2
|
+
import { d as writeOut, i as reportFailure } from "./error-CxoEKg-4.mjs";
|
|
3
|
+
import { a as resolveTarget, c as withPluginsLock, i as readPlugins, l as writePlugins, o as spellings, r as matching, t as identify } from "./settings-aqM_b9UE.mjs";
|
|
4
4
|
import { Effect, FileSystem, Option, Path } from "effect";
|
|
5
|
+
import { Global } from "@codeworksh/harness/effect";
|
|
5
6
|
//#region src/cli/cmd/handlers/plugin/remove.ts
|
|
6
7
|
var remove_default = handler(Cmd.commands.plugin.commands.remove, Effect.fn("CLI.plugin.remove")(function* ({ package: reference, global: userWide }) {
|
|
7
8
|
return yield* Effect.gen(function* () {
|
|
8
9
|
const shared = yield* Cmd.spec;
|
|
9
10
|
const path = yield* Path.Path;
|
|
10
11
|
const fs = yield* FileSystem.FileSystem;
|
|
11
|
-
const paths = yield* resolve(Option.isNone(shared.home) ? {} : { home: shared.home.value });
|
|
12
|
+
const paths = yield* Global.resolve(Option.isNone(shared.home) ? {} : { home: shared.home.value });
|
|
12
13
|
const target = yield* resolveTarget(shared, userWide, void 0, false);
|
|
13
14
|
if (!(yield* fs.exists(path.dirname(target.path)))) {
|
|
14
15
|
yield* writeOut(`Plugin "${reference}" is not configured in ${target.path}\n`);
|
|
@@ -33,4 +34,4 @@ var remove_default = handler(Cmd.commands.plugin.commands.remove, Effect.fn("CLI
|
|
|
33
34
|
//#endregion
|
|
34
35
|
export { remove_default as default };
|
|
35
36
|
|
|
36
|
-
//# sourceMappingURL=remove-
|
|
37
|
+
//# sourceMappingURL=remove-CpLi76Ah.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remove-CpLi76Ah.mjs","names":["Runtime.handler"],"sources":["../../src/cli/cmd/handlers/plugin/remove.ts"],"sourcesContent":["import { Global } from \"@codeworksh/harness/effect\";\nimport { Effect, FileSystem, Option, Path } from \"effect\";\nimport { Runtime } from \"../../../../framework/runtime.ts\";\nimport { reportFailure } from \"../../../error.ts\";\nimport { writeOut } from \"../../../output.ts\";\nimport { Cmd } from \"../../cmd.ts\";\nimport {\n\tidentify,\n\tmatching,\n\treadPlugins,\n\tresolveTarget,\n\tspellings,\n\twithPluginsLock,\n\twritePlugins,\n} from \"./settings.ts\";\n\nexport default Runtime.handler(\n\tCmd.commands.plugin.commands.remove,\n\tEffect.fn(\"CLI.plugin.remove\")(function* ({ package: reference, global: userWide }) {\n\t\tconst program = Effect.gen(function* () {\n\t\t\tconst shared = yield* Cmd.spec;\n\t\t\tconst path = yield* Path.Path;\n\t\t\tconst fs = yield* FileSystem.FileSystem;\n\t\t\tconst paths = yield* Global.resolve(Option.isNone(shared.home) ? {} : { home: shared.home.value });\n\t\t\tconst target = yield* resolveTarget(shared, userWide, undefined, false);\n\t\t\t// Removing from a directory that is not a project is a read-only no-op. In particular, it\n\t\t\t// must not create the marker that would make this directory shadow a real project later.\n\t\t\tif (!(yield* fs.exists(path.dirname(target.path)))) {\n\t\t\t\tyield* writeOut(`Plugin \"${reference}\" is not configured in ${target.path}\\n`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst spelled = yield* spellings(reference, path.resolve(\".\"));\n\t\t\tyield* withPluginsLock(\n\t\t\t\ttarget.path,\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst { source, plugins } = yield* readPlugins(target.path);\n\t\t\t\t\t// Both the module entry and any configuration written against it: the package it was\n\t\t\t\t\t// added as, the path or version it was written with, and the ID it declares all name\n\t\t\t\t\t// the one plugin being removed.\n\t\t\t\t\tconst entries = yield* identify(plugins, target.path, paths.cache);\n\t\t\t\t\tconst selected = matching(entries, spelled);\n\t\t\t\t\tconst kept = entries.filter((entry) => !selected.has(entry)).map((entry) => entry.value);\n\t\t\t\t\tif (kept.length === plugins.length) {\n\t\t\t\t\t\tyield* writeOut(`Plugin \"${reference}\" is not configured in ${target.path}\\n`);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tyield* writePlugins(target.path, source, kept);\n\t\t\t\t\tconst dropped = plugins.length - kept.length;\n\t\t\t\t\tyield* writeOut(\n\t\t\t\t\t\t`Removed ${dropped} ${dropped === 1 ? \"entry\" : \"entries\"} for \"${reference}\" from ${target.path}\\n`,\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t);\n\t\t});\n\n\t\treturn yield* program.pipe(Effect.catch(reportFailure));\n\t}),\n);\n"],"mappings":";;;;;;AAgBA,IAAA,iBAAeA,QACd,IAAI,SAAS,OAAO,SAAS,QAC7B,OAAO,GAAG,mBAAmB,CAAC,CAAC,WAAW,EAAE,SAAS,WAAW,QAAQ,YAAY;CAqCnF,OAAO,OApCS,OAAO,IAAI,aAAa;EACvC,MAAM,SAAS,OAAO,IAAI;EAC1B,MAAM,OAAO,OAAO,KAAK;EACzB,MAAM,KAAK,OAAO,WAAW;EAC7B,MAAM,QAAQ,OAAO,OAAO,QAAQ,OAAO,OAAO,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,MAAM,OAAO,KAAK,MAAM,CAAC;EACjG,MAAM,SAAS,OAAO,cAAc,QAAQ,UAAU,KAAA,GAAW,KAAK;EAGtE,IAAI,EAAE,OAAO,GAAG,OAAO,KAAK,QAAQ,OAAO,IAAI,CAAC,IAAI;GACnD,OAAO,SAAS,WAAW,UAAU,yBAAyB,OAAO,KAAK,GAAG;GAC7E;EACD;EACA,MAAM,UAAU,OAAO,UAAU,WAAW,KAAK,QAAQ,GAAG,CAAC;EAC7D,OAAO,gBACN,OAAO,MACP,OAAO,IAAI,aAAa;GACvB,MAAM,EAAE,QAAQ,YAAY,OAAO,YAAY,OAAO,IAAI;GAI1D,MAAM,UAAU,OAAO,SAAS,SAAS,OAAO,MAAM,MAAM,KAAK;GACjE,MAAM,WAAW,SAAS,SAAS,OAAO;GAC1C,MAAM,OAAO,QAAQ,QAAQ,UAAU,CAAC,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,UAAU,MAAM,KAAK;GACvF,IAAI,KAAK,WAAW,QAAQ,QAAQ;IACnC,OAAO,SAAS,WAAW,UAAU,yBAAyB,OAAO,KAAK,GAAG;IAC7E;GACD;GACA,OAAO,aAAa,OAAO,MAAM,QAAQ,IAAI;GAC7C,MAAM,UAAU,QAAQ,SAAS,KAAK;GACtC,OAAO,SACN,WAAW,QAAQ,GAAG,YAAY,IAAI,UAAU,UAAU,QAAQ,UAAU,SAAS,OAAO,KAAK,GAClG;EACD,CAAC,CACF;CACD,CAEoB,CAAC,CAAC,KAAK,OAAO,MAAM,aAAa,CAAC;AACvD,CAAC,CACF"}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import { A as stop, Dt as ID, Ot as schema_exports, _t as LLMTextDelta, a as addUsage, b as attach, bt as instance_exports, c as terminalColumns, d as writeOut, f as layer, gt as LLMEnded, j as layer$1, k as resolve, l as usage, m as run, o as emptyUsage, p as make, r as renderError, s as header, t as InvalidInputError, u as writeError, vt as TurnEnded, x as create } from "./error-D0C5K2Av.mjs";
|
|
2
1
|
import { i as Cmd, t as handler } from "./runtime-B3dlWGfs.mjs";
|
|
3
|
-
import { t as
|
|
2
|
+
import { a as addUsage, c as terminalColumns, d as writeOut, f as layer, l as usage, m as run, o as emptyUsage, p as make, r as renderError, s as header, t as InvalidInputError, u as writeError } from "./error-CxoEKg-4.mjs";
|
|
3
|
+
import { t as harnessOptions } from "./harness-6d8TlAVk.mjs";
|
|
4
4
|
import { Effect, Exit, Fiber, Option, Queue, Ref, Schema, Stream } from "effect";
|
|
5
|
+
import { EventList, Harness, Sandbox, Session } from "@codeworksh/harness/effect";
|
|
5
6
|
//#region src/cli/cmd/handlers/run.ts
|
|
6
7
|
const initialRenderState = {
|
|
7
8
|
usage: emptyUsage,
|
|
8
9
|
textSeen: false,
|
|
9
10
|
textEndsWithNewline: false
|
|
10
11
|
};
|
|
11
|
-
const isTextDelta = Schema.is(LLMTextDelta);
|
|
12
|
-
const isLLMEnded = Schema.is(LLMEnded);
|
|
13
|
-
const isTurnEnded = Schema.is(TurnEnded);
|
|
12
|
+
const isTextDelta = Schema.is(EventList.LLMTextDelta);
|
|
13
|
+
const isLLMEnded = Schema.is(EventList.LLMEnded);
|
|
14
|
+
const isTurnEnded = Schema.is(EventList.TurnEnded);
|
|
14
15
|
const render = (state, ended) => Effect.fn("CLI.render")(function* (event) {
|
|
15
16
|
if (isTextDelta(event)) {
|
|
16
17
|
yield* writeOut(event.data.delta);
|
|
@@ -39,10 +40,10 @@ const awaitMessage = Effect.fn("CLI.awaitMessage")(function* (ended, messageId)
|
|
|
39
40
|
while ((yield* Queue.take(ended)) !== messageId);
|
|
40
41
|
});
|
|
41
42
|
const selectSandbox = Effect.fn("CLI.selectSandbox")(function* (input) {
|
|
42
|
-
const selection = yield* resolve(input);
|
|
43
|
+
const selection = yield* Sandbox.resolve(input);
|
|
43
44
|
if (selection.created && selection.info !== void 0) {
|
|
44
45
|
const id = selection.info.id;
|
|
45
|
-
yield* Effect.addFinalizer(() => Effect.ignore(stop(id)));
|
|
46
|
+
yield* Effect.addFinalizer(() => Effect.ignore(Sandbox.stop(id)));
|
|
46
47
|
}
|
|
47
48
|
return selection.info;
|
|
48
49
|
});
|
|
@@ -57,11 +58,11 @@ var run_default = handler(Cmd.commands.run, Effect.fn("CLI.run")(function* ({ pr
|
|
|
57
58
|
shared.userConfigDir
|
|
58
59
|
].some(Option.isSome)) return yield* new InvalidInputError({ message: "--home, --database, and --user-config-dir belong on codework serve when using --server" });
|
|
59
60
|
if (Option.isSome(sandboxId) && (Option.isSome(sandboxDriver) || Option.isSome(sandboxProviderId))) return yield* new InvalidInputError({ message: "--sandbox-id cannot be combined with --sandbox-driver or --sandbox-provider-id" });
|
|
60
|
-
const selection = Option.isSome(sandboxId) ? { id:
|
|
61
|
+
const selection = Option.isSome(sandboxId) ? { id: Sandbox.SandboxInstance.ID.make(sandboxId.value) } : {
|
|
61
62
|
driver: Option.getOrElse(sandboxDriver, () => "local"),
|
|
62
63
|
...Option.isNone(sandboxProviderId) ? {} : { providerResourceId: sandboxProviderId.value }
|
|
63
64
|
};
|
|
64
|
-
const hostDir =
|
|
65
|
+
const hostDir = Session.AbsolutePath.make(process.cwd());
|
|
65
66
|
const runtime = {
|
|
66
67
|
...Option.isNone(provider) || Option.isNone(model) ? {} : { model: {
|
|
67
68
|
provider: provider.value,
|
|
@@ -72,7 +73,7 @@ var run_default = handler(Cmd.commands.run, Effect.fn("CLI.run")(function* ({ pr
|
|
|
72
73
|
const remote = Effect.gen(function* () {
|
|
73
74
|
const rpc = yield* make;
|
|
74
75
|
const info = Option.isSome(session) ? yield* rpc["session.configure"]({
|
|
75
|
-
sessionId: ID.make(session.value),
|
|
76
|
+
sessionId: Session.SessionSchema.ID.make(session.value),
|
|
76
77
|
runtime
|
|
77
78
|
}) : yield* rpc["session.create"]({
|
|
78
79
|
title: "CLI",
|
|
@@ -98,13 +99,13 @@ var run_default = handler(Cmd.commands.run, Effect.fn("CLI.run")(function* ({ pr
|
|
|
98
99
|
});
|
|
99
100
|
const program = Effect.gen(function* () {
|
|
100
101
|
let handle;
|
|
101
|
-
if (Option.isSome(session)) handle = yield* attach({
|
|
102
|
-
sessionId: ID.make(session.value),
|
|
102
|
+
if (Option.isSome(session)) handle = yield* Session.attach({
|
|
103
|
+
sessionId: Session.SessionSchema.ID.make(session.value),
|
|
103
104
|
...runtime
|
|
104
105
|
});
|
|
105
106
|
else {
|
|
106
107
|
const selected = yield* selectSandbox(selection);
|
|
107
|
-
handle = yield* create({
|
|
108
|
+
handle = yield* Session.create({
|
|
108
109
|
title: "CLI",
|
|
109
110
|
...runtime,
|
|
110
111
|
...selected === void 0 ? {} : { sandbox: selected },
|
|
@@ -136,7 +137,7 @@ var run_default = handler(Cmd.commands.run, Effect.fn("CLI.run")(function* ({ pr
|
|
|
136
137
|
});
|
|
137
138
|
return yield* Effect.gen(function* () {
|
|
138
139
|
if (Option.isSome(server)) return yield* remote.pipe(Effect.provide(layer(server.value)));
|
|
139
|
-
return yield* program.pipe(Effect.provide(layer
|
|
140
|
+
return yield* program.pipe(Effect.provide(Harness.layer(harnessOptions(shared))));
|
|
140
141
|
}).pipe(Effect.scoped, Effect.catch((error) => writeError(renderError(error)).pipe(Effect.andThen(Effect.sync(() => {
|
|
141
142
|
process.exitCode = 1;
|
|
142
143
|
})))));
|
|
@@ -144,4 +145,4 @@ var run_default = handler(Cmd.commands.run, Effect.fn("CLI.run")(function* ({ pr
|
|
|
144
145
|
//#endregion
|
|
145
146
|
export { run_default as default };
|
|
146
147
|
|
|
147
|
-
//# sourceMappingURL=run-
|
|
148
|
+
//# sourceMappingURL=run-D7h83L_m.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-D7h83L_m.mjs","names":["Runtime.handler","Client.make","Client.run","Client.layer"],"sources":["../../src/cli/cmd/handlers/run.ts"],"sourcesContent":["import { EventList, type EventSchema, Harness, Sandbox, Session } from \"@codeworksh/harness/effect\";\nimport { Effect, Exit, Fiber, Option, Queue, Ref, Schema, Stream } from \"effect\";\nimport { Runtime } from \"../../../framework/runtime.ts\";\nimport { Client } from \"../../../server/client.ts\";\nimport { InvalidInputError, renderError } from \"../../error.ts\";\nimport { harnessOptions } from \"../../harness.ts\";\nimport {\n\taddUsage,\n\temptyUsage,\n\theader,\n\tterminalColumns,\n\tusage,\n\ttype UsageSummary,\n\twriteError,\n\twriteOut,\n} from \"../../output.ts\";\nimport { Cmd } from \"../cmd.ts\";\n\ninterface RenderState {\n\treadonly usage: UsageSummary;\n\treadonly textSeen: boolean;\n\treadonly textEndsWithNewline: boolean;\n}\n\nconst initialRenderState: RenderState = {\n\tusage: emptyUsage,\n\ttextSeen: false,\n\ttextEndsWithNewline: false,\n};\n\nconst isTextDelta = Schema.is(EventList.LLMTextDelta);\nconst isLLMEnded = Schema.is(EventList.LLMEnded);\nconst isTurnEnded = Schema.is(EventList.TurnEnded);\n\nconst render = (state: Ref.Ref<RenderState>, ended?: Queue.Queue<string>) =>\n\tEffect.fn(\"CLI.render\")(function* (event: EventSchema.Payload) {\n\t\tif (isTextDelta(event)) {\n\t\t\tyield* writeOut(event.data.delta);\n\t\t\tif (event.data.delta.length > 0) {\n\t\t\t\tyield* Ref.update(state, (current) => ({\n\t\t\t\t\t...current,\n\t\t\t\t\ttextSeen: true,\n\t\t\t\t\ttextEndsWithNewline: event.data.delta.endsWith(\"\\n\"),\n\t\t\t\t}));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (isLLMEnded(event)) {\n\t\t\tyield* Ref.update(state, (current) => ({ ...current, usage: addUsage(current.usage, event.data.message) }));\n\t\t\treturn;\n\t\t}\n\t\tif (ended !== undefined && isTurnEnded(event)) {\n\t\t\tyield* Queue.offer(ended, event.data.messageId);\n\t\t}\n\t});\n\nconst finish = Effect.fn(\"CLI.finish\")(function* (state: Ref.Ref<RenderState>, columns: number) {\n\tconst rendered = yield* Ref.get(state);\n\tif (rendered.textSeen && !rendered.textEndsWithNewline) yield* writeOut(\"\\n\");\n\tyield* writeError(usage(rendered.usage, columns));\n});\n\nconst awaitMessage = Effect.fn(\"CLI.awaitMessage\")(function* (ended: Queue.Queue<string>, messageId: string) {\n\twhile ((yield* Queue.take(ended)) !== messageId) {\n\t\t// Earlier turns in the same drain are expected when a tool call continues.\n\t}\n});\n\nconst selectSandbox = Effect.fn(\"CLI.selectSandbox\")(function* (input: Sandbox.Selection) {\n\tconst selection = yield* Sandbox.resolve(input);\n\tif (selection.created && selection.info !== undefined) {\n\t\tconst id = selection.info.id;\n\t\tyield* Effect.addFinalizer(() => Effect.ignore(Sandbox.stop(id)));\n\t}\n\treturn selection.info;\n});\n\nexport default Runtime.handler(\n\tCmd.commands.run,\n\tEffect.fn(\"CLI.run\")(function* ({\n\t\tprompt,\n\t\tsession,\n\t\tcwd,\n\t\tsandboxDriver,\n\t\tsandboxProviderId,\n\t\tsandboxId,\n\t\tprovider,\n\t\tmodel,\n\t\tthinking,\n\t\tserver,\n\t}) {\n\t\tconst shared = yield* Cmd.spec;\n\t\tif (\n\t\t\tOption.isSome(session) &&\n\t\t\t(Option.isSome(cwd) ||\n\t\t\t\tOption.isSome(sandboxDriver) ||\n\t\t\t\tOption.isSome(sandboxProviderId) ||\n\t\t\t\tOption.isSome(sandboxId))\n\t\t) {\n\t\t\treturn yield* new InvalidInputError({\n\t\t\t\tmessage:\n\t\t\t\t\t\"--cwd, --sandbox-driver, --sandbox-id, and --sandbox-provider-id can only be used when creating a new session\",\n\t\t\t});\n\t\t}\n\t\tif (Option.isSome(provider) !== Option.isSome(model)) {\n\t\t\treturn yield* new InvalidInputError({ message: \"--provider and --model must be provided together\" });\n\t\t}\n\t\tif (Option.isSome(sandboxProviderId) && Option.isNone(sandboxDriver)) {\n\t\t\treturn yield* new InvalidInputError({\n\t\t\t\tmessage: \"--sandbox-provider-id requires a remote --sandbox-driver\",\n\t\t\t});\n\t\t}\n\t\tif (Option.isSome(server) && [shared.home, shared.database, shared.userConfigDir].some(Option.isSome)) {\n\t\t\treturn yield* new InvalidInputError({\n\t\t\t\tmessage: \"--home, --database, and --user-config-dir belong on codework serve when using --server\",\n\t\t\t});\n\t\t}\n\n\t\tif (Option.isSome(sandboxId) && (Option.isSome(sandboxDriver) || Option.isSome(sandboxProviderId))) {\n\t\t\treturn yield* new InvalidInputError({\n\t\t\t\tmessage: \"--sandbox-id cannot be combined with --sandbox-driver or --sandbox-provider-id\",\n\t\t\t});\n\t\t}\n\t\tconst selection: Sandbox.Selection = Option.isSome(sandboxId)\n\t\t\t? { id: Sandbox.SandboxInstance.ID.make(sandboxId.value) }\n\t\t\t: {\n\t\t\t\t\tdriver: Option.getOrElse(sandboxDriver, () => \"local\"),\n\t\t\t\t\t...(Option.isNone(sandboxProviderId) ? {} : { providerResourceId: sandboxProviderId.value }),\n\t\t\t\t};\n\n\t\t// The session's host directory, with no flag to set it: a person running a command is always\n\t\t// somewhere, and that somewhere is what they mean by \"this project\". `--cwd` is a different\n\t\t// thing entirely -- where the work runs inside the session's space, which may be a sandbox\n\t\t// on another machine.\n\t\tconst hostDir = Session.AbsolutePath.make(process.cwd());\n\n\t\tconst runtime = {\n\t\t\t...(Option.isNone(provider) || Option.isNone(model)\n\t\t\t\t? {}\n\t\t\t\t: { model: { provider: provider.value, id: model.value } }),\n\t\t\t...(Option.isNone(thinking) ? {} : { thinkingLevel: thinking.value }),\n\t\t};\n\t\tconst remote = Effect.gen(function* () {\n\t\t\tconst rpc = yield* Client.make;\n\t\t\tconst info = Option.isSome(session)\n\t\t\t\t? yield* rpc[\"session.configure\"]({ sessionId: Session.SessionSchema.ID.make(session.value), runtime })\n\t\t\t\t: yield* rpc[\"session.create\"]({\n\t\t\t\t\t\ttitle: \"CLI\",\n\t\t\t\t\t\truntime,\n\t\t\t\t\t\t...(Option.isNone(cwd) ? {} : { directory: cwd.value }),\n\t\t\t\t\t\thostDir,\n\t\t\t\t\t\tsandbox: selection,\n\t\t\t\t\t});\n\t\t\tconst state = yield* Ref.make(initialRenderState);\n\t\t\tconst columns = terminalColumns();\n\t\t\tyield* writeError(\n\t\t\t\theader({\n\t\t\t\t\tsessionId: info.id,\n\t\t\t\t\tsandbox: info.sandbox?.driver ?? \"local\",\n\t\t\t\t\tdirectory: info.directory,\n\t\t\t\t\tcolumns,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tif (info.sandbox !== undefined) yield* writeError(`sandbox-id: ${info.sandbox.id}\\n`);\n\t\t\tyield* Client.run(rpc, { sessionId: info.id, text: prompt }, render(state)).pipe(\n\t\t\t\tEffect.onInterrupt(() =>\n\t\t\t\t\trpc[\"session.interrupt\"]({ sessionId: info.id }).pipe(Effect.timeout(\"5 seconds\"), Effect.ignore),\n\t\t\t\t),\n\t\t\t);\n\t\t\tyield* finish(state, columns);\n\t\t});\n\t\tconst program = Effect.gen(function* () {\n\t\t\tlet handle: Session.Handle;\n\t\t\tif (Option.isSome(session)) {\n\t\t\t\thandle = yield* Session.attach({ sessionId: Session.SessionSchema.ID.make(session.value), ...runtime });\n\t\t\t} else {\n\t\t\t\tconst selected = yield* selectSandbox(selection);\n\t\t\t\thandle = yield* Session.create({\n\t\t\t\t\ttitle: \"CLI\",\n\t\t\t\t\t...runtime,\n\t\t\t\t\t...(selected === undefined ? {} : { sandbox: selected }),\n\t\t\t\t\t...(Option.isNone(cwd) ? {} : { directory: cwd.value }),\n\t\t\t\t\thostDir,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst ended = yield* Queue.unbounded<string>();\n\t\t\tconst renderState = yield* Ref.make(initialRenderState);\n\t\t\tconst printer = yield* handle\n\t\t\t\t.events()\n\t\t\t\t.pipe(Stream.runForEach(render(renderState, ended)), Effect.forkScoped({ startImmediately: true }));\n\n\t\t\tconst info = yield* handle.info;\n\t\t\tconst columns = terminalColumns();\n\t\t\tyield* writeError(\n\t\t\t\theader({\n\t\t\t\t\tsessionId: handle.id,\n\t\t\t\t\tsandbox: info.sandbox?.driver ?? \"local\",\n\t\t\t\t\tdirectory: info.directory,\n\t\t\t\t\tcolumns,\n\t\t\t\t}),\n\t\t\t);\n\t\t\t// The local command joins execution to retain typed error details.\n\t\t\tconst execution = yield* handle\n\t\t\t\t.prompt({ text: prompt, delivery: \"followUp\" })\n\t\t\t\t.pipe(Effect.andThen(handle.resume()), Effect.exit);\n\t\t\tyield* handle.wait();\n\t\t\tif (Exit.isFailure(execution)) return yield* Effect.failCause(execution.cause);\n\t\t\tconst path = yield* handle.path();\n\t\t\tconst leaf = path.at(-1);\n\t\t\tif (leaf !== undefined) yield* awaitMessage(ended, leaf.entry.id);\n\t\t\tyield* Fiber.interrupt(printer);\n\t\t\tyield* finish(renderState, columns);\n\t\t});\n\n\t\tconst execute = Effect.gen(function* () {\n\t\t\tif (Option.isSome(server)) return yield* remote.pipe(Effect.provide(Client.layer(server.value)));\n\t\t\treturn yield* program.pipe(Effect.provide(Harness.layer(harnessOptions(shared))));\n\t\t});\n\t\treturn yield* execute.pipe(\n\t\t\tEffect.scoped,\n\t\t\tEffect.catch((error) =>\n\t\t\t\twriteError(renderError(error)).pipe(\n\t\t\t\t\tEffect.andThen(\n\t\t\t\t\t\tEffect.sync(() => {\n\t\t\t\t\t\t\tprocess.exitCode = 1;\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}),\n);\n"],"mappings":"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"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { A as stop, C as link, D as list, E as drivers, M as Service$7, O as register, S as get, T as create$1, Tt as authFile, _ as Connected, at as Service$3, b as attach, g as OAuthError, h as Api, j as layer$4, k as resolve, lt as Service$6, mt as SubscriptionOverflowError, ot as Service$5, pt as Service$2, r as renderError, u as writeError, ut as SessionNotFoundError, v as Core, w as relink, wt as Service$4, x as create, xt as schema_exports, y as encode, yt as Prompt } from "./error-D0C5K2Av.mjs";
|
|
2
1
|
import { i as Cmd, t as handler } from "./runtime-B3dlWGfs.mjs";
|
|
3
|
-
import {
|
|
2
|
+
import { _ as Connected, g as OAuthError, h as Api, r as renderError, u as writeError, v as Core, y as encode } from "./error-CxoEKg-4.mjs";
|
|
3
|
+
import { t as harnessOptions } from "./harness-6d8TlAVk.mjs";
|
|
4
4
|
import { Cause, Context, Effect, Layer, Option, Queue, Stream } from "effect";
|
|
5
5
|
import { summarizeGitHubCopilot, summarizeOpenAICodex } from "@codeworksh/aikit/oauth/summary";
|
|
6
|
+
import { Control, Event, EventRegistry, EventSchema, Global, Harness, PromptSchema, Sandbox, Session, SessionStore, State } from "@codeworksh/harness/effect";
|
|
6
7
|
import { NodeHttpServer } from "@effect/platform-node";
|
|
8
|
+
import { RpcSerialization, RpcServer } from "effect/unstable/rpc";
|
|
7
9
|
import { GitHubCopilotOAuthClient, JsonGitHubCopilotAuthStorage } from "@codeworksh/aikit/oauth/github/copilot";
|
|
8
10
|
import { JsonOpenAICodexAuthStorage, OpenAICodexOAuthClient } from "@codeworksh/aikit/oauth/openai/codex";
|
|
9
|
-
import { RpcSerialization, RpcServer } from "effect/unstable/rpc";
|
|
10
11
|
import { HttpRouter, HttpServer } from "effect/unstable/http";
|
|
11
12
|
import * as NetAddress from "effect/unstable/net/NetAddress";
|
|
12
13
|
import { createServer } from "node:http";
|
|
@@ -38,7 +39,7 @@ const make = Effect.fn("EventFeed.make")(function* (listen, options) {
|
|
|
38
39
|
for (const subscriber of subscribers) {
|
|
39
40
|
if (Queue.offerUnsafe(subscriber, envelope)) continue;
|
|
40
41
|
subscribers.delete(subscriber);
|
|
41
|
-
Queue.failCauseUnsafe(subscriber, Cause.fail(new SubscriptionOverflowError({ capacity })));
|
|
42
|
+
Queue.failCauseUnsafe(subscriber, Cause.fail(new Event.SubscriptionOverflowError({ capacity })));
|
|
42
43
|
}
|
|
43
44
|
});
|
|
44
45
|
const publish = (event) => deliver(event).pipe(Effect.catchTags({
|
|
@@ -53,8 +54,8 @@ const make = Effect.fn("EventFeed.make")(function* (listen, options) {
|
|
|
53
54
|
return Service$1.of({ subscribe: Effect.acquireRelease(Queue.dropping(capacity).pipe(Effect.tap((queue) => Effect.sync(() => subscribers.add(queue)))), (queue) => Effect.sync(() => subscribers.delete(queue)).pipe(Effect.andThen(Queue.shutdown(queue)))).pipe(Effect.map(Stream.fromQueue)) });
|
|
54
55
|
});
|
|
55
56
|
const layer$3 = Layer.effect(Service$1, Effect.gen(function* () {
|
|
56
|
-
const events = yield* Service
|
|
57
|
-
const registered = yield* Service
|
|
57
|
+
const events = yield* Event.Service;
|
|
58
|
+
const registered = yield* EventRegistry.Service;
|
|
58
59
|
return yield* make(events.listen, { registry: registered.get });
|
|
59
60
|
}));
|
|
60
61
|
//#endregion
|
|
@@ -76,9 +77,9 @@ const message = (cause) => cause instanceof Error && cause.message.trim().length
|
|
|
76
77
|
const codexInfo = summarizeOpenAICodex;
|
|
77
78
|
const copilotInfo = summarizeGitHubCopilot;
|
|
78
79
|
const layer$2 = (options = {}) => Layer.effect(Service, Effect.gen(function* () {
|
|
79
|
-
const global = yield* Service
|
|
80
|
-
const authFile
|
|
81
|
-
const file = authFile
|
|
80
|
+
const global = yield* Global.Service;
|
|
81
|
+
const authFile = Global.authFile(options.home === void 0 ? void 0 : global.home);
|
|
82
|
+
const file = authFile === void 0 ? {} : { path: authFile };
|
|
82
83
|
const codex = new OpenAICodexOAuthClient({ storage: new JsonOpenAICodexAuthStorage(file) });
|
|
83
84
|
const copilot = new GitHubCopilotOAuthClient({ storage: new JsonGitHubCopilotAuthStorage(file) });
|
|
84
85
|
const attempt = (run) => Effect.tryPromise({
|
|
@@ -138,16 +139,16 @@ const runtimeInput = (runtime) => ({
|
|
|
138
139
|
...runtime?.thinkingLevel === void 0 ? {} : { thinkingLevel: runtime.thinkingLevel }
|
|
139
140
|
});
|
|
140
141
|
const sessionInfo = Effect.fn("Server.sessionInfo")(function* (sessionId) {
|
|
141
|
-
const found = yield* get(sessionId);
|
|
142
|
-
if (Option.isNone(found)) return yield* new SessionNotFoundError({ sessionId });
|
|
142
|
+
const found = yield* Session.get(sessionId);
|
|
143
|
+
if (Option.isNone(found)) return yield* new SessionStore.SessionNotFoundError({ sessionId });
|
|
143
144
|
return toSessionInfo(yield* found.value.info);
|
|
144
145
|
});
|
|
145
|
-
const releaseOnFailure = (selection) => selection?.created && selection.info !== void 0 ? stop(selection.info.id).pipe(Effect.catchCause(Effect.logError)) : Effect.void;
|
|
146
|
+
const releaseOnFailure = (selection) => selection?.created && selection.info !== void 0 ? Sandbox.stop(selection.info.id).pipe(Effect.catchCause(Effect.logError)) : Effect.void;
|
|
146
147
|
const layer$1 = Api.toLayer(Effect.gen(function* () {
|
|
147
|
-
const control = yield* Service
|
|
148
|
+
const control = yield* Control.Service;
|
|
148
149
|
const feed = yield* Service$1;
|
|
149
|
-
const sessions = yield* Service
|
|
150
|
-
const state = yield* Service
|
|
150
|
+
const sessions = yield* SessionStore.Service;
|
|
151
|
+
const state = yield* State.Service;
|
|
151
152
|
const oauth = yield* Service;
|
|
152
153
|
return Api.of({
|
|
153
154
|
"auth.save": ({ credentials }) => oauth.save(credentials),
|
|
@@ -155,9 +156,9 @@ const layer$1 = Api.toLayer(Effect.gen(function* () {
|
|
|
155
156
|
"auth.refresh": ({ provider }) => oauth.refresh(provider),
|
|
156
157
|
"auth.logout": ({ provider }) => oauth.logout(provider),
|
|
157
158
|
"session.create": Effect.fnUntraced(function* ({ title, directory, hostDir, sandbox, runtime }) {
|
|
158
|
-
const selection = sandbox === void 0 ? void 0 : yield* resolve(sandbox);
|
|
159
|
+
const selection = sandbox === void 0 ? void 0 : yield* Sandbox.resolve(sandbox);
|
|
159
160
|
const selected = selection?.info;
|
|
160
|
-
const handle = yield* create({
|
|
161
|
+
const handle = yield* Session.create({
|
|
161
162
|
...title === void 0 ? {} : { title },
|
|
162
163
|
...directory === void 0 ? {} : { directory },
|
|
163
164
|
...hostDir === void 0 ? {} : { hostDir },
|
|
@@ -174,7 +175,7 @@ const layer$1 = Api.toLayer(Effect.gen(function* () {
|
|
|
174
175
|
return yield* Effect.forEach(rows, (row) => sessionInfo(row.id).pipe(Effect.orDie));
|
|
175
176
|
}),
|
|
176
177
|
"session.configure": Effect.fnUntraced(function* ({ sessionId, runtime }) {
|
|
177
|
-
const handle = yield* attach({
|
|
178
|
+
const handle = yield* Session.attach({
|
|
178
179
|
sessionId,
|
|
179
180
|
...runtimeInput(runtime)
|
|
180
181
|
});
|
|
@@ -184,16 +185,16 @@ const layer$1 = Api.toLayer(Effect.gen(function* () {
|
|
|
184
185
|
return yield* sessionInfo(sessionId);
|
|
185
186
|
}),
|
|
186
187
|
"session.link": Effect.fnUntraced(function* ({ sessionId, hostDir }) {
|
|
187
|
-
const handle = yield* link({
|
|
188
|
+
const handle = yield* Session.link({
|
|
188
189
|
sessionId,
|
|
189
190
|
hostDir: hostDir ?? null
|
|
190
191
|
});
|
|
191
192
|
return toSessionInfo(yield* handle.info);
|
|
192
193
|
}),
|
|
193
194
|
"session.relink": Effect.fnUntraced(function* ({ sessionId, sandbox, directory }) {
|
|
194
|
-
const selection = sandbox === void 0 ? void 0 : yield* resolve(sandbox);
|
|
195
|
+
const selection = sandbox === void 0 ? void 0 : yield* Sandbox.resolve(sandbox);
|
|
195
196
|
const selected = selection?.info;
|
|
196
|
-
const handle = yield* relink({
|
|
197
|
+
const handle = yield* Session.relink({
|
|
197
198
|
sessionId,
|
|
198
199
|
...selected === void 0 ? {} : { sandbox: selected },
|
|
199
200
|
...directory === void 0 ? {} : { directory }
|
|
@@ -203,7 +204,7 @@ const layer$1 = Api.toLayer(Effect.gen(function* () {
|
|
|
203
204
|
"session.prompt": Effect.fnUntraced(function* ({ sessionId, text, delivery, id }) {
|
|
204
205
|
yield* control.prompt({
|
|
205
206
|
sessionId,
|
|
206
|
-
prompt: Prompt.make({ text }),
|
|
207
|
+
prompt: PromptSchema.Prompt.make({ text }),
|
|
207
208
|
...delivery === void 0 ? {} : { delivery },
|
|
208
209
|
...id === void 0 ? {} : { id }
|
|
209
210
|
});
|
|
@@ -219,28 +220,28 @@ const layer$1 = Api.toLayer(Effect.gen(function* () {
|
|
|
219
220
|
yield* control.wait(sessionId);
|
|
220
221
|
}),
|
|
221
222
|
"sandbox.drivers": Effect.fnUntraced(function* () {
|
|
222
|
-
return (yield* drivers()).map(({ name, kind }) => ({
|
|
223
|
+
return (yield* Sandbox.drivers()).map(({ name, kind }) => ({
|
|
223
224
|
name,
|
|
224
225
|
kind
|
|
225
226
|
}));
|
|
226
227
|
}),
|
|
227
228
|
"sandbox.list": Effect.fnUntraced(function* () {
|
|
228
|
-
return (yield* list()).map(toSandboxInfo);
|
|
229
|
+
return (yield* Sandbox.list()).map(toSandboxInfo);
|
|
229
230
|
}),
|
|
230
231
|
"sandbox.create": Effect.fnUntraced(function* ({ driver }) {
|
|
231
|
-
return toSandboxInfo(yield* create
|
|
232
|
+
return toSandboxInfo(yield* Sandbox.create({ driver }));
|
|
232
233
|
}),
|
|
233
234
|
"sandbox.register": Effect.fnUntraced(function* ({ driver, providerResourceId }) {
|
|
234
|
-
return toSandboxInfo(yield* register({
|
|
235
|
+
return toSandboxInfo(yield* Sandbox.register({
|
|
235
236
|
driver,
|
|
236
237
|
providerResourceId
|
|
237
238
|
}));
|
|
238
239
|
}),
|
|
239
240
|
"sandbox.stop": Effect.fnUntraced(function* ({ sandboxId }) {
|
|
240
|
-
yield* stop(sandboxId);
|
|
241
|
+
yield* Sandbox.stop(sandboxId);
|
|
241
242
|
}),
|
|
242
243
|
"event.subscribe": () => Stream.unwrap(feed.subscribe.pipe(Effect.map((events) => Stream.make({
|
|
243
|
-
id:
|
|
244
|
+
id: EventSchema.ID.create(),
|
|
244
245
|
type: Connected.type,
|
|
245
246
|
data: {}
|
|
246
247
|
}).pipe(Stream.concat(events)))))
|
|
@@ -250,7 +251,7 @@ const layer$1 = Api.toLayer(Effect.gen(function* () {
|
|
|
250
251
|
//#region src/server/server.ts
|
|
251
252
|
const WsProtocol = RpcServer.layerProtocolWebsocket({ path: "/rpc" }).pipe(Layer.provide(HttpRouter.layer));
|
|
252
253
|
const managedShutdown = Layer.unwrap(Effect.gen(function* () {
|
|
253
|
-
const control = yield* Service
|
|
254
|
+
const control = yield* Control.Service;
|
|
254
255
|
yield* Effect.addFinalizer(() => Effect.gen(function* () {
|
|
255
256
|
yield* Effect.forEach(yield* control.active, (id) => control.interrupt(id, {
|
|
256
257
|
reason: "shutdown",
|
|
@@ -259,8 +260,8 @@ const managedShutdown = Layer.unwrap(Effect.gen(function* () {
|
|
|
259
260
|
concurrency: "unbounded",
|
|
260
261
|
discard: true
|
|
261
262
|
});
|
|
262
|
-
const infos = yield* list();
|
|
263
|
-
yield* Effect.forEach(infos.filter((info) => info.ownership === "managed"), (info) => stop(info.id).pipe(Effect.timeout("10 seconds"), Effect.catchCause((cause) => Effect.logError("Failed to stop managed sandbox during shutdown", cause).pipe(Effect.annotateLogs({ sandboxInstanceId: info.id })))), {
|
|
263
|
+
const infos = yield* Sandbox.list();
|
|
264
|
+
yield* Effect.forEach(infos.filter((info) => info.ownership === "managed"), (info) => Sandbox.stop(info.id).pipe(Effect.timeout("10 seconds"), Effect.catchCause((cause) => Effect.logError("Failed to stop managed sandbox during shutdown", cause).pipe(Effect.annotateLogs({ sandboxInstanceId: info.id })))), {
|
|
264
265
|
concurrency: "unbounded",
|
|
265
266
|
discard: true
|
|
266
267
|
});
|
|
@@ -276,7 +277,7 @@ const layer = (options) => {
|
|
|
276
277
|
return RpcServer.layer(Api).pipe(Layer.provide(layer$1.pipe(Layer.provide(layer$3)))).pipe(Layer.provideMerge(WsProtocol), Layer.provide(HttpRouter.serve(WsProtocol, { disableListenLog: true })), Layer.provideMerge(managedShutdown), Layer.provide(layer$2(options.harness.home === void 0 ? {} : { home: options.harness.home }))).pipe(Layer.provideMerge(listenLog), Layer.provideMerge(NodeHttpServer.layer(createServer, {
|
|
277
278
|
host: options.host,
|
|
278
279
|
port: options.port
|
|
279
|
-
})), Layer.provide(RpcSerialization.layerNdjson), Layer.provide(layer
|
|
280
|
+
})), Layer.provide(RpcSerialization.layerNdjson), Layer.provide(Harness.layer(options.harness)));
|
|
280
281
|
};
|
|
281
282
|
//#endregion
|
|
282
283
|
//#region src/cli/cmd/handlers/serve.ts
|
|
@@ -296,4 +297,4 @@ var serve_default = handler(Cmd.commands.serve, Effect.fn("CLI.serve")(function*
|
|
|
296
297
|
//#endregion
|
|
297
298
|
export { serve_default as default };
|
|
298
299
|
|
|
299
|
-
//# sourceMappingURL=serve-
|
|
300
|
+
//# sourceMappingURL=serve-BGrH_Wr6.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve-BGrH_Wr6.mjs","names":["Service","Envelope.Core","Envelope.encode","layer","layer","Contract.OAuthError","layer","EventFeed.Service","OAuth.Service","Contract.Api","EventFeed.layer","OAuth.layer","Runtime.handler","Server.layer"],"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 { Control, EventSchema, PromptSchema, Sandbox, Session, SessionStore, State } from \"@codeworksh/harness/effect\";\nimport { Effect, Option, Stream } from \"effect\";\nimport { Contract, type RuntimeConfig, type SandboxInfo, type SessionInfo } from \"./contract.ts\";\nimport { Envelope } from \"./envelope.ts\";\nimport { EventFeed } from \"./feed.ts\";\nimport { OAuth } from \"./oauth.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\ttitle: info.title,\n\tdirectory: info.directory,\n\t...(info.hostDir === undefined ? {} : { hostDir: info.hostDir }),\n\t...(info.sandbox === undefined ? {} : { sandbox: toSandboxInfo(info.sandbox) }),\n});\n\n// Wire configs name only the keys they set, so `undefined` never reaches the\n// harness inputs under exactOptionalPropertyTypes.\nconst runtimeInput = (runtime: RuntimeConfig | undefined): Session.RuntimeInput => ({\n\t...(runtime?.model === undefined ? {} : { model: runtime.model }),\n\t...(runtime?.thinkingLevel === undefined ? {} : { thinkingLevel: runtime.thinkingLevel }),\n});\n\nconst sessionInfo = Effect.fn(\"Server.sessionInfo\")(function* (sessionId: Session.SessionSchema.ID) {\n\tconst found = yield* Session.get(sessionId);\n\tif (Option.isNone(found)) return yield* new SessionStore.SessionNotFoundError({ sessionId });\n\treturn toSessionInfo(yield* found.value.info);\n});\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\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 state = yield* State.Service;\n\t\tconst oauth = yield* OAuth.Service;\n\n\t\treturn Contract.Api.of({\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 }) {\n\t\t\t\tconst selection = sandbox === undefined ? undefined : yield* 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...runtimeInput(runtime),\n\t\t\t\t}).pipe(Effect.onError(() => releaseOnFailure(selection)));\n\t\t\t\treturn toSessionInfo(yield* handle.info);\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.list\": Effect.fnUntraced(function* () {\n\t\t\t\tconst rows = yield* sessions.list();\n\t\t\t\treturn yield* Effect.forEach(rows, (row) => sessionInfo(row.id).pipe(Effect.orDie));\n\t\t\t}),\n\t\t\t\"session.configure\": Effect.fnUntraced(function* ({ sessionId, runtime }) {\n\t\t\t\tconst handle = yield* Session.attach({ sessionId, ...runtimeInput(runtime) });\n\t\t\t\treturn toSessionInfo(yield* handle.info);\n\t\t\t}),\n\t\t\t\"session.info\": Effect.fnUntraced(function* ({ sessionId }) {\n\t\t\t\treturn yield* sessionInfo(sessionId);\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, sandbox, directory }) {\n\t\t\t\tconst selection = sandbox === undefined ? undefined : yield* 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...(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\treturn toSessionInfo(yield* handle.info);\n\t\t\t}),\n\t\t\t\"session.prompt\": Effect.fnUntraced(function* ({ sessionId, text, delivery, id }) {\n\t\t\t\tyield* control.prompt({\n\t\t\t\t\tsessionId,\n\t\t\t\t\tprompt: PromptSchema.Prompt.make({ 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}),\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 `session.wait` when it needs cleanup to have finished.\n\t\t\t\treturn { interrupted: yield* control.interrupt(sessionId, { reason: \"user\" }) };\n\t\t\t}),\n\t\t\t\"session.message\": Effect.fnUntraced(function* ({ sessionId, messageId }) {\n\t\t\t\tconst found = yield* sessions.entry(messageId);\n\t\t\t\t// Scoped to the session the caller named: an entry id is global, and a\n\t\t\t\t// client should not learn about conversations it did not ask for.\n\t\t\t\treturn { found: Option.isSome(found) && found.value.entry.sessionId === sessionId };\n\t\t\t}),\n\t\t\t\"session.wait\": Effect.fnUntraced(function* ({ sessionId }) {\n\t\t\t\tyield* control.wait(sessionId);\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* 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\": () =>\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(events),\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, Harness, Sandbox } from \"@codeworksh/harness/effect\";\nimport { NodeHttpServer } from \"@effect/platform-node\";\nimport { Effect, Layer } from \"effect\";\nimport { HttpRouter, HttpServer } from \"effect/unstable/http\";\nimport * as NetAddress from \"effect/unstable/net/NetAddress\";\nimport { RpcSerialization, RpcServer } from \"effect/unstable/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 { OAuth } from \"./oauth.ts\";\n\nconst WsProtocol = RpcServer.layerProtocolWebsocket({ path: \"/rpc\" }).pipe(Layer.provide(HttpRouter.layer));\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\nconst listenLog = Layer.unwrap(\n\tEffect.gen(function* () {\n\t\tconst server = yield* HttpServer.HttpServer;\n\t\tyield* Effect.log(`codework serve listening on ${NetAddress.formatUrlUnsafe(server.address, \"ws\")}/rpc`);\n\t\treturn Layer.empty;\n\t}),\n);\n\nexport const layer = (options: { host: string; port: number; harness: Harness.Options }) => {\n\tconst rpc = RpcServer.layer(Contract.Api).pipe(Layer.provide(Handlers.layer.pipe(Layer.provide(EventFeed.layer))));\n\tconst app = rpc.pipe(\n\t\tLayer.provideMerge(WsProtocol),\n\t\tLayer.provide(HttpRouter.serve(WsProtocol, { disableListenLog: true })),\n\t\tLayer.provideMerge(managedShutdown),\n\t\tLayer.provide(OAuth.layer(options.harness.home === undefined ? {} : { home: options.harness.home })),\n\t);\n\treturn app.pipe(\n\t\tLayer.provideMerge(listenLog),\n\t\tLayer.provideMerge(NodeHttpServer.layer(createServer, { host: options.host, port: options.port })),\n\t\tLayer.provide(RpcSerialization.layerNdjson),\n\t\tLayer.provide(Harness.layer(options.harness)),\n\t);\n};\n\nexport * as Server from \"./server.ts\";\n","import { Effect, Layer } from \"effect\";\nimport { Runtime } from \"../../../framework/runtime.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\nexport default Runtime.handler(\n\tCmd.commands.serve,\n\tEffect.fn(\"CLI.serve\")(function* ({ host, port }) {\n\t\tconst shared = yield* Cmd.spec;\n\t\tyield* Layer.launch(Server.layer({ host, port, harness: { ...harnessOptions(shared), watchModels: true } })).pipe(\n\t\t\tEffect.catch((error) =>\n\t\t\t\twriteError(renderError(error)).pipe(\n\t\t\t\t\tEffect.andThen(\n\t\t\t\t\t\tEffect.sync(() => {\n\t\t\t\t\t\t\tprocess.exitCode = 1;\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}),\n);\n"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as InvalidInputError } from "./error-CxoEKg-4.mjs";
|
|
2
2
|
import { Effect, FileSystem, Option, Path } from "effect";
|
|
3
|
+
import { Global, Plugin, Settings } from "@codeworksh/harness/effect";
|
|
3
4
|
import { applyEdits, modify, parse } from "jsonc-parser";
|
|
4
5
|
//#region src/cli/cmd/handlers/plugin/settings.ts
|
|
5
6
|
/**
|
|
@@ -7,7 +8,7 @@ import { applyEdits, modify, parse } from "jsonc-parser";
|
|
|
7
8
|
* the home's settings file -- resolved, like every app-level flag, against the directory the
|
|
8
9
|
* command runs in (`hostCwd`), never against a linked session's `hostDir`.
|
|
9
10
|
*/
|
|
10
|
-
const userLayer = (shared, hostCwd) => Option.isNone(shared.userConfigDir) ? {} : { userConfigDir: userConfigDir(shared.userConfigDir.value, hostCwd) };
|
|
11
|
+
const userLayer = (shared, hostCwd) => Option.isNone(shared.userConfigDir) ? {} : { userConfigDir: Settings.userConfigDir(shared.userConfigDir.value, hostCwd) };
|
|
11
12
|
/** The module an entry names: a bare loader string, or the `package` of a config object. */
|
|
12
13
|
const moduleOf = (entry) => {
|
|
13
14
|
if (typeof entry === "string") return entry;
|
|
@@ -28,7 +29,7 @@ const idOf = (entry) => {
|
|
|
28
29
|
* it, so `@acme/x@1.2.0` and `@acme/x` are one name. The literal string is kept alongside it
|
|
29
30
|
* because a plugin ID is not a module reference and survives `canonical` unchanged.
|
|
30
31
|
*/
|
|
31
|
-
const aliases = (reference, directory) => canonical(reference, directory).pipe(Effect.map((canonical) => [reference, canonical]), Effect.orElseSucceed(() => [reference]));
|
|
32
|
+
const aliases = (reference, directory) => Plugin.canonical(reference, directory).pipe(Effect.map((canonical) => [reference, canonical]), Effect.orElseSucceed(() => [reference]));
|
|
32
33
|
/** Every spelling `reference` answers to, computed once for a whole command. */
|
|
33
34
|
const spellings = (reference, directory) => Effect.map(aliases(reference, directory), (found) => new Set(found));
|
|
34
35
|
/**
|
|
@@ -55,11 +56,11 @@ const identify = Effect.fn("CLI.plugin.identify")(function* (plugins, file, cach
|
|
|
55
56
|
const module = moduleOf(value);
|
|
56
57
|
if (module !== void 0) {
|
|
57
58
|
for (const alias of yield* aliases(module, directory)) answers.add(alias);
|
|
58
|
-
const declared = yield* inspect(module, {
|
|
59
|
+
const declared = yield* Plugin.inspect(module, {
|
|
59
60
|
cache,
|
|
60
61
|
hostDir: directory,
|
|
61
62
|
file,
|
|
62
|
-
install:
|
|
63
|
+
install: Plugin.resolveCached
|
|
63
64
|
}).pipe(Effect.option);
|
|
64
65
|
if (Option.isSome(declared)) {
|
|
65
66
|
answers.add(declared.value.id);
|
|
@@ -97,7 +98,7 @@ const identify = Effect.fn("CLI.plugin.identify")(function* (plugins, file, cach
|
|
|
97
98
|
*/
|
|
98
99
|
const written = Effect.fn("CLI.plugin.written")(function* (reference, input) {
|
|
99
100
|
const nodePath = yield* Path.Path;
|
|
100
|
-
const target = yield* parse
|
|
101
|
+
const target = yield* Plugin.parse(reference, input.hostDir).pipe(Effect.option);
|
|
101
102
|
if (Option.isNone(target) || target.value.kind !== "local") return reference;
|
|
102
103
|
const absolute = target.value.path;
|
|
103
104
|
const inside = (root, path) => path === root || path.startsWith(`${root}${nodePath.sep}`);
|
|
@@ -162,7 +163,7 @@ const withPluginsLock = (path, edit) => Effect.gen(function* () {
|
|
|
162
163
|
const fs = yield* FileSystem.FileSystem;
|
|
163
164
|
const nodePath = yield* Path.Path;
|
|
164
165
|
yield* fs.makeDirectory(nodePath.dirname(path), { recursive: true });
|
|
165
|
-
yield*
|
|
166
|
+
yield* Plugin.settingsLock(`${path}.lock`, () => new InvalidInputError({ message: `timed out waiting to edit ${path}` }));
|
|
166
167
|
return yield* edit;
|
|
167
168
|
}).pipe(Effect.scoped);
|
|
168
169
|
/**
|
|
@@ -187,9 +188,9 @@ const resolveTarget = Effect.fn("CLI.plugin.resolveTarget")(function* (shared, g
|
|
|
187
188
|
const nodePath = yield* Path.Path;
|
|
188
189
|
const hostCwd = nodePath.resolve(".");
|
|
189
190
|
const hostDir = from ?? hostCwd;
|
|
190
|
-
const home = yield* resolve(Option.isNone(shared.home) ? {} : { home: shared.home.value });
|
|
191
|
-
const root = global ? void 0 : yield* projectRoot(hostDir, home.home);
|
|
192
|
-
const found = paths({
|
|
191
|
+
const home = yield* Global.resolve(Option.isNone(shared.home) ? {} : { home: shared.home.value });
|
|
192
|
+
const root = global ? void 0 : yield* Settings.projectRoot(hostDir, home.home);
|
|
193
|
+
const found = Settings.paths({
|
|
193
194
|
home: home.home,
|
|
194
195
|
...root === void 0 ? {} : { root },
|
|
195
196
|
...userLayer(shared, hostCwd)
|
|
@@ -217,4 +218,4 @@ const resolveTarget = Effect.fn("CLI.plugin.resolveTarget")(function* (shared, g
|
|
|
217
218
|
//#endregion
|
|
218
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 };
|
|
219
220
|
|
|
220
|
-
//# sourceMappingURL=settings-
|
|
221
|
+
//# sourceMappingURL=settings-aqM_b9UE.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-aqM_b9UE.mjs","names":["parseJsonc"],"sources":["../../src/cli/cmd/handlers/plugin/settings.ts"],"sourcesContent":["import { Global, Plugin, Settings } from \"@codeworksh/harness/effect\";\nimport { Effect, FileSystem, Option, Path } from \"effect\";\nimport { applyEdits, modify, parse as parseJsonc, type ParseError } from \"jsonc-parser\";\nimport { InvalidInputError } from \"../../../error.ts\";\n\n/**\n * Reading and rewriting the `plugins` array of one settings file.\n *\n * Edits go through `jsonc-parser`, so a hand-written file keeps its comments, key order and\n * formatting: a plugin added by the CLI must not reformat a file its owner maintains. The write\n * is a temp file renamed over the original, so an interrupted run leaves the previous settings\n * intact rather than a half-written document.\n */\n\nexport interface Shared {\n\treadonly userConfigDir: Option.Option<string>;\n\treadonly home: Option.Option<string>;\n}\n\n/**\n * The user layer a command reads and writes: `--user-config-dir` when given -- a hard override of\n * the home's settings file -- resolved, like every app-level flag, against the directory the\n * command runs in (`hostCwd`), never against a linked session's `hostDir`.\n */\nexport const userLayer = (shared: Shared, hostCwd: string) =>\n\tOption.isNone(shared.userConfigDir)\n\t\t? {}\n\t\t: { userConfigDir: Settings.userConfigDir(shared.userConfigDir.value, hostCwd) };\n\nexport interface Target {\n\treadonly path: string;\n\t/** Set when this command had to create the project directory, so the caller can say so. */\n\treadonly created?: string;\n\t/** The project this file belongs to, which a local entry is written relative to. */\n\treadonly root?: string;\n}\n\n/** The module an entry names: a bare loader string, or the `package` of a config object. */\nconst moduleOf = (entry: unknown): string | undefined => {\n\tif (typeof entry === \"string\") return entry;\n\tif (typeof entry !== \"object\" || entry === null) return undefined;\n\tconst { package: located } = entry as { package?: unknown };\n\treturn typeof located === \"string\" ? located : undefined;\n};\n\n/** The plugin ID an entry configures, if it names one. */\nconst idOf = (entry: unknown): string | undefined => {\n\tif (typeof entry !== \"object\" || entry === null) return undefined;\n\tconst { plugin } = entry as { plugin?: unknown };\n\treturn typeof plugin === \"string\" ? plugin : undefined;\n};\n\n/**\n * Every spelling a reference answers to, without touching the filesystem.\n *\n * `canonical` drops a version suffix and resolves a relative path against the file that declared\n * it, so `@acme/x@1.2.0` and `@acme/x` are one name. The literal string is kept alongside it\n * because a plugin ID is not a module reference and survives `canonical` unchanged.\n */\nconst aliases = (reference: string, directory: string): Effect.Effect<ReadonlyArray<string>> =>\n\tPlugin.canonical(reference, directory).pipe(\n\t\tEffect.map((canonical) => [reference, canonical] as ReadonlyArray<string>),\n\t\t// A reference that does not parse still answers to itself: a plugin ID is not a module\n\t\t// reference, and it has to keep matching an entry that names it.\n\t\tEffect.orElseSucceed(() => [reference] as ReadonlyArray<string>),\n\t);\n\n/** Every spelling `reference` answers to, computed once for a whole command. */\nexport const spellings = (reference: string, directory: string): Effect.Effect<ReadonlySet<string>> =>\n\tEffect.map(aliases(reference, directory), (found) => new Set(found));\n\nexport interface Entry {\n\treadonly value: unknown;\n\treadonly answers: ReadonlySet<string>;\n\treadonly loads: boolean;\n}\n\n/**\n * What each configured entry answers to.\n *\n * Comparing the string as written is not enough. `plugin add @acme/x@1.2.0` records a version the\n * user will not repeat when removing it, and one plugin can be named three ways: by package, by\n * path, or by the ID it declares -- a `{ \"plugin\": \"<id>\" }` configuration object sits next to the\n * module entry that loaded it, and removing the plugin has to take both.\n *\n * The declared ID is only knowable by importing the module, so it is read from what is already\n * installed: `resolveCached` reads a published package out of the harness cache and never runs an\n * installer, so editing a settings file cannot fetch anything. An entry that does not resolve --\n * uninstalled, moved, or broken -- keeps the names it was written with rather than failing the\n * command, because an unusable plugin is exactly the one a user is trying to remove.\n */\nexport const identify = Effect.fn(\"CLI.plugin.identify\")(function* (\n\tplugins: ReadonlyArray<unknown>,\n\tfile: string,\n\tcache: string,\n) {\n\tconst nodePath = yield* Path.Path;\n\tconst directory = nodePath.dirname(file);\n\tconst entries: Entry[] = [];\n\tfor (const value of plugins) {\n\t\tconst answers = new Set<string>();\n\t\tconst id = idOf(value);\n\t\tif (id !== undefined) answers.add(id);\n\t\tconst module = moduleOf(value);\n\t\tif (module !== undefined) {\n\t\t\tfor (const alias of yield* aliases(module, directory)) answers.add(alias);\n\t\t\tconst declared = yield* Plugin.inspect(module, {\n\t\t\t\tcache,\n\t\t\t\thostDir: directory,\n\t\t\t\tfile,\n\t\t\t\tinstall: Plugin.resolveCached,\n\t\t\t}).pipe(Effect.option);\n\t\t\tif (Option.isSome(declared)) {\n\t\t\t\tanswers.add(declared.value.id);\n\t\t\t\tif (declared.value.name !== undefined) answers.add(declared.value.name);\n\t\t\t}\n\t\t}\n\t\tentries.push({ value, answers, loads: typeof value === \"string\" });\n\t}\n\treturn entries as ReadonlyArray<Entry>;\n});\n\n/**\n * What a local reference should be *written* as, which is rarely what was typed.\n *\n * A relative path on the command line is relative to the command's host directory; in a settings file it is relative to\n * that file's own directory. Those differ the moment the command runs anywhere but the directory\n * holding the file, and writing the string verbatim produces a silently wrong entry:\n *\n * ```\n * $ cd ~/workspace/app/packages/fubar\n * $ codework plugin add ./plugins/x.ts # means packages/fubar/plugins/x.ts\n * → the project is ~/workspace/app, so the entry lands in app/.codework/settings.jsonc\n * → written verbatim, the harness loads app/.codework/plugins/x.ts ← a different file\n * ```\n *\n * With both ends inside one project the entry is written relative to the file, which is portable\n * to any checkout of that repository and therefore worth committing. Otherwise -- a `-g` write\n * into `<home>`, a `--user-config-dir` elsewhere, or a target outside the project -- relative\n * would be a lie, and an absolute path means the same thing read from anywhere.\n *\n * A package spec is returned untouched: it names no location.\n */\nexport const written = Effect.fn(\"CLI.plugin.written\")(function* (\n\treference: string,\n\tinput: { readonly hostDir: string; readonly file: string; readonly root: string | undefined },\n) {\n\tconst nodePath = yield* Path.Path;\n\tconst target = yield* Plugin.parse(reference, input.hostDir).pipe(Effect.option);\n\tif (Option.isNone(target) || target.value.kind !== \"local\") return reference;\n\n\tconst absolute = target.value.path;\n\tconst inside = (root: string, path: string) => path === root || path.startsWith(`${root}${nodePath.sep}`);\n\tif (input.root !== undefined && inside(input.root, input.file) && inside(input.root, absolute)) {\n\t\tconst relative = nodePath.relative(nodePath.dirname(input.file), absolute);\n\t\treturn relative.startsWith(\"..\") ? relative : `./${relative}`;\n\t}\n\treturn absolute;\n});\n\n/** `reference` selects `entry` when any spelling of one is a spelling of the other. */\nexport const matches = (entry: Entry, spelled: ReadonlySet<string>) =>\n\t[...spelled].some((alias) => entry.answers.has(alias));\n\n/** Every entry connected to a reference through a package spelling or declared plugin ID. */\nexport const matching = (entries: ReadonlyArray<Entry>, spelled: ReadonlySet<string>) => {\n\tconst answers = new Set(spelled);\n\tconst found = new Set<Entry>();\n\tfor (;;) {\n\t\tconst next = entries.filter(\n\t\t\t(entry) => !found.has(entry) && [...entry.answers].some((answer) => answers.has(answer)),\n\t\t);\n\t\tif (next.length === 0) return found as ReadonlySet<Entry>;\n\t\tfor (const entry of next) {\n\t\t\tfound.add(entry);\n\t\t\tfor (const answer of entry.answers) answers.add(answer);\n\t\t}\n\t}\n};\n\nexport const readPlugins = Effect.fn(\"CLI.plugin.readPlugins\")(function* (path: string) {\n\tconst fs = yield* FileSystem.FileSystem;\n\tconst exists = yield* fs.exists(path);\n\tconst source = exists ? yield* fs.readFileString(path) : \"{}\";\n\tconst errors: ParseError[] = [];\n\tconst document: unknown = parseJsonc(source, errors, { allowTrailingComma: true });\n\tif (errors.length > 0 || typeof document !== \"object\" || document === null || Array.isArray(document)) {\n\t\treturn yield* new InvalidInputError({ message: `${path} is not a valid settings file` });\n\t}\n\tconst plugins = (document as { plugins?: unknown }).plugins;\n\tif (plugins !== undefined && !Array.isArray(plugins)) {\n\t\treturn yield* new InvalidInputError({ message: `${path}: \"plugins\" must be an array` });\n\t}\n\treturn { source, plugins: (plugins ?? []) as ReadonlyArray<unknown> };\n});\n\nexport const writePlugins = Effect.fn(\"CLI.plugin.writePlugins\")(function* (\n\tpath: string,\n\tsource: string,\n\tplugins: ReadonlyArray<unknown>,\n) {\n\tconst fs = yield* FileSystem.FileSystem;\n\tconst nodePath = yield* Path.Path;\n\tconst edited = applyEdits(\n\t\tsource,\n\t\tmodify(source, [\"plugins\"], plugins, { formattingOptions: { tabSize: 2, insertSpaces: false } }),\n\t);\n\tconst directory = nodePath.dirname(path);\n\tyield* fs.makeDirectory(directory, { recursive: true });\n\tconst mode = (yield* fs.exists(path)) ? (yield* fs.stat(path)).mode & 0o777 : 0o600;\n\tconst temporary = yield* fs.makeTempFile({ directory, prefix: `.${nodePath.basename(path)}.`, suffix: \".tmp\" });\n\tyield* fs\n\t\t.writeFileString(temporary, edited.endsWith(\"\\n\") ? edited : `${edited}\\n`)\n\t\t.pipe(\n\t\t\tEffect.andThen(fs.chmod(temporary, mode)),\n\t\t\tEffect.andThen(fs.rename(temporary, path)),\n\t\t\tEffect.ensuring(fs.remove(temporary, { force: true }).pipe(Effect.ignore)),\n\t\t);\n});\n\n/**\n * Serialize one settings read-modify-rename across CLI processes.\n *\n * The install or inspection that precedes an edit stays outside this scope; only the local edit is\n * locked, so unrelated downloads do not wait behind one another.\n */\nexport const withPluginsLock = <A, E, R>(path: string, edit: Effect.Effect<A, E, R>) =>\n\tEffect.gen(function* () {\n\t\tconst fs = yield* FileSystem.FileSystem;\n\t\tconst nodePath = yield* Path.Path;\n\t\tyield* fs.makeDirectory(nodePath.dirname(path), { recursive: true });\n\t\tyield* Plugin.settingsLock(\n\t\t\t`${path}.lock`,\n\t\t\t() => new InvalidInputError({ message: `timed out waiting to edit ${path}` }),\n\t\t);\n\t\treturn yield* edit;\n\t}).pipe(Effect.scoped);\n\n/**\n * Which file the edit lands in.\n *\n * A plugin belongs to a project by default — it is part of how that repository is worked on, so\n * the entry belongs in a file the repository can commit. `--global` writes the user settings file\n * instead, the way `npm -g` installs outside a package: `<--home>/settings.jsonc`, or the\n * `--user-config-dir` one that replaces it.\n *\n * The project is found the way the harness finds it: the nearest ancestor holding a `.codework`\n * directory, so a command run from `packages/app` edits the repository's own file rather than\n * creating a second one beside it. When no ancestor has one, the project begins here -- the\n * directory is created and the caller is told, because that decision changes where every future\n * plugin entry lands, and a mistyped `cd` is the way it goes wrong.\n *\n * There is nothing to warn about between layers: plugin entries from every layer accumulate, so a\n * user-wide entry still applies inside a project that declares its own.\n */\nexport const resolveTarget = Effect.fn(\"CLI.plugin.resolveTarget\")(function* (\n\tshared: Shared,\n\tglobal: boolean,\n\t/**\n\t * Where to discover the project from, when it is not the shell's directory.\n\t *\n\t * A session's host directory is the only other honest answer: it is a declared host path. The\n\t * session's *space* is not, and neither is its project -- a `Project` is env-independent by\n\t * design, so it has no host directory to offer.\n\t */\n\tfrom?: string,\n\t/** Only `plugin add` may establish a project marker when no project exists yet. */\n\tcreate = true,\n) {\n\tconst fs = yield* FileSystem.FileSystem;\n\tconst nodePath = yield* Path.Path;\n\tconst hostCwd = nodePath.resolve(\".\");\n\t// The linked session's host directory, or -- with none -- the one the command runs in.\n\tconst hostDir = from ?? hostCwd;\n\tconst home = yield* Global.resolve(Option.isNone(shared.home) ? {} : { home: shared.home.value });\n\tconst root = global ? undefined : yield* Settings.projectRoot(hostDir, home.home);\n\t// `paths` is ordered lowest priority first: the user layer, then the project.\n\tconst groups = Settings.paths({\n\t\thome: home.home,\n\t\t...(root === undefined ? {} : { root }),\n\t\t...userLayer(shared, hostCwd),\n\t});\n\tconst chosen = global ? 0 : 1;\n\t// An empty group is the project layer saying there is no project above this directory. Then\n\t// this directory becomes one -- reported, not silent, because the marker shadows any outer\n\t// project from now on, so a `.codework/` created by a mistyped `cd` is worth spotting at once.\n\tconst found = groups[chosen] ?? [];\n\tif (found.length > 0) {\n\t\tconst existing = yield* Effect.findFirst(found, (candidate) => fs.exists(candidate));\n\t\treturn {\n\t\t\tpath: Option.getOrElse(existing, () => found[0]!),\n\t\t\t...(root === undefined ? {} : { root }),\n\t\t} satisfies Target;\n\t}\n\tconst marker = nodePath.join(hostDir, \".codework\");\n\t// `created` is reported either way: with `create` unset the marker is named, not made, so a\n\t// caller can say what its write is about to establish without establishing it early.\n\tif (!create)\n\t\treturn { path: nodePath.join(marker, \"settings.jsonc\"), created: marker, root: hostDir } satisfies Target;\n\tyield* fs.makeDirectory(marker, { recursive: true });\n\treturn { path: nodePath.join(marker, \"settings.jsonc\"), created: marker, root: hostDir } satisfies Target;\n});\n"],"mappings":";;;;;;;;;;AAwBA,MAAa,aAAa,QAAgB,YACzC,OAAO,OAAO,OAAO,aAAa,IAC/B,CAAC,IACD,EAAE,eAAe,SAAS,cAAc,OAAO,cAAc,OAAO,OAAO,EAAE;;AAWjF,MAAM,YAAY,UAAuC;CACxD,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO,KAAA;CACxD,MAAM,EAAE,SAAS,YAAY;CAC7B,OAAO,OAAO,YAAY,WAAW,UAAU,KAAA;AAChD;;AAGA,MAAM,QAAQ,UAAuC;CACpD,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO,KAAA;CACxD,MAAM,EAAE,WAAW;CACnB,OAAO,OAAO,WAAW,WAAW,SAAS,KAAA;AAC9C;;;;;;;;AASA,MAAM,WAAW,WAAmB,cACnC,OAAO,UAAU,WAAW,SAAS,CAAC,CAAC,KACtC,OAAO,KAAK,cAAc,CAAC,WAAW,SAAS,CAA0B,GAGzE,OAAO,oBAAoB,CAAC,SAAS,CAA0B,CAChE;;AAGD,MAAa,aAAa,WAAmB,cAC5C,OAAO,IAAI,QAAQ,WAAW,SAAS,IAAI,UAAU,IAAI,IAAI,KAAK,CAAC;;;;;;;;;;;;;;;AAsBpE,MAAa,WAAW,OAAO,GAAG,qBAAqB,CAAC,CAAC,WACxD,SACA,MACA,OACC;CAED,MAAM,aAAY,OADM,KAAK,KAAA,CACF,QAAQ,IAAI;CACvC,MAAM,UAAmB,CAAC;CAC1B,KAAK,MAAM,SAAS,SAAS;EAC5B,MAAM,0BAAU,IAAI,IAAY;EAChC,MAAM,KAAK,KAAK,KAAK;EACrB,IAAI,OAAO,KAAA,GAAW,QAAQ,IAAI,EAAE;EACpC,MAAM,SAAS,SAAS,KAAK;EAC7B,IAAI,WAAW,KAAA,GAAW;GACzB,KAAK,MAAM,SAAS,OAAO,QAAQ,QAAQ,SAAS,GAAG,QAAQ,IAAI,KAAK;GACxE,MAAM,WAAW,OAAO,OAAO,QAAQ,QAAQ;IAC9C;IACA,SAAS;IACT;IACA,SAAS,OAAO;GACjB,CAAC,CAAC,CAAC,KAAK,OAAO,MAAM;GACrB,IAAI,OAAO,OAAO,QAAQ,GAAG;IAC5B,QAAQ,IAAI,SAAS,MAAM,EAAE;IAC7B,IAAI,SAAS,MAAM,SAAS,KAAA,GAAW,QAAQ,IAAI,SAAS,MAAM,IAAI;GACvE;EACD;EACA,QAAQ,KAAK;GAAE;GAAO;GAAS,OAAO,OAAO,UAAU;EAAS,CAAC;CAClE;CACA,OAAO;AACR,CAAC;;;;;;;;;;;;;;;;;;;;;;AAuBD,MAAa,UAAU,OAAO,GAAG,oBAAoB,CAAC,CAAC,WACtD,WACA,OACC;CACD,MAAM,WAAW,OAAO,KAAK;CAC7B,MAAM,SAAS,OAAO,OAAO,MAAM,WAAW,MAAM,OAAO,CAAC,CAAC,KAAK,OAAO,MAAM;CAC/E,IAAI,OAAO,OAAO,MAAM,KAAK,OAAO,MAAM,SAAS,SAAS,OAAO;CAEnE,MAAM,WAAW,OAAO,MAAM;CAC9B,MAAM,UAAU,MAAc,SAAiB,SAAS,QAAQ,KAAK,WAAW,GAAG,OAAO,SAAS,KAAK;CACxG,IAAI,MAAM,SAAS,KAAA,KAAa,OAAO,MAAM,MAAM,MAAM,IAAI,KAAK,OAAO,MAAM,MAAM,QAAQ,GAAG;EAC/F,MAAM,WAAW,SAAS,SAAS,SAAS,QAAQ,MAAM,IAAI,GAAG,QAAQ;EACzE,OAAO,SAAS,WAAW,IAAI,IAAI,WAAW,KAAK;CACpD;CACA,OAAO;AACR,CAAC;;AAGD,MAAa,WAAW,OAAc,YACrC,CAAC,GAAG,OAAO,CAAC,CAAC,MAAM,UAAU,MAAM,QAAQ,IAAI,KAAK,CAAC;;AAGtD,MAAa,YAAY,SAA+B,YAAiC;CACxF,MAAM,UAAU,IAAI,IAAI,OAAO;CAC/B,MAAM,wBAAQ,IAAI,IAAW;CAC7B,SAAS;EACR,MAAM,OAAO,QAAQ,QACnB,UAAU,CAAC,MAAM,IAAI,KAAK,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,CAAC,MAAM,WAAW,QAAQ,IAAI,MAAM,CAAC,CACxF;EACA,IAAI,KAAK,WAAW,GAAG,OAAO;EAC9B,KAAK,MAAM,SAAS,MAAM;GACzB,MAAM,IAAI,KAAK;GACf,KAAK,MAAM,UAAU,MAAM,SAAS,QAAQ,IAAI,MAAM;EACvD;CACD;AACD;AAEA,MAAa,cAAc,OAAO,GAAG,wBAAwB,CAAC,CAAC,WAAW,MAAc;CACvF,MAAM,KAAK,OAAO,WAAW;CAE7B,MAAM,UAAS,OADO,GAAG,OAAO,IAAI,KACZ,OAAO,GAAG,eAAe,IAAI,IAAI;CACzD,MAAM,SAAuB,CAAC;CAC9B,MAAM,WAAoBA,MAAW,QAAQ,QAAQ,EAAE,oBAAoB,KAAK,CAAC;CACjF,IAAI,OAAO,SAAS,KAAK,OAAO,aAAa,YAAY,aAAa,QAAQ,MAAM,QAAQ,QAAQ,GACnG,OAAO,OAAO,IAAI,kBAAkB,EAAE,SAAS,GAAG,KAAK,+BAA+B,CAAC;CAExF,MAAM,UAAW,SAAmC;CACpD,IAAI,YAAY,KAAA,KAAa,CAAC,MAAM,QAAQ,OAAO,GAClD,OAAO,OAAO,IAAI,kBAAkB,EAAE,SAAS,GAAG,KAAK,8BAA8B,CAAC;CAEvF,OAAO;EAAE;EAAQ,SAAU,WAAW,CAAC;CAA6B;AACrE,CAAC;AAED,MAAa,eAAe,OAAO,GAAG,yBAAyB,CAAC,CAAC,WAChE,MACA,QACA,SACC;CACD,MAAM,KAAK,OAAO,WAAW;CAC7B,MAAM,WAAW,OAAO,KAAK;CAC7B,MAAM,SAAS,WACd,QACA,OAAO,QAAQ,CAAC,SAAS,GAAG,SAAS,EAAE,mBAAmB;EAAE,SAAS;EAAG,cAAc;CAAM,EAAE,CAAC,CAChG;CACA,MAAM,YAAY,SAAS,QAAQ,IAAI;CACvC,OAAO,GAAG,cAAc,WAAW,EAAE,WAAW,KAAK,CAAC;CACtD,MAAM,QAAQ,OAAO,GAAG,OAAO,IAAI,MAAM,OAAO,GAAG,KAAK,IAAI,EAAA,CAAG,OAAO,MAAQ;CAC9E,MAAM,YAAY,OAAO,GAAG,aAAa;EAAE;EAAW,QAAQ,IAAI,SAAS,SAAS,IAAI,EAAE;EAAI,QAAQ;CAAO,CAAC;CAC9G,OAAO,GACL,gBAAgB,WAAW,OAAO,SAAS,IAAI,IAAI,SAAS,GAAG,OAAO,GAAG,CAAC,CAC1E,KACA,OAAO,QAAQ,GAAG,MAAM,WAAW,IAAI,CAAC,GACxC,OAAO,QAAQ,GAAG,OAAO,WAAW,IAAI,CAAC,GACzC,OAAO,SAAS,GAAG,OAAO,WAAW,EAAE,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,MAAM,CAAC,CAC1E;AACF,CAAC;;;;;;;AAQD,MAAa,mBAA4B,MAAc,SACtD,OAAO,IAAI,aAAa;CACvB,MAAM,KAAK,OAAO,WAAW;CAC7B,MAAM,WAAW,OAAO,KAAK;CAC7B,OAAO,GAAG,cAAc,SAAS,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;CACnE,OAAO,OAAO,aACb,GAAG,KAAK,cACF,IAAI,kBAAkB,EAAE,SAAS,6BAA6B,OAAO,CAAC,CAC7E;CACA,OAAO,OAAO;AACf,CAAC,CAAC,CAAC,KAAK,OAAO,MAAM;;;;;;;;;;;;;;;;;;AAmBtB,MAAa,gBAAgB,OAAO,GAAG,0BAA0B,CAAC,CAAC,WAClE,QACA,QAQA,MAEA,SAAS,MACR;CACD,MAAM,KAAK,OAAO,WAAW;CAC7B,MAAM,WAAW,OAAO,KAAK;CAC7B,MAAM,UAAU,SAAS,QAAQ,GAAG;CAEpC,MAAM,UAAU,QAAQ;CACxB,MAAM,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,MAAM,OAAO,KAAK,MAAM,CAAC;CAChG,MAAM,OAAO,SAAS,KAAA,IAAY,OAAO,SAAS,YAAY,SAAS,KAAK,IAAI;CAWhF,MAAM,QATS,SAAS,MAAM;EAC7B,MAAM,KAAK;EACX,GAAI,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,KAAK;EACrC,GAAG,UAAU,QAAQ,OAAO;CAC7B,CAKmB,CAAC,CAJL,SAAS,IAAI,MAII,CAAC;CACjC,IAAI,MAAM,SAAS,GAAG;EACrB,MAAM,WAAW,OAAO,OAAO,UAAU,QAAQ,cAAc,GAAG,OAAO,SAAS,CAAC;EACnF,OAAO;GACN,MAAM,OAAO,UAAU,gBAAgB,MAAM,EAAG;GAChD,GAAI,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,KAAK;EACtC;CACD;CACA,MAAM,SAAS,SAAS,KAAK,SAAS,WAAW;CAGjD,IAAI,CAAC,QACJ,OAAO;EAAE,MAAM,SAAS,KAAK,QAAQ,gBAAgB;EAAG,SAAS;EAAQ,MAAM;CAAQ;CACxF,OAAO,GAAG,cAAc,QAAQ,EAAE,WAAW,KAAK,CAAC;CACnD,OAAO;EAAE,MAAM,SAAS,KAAK,QAAQ,gBAAgB;EAAG,SAAS;EAAQ,MAAM;CAAQ;AACxF,CAAC"}
|