@codeworksh/cli 0.5.0-canary.69.1.g5be1ef81 → 0.5.0-canary.71.1.g8233e4eb

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +27 -2
  2. package/{acp-BCeZqkaQ.mjs → acp-BTtByOlX.mjs} +92 -42
  3. package/acp-BTtByOlX.mjs.map +1 -0
  4. package/{add-Dzsv-fKd.mjs → add-Dm3RaxB1.mjs} +5 -5
  5. package/add-Dm3RaxB1.mjs.map +1 -0
  6. package/{catalog-C1G3pzHZ.mjs → catalog-Do2eDgti.mjs} +2 -2
  7. package/{catalog-C1G3pzHZ.mjs.map → catalog-Do2eDgti.mjs.map} +1 -1
  8. package/{check-DhojkK_E.mjs → check-BdfxwBaL.mjs} +4 -4
  9. package/{check-DhojkK_E.mjs.map → check-BdfxwBaL.mjs.map} +1 -1
  10. package/{entries-KpYvZdpi.mjs → entries-C6AeEOS1.mjs} +3 -3
  11. package/{entries-KpYvZdpi.mjs.map → entries-C6AeEOS1.mjs.map} +1 -1
  12. package/{error-BMI81XvR.mjs → error-CSeYCa9R.mjs} +195 -89
  13. package/error-CSeYCa9R.mjs.map +1 -0
  14. package/fork-CAu8PdA3.mjs +32 -0
  15. package/fork-CAu8PdA3.mjs.map +1 -0
  16. package/{identity-BfTAc3aC.mjs → identity-CpsvMaTx.mjs} +2 -2
  17. package/{identity-BfTAc3aC.mjs.map → identity-CpsvMaTx.mjs.map} +1 -1
  18. package/index.mjs +32 -25
  19. package/index.mjs.map +1 -1
  20. package/{install-BLRDBzp1.mjs → install-D5kkATcv.mjs} +4 -4
  21. package/{install-BLRDBzp1.mjs.map → install-D5kkATcv.mjs.map} +1 -1
  22. package/{link--UnM2qnT.mjs → link-CsfmcRa8.mjs} +3 -3
  23. package/{link--UnM2qnT.mjs.map → link-CsfmcRa8.mjs.map} +1 -1
  24. package/list-C60d6ifJ.mjs +36 -0
  25. package/list-C60d6ifJ.mjs.map +1 -0
  26. package/{list-9fVqelid.mjs → list-CHIzxyZx.mjs} +4 -4
  27. package/{list-9fVqelid.mjs.map → list-CHIzxyZx.mjs.map} +1 -1
  28. package/{list-BE4xSEe3.mjs → list-CakHFl9C.mjs} +4 -4
  29. package/{list-BE4xSEe3.mjs.map → list-CakHFl9C.mjs.map} +1 -1
  30. package/{login-CRwxi5WD.mjs → login-BaUYCO2G.mjs} +4 -4
  31. package/{login-CRwxi5WD.mjs.map → login-BaUYCO2G.mjs.map} +1 -1
  32. package/{logout-C89X0B9M.mjs → logout-BAks2xS7.mjs} +4 -4
  33. package/{logout-C89X0B9M.mjs.map → logout-BAks2xS7.mjs.map} +1 -1
  34. package/package-CmagAGZz.mjs +6 -0
  35. package/package-CmagAGZz.mjs.map +1 -0
  36. package/package.json +4 -4
  37. package/{providers-BrXJvY2P.mjs → providers-DVh6hhLU.mjs} +4 -4
  38. package/{providers-BrXJvY2P.mjs.map → providers-DVh6hhLU.mjs.map} +1 -1
  39. package/{refresh-D0wBP2Go.mjs → refresh-CNQBX5NK.mjs} +4 -4
  40. package/{refresh-D0wBP2Go.mjs.map → refresh-CNQBX5NK.mjs.map} +1 -1
  41. package/{refresh--j0Pj4Cw.mjs → refresh-tj3xbNRY.mjs} +4 -4
  42. package/{refresh--j0Pj4Cw.mjs.map → refresh-tj3xbNRY.mjs.map} +1 -1
  43. package/relink-BlRMYOra.mjs +23 -0
  44. package/relink-BlRMYOra.mjs.map +1 -0
  45. package/{reload-DgPawyzr.mjs → reload-h_2WARQN.mjs} +3 -3
  46. package/{reload-DgPawyzr.mjs.map → reload-h_2WARQN.mjs.map} +1 -1
  47. package/{remove-DfFme5w2.mjs → remove-CVbXLNTb.mjs} +4 -4
  48. package/{remove-DfFme5w2.mjs.map → remove-CVbXLNTb.mjs.map} +1 -1
  49. package/{restart-JPAbjFUh.mjs → restart-B0XSXYtj.mjs} +4 -4
  50. package/{restart-JPAbjFUh.mjs.map → restart-B0XSXYtj.mjs.map} +1 -1
  51. package/{run-CVRkm_Iz.mjs → run-CRV3jJ2d.mjs} +26 -17
  52. package/run-CRV3jJ2d.mjs.map +1 -0
  53. package/{runtime-B43doHjV.mjs → runtime-Bg4mc9BB.mjs} +59 -3
  54. package/runtime-Bg4mc9BB.mjs.map +1 -0
  55. package/{serve-DT8-nVCx.mjs → serve-XrW3PuIZ.mjs} +101 -73
  56. package/serve-XrW3PuIZ.mjs.map +1 -0
  57. package/{service-Cv-MLS-9.mjs → service-D_vwPPPh.mjs} +3 -3
  58. package/{service-Cv-MLS-9.mjs.map → service-D_vwPPPh.mjs.map} +1 -1
  59. package/{settings-BfmoL27m.mjs → settings-DcwstDUm.mjs} +2 -2
  60. package/{settings-BfmoL27m.mjs.map → settings-DcwstDUm.mjs.map} +1 -1
  61. package/{shared-CnuCjvcG.mjs → shared-D_3E8bu_.mjs} +3 -3
  62. package/{shared-CnuCjvcG.mjs.map → shared-D_3E8bu_.mjs.map} +1 -1
  63. package/{start-Qb1Ea9oT.mjs → start-CJ4XeLwV.mjs} +4 -4
  64. package/{start-Qb1Ea9oT.mjs.map → start-CJ4XeLwV.mjs.map} +1 -1
  65. package/{status-VGKqsdkQ.mjs → status-6NyZu0f_.mjs} +4 -4
  66. package/{status-VGKqsdkQ.mjs.map → status-6NyZu0f_.mjs.map} +1 -1
  67. package/{status-DVzFDoek.mjs → status-DBzQVkL2.mjs} +4 -4
  68. package/{status-DVzFDoek.mjs.map → status-DBzQVkL2.mjs.map} +1 -1
  69. package/{stop-mO7eg0nG.mjs → stop-BY1c7cUX.mjs} +4 -4
  70. package/{stop-mO7eg0nG.mjs.map → stop-BY1c7cUX.mjs.map} +1 -1
  71. package/thread-CEYjLavT.mjs +15 -0
  72. package/thread-CEYjLavT.mjs.map +1 -0
  73. package/{tui-DVVaevMF.mjs → tui-CBUtCHzR.mjs} +5 -5
  74. package/{tui-DVVaevMF.mjs.map → tui-CBUtCHzR.mjs.map} +1 -1
  75. package/{update-D0XPVfJu.mjs → update-CORsF38E.mjs} +4 -4
  76. package/{update-D0XPVfJu.mjs.map → update-CORsF38E.mjs.map} +1 -1
  77. package/acp-BCeZqkaQ.mjs.map +0 -1
  78. package/add-Dzsv-fKd.mjs.map +0 -1
  79. package/error-BMI81XvR.mjs.map +0 -1
  80. package/package-D9XCaBr1.mjs +0 -6
  81. package/package-D9XCaBr1.mjs.map +0 -1
  82. package/run-CVRkm_Iz.mjs.map +0 -1
  83. package/runtime-B43doHjV.mjs.map +0 -1
  84. package/serve-DT8-nVCx.mjs.map +0 -1
package/README.md CHANGED
@@ -39,9 +39,12 @@ codework run "Inspect and fix the failing tests"
39
39
  # Create a session with explicit provider and model
40
40
  codework run --provider openai --model gpt-5.5 --thinking high "Plan database migration"
41
41
 
42
- # Continue an existing session
42
+ # Continue an existing session (its main thread)
43
43
  codework run --session ses_01a070f0 "Now implement the migration script"
44
44
 
45
+ # Continue one of its threads
46
+ codework run --session ses_01a070f0 --thread thr_01a071c2 "Try it without the cache"
47
+
45
48
  # Run in an isolated sandbox (local, daytona, vercel, memory, sqldb)
46
49
  codework run --sandbox-driver daytona "Inspect repository"
47
50
  codework run --sandbox-driver daytona --sandbox-provider-id <remote-id> "Continue in sandbox"
@@ -51,6 +54,7 @@ codework run --sandbox-driver daytona --sandbox-provider-id <remote-id> "Continu
51
54
 
52
55
  - `--server <url>` — Connect to a running RPC server, e.g. `ws://127.0.0.1:7433/rpc/v1`.
