@codeworksh/cli 0.0.1-dev.20260923102823 → 0.0.1-dev.20260925163815

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/{add-D1yPPRz2.mjs → add-BPuCxrRi.mjs} +14 -13
  2. package/add-BPuCxrRi.mjs.map +1 -0
  3. package/{catalog-BtH_l7f2.mjs → catalog-DyQXd30n.mjs} +5 -5
  4. package/catalog-DyQXd30n.mjs.map +1 -0
  5. package/{check-B7Uh_G-l.mjs → check-CKi11Mtm.mjs} +17 -10
  6. package/check-CKi11Mtm.mjs.map +1 -0
  7. package/entries-BXBULTVt.mjs +90 -0
  8. package/entries-BXBULTVt.mjs.map +1 -0
  9. package/error-CxoEKg-4.mjs +610 -0
  10. package/error-CxoEKg-4.mjs.map +1 -0
  11. package/{harness-LSywfXzo.mjs → harness-6d8TlAVk.mjs} +4 -3
  12. package/harness-6d8TlAVk.mjs.map +1 -0
  13. package/index.mjs +18 -18
  14. package/{install-zXEeTQ8w.mjs → install-C2QXwvU6.mjs} +7 -6
  15. package/install-C2QXwvU6.mjs.map +1 -0
  16. package/{link-DquUj9D6.mjs → link-D5uOUo0m.mjs} +6 -5
  17. package/{link-DquUj9D6.mjs.map → link-D5uOUo0m.mjs.map} +1 -1
  18. package/{list-eorMHI-g.mjs → list-B7wmE2Hz.mjs} +11 -10
  19. package/list-B7wmE2Hz.mjs.map +1 -0
  20. package/{list-C1ZWDpwI.mjs → list-CEDVgkex.mjs} +6 -5
  21. package/list-CEDVgkex.mjs.map +1 -0
  22. package/{login-DEjauWkd.mjs → login-DD5n0PHg.mjs} +4 -4
  23. package/{login-DEjauWkd.mjs.map → login-DD5n0PHg.mjs.map} +1 -1
  24. package/{logout-BUY-ESj_.mjs → logout--lzv9ftF.mjs} +4 -4
  25. package/{logout-BUY-ESj_.mjs.map → logout--lzv9ftF.mjs.map} +1 -1
  26. package/package.json +7 -33
  27. package/{providers-wTGawU9e.mjs → providers-CO0ERtiv.mjs} +6 -5
  28. package/providers-CO0ERtiv.mjs.map +1 -0
  29. package/{refresh-B2jxJmk1.mjs → refresh-BcI6iAiQ.mjs} +6 -5
  30. package/refresh-BcI6iAiQ.mjs.map +1 -0
  31. package/{refresh-C7e_qZit.mjs → refresh-DKBOk5RX.mjs} +4 -4
  32. package/{refresh-C7e_qZit.mjs.map → refresh-DKBOk5RX.mjs.map} +1 -1
  33. package/{reload-B5LO2rk9.mjs → reload-L4NyTZaU.mjs} +3 -3
  34. package/{reload-B5LO2rk9.mjs.map → reload-L4NyTZaU.mjs.map} +1 -1
  35. package/{remove-CTVgJKXM.mjs → remove-CpLi76Ah.mjs} +6 -5
  36. package/remove-CpLi76Ah.mjs.map +1 -0
  37. package/{run-CORFA6op.mjs → run-D7h83L_m.mjs} +17 -16
  38. package/run-D7h83L_m.mjs.map +1 -0
  39. package/{runtime-Bp4kILYn.mjs → runtime-B3dlWGfs.mjs} +25 -12
  40. package/runtime-B3dlWGfs.mjs.map +1 -0
  41. package/{serve-DzaOcgKC.mjs → serve-BGrH_Wr6.mjs} +35 -34
  42. package/serve-BGrH_Wr6.mjs.map +1 -0
  43. package/{settings-tMD7Y0ev.mjs → settings-aqM_b9UE.mjs} +29 -23
  44. package/settings-aqM_b9UE.mjs.map +1 -0
  45. package/{shared-D8hbPMPF.mjs → shared-IycfDUnF.mjs} +5 -4
  46. package/shared-IycfDUnF.mjs.map +1 -0
  47. package/{status-CrAKnTHQ.mjs → status-CCj71RVv.mjs} +4 -4
  48. package/{status-CrAKnTHQ.mjs.map → status-CCj71RVv.mjs.map} +1 -1
  49. package/{update-DK7kAVc3.mjs → update-C-RdaEiC.mjs} +18 -11
  50. package/update-C-RdaEiC.mjs.map +1 -0
  51. package/add-D1yPPRz2.mjs.map +0 -1
  52. package/catalog-BtH_l7f2.mjs.map +0 -1
  53. package/check-B7Uh_G-l.mjs.map +0 -1
  54. package/commonjs-bcl-ngMU.mjs +0 -160
  55. package/commonjs-bcl-ngMU.mjs.map +0 -1
  56. package/definitions-XbglYT7Q.mjs +0 -3348
  57. package/definitions-XbglYT7Q.mjs.map +0 -1
  58. package/entries-B4tUkrxs.mjs +0 -48
  59. package/entries-B4tUkrxs.mjs.map +0 -1
  60. package/error-DG5INUkQ.mjs +0 -10321
  61. package/error-DG5INUkQ.mjs.map +0 -1
  62. package/harness-LSywfXzo.mjs.map +0 -1
  63. package/index.d.mts +0 -24
  64. package/install-zXEeTQ8w.mjs.map +0 -1
  65. package/lib-BCUUrctP.mjs +0 -846
  66. package/lib-BCUUrctP.mjs.map +0 -1
  67. package/lib-CNtGmPS7.mjs +0 -16078
  68. package/lib-CNtGmPS7.mjs.map +0 -1
  69. package/lib-CZnS894S.mjs +0 -10868
  70. package/lib-CZnS894S.mjs.map +0 -1
  71. package/lib-DHoZNIet.mjs +0 -37659
  72. package/lib-DHoZNIet.mjs.map +0 -1
  73. package/list-C1ZWDpwI.mjs.map +0 -1
  74. package/list-eorMHI-g.mjs.map +0 -1
  75. package/p-map-CMI1i54p.mjs +0 -116
  76. package/p-map-CMI1i54p.mjs.map +0 -1
  77. package/providers-wTGawU9e.mjs.map +0 -1
  78. package/refresh-B2jxJmk1.mjs.map +0 -1
  79. package/remove-CTVgJKXM.mjs.map +0 -1
  80. package/run-CORFA6op.mjs.map +0 -1
  81. package/runtime-Bp4kILYn.mjs.map +0 -1
  82. package/serve-DzaOcgKC.mjs.map +0 -1
  83. package/settings-tMD7Y0ev.mjs.map +0 -1
  84. package/shared-D8hbPMPF.mjs.map +0 -1
  85. package/type-defs-JBxRyl-4.mjs +0 -538
  86. package/type-defs-JBxRyl-4.mjs.map +0 -1
  87. package/update-DK7kAVc3.mjs.map +0 -1
  88. package/valid-Bc7tec52.mjs +0 -354
  89. package/valid-Bc7tec52.mjs.map +0 -1
