@codeworksh/cli 0.0.1-dev.20260925125202 → 0.1.0-canary.15.1.g86693cf5

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.
Files changed (75) hide show
  1. package/acp-DK_xXx9y.mjs +494 -0
  2. package/acp-DK_xXx9y.mjs.map +1 -0
  3. package/{add-CIQSfxan.mjs → add-B9gIgFb3.mjs} +13 -12
  4. package/add-B9gIgFb3.mjs.map +1 -0
  5. package/{catalog-C5fDCgtx.mjs → catalog-D5BxyTfH.mjs} +5 -5
  6. package/catalog-D5BxyTfH.mjs.map +1 -0
  7. package/{check-B7bP5lRI.mjs → check-B9PJ6rn_.mjs} +6 -5
  8. package/check-B9PJ6rn_.mjs.map +1 -0
  9. package/{entries-CSY5N6jH.mjs → entries-CzgqHfKQ.mjs} +15 -14
  10. package/entries-CzgqHfKQ.mjs.map +1 -0
  11. package/error-C9ACQhhu.mjs +610 -0
  12. package/error-C9ACQhhu.mjs.map +1 -0
  13. package/{harness-DXAwGk0B.mjs → harness-6d8TlAVk.mjs} +4 -3
  14. package/harness-6d8TlAVk.mjs.map +1 -0
  15. package/index.mjs +20 -21
  16. package/index.mjs.map +1 -1
  17. package/{install-B02SIXwF.mjs → install-Cw6h6IRB.mjs} +7 -6
  18. package/install-Cw6h6IRB.mjs.map +1 -0
  19. package/{link-CA9XdPwj.mjs → link-B7iVolAn.mjs} +6 -5
  20. package/{link-CA9XdPwj.mjs.map → link-B7iVolAn.mjs.map} +1 -1
  21. package/{list-Bbo4XnG_.mjs → list-3hYMW1Wo.mjs} +11 -10
  22. package/list-3hYMW1Wo.mjs.map +1 -0
  23. package/{list-Ce1Ry4JN.mjs → list-BAonMfru.mjs} +6 -5
  24. package/list-BAonMfru.mjs.map +1 -0
  25. package/{login-CagARGqW.mjs → login-CXelgTth.mjs} +4 -4
  26. package/{login-CagARGqW.mjs.map → login-CXelgTth.mjs.map} +1 -1
  27. package/{logout-CYYtjZL3.mjs → logout-DrQQPxEW.mjs} +4 -4
  28. package/{logout-CYYtjZL3.mjs.map → logout-DrQQPxEW.mjs.map} +1 -1
  29. package/package-7FOUqcPO.mjs +6 -0
  30. package/package-7FOUqcPO.mjs.map +1 -0
  31. package/package.json +10 -34
  32. package/{providers-CoYj1SYv.mjs → providers-DksUoT4Z.mjs} +6 -5
  33. package/providers-DksUoT4Z.mjs.map +1 -0
  34. package/{refresh-8_nfeYNZ.mjs → refresh-CHBg5ya9.mjs} +4 -4
  35. package/{refresh-8_nfeYNZ.mjs.map → refresh-CHBg5ya9.mjs.map} +1 -1
  36. package/{refresh-D2a1ikea.mjs → refresh-DPBpboO0.mjs} +6 -5
  37. package/refresh-DPBpboO0.mjs.map +1 -0
  38. package/{reload-C5ysPM58.mjs → reload-DDsh7kFG.mjs} +3 -3
  39. package/{reload-C5ysPM58.mjs.map → reload-DDsh7kFG.mjs.map} +1 -1
  40. package/{remove-BkbspSED.mjs → remove-__JfeHO-.mjs} +6 -5
  41. package/remove-__JfeHO-.mjs.map +1 -0
  42. package/{run-CnxjZIGy.mjs → run-D47jXr5Q.mjs} +17 -18
  43. package/run-D47jXr5Q.mjs.map +1 -0
  44. package/{runtime-B3dlWGfs.mjs → runtime-D4zyJPrh.mjs} +9 -2
  45. package/runtime-D4zyJPrh.mjs.map +1 -0
  46. package/{serve-DaD7Eijz.mjs → serve-gOODO9pv.mjs} +44 -39
  47. package/serve-gOODO9pv.mjs.map +1 -0
  48. package/{settings-BZXmb54m.mjs → settings-DDkmAxW5.mjs} +12 -11
  49. package/settings-DDkmAxW5.mjs.map +1 -0
  50. package/{shared-BaTfajJ2.mjs → shared-DFB2--6V.mjs} +5 -4
  51. package/shared-DFB2--6V.mjs.map +1 -0
  52. package/{status-qJImmv6V.mjs → status-BNc5JZ1C.mjs} +4 -4
  53. package/{status-qJImmv6V.mjs.map → status-BNc5JZ1C.mjs.map} +1 -1
  54. package/{update-CxcNv_t0.mjs → update-CaW7oDOl.mjs} +7 -6
  55. package/update-CaW7oDOl.mjs.map +1 -0
  56. package/add-CIQSfxan.mjs.map +0 -1
  57. package/catalog-C5fDCgtx.mjs.map +0 -1
  58. package/check-B7bP5lRI.mjs.map +0 -1
  59. package/entries-CSY5N6jH.mjs.map +0 -1
  60. package/error-D0C5K2Av.mjs +0 -10376
  61. package/error-D0C5K2Av.mjs.map +0 -1
  62. package/harness-DXAwGk0B.mjs.map +0 -1
  63. package/index.d.mts +0 -24
  64. package/install-B02SIXwF.mjs.map +0 -1
  65. package/list-Bbo4XnG_.mjs.map +0 -1
  66. package/list-Ce1Ry4JN.mjs.map +0 -1
  67. package/providers-CoYj1SYv.mjs.map +0 -1
  68. package/refresh-D2a1ikea.mjs.map +0 -1
  69. package/remove-BkbspSED.mjs.map +0 -1
  70. package/run-CnxjZIGy.mjs.map +0 -1
  71. package/runtime-B3dlWGfs.mjs.map +0 -1
  72. package/serve-DaD7Eijz.mjs.map +0 -1
  73. package/settings-BZXmb54m.mjs.map +0 -1
  74. package/shared-BaTfajJ2.mjs.map +0 -1
  75. package/update-CxcNv_t0.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve-gOODO9pv.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.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}),\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/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 { OAuth } from \"./oauth.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\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.layerHttp({ group: Contract.Api, path: \"/rpc\", 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.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 { Et as resolve, F as paths, G as required, I as projectRoot, J as lock, L as userConfigDir, V as inspect, Y as parse$1, t as InvalidInputError, z as canonical } from "./error-D0C5K2Av.mjs";
1
+ import { t as InvalidInputError } from "./error-C9ACQhhu.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: required
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$1(reference, input.hostDir).pipe(Effect.option);
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* lock(`${path}.lock`, () => new InvalidInputError({ message: `timed out waiting to edit ${path}` }));
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-BZXmb54m.mjs.map
221
+ //# sourceMappingURL=settings-DDkmAxW5.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-DDkmAxW5.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":"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"}
@@ -1,6 +1,7 @@
1
- import { Et as resolve, f as layer, n as OAuthError, t as InvalidInputError } from "./error-D0C5K2Av.mjs";
2
- import { i as Cmd } from "./runtime-B3dlWGfs.mjs";
1
+ import { i as Cmd } from "./runtime-D4zyJPrh.mjs";
2
+ import { f as layer, n as OAuthError, t as InvalidInputError } from "./error-C9ACQhhu.mjs";
3
3
  import { Effect, Option, Path } from "effect";
