t3code-cli 0.7.0 → 0.9.0

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 (82) hide show
  1. package/README.md +90 -35
  2. package/dist/application.js +1 -1
  3. package/dist/auth.js +1 -2
  4. package/dist/bin.js +241 -45
  5. package/dist/cli.js +1 -1
  6. package/dist/config.js +1 -3
  7. package/dist/connection.js +1 -4
  8. package/dist/index.js +1 -4
  9. package/dist/layout.js +1 -1
  10. package/dist/orchestration.js +1 -1
  11. package/dist/rpc.js +1 -1
  12. package/dist/runtime.js +1 -2
  13. package/dist/scope.js +1 -1
  14. package/dist/shared.js +85492 -0
  15. package/dist/src/application/layer.d.ts +86 -2
  16. package/dist/src/application/models.d.ts +1 -0
  17. package/dist/src/application/projects.d.ts +10 -1
  18. package/dist/src/application/service.d.ts +30 -1
  19. package/dist/src/application/shell-sequence.d.ts +9 -0
  20. package/dist/src/application/thread-commands.d.ts +27 -1
  21. package/dist/src/application/thread-wait.d.ts +9 -0
  22. package/dist/src/application/threads.d.ts +102 -2
  23. package/dist/src/cli-path/layer.d.ts +3 -0
  24. package/dist/src/cli-path/service.d.ts +8 -0
  25. package/dist/src/domain/helpers.d.ts +9 -0
  26. package/dist/src/domain/model-config.d.ts +3 -0
  27. package/dist/src/domain/thread-activities.d.ts +14 -0
  28. package/dist/src/domain/thread-lifecycle.d.ts +10 -0
  29. package/dist/src/orchestration/layer.d.ts +215 -0
  30. package/dist/src/rpc/layer.d.ts +466 -0
  31. package/dist/src/rpc/ws-group.d.ts +142 -0
  32. package/dist/src/runtime/layer.d.ts +1 -1
  33. package/dist/t3tools.js +2 -2
  34. package/dist/upstream-t3code/packages/contracts/src/environmentHttp.d.ts +33 -10
  35. package/dist/upstream-t3code/packages/contracts/src/ipc.d.ts +6 -0
  36. package/dist/upstream-t3code/packages/contracts/src/orchestration.d.ts +657 -1
  37. package/dist/upstream-t3code/packages/contracts/src/provider.d.ts +14 -0
  38. package/dist/upstream-t3code/packages/contracts/src/providerRuntime.d.ts +175 -1
  39. package/dist/upstream-t3code/packages/contracts/src/rpc.d.ts +492 -0
  40. package/dist/upstream-t3code/packages/contracts/src/server.d.ts +45 -0
  41. package/dist/upstream-t3code/packages/contracts/src/settings.d.ts +21 -0
  42. package/dist/upstream-t3code/packages/contracts/src/terminal.d.ts +6 -3
  43. package/package.json +2 -2
  44. package/src/application/service.ts +32 -0
  45. package/src/application/thread-commands.ts +45 -0
  46. package/src/application/threads.ts +100 -1
  47. package/src/cli/error.ts +15 -0
  48. package/src/cli/message-input.ts +30 -0
  49. package/src/cli/thread-format.ts +47 -0
  50. package/src/cli/thread.ts +8 -0
  51. package/src/cli/threads/approve.ts +61 -0
  52. package/src/cli/threads/archive.ts +18 -3
  53. package/src/cli/threads/callback.ts +92 -0
  54. package/src/cli/threads/respond.ts +70 -0
  55. package/src/cli/threads/show.ts +43 -0
  56. package/src/cli-path/layer.ts +10 -0
  57. package/src/cli-path/service.ts +7 -0
  58. package/src/domain/thread-activities.test.ts +321 -0
  59. package/src/domain/thread-activities.ts +244 -0
  60. package/src/domain/thread-lifecycle.ts +2 -0
  61. package/src/runtime/layer.ts +2 -0
  62. package/dist/Context-DueQ9iMH.js +0 -4916
  63. package/dist/Path-D8WPdPwR.js +0 -11406
  64. package/dist/Schema-DsQxYh6_.js +0 -13581
  65. package/dist/UrlParams-BA6gBvaY.js +0 -205
  66. package/dist/base-dir-R12OMDso.js +0 -20
  67. package/dist/error-B2t1bAP9.js +0 -169
  68. package/dist/error-BHRnjLux.js +0 -15
  69. package/dist/error-jwMt3VoW.js +0 -54
  70. package/dist/flags-CM7_iGdA.js +0 -13371
  71. package/dist/layer-CfC5qZol.js +0 -1508
  72. package/dist/layer-DHhKS5jd.js +0 -13
  73. package/dist/layer-DUv99vsS.js +0 -72
  74. package/dist/layer-DvHnKBYj.js +0 -29466
  75. package/dist/layer-MqCKkIGD.js +0 -1206
  76. package/dist/scope-GycYiJ54.js +0 -29
  77. package/dist/service-CLmRO2Dp.js +0 -8
  78. package/dist/service-ybOWV9pL.js +0 -5
  79. package/dist/src-KdbHqrex.js +0 -8874
  80. package/dist/transport-D3zBdZ1h.js +0 -539
  81. package/dist/url-SlsaG8nY.js +0 -165
  82. /package/dist/{chunk-B5meny8j.js → rolldown-runtime.js} +0 -0