@@ -0,0 +1,610 @@
1
+ import { Deferred, Duration, Effect, Layer, Predicate, Schema, Stream } from "effect";
2
+ import { Model } from "@codeworksh/aikit";
3
+ import { Control, Event, EventList, EventSchema, Location, ModelCatalog, Plugin, PromptSchema, Runner, Sandbox, SandboxError, Session, SessionStore, Settings, optional } from "@codeworksh/harness/effect";
4
+ import { SandboxProvider } from "@codeworksh/harness/sandbox";
5
+ import { NodeSocket } from "@effect/platform-node";
6
+ import { Rpc, RpcClient, RpcGroup, RpcSerialization } from "effect/unstable/rpc";
7
+ //#region src/server/envelope.ts
8
+ /**
9
+ * The wire form of an `EventSchema.Payload`. `data` is carried in its encoded
10
+ * form — decoded payloads are not wire-safe (`Schema.Duration`, aikit class
11
+ * transforms) — so clients decode it lazily through their own copy of the
12
+ * registry and can skip types they do not know.
13
+ */
14
+ const EventEnvelope = Schema.Struct({
15
+ id: EventSchema.ID,
16
+ type: Schema.String,
17
+ durable: optional(Schema.Struct({
18
+ aggregateId: Schema.String,
19
+ seq: Schema.Int,
20
+ version: Schema.Int
21
+ })),
22
+ metadata: optional(Schema.Record(Schema.String, Schema.String)),
23
+ data: Schema.Unknown
24
+ });
25
+ var UnknownEventTypeError = class extends Schema.TaggedError()("UnknownEventTypeError", { type: Schema.String }) {};
26
+ /** The transport's own readiness frame; it has no meaning inside the harness. */
27
+ const Connected = EventSchema.define({
28
+ type: "server.connected",
29
+ schema: {}
30
+ });
31
+ /**
32
+ * What a stock client can decode: the harness's public events plus the frames
33
+ * the transport adds itself. A server may know more than this -- plugins
34
+ * register their own types -- which is exactly why `data` crosses the wire
35
+ * encoded and is decoded lazily, so an unknown type is skipped, not fatal.
36
+ */
37
+ const core = EventSchema.latest([...EventList.PublicDefinitions, Connected]);
38
+ const Core = (type) => core.get(type);
39
+ var EncodingError = class extends Schema.TaggedError()("EventEncodingError", {
40
+ type: Schema.String,
41
+ cause: Schema.Defect()
42
+ }) {};
43
+ const encode = Effect.fn("Envelope.encode")(function* (payload, registry = Core) {
44
+ const definition = registry(payload.type);
45
+ if (definition === void 0) return yield* new UnknownEventTypeError({ type: payload.type });
46
+ const data = yield* Schema.encodeEffect(definition.data)(payload.data).pipe(Effect.mapError((cause) => new EncodingError({
47
+ type: payload.type,
48
+ cause
49
+ })));
50
+ return {
51
+ id: payload.id,
52
+ type: payload.type,
53
+ ...payload.durable === void 0 ? {} : { durable: payload.durable },
54
+ ...payload.metadata === void 0 ? {} : { metadata: payload.metadata },
55
+ data
56
+ };
57
+ });
58
+ const decode = Effect.fn("Envelope.decode")(function* (envelope, registry = Core) {
59
+ const definition = registry(envelope.type);
60
+ if (definition === void 0) return yield* new UnknownEventTypeError({ type: envelope.type });
61
+ const data = yield* Schema.decodeEffect(definition.data)(envelope.data);
62
+ return {
63
+ id: envelope.id,
64
+ type: envelope.type,
65
+ ...envelope.durable === void 0 ? {} : { durable: envelope.durable },
66
+ ...envelope.metadata === void 0 ? {} : { metadata: envelope.metadata },
67
+ data
68
+ };
69
+ });
70
+ //#endregion
71
+ //#region src/server/contract.ts
72
+ const SandboxInfo = Schema.Struct({
73
+ id: Sandbox.SandboxInstance.ID,
74
+ driver: Schema.String,
75
+ kind: Sandbox.SandboxInstance.Kind,
76
+ providerResourceId: Schema.OptionFromNullOr(Schema.String),
77
+ ownership: Sandbox.SandboxInstance.Ownership,
78
+ status: Sandbox.SandboxInstance.Status,
79
+ usage: Sandbox.SandboxInstance.Usage,
80
+ refCount: Schema.Int,
81
+ createdAt: Schema.DateFromString,
82
+ updatedAt: Schema.DateFromString
83
+ });
84
+ const SessionInfo = Schema.Struct({
85
+ id: Session.SessionSchema.ID,
86
+ title: Schema.String,
87
+ directory: Session.AbsolutePath,
88
+ /** The host directory this session is anchored to. Absent when it has none. */
89
+ hostDir: optional(Session.AbsolutePath),
90
+ sandbox: optional(SandboxInfo)
91
+ });
92
+ const RuntimeConfig = Schema.Struct({
93
+ model: optional(Schema.Struct({
94
+ provider: Schema.String,
95
+ id: Schema.String
96
+ })),
97
+ thinkingLevel: optional(Schema.Enum(Model.ThinkingLevelEnum))
98
+ });
99
+ const SandboxRef = Sandbox.Selection;
100
+ var OAuthError$1 = class extends Schema.TaggedError()("Server.OAuthError", { message: Schema.String }) {};
101
+ /** OAuth providers whose credentials this server stores. */
102
+ const OAuthProvider = Schema.Literals(["openai-codex", "github-copilot"]);
103
+ /**
104
+ * Credentials as the provider's aikit module persists them. The union is
105
+ * discriminated by `provider` so one set of RPCs serves every login.
106
+ */
107
+ const OAuthCredentials = Schema.Union([Schema.Struct({
108
+ provider: Schema.Literal("openai-codex"),
109
+ access: Schema.String,
110
+ refresh: Schema.String,
111
+ expires: Schema.Finite,
112
+ accountId: Schema.String
113
+ }), Schema.Struct({
114
+ provider: Schema.Literal("github-copilot"),
115
+ access: Schema.String,
116
+ refresh: Schema.String,
117
+ expires: Schema.Finite,
118
+ enterpriseUrl: optional(Schema.String),
119
+ apiEndpoint: optional(Schema.String),
120
+ availableModelIds: optional(Schema.Array(Schema.String))
121
+ })]);
122
+ /** What a login looks like from the outside: never the tokens themselves. */
123
+ const OAuthInfo = Schema.Struct({
124
+ provider: OAuthProvider,
125
+ /** Epoch millis, or 0 for a credential that does not expire. */
126
+ expires: Schema.Finite,
127
+ accountId: optional(Schema.String),
128
+ apiEndpoint: optional(Schema.String),
129
+ enterpriseUrl: optional(Schema.String),
130
+ availableModels: optional(Schema.Int)
131
+ });
132
+ const SessionErrors = Schema.Union([
133
+ SessionStore.SessionNotFoundError,
134
+ SessionStore.SessionLinkedSpaceNotFoundError,
135
+ SessionStore.RelinkError
136
+ ]);
137
+ const SandboxErrors = Schema.Union([
138
+ SandboxError.SandboxNotFoundError,
139
+ SandboxError.SandboxDriverNotRegisteredError,
140
+ SandboxError.SandboxDriverRegistrationError,
141
+ SandboxError.SandboxUnsupportedError,
142
+ SandboxError.SandboxProviderError,
143
+ SandboxError.SandboxUnavailError,
144
+ SandboxError.SandboxRemovedError,
145
+ SandboxError.SandboxTransitionConflictError,
146
+ SandboxError.SandboxBusyError
147
+ ]);
148
+ const LocationErrors = Schema.Union([Location.DirectoryNotFoundError, Location.NotDirectoryError]);
149
+ const Api = RpcGroup.make(
150
+ Rpc.make("auth.save", {
151
+ payload: { credentials: OAuthCredentials },
152
+ success: OAuthInfo,
153
+ error: OAuthError$1
154
+ }),
155
+ Rpc.make("auth.status", {
156
+ payload: { provider: OAuthProvider },
157
+ success: Schema.NullOr(OAuthInfo),
158
+ error: OAuthError$1
159
+ }),
160
+ Rpc.make("auth.refresh", {
161
+ payload: { provider: OAuthProvider },
162
+ success: Schema.NullOr(OAuthInfo),
163
+ error: OAuthError$1
164
+ }),
165
+ Rpc.make("auth.logout", {
166
+ payload: { provider: OAuthProvider },
167
+ success: Schema.Void,
168
+ error: OAuthError$1
169
+ }),
170
+ Rpc.make("session.create", {
171
+ payload: {
172
+ title: optional(Schema.String),
173
+ directory: optional(Schema.String),
174
+ /**
175
+ * The host directory this session is anchored to, usually the caller's project root.
176
+ * Unrelated to `directory`, which names a place inside the session's space.
177
+ *
178
+ * It is an anchor and nothing more: whatever needs a host-side directory resolves from
179
+ * here rather than from wherever the server happens to be running. What reads it is the
180
+ * reader's business, not this field's.
181
+ *
182
+ * Optional and honoured as given. Omitting it is normal, not a failure.
183
+ */
184
+ hostDir: optional(Session.AbsolutePath),
185
+ sandbox: optional(SandboxRef),
186
+ runtime: optional(RuntimeConfig)
187
+ },
188
+ success: SessionInfo,
189
+ error: Schema.Union([
190
+ SessionErrors,
191
+ SandboxErrors,
192
+ LocationErrors
193
+ ])
194
+ }),
195
+ Rpc.make("session.list", {
196
+ payload: {},
197
+ success: Schema.Array(SessionInfo)
198
+ }),
199
+ Rpc.make("session.configure", {
200
+ payload: {
201
+ sessionId: Session.SessionSchema.ID,
202
+ runtime: RuntimeConfig
203
+ },
204
+ success: SessionInfo,
205
+ error: SessionStore.SessionNotFoundError
206
+ }),
207
+ Rpc.make("session.info", {
208
+ payload: { sessionId: Session.SessionSchema.ID },
209
+ success: SessionInfo,
210
+ error: SessionStore.SessionNotFoundError
211
+ }),
212
+ /**
213
+ * Point an existing session at a host directory, or clear it with `null`.
214
+ *
215
+ * Not `session.relink`: that moves where the *work* happens, this changes which host directory
216
+ * the session is *anchored to*. Conflating them would recreate exactly the `cwd`/`hostDir`
217
+ * confusion the split exists to remove, which is why they sound alike and stay apart.
218
+ */
219
+ Rpc.make("session.link", {
220
+ payload: {
221
+ sessionId: Session.SessionSchema.ID,
222
+ /** Absent clears the anchor, leaving the session with no host directory. */
223
+ hostDir: optional(Session.AbsolutePath)
224
+ },
225
+ success: SessionInfo,
226
+ error: SessionStore.SessionNotFoundError
227
+ }),
228
+ Rpc.make("session.relink", {
229
+ payload: {
230
+ sessionId: Session.SessionSchema.ID,
231
+ sandbox: optional(SandboxRef),
232
+ directory: optional(Schema.String)
233
+ },
234
+ success: SessionInfo,
235
+ error: Schema.Union([
236
+ SessionErrors,
237
+ SandboxErrors,
238
+ LocationErrors
239
+ ])
240
+ }),
241
+ Rpc.make("session.prompt", {
242
+ payload: {
243
+ sessionId: Session.SessionSchema.ID,
244
+ text: Schema.String,
245
+ delivery: optional(PromptSchema.Delivery),
246
+ id: optional(Session.SessionMessageSchema.ID)
247
+ },
248
+ success: Schema.Void,
249
+ error: Schema.Union([SessionStore.SessionNotFoundError, Control.PromptConflictError])
250
+ }),
251
+ Rpc.make("session.interrupt", {
252
+ payload: { sessionId: Session.SessionSchema.ID },
253
+ success: Schema.Struct({ interrupted: Schema.Boolean })
254
+ }),
255
+ /**
256
+ * Whether a prompt materialized into the conversation. An admitted prompt
257
+ * that is still queued has no entry yet, so this is the projection a client
258
+ * reconciles against when the volatile stream left it unsure
259
+ */
260
+ Rpc.make("session.message", {
261
+ payload: {
262
+ sessionId: Session.SessionSchema.ID,
263
+ messageId: Session.SessionMessageSchema.ID
264
+ },
265
+ success: Schema.Struct({ found: Schema.Boolean })
266
+ }),
267
+ Rpc.make("session.wait", {
268
+ payload: { sessionId: Session.SessionSchema.ID },
269
+ success: Schema.Void,
270
+ error: SessionStore.SessionNotFoundError
271
+ }),
272
+ /**
273
+ * Re-import every configured plugin, for the whole server.
274
+ *
275
+ * The one thing an exchange cannot notice on its own: a local plugin whose contents changed
276
+ * while its path did not. A failure keeps the previous set and is reported here rather than
277
+ * emptying a running server's tool registry.
278
+ */
279
+ Rpc.make("plugin.reload", {
280
+ payload: {},
281
+ success: Schema.Struct({
282
+ plugins: Schema.Int,
283
+ failure: optional(Schema.String)
284
+ })
285
+ }),
286
+ Rpc.make("sandbox.drivers", {
287
+ payload: {},
288
+ success: Schema.Array(Schema.Struct({
289
+ name: Schema.String,
290
+ kind: Schema.String
291
+ }))
292
+ }),
293
+ Rpc.make("sandbox.list", {
294
+ payload: {},
295
+ success: Schema.Array(SandboxInfo)
296
+ }),
297
+ Rpc.make("sandbox.create", {
298
+ payload: { driver: Schema.String },
299
+ success: SandboxInfo,
300
+ error: SandboxErrors
301
+ }),
302
+ Rpc.make("sandbox.register", {
303
+ payload: {
304
+ driver: Schema.String,
305
+ providerResourceId: Schema.String
306
+ },
307
+ success: SandboxInfo,
308
+ error: SandboxErrors
309
+ }),
310
+ Rpc.make("sandbox.stop", {
311
+ payload: { sandboxId: Sandbox.SandboxInstance.ID },
312
+ success: Schema.Void,
313
+ error: SandboxErrors
314
+ }),
315
+ Rpc.make("event.subscribe", {
316
+ payload: {},
317
+ success: EventEnvelope,
318
+ error: Schema.Union([Event.SubscriptionOverflowError, EncodingError]),
319
+ stream: true
320
+ })
321
+ );
322
+ //#endregion
323
+ //#region src/server/client.ts
324
+ const make = RpcClient.make(Api);
325
+ const layer = (url) => RpcClient.layerProtocolSocket().pipe(Layer.provide(NodeSocket.layerWebSocket(url)), Layer.provide(RpcSerialization.layerNdjson));
326
+ /** A server-side failure as the client sees it: the category, not the cause. */
327
+ var ExecutionError = class extends Schema.TaggedError()("Client.ExecutionError", {
328
+ type: Schema.String,
329
+ message: Schema.String,
330
+ status: optional(Schema.Int)
331
+ }) {};
332
+ /**
333
+ * Runs one prompt against a server and renders its output.
334
+ *
335
+ * Sessions are shared, so the stream carries other clients' work too and every
336
+ * terminal event has to be attributed before it is believed. A terminal that
337
+ * arrives before our own prompt is promoted belongs to somebody else's drain:
338
+ * it is remembered rather than raised, and forgotten the moment our prompt is
339
+ * promoted. It only becomes our outcome if the session reaches idle having
340
+ * never promoted us -- at which point it is the best explanation available for
341
+ * why our prompt never ran.
342
+ */
343
+ const run = Effect.fn("Client.run")(function* (rpc, input, render) {
344
+ const id = Session.SessionMessageSchema.ID.create();
345
+ let admitted = false;
346
+ let promoted = false;
347
+ let settled = false;
348
+ let unattributed;
349
+ const stalled = yield* Deferred.make();
350
+ const terminal = (event) => {
351
+ if (Schema.is(EventList.ExecutionInterrupted)(event)) return new ExecutionError({
352
+ type: "aborted",
353
+ message: event.data.reason === "shutdown" ? "Server stopped the session" : "Session interrupted"
354
+ });
355
+ if (Schema.is(EventList.ExecutionFailed)(event)) return new ExecutionError({
356
+ type: event.data.error.type,
357
+ message: event.data.error.message,
358
+ ...event.data.error.status === void 0 ? {} : { status: event.data.error.status }
359
+ });
360
+ };
361
+ const consume = rpc["event.subscribe"]({}).pipe(Stream.mapEffect(Effect.fnUntraced(function* (envelope) {
362
+ if (envelope.type === Connected.type) {
363
+ yield* rpc["session.prompt"]({
364
+ ...input,
365
+ id,
366
+ delivery: "followUp"
367
+ });
368
+ return;
369
+ }
370
+ const event = yield* decode(envelope).pipe(Effect.catchTag("UnknownEventTypeError", () => Effect.void));
371
+ if (event === void 0 || !Predicate.hasProperty(event.data, "sessionId") || event.data.sessionId !== input.sessionId) return;
372
+ if (Schema.is(EventList.PromptAdmitted)(event) && event.data.messageId === id) admitted = true;
373
+ if (Schema.is(EventList.Prompted)(event) && event.data.messageId === id) {
374
+ promoted = true;
375
+ unattributed = void 0;
376
+ }
377
+ if (!admitted) return;
378
+ const ended = terminal(event);
379
+ const succeeded = Schema.is(EventList.ExecutionSucceeded)(event);
380
+ if (!promoted) {
381
+ if (ended !== void 0) unattributed = ended;
382
+ if (ended !== void 0 || succeeded) yield* Deferred.succeed(stalled, void 0);
383
+ return;
384
+ }
385
+ if (ended !== void 0) return yield* ended;
386
+ if (succeeded) {
387
+ settled = true;
388
+ return;
389
+ }
390
+ yield* render(event);
391
+ })), Stream.takeUntil(() => settled), Stream.runDrain);
392
+ let abandoned = false;
393
+ const reconcile = Deferred.await(stalled).pipe(Effect.andThen(rpc["session.wait"]({ sessionId: input.sessionId })), Effect.andThen(rpc["session.message"]({
394
+ sessionId: input.sessionId,
395
+ messageId: id
396
+ })), Effect.andThen(({ found }) => found ? Effect.never : Effect.sync(() => {
397
+ abandoned = true;
398
+ })));
399
+ yield* Effect.raceFirst(consume, reconcile);
400
+ if (settled) return;
401
+ if (abandoned) return yield* unattributed ?? new ExecutionError({
402
+ type: "unknown",
403
+ message: "Prompt was not promoted"
404
+ });
405
+ return yield* new ExecutionError({
406
+ type: "transport.disconnected",
407
+ message: "Event stream ended before the prompt finished; its output was not rendered"
408
+ });
409
+ });
410
+ //#endregion
411
+ //#region src/cli/output.ts
412
+ const emptyUsage = {
413
+ turns: 0,
414
+ input: 0,
415
+ output: 0,
416
+ reasoning: 0,
417
+ cacheRead: 0,
418
+ cacheWrite: 0,
419
+ totalTokens: 0,
420
+ cost: 0
421
+ };
422
+ const addUsage = (summary, message) => ({
423
+ turns: summary.turns + 1,
424
+ provider: message.provider.id,
425
+ model: message.responseModel ?? message.model,
426
+ input: summary.input + message.usage.input,
427
+ output: summary.output + message.usage.output,
428
+ reasoning: summary.reasoning + (message.usage.reasoning ?? 0),
429
+ cacheRead: summary.cacheRead + message.usage.cacheRead,
430
+ cacheWrite: summary.cacheWrite + message.usage.cacheWrite,
431
+ totalTokens: summary.totalTokens + message.usage.totalTokens,
432
+ cost: summary.cost + message.usage.cost.total
433
+ });
434
+ const number = new Intl.NumberFormat("en-US");
435
+ const row = (label, value) => `${label.padEnd(9)}${value}\n`;
436
+ const formatCost = (cost) => `$${cost.toFixed(cost > 0 && cost < .01 ? 6 : 4)}`;
437
+ const divider = (label, columns = 72) => {
438
+ const width = Math.min(100, Math.max(32, columns));
439
+ const start = `── ${label} `;
440
+ return `${start}${"─".repeat(Math.max(2, width - start.length))}\n`;
441
+ };
442
+ const header = (input) => `${row("session", input.sessionId)}${row("sandbox", `${input.sandbox} · ${input.directory}`)}\n${divider("response", input.columns)}`;
443
+ const usage = (summary, columns) => {
444
+ const turns = `${summary.turns} ${summary.turns === 1 ? "turn" : "turns"}`;
445
+ const model = summary.provider === void 0 || summary.model === void 0 ? "unknown" : `${summary.provider}/${summary.model}`;
446
+ const reasoning = summary.reasoning === 0 ? "" : ` · ${number.format(summary.reasoning)} reasoning`;
447
+ return `${divider("usage", columns)}${row("model", model)}${row("tokens", `${number.format(summary.input)} input · ${number.format(summary.output)} output${reasoning} · ${number.format(summary.totalTokens)} total`)}${row("cache", `${number.format(summary.cacheRead)} read · ${number.format(summary.cacheWrite)} write`)}${row("cost", `${formatCost(summary.cost)} · ${turns}`)}`;
448
+ };
449
+ const writeOut = (value) => Effect.sync(() => void process.stdout.write(value));
450
+ const writeError = (value) => Effect.sync(() => void process.stderr.write(value));
451
+ const terminalColumns = () => process.stderr.isTTY ? process.stderr.columns ?? 72 : 72;
452
+ //#endregion
453
+ //#region src/cli/error.ts
454
+ /** Bad flag or argument combinations the parser cannot express on its own. */
455
+ var InvalidInputError = class extends Schema.TaggedError()("CLI.InvalidInputError", { message: Schema.String }) {};
456
+ var OAuthError = class extends Schema.TaggedError()("CLI.OAuthError", {
457
+ message: Schema.String,
458
+ cause: Schema.optional(Schema.Defect())
459
+ }) {};
460
+ const isInvalidInputError = Schema.is(InvalidInputError);
461
+ const isOAuthError = Schema.is(OAuthError);
462
+ const isProviderError = Schema.is(Runner.ProviderError);
463
+ const isModelCatalogError = Schema.is(Runner.ModelCatalogError);
464
+ const isModelCatalogRefreshError = Schema.is(ModelCatalog.RefreshError);
465
+ const isModelNotFoundError = Schema.is(Runner.ModelNotFoundError);
466
+ const isLLMStreamError = Schema.is(Runner.LLMStreamError);
467
+ const isSandboxProviderError = Schema.is(SandboxProvider.SandboxProviderError);
468
+ const isPluginInstallError = Schema.is(Plugin.InstallError);
469
+ const isPluginSourceError = Schema.is(Plugin.SourceError);
470
+ const isPluginStoreError = Schema.is(Plugin.StoreError);
471
+ const isPluginLoadError = Schema.is(Plugin.LoadError);
472
+ const isSessionNotLinkedError = Schema.is(SessionStore.SessionNotLinkedError);
473
+ const isSettingsError = Schema.is(Settings.SettingsError);
474
+ const isSandboxDriverNotRegisteredError = Schema.is(SandboxError.SandboxDriverNotRegisteredError);
475
+ const isSandboxDriverRegistrationError = Schema.is(SandboxError.SandboxDriverRegistrationError);
476
+ const isExecutionError = Schema.is(ExecutionError);
477
+ const credentialHint = (provider) => {
478
+ switch (provider) {
479
+ case "openrouter": return "set OPENROUTER_API_KEY and retry";
480
+ case "openai": return "set OPENAI_API_KEY and retry";
481
+ case "openai-codex": return "run `codework auth login --openai-codex` and retry";
482
+ case "github-copilot": return "run `codework auth login --github-copilot` and retry";
483
+ case "anthropic": return "set ANTHROPIC_API_KEY and retry";
484
+ case "google": return "set GOOGLE_GENERATIVE_AI_API_KEY and retry";
485
+ case "xai": return "set XAI_API_KEY and retry";
486
+ default: return `configure credentials for provider "${provider}" and retry`;
487
+ }
488
+ };
489
+ const providerHint = (error) => {
490
+ switch (error.reason._tag) {
491
+ case "Runner.ProviderAuthenticationError": return error.reason.authentication === "missing" ? credentialHint(error.provider) : `check the credentials configured for provider "${error.provider}"`;
492
+ case "Runner.ProviderAuthorizationError": return "check that the credential can access this model and endpoint";
493
+ case "Runner.ProviderModelUnavailableError": return "check the provider model ID and whether your account can access it";
494
+ case "Runner.ProviderRateLimitError": return error.reason.retryAfter === void 0 ? "retry after the provider rate-limit window resets" : `retry in about ${Math.ceil(Duration.toMillis(error.reason.retryAfter) / 1e3)} seconds`;
495
+ case "Runner.ProviderQuotaError": return "check the provider account quota or billing balance";
496
+ case "Runner.ProviderTimeoutError":
497
+ case "Runner.ProviderTransportError":
498
+ case "Runner.ProviderUnavailableError": return error.isRetryable ? "this failure is retryable" : void 0;
499
+ default: return;
500
+ }
501
+ };
502
+ const unknownMessage = (error) => {
503
+ if (error instanceof Error && error.message.trim().length > 0) return error.message;
504
+ if (typeof error === "string" && error.trim().length > 0) return error;
505
+ if (typeof error === "object" && error !== null && "_tag" in error) return String(error._tag);
506
+ return "the command failed for an unknown reason";
507
+ };
508
+ /**
509
+ * What the reader can do about a reference that failed to prepare. A plugin list is
510
+ * usually hand-written in a settings file, so the phase is worth translating.
511
+ */
512
+ /** One hint per reason. Lowercase, like everything else a plugin failure prints. */
513
+ const providerCategory = (reason) => {
514
+ switch (reason._tag) {
515
+ case "Runner.ProviderAuthenticationError": return "provider-authentication-error";
516
+ case "Runner.ProviderConfigurationError": return "provider-configuration-error";
517
+ case "Runner.ProviderAuthorizationError": return "provider-authorization-error";
518
+ case "Runner.ProviderModelUnavailableError": return "provider-model-unavailable-error";
519
+ case "Runner.ProviderRateLimitError": return "provider-rate-limit-error";
520
+ case "Runner.ProviderQuotaError": return "provider-quota-error";
521
+ case "Runner.ProviderInvalidRequestError": return "provider-invalid-request-error";
522
+ case "Runner.ProviderContentPolicyError": return "provider-content-filter-error";
523
+ case "Runner.ProviderTimeoutError": return "provider-timeout-error";
524
+ case "Runner.ProviderTransportError": return "provider-transport-error";
525
+ case "Runner.ProviderUnavailableError": return "provider-unavailable-error";
526
+ case "Runner.ProviderInvalidResponseError": return "provider-invalid-response-error";
527
+ case "Runner.ProviderUnknownError": return "provider-unknown-error";
528
+ }
529
+ };
530
+ const pluginReasonHint = (reason) => {
531
+ switch (reason) {
532
+ case "plugin-unsupported-source": return "a path entry starts with `./`, `../`, `~/` or `/`; anything else is a package or a git spec, and a remote tarball is not supported";
533
+ case "plugin-not-found": return "the path does not exist; check the spelling, remembering it anchors to the settings file that declares it";
534
+ case "plugin-escapes-root": return "a plugin path must stay inside the project it is declared in";
535
+ case "plugin-resolve-failed": return "check that the registry or git remote is reachable, and that your credentials are current";
536
+ case "plugin-fetch-failed": return "check the package name and version, and that the registry is reachable";
537
+ case "plugin-no-commit": return "the git source installed but no commit could be recovered; name a branch, tag or commit explicitly";
538
+ case "plugin-no-entrypoint": return "the package installed but exports no module to import; check its `exports` and `main`";
539
+ case "plugin-not-installed": return "run `codework plugin install` to fetch what the settings files name";
540
+ case "plugin-lock-timeout": return "another install is holding this entry; wait for it to finish, or remove the stale `.lock` directory";
541
+ case "plugin-marker-invalid":
542
+ case "plugin-index-invalid": return "the store entry is damaged; remove it and install again";
543
+ case "plugin-collect-failed": return "the store could not be tidied; check the permissions on the plugin cache";
544
+ case "plugin-import-failed": return "the module failed to load; import it directly to see its own error";
545
+ case "plugin-missing-dependency": return "the plugin's own dependencies are missing; install them where the plugin lives";
546
+ case "plugin-not-compiled": return "a plugin installed from git or npm must ship compiled javascript; build it and commit or publish the output";
547
+ case "plugin-invalid-definition": return "a plugin module must default-export one object with a `setup` and a `vendor.domain.name` id";
548
+ }
549
+ };
550
+ const settingsHint = (reason) => {
551
+ switch (reason) {
552
+ case "read": return "the file exists but could not be read; check that it is a file and readable";
553
+ case "parse": return "the file is not valid JSON; the location above is where parsing stopped";
554
+ case "decode": return "the key above holds a value this setting does not accept";
555
+ }
556
+ };
557
+ /** Render typed SDK errors for humans without exposing Effect causes or provider payloads. */
558
+ const renderError = (error) => {
559
+ if (isSandboxDriverNotRegisteredError(error)) return `error: sandbox driver "${error.driver}" is not registered (available: ${error.registered?.join(", ") ?? "none"})\n`;
560
+ if (isSandboxDriverRegistrationError(error)) return `error: ${error.reason}\n`;
561
+ if (isInvalidInputError(error)) return `error: ${error.message}\n`;
562
+ if (isOAuthError(error)) return [`error[oauth-credential-error]: ${error.message}`, ...error.cause === void 0 ? [] : [`detail: ${unknownMessage(error.cause)}`]].join("\n") + "\n";
563
+ if (isSandboxProviderError(error)) return [
564
+ `error: SandboxProviderError - ${error.sanitized.message}`,
565
+ `driver: ${error.driver}`,
566
+ `operation: ${error.operation}`,
567
+ ...error.sanitized.code === void 0 ? [] : [`code: ${error.sanitized.code}`],
568
+ ...error.stack === void 0 ? [] : ["traceback:", error.stack]
569
+ ].join("\n") + "\n";
570
+ if (isSessionNotLinkedError(error)) return [
571
+ `error[${error.reason}]: ${error.message}`,
572
+ `session: ${error.sessionId}`,
573
+ "hint: run `codework session link <session-id>` from the directory to anchor it to"
574
+ ].join("\n") + "\n";
575
+ if (isSettingsError(error)) return [
576
+ `error[settings-${error.reason}-failed]: ${error.path}`,
577
+ `detail: ${error.detail}`,
578
+ `hint: ${settingsHint(error.reason)}`
579
+ ].join("\n") + "\n";
580
+ if (isPluginSourceError(error) || isPluginInstallError(error) || isPluginStoreError(error) || isPluginLoadError(error)) return [
581
+ `error[${error.reason}]: ${error.message}`,
582
+ ...error.reference === "" ? [] : [`reference: ${error.reference}`],
583
+ ...error.file === void 0 ? [] : [`declared in: ${error.file}`],
584
+ ...isPluginLoadError(error) && error.id !== void 0 ? [`id: ${error.id}`] : [],
585
+ `hint: ${pluginReasonHint(error.reason)}`
586
+ ].join("\n") + "\n";
587
+ if (isProviderError(error)) {
588
+ const hint = providerHint(error);
589
+ return [
590
+ `error[${providerCategory(error.reason)}]: ${error.message}`,
591
+ `provider: ${error.provider}`,
592
+ `model: ${error.model}`,
593
+ ...error.reason.requestId === void 0 ? [] : [`request: ${error.reason.requestId}`],
594
+ ...hint === void 0 ? [] : [`hint: ${hint}`]
595
+ ].join("\n") + "\n";
596
+ }
597
+ if (isModelCatalogError(error)) return [`error[model-catalog-${error.reason}]: ${error.message}`, "hint: run `codework models refresh`"].join("\n") + "\n";
598
+ if (isModelCatalogRefreshError(error)) return [`error[catalog-refresh-failed]: ${error.message}`, "hint: check the network connection and retry"].join("\n") + "\n";
599
+ if (isModelNotFoundError(error)) return [`error[model-not-found-error]: ${error.message}`, "hint: check the provider/model IDs in models.gen.json or regenerate the catalog"].join("\n") + "\n";
600
+ if (isLLMStreamError(error)) return `error[llm-stream-error]: ${error.message}\n`;
601
+ if (isExecutionError(error)) return [error.type === "aborted" ? `error: ${error.message}` : `error[${error.type}]: ${error.message}`, ...error.status === void 0 ? [] : [`status: ${error.status}`]].join("\n") + "\n";
602
+ return `error: ${unknownMessage(error)}\n`;
603
+ };
604
+ const reportFailure = (error) => writeError(renderError(error)).pipe(Effect.andThen(Effect.sync(() => {
605
+ process.exitCode = 1;
606
+ })));
607
+ //#endregion
608
+ export { Connected as _, addUsage as a, terminalColumns as c, writeOut as d, layer as f, OAuthError$1 as g, Api as h, reportFailure as i, usage as l, run as m, OAuthError as n, emptyUsage as o, make as p, renderError as r, header as s, InvalidInputError as t, writeError as u, Core as v, encode as y };
609
+
610
+ //# sourceMappingURL=error-CxoEKg-4.mjs.map