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