@@ -1,1206 +0,0 @@
1
- import { An as identity, C as isNone, S as getOrUndefined, T as isSome, an as hasProperty, n as Service } from "./Context-DueQ9iMH.js";
2
- import { $ as mapError, Fn as succeed$1, It as try_, Mn as mergeAll, Mt as tapError, Nn as provide$1, P as fn, Tt as succeed, U as gen, Vt as void_, X as map, Yt as exponential, Zt as take, b as catchTags, bt as scope, dt as provideService, j as flatMap, k as fail, kn as effect, kt as sync, lt as provide, mt as retry, qt as collectWhile, st as orDie, t as Path, xt as scoped, zn as addFinalizer } from "./Path-D8WPdPwR.js";
3
- import { $ as optional, $t as tapError$1, At as map$1, Ct as flatMap$1, Et as fromIterableEffect, F as decodeUnknownSync, Ft as peel, Gt as runHead, Kt as runLast, Ln as formatIso, Rn as now, Rt as retry$1, St as filter, T as Union, Tt as fromIterable, Zt as takeUntil, _t as catchTags$1, a as Defect, g as Number, nn as unwrap, qt as scoped$1, sn as head, x as TaggedErrorClass, xt as fail$1, y as String } from "./Schema-DsQxYh6_.js";
4
- import { n as T3AuthTransportLive } from "./transport-D3zBdZ1h.js";
5
- import { a as makeT3CodeConnectionProvider, n as T3Rpc, o as layerWebSocketConstructor, r as T3CodeConnectionProvider, s as layerUndici, t as T3RpcLive } from "./layer-DvHnKBYj.js";
6
- import { S as Crypto, _ as layer, c as T3LocalAuthLive, d as T3LocalAuthTokenLive, g as makeCompilerSqlite, h as defaultTransforms, i as T3AuthPairingLive, m as make, p as SqlClientFactory, t as T3AuthLive, y as T3LocalAuthOriginLive } from "./layer-CfC5qZol.js";
7
- import { $c as ProviderInstanceId, Gu as MessageId, Vu as CommandId, Yu as ProjectId, is as ORCHESTRATION_WS_METHODS, rs as ModelSelection, t as WS_METHODS, td as ThreadId, ws as OrchestrationMessage } from "./src-KdbHqrex.js";
8
- import { n as T3Config, t as Environment } from "./service-CLmRO2Dp.js";
9
- import { t as T3Application } from "./service-ybOWV9pL.js";
10
- import { i as RpcClientError, n as T3CodeConnectionError, t as RpcError } from "./error-B2t1bAP9.js";
11
- import { t as T3ConfigLive } from "./layer-DUv99vsS.js";
12
- import { DatabaseSync } from "node:sqlite";
13
- //#region src/domain/error.ts
14
- var ProjectLookupError = class extends TaggedErrorClass()("ProjectLookupError", {
15
- message: String,
16
- ref: String
17
- }) {};
18
- var ModelSelectionError = class extends TaggedErrorClass()("ModelSelectionError", { message: String }) {};
19
- TaggedErrorClass()("ThreadEventError", { message: String });
20
- var ThreadSessionError = class extends TaggedErrorClass()("ThreadSessionError", {
21
- message: String,
22
- threadId: String
23
- }) {};
24
- var ProjectCreateVisibilityError = class extends TaggedErrorClass()("ProjectCreateVisibilityError", {
25
- message: String,
26
- projectId: String
27
- }) {};
28
- //#endregion
29
- //#region src/domain/thread-lifecycle.ts
30
- function isThreadActive(thread) {
31
- return thread.session?.status === "starting" || thread.session?.status === "running" || thread.latestTurn?.state === "running" || isPendingStart(thread);
32
- }
33
- function threadStatus(thread) {
34
- if (isPendingStart(thread)) return "pending";
35
- return thread.session?.status ?? thread.latestTurn?.state ?? "unknown";
36
- }
37
- function latestAssistantMessage(thread) {
38
- return thread.messages.toReversed().find((message) => message.role === "assistant");
39
- }
40
- function isThreadCompleteEnough(thread) {
41
- if (thread.session?.status === "error" || thread.session?.status === "interrupted") return true;
42
- const lastUserIndex = thread.messages.findLastIndex((message) => message.role === "user");
43
- if (lastUserIndex === -1) return true;
44
- return thread.messages.slice(lastUserIndex + 1).some((message) => message.role === "assistant");
45
- }
46
- function applyThreadEvent(current, event, messages) {
47
- const message = messageFromEvent(event, messages);
48
- if (message !== null) {
49
- messages.set(messageKey(message), message);
50
- return {
51
- ...current,
52
- messages: [...messages.values()]
53
- };
54
- }
55
- if (event.type === "thread.session-set") return {
56
- ...current,
57
- session: event.payload.session
58
- };
59
- return current;
60
- }
61
- function messageFromEvent(event, existingMessages = /* @__PURE__ */ new Map()) {
62
- if (event.type !== "thread.message-sent") return null;
63
- const payload = event.payload;
64
- const id = payload.messageId;
65
- const previous = existingMessages.get(id);
66
- const text = payload.text;
67
- return decodeUnknownSync(OrchestrationMessage)({
68
- id,
69
- role: payload.role,
70
- text: text.length > 0 || previous === void 0 ? text : previous.text,
71
- turnId: payload.turnId,
72
- streaming: payload.streaming,
73
- createdAt: payload.createdAt,
74
- updatedAt: payload.updatedAt
75
- });
76
- }
77
- function messageKey(message) {
78
- return message.id;
79
- }
80
- function isPendingStart(thread) {
81
- if (thread.session !== null || thread.latestTurn !== null || !("messages" in thread)) return false;
82
- return thread.messages.at(-1)?.role === "user";
83
- }
84
- //#endregion
85
- //#region src/domain/model-config.ts
86
- function isSelectableProvider(provider) {
87
- return provider.status === "ready" && provider.models.length > 0;
88
- }
89
- function firstSelectableProvider(providers) {
90
- return providers.find(isSelectableProvider);
91
- }
92
- function firstSelectableModel(provider) {
93
- return provider.models[0];
94
- }
95
- function findSelectableProvider(providers, instanceId) {
96
- return providers.find((provider) => provider.instanceId === instanceId && isSelectableProvider(provider));
97
- }
98
- function filterProvidersForModelListing(input) {
99
- return input.providers.filter((provider) => input.provider === void 0 || provider.instanceId === input.provider).flatMap((provider) => {
100
- if (input.all) return [provider];
101
- if (!isSelectableProvider(provider)) return [];
102
- return [provider];
103
- });
104
- }
105
- //#endregion
106
- //#region src/orchestration/service.ts
107
- var T3Orchestration = class extends Service()("t3cli/T3Orchestration") {};
108
- //#endregion
109
- //#region src/application/models.ts
110
- const makeModelsApplication = fn("makeModelsApplication")(function* () {
111
- const orchestration = yield* T3Orchestration;
112
- return { listModels: fn("T3Application.listModels")(function* (input) {
113
- return filterProvidersForModelListing({
114
- providers: (yield* orchestration.getServerConfig()).providers,
115
- all: input.all === true,
116
- ...input.provider !== void 0 && input.provider.length > 0 ? { provider: input.provider } : {}
117
- });
118
- }) };
119
- });
120
- //#endregion
121
- //#region src/domain/helpers.ts
122
- const resolveProjectScope = fn("resolveProjectScope")(function* (snapshot, input) {
123
- const path = yield* Path;
124
- const byId = findProjectById(snapshot, input.ref);
125
- if (byId !== null) return { project: byId };
126
- if (!path.isAbsolute(input.ref)) return;
127
- return yield* findProjectByPathPriority(snapshot, path.normalize(input.ref));
128
- });
129
- function findProjectById(snapshot, projectId) {
130
- return snapshot.projects.find((project) => project.id === projectId) ?? null;
131
- }
132
- const isDescendantPath = fn("isDescendantPath")(function* (parent, child) {
133
- const path = yield* Path;
134
- if (child === parent) return true;
135
- const relative = path.relative(parent, child);
136
- return relative.length > 0 && !relative.startsWith("..") && !path.isAbsolute(relative);
137
- });
138
- const findProjectByPathPriority = fn("findProjectByPathPriority")(function* (snapshot, absolutePath) {
139
- const path = yield* Path;
140
- const projectsById = new Map(snapshot.projects.map((project) => [project.id, project]));
141
- const workspaceRoots = new Map(snapshot.projects.map((project) => [project.id, path.normalize(project.workspaceRoot)]));
142
- const candidates = [];
143
- for (const thread of snapshot.threads) {
144
- if (thread.worktreePath === null) continue;
145
- const project = projectsById.get(thread.projectId);
146
- if (project === void 0) continue;
147
- const workspaceRoot = workspaceRoots.get(thread.projectId);
148
- if (workspaceRoot === void 0) continue;
149
- const matchPath = path.normalize(thread.worktreePath);
150
- if (!(yield* isDescendantPath(matchPath, absolutePath))) continue;
151
- candidates.push({
152
- project,
153
- matchPath,
154
- workspaceRoot,
155
- source: "worktree"
156
- });
157
- }
158
- for (const project of snapshot.projects) {
159
- const workspaceRoot = workspaceRoots.get(project.id);
160
- if (workspaceRoot === void 0) continue;
161
- if (!(yield* isDescendantPath(workspaceRoot, absolutePath))) continue;
162
- candidates.push({
163
- project,
164
- matchPath: workspaceRoot,
165
- workspaceRoot,
166
- source: "project"
167
- });
168
- }
169
- if (candidates.length === 0) return;
170
- candidates.sort((left, right) => {
171
- if (left.matchPath.length !== right.matchPath.length) return right.matchPath.length - left.matchPath.length;
172
- if (left.source === right.source) return 0;
173
- return left.source === "worktree" ? -1 : 1;
174
- });
175
- const best = candidates[0];
176
- if (absolutePath === best.matchPath) {
177
- if (best.source === "worktree" && best.matchPath !== best.workspaceRoot) return {
178
- project: best.project,
179
- inferredWorktreePath: best.matchPath
180
- };
181
- return { project: best.project };
182
- }
183
- return {
184
- project: best.project,
185
- inferredWorktreePath: absolutePath
186
- };
187
- });
188
- //#endregion
189
- //#region src/application/project-commands.ts
190
- const makeProjectCreateCommand = fn("makeProjectCreateCommand")(function* (input) {
191
- const path = yield* Path;
192
- const crypto = yield* Crypto;
193
- const environment = yield* Environment;
194
- const workspaceRoot = path.resolve(environment.cwd, input.path);
195
- const projectId = ProjectId.make(yield* crypto.randomUUIDv4.pipe(orDie));
196
- const title = input.title?.trim();
197
- const createdAt = formatIso(yield* now);
198
- return {
199
- type: "project.create",
200
- commandId: CommandId.make(`t3cli:project-create:${yield* crypto.randomUUIDv4.pipe(orDie)}`),
201
- projectId,
202
- title: title !== void 0 && title.length > 0 ? title : path.basename(workspaceRoot),
203
- workspaceRoot,
204
- createdAt
205
- };
206
- });
207
- //#endregion
208
- //#region src/application/shell-sequence.ts
209
- function waitForShellSequence(input) {
210
- return gen(function* () {
211
- if (isNone(yield* input.orchestration.watchShellSequence().pipe(filter((snapshotSequence) => snapshotSequence >= input.sequence), runHead, scoped))) return yield* fail(new RpcError({
212
- message: `shell stream ended before sequence ${input.sequence}`,
213
- method: ORCHESTRATION_WS_METHODS.subscribeShell
214
- }));
215
- return yield* input.orchestration.getShellSnapshot();
216
- });
217
- }
218
- //#endregion
219
- //#region src/application/projects.ts
220
- const makeProjectApplication = fn("makeProjectApplication")(function* () {
221
- const orchestration = yield* T3Orchestration;
222
- const crypto = yield* Crypto;
223
- const path = yield* Path;
224
- const environment = yield* Environment;
225
- return {
226
- loadShell: fn("T3ApplicationLive.loadShell")(function* () {
227
- return yield* orchestration.getShellSnapshot();
228
- }),
229
- addProject: fn("T3ApplicationLive.addProject")(function* (projectInput) {
230
- const command = yield* makeProjectCreateCommand(projectInput).pipe(provideService(Path, path), provideService(Crypto, crypto), provideService(Environment, environment));
231
- const dispatch = yield* orchestration.dispatch(command);
232
- const project = findProjectById(yield* waitForShellSequence({
233
- orchestration,
234
- sequence: dispatch.sequence
235
- }), command.projectId);
236
- if (project === null) return yield* fail(new ProjectCreateVisibilityError({
237
- message: `project created but not visible in shell snapshot: ${command.projectId}`,
238
- projectId: command.projectId
239
- }));
240
- return {
241
- dispatch,
242
- project
243
- };
244
- })
245
- };
246
- });
247
- //#endregion
248
- //#region src/application/model-selection.ts
249
- function resolveModelSelection(input) {
250
- return gen(function* () {
251
- if (input.start.provider !== void 0 && input.start.model !== void 0) return withModelOptions(input.start, {
252
- instanceId: ProviderInstanceId.make(input.start.provider),
253
- model: input.start.model
254
- });
255
- if (input.start.provider !== void 0) {
256
- const model = firstSelectableModel(yield* findProvider(input.serverConfig, input.start.provider));
257
- if (model === void 0) return yield* failNoAvailableModel();
258
- return withModelOptions(input.start, {
259
- instanceId: ProviderInstanceId.make(input.start.provider),
260
- model: model.slug
261
- });
262
- }
263
- if (input.start.model !== void 0) {
264
- const provider = yield* firstAvailableModel(input.serverConfig);
265
- return withModelOptions(input.start, {
266
- instanceId: provider.instanceId,
267
- model: input.start.model
268
- });
269
- }
270
- if (input.project.defaultModelSelection !== null) return withModelOptions(input.start, input.project.defaultModelSelection);
271
- const provider = yield* firstAvailableModel(input.serverConfig);
272
- const model = firstSelectableModel(provider);
273
- if (model === void 0) return yield* failNoAvailableModel();
274
- return withModelOptions(input.start, {
275
- instanceId: provider.instanceId,
276
- model: model.slug
277
- });
278
- });
279
- }
280
- function mergeModelOptions(selection, options) {
281
- if (options.length === 0) return selection;
282
- const optionsById = new Map((selection.options ?? []).map((option) => [option.id, option]));
283
- for (const option of options) optionsById.set(option.id, option);
284
- return decodeUnknownSync(ModelSelection)({
285
- ...selection,
286
- options: [...optionsById.values()]
287
- });
288
- }
289
- function withModelOptions(input, selection) {
290
- if (input.options === void 0 || input.options.length === 0) return selection;
291
- return mergeModelOptions(selection, input.options);
292
- }
293
- function firstAvailableModel(serverConfig) {
294
- const providers = serverConfig.providers;
295
- const provider = firstSelectableProvider(providers);
296
- if (provider === void 0) return failNoAvailableModel();
297
- return succeed(provider);
298
- }
299
- function findProvider(serverConfig, instanceId) {
300
- const provider = findSelectableProvider(serverConfig.providers, instanceId);
301
- if (provider === void 0) return failNoAvailableModel();
302
- return succeed(provider);
303
- }
304
- function failNoAvailableModel() {
305
- return fail(new ModelSelectionError({ message: "no available provider model found; pass --provider and --model" }));
306
- }
307
- //#endregion
308
- //#region src/application/thread-commands.ts
309
- const makeThreadStartCommands = fn("makeThreadStartCommands")(function* (input) {
310
- const crypto = yield* Crypto;
311
- const threadId = ThreadId.make(yield* crypto.randomUUIDv4.pipe(orDie));
312
- const createdAt = formatIso(yield* now);
313
- const modelSelection = yield* resolveModelSelection(input);
314
- const inputTitle = input.start.title?.trim();
315
- const messageTitle = input.start.message.trim().split(/\s+/).slice(0, 8).join(" ");
316
- const title = inputTitle !== void 0 && inputTitle.length > 0 ? inputTitle : messageTitle;
317
- return {
318
- createCommand: {
319
- type: "thread.create",
320
- commandId: CommandId.make(`t3cli:thread-create:${yield* crypto.randomUUIDv4.pipe(orDie)}`),
321
- threadId,
322
- projectId: input.project.id,
323
- title: title.length > 0 ? title : "New thread",
324
- modelSelection,
325
- runtimeMode: "full-access",
326
- interactionMode: "default",
327
- branch: null,
328
- worktreePath: input.start.worktreePath ?? null,
329
- createdAt
330
- },
331
- turnCommand: {
332
- type: "thread.turn.start",
333
- commandId: CommandId.make(`t3cli:thread-start:${yield* crypto.randomUUIDv4.pipe(orDie)}`),
334
- threadId,
335
- message: {
336
- messageId: MessageId.make(yield* crypto.randomUUIDv4.pipe(orDie)),
337
- role: "user",
338
- text: input.start.message,
339
- attachments: []
340
- },
341
- modelSelection,
342
- titleSeed: title,
343
- runtimeMode: "full-access",
344
- interactionMode: "default",
345
- createdAt
346
- },
347
- threadId
348
- };
349
- });
350
- const makeThreadTurnContinueCommand = fn("makeThreadTurnContinueCommand")(function* (input) {
351
- const crypto = yield* Crypto;
352
- const createdAt = formatIso(yield* now);
353
- return {
354
- type: "thread.turn.start",
355
- commandId: CommandId.make(`t3cli:thread-start:${yield* crypto.randomUUIDv4.pipe(orDie)}`),
356
- threadId: ThreadId.make(input.threadId),
357
- message: {
358
- messageId: MessageId.make(yield* crypto.randomUUIDv4.pipe(orDie)),
359
- role: "user",
360
- text: input.message,
361
- attachments: []
362
- },
363
- runtimeMode: "full-access",
364
- interactionMode: "default",
365
- ...input.modelSelection !== void 0 ? { modelSelection: input.modelSelection } : {},
366
- createdAt
367
- };
368
- });
369
- const makeThreadArchiveCommand = fn("makeThreadArchiveCommand")(function* (threadId) {
370
- const crypto = yield* Crypto;
371
- return {
372
- type: "thread.archive",
373
- commandId: CommandId.make(`t3cli:thread-archive:${yield* crypto.randomUUIDv4.pipe(orDie)}`),
374
- threadId: ThreadId.make(threadId)
375
- };
376
- });
377
- //#endregion
378
- //#region src/application/thread-wait.ts
379
- function watchThread(input) {
380
- let current;
381
- let currentMessages;
382
- return scoped$1(input.orchestration.watchThreadItems(input.threadId).pipe(flatMap$1((item) => {
383
- if (item.kind === "snapshot") {
384
- const messages = /* @__PURE__ */ new Map();
385
- for (const message of item.snapshot.thread.messages) messages.set(messageKey(message), message);
386
- current = item.snapshot.thread;
387
- currentMessages = messages;
388
- const events = [{
389
- type: "thread",
390
- thread: current
391
- }, {
392
- type: "status",
393
- status: threadStatus(current),
394
- threadId: current.id
395
- }];
396
- if (!isThreadActive(current) && isThreadCompleteEnough(current)) events.push({
397
- type: "done",
398
- thread: current
399
- });
400
- return fromIterable(events);
401
- }
402
- if (current === void 0 || currentMessages === void 0) return fail$1(new ThreadSessionError({
403
- message: `thread stream event received before snapshot: ${input.threadId}`,
404
- threadId: input.threadId
405
- }));
406
- current = applyThreadEvent(current, item.event, currentMessages);
407
- const message = messageFromEvent(item.event, currentMessages);
408
- const events = message !== null ? [{
409
- type: "message",
410
- message
411
- }] : [];
412
- events.push({
413
- type: "status",
414
- status: threadStatus(current),
415
- threadId: current.id
416
- });
417
- if (!isThreadActive(current) && isThreadCompleteEnough(current)) events.push({
418
- type: "done",
419
- thread: current
420
- });
421
- return fromIterable(events);
422
- }), takeUntil((event) => event.type === "done")));
423
- }
424
- function waitForThread(input) {
425
- return watchThread(input).pipe(runLast, flatMap((event) => {
426
- if (isSome(event) && event.value.type === "done") return succeed(event.value.thread);
427
- return fail(new ThreadSessionError({
428
- message: `thread wait ended without done event: ${input.threadId}`,
429
- threadId: input.threadId
430
- }));
431
- }));
432
- }
433
- //#endregion
434
- //#region src/application/threads.ts
435
- const makeThreadApplication = fn("makeThreadApplication")(function* () {
436
- const orchestration = yield* T3Orchestration;
437
- const crypto = yield* Crypto;
438
- const path = yield* Path;
439
- const environment = yield* Environment;
440
- const listThreads = fn("T3ApplicationLive.listThreads")(function* (projectRef) {
441
- const snapshot = yield* orchestration.getShellSnapshot();
442
- const scope = yield* resolveProjectScope(snapshot, { ref: projectRef }).pipe(provideService(Path, path));
443
- if (scope === void 0) return yield* fail(new ProjectLookupError({
444
- message: `project not found: ${projectRef}`,
445
- ref: projectRef
446
- }));
447
- return {
448
- project: scope.project,
449
- threads: snapshot.threads.filter((thread) => thread.projectId === scope.project.id)
450
- };
451
- });
452
- const getThreadMessages = fn("T3ApplicationLive.getThreadMessages")(function* (threadId) {
453
- return yield* orchestration.getThreadSnapshot(threadId);
454
- });
455
- const archiveThread = fn("T3ApplicationLive.archiveThread")(function* (threadId) {
456
- const command = yield* makeThreadArchiveCommand(threadId).pipe(provideService(Crypto, crypto));
457
- return yield* orchestration.dispatch(command);
458
- });
459
- const startThread = fn("T3ApplicationLive.startThread")(function* (startInput, policy) {
460
- const snapshot = yield* orchestration.getShellSnapshot();
461
- const projectRef = startInput.projectRef;
462
- if (projectRef === void 0) return yield* fail(new ProjectLookupError({
463
- message: "project is required",
464
- ref: environment.cwd
465
- }));
466
- const scope = yield* resolveProjectScope(snapshot, { ref: projectRef }).pipe(provideService(Path, path));
467
- if (scope === void 0) return yield* fail(new ProjectLookupError({
468
- message: `project not found: ${projectRef}`,
469
- ref: projectRef
470
- }));
471
- const worktreePath = startInput.worktreePath ?? scope.inferredWorktreePath;
472
- const serverConfig = yield* orchestration.getServerConfig();
473
- const commands = yield* makeThreadStartCommands({
474
- start: {
475
- ...startInput,
476
- ...worktreePath !== void 0 ? { worktreePath } : {}
477
- },
478
- project: scope.project,
479
- serverConfig
480
- }).pipe(provideService(Crypto, crypto));
481
- yield* waitForShellSequence({
482
- orchestration,
483
- sequence: (yield* orchestration.dispatch(commands.createCommand)).sequence
484
- });
485
- const dispatch = yield* orchestration.dispatch(commands.turnCommand);
486
- const threadId = commands.threadId;
487
- const until = policy?.until ?? "dispatch";
488
- if (until === "dispatch") return {
489
- dispatch,
490
- project: scope.project,
491
- threadId
492
- };
493
- yield* waitForShellSequence({
494
- orchestration,
495
- sequence: dispatch.sequence
496
- });
497
- if (until === "visible") {
498
- const thread = yield* scoped(gen(function* () {
499
- return (yield* orchestration.openThread(threadId)).snapshot;
500
- }));
501
- return {
502
- dispatch,
503
- project: scope.project,
504
- threadId,
505
- thread
506
- };
507
- }
508
- const thread = yield* waitForThread({
509
- orchestration,
510
- threadId
511
- });
512
- yield* failIfThreadError(thread);
513
- return {
514
- dispatch,
515
- project: scope.project,
516
- threadId,
517
- thread
518
- };
519
- });
520
- const sendThread = fn("T3ApplicationLive.sendThread")(function* (input, policy) {
521
- const modelSelection = input.options !== void 0 && input.options.length > 0 ? mergeModelOptions((yield* orchestration.getThreadSnapshot(input.threadId)).modelSelection, input.options) : void 0;
522
- const command = yield* makeThreadTurnContinueCommand({
523
- ...input,
524
- ...modelSelection !== void 0 ? { modelSelection } : {}
525
- }).pipe(provideService(Crypto, crypto));
526
- const dispatch = yield* orchestration.dispatch(command);
527
- const until = policy?.until ?? "dispatch";
528
- if (until === "dispatch") return {
529
- dispatch,
530
- threadId: input.threadId
531
- };
532
- yield* waitForShellSequence({
533
- orchestration,
534
- sequence: dispatch.sequence
535
- });
536
- if (until === "visible") {
537
- const thread = yield* scoped(gen(function* () {
538
- return (yield* orchestration.openThread(input.threadId)).snapshot;
539
- }));
540
- return {
541
- dispatch,
542
- threadId: input.threadId,
543
- thread
544
- };
545
- }
546
- const thread = yield* waitForThread({
547
- orchestration,
548
- threadId: input.threadId
549
- });
550
- yield* failIfThreadError(thread);
551
- return {
552
- dispatch,
553
- threadId: input.threadId,
554
- thread
555
- };
556
- });
557
- const watchThread$1 = (threadId) => watchThread({
558
- orchestration,
559
- threadId
560
- });
561
- return {
562
- archiveThread,
563
- listThreads,
564
- getThreadMessages,
565
- sendThread,
566
- startThread,
567
- watchThread: watchThread$1,
568
- waitForThread: fn("T3ApplicationLive.waitForThread")(function* (threadId) {
569
- const thread = yield* waitForThread({
570
- orchestration,
571
- threadId
572
- });
573
- yield* failIfThreadError(thread);
574
- return thread;
575
- })
576
- };
577
- });
578
- function failIfThreadError(thread) {
579
- if (thread.session?.status !== "error") return void_;
580
- return fail(new ThreadSessionError({
581
- threadId: thread.id,
582
- message: thread.session.lastError ?? "thread ended with error"
583
- }));
584
- }
585
- const T3ApplicationLive = effect(T3Application, fn("makeT3Application")(function* () {
586
- const models = yield* makeModelsApplication();
587
- const projects = yield* makeProjectApplication();
588
- const threads = yield* makeThreadApplication();
589
- return {
590
- ...models,
591
- ...projects,
592
- ...threads
593
- };
594
- })());
595
- //#endregion
596
- //#region src/orchestration/layer.ts
597
- const rpcRetrySchedule = exponential("100 millis").pipe(take(4), collectWhile((metadata) => metadata.input instanceof RpcClientError));
598
- function runRpc(rpc, method, f) {
599
- return gen(function* () {
600
- return yield* f(yield* rpc.getClient);
601
- }).pipe(tapError((error) => error instanceof RpcClientError ? rpc.disconnect : void_), retry(rpcRetrySchedule), catchTags({
602
- RpcError: (error) => fail(error),
603
- EnvironmentAuthorizationError: (error) => fail(toRpcRequestError(error, method)),
604
- RpcClientError: (error) => fail(toRpcRequestError(error, method)),
605
- KeybindingsConfigParseError: (error) => fail(toRpcRequestError(error, method)),
606
- OrchestrationDispatchCommandError: (error) => fail(toRpcRequestError(error, method)),
607
- OrchestrationGetSnapshotError: (error) => fail(toRpcRequestError(error, method)),
608
- ServerSettingsError: (error) => fail(toRpcRequestError(error, method))
609
- }));
610
- }
611
- function subscribeRpc(rpc, method, f) {
612
- return unwrap(map(rpc.getClient, f)).pipe(tapError$1((error) => error instanceof RpcClientError ? rpc.disconnect : void_), retry$1(rpcRetrySchedule), catchTags$1({
613
- RpcError: (error) => fail$1(error),
614
- EnvironmentAuthorizationError: (error) => fail$1(toRpcRequestError(error, method)),
615
- RpcClientError: (error) => fail$1(toRpcRequestError(error, method)),
616
- KeybindingsConfigParseError: (error) => fail$1(toRpcRequestError(error, method)),
617
- OrchestrationDispatchCommandError: (error) => fail$1(toRpcRequestError(error, method)),
618
- OrchestrationGetSnapshotError: (error) => fail$1(toRpcRequestError(error, method)),
619
- ServerSettingsError: (error) => fail$1(toRpcRequestError(error, method))
620
- }));
621
- }
622
- const T3OrchestrationLive = effect(T3Orchestration, fn("makeT3Orchestration")(function* () {
623
- const rpc = yield* T3Rpc;
624
- const dispatch = fn("T3OrchestrationLive.dispatch")(function* (command) {
625
- return yield* runRpc(rpc, ORCHESTRATION_WS_METHODS.dispatchCommand, (client) => client[ORCHESTRATION_WS_METHODS.dispatchCommand](command));
626
- });
627
- const getServerConfig = fn("T3OrchestrationLive.getServerConfig")(function* () {
628
- return yield* runRpc(rpc, WS_METHODS.serverGetConfig, (client) => client[WS_METHODS.serverGetConfig]({}));
629
- });
630
- const getShellSnapshot = fn("T3OrchestrationLive.getShellSnapshot")(function* () {
631
- const value = getOrUndefined(yield* runHead(subscribeRpc(rpc, ORCHESTRATION_WS_METHODS.subscribeShell, (client) => client[ORCHESTRATION_WS_METHODS.subscribeShell]({}))));
632
- if (value === void 0 || value.kind !== "snapshot") return yield* fail(new RpcError({
633
- message: "server did not return shell snapshot",
634
- method: ORCHESTRATION_WS_METHODS.subscribeShell
635
- }));
636
- return value.snapshot;
637
- });
638
- const getThreadSnapshot = fn("T3OrchestrationLive.getThreadSnapshot")(function* (threadId) {
639
- const value = getOrUndefined(yield* runHead(subscribeRpc(rpc, ORCHESTRATION_WS_METHODS.subscribeThread, (client) => client[ORCHESTRATION_WS_METHODS.subscribeThread]({ threadId: ThreadId.make(threadId) }))));
640
- if (value === void 0 || value.kind !== "snapshot") return yield* fail(new RpcError({
641
- message: `thread ${threadId} not found`,
642
- method: ORCHESTRATION_WS_METHODS.subscribeThread
643
- }));
644
- return value.snapshot.thread;
645
- });
646
- const watchShellSequence = () => subscribeRpc(rpc, ORCHESTRATION_WS_METHODS.subscribeShell, (client) => client[ORCHESTRATION_WS_METHODS.subscribeShell]({})).pipe(map$1((item) => item.kind === "snapshot" ? item.snapshot.snapshotSequence : item.sequence));
647
- const watchThreadItems = (threadId) => subscribeRpc(rpc, ORCHESTRATION_WS_METHODS.subscribeThread, (client) => client[ORCHESTRATION_WS_METHODS.subscribeThread]({ threadId: ThreadId.make(threadId) }));
648
- return {
649
- dispatch,
650
- getServerConfig,
651
- getShellSnapshot,
652
- getThreadSnapshot,
653
- watchShellSequence,
654
- watchThreadItems,
655
- openThread: fn("T3OrchestrationLive.openThread")(function* (threadId) {
656
- return yield* watchThreadItems(threadId).pipe(peel(head()), flatMap(([item, rest]) => {
657
- const value = getOrUndefined(item);
658
- if (value === void 0 || value.kind !== "snapshot") return fail(new RpcError({
659
- message: `thread ${threadId} not found`,
660
- method: ORCHESTRATION_WS_METHODS.subscribeThread
661
- }));
662
- return succeed({
663
- snapshot: value.snapshot.thread,
664
- events: rest.pipe(filter((next) => next.kind === "event"), map$1((next) => next.event))
665
- });
666
- }));
667
- })
668
- };
669
- })());
670
- function toRpcRequestError(error, method) {
671
- return new RpcError({
672
- message: error.message,
673
- method,
674
- cause: error
675
- });
676
- }
677
- //#endregion
678
- //#region node_modules/.pnpm/effect@4.0.0-beta.78/node_modules/effect/dist/unstable/sql/SqlError.js
679
- /**
680
- * Structured SQL failures for unstable SQL clients and driver integrations.
681
- *
682
- * This module provides the top-level `SqlError` wrapper, the concrete
683
- * `SqlErrorReason` variants used by adapters, schemas for encoding or decoding
684
- * those errors, guards for recognizing them, and a SQLite classifier for native
685
- * driver causes. The model keeps query mistakes, authentication and
686
- * authorization failures, constraint violations, connection failures, lock
687
- * waits, deadlocks, serialization conflicts, statement timeouts, and unknown
688
- * failures distinguishable in the Effect error channel.
689
- *
690
- * **Mental model**
691
- *
692
- * `SqlError` wraps exactly one reason. Its `message`, `cause`, and
693
- * `isRetryable` values are delegated to that reason, so recovery code can branch
694
- * on either the reason tag or the retryability flag without losing the original
695
- * native cause. Reasons are intentionally driver-neutral; adapters translate
696
- * database-specific error codes into this shared vocabulary.
697
- *
698
- * **Common tasks**
699
- *
700
- * Construct a reason when adapting a driver failure, wrap it in `SqlError` for
701
- * client APIs, use `isSqlError` or `isSqlErrorReason` at boundaries that receive
702
- * unknown failures, and use `classifySqliteError` when mapping SQLite `code` or
703
- * `errno` values.
704
- *
705
- * **Gotchas**
706
- *
707
- * Preserve the native `cause` and `operation` metadata when constructing these
708
- * errors; they are often the only way to diagnose dialect-specific failures.
709
- * Retryable reasons represent transient infrastructure or concurrency problems,
710
- * while syntax, credential, permission, and constraint failures generally need a
711
- * changed query, configuration, or data set. SQLite unique violations include a
712
- * best-effort constraint name when one can be extracted.
713
- *
714
- * @since 4.0.0
715
- */
716
- const TypeId = "~effect/sql/SqlError";
717
- const ReasonTypeId = "~effect/sql/SqlError/Reason";
718
- const ReasonFields = {
719
- cause: /*#__PURE__*/ Defect(),
720
- message: /*#__PURE__*/ optional(String),
721
- operation: /*#__PURE__*/ optional(String)
722
- };
723
- /**
724
- * SQL error reason for connection or open failures; marked retryable.
725
- *
726
- * @category errors
727
- * @since 4.0.0
728
- */
729
- var ConnectionError = class extends TaggedErrorClass("effect/sql/SqlError/ConnectionError")("ConnectionError", ReasonFields) {
730
- /**
731
- * Marks this value as a structured SQL error reason for runtime guards.
732
- *
733
- * @since 4.0.0
734
- */
735
- [ReasonTypeId] = ReasonTypeId;
736
- /**
737
- * Indicates whether retrying the failed SQL operation may succeed.
738
- *
739
- * @since 4.0.0
740
- */
741
- get isRetryable() {
742
- return true;
743
- }
744
- };
745
- /**
746
- * SQL error reason for authentication failures such as invalid credentials; not
747
- * marked retryable.
748
- *
749
- * @category errors
750
- * @since 4.0.0
751
- */
752
- var AuthenticationError = class extends TaggedErrorClass("effect/sql/SqlError/AuthenticationError")("AuthenticationError", ReasonFields) {
753
- /**
754
- * Marks this value as a structured SQL error reason for runtime guards.
755
- *
756
- * @since 4.0.0
757
- */
758
- [ReasonTypeId] = ReasonTypeId;
759
- /**
760
- * Indicates whether retrying the failed SQL operation may succeed.
761
- *
762
- * @since 4.0.0
763
- */
764
- get isRetryable() {
765
- return false;
766
- }
767
- };
768
- /**
769
- * SQL error reason for authorization or permission failures; not marked
770
- * retryable.
771
- *
772
- * @category errors
773
- * @since 4.0.0
774
- */
775
- var AuthorizationError = class extends TaggedErrorClass("effect/sql/SqlError/AuthorizationError")("AuthorizationError", ReasonFields) {
776
- /**
777
- * Marks this value as a structured SQL error reason for runtime guards.
778
- *
779
- * @since 4.0.0
780
- */
781
- [ReasonTypeId] = ReasonTypeId;
782
- /**
783
- * Indicates whether retrying the failed SQL operation may succeed.
784
- *
785
- * @since 4.0.0
786
- */
787
- get isRetryable() {
788
- return false;
789
- }
790
- };
791
- /**
792
- * SQL error reason for invalid SQL syntax; not marked retryable.
793
- *
794
- * @category errors
795
- * @since 4.0.0
796
- */
797
- var SqlSyntaxError = class extends TaggedErrorClass("effect/sql/SqlError/SqlSyntaxError")("SqlSyntaxError", ReasonFields) {
798
- /**
799
- * Marks this value as a structured SQL error reason for runtime guards.
800
- *
801
- * @since 4.0.0
802
- */
803
- [ReasonTypeId] = ReasonTypeId;
804
- /**
805
- * Indicates whether retrying the failed SQL operation may succeed.
806
- *
807
- * @since 4.0.0
808
- */
809
- get isRetryable() {
810
- return false;
811
- }
812
- };
813
- const UniqueViolationFields = {
814
- ...ReasonFields,
815
- constraint: String
816
- };
817
- /**
818
- * SQL error reason for a unique constraint violation, including the violated
819
- * constraint identifier; not marked retryable.
820
- *
821
- * @category errors
822
- * @since 4.0.0
823
- */
824
- var UniqueViolation = class extends TaggedErrorClass("effect/sql/SqlError/UniqueViolation")("UniqueViolation", UniqueViolationFields) {
825
- /**
826
- * Marks this value as a structured SQL error reason for runtime guards.
827
- *
828
- * @since 4.0.0
829
- */
830
- [ReasonTypeId] = ReasonTypeId;
831
- /**
832
- * Indicates whether retrying the failed SQL operation may succeed.
833
- *
834
- * @since 4.0.0
835
- */
836
- get isRetryable() {
837
- return false;
838
- }
839
- };
840
- /**
841
- * SQL error reason for a non-unique constraint violation; not marked retryable.
842
- *
843
- * @category errors
844
- * @since 4.0.0
845
- */
846
- var ConstraintError = class extends TaggedErrorClass("effect/sql/SqlError/ConstraintError")("ConstraintError", ReasonFields) {
847
- /**
848
- * Marks this value as a structured SQL error reason for runtime guards.
849
- *
850
- * @since 4.0.0
851
- */
852
- [ReasonTypeId] = ReasonTypeId;
853
- /**
854
- * Indicates whether retrying the failed SQL operation may succeed.
855
- *
856
- * @since 4.0.0
857
- */
858
- get isRetryable() {
859
- return false;
860
- }
861
- };
862
- /**
863
- * SQL error reason for a database deadlock; marked retryable.
864
- *
865
- * @category errors
866
- * @since 4.0.0
867
- */
868
- var DeadlockError = class extends TaggedErrorClass("effect/sql/SqlError/DeadlockError")("DeadlockError", ReasonFields) {
869
- /**
870
- * Marks this value as a structured SQL error reason for runtime guards.
871
- *
872
- * @since 4.0.0
873
- */
874
- [ReasonTypeId] = ReasonTypeId;
875
- /**
876
- * Indicates whether retrying the failed SQL operation may succeed.
877
- *
878
- * @since 4.0.0
879
- */
880
- get isRetryable() {
881
- return true;
882
- }
883
- };
884
- /**
885
- * SQL error reason for a transaction serialization or isolation conflict;
886
- * marked retryable.
887
- *
888
- * @category errors
889
- * @since 4.0.0
890
- */
891
- var SerializationError = class extends TaggedErrorClass("effect/sql/SqlError/SerializationError")("SerializationError", ReasonFields) {
892
- /**
893
- * Marks this value as a structured SQL error reason for runtime guards.
894
- *
895
- * @since 4.0.0
896
- */
897
- [ReasonTypeId] = ReasonTypeId;
898
- /**
899
- * Indicates whether retrying the failed SQL operation may succeed.
900
- *
901
- * @since 4.0.0
902
- */
903
- get isRetryable() {
904
- return true;
905
- }
906
- };
907
- /**
908
- * SQL error reason for timing out while waiting on a database lock; marked
909
- * retryable.
910
- *
911
- * @category errors
912
- * @since 4.0.0
913
- */
914
- var LockTimeoutError = class extends TaggedErrorClass("effect/sql/SqlError/LockTimeoutError")("LockTimeoutError", ReasonFields) {
915
- /**
916
- * Marks this value as a structured SQL error reason for runtime guards.
917
- *
918
- * @since 4.0.0
919
- */
920
- [ReasonTypeId] = ReasonTypeId;
921
- /**
922
- * Indicates whether retrying the failed SQL operation may succeed.
923
- *
924
- * @since 4.0.0
925
- */
926
- get isRetryable() {
927
- return true;
928
- }
929
- };
930
- /**
931
- * SQL error reason for a statement or query timeout; marked retryable.
932
- *
933
- * @category errors
934
- * @since 4.0.0
935
- */
936
- var StatementTimeoutError = class extends TaggedErrorClass("effect/sql/SqlError/StatementTimeoutError")("StatementTimeoutError", ReasonFields) {
937
- /**
938
- * Marks this value as a structured SQL error reason for runtime guards.
939
- *
940
- * @since 4.0.0
941
- */
942
- [ReasonTypeId] = ReasonTypeId;
943
- /**
944
- * Indicates whether retrying the failed SQL operation may succeed.
945
- *
946
- * @since 4.0.0
947
- */
948
- get isRetryable() {
949
- return true;
950
- }
951
- };
952
- /**
953
- * SQL error reason for an unclassified database failure; not marked retryable.
954
- *
955
- * @category errors
956
- * @since 4.0.0
957
- */
958
- var UnknownError = class extends TaggedErrorClass("effect/sql/SqlError/UnknownError")("UnknownError", ReasonFields) {
959
- /**
960
- * Marks this value as a structured SQL error reason for runtime guards.
961
- *
962
- * @since 4.0.0
963
- */
964
- [ReasonTypeId] = ReasonTypeId;
965
- /**
966
- * Indicates whether retrying the failed SQL operation may succeed.
967
- *
968
- * @since 4.0.0
969
- */
970
- get isRetryable() {
971
- return false;
972
- }
973
- };
974
- /**
975
- * Schema for encoding and decoding SQL error reasons.
976
- *
977
- * @category schemas
978
- * @since 4.0.0
979
- */
980
- const SqlErrorReason = /*#__PURE__*/ Union([
981
- ConnectionError,
982
- AuthenticationError,
983
- AuthorizationError,
984
- SqlSyntaxError,
985
- UniqueViolation,
986
- ConstraintError,
987
- DeadlockError,
988
- SerializationError,
989
- LockTimeoutError,
990
- StatementTimeoutError,
991
- UnknownError
992
- ]);
993
- /**
994
- * Error wrapper for SQL failures whose `message`, `cause`, and `isRetryable`
995
- * values are derived from its `SqlErrorReason`.
996
- *
997
- * @category errors
998
- * @since 4.0.0
999
- */
1000
- var SqlError = class extends TaggedErrorClass("effect/sql/SqlError")("SqlError", { reason: SqlErrorReason }) {
1001
- /**
1002
- * Marks this value as the top-level SQL error wrapper for runtime guards.
1003
- *
1004
- * @since 4.0.0
1005
- */
1006
- [TypeId] = TypeId;
1007
- /**
1008
- * Exposes the structured SQL reason as the JavaScript error cause.
1009
- *
1010
- * @since 4.0.0
1011
- */
1012
- cause = this.reason;
1013
- /**
1014
- * Uses the reason message when present, otherwise falls back to the reason tag.
1015
- *
1016
- * @since 4.0.0
1017
- */
1018
- get message() {
1019
- return this.reason.message || this.reason._tag;
1020
- }
1021
- /**
1022
- * Delegates retryability to the underlying SQL error reason.
1023
- *
1024
- * @since 4.0.0
1025
- */
1026
- get isRetryable() {
1027
- return this.reason.isRetryable;
1028
- }
1029
- };
1030
- const sqliteCodeFromCause = (cause) => {
1031
- if (!hasProperty(cause, "code")) return;
1032
- const code = cause.code;
1033
- return typeof code === "string" || typeof code === "number" ? code : void 0;
1034
- };
1035
- const sqliteNumericCodeFromCause = (cause) => {
1036
- const code = sqliteCodeFromCause(cause);
1037
- if (typeof code === "number") return code;
1038
- if (!hasProperty(cause, "errno")) return;
1039
- const errno = cause.errno;
1040
- return typeof errno === "number" ? errno : void 0;
1041
- };
1042
- const matchesSqliteNumericCode = (cause, expected) => {
1043
- if (sqliteCodeFromCause(cause) === expected) return true;
1044
- if (!hasProperty(cause, "errno")) return false;
1045
- return cause.errno === expected;
1046
- };
1047
- const matchesSqliteCode = (code, expected) => code === expected || code.startsWith(expected + "_");
1048
- const UNKNOWN_CONSTRAINT = "unknown";
1049
- const SQLITE_CONSTRAINT_UNIQUE = "SQLITE_CONSTRAINT_UNIQUE";
1050
- const SQLITE_CONSTRAINT_UNIQUE_CODE = 2067;
1051
- const normalizeConstraintIdentifier = (identifier) => {
1052
- if (typeof identifier !== "string") return UNKNOWN_CONSTRAINT;
1053
- const trimmed = identifier.trim();
1054
- return trimmed.length === 0 ? UNKNOWN_CONSTRAINT : trimmed;
1055
- };
1056
- const sqliteUniqueConstraintFromCause = (cause) => {
1057
- if (hasProperty(cause, "constraint")) return normalizeConstraintIdentifier(cause.constraint);
1058
- if (!hasProperty(cause, "message")) return UNKNOWN_CONSTRAINT;
1059
- const message = cause.message;
1060
- if (typeof message !== "string") return UNKNOWN_CONSTRAINT;
1061
- const index = message.indexOf("UNIQUE constraint failed:");
1062
- return index === -1 ? UNKNOWN_CONSTRAINT : normalizeConstraintIdentifier(message.slice(index + 25));
1063
- };
1064
- /**
1065
- * Classifies a native SQLite error cause into a `SqlErrorReason` using its
1066
- * `code` or `errno`, with optional message and operation metadata.
1067
- *
1068
- * @category converting
1069
- * @since 4.0.0
1070
- */
1071
- const classifySqliteError = (cause, { message, operation } = {}) => {
1072
- const props = {
1073
- cause,
1074
- message,
1075
- operation
1076
- };
1077
- const code = sqliteCodeFromCause(cause);
1078
- const numericCode = sqliteNumericCodeFromCause(cause);
1079
- if (code === SQLITE_CONSTRAINT_UNIQUE || matchesSqliteNumericCode(cause, SQLITE_CONSTRAINT_UNIQUE_CODE)) return new UniqueViolation({
1080
- ...props,
1081
- constraint: sqliteUniqueConstraintFromCause(cause)
1082
- });
1083
- if (typeof code === "string") {
1084
- if (matchesSqliteCode(code, "SQLITE_AUTH")) return new AuthenticationError(props);
1085
- if (matchesSqliteCode(code, "SQLITE_PERM")) return new AuthorizationError(props);
1086
- if (matchesSqliteCode(code, "SQLITE_CONSTRAINT")) return new ConstraintError(props);
1087
- if (matchesSqliteCode(code, "SQLITE_BUSY") || matchesSqliteCode(code, "SQLITE_LOCKED")) return new LockTimeoutError(props);
1088
- if (matchesSqliteCode(code, "SQLITE_CANTOPEN")) return new ConnectionError(props);
1089
- }
1090
- if (typeof numericCode === "number") switch (numericCode & 255) {
1091
- case 23: return new AuthenticationError(props);
1092
- case 3: return new AuthorizationError(props);
1093
- case 19: return new ConstraintError(props);
1094
- case 5:
1095
- case 6: return new LockTimeoutError(props);
1096
- case 14: return new ConnectionError(props);
1097
- default: return new UnknownError(props);
1098
- }
1099
- return new UnknownError(props);
1100
- };
1101
- TaggedErrorClass("effect/sql/ResultLengthMismatch")("ResultLengthMismatch", {
1102
- expected: Number,
1103
- actual: Number
1104
- });
1105
- //#endregion
1106
- //#region src/sql/node-sqlite-client.ts
1107
- const ATTR_DB_SYSTEM_NAME = "db.system.name";
1108
- const classifyError = (cause, message, operation) => classifySqliteError(cause, {
1109
- message,
1110
- operation
1111
- });
1112
- const makeNodeSqliteClient = fn("makeNodeSqliteClient")(function* (config) {
1113
- const compiler = makeCompilerSqlite(config.transformQueryNames);
1114
- const transformRows = config.transformResultNames === void 0 ? void 0 : defaultTransforms(config.transformResultNames).array;
1115
- const scope$1 = yield* scope;
1116
- const db = yield* try_({
1117
- try: () => new DatabaseSync(config.filename),
1118
- catch: (cause) => new SqlError({ reason: classifyError(cause, "Failed to open sqlite database", "connect") })
1119
- });
1120
- yield* addFinalizer(scope$1, sync(() => {
1121
- try {
1122
- db.close();
1123
- } catch {}
1124
- }));
1125
- const runRows = (sql, params) => try_({
1126
- try: () => {
1127
- const statement = db.prepare(sql);
1128
- const bound = params.map(toSqlInputValue);
1129
- if (statement.columns().length > 0) return statement.all(...bound);
1130
- statement.run(...bound);
1131
- return [];
1132
- },
1133
- catch: (cause) => new SqlError({ reason: classifyError(cause, "Failed to execute sqlite statement", "execute") })
1134
- });
1135
- const runRaw = (sql, params) => try_({
1136
- try: () => {
1137
- const statement = db.prepare(sql);
1138
- const bound = params.map(toSqlInputValue);
1139
- return statement.columns().length > 0 ? statement.all(...bound) : statement.run(...bound);
1140
- },
1141
- catch: (cause) => new SqlError({ reason: classifyError(cause, "Failed to execute sqlite statement", "execute") })
1142
- });
1143
- const runValues = (sql, params) => map(runRows(sql, params), (rows) => rows.map((row) => Object.values(row)));
1144
- return yield* make({
1145
- acquirer: succeed(identity({
1146
- execute(sql, params, rowTransform) {
1147
- const effect = runRows(sql, params);
1148
- return rowTransform === void 0 ? effect : map(effect, rowTransform);
1149
- },
1150
- executeRaw(sql, params) {
1151
- return runRaw(sql, params);
1152
- },
1153
- executeValues(sql, params) {
1154
- return runValues(sql, params);
1155
- },
1156
- executeUnprepared(sql, params, rowTransform) {
1157
- const effect = runRows(sql, params);
1158
- return rowTransform === void 0 ? effect : map(effect, rowTransform);
1159
- },
1160
- executeStream(sql, params, rowTransform) {
1161
- return fromIterableEffect(this.execute(sql, params, rowTransform));
1162
- }
1163
- })),
1164
- compiler,
1165
- spanAttributes: [[ATTR_DB_SYSTEM_NAME, "sqlite"]],
1166
- transformRows
1167
- });
1168
- });
1169
- const NodeSqlClientFactoryLive = succeed$1(SqlClientFactory, { sqliteClient: (config) => makeNodeSqliteClient(config).pipe(provide(layer)) });
1170
- function toSqlInputValue(value) {
1171
- if (value === void 0 || value === null) return null;
1172
- if (typeof value === "string" || typeof value === "number" || typeof value === "bigint") return value;
1173
- if (typeof value === "boolean") return value ? 1 : 0;
1174
- if (value instanceof Date) return value.toISOString();
1175
- if (ArrayBuffer.isView(value)) {
1176
- const bytes = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
1177
- const copy = new Uint8Array(bytes.byteLength);
1178
- copy.set(bytes);
1179
- return copy;
1180
- }
1181
- return JSON.stringify(value) ?? null;
1182
- }
1183
- //#endregion
1184
- //#region src/runtime/layer.ts
1185
- const T3AuthTransportLayer = T3AuthTransportLive.pipe(provide$1(layerUndici));
1186
- const T3LocalAuthOriginLayer = T3LocalAuthOriginLive;
1187
- const T3LocalAuthTokenLayer = T3LocalAuthTokenLive.pipe(provide$1(NodeSqlClientFactoryLive));
1188
- const T3LocalAuthLayer = T3LocalAuthLive.pipe(provide$1(mergeAll(T3LocalAuthOriginLayer, T3LocalAuthTokenLayer)));
1189
- const T3AuthPairingLayer = T3AuthPairingLive.pipe(provide$1(T3AuthTransportLayer));
1190
- const T3AuthLayer = T3AuthLive.pipe(provide$1(mergeAll(T3ConfigLive, T3AuthTransportLayer, T3LocalAuthLayer, T3AuthPairingLayer)));
1191
- const T3ConfigConnectionProviderLayer = effect(T3CodeConnectionProvider, gen(function* () {
1192
- return makeT3CodeConnectionProvider((yield* T3Config).resolve().pipe(map((resolved) => ({
1193
- origin: { url: resolved.url },
1194
- auth: { token: resolved.token }
1195
- })), mapError((error) => new T3CodeConnectionError({
1196
- message: "failed to resolve T3 Code connection from CLI config",
1197
- cause: error
1198
- }))));
1199
- })).pipe(provide$1(T3ConfigLive));
1200
- const T3RpcLayer = T3RpcLive.pipe(provide$1(mergeAll(T3ConfigConnectionProviderLayer, T3AuthTransportLayer, layerWebSocketConstructor)));
1201
- const T3OrchestrationLayer = T3OrchestrationLive.pipe(provide$1(T3RpcLayer));
1202
- const T3ApplicationLayer = T3ApplicationLive.pipe(provide$1(T3OrchestrationLayer));
1203
- const AuthAppLayer = mergeAll(T3ConfigLive, T3AuthLayer);
1204
- const AppLayer = mergeAll(T3ConfigLive, T3AuthLayer, T3RpcLayer, T3OrchestrationLayer, T3ApplicationLayer);
1205
- //#endregion
1206
- export { T3AuthTransportLayer as a, T3LocalAuthTokenLayer as c, latestAssistantMessage as d, threadStatus as f, T3AuthPairingLayer as i, T3OrchestrationLayer as l, ThreadSessionError as m, AuthAppLayer as n, T3LocalAuthLayer as o, ProjectLookupError as p, T3AuthLayer as r, T3LocalAuthOriginLayer as s, AppLayer as t, T3Orchestration as u };