53
56
  - `-s, --session <id>` — Continue an existing session.
57
+ - `--thread <id>` — Thread of `--session` to continue: a thread ID, or `main` (default).
54
58
  - `-C, --cwd <path>` — Working directory for a new session.
55
59
  - `--sandbox-driver <driver>` — Sandbox driver (`local`, `daytona`, `vercel`, `memory`, `sqldb`). Default: `local`.
56
60
  - `--sandbox-id <id>` — Reuse an existing sandbox instance; mutually exclusive with driver/provider coordinates.
@@ -63,6 +67,27 @@ Global flags: `--user-config-dir`, `--home`, `--database`.
63
67
 
64
68
  ---
65
69
 
70
+ ### `codework thread`
71
+
72
+ A session holds one or more threads: its `main` thread, and the forks made from it. These commands talk to a running server (`--server`, default `http://127.0.0.1:7433`).
73
+
74
+ ```bash
75
+ # List a session's threads with their model and usage
76
+ codework thread list ses_01a070f0
77
+
78
+ # Start a new thread through an entry, or just before a prompt to send it again
79
+ codework thread fork ses_01a070f0 --at <entry-id>
80
+ codework thread fork ses_01a070f0 --thread thr_01a071c2 --before <entry-id>
81
+
82
+ # Move one thread into another checkout of the project, keeping its position under it;
83
+ # the rest of the session stays where it is
84
+ codework session relink ses_01a070f0 --thread thr_01a071c2 -C ~/work/api
85
+ ```
86
+
87
+ `thread fork` prints the new thread ID, then for `--before` the text of the prompt it left out. `--json` prints the wire form.
88
+
89
+ ---
90
+
66
91
  ### `codework serve`
67
92
 
68
93
  Start a persistent server that owns sessions and sandboxes:
@@ -76,7 +101,7 @@ codework run --server ws://127.0.0.1:7433/rpc/v1 --sandbox-id <sandbox-id> "Star
76
101
 
77
102
  The default address is `127.0.0.1:7433`; `--port 0` picks an available port and prints the actual URL. Set `--home`, `--database`, and `--user-config-dir` on the server. Model credentials, plugins, and working directories are resolved by the server. A remote run does not boot a local harness.
78
103
 
79
- Events are live and not replayed. The client subscribes before admitting its prompt and waits for execution completion after rendering. Lost connections and overflow fail the command; disconnecting leaves server work running. Ctrl-C sends `session.interrupt`, which interrupts the shared session. Remote runs print the sandbox ID for reuse. `session.interrupt` returns `{ interrupted }` as soon as the stop is accepted; `session.wait` is the separate cleanup barrier. A busy period reports itself as `session.execution.started` followed by exactly one of `succeeded`, `failed`, or `interrupted` -- a failure carries a category (`provider-authentication-error`, `model-not-found-error`, `sandbox-mount-error`, ...) that the client renders, and an interruption carries whether it was the user or a server shutdown. Managed sandboxes remain available until explicitly stopped or server shutdown; external sandboxes are not stopped.
104
+ Events are live and not replayed. The client subscribes before admitting its prompt and waits for execution completion after rendering. Lost connections and overflow fail the command; disconnecting leaves server work running. Ctrl-C sends `thread.interrupt`, which stops the thread the run prompted. Remote runs print the sandbox ID for reuse. `thread.interrupt` returns `{ interrupted }` as soon as the stop is accepted; `thread.wait` is the separate cleanup barrier, and `session.interrupt` stops every thread of a session. A busy period reports itself as `session.execution.started` followed by exactly one of `succeeded`, `failed`, or `interrupted` -- a failure carries a category (`provider-authentication-error`, `model-not-found-error`, `sandbox-mount-error`, ...) that the client renders, and an interruption carries whether it was the user or a server shutdown. Managed sandboxes remain available until explicitly stopped or server shutdown; external sandboxes are not stopped.
80
105
 
81
106
  The v0 endpoint has no authentication; its default binding is loopback. Plugins publish their own event types by declaring them (`Plugin.define({ events: [...] })`, namespaced `plugin.<plugin-id>.*`); the feed carries those and skips types nothing declared. Invalid payloads for declared types fail with a typed encoding error.
82
107
 
@@ -1,10 +1,10 @@
1
- import { t as version } from "./package-D9XCaBr1.mjs";
2
- import { i as Cmd, t as handler } from "./runtime-B43doHjV.mjs";
3
- import { i as reportFailure } from "./error-BMI81XvR.mjs";
1
+ import { t as version } from "./package-CmagAGZz.mjs";
2
+ import { i as Cmd, t as handler } from "./runtime-Bg4mc9BB.mjs";
3
+ import { i as reportFailure } from "./error-CSeYCa9R.mjs";
4
4
  import { t as harnessOptions } from "./harness-6d8TlAVk.mjs";
5
5
  import { Cause, DateTime, Deferred, Effect, Exit, Fiber, Logger, Option, Schema, Stdio, Stream } from "effect";
6
6
  import { Model } from "@codeworksh/aikit";
7
- import { Control, EventList, Harness, ModelCatalog, PromptSchema, Sandbox, Session, SessionStore, Settings } from "@codeworksh/harness/effect";
7
+ import { Control, EventList, Harness, ModelCatalog, PromptSchema, Sandbox, Session, SessionStore, Settings, ThreadStore } from "@codeworksh/harness/effect";
8
8
  import * as Acp from "@agentclientprotocol/sdk";
9
9
  //#region src/acp/agent.ts
10
10
  /** A JSON-RPC error a handler answers a request with. */
@@ -55,7 +55,7 @@ const serve$1 = Effect.fn("ACP.serve")(function* (stdio, makeHandlers) {
55
55
  });
56
56
  const input = yield* Stream.toReadableStreamEffect(stdio.stdin);
57
57
  const output = new WritableStream({ write: (chunk) => Effect.runPromiseWith(context)(Stream.run(Stream.make(chunk), stdio.stdout())) });
58
- const connection = Acp.agent({ name: "codework" }).onRequest("initialize", handle(handlers.initialize)).onRequest("session/new", handle(handlers.newSession)).onRequest("session/load", handle(handlers.loadSession)).onRequest("session/list", handle(handlers.listSessions)).onRequest("session/set_config_option", handle(handlers.setConfigOption)).onRequest("session/prompt", handle(handlers.prompt)).onNotification("session/cancel", handle(handlers.cancel)).connect(Acp.ndJsonStream(output, input));
58
+ const connection = Acp.agent({ name: "codework" }).onRequest("initialize", handle(handlers.initialize)).onRequest("session/new", handle(handlers.newSession)).onRequest("session/load", handle(handlers.loadSession)).onRequest("session/list", handle(handlers.listSessions)).onRequest("session/fork", handle(handlers.forkSession)).onRequest("session/set_config_option", handle(handlers.setConfigOption)).onRequest("session/prompt", handle(handlers.prompt)).onNotification("session/cancel", handle(handlers.cancel)).connect(Acp.ndJsonStream(output, input));
59
59
  yield* Deferred.succeed(opened, connection);
60
60
  yield* Effect.addFinalizer(() => Effect.sync(() => connection.close()));
61
61
  yield* Effect.promise(() => connection.closed);
@@ -324,16 +324,43 @@ const promptParts = Effect.fnUntraced(function* (blocks) {
324
324
  }
325
325
  return parts;
326
326
  });