4
+ import { Global } from "@codeworksh/harness/effect";
4
5
  import { checkOAuthProvider, oauthProviderLabel, summarizeGitHubCopilot, summarizeOpenAICodex } from "@codeworksh/aikit/oauth/summary";
5
6
  import { GitHubCopilotOAuthClient, JsonGitHubCopilotAuthStorage } from "@codeworksh/aikit/oauth/github/copilot";
6
7
  import { JsonOpenAICodexAuthStorage, OpenAICodexOAuthClient } from "@codeworksh/aikit/oauth/openai/codex";
@@ -104,7 +105,7 @@ const assertServerScope = (authFile) => Effect.gen(function* () {
104
105
  const localOps = (provider, authFile) => Effect.gen(function* () {
105
106
  const shared = yield* Cmd.spec;
106
107
  const path = yield* Path.Path;
107
- const file = Option.isSome(authFile) ? authFile.value : Option.isSome(shared.home) ? path.join((yield* resolve({ home: shared.home.value })).home, "aikit", "auth.json") : void 0;
108
+ const file = Option.isSome(authFile) ? authFile.value : Option.isSome(shared.home) ? path.join((yield* Global.resolve({ home: shared.home.value })).home, "aikit", "auth.json") : void 0;
108
109
  return makeOps(provider, file === void 0 ? {} : { path: file });
109
110
  });
110
111
  /** Run an effect against the RPC server at `url`, discharging the client. */
@@ -112,4 +113,4 @@ const withServer = (url, program) => program.pipe(Effect.provide(layer(url)), Ef
112
113
  //#endregion
113
114
  export { oauthProviderLabel as a, makeOps as i, attempt as n, selectProvider as o, localOps as r, withServer as s, assertServerScope as t };
114
115
 
115
- //# sourceMappingURL=shared-BaTfajJ2.mjs.map
116
+ //# sourceMappingURL=shared-DFB2--6V.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-DFB2--6V.mjs","names":["Client.layer"],"sources":["../../src/cli/cmd/handlers/auth/shared.ts"],"sourcesContent":["/* @effect-diagnostics nodeBuiltinImport:off -- OAuth login opens the system browser. */\n/* @effect-diagnostics globalDate:off -- Stored expiry timestamps are rendered for the user. */\n/* oxlint-disable effecttsgo/async-function -- Aikit OAuth callbacks require Promise-returning functions. */\nimport {\n\tGitHubCopilotOAuthClient,\n\tJsonGitHubCopilotAuthStorage,\n\ttype GitHubCopilotAuthStorage,\n} from \"@codeworksh/aikit/oauth/github/copilot\";\nimport {\n\tJsonOpenAICodexAuthStorage,\n\tOpenAICodexOAuthClient,\n\ttype OpenAICodexAuthStorage,\n} from \"@codeworksh/aikit/oauth/openai/codex\";\nimport { openBrowser, promptLine } from \"@codeworksh/aikit/oauth/interactive\";\nimport {\n\tcheckOAuthProvider,\n\toauthProviderLabel,\n\tsummarizeGitHubCopilot,\n\tsummarizeOpenAICodex,\n\ttype OAuthSummary,\n} from \"@codeworksh/aikit/oauth/summary\";\nimport { Global } from \"@codeworksh/harness/effect\";\nimport { Effect, Option, Path } from \"effect\";\nimport { Client } from \"../../../../server/client.ts\";\nimport type { Contract } from \"../../../../server/contract.ts\";\nimport { InvalidInputError, OAuthError } from \"../../../error.ts\";\nimport { Cmd } from \"../../cmd.ts\";\n\nexport type Provider = Contract.OAuthProvider;\n\n// The wire shape and aikit's summary are the same record.\nexport type Summary = Contract.OAuthInfo & OAuthSummary;\n\nconst announce = (\n\tinfo: { url: string; userCode?: string | undefined; instructions?: string | undefined },\n\tbrowser: boolean,\n): void => {\n\tprocess.stderr.write(\n\t\t`${info.instructions ?? \"Complete authentication in your browser.\"}\\n${\n\t\t\tinfo.userCode === undefined ? \"\" : `Enter code: ${info.userCode}\\n`\n\t\t}${info.url}\\n`,\n\t);\n\tif (browser) {\n\t\tvoid openBrowser(info.url, (error) => void process.stderr.write(`Failed to open browser: ${error.message}\\n`));\n\t}\n};\n\nexport interface LoginOptions {\n\treadonly browser: boolean;\n\treadonly device: boolean;\n\treadonly enterprise: Option.Option<string>;\n\treadonly enableModels: boolean;\n}\n\nexport interface Ops {\n\treadonly path: string;\n\treadonly login: (options: LoginOptions) => Promise<{ wire: Contract.OAuthCredentials; summary: Summary }>;\n\treadonly stored: () => Promise<Summary | undefined>;\n\treadonly refreshed: () => Promise<Summary | undefined>;\n\treadonly logout: () => Promise<void>;\n}\n\n/** Holds nothing: a server's credentials live on the server, not on this disk. */\nconst transient: OpenAICodexAuthStorage & GitHubCopilotAuthStorage = {\n\tget: async () => undefined,\n\tset: async () => {},\n\tclear: async () => {},\n};\n\nconst codexOps = (storage: OpenAICodexAuthStorage, path: string): Ops => {\n\tconst client = new OpenAICodexOAuthClient({ storage });\n\treturn {\n\t\tpath,\n\t\tlogin: async (options) => {\n\t\t\tconst credentials = await client.login({\n\t\t\t\tdevice: options.device,\n\t\t\t\tonAuth: (info) => announce(info, options.browser),\n\t\t\t\tonProgress: (message) => void process.stderr.write(`${message}\\n`),\n\t\t\t\tonPrompt: (prompt) => promptLine(prompt.message),\n\t\t\t});\n\t\t\treturn { wire: { provider: \"openai-codex\", ...credentials }, summary: summarizeOpenAICodex(credentials) };\n\t\t},\n\t\tstored: async () => {\n\t\t\tconst credentials = await storage.get();\n\t\t\treturn credentials && summarizeOpenAICodex(credentials);\n\t\t},\n\t\trefreshed: async () => {\n\t\t\tconst credentials = await client.getCredentials();\n\t\t\treturn credentials && summarizeOpenAICodex(credentials);\n\t\t},\n\t\tlogout: () => client.logout(),\n\t};\n};\n\nconst copilotOps = (storage: GitHubCopilotAuthStorage, path: string): Ops => {\n\tconst client = new GitHubCopilotOAuthClient({ storage });\n\tconst read = async () => {\n\t\tconst credentials = await storage.get();\n\t\treturn credentials && summarizeGitHubCopilot(credentials);\n\t};\n\treturn {\n\t\tpath,\n\t\tlogin: async (options) => {\n\t\t\tconst credentials = await client.login({\n\t\t\t\t...(Option.isSome(options.enterprise) && { enterpriseUrl: options.enterprise.value }),\n\t\t\t\tenableModels: options.enableModels,\n\t\t\t\tonAuth: (info) => announce(info, options.browser),\n\t\t\t\tonProgress: (message) => void process.stderr.write(`${message}\\n`),\n\t\t\t});\n\t\t\treturn { wire: { provider: \"github-copilot\", ...credentials }, summary: summarizeGitHubCopilot(credentials) };\n\t\t},\n\t\tstored: read,\n\t\t// GitHub OAuth tokens never expire, so there is nothing to refresh.\n\t\trefreshed: read,\n\t\tlogout: () => client.logout(),\n\t};\n};\n\nexport const makeOps = (provider: Provider, options: { path?: string | undefined; persist?: boolean } = {}): Ops => {\n\tconst file = options.path === undefined ? {} : { path: options.path };\n\tif (provider === \"openai-codex\") {\n\t\tconst storage = options.persist === false ? undefined : new JsonOpenAICodexAuthStorage(file);\n\t\treturn codexOps(storage ?? transient, storage?.path ?? \"\");\n\t}\n\tconst storage = options.persist === false ? undefined : new JsonGitHubCopilotAuthStorage(file);\n\treturn copilotOps(storage ?? transient, storage?.path ?? \"\");\n};\n\nexport const attempt = <A>(message: string, run: () => Promise<A>) =>\n\tEffect.tryPromise({ try: run, catch: (cause) => new OAuthError({ message, cause }) });\n\n/** The provider named by the two mutually exclusive flags. */\nexport const selectProvider = (flags: {\n\treadonly openaiCodex: boolean;\n\treadonly githubCopilot: boolean;\n}): Effect.Effect<Provider, InvalidInputError> => {\n\tconst checked = checkOAuthProvider(flags);\n\treturn checked.ok\n\t\t? Effect.succeed(checked.provider)\n\t\t: Effect.fail(new InvalidInputError({ message: checked.message }));\n};\n\n/** Reject the local-credential flags when the credentials live on a server. */\nexport const assertServerScope = (authFile: Option.Option<string>) =>\n\tEffect.gen(function* () {\n\t\tconst shared = yield* Cmd.spec;\n\t\tif (Option.isSome(authFile) || Option.isSome(shared.home)) {\n\t\t\treturn yield* new InvalidInputError({\n\t\t\t\tmessage: \"--auth-file and --home belong on codework serve when using --server\",\n\t\t\t});\n\t\t}\n\t});\n\n/** Credential operations against this machine's auth.json. */\nexport const localOps = (provider: Provider, authFile: Option.Option<string>) =>\n\tEffect.gen(function* () {\n\t\tconst shared = yield* Cmd.spec;\n\t\tconst path = yield* Path.Path;\n\t\tconst file = Option.isSome(authFile)\n\t\t\t? authFile.value\n\t\t\t: Option.isSome(shared.home)\n\t\t\t\t? path.join((yield* Global.resolve({ home: shared.home.value })).home, \"aikit\", \"auth.json\")\n\t\t\t\t: undefined;\n\t\treturn makeOps(provider, file === undefined ? {} : { path: file });\n\t});\n\n/** Run an effect against the RPC server at `url`, discharging the client. */\nexport const withServer = <A, E, R>(url: string, program: Effect.Effect<A, E, R>) =>\n\tprogram.pipe(Effect.provide(Client.layer(url)), Effect.scoped);\n\nexport { Client, oauthProviderLabel };\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { d as writeOut, i as reportFailure, n as OAuthError, p as make } from "./error-D0C5K2Av.mjs";
2
- import { i as Cmd, t as handler } from "./runtime-B3dlWGfs.mjs";
3
- import { a as oauthProviderLabel, n as attempt, o as selectProvider, r as localOps, s as withServer, t as assertServerScope } from "./shared-BaTfajJ2.mjs";
1
+ import { i as Cmd, t as handler } from "./runtime-D4zyJPrh.mjs";
2
+ import { d as writeOut, i as reportFailure, n as OAuthError, p as make } from "./error-C9ACQhhu.mjs";
3
+ import { a as oauthProviderLabel, n as attempt, o as selectProvider, r as localOps, s as withServer, t as assertServerScope } from "./shared-DFB2--6V.mjs";
4
4
  import { Effect, Option } from "effect";
5
5
  import { formatOAuthSummary, oauthNotice } from "@codeworksh/aikit/oauth/summary";
6
6
  //#region src/cli/cmd/handlers/auth/status.ts
@@ -28,4 +28,4 @@ var status_default = handler(Cmd.commands.auth.commands.status, Effect.fn("CLI.a
28
28
  //#endregion
29
29
  export { status_default as default };
30
30
 
31
- //# sourceMappingURL=status-qJImmv6V.mjs.map
31
+ //# sourceMappingURL=status-BNc5JZ1C.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"status-qJImmv6V.mjs","names":["Runtime.handler","Client.make"],"sources":["../../src/cli/cmd/handlers/auth/status.ts"],"sourcesContent":["import { formatOAuthSummary, oauthNotice } from \"@codeworksh/aikit/oauth/summary\";\nimport { Effect, Option } from \"effect\";\nimport { Runtime } from \"../../../../framework/runtime.ts\";\nimport { OAuthError, reportFailure } from \"../../../error.ts\";\nimport { 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.status,\n\tEffect.fn(\"CLI.auth.status\")(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 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.status\"]({ 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* 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.stored());\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* writeOut(formatOAuthSummary(summary, { json }));\n\t\t});\n\n\t\treturn yield* program.pipe(Effect.catch(reportFailure));\n\t}),\n);\n"],"mappings":";;;;;;AAgBA,IAAA,iBAAeA,QACd,IAAI,SAAS,KAAK,SAAS,QAC3B,OAAO,GAAG,iBAAiB,CAAC,CAAC,WAAW,EAAE,QAAQ,aAAa,eAAe,UAAU,QAAQ;CA4B/F,OAAO,OA3BS,OAAO,IAAI,aAAa;EACvC,MAAM,WAAW,OAAO,eAAe;GAAE;GAAa;EAAc,CAAC;EACrE,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,cAAc,CAAC,EAAE,SAAS,CAAC;IACnD,IAAI,SAAS,MACZ,OAAO,OAAO,IAAI,WAAW,EAAE,SAAS,YAAY,WAAW,UAAU,YAAY,EAAE,CAAC;IAEzF,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,OAAO,CAAC;EACvF,IAAI,YAAY,KAAA,GACf,OAAO,OAAO,IAAI,WAAW,EAAE,SAAS,YAAY,WAAW,UAAU,IAAI,IAAI,EAAE,CAAC;EAErF,OAAO,SAAS,mBAAmB,SAAS,EAAE,KAAK,CAAC,CAAC;CACtD,CAEoB,CAAC,CAAC,KAAK,OAAO,MAAM,aAAa,CAAC;AACvD,CAAC,CACF"}
1
+ {"version":3,"file":"status-BNc5JZ1C.mjs","names":["Runtime.handler","Client.make"],"sources":["../../src/cli/cmd/handlers/auth/status.ts"],"sourcesContent":["import { formatOAuthSummary, oauthNotice } from \"@codeworksh/aikit/oauth/summary\";\nimport { Effect, Option } from \"effect\";\nimport { Runtime } from \"../../../../framework/runtime.ts\";\nimport { OAuthError, reportFailure } from \"../../../error.ts\";\nimport { 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.status,\n\tEffect.fn(\"CLI.auth.status\")(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 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.status\"]({ 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* 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.stored());\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* writeOut(formatOAuthSummary(summary, { json }));\n\t\t});\n\n\t\treturn yield* program.pipe(Effect.catch(reportFailure));\n\t}),\n);\n"],"mappings":";;;;;;AAgBA,IAAA,iBAAeA,QACd,IAAI,SAAS,KAAK,SAAS,QAC3B,OAAO,GAAG,iBAAiB,CAAC,CAAC,WAAW,EAAE,QAAQ,aAAa,eAAe,UAAU,QAAQ;CA4B/F,OAAO,OA3BS,OAAO,IAAI,aAAa;EACvC,MAAM,WAAW,OAAO,eAAe;GAAE;GAAa;EAAc,CAAC;EACrE,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,cAAc,CAAC,EAAE,SAAS,CAAC;IACnD,IAAI,SAAS,MACZ,OAAO,OAAO,IAAI,WAAW,EAAE,SAAS,YAAY,WAAW,UAAU,YAAY,EAAE,CAAC;IAEzF,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,OAAO,CAAC;EACvF,IAAI,YAAY,KAAA,GACf,OAAO,OAAO,IAAI,WAAW,EAAE,SAAS,YAAY,WAAW,UAAU,IAAI,IAAI,EAAE,CAAC;EAErF,OAAO,SAAS,mBAAmB,SAAS,EAAE,KAAK,CAAC,CAAC;CACtD,CAEoB,CAAC,CAAC,KAAK,OAAO,MAAM,aAAa,CAAC;AACvD,CAAC,CACF"}
@@ -1,7 +1,8 @@
1
- import { B as definition, d as writeOut, i as reportFailure, q as update } from "./error-D0C5K2Av.mjs";
2
- import { i as Cmd, t as handler } from "./runtime-B3dlWGfs.mjs";
3
- import { a as targeted, i as read, n as local, r as probe, t as fetchable } from "./entries-CSY5N6jH.mjs";
1
+ import { i as Cmd, t as handler } from "./runtime-D4zyJPrh.mjs";
2
+ import { d as writeOut, i as reportFailure } from "./error-C9ACQhhu.mjs";
3
+ import { a as targeted, i as read, n as local, r as probe, t as fetchable } from "./entries-CzgqHfKQ.mjs";
4
4
  import { Effect, Option } from "effect";
5
+ import { Plugin } from "@codeworksh/harness/effect";
5
6
  //#region src/cli/cmd/handlers/plugin/update.ts
6
7
  /**
7
8
  * Take whatever `check` found.
@@ -24,10 +25,10 @@ var update_default = handler(Cmd.commands.plugin.commands.update, Effect.fn("CLI
24
25
  yield* local(entry, spec);
25
26
  continue;
26
27
  }
27
- const result = yield* update(target, cache, {
28
+ const result = yield* Plugin.update(target, cache, {
28
29
  probe: probe(cache, entry.from),
29
30
  from: entry.from,
30
- validate: (fetched) => definition(fetched.entrypoint, entry.reference).pipe(Effect.asVoid)
31
+ validate: (fetched) => Plugin.definition(fetched.entrypoint, entry.reference).pipe(Effect.asVoid)
31
32
  }).pipe(Effect.result);
32
33
  if (result._tag === "Failure") {
33
34
  failed += 1;
@@ -47,4 +48,4 @@ var update_default = handler(Cmd.commands.plugin.commands.update, Effect.fn("CLI
47
48
  //#endregion
48
49
  export { update_default as default };
49
50
 
50
- //# sourceMappingURL=update-CxcNv_t0.mjs.map
51
+ //# sourceMappingURL=update-CaW7oDOl.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-CaW7oDOl.mjs","names":["Runtime.handler"],"sources":["../../src/cli/cmd/handlers/plugin/update.ts"],"sourcesContent":["import { Plugin } from \"@codeworksh/harness/effect\";\nimport { Effect, Option } from \"effect\";\nimport { Runtime } from \"../../../../framework/runtime.ts\";\nimport { reportFailure } from \"../../../error.ts\";\nimport { writeOut } from \"../../../output.ts\";\nimport { Cmd } from \"../../cmd.ts\";\nimport { fetchable, local, probe, read, targeted } from \"./entries.ts\";\n\n/**\n * Take whatever `check` found.\n *\n * Only a plugin that is **already installed** is refreshed: \"not installed\" is not \"outdated\", and\n * `plugin install` is the verb for that. Each refresh publishes a new generation, which a running\n * session picks up at its next exchange -- so this command never has to reach into a server.\n */\nexport default Runtime.handler(\n\tCmd.commands.plugin.commands.update,\n\tEffect.fn(\"CLI.plugin.update\")(function* ({ spec }) {\n\t\tconst program = Effect.gen(function* () {\n\t\t\tconst shared = yield* Cmd.spec;\n\t\t\tconst { entries, cache, hostDir } = yield* read(shared);\n\t\t\tconst selected = yield* targeted(entries, spec, hostDir);\n\t\t\tif (selected.length === 0 && Option.isSome(spec)) return;\n\n\t\t\tlet updated = 0;\n\t\t\tlet failed = 0;\n\t\t\tfor (const entry of selected) {\n\t\t\t\tconst target = fetchable(entry.target);\n\t\t\t\t// A local plugin has no revision to compare and is never copied into the store.\n\t\t\t\tif (target === undefined) {\n\t\t\t\t\tyield* local(entry, spec);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst result = yield* Plugin.update(target, cache, {\n\t\t\t\t\tprobe: probe(cache, entry.from),\n\t\t\t\t\tfrom: entry.from,\n\t\t\t\t\t// Validated while staged, so a refresh that fetches something broken leaves\n\t\t\t\t\t// the generation already in use as the answer. Preserve the loader's reason:\n\t\t\t\t\t// an import failure or invalid definition is not a missing entrypoint.\n\t\t\t\t\tvalidate: (fetched) => Plugin.definition(fetched.entrypoint, entry.reference).pipe(Effect.asVoid),\n\t\t\t\t}).pipe(Effect.result);\n\n\t\t\t\tif (result._tag === \"Failure\") {\n\t\t\t\t\tfailed += 1;\n\t\t\t\t\tyield* writeOut(`${entry.reference} error[${result.failure.reason}]: ${result.failure.message}\\n`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (result.success._tag === \"updated\") {\n\t\t\t\t\tupdated += 1;\n\t\t\t\t\tyield* writeOut(`Updated ${entry.reference} to ${result.success.entry.revision ?? \"a new revision\"}\\n`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// A spec that named only local plugins compared nothing, so there is nothing to sum up.\n\t\t\tif (Option.isSome(spec) && selected.every((entry) => fetchable(entry.target) === undefined)) return;\n\t\t\tyield* writeOut(updated === 0 ? \"Nothing to update.\\n\" : `${updated} updated.\\n`);\n\t\t\tif (failed > 0) process.exitCode = 1;\n\t\t});\n\n\t\treturn yield* program.pipe(Effect.catch(reportFailure));\n\t}),\n);\n"],"mappings":";;;;;;;;;;;;;AAeA,IAAA,iBAAeA,QACd,IAAI,SAAS,OAAO,SAAS,QAC7B,OAAO,GAAG,mBAAmB,CAAC,CAAC,WAAW,EAAE,QAAQ;CA2CnD,OAAO,OA1CS,OAAO,IAAI,aAAa;EACvC,MAAM,SAAS,OAAO,IAAI;EAC1B,MAAM,EAAE,SAAS,OAAO,YAAY,OAAO,KAAK,MAAM;EACtD,MAAM,WAAW,OAAO,SAAS,SAAS,MAAM,OAAO;EACvD,IAAI,SAAS,WAAW,KAAK,OAAO,OAAO,IAAI,GAAG;EAElD,IAAI,UAAU;EACd,IAAI,SAAS;EACb,KAAK,MAAM,SAAS,UAAU;GAC7B,MAAM,SAAS,UAAU,MAAM,MAAM;GAErC,IAAI,WAAW,KAAA,GAAW;IACzB,OAAO,MAAM,OAAO,IAAI;IACxB;GACD;GAEA,MAAM,SAAS,OAAO,OAAO,OAAO,QAAQ,OAAO;IAClD,OAAO,MAAM,OAAO,MAAM,IAAI;IAC9B,MAAM,MAAM;IAIZ,WAAW,YAAY,OAAO,WAAW,QAAQ,YAAY,MAAM,SAAS,CAAC,CAAC,KAAK,OAAO,MAAM;GACjG,CAAC,CAAC,CAAC,KAAK,OAAO,MAAM;GAErB,IAAI,OAAO,SAAS,WAAW;IAC9B,UAAU;IACV,OAAO,SAAS,GAAG,MAAM,UAAU,UAAU,OAAO,QAAQ,OAAO,KAAK,OAAO,QAAQ,QAAQ,GAAG;IAClG;GACD;GACA,IAAI,OAAO,QAAQ,SAAS,WAAW;IACtC,WAAW;IACX,OAAO,SAAS,WAAW,MAAM,UAAU,MAAM,OAAO,QAAQ,MAAM,YAAY,iBAAiB,GAAG;GACvG;EACD;EAGA,IAAI,OAAO,OAAO,IAAI,KAAK,SAAS,OAAO,UAAU,UAAU,MAAM,MAAM,MAAM,KAAA,CAAS,GAAG;EAC7F,OAAO,SAAS,YAAY,IAAI,yBAAyB,GAAG,QAAQ,YAAY;EAChF,IAAI,SAAS,GAAG,QAAQ,WAAW;CACpC,CAEoB,CAAC,CAAC,KAAK,OAAO,MAAM,aAAa,CAAC;AACvD,CAAC,CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"add-CIQSfxan.mjs","names":["Global.resolve","SessionStore.Service","SessionStore.SessionNotFoundError","SessionStore.SessionNotLinkedError","Event.layer","Database.layer","Database.path","Runtime.handler","Global.resolve","Plugin.inspect"],"sources":["../../src/cli/cmd/handlers/plugin/session.ts","../../src/cli/cmd/handlers/plugin/add.ts"],"sourcesContent":["import { Database, Event, Global, Session, SessionStore } from \"@codeworksh/harness/effect\";\nimport { Effect, Layer, Option } from \"effect\";\n\n/**\n * The host directory a session is linked to.\n *\n * **A session ID can answer this and a project ID cannot**, which is why the flag takes one. A\n * `Project` is env-independent by design -- its identity is a repo marker, a remote hash or a root\n * commit, never a path -- and its spaces hold `location`s *inside* an env, which may be a container\n * on another machine. Deriving a host settings file from one would mean walking the host\n * filesystem from a path that means something somewhere else, which is the exact failure the\n * `hostDir` split exists to prevent: it does not error, it finds a stranger's project.\n *\n * A session, by contrast, carries a `hostDir` that was *declared* on the host. Absent is a normal\n * state rather than corruption, and it is the one this refuses.\n */\nexport const linkedDirectory = Effect.fn(\"CLI.plugin.linkedDirectory\")(function* (\n\tsessionId: string,\n\thome: Option.Option<string>,\n) {\n\tconst paths = yield* Global.resolve(Option.isNone(home) ? {} : { home: home.value });\n\tconst id = Session.SessionSchema.ID.ascending(sessionId);\n\n\treturn yield* Effect.gen(function* () {\n\t\tconst sessions = yield* SessionStore.Service;\n\t\tconst found = yield* sessions.get(id);\n\t\tif (Option.isNone(found)) return yield* new SessionStore.SessionNotFoundError({ sessionId: id });\n\t\tconst hostDir = Option.getOrUndefined(found.value.hostDir);\n\t\tif (hostDir === undefined) return yield* new SessionStore.SessionNotLinkedError({ sessionId: id });\n\t\treturn hostDir;\n\t}).pipe(\n\t\t// Only the session row is read, so this needs the database and the event log the store is\n\t\t// built on -- no sandboxes, no control plane, no plugin machinery.\n\t\tEffect.provide(\n\t\t\tSessionStore.layer.pipe(\n\t\t\t\tLayer.provide(Event.layer),\n\t\t\t\tLayer.provide(Database.layer(yield* Database.path(paths.data))),\n\t\t\t),\n\t\t),\n\t);\n});\n","import { Global, Plugin } from \"@codeworksh/harness/effect\";\nimport { Effect, 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 { linkedDirectory } from \"./session.ts\";\nimport {\n\tidentify,\n\tmatches,\n\treadPlugins,\n\tresolveTarget,\n\tspellings,\n\twithPluginsLock,\n\twritePlugins,\n\twritten,\n} from \"./settings.ts\";\n\nexport default Runtime.handler(\n\tCmd.commands.plugin.commands.add,\n\tEffect.fn(\"CLI.plugin.add\")(function* ({ package: reference, global: userWide, session }) {\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 paths = yield* Global.resolve(Option.isNone(shared.home) ? {} : { home: shared.home.value });\n\n\t\t\t// A session names the project to write into when the shell's directory is not it --\n\t\t\t// a server or a UI acting on a session's behalf, rather than a person standing in the\n\t\t\t// repository. It fails when that session has no project, which is a state `session\n\t\t\t// link` exists to fix.\n\t\t\tconst linked = Option.isNone(session) ? undefined : yield* linkedDirectory(session.value, shared.home);\n\t\t\t/*\n\t\t\t * One directory answers every question this command asks about the reference, and it\n\t\t\t * is resolved before any of them.\n\t\t\t *\n\t\t\t * A relative spec anchors here, the `.npmrc` chain governing the install is read from\n\t\t\t * here, and the entry is written anchored here. Splitting them is not a cosmetic\n\t\t\t * inconsistency: under `--session` the shell's directory is a server's, so validating\n\t\t\t * `./plugins/x.ts` against it imports one file and writes a reference to another, and\n\t\t\t * reading the `.npmrc` chain from it installs from the wrong registry -- a private\n\t\t\t * scope's token lives in the project being written to, not wherever the server runs.\n\t\t\t */\n\t\t\tconst from = linked ?? path.resolve(\".\");\n\n\t\t\t// The file the entry will land in decides the install's registry identity: it is named\n\t\t\t// here -- without creating the marker -- so the store keys the artifact under the same\n\t\t\t// `.npmrc` chain every later resolve of this entry re-derives, and a bad reference\n\t\t\t// still leaves nothing behind.\n\t\t\tconst target = yield* resolveTarget(shared, userWide, linked, false);\n\n\t\t\t// Install and import before touching the file: a spec that turns out not to be a plugin\n\t\t\t// should fail here, with its own error, rather than at the next run from a file the user\n\t\t\t// then has to repair by hand.\n\t\t\tconst plugin = yield* Plugin.inspect(reference, { cache: paths.cache, hostDir: from, file: target.path });\n\t\t\t// What goes in the file, which is not always what was typed: a relative path anchors to\n\t\t\t// the settings file being written, not to the directory the command ran in.\n\t\t\tconst entry = yield* written(reference, {\n\t\t\t\thostDir: from,\n\t\t\t\tfile: target.path,\n\t\t\t\troot: target.root,\n\t\t\t});\n\t\t\tconst spelled = yield* spellings(reference, from);\n\t\t\tconst version = plugin.version === undefined ? \"\" : `@${plugin.version}`;\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\tconst entries = yield* identify(plugins, target.path, paths.cache);\n\t\t\t\t\t// Configured already if any spelling of an existing entry names this plugin -- the same\n\t\t\t\t\t// package under a different version, the path it was added by, or the ID it declares.\n\t\t\t\t\tconst names = (candidate: (typeof entries)[number]) =>\n\t\t\t\t\t\tmatches(candidate, spelled) || candidate.answers.has(plugin.id);\n\t\t\t\t\tconst existing = entries.findIndex((candidate) => candidate.loads && names(candidate));\n\t\t\t\t\tif (existing >= 0) {\n\t\t\t\t\t\tconst current = entries[existing]?.value;\n\t\t\t\t\t\tif (current === entry) {\n\t\t\t\t\t\t\tyield* writeOut(`Plugin \"${reference}\" is already configured in ${target.path}\\n`);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst replaced = [...plugins];\n\t\t\t\t\t\treplaced[existing] = entry;\n\t\t\t\t\t\tyield* writePlugins(target.path, source, replaced);\n\t\t\t\t\t\tyield* writeOut(\n\t\t\t\t\t\t\t`Updated ${plugin.id} (${String(current)} -> ${entry}${version}) in ${target.path}\\n`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Put the loader before existing configuration so its options apply to the module.\n\t\t\t\t\tconst configured = entries.findIndex((candidate) => !candidate.loads && names(candidate));\n\t\t\t\t\tconst updated = [...plugins];\n\t\t\t\t\tupdated.splice(configured < 0 ? updated.length : configured, 0, entry);\n\t\t\t\t\tyield* writePlugins(target.path, source, updated);\n\t\t\t\t\tyield* writeOut(`Added ${plugin.id} (${entry}${version}) to ${target.path}\\n`);\n\t\t\t\t}),\n\t\t\t);\n\t\t\t// Said after the write, because `resolveTarget` only named the marker: the lock's\n\t\t\t// write is what made it, and \"created\" should be true by the time it is printed.\n\t\t\tif (target.created !== undefined) yield* writeOut(`Created ${target.created}/\\n`);\n\t\t});\n\n\t\treturn yield* program.pipe(Effect.catch(reportFailure));\n\t}),\n);\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"catalog-C5fDCgtx.mjs","names":["Global.resolve","ModelCatalog.sync"],"sources":["../../src/cli/cmd/handlers/models/catalog.ts"],"sourcesContent":["import { Global, ModelCatalog } from \"@codeworksh/harness/effect\";\nimport { Effect, Option } from \"effect\";\nimport { Cmd } from \"../../cmd.ts\";\n\n/** The home `--home` names, or the default one. */\nexport const home = Effect.gen(function* () {\n\tconst shared = yield* Cmd.spec;\n\treturn (yield* Global.resolve(Option.isNone(shared.home) ? {} : { home: shared.home.value })).home;\n});\n\n/** Check the home's catalog, as `run` does at boot, before reading it. */\nexport const synced = Effect.gen(function* () {\n\tyield* ModelCatalog.sync(yield* home);\n});\n"],"mappings":";;;;;AAKA,MAAa,OAAO,OAAO,IAAI,aAAa;CAC3C,MAAM,SAAS,OAAO,IAAI;CAC1B,QAAQ,OAAOA,QAAe,OAAO,OAAO,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,MAAM,OAAO,KAAK,MAAM,CAAC,EAAA,CAAG;AAC/F,CAAC;;AAGD,MAAa,SAAS,OAAO,IAAI,aAAa;CAC7C,OAAOC,KAAkB,OAAO,IAAI;AACrC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"check-B7bP5lRI.mjs","names":["Runtime.handler","Plugin.check"],"sources":["../../src/cli/cmd/handlers/plugin/check.ts"],"sourcesContent":["import { Plugin } from \"@codeworksh/harness/effect\";\nimport { Effect, Option } from \"effect\";\nimport { Runtime } from \"../../../../framework/runtime.ts\";\nimport { reportFailure } from \"../../../error.ts\";\nimport { writeOut } from \"../../../output.ts\";\nimport { Cmd } from \"../../cmd.ts\";\nimport { fetchable, local, probe, read, targeted } from \"./entries.ts\";\n\n/**\n * Which configured plugins have a newer revision available.\n *\n * A probe failure -- offline, registry down, a remote that refuses -- is **not** an update. It is\n * reported per target and the command exits non-zero, rather than being swallowed into \"you are up\n * to date\": an outage that reads as currency is the one answer this command must never give.\n */\nexport default Runtime.handler(\n\tCmd.commands.plugin.commands.check,\n\tEffect.fn(\"CLI.plugin.check\")(function* ({ refresh, spec }) {\n\t\tconst program = Effect.gen(function* () {\n\t\t\tconst shared = yield* Cmd.spec;\n\t\t\tconst { entries, cache, hostDir } = yield* read(shared);\n\t\t\tconst selected = yield* targeted(entries, spec, hostDir);\n\t\t\tif (selected.length === 0 && Option.isSome(spec)) return;\n\n\t\t\tlet outdated = 0;\n\t\t\tlet failed = 0;\n\t\t\tfor (const entry of selected) {\n\t\t\t\tconst target = fetchable(entry.target);\n\t\t\t\t// Nothing to compare: a local path has no revision, and `check` skips it rather\n\t\t\t\t// than reporting it as current.\n\t\t\t\tif (target === undefined) {\n\t\t\t\t\tyield* local(entry, spec);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst state = yield* Plugin.check(target, cache, {\n\t\t\t\t\trefresh,\n\t\t\t\t\tprobe: probe(cache, entry.from),\n\t\t\t\t\tfrom: entry.from,\n\t\t\t\t}).pipe(Effect.result);\n\t\t\t\tif (state._tag === \"Failure\") {\n\t\t\t\t\tfailed += 1;\n\t\t\t\t\tyield* writeOut(`${entry.reference} error[${state.failure.reason}]: ${state.failure.message}\\n`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tswitch (state.success._tag) {\n\t\t\t\t\tcase \"outdated\":\n\t\t\t\t\t\toutdated += 1;\n\t\t\t\t\t\tyield* writeOut(`${entry.reference} ${state.success.filed ?? \"?\"} -> ${state.success.available}\\n`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"not-installed\":\n\t\t\t\t\t\tyield* writeOut(`${entry.reference} plugin-not-installed\\n`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t// An exact version and a commit SHA cannot move, so neither is worth a line.\n\t\t\t\t\tcase \"immutable\":\n\t\t\t\t\tcase \"current\":\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// A spec that named only local plugins compared nothing, so there is nothing to sum up.\n\t\t\tif (Option.isSome(spec) && selected.every((entry) => fetchable(entry.target) === undefined)) return;\n\t\t\tyield* writeOut(\n\t\t\t\toutdated === 0 && failed === 0\n\t\t\t\t\t? \"Everything is up to date.\\n\"\n\t\t\t\t\t: `${outdated} update${outdated === 1 ? \"\" : \"s\"} available.\\n`,\n\t\t\t);\n\t\t\tif (failed > 0) process.exitCode = 1;\n\t\t});\n\n\t\treturn yield* program.pipe(Effect.catch(reportFailure));\n\t}),\n);\n"],"mappings":";;;;;;;;;;;;AAeA,IAAA,gBAAeA,QACd,IAAI,SAAS,OAAO,SAAS,OAC7B,OAAO,GAAG,kBAAkB,CAAC,CAAC,WAAW,EAAE,SAAS,QAAQ;CAqD3D,OAAO,OApDS,OAAO,IAAI,aAAa;EACvC,MAAM,SAAS,OAAO,IAAI;EAC1B,MAAM,EAAE,SAAS,OAAO,YAAY,OAAO,KAAK,MAAM;EACtD,MAAM,WAAW,OAAO,SAAS,SAAS,MAAM,OAAO;EACvD,IAAI,SAAS,WAAW,KAAK,OAAO,OAAO,IAAI,GAAG;EAElD,IAAI,WAAW;EACf,IAAI,SAAS;EACb,KAAK,MAAM,SAAS,UAAU;GAC7B,MAAM,SAAS,UAAU,MAAM,MAAM;GAGrC,IAAI,WAAW,KAAA,GAAW;IACzB,OAAO,MAAM,OAAO,IAAI;IACxB;GACD;GAEA,MAAM,QAAQ,OAAOC,MAAa,QAAQ,OAAO;IAChD;IACA,OAAO,MAAM,OAAO,MAAM,IAAI;IAC9B,MAAM,MAAM;GACb,CAAC,CAAC,CAAC,KAAK,OAAO,MAAM;GACrB,IAAI,MAAM,SAAS,WAAW;IAC7B,UAAU;IACV,OAAO,SAAS,GAAG,MAAM,UAAU,UAAU,MAAM,QAAQ,OAAO,KAAK,MAAM,QAAQ,QAAQ,GAAG;IAChG;GACD;GACA,QAAQ,MAAM,QAAQ,MAAtB;IACC,KAAK;KACJ,YAAY;KACZ,OAAO,SAAS,GAAG,MAAM,UAAU,IAAI,MAAM,QAAQ,SAAS,IAAI,MAAM,MAAM,QAAQ,UAAU,GAAG;KACnG;IACD,KAAK,iBACJ,OAAO,SAAS,GAAG,MAAM,UAAU,yBAAyB;GAM9D;EACD;EAGA,IAAI,OAAO,OAAO,IAAI,KAAK,SAAS,OAAO,UAAU,UAAU,MAAM,MAAM,MAAM,KAAA,CAAS,GAAG;EAC7F,OAAO,SACN,aAAa,KAAK,WAAW,IAC1B,gCACA,GAAG,SAAS,SAAS,aAAa,IAAI,KAAK,IAAI,cACnD;EACA,IAAI,SAAS,GAAG,QAAQ,WAAW;CACpC,CAEoB,CAAC,CAAC,KAAK,OAAO,MAAM,aAAa,CAAC;AACvD,CAAC,CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"entries-CSY5N6jH.mjs","names":["Global.resolve","Settings.projectRoot","Settings.load","Settings.modules","Plugin.parse","Plugin.anchor","Plugin.identity","Plugin.canonical","Plugin.localName","Plugin.probe"],"sources":["../../src/cli/cmd/handlers/plugin/entries.ts"],"sourcesContent":["import { Global, Plugin, Settings } from \"@codeworksh/harness/effect\";\nimport { Effect, Option, Path } from \"effect\";\nimport { writeOut } from \"../../../output.ts\";\nimport { userLayer, type Shared } from \"./settings.ts\";\n\n/**\n * Every plugin entry the settings files name, across every layer, in the order they accumulate.\n *\n * This is what `install`, `list`, `check` and `update` all operate on: unlike `add` and `remove`,\n * none of them writes an entry. They read what is already there and act on the store -- each one\n * under the `.npmrc` context of the file that declared it, which is what keys the artifact.\n */\nexport interface Entry {\n\t/** The reference as the settings file spells it: the string a person will search for. */\n\treadonly written: string;\n\t/** The same reference, anchored to the file that declared it. This is what resolves. */\n\treadonly reference: string;\n\t/** Which settings file owns it: the last to declare it in the view that needs it. */\n\treadonly file: string;\n\t/**\n\t * The `.npmrc` anchor for the entry's store identity: the project that declared it, so the\n\t * registry context is the same wherever this command happens to run.\n\t */\n\treadonly from: string;\n\t/** Absent for an unparseable entry and for a local path. */\n\treadonly target: Plugin.Target | undefined;\n}\n\n/** Only a string entry loads a module; `{ package }` is configuration for one already selected. */\nconst moduleOf = (entry: unknown): string | undefined => (typeof entry === \"string\" ? entry : undefined);\n\nexport const read = Effect.fn(\"CLI.plugin.entries\")(function* (shared: Shared) {\n\tconst nodePath = yield* Path.Path;\n\t// The directory the command runs in resolves its app-level flags. No session links it to\n\t// another host directory, so it is the command's anchor too: project settings are discovered\n\t// from here, and a relative spec typed here resolves here.\n\tconst hostCwd = nodePath.resolve(\".\");\n\tconst hostDir = hostCwd;\n\tconst paths = yield* Global.resolve(Option.isNone(shared.home) ? {} : { home: shared.home.value });\n\tconst root = yield* Settings.projectRoot(hostDir, paths.home);\n\tconst layers = { home: paths.home, ...userLayer(shared, hostCwd) };\n\t/*\n\t * The runtime resolves plugins in two views, and each needs its own artifact on disk: boot\n\t * reads the user layers alone, and a session reads every layer. Within a view the last file to\n\t * declare a reference owns it, so a spec both layers name is owned by the user file at boot and\n\t * by the project file in the project's sessions -- two `.npmrc` anchors, and possibly two\n\t * registries. Collapsing it to one owner leaves one of those views without its artifact.\n\t */\n\tconst boot = yield* Settings.load(layers);\n\tconst views = root === undefined ? [boot] : [boot, yield* Settings.load({ ...layers, hostDir: root })];\n\n\t// One entry per store artifact, so two anchors on one registry stay a single line. A later\n\t// view names the file, which is the one a person in this project would edit.\n\tconst entries = new Map<string, Entry>();\n\tfor (const view of views) {\n\t\t// views is [boot] outside a project, or [boot, session] inside one.\n\t\t// Boot comes first, and the order matters (see below).\n\t\tfor (const [reference, one] of Settings.modules(view.declared)) {\n\t\t\t// Already anchored to the file that declared it, so `hostDir` here only affects a\n\t\t\t// reference no settings file produced.\n\t\t\tconst target = Option.getOrUndefined(yield* Plugin.parse(reference, hostDir).pipe(Effect.option));\n\t\t\tconst from = Plugin.anchor(one.file, hostDir);\n\t\t\tconst key = yield* identity(target, reference, from, paths.cache);\n\t\t\tentries.set(key, { written: moduleOf(one.written) ?? reference, reference, file: one.file, from, target });\n\t\t}\n\t}\n\treturn { entries: [...entries.values()] as ReadonlyArray<Entry>, cache: paths.cache, hostDir };\n});\n\n/**\n * What makes two entries one artifact: the store's own key for a fetched target, the file for a\n * local one. A registry that cannot be read keeps the entry apart, so its install reports why.\n */\nconst identity = (target: Plugin.Target | undefined, reference: string, from: string, cache: string) => {\n\tconst fetched = fetchable(target);\n\tif (fetched === undefined) return Effect.succeed(target?.kind === \"local\" ? target.path : reference);\n\treturn Plugin.identity(fetched, cache, from).pipe(Effect.orElseSucceed(() => `${reference}\\0${from}`));\n};\n\n/** What a reference names, whatever version it was written with: a package, a git spec, a file. */\nconst source = (reference: string, hostDir: string) =>\n\tPlugin.canonical(reference, hostDir).pipe(Effect.orElseSucceed(() => reference));\n\n/**\n * The entries a command acts on: all of them, or every one `spec` names.\n *\n * Matched by source identity, the way the `plugins` array reads -- `@acme/x` selects\n * `@acme/x@^1`, a relative path selects the file it resolves to from `hostDir`, and a local package\n * also answers to the name its `package.json` declares. A plugin ID is not a spelling of anything\n * in that array, so it matches nothing. Every match is kept: a spec both layers declare under\n * different registries is two artifacts, and both answer to it.\n */\nexport const targeted = Effect.fn(\"CLI.plugin.targeted\")(function* (\n\tentries: ReadonlyArray<Entry>,\n\tspec: Option.Option<string>,\n\t/** The host directory the command resolves from, which a relative spec is typed against. */\n\thostDir: string,\n) {\n\tif (Option.isNone(spec)) return entries;\n\tconst wanted = yield* source(spec.value, hostDir);\n\tconst selected: Entry[] = [];\n\tfor (const entry of entries) {\n\t\tconst named =\n\t\t\t(yield* source(entry.reference, hostDir)) === wanted ||\n\t\t\t(entry.target?.kind === \"local\" && (yield* Plugin.localName(entry.target.path)) === wanted);\n\t\tif (named) selected.push(entry);\n\t}\n\tif (selected.length === 0) {\n\t\tyield* writeOut(`Plugin \"${spec.value}\" is not configured. Run \\`codework plugin list\\` to see what is.\\n`);\n\t\tprocess.exitCode = 1;\n\t}\n\treturn selected as ReadonlyArray<Entry>;\n});\n\n/**\n * A local plugin has no revision to compare and is never copied into the store. Skipped quietly\n * when a command walks everything; named, it says why nothing happened.\n */\nexport const local = (entry: Entry, spec: Option.Option<string>) =>\n\tOption.isSome(spec) ? writeOut(`${entry.reference} local: no remote revision to compare\\n`) : Effect.void;\n\n/**\n * The network half, handed to the store so the store itself never opens a socket.\n *\n * `probe` bypasses pacote's own metadata cache, because a staleness check that reads a cache is\n * not a staleness check. `from` is the host directory: a probe that read a different `.npmrc`\n * chain than the install would answer about a registry nothing is ever fetched from.\n */\nexport const probe =\n\t(cache: string, from: string): Plugin.Probe =>\n\t(target) =>\n\t\tPlugin.probe(target, cache, from);\n\n/** Only a fetched target has a store entry; a local one is loaded where it lies. */\nexport const fetchable = (target: Plugin.Target | undefined): Plugin.Fetchable | undefined =>\n\ttarget === undefined || target.kind === \"local\" ? undefined : target;\n"],"mappings":";;;;;AA6BA,MAAM,YAAY,UAAwC,OAAO,UAAU,WAAW,QAAQ,KAAA;AAE9F,MAAa,OAAO,OAAO,GAAG,oBAAoB,CAAC,CAAC,WAAW,QAAgB;CAK9E,MAAM,WAAU,OAJQ,KAAK,KAAA,CAIJ,QAAQ,GAAG;CACpC,MAAM,UAAU;CAChB,MAAM,QAAQ,OAAOA,QAAe,OAAO,OAAO,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,MAAM,OAAO,KAAK,MAAM,CAAC;CACjG,MAAM,OAAO,OAAOC,YAAqB,SAAS,MAAM,IAAI;CAC5D,MAAM,SAAS;EAAE,MAAM,MAAM;EAAM,GAAG,UAAU,QAAQ,OAAO;CAAE;CAQjE,MAAM,OAAO,OAAOC,KAAc,MAAM;CACxC,MAAM,QAAQ,SAAS,KAAA,IAAY,CAAC,IAAI,IAAI,CAAC,MAAM,OAAOA,KAAc;EAAE,GAAG;EAAQ,SAAS;CAAK,CAAC,CAAC;CAIrG,MAAM,0BAAU,IAAI,IAAmB;CACvC,KAAK,MAAM,QAAQ,OAGlB,KAAK,MAAM,CAAC,WAAW,QAAQC,QAAiB,KAAK,QAAQ,GAAG;EAG/D,MAAM,SAAS,OAAO,eAAe,OAAOC,MAAa,WAAW,OAAO,CAAC,CAAC,KAAK,OAAO,MAAM,CAAC;EAChG,MAAM,OAAOC,OAAc,IAAI,MAAM,OAAO;EAC5C,MAAM,MAAM,OAAO,SAAS,QAAQ,WAAW,MAAM,MAAM,KAAK;EAChE,QAAQ,IAAI,KAAK;GAAE,SAAS,SAAS,IAAI,OAAO,KAAK;GAAW;GAAW,MAAM,IAAI;GAAM;GAAM;EAAO,CAAC;CAC1G;CAED,OAAO;EAAE,SAAS,CAAC,GAAG,QAAQ,OAAO,CAAC;EAA2B,OAAO,MAAM;EAAO;CAAQ;AAC9F,CAAC;;;;;AAMD,MAAM,YAAY,QAAmC,WAAmB,MAAc,UAAkB;CACvG,MAAM,UAAU,UAAU,MAAM;CAChC,IAAI,YAAY,KAAA,GAAW,OAAO,OAAO,QAAQ,QAAQ,SAAS,UAAU,OAAO,OAAO,SAAS;CACnG,OAAOC,OAAgB,SAAS,OAAO,IAAI,CAAC,CAAC,KAAK,OAAO,oBAAoB,GAAG,UAAU,IAAI,MAAM,CAAC;AACtG;;AAGA,MAAM,UAAU,WAAmB,YAClCC,UAAiB,WAAW,OAAO,CAAC,CAAC,KAAK,OAAO,oBAAoB,SAAS,CAAC;;;;;;;;;;AAWhF,MAAa,WAAW,OAAO,GAAG,qBAAqB,CAAC,CAAC,WACxD,SACA,MAEA,SACC;CACD,IAAI,OAAO,OAAO,IAAI,GAAG,OAAO;CAChC,MAAM,SAAS,OAAO,OAAO,KAAK,OAAO,OAAO;CAChD,MAAM,WAAoB,CAAC;CAC3B,KAAK,MAAM,SAAS,SAInB,KAFE,OAAO,OAAO,MAAM,WAAW,OAAO,OAAO,UAC7C,MAAM,QAAQ,SAAS,YAAY,OAAOC,UAAiB,MAAM,OAAO,IAAI,OAAO,QAC1E,SAAS,KAAK,KAAK;CAE/B,IAAI,SAAS,WAAW,GAAG;EAC1B,OAAO,SAAS,WAAW,KAAK,MAAM,oEAAoE;EAC1G,QAAQ,WAAW;CACpB;CACA,OAAO;AACR,CAAC;;;;;AAMD,MAAa,SAAS,OAAc,SACnC,OAAO,OAAO,IAAI,IAAI,SAAS,GAAG,MAAM,UAAU,yCAAyC,IAAI,OAAO;;;;;;;;AASvG,MAAa,SACX,OAAe,UACf,WACAC,QAAa,QAAQ,OAAO,IAAI;;AAGlC,MAAa,aAAa,WACzB,WAAW,KAAA,KAAa,OAAO,SAAS,UAAU,KAAA,IAAY"}