327
- const sessionId = (id) => Session.SessionSchema.ID.make(id);
327
+ const threadId = (id) => Session.ThreadSchema.ID.make(id);
328
328
  const make = Effect.gen(function* () {
329
329
  const control = yield* Control.Service;
330
330
  const sessions = yield* SessionStore.Service;
331
+ const threads = yield* ThreadStore.Service;
331
332
  const context = yield* Effect.context();
332
333
  const running = /* @__PURE__ */ new Set();
333
- const found = Effect.fn("ACP.found")(function* (id) {
334
- const row = yield* sessions.get(sessionId(id));
335
- if (Option.isNone(row)) return yield* new SessionStore.SessionNotFoundError({ sessionId: sessionId(id) });
336
- return row.value;
334
+ const acpId = (thread) => thread.originKind === "main" ? thread.sessionId : thread.id;
335
+ /** The CodeWork session and thread an ACP session id names. */
336
+ const resolve = Effect.fn("ACP.resolve")(function* (id) {
337
+ const session = yield* sessions.get(id);
338
+ if (Option.isSome(session)) {
339
+ const main = yield* threads.main(session.value.id);
340
+ if (Option.isSome(main)) return {
341
+ session: session.value,
342
+ threadId: threadId(main.value.id)
343
+ };
344
+ }
345
+ const thread = yield* threads.get(id);
346
+ if (Option.isSome(thread)) {
347
+ const owner = yield* sessions.get(thread.value.sessionId);
348
+ if (Option.isSome(owner)) return {
349
+ session: owner.value,
350
+ threadId: threadId(thread.value.id)
351
+ };
352
+ }
353
+ return yield* new SessionStore.SessionNotFoundError({ sessionId: id });
354
+ });
355
+ const attach = Effect.fn("ACP.attach")(function* (id) {
356
+ const { session, threadId } = yield* resolve(id);
357
+ return {
358
+ thread: yield* Session.attach({
359
+ sessionId: session.id,
360
+ threadId
361
+ }),
362
+ hostDir: Option.getOrUndefined(session.hostDir)
363
+ };
337
364
  });
338
365
  return (client) => {
339
366
  const run = (effect) => effect.pipe(Effect.provide(context), Effect.mapError(toRequestError));
@@ -350,7 +377,10 @@ const make = Effect.gen(function* () {
350
377
  embeddedContext: true,
351
378
  image: true
352
379
  },
353
- sessionCapabilities: { list: {} }
380
+ sessionCapabilities: {
381
+ list: {},
382
+ fork: {}
383
+ }
354
384
  }
355
385
  }),
356
386
  newSession: ({ cwd }) => run(Effect.gen(function* () {
@@ -358,65 +388,85 @@ const make = Effect.gen(function* () {
358
388
  directory: cwd,
359
389
  hostDir: cwd
360
390
  });
361
- const current = yield* Session.configuration(handle.id);
391
+ const current = yield* Session.configuration(handle.main.id);
362
392
  return {
363
393
  sessionId: handle.id,
364
394
  configOptions: yield* options(current, cwd)
365
395
  };
366
396
  })),
367
397
  loadSession: ({ sessionId: id }) => run(Effect.gen(function* () {
368
- yield* Session.attach({ sessionId: sessionId(id) });
369
- const row = yield* found(id);
370
- const hostDir = Option.getOrUndefined(row.hostDir);
371
- const current = yield* Session.configuration(row.id);
372
- for (const entry of yield* sessions.path(sessionId(id))) for (const update of replay(entry)) yield* client.sessionUpdate({
398
+ const { thread, hostDir } = yield* attach(id);
399
+ const current = yield* Session.configuration(thread.id);
400
+ for (const entry of yield* thread.history()) for (const update of replay(entry)) yield* client.sessionUpdate({
373
401
  sessionId: id,
374
402
  update
375
403
  });
376
404
  return { configOptions: yield* options(current, hostDir) };
377
405
  })),
378
406
  listSessions: ({ cwd, cursor }) => run(Effect.gen(function* () {
379
- const rows = (yield* sessions.list()).filter((row) => cwd == null || Option.getOrUndefined(row.hostDir) === cwd).sort((a, b) => DateTime.Order(b.updatedAt ?? b.createdAt, a.updatedAt ?? a.createdAt));
407
+ const owners = new Map((yield* sessions.list()).map((row) => [row.id, row]));
408
+ const all = yield* threads.list();
409
+ const titles = new Map(all.map((thread) => [thread.id, Option.getOrUndefined(thread.title)]));
410
+ const rows = all.flatMap((thread) => {
411
+ const session = owners.get(thread.sessionId);
412
+ return session === void 0 ? [] : [{
413
+ thread,
414
+ session
415
+ }];
416
+ }).filter(({ session }) => cwd == null || Option.getOrUndefined(session.hostDir) === cwd).sort((a, b) => DateTime.Order(b.thread.updatedAt ?? b.thread.createdAt, a.thread.updatedAt ?? a.thread.createdAt));
380
417
  const offset = cursor == null ? 0 : Number(cursor);
381
418
  if (!Number.isSafeInteger(offset) || offset < 0) return yield* RequestError.invalidParams(`Invalid cursor: ${cursor}`);
382
419
  const next = offset + PAGE_SIZE;
383
420
  return {
384
- sessions: rows.slice(offset, next).map((row) => ({
385
- sessionId: row.id,
386
- cwd: Option.getOrElse(row.hostDir, () => row.directory),
387
- title: row.title,
388
- updatedAt: DateTime.formatIso(row.updatedAt ?? row.createdAt)
421
+ sessions: rows.slice(offset, next).map(({ thread, session }) => ({
422
+ sessionId: acpId(thread),
423
+ cwd: Option.getOrElse(session.hostDir, () => session.directory),
424
+ title: titles.get(thread.id) ?? Option.match(thread.originThreadId, {
425
+ onNone: () => void 0,
426
+ onSome: (origin) => titles.get(origin)
427
+ }) ?? null,
428
+ updatedAt: DateTime.formatIso(thread.updatedAt ?? thread.createdAt)
389
429
  })),
390
430
  ...next < rows.length ? { nextCursor: String(next) } : {}
391
431
  };
392
432
  })),
433
+ forkSession: ({ sessionId: id }) => run(Effect.gen(function* () {
434
+ const { thread, hostDir } = yield* attach(id);
435
+ const last = (yield* thread.history()).findLast(({ entry }) => entry.state === "committed");
436
+ if (last === void 0) return yield* RequestError.invalidRequest("Nothing to fork yet: the session has no messages");
437
+ const forked = yield* thread.fork({ entryId: last.entry.id });
438
+ const current = yield* Session.configuration(forked.thread.id);
439
+ return {
440
+ sessionId: forked.thread.id,
441
+ configOptions: yield* options(current, hostDir)
442
+ };
443
+ })),
393
444
  setConfigOption: (request) => run(Effect.gen(function* () {
394
- const row = yield* found(request.sessionId);
395
- const hostDir = Option.getOrUndefined(row.hostDir);
445
+ const { session, threadId } = yield* resolve(request.sessionId);
446
+ const hostDir = Option.getOrUndefined(session.hostDir);
396
447
  const value = String(request.value);
448
+ let runtime;
397
449
  if (request.configId === "model") {
398
450
  const model = Option.getOrUndefined(parseModel(value));
399
451
  if (model === void 0 || !(yield* known(model, hostDir))) return yield* RequestError.invalidParams(`Unknown model: ${value}`);
400
- yield* Session.attach({
401
- sessionId: row.id,
402
- model
403
- });
452
+ runtime = { model };
404
453
  } else if (request.configId === "thought_level") {
405
454
  if (!isThinkingLevel(value)) return yield* RequestError.invalidParams(`Unknown thinking level: ${value}`);
406
- yield* Session.attach({
407
- sessionId: row.id,
408
- thinkingLevel: value
409
- });
455
+ runtime = { thinkingLevel: value };
410
456
  } else return yield* RequestError.invalidParams(`Unknown config option: ${request.configId}`);
411
- return { configOptions: yield* options(yield* Session.configuration(row.id), hostDir) };
457
+ const thread = yield* Session.attach({
458
+ sessionId: session.id,
459
+ threadId,
460
+ ...runtime
461
+ });
462
+ return { configOptions: yield* options(yield* Session.configuration(thread.id), hostDir) };
412
463
  })),
413
464
  prompt: ({ sessionId: id, prompt }) => run(Effect.gen(function* () {
414
465
  const parts = yield* promptParts(prompt);
415
- const handle = Option.getOrUndefined(yield* Session.get(sessionId(id)));
416
- if (handle === void 0) return yield* new SessionStore.SessionNotFoundError({ sessionId: sessionId(id) });
417
- if (running.has(id)) return yield* RequestError.invalidRequest("A prompt is already running for this session");
418
- running.add(id);
419
- yield* Effect.addFinalizer(() => Effect.sync(() => running.delete(id)));
466
+ const { thread: handle } = yield* attach(id);
467
+ if (running.has(handle.id)) return yield* RequestError.invalidRequest("A prompt is already running for this session");
468
+ running.add(handle.id);
469
+ yield* Effect.addFinalizer(() => Effect.sync(() => running.delete(handle.id)));
420
470
  let reason;
421
471
  const notices = /* @__PURE__ */ new Set();
422
472
  const settled = yield* handle.events().pipe(Stream.tap((event) => {
@@ -439,7 +489,7 @@ const make = Effect.gen(function* () {
439
489
  yield* handle.run({ parts });
440
490
  const end = yield* Fiber.join(settled);
441
491
  const { title } = yield* handle.info;
442
- if (title !== before) yield* client.sessionUpdate({
492
+ if (title !== void 0 && title !== before) yield* client.sessionUpdate({
443
493
  sessionId: id,
444
494
  update: {
445
495
  sessionUpdate: "session_info_update",
@@ -450,7 +500,7 @@ const make = Effect.gen(function* () {
450
500
  if (isFailed(end.value)) return yield* RequestError.internalError(end.value.data.error.message);
451
501
  return { stopReason: reason === "length" ? "max_tokens" : "end_turn" };
452
502
  }).pipe(Effect.scoped)),
453
- cancel: ({ sessionId: id }) => control.interrupt(sessionId(id), { reason: "user" }).pipe(Effect.asVoid)
503
+ cancel: ({ sessionId: id }) => resolve(id).pipe(Effect.flatMap((found) => control.interrupt(found.threadId, { reason: "user" })), Effect.ignore, Effect.provide(context))
454
504
  };
455
505
  };
456
506
  });
@@ -491,4 +541,4 @@ var acp_default = handler(Cmd.commands.acp, Effect.fn("CLI.acp", { level: "Info"
491
541
  //#endregion
492
542
  export { acp_default as default };
493
543
 
494
- //# sourceMappingURL=acp-BCeZqkaQ.mjs.map
544
+ //# sourceMappingURL=acp-BTtByOlX.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acp-BTtByOlX.mjs","names":["serve","Agent.RequestError","pkg.version","Config.options","Feed.replay","Config.parseModel","Config.known","Config.isThinkingLevel","update","Feed.update","notice","Feed.notice","Feed.noticeUpdate","Handlers.make","Agent.serve","Runtime.handler","Server.serve"],"sources":["../../src/acp/agent.ts","../../src/acp/config.ts","../../src/acp/feed.ts","../../src/acp/handlers.ts","../../src/acp/server.ts","../../src/cli/cmd/handlers/acp.ts"],"sourcesContent":["import * as Acp from \"@agentclientprotocol/sdk\";\nimport { Cause, Deferred, Effect, Exit, Option, Schema, type Scope, type Stdio, Stream } from \"effect\";\n\n/** A JSON-RPC error a handler answers a request with. */\nexport class RequestError extends Schema.TaggedError<RequestError>()(\"AcpRequestError\", {\n\tcode: Schema.Int,\n\tmessage: Schema.String,\n}) {\n\tstatic invalidRequest = (message: string) => new RequestError({ code: -32600, message });\n\tstatic invalidParams = (message: string) => new RequestError({ code: -32602, message });\n\tstatic internalError = (message: string) => new RequestError({ code: -32603, message });\n\tstatic resourceNotFound = (message: string) => new RequestError({ code: -32002, message });\n}\n\ntype Handler<Request, Response> = (request: Request) => Effect.Effect<Response, RequestError>;\n\n/** Calls the agent makes to the connected client. */\nexport interface Client {\n\treadonly sessionUpdate: (notification: Acp.SessionNotification) => Effect.Effect<void, RequestError>;\n}\n\nexport interface Handlers {\n\treadonly initialize: Handler<Acp.InitializeRequest, Acp.InitializeResponse>;\n\treadonly newSession: Handler<Acp.NewSessionRequest, Acp.NewSessionResponse>;\n\t/** Must replay the session's history through `Client.sessionUpdate` before it returns. */\n\treadonly loadSession: Handler<Acp.LoadSessionRequest, Acp.LoadSessionResponse>;\n\treadonly listSessions: Handler<Acp.ListSessionsRequest, Acp.ListSessionsResponse>;\n\treadonly forkSession: Handler<Acp.ForkSessionRequest, Acp.ForkSessionResponse>;\n\treadonly setConfigOption: Handler<Acp.SetSessionConfigOptionRequest, Acp.SetSessionConfigOptionResponse>;\n\treadonly prompt: Handler<Acp.PromptRequest, Acp.PromptResponse>;\n\treadonly cancel: (notification: Acp.CancelNotification) => Effect.Effect<void>;\n}\n\n/**\n * Serves an ACP agent over `stdio` until the client closes its end.\n *\n * Handlers run as fibers on this effect's services; a request the client cancels, or the\n * connection closing, interrupts its fiber.\n */\nexport const serve = Effect.fn(\"ACP.serve\")(function* (\n\tstdio: Stdio.Stdio,\n\tmakeHandlers: (client: Client) => Handlers,\n): Effect.fn.Return<void, never, Scope.Scope> {\n\tconst context = yield* Effect.context<never>();\n\tconst runExit = Effect.runPromiseExitWith(context);\n\tconst opened = yield* Deferred.make<Acp.AgentConnection>();\n\n\tconst handlers = makeHandlers({\n\t\tsessionUpdate: (notification) =>\n\t\t\tDeferred.await(opened).pipe(\n\t\t\t\tEffect.flatMap((connection) =>\n\t\t\t\t\tEffect.tryPromise({\n\t\t\t\t\t\ttry: () => connection.client.notify(Acp.methods.client.session.update, notification),\n\t\t\t\t\t\tcatch: (error) => RequestError.internalError(`Failed to send session/update: ${String(error)}`),\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t});\n\n\t// A JSON-RPC answer for a handler that didn't succeed; the SDK sends what `handle` throws.\n\tconst toWire = (cause: Cause.Cause<RequestError>): Acp.RequestError => {\n\t\tconst error = Cause.findErrorOption(cause);\n\t\tif (Option.isSome(error)) return new Acp.RequestError(error.value.code, error.value.message);\n\t\tif (Cause.hasInterruptsOnly(cause)) return Acp.RequestError.requestCancelled();\n\t\treturn Acp.RequestError.internalError(undefined, String(Cause.squash(cause)));\n\t};\n\tconst handle =\n\t\t<Params, A>(handler: (params: Params) => Effect.Effect<A, RequestError>) =>\n\t\t({ params, signal }: { readonly params: Params; readonly signal: AbortSignal }): Promise<A> =>\n\t\t\trunExit(handler(params), { signal }).then((exit) => {\n\t\t\t\tif (Exit.isSuccess(exit)) return exit.value;\n\t\t\t\tthrow toWire(exit.cause);\n\t\t\t});\n\n\tconst input = yield* Stream.toReadableStreamEffect(stdio.stdin);\n\tconst output = new WritableStream<Uint8Array>({\n\t\twrite: (chunk) => Effect.runPromiseWith(context)(Stream.run(Stream.make(chunk), stdio.stdout())),\n\t});\n\n\tconst connection = Acp.agent({ name: \"codework\" })\n\t\t.onRequest(\"initialize\", handle(handlers.initialize))\n\t\t.onRequest(\"session/new\", handle(handlers.newSession))\n\t\t.onRequest(\"session/load\", handle(handlers.loadSession))\n\t\t.onRequest(\"session/list\", handle(handlers.listSessions))\n\t\t.onRequest(\"session/fork\", handle(handlers.forkSession))\n\t\t.onRequest(\"session/set_config_option\", handle(handlers.setConfigOption))\n\t\t.onRequest(\"session/prompt\", handle(handlers.prompt))\n\t\t.onNotification(\"session/cancel\", handle(handlers.cancel))\n\t\t.connect(Acp.ndJsonStream(output, input));\n\tyield* Deferred.succeed(opened, connection);\n\tyield* Effect.addFinalizer(() => Effect.sync(() => connection.close()));\n\tyield* Effect.promise(() => connection.closed);\n});\n\nexport * as Agent from \"./agent.ts\";\n","import type * as Acp from \"@agentclientprotocol/sdk\";\nimport { Model } from \"@codeworksh/aikit\";\nimport { ModelCatalog, Settings, type State } from \"@codeworksh/harness/effect\";\nimport { Effect, Option } from \"effect\";\n\nexport const MODEL = \"model\";\nexport const THOUGHT_LEVEL = \"thought_level\";\n\nconst thinkingLabels: Record<Model.ThinkingLevel, string> = {\n\toff: \"Off\",\n\tminimal: \"Minimal\",\n\tlow: \"Low\",\n\tmedium: \"Medium\",\n\thigh: \"High\",\n\txhigh: \"Extra High\",\n\tmax: \"Max\",\n};\n\nexport const isThinkingLevel = (value: string): value is Model.ThinkingLevel => Object.hasOwn(thinkingLabels, value);\n\n/** Splits a `provider/model` option value on its first slash; model ids may contain more. */\nexport const parseModel = (value: string): Option.Option<{ readonly provider: string; readonly id: string }> => {\n\tconst slash = value.indexOf(\"/\");\n\tif (slash <= 0 || slash === value.length - 1) return Option.none();\n\treturn Option.some({ provider: value.slice(0, slash), id: value.slice(slash + 1) });\n};\n\n/** The catalog a session in `hostDir` sees: generated entries plus its settings' `models`. */\nconst catalogFor = (hostDir: string | undefined) =>\n\tEffect.gen(function* () {\n\t\tconst settings = yield* Settings.Service;\n\t\treturn yield* ModelCatalog.effective((yield* settings.load(hostDir)).models);\n\t}).pipe(Effect.orElseSucceed((): Model.BuiltInModels => ({})));\n\n/** The `model` and `thought_level` selectors for a session's current configuration. */\nexport const options = Effect.fn(\"ACP.config.options\")(function* (\n\tselection: State.Configuration,\n\thostDir: string | undefined,\n) {\n\tconst catalog = yield* catalogFor(hostDir);\n\t// Providers the harness has credentials for; the current model stays selectable even if not.\n\tconst providers = yield* ModelCatalog.available(hostDir === undefined ? {} : { hostDir }).pipe(\n\t\tEffect.orElseSucceed(() => []),\n\t);\n\n\tconst current = `${selection.provider}/${selection.model}`;\n\tconst models = providers.flatMap((provider) =>\n\t\tObject.entries(provider.models).map(([id, info]) => ({\n\t\t\tvalue: `${provider.id}/${id}`,\n\t\t\tname: `${info.provider.name}: ${info.name}`,\n\t\t})),\n\t);\n\tif (!models.some((option) => option.value === current)) models.unshift({ value: current, name: current });\n\n\tconst result: Array<Acp.SessionConfigOption> = [\n\t\t{ id: MODEL, name: \"Model\", category: \"model\", type: \"select\", currentValue: current, options: models },\n\t];\n\n\tconst info = catalog[selection.provider]?.[selection.model];\n\tconst levels = info === undefined ? [] : Model.getSupportedThinkingLevels(info);\n\tif (levels.some((level) => level !== \"off\")) {\n\t\tresult.push({\n\t\t\tid: THOUGHT_LEVEL,\n\t\t\tname: \"Thinking Effort\",\n\t\t\tcategory: \"thought_level\",\n\t\t\ttype: \"select\",\n\t\t\tcurrentValue: selection.thinkingLevel,\n\t\t\toptions: levels.map((level) => ({ value: level, name: thinkingLabels[level] })),\n\t\t});\n\t}\n\treturn result;\n});\n\n/** Whether a model is in the catalog a session in `hostDir` sees. */\nexport const known = Effect.fn(\"ACP.config.known\")(function* (\n\tmodel: { readonly provider: string; readonly id: string },\n\thostDir: string | undefined,\n) {\n\tconst catalog = yield* catalogFor(hostDir);\n\treturn catalog[model.provider]?.[model.id] !== undefined;\n});\n\nexport * as Config from \"./config.ts\";\n","import type * as Acp from \"@agentclientprotocol/sdk\";\nimport { EventList, type EventSchema, type ThreadStore } from \"@codeworksh/harness/effect\";\nimport { Option, Schema } from \"effect\";\n\nconst isTextDelta = Schema.is(EventList.LLMTextDelta);\nconst isThinkingDelta = Schema.is(EventList.LLMThinkingDelta);\nconst isToolStarted = Schema.is(EventList.ToolStarted);\nconst isToolSettled = Schema.is(EventList.ToolSettled);\nconst isPluginUpdated = Schema.is(EventList.PluginUpdated);\n\nconst TextContent = Schema.Struct({ type: Schema.Literal(\"text\"), text: Schema.String });\nconst ImageContent = Schema.Struct({ type: Schema.Literal(\"image\"), data: Schema.String, mimeType: Schema.String });\nconst ToolResult = Schema.Struct({\n\tcontent: Schema.Array(Schema.Union([TextContent, Schema.Struct({ type: Schema.Literal(\"image\") })])),\n\tisError: Schema.Boolean,\n});\nconst ToolCall = Schema.Struct({\n\ttype: Schema.Literal(\"toolCall\"),\n\tcallID: Schema.String,\n\tname: Schema.String,\n\targuments: Schema.Record(Schema.String, Schema.Json),\n\tstatus: Schema.String,\n\tresult: Schema.optional(ToolResult),\n});\nconst StoredPart = Schema.Union([\n\tTextContent,\n\tImageContent,\n\tSchema.Struct({ type: Schema.Literal(\"thinking\"), thinking: Schema.String }),\n\tToolCall,\n]);\nconst decodePart = Schema.decodeUnknownOption(Schema.fromJsonString(StoredPart));\n\ntype ToolCall = typeof ToolCall.Type;\n\nconst text = (value: string): Acp.ContentBlock => ({ type: \"text\", text: value });\n\n// The kind comes from the tool's name. Only `bash` ships built in; plugin tools report `other`.\nconst kind = (name: string): Acp.ToolKind => (name === \"bash\" ? \"execute\" : \"other\");\n\n/** The command for `bash`, otherwise the tool's label or name. */\nconst title = (name: string, args: Readonly<Record<string, unknown>>, label?: string): string =>\n\tname === \"bash\" && typeof args.command === \"string\" ? args.command : (label ?? name);\n\nconst settled = (call: Pick<ToolCall, \"callID\" | \"name\" | \"arguments\" | \"status\" | \"result\">): Acp.SessionUpdate => {\n\tconst output = call.result?.content.flatMap((block) => (block.type === \"text\" ? [block.text] : [])).join(\"\\n\");\n\treturn {\n\t\tsessionUpdate: \"tool_call_update\",\n\t\ttoolCallId: call.callID,\n\t\tkind: kind(call.name),\n\t\tstatus: call.status === \"completed\" ? \"completed\" : \"failed\",\n\t\trawInput: call.arguments,\n\t\t...(call.result === undefined ? {} : { rawOutput: call.result }),\n\t\t...(output ? { content: [{ type: \"content\", content: text(output) }] } : {}),\n\t};\n};\n\n/** The live `session/update` for a harness event, if the client should see one. */\nexport const update = (event: EventSchema.Payload): Option.Option<Acp.SessionUpdate> => {\n\tif (isTextDelta(event)) {\n\t\treturn Option.some({ sessionUpdate: \"agent_message_chunk\", content: text(event.data.delta) });\n\t}\n\tif (isThinkingDelta(event)) {\n\t\treturn Option.some({ sessionUpdate: \"agent_thought_chunk\", content: text(event.data.delta) });\n\t}\n\tif (isToolStarted(event)) {\n\t\treturn Option.some({\n\t\t\tsessionUpdate: \"tool_call\",\n\t\t\ttoolCallId: event.data.callID,\n\t\t\ttitle: title(event.data.name, event.data.arguments, event.data.label),\n\t\t\tkind: kind(event.data.name),\n\t\t\tstatus: \"in_progress\",\n\t\t\trawInput: event.data.arguments,\n\t\t});\n\t}\n\tif (isToolSettled(event)) return Option.some(settled(event.data.part));\n\treturn Option.none();\n};\n\n/**\n * Text for the user about a plugin that failed to load, such as one configured but not installed.\n * It belongs in the conversation because the user may never see this process's logs.\n */\nexport const notice = (event: EventSchema.Payload): Option.Option<string> =>\n\tisPluginUpdated(event) && event.data.status === \"failed\" && event.data.error !== undefined\n\t\t? Option.some(event.data.error)\n\t\t: Option.none();\n\n/** A notice shown to the user in the agent's message. */\nexport const noticeUpdate = (notice: string): Acp.SessionUpdate => ({\n\tsessionUpdate: \"agent_message_chunk\",\n\tcontent: text(`> ⚠ ${notice}\\n\\n`),\n});\n\n/** The `session/update`s that replay one stored entry during `session/load`. */\nexport const replay = ({ entry, parts }: ThreadStore.HydratedEntry): ReadonlyArray<Acp.SessionUpdate> => {\n\tif (entry.type !== \"user\" && entry.type !== \"assistant\") return [];\n\treturn parts.flatMap((row): ReadonlyArray<Acp.SessionUpdate> => {\n\t\tconst part = decodePart(row.data);\n\t\tif (Option.isNone(part)) return [];\n\t\tswitch (part.value.type) {\n\t\t\tcase \"text\":\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\tsessionUpdate: entry.type === \"user\" ? \"user_message_chunk\" : \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: text(part.value.text),\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\tcase \"image\":\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\tsessionUpdate: entry.type === \"user\" ? \"user_message_chunk\" : \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"image\", data: part.value.data, mimeType: part.value.mimeType },\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\tcase \"thinking\":\n\t\t\t\treturn [{ sessionUpdate: \"agent_thought_chunk\", content: text(part.value.thinking) }];\n\t\t\tcase \"toolCall\":\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\tsessionUpdate: \"tool_call\",\n\t\t\t\t\t\ttoolCallId: part.value.callID,\n\t\t\t\t\t\ttitle: title(part.value.name, part.value.arguments),\n\t\t\t\t\t\tkind: kind(part.value.name),\n\t\t\t\t\t\tstatus: \"in_progress\",\n\t\t\t\t\t\trawInput: part.value.arguments,\n\t\t\t\t\t},\n\t\t\t\t\tsettled(part.value),\n\t\t\t\t];\n\t\t}\n\t});\n};\n\nexport * as Feed from \"./feed.ts\";\n","import type * as Acp from \"@agentclientprotocol/sdk\";\nimport {\n\tControl,\n\tEventList,\n\ttype EventSchema,\n\ttype Harness,\n\tPromptSchema,\n\tSession,\n\tSessionStore,\n\tThreadStore,\n} from \"@codeworksh/harness/effect\";\nimport { DateTime, Effect, Fiber, type Layer, Option, Schema, Stream } from \"effect\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport { Agent } from \"./agent.ts\";\nimport { Config } from \"./config.ts\";\nimport { Feed } from \"./feed.ts\";\n\nconst PAGE_SIZE = 50;\n\nconst isRequestError = Schema.is(Agent.RequestError);\nconst isNotFound = Schema.is(SessionStore.SessionNotFoundError);\nconst isConflict = Schema.is(Control.PromptConflictError);\nconst isInvalidPrompt = Schema.is(PromptSchema.InvalidPromptError);\nconst isLLMEnded = Schema.is(EventList.LLMEnded);\nconst isSucceeded = Schema.is(EventList.ExecutionSucceeded);\nconst isFailed = Schema.is(EventList.ExecutionFailed);\nconst isInterrupted = Schema.is(EventList.ExecutionInterrupted);\nconst isSettled = (event: EventSchema.Payload) => isSucceeded(event) || isFailed(event) || isInterrupted(event);\n\n/** Harness failures as JSON-RPC errors; handlers raise protocol-level ones directly. */\nconst toRequestError = (error: { readonly message: string }): Agent.RequestError => {\n\tif (isRequestError(error)) return error;\n\tif (isNotFound(error)) return Agent.RequestError.resourceNotFound(`Session not found: ${error.sessionId}`);\n\tif (isConflict(error)) return Agent.RequestError.invalidRequest(error.message);\n\tif (isInvalidPrompt(error)) return Agent.RequestError.invalidParams(error.message);\n\treturn Agent.RequestError.internalError(error.message);\n};\n\n/**\n * Prompt content as harness prompt parts, in order. Text, embedded context and images are\n * advertised; anything else is rejected. Adjacent text joins into one part. The harness checks\n * the images.\n */\nconst promptParts = Effect.fnUntraced(function* (blocks: ReadonlyArray<Acp.ContentBlock>) {\n\tconst parts: Array<PromptSchema.Part> = [];\n\tconst add = (part: PromptSchema.Part) => {\n\t\tconst last = parts.at(-1);\n\t\tif (part.type === \"text\" && last?.type === \"text\")\n\t\t\tparts[parts.length - 1] = { ...last, text: `${last.text}\\n\\n${part.text}` };\n\t\telse parts.push(part);\n\t};\n\tfor (const block of blocks) {\n\t\tswitch (block.type) {\n\t\t\tcase \"text\":\n\t\t\t\tadd({ type: \"text\", text: block.text });\n\t\t\t\tbreak;\n\t\t\tcase \"resource_link\":\n\t\t\t\tadd({ type: \"text\", text: `[${block.name}](${block.uri})` });\n\t\t\t\tbreak;\n\t\t\tcase \"image\":\n\t\t\t\tadd({ type: \"image\", data: block.data, mimeType: block.mimeType });\n\t\t\t\tbreak;\n\t\t\tcase \"resource\":\n\t\t\t\tif (\"text\" in block.resource) {\n\t\t\t\t\tadd({ type: \"text\", text: `\\`\\`\\`${block.resource.uri}\\n${block.resource.text}\\n\\`\\`\\`` });\n\t\t\t\t} else if (block.resource.mimeType?.startsWith(\"image/\")) {\n\t\t\t\t\tadd({ type: \"image\", data: block.resource.blob, mimeType: block.resource.mimeType });\n\t\t\t\t} else {\n\t\t\t\t\treturn yield* Agent.RequestError.invalidParams(`Unsupported binary resource: ${block.resource.uri}`);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn yield* Agent.RequestError.invalidParams(`Unsupported prompt content: ${block.type}`);\n\t\t}\n\t}\n\treturn parts;\n});\n\nconst threadId = (id: string) => Session.ThreadSchema.ID.make(id);\n\ntype Services = Layer.Success<ReturnType<typeof Harness.layer>>;\n\nexport const make = Effect.gen(function* () {\n\tconst control = yield* Control.Service;\n\tconst sessions = yield* SessionStore.Service;\n\tconst threads = yield* ThreadStore.Service;\n\t// Handlers run on the agent's fibers, outside this layer; they carry the harness with them.\n\tconst context = yield* Effect.context<Services>();\n\n\tconst running = new Set<string>();\n\n\t// Every thread is an ACP session of its own. The main thread keeps the CodeWork session's id,\n\t// so a session an editor knew before it had forks still loads; any other thread goes by its id.\n\tconst acpId = (thread: { readonly originKind: string; readonly sessionId: string; readonly id: string }) =>\n\t\tthread.originKind === \"main\" ? thread.sessionId : thread.id;\n\n\t/** The CodeWork session and thread an ACP session id names. */\n\tconst resolve = Effect.fn(\"ACP.resolve\")(function* (id: string) {\n\t\tconst session = yield* sessions.get(id);\n\t\tif (Option.isSome(session)) {\n\t\t\tconst main = yield* threads.main(session.value.id);\n\t\t\tif (Option.isSome(main)) return { session: session.value, threadId: threadId(main.value.id) };\n\t\t}\n\t\tconst thread = yield* threads.get(id);\n\t\tif (Option.isSome(thread)) {\n\t\t\tconst owner = yield* sessions.get(thread.value.sessionId);\n\t\t\tif (Option.isSome(owner)) return { session: owner.value, threadId: threadId(thread.value.id) };\n\t\t}\n\t\treturn yield* new SessionStore.SessionNotFoundError({ sessionId: id });\n\t});\n\n\tconst attach = Effect.fn(\"ACP.attach\")(function* (id: string) {\n\t\tconst { session, threadId } = yield* resolve(id);\n\t\tconst thread = yield* Session.attach({ sessionId: session.id, threadId });\n\t\treturn { thread, hostDir: Option.getOrUndefined(session.hostDir) };\n\t});\n\n\treturn (client: Agent.Client): Agent.Handlers => {\n\t\tconst run = <A, E extends { readonly message: string }>(effect: Effect.Effect<A, E, Services>) =>\n\t\t\teffect.pipe(Effect.provide(context), Effect.mapError(toRequestError));\n\n\t\treturn {\n\t\t\tinitialize: () =>\n\t\t\t\tEffect.succeed({\n\t\t\t\t\tprotocolVersion: 1,\n\t\t\t\t\tagentInfo: { name: \"codework\", version: pkg.version },\n\t\t\t\t\tagentCapabilities: {\n\t\t\t\t\t\tloadSession: true,\n\t\t\t\t\t\tpromptCapabilities: { embeddedContext: true, image: true },\n\t\t\t\t\t\tsessionCapabilities: { list: {}, fork: {} },\n\t\t\t\t\t},\n\t\t\t\t}),\n\n\t\t\tnewSession: ({ cwd }) =>\n\t\t\t\trun(\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tconst handle = yield* Session.create({ directory: cwd, hostDir: cwd });\n\t\t\t\t\t\tconst current = yield* Session.configuration(handle.main.id);\n\t\t\t\t\t\treturn { sessionId: handle.id, configOptions: yield* Config.options(current, cwd) };\n\t\t\t\t\t}),\n\t\t\t\t),\n\n\t\t\tloadSession: ({ sessionId: id }) =>\n\t\t\t\trun(\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tconst { thread, hostDir } = yield* attach(id);\n\t\t\t\t\t\tconst current = yield* Session.configuration(thread.id);\n\t\t\t\t\t\t// A fork replays its whole line, the part it inherits included.\n\t\t\t\t\t\tfor (const entry of yield* thread.history()) {\n\t\t\t\t\t\t\tfor (const update of Feed.replay(entry)) {\n\t\t\t\t\t\t\t\tyield* client.sessionUpdate({ sessionId: id, update });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn { configOptions: yield* Config.options(current, hostDir) };\n\t\t\t\t\t}),\n\t\t\t\t),\n\n\t\t\tlistSessions: ({ cwd, cursor }) =>\n\t\t\t\trun(\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tconst owners = new Map((yield* sessions.list()).map((row) => [row.id, row]));\n\t\t\t\t\t\tconst all = yield* threads.list();\n\t\t\t\t\t\tconst titles = new Map(all.map((thread) => [thread.id, Option.getOrUndefined(thread.title)]));\n\t\t\t\t\t\tconst rows = all\n\t\t\t\t\t\t\t.flatMap((thread) => {\n\t\t\t\t\t\t\t\tconst session = owners.get(thread.sessionId);\n\t\t\t\t\t\t\t\treturn session === undefined ? [] : [{ thread, session }];\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.filter(({ session }) => cwd == null || Option.getOrUndefined(session.hostDir) === cwd)\n\t\t\t\t\t\t\t.sort((a, b) =>\n\t\t\t\t\t\t\t\tDateTime.Order(\n\t\t\t\t\t\t\t\t\tb.thread.updatedAt ?? b.thread.createdAt,\n\t\t\t\t\t\t\t\t\ta.thread.updatedAt ?? a.thread.createdAt,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\tconst offset = cursor == null ? 0 : Number(cursor);\n\t\t\t\t\t\tif (!Number.isSafeInteger(offset) || offset < 0) {\n\t\t\t\t\t\t\treturn yield* Agent.RequestError.invalidParams(`Invalid cursor: ${cursor}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst next = offset + PAGE_SIZE;\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tsessions: rows.slice(offset, next).map(({ thread, session }) => ({\n\t\t\t\t\t\t\t\tsessionId: acpId(thread),\n\t\t\t\t\t\t\t\tcwd: Option.getOrElse(session.hostDir, () => session.directory),\n\t\t\t\t\t\t\t\t// A fork is untitled until its own first prompt; it reads as its source until then.\n\t\t\t\t\t\t\t\ttitle:\n\t\t\t\t\t\t\t\t\ttitles.get(thread.id) ??\n\t\t\t\t\t\t\t\t\tOption.match(thread.originThreadId, {\n\t\t\t\t\t\t\t\t\t\tonNone: () => undefined,\n\t\t\t\t\t\t\t\t\t\tonSome: (origin) => titles.get(origin),\n\t\t\t\t\t\t\t\t\t}) ??\n\t\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\tupdatedAt: DateTime.formatIso(thread.updatedAt ?? thread.createdAt),\n\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t...(next < rows.length ? { nextCursor: String(next) } : {}),\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t\t),\n\n\t\t\tforkSession: ({ sessionId: id }) =>\n\t\t\t\trun(\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tconst { thread, hostDir } = yield* attach(id);\n\t\t\t\t\t\t// ACP forks the conversation as it stands: at its last committed entry, of any type, so\n\t\t\t\t\t\t// a trailing tool result or compaction comes along.\n\t\t\t\t\t\tconst last = (yield* thread.history()).findLast(({ entry }) => entry.state === \"committed\");\n\t\t\t\t\t\tif (last === undefined) {\n\t\t\t\t\t\t\treturn yield* Agent.RequestError.invalidRequest(\n\t\t\t\t\t\t\t\t\"Nothing to fork yet: the session has no messages\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst forked = yield* thread.fork({ entryId: last.entry.id });\n\t\t\t\t\t\tconst current = yield* Session.configuration(forked.thread.id);\n\t\t\t\t\t\treturn { sessionId: forked.thread.id, configOptions: yield* Config.options(current, hostDir) };\n\t\t\t\t\t}),\n\t\t\t\t),\n\n\t\t\tsetConfigOption: (request) =>\n\t\t\t\trun(\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tconst { session, threadId } = yield* resolve(request.sessionId);\n\t\t\t\t\t\tconst hostDir = Option.getOrUndefined(session.hostDir);\n\t\t\t\t\t\tconst value = String(request.value);\n\t\t\t\t\t\tlet runtime: Session.RuntimeInput;\n\t\t\t\t\t\tif (request.configId === Config.MODEL) {\n\t\t\t\t\t\t\tconst model = Option.getOrUndefined(Config.parseModel(value));\n\t\t\t\t\t\t\tif (model === undefined || !(yield* Config.known(model, hostDir))) {\n\t\t\t\t\t\t\t\treturn yield* Agent.RequestError.invalidParams(`Unknown model: ${value}`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\truntime = { model };\n\t\t\t\t\t\t} else if (request.configId === Config.THOUGHT_LEVEL) {\n\t\t\t\t\t\t\tif (!Config.isThinkingLevel(value)) {\n\t\t\t\t\t\t\t\treturn yield* Agent.RequestError.invalidParams(`Unknown thinking level: ${value}`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\truntime = { thinkingLevel: value };\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn yield* Agent.RequestError.invalidParams(`Unknown config option: ${request.configId}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst thread = yield* Session.attach({ sessionId: session.id, threadId, ...runtime });\n\t\t\t\t\t\treturn { configOptions: yield* Config.options(yield* Session.configuration(thread.id), hostDir) };\n\t\t\t\t\t}),\n\t\t\t\t),\n\n\t\t\tprompt: ({ sessionId: id, prompt }) =>\n\t\t\t\trun(\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tconst parts = yield* promptParts(prompt);\n\t\t\t\t\t\tconst { thread: handle } = yield* attach(id);\n\t\t\t\t\t\t// Keyed by thread: main answers to its session id and its own thread id alike.\n\t\t\t\t\t\tif (running.has(handle.id)) {\n\t\t\t\t\t\t\treturn yield* Agent.RequestError.invalidRequest(\"A prompt is already running for this session\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\trunning.add(handle.id);\n\t\t\t\t\t\tyield* Effect.addFinalizer(() => Effect.sync(() => running.delete(handle.id)));\n\n\t\t\t\t\t\t// Forward this execution's updates until it settles; the settling event decides the answer.\n\t\t\t\t\t\tlet reason: EventList.LLMEnded[\"data\"][\"reason\"] | undefined;\n\t\t\t\t\t\t// Plugins are checked every exchange; tell the user about each failure once per prompt.\n\t\t\t\t\t\tconst notices = new Set<string>();\n\t\t\t\t\t\tconst settled = yield* handle.events().pipe(\n\t\t\t\t\t\t\tStream.tap((event) => {\n\t\t\t\t\t\t\t\tif (isLLMEnded(event)) reason = event.data.reason;\n\t\t\t\t\t\t\t\tlet update = Feed.update(event);\n\t\t\t\t\t\t\t\tconst notice = Feed.notice(event);\n\t\t\t\t\t\t\t\tif (Option.isSome(notice) && !notices.has(notice.value)) {\n\t\t\t\t\t\t\t\t\tnotices.add(notice.value);\n\t\t\t\t\t\t\t\t\tupdate = Option.some(Feed.noticeUpdate(notice.value));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn Option.match(update, {\n\t\t\t\t\t\t\t\t\tonNone: () => Effect.void,\n\t\t\t\t\t\t\t\t\tonSome: (update) => client.sessionUpdate({ sessionId: id, update }).pipe(Effect.ignore),\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tStream.filter(isSettled),\n\t\t\t\t\t\t\tStream.runHead,\n\t\t\t\t\t\t\tEffect.forkScoped({ startImmediately: true }),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst before = (yield* handle.info).title;\n\t\t\t\t\t\tyield* handle.run({ parts });\n\t\t\t\t\t\tconst end = yield* Fiber.join(settled);\n\n\t\t\t\t\t\t// The harness titles a thread from its first prompt; tell the editor.\n\t\t\t\t\t\tconst { title } = yield* handle.info;\n\t\t\t\t\t\tif (title !== undefined && title !== before) {\n\t\t\t\t\t\t\tyield* client\n\t\t\t\t\t\t\t\t.sessionUpdate({ sessionId: id, update: { sessionUpdate: \"session_info_update\", title } })\n\t\t\t\t\t\t\t\t.pipe(Effect.ignore);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (Option.isNone(end) || isInterrupted(end.value)) return { stopReason: \"cancelled\" as const };\n\t\t\t\t\t\tif (isFailed(end.value)) return yield* Agent.RequestError.internalError(end.value.data.error.message);\n\t\t\t\t\t\treturn { stopReason: reason === \"length\" ? (\"max_tokens\" as const) : (\"end_turn\" as const) };\n\t\t\t\t\t}).pipe(Effect.scoped),\n\t\t\t\t),\n\n\t\t\tcancel: ({ sessionId: id }) =>\n\t\t\t\tresolve(id).pipe(\n\t\t\t\t\tEffect.flatMap((found) => control.interrupt(found.threadId, { reason: \"user\" })),\n\t\t\t\t\tEffect.ignore,\n\t\t\t\t\tEffect.provide(context),\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 { Effect, Logger, Stdio } from \"effect\";\nimport { Agent } from \"./agent.ts\";\nimport { Handlers } from \"./handlers.ts\";\n\n// Sessions and managed sandboxes outlive any single request; the connection's end is what stops them.\nconst shutdown = Effect.gen(function* () {\n\tconst control = yield* Control.Service;\n\tyield* Effect.forEach(\n\t\tyield* control.active,\n\t\t(id) =>\n\t\t\tcontrol\n\t\t\t\t.interrupt(id, { reason: \"shutdown\", awaitSettlement: true })\n\t\t\t\t.pipe(Effect.timeout(\"10 seconds\"), Effect.ignore),\n\t\t{ concurrency: \"unbounded\", discard: true },\n\t);\n\tconst managed = (yield* Sandbox.list()).filter((info) => info.ownership === \"managed\");\n\tyield* Effect.forEach(\n\t\tmanaged,\n\t\t(info) =>\n\t\t\tSandbox.stop(info.id).pipe(\n\t\t\t\tEffect.timeout(\"10 seconds\"),\n\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\tEffect.logError(\"Failed to stop managed sandbox during ACP shutdown\", cause).pipe(\n\t\t\t\t\t\tEffect.annotateLogs({ sandboxInstanceId: info.id }),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t{ concurrency: \"unbounded\", discard: true },\n\t);\n});\n\n/**\n * Serves ACP v1 on stdio until the client disconnects.\n *\n * stdout carries the protocol, so logs go to stderr. The reference is set outside the harness layer\n * so the fibers it forks (turns, plugin loads) inherit it too.\n */\nexport const serve = (options: Harness.Options) =>\n\tEffect.gen(function* () {\n\t\tyield* Effect.addFinalizer(() => shutdown.pipe(Effect.ignore));\n\t\tconst handlers = yield* Handlers.make;\n\t\tyield* Agent.serve(yield* Stdio.Stdio, handlers);\n\t}).pipe(Effect.scoped, Effect.provide(Harness.layer(options)), Effect.provideService(Logger.LogToStderr, true));\n\nexport * as Server from \"./server.ts\";\n","import { Effect } from \"effect\";\nimport { Server } from \"../../../acp/server.ts\";\nimport { Runtime } from \"../../../framework/runtime.ts\";\nimport { reportFailure } from \"../../error.ts\";\nimport { harnessOptions } from \"../../harness.ts\";\nimport { Cmd } from \"../cmd.ts\";\n\nexport default Runtime.handler(\n\tCmd.commands.acp,\n\tEffect.fn(\"CLI.acp\", { level: \"Info\" })(function* () {\n\t\tconst shared = yield* Cmd.spec;\n\t\treturn yield* Server.serve(harnessOptions(shared)).pipe(Effect.catch(reportFailure));\n\t}),\n);\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { i as Cmd, t as handler } from "./runtime-B43doHjV.mjs";
2
- import { d as writeOut, i as reportFailure } from "./error-BMI81XvR.mjs";
3
- import { a as resolveTarget, c as withPluginsLock, i as readPlugins, l as writePlugins, n as matches, o as spellings, t as identify, u as written } from "./settings-BfmoL27m.mjs";
1
+ import { i as Cmd, t as handler } from "./runtime-Bg4mc9BB.mjs";
2
+ import { f as writeOut, i as reportFailure } from "./error-CSeYCa9R.mjs";
3
+ import { a as resolveTarget, c as withPluginsLock, i as readPlugins, l as writePlugins, n as matches, o as spellings, t as identify, u as written } from "./settings-DcwstDUm.mjs";
4
4
  import { Effect, Layer, Option, Path } from "effect";
5
5
  import { Database, Event, Global, Plugin, Session, SessionStore } from "@codeworksh/harness/effect";
6
6
  //#region src/cli/cmd/handlers/plugin/session.ts
@@ -26,7 +26,7 @@ const linkedDirectory = Effect.fn("CLI.plugin.linkedDirectory")(function* (sessi
26
26
  const hostDir = Option.getOrUndefined(found.value.hostDir);
27
27
  if (hostDir === void 0) return yield* new SessionStore.SessionNotLinkedError({ sessionId: id });
28
28
  return hostDir;
29
- }).pipe(Effect.provide(SessionStore.layer.pipe(Layer.provide(Event.layer), Layer.provide(Database.layer(yield* Database.path(paths.data))))));
29
+ }).pipe(Effect.provide(SessionStore.storeLayer.pipe(Layer.provide(Event.layer), Layer.provide(Database.layer(yield* Database.path(paths.data))))));
30
30
  });
31
31
  //#endregion
32
32
  //#region src/cli/cmd/handlers/plugin/add.ts
@@ -79,4 +79,4 @@ var add_default = handler(Cmd.commands.plugin.commands.add, Effect.fn("CLI.plugi
79
79
  //#endregion
80
80
  export { add_default as default };
81
81
 
82
- //# sourceMappingURL=add-Dzsv-fKd.mjs.map
82
+ //# sourceMappingURL=add-Dm3RaxB1.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-Dm3RaxB1.mjs","names":["Runtime.handler"],"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.storeLayer.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,4 +1,4 @@
1
- import { i as Cmd } from "./runtime-B43doHjV.mjs";
1
+ import { i as Cmd } from "./runtime-Bg4mc9BB.mjs";
2
2
  import { Effect, Option } from "effect";
3
3
  import { Global, ModelCatalog } from "@codeworksh/harness/effect";
4
4
  //#region src/cli/cmd/handlers/models/catalog.ts
@@ -14,4 +14,4 @@ const synced = Effect.gen(function* () {
14
14
  //#endregion
15
15
  export { synced as n, home as t };
16
16
 
17
- //# sourceMappingURL=catalog-C1G3pzHZ.mjs.map
17
+ //# sourceMappingURL=catalog-Do2eDgti.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"catalog-C1G3pzHZ.mjs","names":[],"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,OAAO,OAAO,QAAQ,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,OAAO,aAAa,KAAK,OAAO,IAAI;AACrC,CAAC"}
1
+ {"version":3,"file":"catalog-Do2eDgti.mjs","names":[],"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,OAAO,OAAO,QAAQ,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,OAAO,aAAa,KAAK,OAAO,IAAI;AACrC,CAAC"}
@@ -1,6 +1,6 @@
1
- import { i as Cmd, t as handler } from "./runtime-B43doHjV.mjs";
2
- import { d as writeOut, i as reportFailure } from "./error-BMI81XvR.mjs";
3
- import { a as targeted, i as read, n as local, r as probe, t as fetchable } from "./entries-KpYvZdpi.mjs";
1
+ import { i as Cmd, t as handler } from "./runtime-Bg4mc9BB.mjs";
2
+ import { f as writeOut, i as reportFailure } from "./error-CSeYCa9R.mjs";
3
+ import { a as targeted, i as read, n as local, r as probe, t as fetchable } from "./entries-C6AeEOS1.mjs";
4
4
  import { Effect, Option } from "effect";
5
5
  import { Plugin } from "@codeworksh/harness/effect";
6
6
  //#region src/cli/cmd/handlers/plugin/check.ts
@@ -51,4 +51,4 @@ var check_default = handler(Cmd.commands.plugin.commands.check, Effect.fn("CLI.p
51
51
  //#endregion
52
52
  export { check_default as default };
53
53
 
54
- //# sourceMappingURL=check-DhojkK_E.mjs.map
54
+ //# sourceMappingURL=check-BdfxwBaL.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"check-DhojkK_E.mjs","names":["Runtime.handler"],"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,OAAO,OAAO,MAAM,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
+ {"version":3,"file":"check-BdfxwBaL.mjs","names":["Runtime.handler"],"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,OAAO,OAAO,MAAM,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,5 +1,5 @@
1
- import { d as writeOut } from "./error-BMI81XvR.mjs";
2
- import { s as userLayer } from "./settings-BfmoL27m.mjs";
1
+ import { f as writeOut } from "./error-CSeYCa9R.mjs";
2
+ import { s as userLayer } from "./settings-DcwstDUm.mjs";
3
3
  import { Effect, Option, Path } from "effect";
4
4
  import { Global, Plugin, Settings } from "@codeworksh/harness/effect";
5
5
  //#region src/cli/cmd/handlers/plugin/entries.ts
@@ -87,4 +87,4 @@ const fetchable = (target) => target === void 0 || target.kind === "local" ? voi
87
87
  //#endregion
88
88
  export { targeted as a, read as i, local as n, probe as r, fetchable as t };
89
89
 
90
- //# sourceMappingURL=entries-KpYvZdpi.mjs.map
90
+ //# sourceMappingURL=entries-C6AeEOS1.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"entries-KpYvZdpi.mjs","names":[],"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,OAAO,OAAO,QAAQ,OAAO,OAAO,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,MAAM,OAAO,KAAK,MAAM,CAAC;CACjG,MAAM,OAAO,OAAO,SAAS,YAAY,SAAS,MAAM,IAAI;CAC5D,MAAM,SAAS;EAAE,MAAM,MAAM;EAAM,GAAG,UAAU,QAAQ,OAAO;CAAE;CAQjE,MAAM,OAAO,OAAO,SAAS,KAAK,MAAM;CACxC,MAAM,QAAQ,SAAS,KAAA,IAAY,CAAC,IAAI,IAAI,CAAC,MAAM,OAAO,SAAS,KAAK;EAAE,GAAG;EAAQ,SAAS;CAAK,CAAC,CAAC;CAIrG,MAAM,0BAAU,IAAI,IAAmB;CACvC,KAAK,MAAM,QAAQ,OAGlB,KAAK,MAAM,CAAC,WAAW,QAAQ,SAAS,QAAQ,KAAK,QAAQ,GAAG;EAG/D,MAAM,SAAS,OAAO,eAAe,OAAO,OAAO,MAAM,WAAW,OAAO,CAAC,CAAC,KAAK,OAAO,MAAM,CAAC;EAChG,MAAM,OAAO,OAAO,OAAO,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,OAAO,OAAO,SAAS,SAAS,OAAO,IAAI,CAAC,CAAC,KAAK,OAAO,oBAAoB,GAAG,UAAU,IAAI,MAAM,CAAC;AACtG;;AAGA,MAAM,UAAU,WAAmB,YAClC,OAAO,UAAU,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,OAAO,OAAO,UAAU,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,WACA,OAAO,MAAM,QAAQ,OAAO,IAAI;;AAGlC,MAAa,aAAa,WACzB,WAAW,KAAA,KAAa,OAAO,SAAS,UAAU,KAAA,IAAY"}
1
+ {"version":3,"file":"entries-C6AeEOS1.mjs","names":[],"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,OAAO,OAAO,QAAQ,OAAO,OAAO,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,MAAM,OAAO,KAAK,MAAM,CAAC;CACjG,MAAM,OAAO,OAAO,SAAS,YAAY,SAAS,MAAM,IAAI;CAC5D,MAAM,SAAS;EAAE,MAAM,MAAM;EAAM,GAAG,UAAU,QAAQ,OAAO;CAAE;CAQjE,MAAM,OAAO,OAAO,SAAS,KAAK,MAAM;CACxC,MAAM,QAAQ,SAAS,KAAA,IAAY,CAAC,IAAI,IAAI,CAAC,MAAM,OAAO,SAAS,KAAK;EAAE,GAAG;EAAQ,SAAS;CAAK,CAAC,CAAC;CAIrG,MAAM,0BAAU,IAAI,IAAmB;CACvC,KAAK,MAAM,QAAQ,OAGlB,KAAK,MAAM,CAAC,WAAW,QAAQ,SAAS,QAAQ,KAAK,QAAQ,GAAG;EAG/D,MAAM,SAAS,OAAO,eAAe,OAAO,OAAO,MAAM,WAAW,OAAO,CAAC,CAAC,KAAK,OAAO,MAAM,CAAC;EAChG,MAAM,OAAO,OAAO,OAAO,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,OAAO,OAAO,SAAS,SAAS,OAAO,IAAI,CAAC,CAAC,KAAK,OAAO,oBAAoB,GAAG,UAAU,IAAI,MAAM,CAAC;AACtG;;AAGA,MAAM,UAAU,WAAmB,YAClC,OAAO,UAAU,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,OAAO,OAAO,UAAU,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,WACA,OAAO,MAAM,QAAQ,OAAO,IAAI;;AAGlC,MAAa,aAAa,WACzB,WAAW,KAAA,KAAa,OAAO,SAAS,UAAU,KAAA,IAAY"}