subagent-extension-for-codex 0.1.1 → 0.2.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.
@@ -0,0 +1,1702 @@
1
+ import { createRequire as __bundleCreateRequire } from "node:module"; const require = __bundleCreateRequire(import.meta.url);
2
+ import {
3
+ CONSTANTS,
4
+ Column,
5
+ DefaultLogger,
6
+ DrizzleQueryError,
7
+ NoopLogger,
8
+ SQL,
9
+ SQLiteAsyncDatabase,
10
+ SQLiteAsyncPreparedQuery,
11
+ SQLiteAsyncSession,
12
+ SQLiteAsyncTransaction,
13
+ SQLiteDialect,
14
+ and,
15
+ approvalModeSchema,
16
+ booleanFromInteger,
17
+ bufferFromBytes,
18
+ castToText,
19
+ dateFromStoredMilliseconds,
20
+ dateFromStoredSeconds,
21
+ deliveries,
22
+ desc,
23
+ entityKind,
24
+ eq,
25
+ extractExtendedColumnType,
26
+ formatToMillis,
27
+ getColumnTable,
28
+ getColumns,
29
+ getTableName,
30
+ gt,
31
+ inArray,
32
+ index,
33
+ integer,
34
+ is,
35
+ isTable,
36
+ isView,
37
+ isWithEnum,
38
+ jitCompatCheck,
39
+ logError,
40
+ logEvent,
41
+ lt,
42
+ lte,
43
+ max,
44
+ or,
45
+ packagePath,
46
+ primaryKey,
47
+ providerOptionsSchema,
48
+ refineSqliteCodecs,
49
+ roles,
50
+ sql,
51
+ sqliteTable,
52
+ statuses,
53
+ text,
54
+ uniqueIndex,
55
+ withLogContext
56
+ } from "./chunk-MOWBM7MZ.js";
57
+ import {
58
+ external_exports
59
+ } from "./chunk-5TX3SEV2.js";
60
+
61
+ // src/service/features/tasks/storage/store.ts
62
+ import { randomUUID } from "node:crypto";
63
+ import { EventEmitter } from "node:events";
64
+
65
+ // src/shared/tasks/conversation/unread.ts
66
+ var READ_EVENTS = [
67
+ "agent.message",
68
+ "agent.reply",
69
+ "task.turn_ended",
70
+ "task.failed",
71
+ "agent.input_required"
72
+ ];
73
+ var isUnread = (latest, mark) => Boolean(mark?.unread) || latest > (mark?.through ?? 0);
74
+
75
+ // src/shared/time.ts
76
+ var now = () => (/* @__PURE__ */ new Date()).toISOString();
77
+
78
+ // src/service/platform/database/database.ts
79
+ import { mkdirSync as mkdirSync2 } from "node:fs";
80
+ import { dirname as dirname2 } from "node:path";
81
+ import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
82
+
83
+ // node_modules/drizzle-orm/node-sqlite/codecs.js
84
+ var nodeSQLiteCodecs = refineSqliteCodecs({
85
+ "integer:boolean": { normalize: booleanFromInteger },
86
+ "integer:timestamp": { normalize: dateFromStoredSeconds },
87
+ "integer:timestamp_ms": { normalize: dateFromStoredMilliseconds },
88
+ "text:json": { normalize: JSON.parse },
89
+ blob: { normalize: bufferFromBytes },
90
+ "blob:json": {
91
+ cast: castToText,
92
+ normalize: JSON.parse
93
+ },
94
+ "blob:bigint": {
95
+ cast: castToText,
96
+ normalize: BigInt
97
+ },
98
+ numeric: {
99
+ cast: castToText,
100
+ normalize: String
101
+ },
102
+ "numeric:number": { normalize: Number },
103
+ "numeric:bigint": {
104
+ cast: castToText,
105
+ normalize: BigInt
106
+ }
107
+ });
108
+
109
+ // node_modules/drizzle-orm/node-sqlite/session.js
110
+ var NodeSQLiteSession = class extends SQLiteAsyncSession {
111
+ client;
112
+ relations;
113
+ options;
114
+ static [entityKind] = "SQLJsSession";
115
+ logger;
116
+ constructor(client, dialect, relations, options = {}) {
117
+ super(dialect, "sync");
118
+ this.client = client;
119
+ this.relations = relations;
120
+ this.options = options;
121
+ this.logger = options.logger ?? new NoopLogger();
122
+ }
123
+ prepareQuery(query, mode, _prepare, executeMethod, mapper, queryMetadata) {
124
+ let stmt;
125
+ try {
126
+ stmt = this.client.prepare(query.sql);
127
+ } catch (e) {
128
+ throw new DrizzleQueryError(query.sql, this.options.paramsInErrors ? query.params : void 0, e);
129
+ }
130
+ return new SQLiteAsyncPreparedQuery("sync", executeMethod, {
131
+ all: (params) => {
132
+ stmt.setReturnArrays(mode === "arrays");
133
+ const res = stmt.all(...params);
134
+ if (mode === "objects") return res.map((row) => ({ ...row }));
135
+ return res;
136
+ },
137
+ get: (params) => {
138
+ stmt.setReturnArrays(mode === "arrays");
139
+ const res = stmt.get(...params);
140
+ if (res && mode === "objects") return { ...res };
141
+ return res;
142
+ },
143
+ run: (params) => {
144
+ stmt.setReturnArrays(false);
145
+ return stmt.run(...params);
146
+ }
147
+ }, query, mapper, mode, this.logger, void 0, queryMetadata, void 0, this.options.paramsInErrors);
148
+ }
149
+ transaction(transaction, config = {}) {
150
+ if (config?.behavior === "concurrent") throw new Error("Concurrent transactions are not supported by driver");
151
+ const tx = new NodeSQLiteTransaction("sync", this.dialect, this, this.relations);
152
+ this.run(sql.raw(`begin${config.behavior ? ` ${config.behavior}` : ""}`));
153
+ try {
154
+ const result = transaction(tx);
155
+ this.run(sql`commit`);
156
+ return result;
157
+ } catch (err) {
158
+ try {
159
+ this.run(sql`rollback`);
160
+ } catch {
161
+ }
162
+ throw err;
163
+ }
164
+ }
165
+ };
166
+ var NodeSQLiteTransaction = class NodeSQLiteTransaction2 extends SQLiteAsyncTransaction {
167
+ static [entityKind] = "SQLJsTransaction";
168
+ transaction(transaction) {
169
+ const savepointName = `sp${this.nestedIndex + 1}`;
170
+ const tx = new NodeSQLiteTransaction2("sync", this.dialect, this.session, this._.relations, this.nestedIndex + 1);
171
+ tx.run(sql.raw(`savepoint ${savepointName}`));
172
+ try {
173
+ const result = transaction(tx);
174
+ tx.run(sql.raw(`release savepoint ${savepointName}`));
175
+ return result;
176
+ } catch (err) {
177
+ try {
178
+ tx.run(sql.raw(`rollback to savepoint ${savepointName}`));
179
+ } catch {
180
+ }
181
+ throw err;
182
+ }
183
+ }
184
+ };
185
+
186
+ // node_modules/drizzle-orm/node-sqlite/driver.js
187
+ import { DatabaseSync } from "node:sqlite";
188
+ var NodeSQLiteDatabase = class extends SQLiteAsyncDatabase {
189
+ static [entityKind] = "NodeSQLiteDatabase";
190
+ };
191
+ function construct(client, config = {}) {
192
+ const dialect = new SQLiteDialect({
193
+ codecs: config.codecs ?? nodeSQLiteCodecs,
194
+ useJitMappers: jitCompatCheck(config.jit)
195
+ });
196
+ let logger;
197
+ if (config.logger === true) logger = new DefaultLogger();
198
+ else if (config.logger !== false) logger = config.logger;
199
+ const relations = config.relations ?? {};
200
+ const db = new NodeSQLiteDatabase("sync", dialect, new NodeSQLiteSession(client, dialect, relations, {
201
+ logger,
202
+ paramsInErrors: config.paramsInErrors
203
+ }), relations);
204
+ db.$client = client;
205
+ return db;
206
+ }
207
+ function drizzle(...params) {
208
+ if (params[0] === void 0 || typeof params[0] === "string") return construct(params[0] === void 0 ? new DatabaseSync(":memory:") : new DatabaseSync(params[0]), params[1]);
209
+ const { connection, client, ...config } = params[0];
210
+ if (client) return construct(client, config);
211
+ if (typeof connection === "object") {
212
+ const { path, ...options } = connection;
213
+ return construct(new DatabaseSync(path ?? ":memory:", options), config);
214
+ }
215
+ return construct(new DatabaseSync(connection ?? ":memory:"), config);
216
+ }
217
+ (function(_drizzle) {
218
+ function mock(config) {
219
+ return construct({}, config);
220
+ }
221
+ _drizzle.mock = mock;
222
+ })(drizzle || (drizzle = {}));
223
+
224
+ // node_modules/drizzle-orm/migrator.js
225
+ import crypto from "node:crypto";
226
+ import fs, { existsSync, readdirSync } from "node:fs";
227
+ import { join } from "node:path";
228
+ function readMigrationFiles(config) {
229
+ if (fs.existsSync(`${config.migrationsFolder}/meta/_journal.json`)) throw Error('We detected that you have old drizzle-kit migration folders. You must upgrade drizzle-kit and run "drizzle-kit up"');
230
+ const migrationFolderTo = config.migrationsFolder;
231
+ const migrationQueries = [];
232
+ const migrations = readdirSync(migrationFolderTo).map((subdir) => ({
233
+ path: join(migrationFolderTo, subdir, "migration.sql"),
234
+ name: subdir
235
+ })).filter((it) => existsSync(it.path));
236
+ migrations.sort((a, b) => a.name.localeCompare(b.name));
237
+ for (const migration of migrations) {
238
+ const migrationPath = migration.path;
239
+ const migrationDate = migration.name.slice(0, 14);
240
+ const query = fs.readFileSync(migrationPath).toString();
241
+ const result = query.split("--> statement-breakpoint").map((it) => {
242
+ return it;
243
+ });
244
+ const millis = formatToMillis(migrationDate);
245
+ migrationQueries.push({
246
+ sql: result,
247
+ bps: true,
248
+ folderMillis: millis,
249
+ hash: crypto.createHash("sha256").update(query).digest("hex"),
250
+ name: migration.name
251
+ });
252
+ }
253
+ return migrationQueries;
254
+ }
255
+
256
+ // src/service/platform/database/backup.ts
257
+ import { mkdirSync, readdirSync as readdirSync2, rmSync } from "node:fs";
258
+ import { basename, dirname, extname, join as join2 } from "node:path";
259
+ var KEEP = 3;
260
+ function backUpDatabase(client, path, lastMigration) {
261
+ const directory = join2(dirname(path), "backups");
262
+ mkdirSync(directory, { recursive: true, mode: 448 });
263
+ const name = basename(path, extname(path));
264
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
265
+ const backup = join2(directory, `${name}-${lastMigration}-${stamp}.sqlite`);
266
+ client.prepare("VACUUM INTO ?").run(backup);
267
+ const stamped = new RegExp(`^${name}-.+-(\\d{4}-[\\dT-]+Z)\\.sqlite$`);
268
+ const backups = readdirSync2(directory).flatMap((file) => {
269
+ const time = file.match(stamped)?.[1];
270
+ return time ? [{ file, time }] : [];
271
+ }).sort(
272
+ (a, b) => b.time.localeCompare(a.time) || b.file.localeCompare(a.file)
273
+ );
274
+ for (const { file } of backups.slice(KEEP)) {
275
+ rmSync(join2(directory, file), { force: true });
276
+ }
277
+ return backup;
278
+ }
279
+
280
+ // src/service/platform/database/migrate.ts
281
+ var LEDGER = "__drizzle_migrations";
282
+ function migrate(client, folder, path) {
283
+ const migrations = readMigrationFiles({ migrationsFolder: folder });
284
+ if (!migrations.length) throw new Error(`No migrations found in ${folder}`);
285
+ const before = ledger(client);
286
+ if (before.length && path !== ":memory:" && migrations.some((m) => !before.includes(m.name))) {
287
+ backUpDatabase(client, path, before.at(-1));
288
+ }
289
+ client.exec("BEGIN IMMEDIATE");
290
+ try {
291
+ const versioned = client.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?").get(LEDGER);
292
+ if (!versioned) {
293
+ const tables = client.prepare(
294
+ "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'"
295
+ ).all();
296
+ if (tables.length) {
297
+ throw new Error(
298
+ `${path} was created by an unsupported earlier version. Delete its data directory to start over.`
299
+ );
300
+ }
301
+ client.exec(
302
+ `CREATE TABLE ${LEDGER}(id INTEGER PRIMARY KEY, hash TEXT NOT NULL, created_at NUMERIC, name TEXT, applied_at TEXT)`
303
+ );
304
+ }
305
+ const applied = new Set(ledger(client));
306
+ const known = new Set(migrations.map((m) => m.name));
307
+ const unknown = [...applied].filter((name) => !known.has(name));
308
+ if (unknown.length) {
309
+ throw new Error(
310
+ `${path} has migration history this build does not recognize (${unknown.join(", ")}). Use a build that includes those migrations, or delete its data directory to start over.`
311
+ );
312
+ }
313
+ const record = client.prepare(
314
+ `INSERT INTO ${LEDGER}(hash, created_at, name, applied_at) VALUES(?,?,?,?)`
315
+ );
316
+ for (const migration of migrations) {
317
+ if (applied.has(migration.name)) continue;
318
+ for (const statement of migration.sql) {
319
+ if (statement.trim()) client.exec(statement);
320
+ }
321
+ record.run(
322
+ migration.hash,
323
+ migration.folderMillis,
324
+ migration.name,
325
+ (/* @__PURE__ */ new Date()).toISOString()
326
+ );
327
+ }
328
+ client.exec("COMMIT");
329
+ } catch (error) {
330
+ client.exec("ROLLBACK");
331
+ throw error;
332
+ }
333
+ }
334
+ function ledger(client) {
335
+ const exists = client.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?").get(LEDGER);
336
+ if (!exists) return [];
337
+ return client.prepare(`SELECT name FROM ${LEDGER} ORDER BY id`).all().map((row) => String(row.name));
338
+ }
339
+
340
+ // src/service/platform/database/database.ts
341
+ var migrationsFolder = packagePath("migrations");
342
+ for (const method of ["run", "all", "get", "values"]) {
343
+ const prototype = SQLiteAsyncPreparedQuery.prototype;
344
+ const execute = prototype[method];
345
+ if (!execute) {
346
+ throw new Error(
347
+ `Drizzle's prepared queries have no ${method} method to wrap; check the drizzle-orm upgrade.`
348
+ );
349
+ }
350
+ prototype[method] = function(...args) {
351
+ try {
352
+ return execute.apply(this, args);
353
+ } catch (error) {
354
+ throw error instanceof DrizzleQueryError && error.cause instanceof Error ? error.cause : error;
355
+ }
356
+ };
357
+ }
358
+ var BUSY_TIMEOUT_MS = 5e3;
359
+ var SQLITE_BUSY = 5;
360
+ function busy(error) {
361
+ return (error.errcode ?? 0) % 256 === SQLITE_BUSY;
362
+ }
363
+ function useWal(client) {
364
+ const deadline = Date.now() + BUSY_TIMEOUT_MS;
365
+ for (; ; ) {
366
+ try {
367
+ if (client.prepare("PRAGMA journal_mode").get()?.journal_mode === "wal") {
368
+ return;
369
+ }
370
+ client.exec("PRAGMA journal_mode=WAL");
371
+ return;
372
+ } catch (error) {
373
+ if (!busy(error) || Date.now() > deadline) throw error;
374
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 25);
375
+ }
376
+ }
377
+ }
378
+ function thenable(value) {
379
+ return typeof value?.then === "function";
380
+ }
381
+ function transactions(client) {
382
+ let queued;
383
+ return {
384
+ transaction(fn) {
385
+ if (queued) {
386
+ throw new Error(
387
+ "A transaction is already open; run this work inside it"
388
+ );
389
+ }
390
+ const notifications = [];
391
+ queued = notifications;
392
+ let result;
393
+ client.exec("BEGIN IMMEDIATE");
394
+ try {
395
+ result = fn();
396
+ if (thenable(result)) {
397
+ throw new Error("Database transactions must be synchronous");
398
+ }
399
+ client.exec("COMMIT");
400
+ } catch (error) {
401
+ client.exec("ROLLBACK");
402
+ throw error;
403
+ } finally {
404
+ queued = void 0;
405
+ }
406
+ for (const notify of notifications) notify();
407
+ return result;
408
+ },
409
+ afterCommit(notify) {
410
+ if (queued) queued.push(notify);
411
+ else notify();
412
+ }
413
+ };
414
+ }
415
+ function openDatabase(path, migrations = migrationsFolder) {
416
+ mkdirSync2(dirname2(path), { recursive: true, mode: 448 });
417
+ const client = new DatabaseSync2(path, { timeout: BUSY_TIMEOUT_MS });
418
+ try {
419
+ useWal(client);
420
+ client.exec("PRAGMA foreign_keys=ON");
421
+ migrate(client, migrations, path);
422
+ } catch (error) {
423
+ client.close();
424
+ throw error;
425
+ }
426
+ return {
427
+ client,
428
+ orm: drizzle({ client }),
429
+ ...transactions(client),
430
+ close: () => client.close()
431
+ };
432
+ }
433
+ var INCREMENTAL = 2;
434
+ function useIncrementalVacuum(database) {
435
+ const { client } = database;
436
+ const mode = client.prepare("PRAGMA auto_vacuum").get()?.auto_vacuum;
437
+ if (mode === INCREMENTAL) return;
438
+ const started = performance.now();
439
+ logEvent("info", "database.vacuum_started");
440
+ client.exec("PRAGMA auto_vacuum=INCREMENTAL");
441
+ client.exec("VACUUM");
442
+ logEvent("info", "database.vacuum_completed", {
443
+ duration_ms: Math.round(performance.now() - started)
444
+ });
445
+ }
446
+
447
+ // src/shared/providers/activity/presentation-contract.generated.ts
448
+ var activityRateLimitWindowSchema = external_exports.object({
449
+ id: external_exports.string(),
450
+ label: external_exports.string(),
451
+ utilization: external_exports.number(),
452
+ resetsAt: external_exports.number().optional()
453
+ });
454
+ var activityStreamAppendSchema = external_exports.union([
455
+ external_exports.object({
456
+ field: external_exports.literal("text"),
457
+ type: external_exports.literal("text"),
458
+ text: external_exports.string()
459
+ }),
460
+ external_exports.object({
461
+ field: external_exports.literal("thinking"),
462
+ type: external_exports.literal("thinking"),
463
+ text: external_exports.string()
464
+ }),
465
+ external_exports.object({
466
+ field: external_exports.literal("partial_json"),
467
+ type: external_exports.literal("input_json_delta"),
468
+ text: external_exports.string()
469
+ })
470
+ ]);
471
+ var activityContentSchema = external_exports.lazy(
472
+ () => external_exports.union([external_exports.string(), activityContentBlockSchema])
473
+ );
474
+ var activityContentBlockSchema = external_exports.lazy(
475
+ () => external_exports.union([
476
+ external_exports.object({
477
+ type: external_exports.literal("text"),
478
+ text: external_exports.string()
479
+ }),
480
+ external_exports.object({
481
+ type: external_exports.literal("thinking"),
482
+ thinking: external_exports.string()
483
+ }),
484
+ external_exports.object({
485
+ type: external_exports.literal("input_json_delta"),
486
+ partial_json: external_exports.string()
487
+ }),
488
+ external_exports.object({
489
+ type: external_exports.literal("tool_use"),
490
+ id: external_exports.string(),
491
+ name: external_exports.string(),
492
+ input: external_exports.record(external_exports.string(), external_exports.unknown())
493
+ }),
494
+ external_exports.object({
495
+ type: external_exports.literal("tool_result"),
496
+ tool_use_id: external_exports.string(),
497
+ content: external_exports.union([external_exports.string(), external_exports.array(activityContentSchema)]),
498
+ is_error: external_exports.boolean().optional()
499
+ }),
500
+ external_exports.object({
501
+ type: external_exports.literal("opaque"),
502
+ data: external_exports.record(external_exports.string(), external_exports.unknown())
503
+ })
504
+ ])
505
+ );
506
+ var activityPresentationSchema = external_exports.lazy(
507
+ () => external_exports.object({
508
+ kind: external_exports.string().optional(),
509
+ title: external_exports.string().optional(),
510
+ summary: external_exports.string().optional(),
511
+ summaryIsResponse: external_exports.boolean().optional(),
512
+ statusTitle: external_exports.string().optional(),
513
+ liveStatus: external_exports.boolean().optional(),
514
+ quiet: external_exports.boolean().optional(),
515
+ thinking: external_exports.boolean().optional(),
516
+ failed: external_exports.boolean().optional(),
517
+ messageId: external_exports.string().optional(),
518
+ hasThinking: external_exports.boolean().optional(),
519
+ rateLimitWindows: external_exports.array(activityRateLimitWindowSchema).optional(),
520
+ statusState: external_exports.union([
521
+ external_exports.literal("running"),
522
+ external_exports.literal("completed"),
523
+ external_exports.literal("failed"),
524
+ external_exports.literal("info")
525
+ ]).optional(),
526
+ operation: external_exports.object({
527
+ id: external_exports.string(),
528
+ kind: external_exports.union([external_exports.literal("tool"), external_exports.literal("operation")]),
529
+ title: external_exports.string(),
530
+ summary: external_exports.string().optional(),
531
+ started: external_exports.boolean().optional(),
532
+ completed: external_exports.boolean().optional(),
533
+ stopped: external_exports.boolean().optional()
534
+ }).optional(),
535
+ stream: external_exports.object({
536
+ id: external_exports.string(),
537
+ messageId: external_exports.string().optional(),
538
+ started: external_exports.boolean().optional(),
539
+ completed: external_exports.boolean().optional(),
540
+ title: external_exports.string().optional(),
541
+ content: external_exports.union([activityContentSchema, external_exports.array(activityContentSchema)]).optional(),
542
+ details: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
543
+ update: external_exports.object({
544
+ index: external_exports.number(),
545
+ block: activityContentBlockSchema.optional(),
546
+ append: activityStreamAppendSchema.optional()
547
+ }).optional()
548
+ }).optional(),
549
+ body: external_exports.object({
550
+ role: external_exports.union([external_exports.literal("assistant"), external_exports.literal("user")]).optional(),
551
+ content: external_exports.array(activityContentSchema).optional(),
552
+ error: external_exports.union([external_exports.boolean(), external_exports.string()]).optional()
553
+ }).optional()
554
+ })
555
+ );
556
+
557
+ // src/shared/tasks/event-contract.generated.ts
558
+ var emptyEventPayloadSchema = external_exports.record(external_exports.string(), external_exports.never());
559
+ var taskStartedPayloadSchema = external_exports.object({
560
+ turn: external_exports.number()
561
+ });
562
+ var taskTurnEndedPayloadSchema = external_exports.object({
563
+ turn: external_exports.number(),
564
+ outcome: external_exports.union([
565
+ external_exports.literal("completed"),
566
+ external_exports.literal("failed"),
567
+ external_exports.literal("interrupted")
568
+ ]),
569
+ runtime_ms: external_exports.number(),
570
+ cost_usd: external_exports.number()
571
+ });
572
+ var taskInstructionPayloadSchema = external_exports.object({
573
+ message_id: external_exports.string(),
574
+ message: external_exports.string(),
575
+ from: external_exports.union([external_exports.literal("user"), external_exports.literal("parent")]),
576
+ delivery: external_exports.union([
577
+ external_exports.literal("steer"),
578
+ external_exports.literal("queue"),
579
+ external_exports.literal("interrupt")
580
+ ])
581
+ });
582
+ var taskQueueChangedPayloadSchema = external_exports.object({
583
+ queue: external_exports.array(
584
+ external_exports.object({
585
+ message_id: external_exports.string(),
586
+ message: external_exports.string(),
587
+ from: external_exports.union([external_exports.literal("user"), external_exports.literal("parent")])
588
+ })
589
+ ),
590
+ paused: external_exports.boolean()
591
+ });
592
+ var taskSessionStartedPayloadSchema = external_exports.object({
593
+ reason: external_exports.union([external_exports.literal("no_session"), external_exports.literal("session_unavailable")])
594
+ });
595
+ var taskWorktreeRecreatedPayloadSchema = external_exports.object({
596
+ from: external_exports.union([external_exports.literal("branch"), external_exports.literal("base")])
597
+ });
598
+ var taskInterruptedPayloadSchema = external_exports.object({
599
+ reason: external_exports.literal("service_restart").optional(),
600
+ error: external_exports.string().optional()
601
+ });
602
+ var taskFailedPayloadSchema = external_exports.object({
603
+ error: external_exports.string().optional()
604
+ });
605
+ var taskWaitingPayloadSchema = external_exports.object({
606
+ reason: external_exports.string().optional(),
607
+ dependency_id: external_exports.string().optional()
608
+ });
609
+ var taskWorktreeRemovedPayloadSchema = external_exports.object({
610
+ path: external_exports.string().optional(),
611
+ branch: external_exports.string().optional(),
612
+ forced: external_exports.boolean().optional()
613
+ });
614
+ var taskBranchDeletedPayloadSchema = external_exports.object({
615
+ branch: external_exports.string().optional()
616
+ });
617
+ var taskControlRequestedPayloadSchema = external_exports.object({
618
+ status: external_exports.literal("interrupted")
619
+ });
620
+ var taskSteerTakenPayloadSchema = external_exports.object({
621
+ message_id: external_exports.string()
622
+ });
623
+ var taskMessageRemovedPayloadSchema = external_exports.object({
624
+ message_id: external_exports.string()
625
+ });
626
+ var taskStatusPayloadSchema = external_exports.object({
627
+ error: external_exports.string().optional()
628
+ });
629
+ var taskEventPayloadMapSchema = external_exports.object({
630
+ "task.started": taskStartedPayloadSchema,
631
+ "task.turn_ended": taskTurnEndedPayloadSchema,
632
+ "task.instruction": taskInstructionPayloadSchema,
633
+ "task.queue_changed": taskQueueChangedPayloadSchema,
634
+ "task.session_started": taskSessionStartedPayloadSchema,
635
+ "task.worktree_recreated": taskWorktreeRecreatedPayloadSchema,
636
+ "task.interrupted": taskInterruptedPayloadSchema,
637
+ "task.failed": taskFailedPayloadSchema,
638
+ "task.waiting": taskWaitingPayloadSchema,
639
+ "task.worktree_removed": taskWorktreeRemovedPayloadSchema,
640
+ "task.branch_deleted": taskBranchDeletedPayloadSchema,
641
+ "task.control_requested": taskControlRequestedPayloadSchema,
642
+ "task.steer_taken": taskSteerTakenPayloadSchema,
643
+ "task.message_removed": taskMessageRemovedPayloadSchema,
644
+ "task.queued": emptyEventPayloadSchema,
645
+ "task.completed": taskStatusPayloadSchema
646
+ });
647
+
648
+ // src/shared/events/event-contract.generated.ts
649
+ var eventEnvelopeSchema = external_exports.object({
650
+ id: external_exports.number(),
651
+ task_id: external_exports.string(),
652
+ type: external_exports.string(),
653
+ timestamp: external_exports.string(),
654
+ data: external_exports.record(external_exports.string(), external_exports.unknown())
655
+ });
656
+ var toolStartedPayloadSchema = external_exports.object({
657
+ id: external_exports.string().optional(),
658
+ name: external_exports.string().optional(),
659
+ input: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
660
+ });
661
+ var toolCompletedPayloadSchema = external_exports.object({
662
+ id: external_exports.string().optional(),
663
+ name: external_exports.string().optional(),
664
+ input: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
665
+ error: external_exports.boolean().optional(),
666
+ content: external_exports.union([external_exports.string(), external_exports.array(activityContentSchema)]).optional()
667
+ });
668
+ var agentMessageFieldsSchema = external_exports.object({
669
+ message_id: external_exports.string().optional(),
670
+ parent_tool_use_id: external_exports.string().optional().nullable()
671
+ });
672
+ var agentMessagePayloadSchema = agentMessageFieldsSchema.extend({
673
+ role: external_exports.literal("assistant"),
674
+ text: external_exports.string(),
675
+ content: external_exports.union([activityContentSchema, external_exports.array(activityContentSchema)]).optional()
676
+ });
677
+ var agentContentPayloadSchema = agentMessageFieldsSchema.extend({
678
+ role: external_exports.union([external_exports.literal("assistant"), external_exports.literal("user")]),
679
+ content: external_exports.union([activityContentSchema, external_exports.array(activityContentSchema)]),
680
+ text: external_exports.string().optional()
681
+ });
682
+ var agentReplyPayloadSchema = external_exports.object({
683
+ text: external_exports.string(),
684
+ turn: external_exports.number()
685
+ });
686
+ var agentStartedPayloadSchema = external_exports.object({
687
+ model: external_exports.string().optional(),
688
+ tools: external_exports.array(external_exports.string()).optional()
689
+ });
690
+ var agentCompletedPayloadSchema = external_exports.object({
691
+ cost_usd: external_exports.number().optional(),
692
+ total_cost_usd: external_exports.number().optional(),
693
+ duration_ms: external_exports.number().optional(),
694
+ result: external_exports.string().optional(),
695
+ subtype: external_exports.string().optional(),
696
+ is_error: external_exports.boolean().optional(),
697
+ errors: external_exports.array(external_exports.string()).optional(),
698
+ usage: external_exports.object({
699
+ input_tokens: external_exports.number().optional(),
700
+ output_tokens: external_exports.number().optional(),
701
+ cache_creation_input_tokens: external_exports.number().optional(),
702
+ cache_read_input_tokens: external_exports.number().optional()
703
+ }).optional()
704
+ });
705
+ var agentInputRequiredPayloadSchema = external_exports.object({
706
+ request: external_exports.object({
707
+ id: external_exports.string(),
708
+ tool: external_exports.string(),
709
+ kind: external_exports.union([external_exports.literal("question"), external_exports.literal("permission")]),
710
+ input: external_exports.record(external_exports.string(), external_exports.unknown())
711
+ }).optional()
712
+ });
713
+ var agentInputSubmittedPayloadSchema = external_exports.object({
714
+ approved: external_exports.boolean()
715
+ });
716
+ var agentPermissionDecidedPayloadSchema = external_exports.object({
717
+ tool: external_exports.string(),
718
+ input: external_exports.record(external_exports.string(), external_exports.unknown()),
719
+ approval_mode: external_exports.union([
720
+ external_exports.literal("ask_user"),
721
+ external_exports.literal("parent_agent"),
722
+ external_exports.literal("auto_approve"),
723
+ external_exports.literal("deny")
724
+ ]),
725
+ approved: external_exports.boolean(),
726
+ authority: external_exports.literal("policy")
727
+ });
728
+ var agentInputDecisionPayloadSchema = external_exports.object({
729
+ request_id: external_exports.string(),
730
+ approved: external_exports.boolean(),
731
+ authority: external_exports.union([external_exports.literal("user"), external_exports.literal("parent")])
732
+ });
733
+ var eventPayloadMapSchema = taskEventPayloadMapSchema.extend({
734
+ "tool.started": toolStartedPayloadSchema,
735
+ "tool.completed": toolCompletedPayloadSchema,
736
+ "agent.message": agentMessagePayloadSchema,
737
+ "agent.content": agentContentPayloadSchema,
738
+ "agent.reply": agentReplyPayloadSchema,
739
+ "agent.started": agentStartedPayloadSchema,
740
+ "agent.completed": agentCompletedPayloadSchema,
741
+ "agent.input_required": agentInputRequiredPayloadSchema,
742
+ "agent.input_submitted": agentInputSubmittedPayloadSchema,
743
+ "agent.permission_decided": agentPermissionDecidedPayloadSchema,
744
+ "agent.input_decision": agentInputDecisionPayloadSchema
745
+ });
746
+
747
+ // src/shared/events/decode.ts
748
+ var knownEventTypes = new Set(Object.keys(eventPayloadMapSchema.shape));
749
+ function decodeEventView(type, data) {
750
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
751
+ throw new Error("Event data must be an object");
752
+ }
753
+ if (!knownEventTypes.has(type)) {
754
+ return {
755
+ kind: "opaque",
756
+ type,
757
+ data
758
+ };
759
+ }
760
+ const eventType = type;
761
+ const schema = eventPayloadMapSchema.shape[eventType];
762
+ const parsed = schema.safeParse(data);
763
+ if (!parsed.success) {
764
+ return { kind: "opaque", type, data };
765
+ }
766
+ return {
767
+ kind: "known",
768
+ type: eventType,
769
+ data: parsed.data
770
+ };
771
+ }
772
+ function decodedEvent(event) {
773
+ const parsedPresentation = activityPresentationSchema.safeParse(
774
+ event.data.activity
775
+ );
776
+ return {
777
+ id: event.id,
778
+ task_id: event.task_id,
779
+ type: event.type,
780
+ timestamp: event.timestamp,
781
+ data: event.data,
782
+ view: decodeEventView(event.type, event.data),
783
+ ...parsedPresentation.success ? { presentation: parsedPresentation.data } : {}
784
+ };
785
+ }
786
+
787
+ // src/service/features/tasks/storage/schema.ts
788
+ var tasks = sqliteTable("tasks", {
789
+ id: text().primaryKey(),
790
+ owner: text().notNull(),
791
+ body: text().notNull()
792
+ });
793
+ var events = sqliteTable(
794
+ "events",
795
+ {
796
+ id: integer().primaryKey({ autoIncrement: true }),
797
+ task_id: text().notNull().references(() => tasks.id, { onDelete: "cascade" }),
798
+ type: text().notNull(),
799
+ timestamp: text().notNull(),
800
+ data: text().notNull(),
801
+ response_ref: text(),
802
+ original_response: text()
803
+ },
804
+ (t) => [
805
+ index("events_task").on(t.task_id, t.id),
806
+ uniqueIndex("events_response").on(t.response_ref)
807
+ ]
808
+ );
809
+ var taskRead = sqliteTable("task_read", {
810
+ task_id: text().primaryKey().references(() => tasks.id, { onDelete: "cascade" }),
811
+ through: integer().notNull(),
812
+ unread: integer({ mode: "boolean" }).notNull()
813
+ });
814
+ var parentSeen = sqliteTable("task_parent_seen", {
815
+ event_id: integer().primaryKey().references(() => events.id, { onDelete: "cascade" })
816
+ });
817
+ var taskArchive = sqliteTable("task_archive", {
818
+ task_id: text().primaryKey().references(() => tasks.id, { onDelete: "cascade" }),
819
+ archived_at: text().notNull()
820
+ });
821
+ var sendReceipts = sqliteTable(
822
+ "task_send_receipts",
823
+ {
824
+ owner: text().notNull(),
825
+ task_id: text().notNull().references(() => tasks.id, { onDelete: "cascade" }),
826
+ sender: text().notNull(),
827
+ request_id: text().notNull(),
828
+ fingerprint: text().notNull(),
829
+ message_id: text().notNull(),
830
+ state: text().notNull()
831
+ },
832
+ (t) => [
833
+ primaryKey({ columns: [t.owner, t.task_id, t.sender, t.request_id] })
834
+ ]
835
+ );
836
+
837
+ // src/service/features/tasks/storage/event-records.ts
838
+ var eventColumns = {
839
+ id: events.id,
840
+ task_id: events.task_id,
841
+ type: events.type,
842
+ timestamp: events.timestamp,
843
+ data: events.data
844
+ };
845
+ function readOriginalResponse(database, id, responseRef) {
846
+ const row = database.orm.select({ body: events.original_response }).from(events).where(and(eq(events.response_ref, responseRef), eq(events.task_id, id))).get();
847
+ return row?.body ? JSON.parse(row.body) : void 0;
848
+ }
849
+ function splitOriginalResponse(payload) {
850
+ const response = typeof payload.response_ref === "string" && payload.raw_response !== void 0 ? {
851
+ id: payload.response_ref,
852
+ body: JSON.stringify(payload.raw_response)
853
+ } : void 0;
854
+ const { raw_response: _original, ...data } = payload;
855
+ return { data, response, serialized: JSON.stringify(data) };
856
+ }
857
+ function insertEvent(database, metrics, taskId, type, payload) {
858
+ const timestamp = now();
859
+ const stored = splitOriginalResponse(payload);
860
+ const { id } = database.orm.insert(events).values({
861
+ task_id: taskId,
862
+ type,
863
+ timestamp,
864
+ data: stored.serialized,
865
+ response_ref: stored.response?.id,
866
+ original_response: stored.response?.body
867
+ }).returning({ id: events.id }).get();
868
+ metrics.committed(database, taskId, stored.serialized, stored.response?.body);
869
+ return decodedEvent({
870
+ id,
871
+ task_id: taskId,
872
+ type,
873
+ timestamp,
874
+ data: stored.data
875
+ });
876
+ }
877
+
878
+ // node_modules/drizzle-orm/zod/column.js
879
+ var literalSchema = external_exports.union([
880
+ external_exports.string(),
881
+ external_exports.number(),
882
+ external_exports.boolean(),
883
+ external_exports.null()
884
+ ]);
885
+ var jsonSchema = external_exports.union([
886
+ literalSchema,
887
+ external_exports.record(external_exports.string(), external_exports.any()),
888
+ external_exports.array(external_exports.any())
889
+ ]);
890
+ var bufferSchema = external_exports.custom((v) => v instanceof Buffer);
891
+ function columnToSchema(column, factory) {
892
+ const z$1 = factory?.zodInstance ?? external_exports;
893
+ const coerce = factory?.coerce ?? {};
894
+ let schema;
895
+ const dimensions = column.dimensions;
896
+ if (typeof dimensions === "number" && dimensions > 0) return pgArrayColumnToSchema(column, dimensions, z$1, coerce);
897
+ const { type, constraint } = extractExtendedColumnType(column);
898
+ switch (type) {
899
+ case "array":
900
+ schema = arrayColumnToSchema(column, constraint, z$1);
901
+ break;
902
+ case "object":
903
+ schema = objectColumnToSchema(column, constraint, z$1, coerce);
904
+ break;
905
+ case "number":
906
+ schema = numberColumnToSchema(column, constraint, z$1, coerce);
907
+ break;
908
+ case "bigint":
909
+ schema = bigintColumnToSchema(column, constraint, z$1, coerce);
910
+ break;
911
+ case "boolean":
912
+ schema = coerce === true || coerce.boolean ? z$1.coerce.boolean() : z$1.boolean();
913
+ break;
914
+ case "string":
915
+ schema = stringColumnToSchema(column, constraint, z$1, coerce);
916
+ break;
917
+ case "custom":
918
+ schema = z$1.any();
919
+ break;
920
+ default:
921
+ schema = z$1.any();
922
+ }
923
+ return schema;
924
+ }
925
+ function numberColumnToSchema(column, constraint, z, coerce) {
926
+ let min;
927
+ let max2;
928
+ let integer2 = false;
929
+ switch (constraint) {
930
+ case "int8":
931
+ min = CONSTANTS.INT8_MIN;
932
+ max2 = CONSTANTS.INT8_MAX;
933
+ integer2 = true;
934
+ break;
935
+ case "uint8":
936
+ min = 0;
937
+ max2 = CONSTANTS.INT8_UNSIGNED_MAX;
938
+ integer2 = true;
939
+ break;
940
+ case "int16":
941
+ min = CONSTANTS.INT16_MIN;
942
+ max2 = CONSTANTS.INT16_MAX;
943
+ integer2 = true;
944
+ break;
945
+ case "uint16":
946
+ min = 0;
947
+ max2 = CONSTANTS.INT16_UNSIGNED_MAX;
948
+ integer2 = true;
949
+ break;
950
+ case "int24":
951
+ min = CONSTANTS.INT24_MIN;
952
+ max2 = CONSTANTS.INT24_MAX;
953
+ integer2 = true;
954
+ break;
955
+ case "uint24":
956
+ min = 0;
957
+ max2 = CONSTANTS.INT24_UNSIGNED_MAX;
958
+ integer2 = true;
959
+ break;
960
+ case "int32":
961
+ min = CONSTANTS.INT32_MIN;
962
+ max2 = CONSTANTS.INT32_MAX;
963
+ integer2 = true;
964
+ break;
965
+ case "uint32":
966
+ min = 0;
967
+ max2 = CONSTANTS.INT32_UNSIGNED_MAX;
968
+ integer2 = true;
969
+ break;
970
+ case "int53":
971
+ min = Number.MIN_SAFE_INTEGER;
972
+ max2 = Number.MAX_SAFE_INTEGER;
973
+ integer2 = true;
974
+ break;
975
+ case "uint53":
976
+ min = 0;
977
+ max2 = Number.MAX_SAFE_INTEGER;
978
+ integer2 = true;
979
+ break;
980
+ case "float":
981
+ min = CONSTANTS.INT24_MIN;
982
+ max2 = CONSTANTS.INT24_MAX;
983
+ break;
984
+ case "ufloat":
985
+ min = 0;
986
+ max2 = CONSTANTS.INT24_UNSIGNED_MAX;
987
+ break;
988
+ case "double":
989
+ min = CONSTANTS.INT48_MIN;
990
+ max2 = CONSTANTS.INT48_MAX;
991
+ break;
992
+ case "udouble":
993
+ min = 0;
994
+ max2 = CONSTANTS.INT48_UNSIGNED_MAX;
995
+ break;
996
+ case "year":
997
+ min = 1901;
998
+ max2 = 2155;
999
+ integer2 = true;
1000
+ break;
1001
+ case "unsigned":
1002
+ min = 0;
1003
+ max2 = Number.MAX_SAFE_INTEGER;
1004
+ break;
1005
+ default:
1006
+ min = Number.MIN_SAFE_INTEGER;
1007
+ max2 = Number.MAX_SAFE_INTEGER;
1008
+ }
1009
+ let schema = coerce === true || coerce?.number ? integer2 ? z.coerce.number().int() : z.coerce.number() : integer2 ? z.int() : z.number();
1010
+ schema = schema.gte(min).lte(max2);
1011
+ return schema;
1012
+ }
1013
+ var bigintStringModeSchema = external_exports.string().regex(/^-?\d+$/).transform(BigInt).pipe(external_exports.bigint().gte(CONSTANTS.INT64_MIN).lte(CONSTANTS.INT64_MAX)).transform(String);
1014
+ var unsignedBigintStringModeSchema = external_exports.string().regex(/^\d+$/).transform(BigInt).pipe(external_exports.bigint().gte(0n).lte(CONSTANTS.INT64_MAX)).transform(String);
1015
+ function bigintColumnToSchema(column, constraint, z, coerce) {
1016
+ let min;
1017
+ let max2;
1018
+ switch (constraint) {
1019
+ case "int64":
1020
+ min = CONSTANTS.INT64_MIN;
1021
+ max2 = CONSTANTS.INT64_MAX;
1022
+ break;
1023
+ case "uint64":
1024
+ min = 0n;
1025
+ max2 = CONSTANTS.INT64_UNSIGNED_MAX;
1026
+ }
1027
+ let schema = coerce === true || coerce?.bigint ? z.coerce.bigint() : z.bigint();
1028
+ if (min !== void 0) schema = schema.min(min);
1029
+ if (max2 !== void 0) schema = schema.max(max2);
1030
+ return schema;
1031
+ }
1032
+ function pgArrayColumnToSchema(column, dimensions, z, coerce) {
1033
+ const [baseType, baseConstraint] = column.dataType.split(" ");
1034
+ let baseSchema;
1035
+ switch (baseType) {
1036
+ case "number":
1037
+ baseSchema = numberColumnToSchema(column, baseConstraint, z, coerce);
1038
+ break;
1039
+ case "bigint":
1040
+ baseSchema = bigintColumnToSchema(column, baseConstraint, z, coerce);
1041
+ break;
1042
+ case "boolean":
1043
+ baseSchema = coerce === true || coerce?.boolean ? z.coerce.boolean() : z.boolean();
1044
+ break;
1045
+ case "string":
1046
+ baseSchema = stringColumnToSchema(column, baseConstraint, z, coerce);
1047
+ break;
1048
+ case "object":
1049
+ baseSchema = objectColumnToSchema(column, baseConstraint, z, coerce);
1050
+ break;
1051
+ case "array":
1052
+ baseSchema = arrayColumnToSchema(column, baseConstraint, z);
1053
+ break;
1054
+ default:
1055
+ baseSchema = z.any();
1056
+ }
1057
+ let schema = z.array(baseSchema);
1058
+ for (let i = 1; i < dimensions; i++) schema = z.array(schema);
1059
+ return schema;
1060
+ }
1061
+ function arrayColumnToSchema(column, constraint, z) {
1062
+ switch (constraint) {
1063
+ case "geometry":
1064
+ case "point":
1065
+ return z.tuple([z.number(), z.number()]);
1066
+ case "line":
1067
+ return z.tuple([
1068
+ z.number(),
1069
+ z.number(),
1070
+ z.number()
1071
+ ]);
1072
+ case "vector":
1073
+ case "halfvector": {
1074
+ const length = column.length;
1075
+ return length ? z.array(z.number()).length(length) : z.array(z.number());
1076
+ }
1077
+ case "int64vector": {
1078
+ const length = column.length;
1079
+ return length ? z.array(z.bigint().min(CONSTANTS.INT64_MIN).max(CONSTANTS.INT64_MAX)).length(length) : z.array(z.bigint().min(CONSTANTS.INT64_MIN).max(CONSTANTS.INT64_MAX));
1080
+ }
1081
+ default:
1082
+ return z.array(z.any());
1083
+ }
1084
+ }
1085
+ function objectColumnToSchema(column, constraint, z, coerce) {
1086
+ switch (constraint) {
1087
+ case "buffer":
1088
+ return bufferSchema;
1089
+ case "date":
1090
+ return coerce === true || coerce?.date ? z.coerce.date() : z.date();
1091
+ case "geometry":
1092
+ case "point":
1093
+ return z.object({
1094
+ x: z.number(),
1095
+ y: z.number()
1096
+ });
1097
+ case "json":
1098
+ return jsonSchema;
1099
+ case "line":
1100
+ return z.object({
1101
+ a: z.number(),
1102
+ b: z.number(),
1103
+ c: z.number()
1104
+ });
1105
+ default:
1106
+ return z.looseObject({});
1107
+ }
1108
+ }
1109
+ function stringColumnToSchema(column, constraint, z, coerce) {
1110
+ const { name: columnName, length, isLengthExact } = column;
1111
+ let regex;
1112
+ if (constraint === "binary") regex = /^[01]*$/;
1113
+ if (constraint === "uuid") return z.uuid();
1114
+ if (constraint === "enum") {
1115
+ const enumValues = column.enumValues;
1116
+ if (!enumValues) throw new Error(`Column "${getTableName(getColumnTable(column))}"."${columnName}" is of 'enum' type, but lacks enum values`);
1117
+ return z.enum(enumValues);
1118
+ }
1119
+ if (constraint === "int64") return bigintStringModeSchema;
1120
+ if (constraint === "uint64") return unsignedBigintStringModeSchema;
1121
+ let schema = coerce === true || coerce?.string ? z.coerce.string() : z.string();
1122
+ schema = regex ? schema.regex(regex) : schema;
1123
+ return length && isLengthExact ? schema.length(length) : length ? schema.max(length) : schema;
1124
+ }
1125
+
1126
+ // node_modules/drizzle-orm/zod/schema.js
1127
+ function handleColumns(columns, refinements, conditions, factory) {
1128
+ const columnSchemas = {};
1129
+ for (const [key, selected] of Object.entries(columns)) {
1130
+ if (!is(selected, Column) && !is(selected, SQL) && !is(selected, SQL.Aliased) && typeof selected === "object") {
1131
+ columnSchemas[key] = handleColumns(isTable(selected) || isView(selected) ? getColumns(selected) : selected, refinements[key] ?? {}, conditions, factory);
1132
+ continue;
1133
+ }
1134
+ const refinement = refinements[key];
1135
+ if (refinement !== void 0 && typeof refinement !== "function") {
1136
+ columnSchemas[key] = refinement;
1137
+ continue;
1138
+ }
1139
+ const column = is(selected, Column) ? selected : void 0;
1140
+ const schema = column ? columnToSchema(column, factory) : external_exports.any();
1141
+ const refined = typeof refinement === "function" ? refinement(schema) : schema;
1142
+ if (conditions.never(column)) continue;
1143
+ else columnSchemas[key] = refined;
1144
+ if (column) {
1145
+ if (conditions.nullable(column)) columnSchemas[key] = columnSchemas[key].nullable();
1146
+ if (conditions.optional(column)) columnSchemas[key] = columnSchemas[key].optional();
1147
+ }
1148
+ }
1149
+ return external_exports.object(columnSchemas);
1150
+ }
1151
+ function handleEnum(enum_, factory) {
1152
+ return (factory?.zodInstance ?? external_exports).enum(enum_.enumValues);
1153
+ }
1154
+ var selectConditions = {
1155
+ never: () => false,
1156
+ optional: () => false,
1157
+ nullable: (column) => !column.notNull
1158
+ };
1159
+ var createSelectSchema = (entity, refine) => {
1160
+ if (isWithEnum(entity)) return handleEnum(entity);
1161
+ return handleColumns(getColumns(entity), refine ?? {}, selectConditions);
1162
+ };
1163
+
1164
+ // src/service/platform/database/decode.ts
1165
+ function checkStored(schema, value, record) {
1166
+ const result = schema.safeParse(value);
1167
+ if (!result.success) {
1168
+ throw new Error(
1169
+ `Stored ${record} is malformed: ${external_exports.prettifyError(result.error)}`
1170
+ );
1171
+ }
1172
+ return result.data;
1173
+ }
1174
+ function decodeStored(schema, json, record) {
1175
+ let value;
1176
+ try {
1177
+ value = JSON.parse(json);
1178
+ } catch (error) {
1179
+ throw new Error(`Stored ${record} is not valid JSON`, { cause: error });
1180
+ }
1181
+ return checkStored(schema, value, record);
1182
+ }
1183
+
1184
+ // src/service/features/tasks/storage/stored.ts
1185
+ var eventRowSchema = createSelectSchema(events).omit({
1186
+ response_ref: true,
1187
+ original_response: true
1188
+ });
1189
+ var eventDataSchema = external_exports.record(external_exports.string(), external_exports.unknown());
1190
+ var sender = external_exports.enum(["user", "parent"]);
1191
+ var message = external_exports.looseObject({
1192
+ id: external_exports.string(),
1193
+ message: external_exports.string(),
1194
+ from: sender
1195
+ });
1196
+ var storedTaskSchema = external_exports.looseObject({
1197
+ id: external_exports.string().min(1),
1198
+ owner: external_exports.string().min(1),
1199
+ title: external_exports.string(),
1200
+ description: external_exports.string(),
1201
+ provider: external_exports.string(),
1202
+ provider_options: providerOptionsSchema.optional(),
1203
+ approval_mode: approvalModeSchema.optional(),
1204
+ worker_profile: external_exports.enum(roles),
1205
+ repository: external_exports.string(),
1206
+ revision: external_exports.string(),
1207
+ workspace_strategy: external_exports.enum(["worktree", "current_repo"]),
1208
+ no_git: external_exports.literal(true).optional(),
1209
+ workspace_fallback: external_exports.enum(["no_git", "no_commits"]).optional(),
1210
+ depends_on: external_exports.array(external_exports.string()),
1211
+ context: external_exports.array(external_exports.string()),
1212
+ budget: external_exports.looseObject({
1213
+ max_runtime_minutes: external_exports.number().nullable(),
1214
+ max_cost_usd: external_exports.number().nullable(),
1215
+ max_tokens: external_exports.number().optional()
1216
+ }),
1217
+ budget_raised_for_turn: external_exports.looseObject({
1218
+ turn: external_exports.number().int().nonnegative(),
1219
+ cost: external_exports.literal(true).optional(),
1220
+ runtime: external_exports.literal(true).optional()
1221
+ }).optional(),
1222
+ created_by: sender,
1223
+ status: external_exports.enum(statuses),
1224
+ created_at: external_exports.string(),
1225
+ updated_at: external_exports.string(),
1226
+ pending_input: external_exports.looseObject({
1227
+ id: external_exports.string(),
1228
+ tool: external_exports.string(),
1229
+ kind: external_exports.enum(["question", "permission"]),
1230
+ input: external_exports.record(external_exports.string(), external_exports.unknown())
1231
+ }).optional(),
1232
+ profile_instructions: external_exports.string().optional(),
1233
+ instructions: external_exports.array(message),
1234
+ instructions_sent: external_exports.number().int().nonnegative(),
1235
+ pending_steers: external_exports.array(message),
1236
+ queue: external_exports.array(
1237
+ message.extend({
1238
+ delivery: external_exports.enum(deliveries),
1239
+ recorded: external_exports.boolean().optional()
1240
+ })
1241
+ ),
1242
+ turn: external_exports.number().int().nonnegative(),
1243
+ runtime_ms: external_exports.number().nonnegative()
1244
+ });
1245
+ function decodeTask(id, body) {
1246
+ return decodeStored(storedTaskSchema, body, `task ${id}`);
1247
+ }
1248
+ function decodeEvent(row) {
1249
+ const stored = checkStored(eventRowSchema, row, `event ${row.id}`);
1250
+ const event = {
1251
+ ...stored,
1252
+ data: decodeStored(eventDataSchema, stored.data, `event ${stored.id}`)
1253
+ };
1254
+ return decodedEvent(event);
1255
+ }
1256
+
1257
+ // src/service/features/tasks/storage/chat-events.ts
1258
+ function chatEvents(orm, id, types) {
1259
+ const compaction = and(
1260
+ eq(events.type, "claude.activity"),
1261
+ // A plain text match first, so most activity skips parsing its JSON.
1262
+ sql`instr(${events.data}, 'compact') > 0`,
1263
+ sql`(json_extract(${events.data},'$.subtype')='compact_boundary' OR json_extract(${events.data},'$.compact_result')='failed')`
1264
+ );
1265
+ return orm.select(eventColumns).from(events).where(
1266
+ and(eq(events.task_id, id), or(inArray(events.type, types), compaction))
1267
+ ).orderBy(events.id).all().map(decodeEvent);
1268
+ }
1269
+
1270
+ // src/service/features/tasks/storage/event-storage-metrics.ts
1271
+ var EventStorageMetrics = class {
1272
+ active = /* @__PURE__ */ new Map();
1273
+ begin(taskId, turn) {
1274
+ const counters = {
1275
+ event_count: 0,
1276
+ json_bytes: 0,
1277
+ original_response_event_count: 0
1278
+ };
1279
+ this.active.set(taskId, counters);
1280
+ return (status) => {
1281
+ if (this.active.get(taskId) !== counters) return;
1282
+ this.active.delete(taskId);
1283
+ try {
1284
+ logEvent("info", "task.event_storage", {
1285
+ task_id: taskId,
1286
+ turn,
1287
+ status,
1288
+ ...counters
1289
+ });
1290
+ } catch {
1291
+ }
1292
+ };
1293
+ }
1294
+ committed(database, taskId, serialized, originalResponse) {
1295
+ const counters = this.active.get(taskId);
1296
+ if (!counters) return;
1297
+ const bytes = Buffer.byteLength(serialized, "utf8") + (originalResponse ? Buffer.byteLength(originalResponse, "utf8") : 0);
1298
+ database.afterCommit(() => {
1299
+ if (this.active.get(taskId) !== counters) return;
1300
+ counters.event_count++;
1301
+ counters.json_bytes += bytes;
1302
+ counters.original_response_event_count += Number(
1303
+ originalResponse !== void 0
1304
+ );
1305
+ });
1306
+ }
1307
+ };
1308
+
1309
+ // src/service/features/tasks/storage/publish-listeners.ts
1310
+ function publishListeners(bus, name, args) {
1311
+ for (const listener of bus.listeners(name)) {
1312
+ try {
1313
+ listener(...args);
1314
+ } catch (error) {
1315
+ logError("store.listener_failed", error, { listener: name });
1316
+ }
1317
+ }
1318
+ }
1319
+
1320
+ // src/service/features/tasks/storage/read-metrics.ts
1321
+ var WINDOW_MS = 6e4;
1322
+ var SLOW_MS = 50;
1323
+ var ReadMetrics = class {
1324
+ summaries = /* @__PURE__ */ new Map();
1325
+ timer;
1326
+ started = 0;
1327
+ measure(operation, run) {
1328
+ const started = performance.now();
1329
+ const work = { rows: 0, tally_rows: 0 };
1330
+ let outcome = "error";
1331
+ try {
1332
+ const result = run(work);
1333
+ outcome = "success";
1334
+ return result;
1335
+ } finally {
1336
+ const duration = performance.now() - started;
1337
+ try {
1338
+ logEvent("debug", "storage.read", {
1339
+ operation,
1340
+ duration_ms: duration,
1341
+ outcome,
1342
+ ...work
1343
+ });
1344
+ } catch {
1345
+ }
1346
+ const summary = this.summaries.get(operation) ?? {
1347
+ count: 0,
1348
+ total_ms: 0,
1349
+ max_ms: 0,
1350
+ rows: 0,
1351
+ tally_rows: 0,
1352
+ slow_count: 0,
1353
+ error_count: 0
1354
+ };
1355
+ summary.count++;
1356
+ summary.total_ms += duration;
1357
+ summary.max_ms = Math.max(summary.max_ms, duration);
1358
+ summary.rows += work.rows;
1359
+ summary.tally_rows += work.tally_rows;
1360
+ summary.slow_count += Number(duration >= SLOW_MS);
1361
+ summary.error_count += Number(outcome === "error");
1362
+ this.summaries.set(operation, summary);
1363
+ if (!this.timer) {
1364
+ this.started = performance.now();
1365
+ this.timer = setTimeout(() => this.flush(), WINDOW_MS);
1366
+ this.timer.unref();
1367
+ }
1368
+ }
1369
+ }
1370
+ rows(operation, run) {
1371
+ return this.measure(operation, (work) => {
1372
+ const rows = run();
1373
+ work.rows = rows.length;
1374
+ return rows;
1375
+ });
1376
+ }
1377
+ flush() {
1378
+ clearTimeout(this.timer);
1379
+ this.timer = void 0;
1380
+ try {
1381
+ withLogContext(
1382
+ {},
1383
+ () => {
1384
+ for (const [operation, summary] of this.summaries) {
1385
+ logEvent("info", "storage.read_summary", {
1386
+ operation,
1387
+ ...summary,
1388
+ window_ms: performance.now() - this.started,
1389
+ slow_threshold_ms: SLOW_MS
1390
+ });
1391
+ }
1392
+ },
1393
+ { inherit: false }
1394
+ );
1395
+ } catch {
1396
+ } finally {
1397
+ this.summaries.clear();
1398
+ }
1399
+ }
1400
+ };
1401
+
1402
+ // src/service/features/tasks/storage/store.ts
1403
+ var PAGE = 1e3;
1404
+ var toTask = (row) => decodeTask(row.id, row.body);
1405
+ var Store = class {
1406
+ /** The shared connection, which other features' storage also uses. */
1407
+ database;
1408
+ reads = new ReadMetrics();
1409
+ eventStorage = new EventStorageMetrics();
1410
+ /** The tasks saved in the open transaction, with the `updated_at` to restore on rollback. */
1411
+ saved;
1412
+ /** The owners whose tasks the open transaction changed. */
1413
+ changed;
1414
+ /** Distinguishes this process's revisions from a restarted service's. */
1415
+ bootId = randomUUID();
1416
+ revisions = /* @__PURE__ */ new Map();
1417
+ projectRevision = 0;
1418
+ // Long-poll reads each listen while they wait, so there can be many.
1419
+ bus = new EventEmitter().setMaxListeners(0);
1420
+ constructor(path) {
1421
+ this.database = openDatabase(path);
1422
+ }
1423
+ beginEventStorage(taskId, turn) {
1424
+ return this.eventStorage.begin(taskId, turn);
1425
+ }
1426
+ get orm() {
1427
+ return this.database.orm;
1428
+ }
1429
+ /**
1430
+ * Runs `fn` in one transaction, so the task state and events it writes
1431
+ * commit together. Listeners hear its events only after the commit; on a
1432
+ * rollback they hear nothing, and saved tasks get back their `updated_at`.
1433
+ */
1434
+ transaction(fn) {
1435
+ if (this.saved) {
1436
+ throw new Error("A transaction is already open; run this work inside it");
1437
+ }
1438
+ const saved = [];
1439
+ this.saved = saved;
1440
+ this.changed = /* @__PURE__ */ new Set();
1441
+ try {
1442
+ return this.database.transaction(() => {
1443
+ try {
1444
+ return fn();
1445
+ } finally {
1446
+ this.saved = void 0;
1447
+ this.changed = void 0;
1448
+ }
1449
+ });
1450
+ } catch (error) {
1451
+ for (const [t, updated] of saved.reverse()) t.updated_at = updated;
1452
+ throw error;
1453
+ }
1454
+ }
1455
+ save(t) {
1456
+ const updated = t.updated_at;
1457
+ t.updated_at = now();
1458
+ const body = JSON.stringify(t);
1459
+ try {
1460
+ this.orm.insert(tasks).values({ id: t.id, owner: t.owner, body }).onConflictDoUpdate({ target: tasks.id, set: { body } }).run();
1461
+ } catch (error) {
1462
+ t.updated_at = updated;
1463
+ throw error;
1464
+ }
1465
+ this.saved?.push([t, updated]);
1466
+ this.markChanged(t.owner);
1467
+ }
1468
+ /**
1469
+ * Deletes a task. Its events and pending forms
1470
+ * reference it and are deleted with it, and the service's database returns
1471
+ * their space to the file system.
1472
+ */
1473
+ delete(id, owner) {
1474
+ this.get(id, owner);
1475
+ this.orm.delete(tasks).where(and(eq(tasks.id, id), eq(tasks.owner, owner))).run();
1476
+ this.database.client.exec("PRAGMA incremental_vacuum");
1477
+ this.markChanged(owner);
1478
+ }
1479
+ /**
1480
+ * Announces `change` for an owner once the open transaction commits, once
1481
+ * per transaction however many writes it holds; at once outside one.
1482
+ * Other task storage built on this connection announces its writes here.
1483
+ */
1484
+ markChanged(owner) {
1485
+ const changed = this.changed;
1486
+ if (!changed) {
1487
+ this.announce([owner]);
1488
+ return;
1489
+ }
1490
+ if (!changed.size) this.database.afterCommit(() => this.announce(changed));
1491
+ changed.add(owner);
1492
+ }
1493
+ announce(owners) {
1494
+ for (const owner of owners) {
1495
+ this.revisions.set(owner, (this.revisions.get(owner) ?? 0) + 1);
1496
+ this.publish("change", owner);
1497
+ }
1498
+ }
1499
+ /** Announces a change to the project list, which every owner shares. */
1500
+ projectsChanged() {
1501
+ this.projectRevision++;
1502
+ this.publish("change", void 0);
1503
+ }
1504
+ /**
1505
+ * An opaque token for the state of an owner's tasks and the project list.
1506
+ * It differs whenever either has changed, including across a restart, so
1507
+ * clients compare it only for equality.
1508
+ */
1509
+ revision(owner) {
1510
+ const count = (this.revisions.get(owner) ?? 0) + this.projectRevision;
1511
+ return `${this.bootId}:${count}`;
1512
+ }
1513
+ /** An owner's tasks, or every task without one, newest first. */
1514
+ all(owner) {
1515
+ return this.reads.rows(
1516
+ "task_list",
1517
+ () => this.orm.select({ id: tasks.id, body: tasks.body }).from(tasks).where(owner ? eq(tasks.owner, owner) : void 0).all().map(toTask).sort((a, b) => b.created_at.localeCompare(a.created_at))
1518
+ );
1519
+ }
1520
+ get(id, owner) {
1521
+ const task = this.find(id, owner);
1522
+ if (!task) throw new Error("Task not found");
1523
+ return task;
1524
+ }
1525
+ /** An owner's task, or undefined when it has none with this id. */
1526
+ find(id, owner) {
1527
+ const row = this.orm.select({ id: tasks.id, body: tasks.body }).from(tasks).where(and(eq(tasks.id, id), eq(tasks.owner, owner))).get();
1528
+ return row && toTask(row);
1529
+ }
1530
+ event(t, type, ...args) {
1531
+ const data = args[0] ?? {};
1532
+ return this.writeEvent(t, type, data);
1533
+ }
1534
+ /** Records a provider-owned event through the explicit opaque extension path. */
1535
+ eventOpaque(t, type, data = {}) {
1536
+ return this.writeEvent(t, type, data);
1537
+ }
1538
+ writeEvent(t, type, data) {
1539
+ const event = insertEvent(
1540
+ this.database,
1541
+ this.eventStorage,
1542
+ t.id,
1543
+ type,
1544
+ data
1545
+ );
1546
+ this.database.afterCommit(() => this.publish("event", event, t.owner));
1547
+ this.markChanged(t.owner);
1548
+ return event;
1549
+ }
1550
+ /** Isolate listener failures after commit so consumers can still catch up. */
1551
+ publish(name, ...args) {
1552
+ publishListeners(this.bus, name, args);
1553
+ }
1554
+ events(id, owner, after = 0) {
1555
+ this.get(id, owner);
1556
+ return this.orm.select(eventColumns).from(events).where(and(eq(events.task_id, id), gt(events.id, after))).orderBy(events.id).limit(PAGE).all().map(decodeEvent);
1557
+ }
1558
+ /** Resolves an original response after checking task ownership. */
1559
+ originalResponse(id, owner, responseRef) {
1560
+ this.get(id, owner);
1561
+ return readOriginalResponse(this.database, id, responseRef);
1562
+ }
1563
+ /**
1564
+ * The id of a task's event `depth` places from its newest, so the newest
1565
+ * `depth` events are those from it on; 0 when there are fewer than that.
1566
+ * `depth` is at least 1: the query offsets by `depth - 1`.
1567
+ */
1568
+ eventWindowStart(id, depth) {
1569
+ return this.orm.select({ id: events.id }).from(events).where(eq(events.task_id, id)).orderBy(desc(events.id)).limit(1).offset(depth - 1).get()?.id ?? 0;
1570
+ }
1571
+ /**
1572
+ * The id of the `depth`th newest of a task's events after `after` and
1573
+ * through `through`, so those events from it on are the newest `depth`;
1574
+ * `after + 1` when there are fewer than that.
1575
+ */
1576
+ rangeWindowStart(id, after, through, depth) {
1577
+ return this.orm.select({ id: events.id }).from(events).where(
1578
+ and(
1579
+ eq(events.task_id, id),
1580
+ gt(events.id, after),
1581
+ lte(events.id, through)
1582
+ )
1583
+ ).orderBy(desc(events.id)).limit(1).offset(depth - 1).get()?.id ?? after + 1;
1584
+ }
1585
+ /**
1586
+ * What the owner has read of a task: whether it has a reply, outcome or
1587
+ * request they haven't read, and the newest event they had read.
1588
+ */
1589
+ readState(id) {
1590
+ const mark = this.orm.select({ through: taskRead.through, unread: taskRead.unread }).from(taskRead).where(eq(taskRead.task_id, id)).get();
1591
+ const latest = this.orm.select({ id: max(events.id) }).from(events).where(and(eq(events.task_id, id), inArray(events.type, READ_EVENTS))).get();
1592
+ return {
1593
+ unread: isUnread(latest?.id ?? 0, mark),
1594
+ through: mark?.through ?? 0
1595
+ };
1596
+ }
1597
+ /**
1598
+ * Records that the owner has read a task through event `through`, or its
1599
+ * newest event without one. It never moves back, never passes the newest
1600
+ * event and clears the task's unread mark.
1601
+ */
1602
+ markRead(t, through) {
1603
+ const newest = this.lastEventId(t.id);
1604
+ const read = Math.min(through ?? newest, newest);
1605
+ this.orm.insert(taskRead).values({ task_id: t.id, through: read, unread: false }).onConflictDoUpdate({
1606
+ target: taskRead.task_id,
1607
+ set: { through: sql`max(${taskRead.through}, ${read})`, unread: false }
1608
+ }).run();
1609
+ this.markChanged(t.owner);
1610
+ }
1611
+ /** Marks a task unread from event `from` on; unlike `markRead`, it can move the read point back. */
1612
+ markUnreadFrom(t, from) {
1613
+ const through = Math.min(from - 1, this.lastEventId(t.id));
1614
+ const mark = { through, unread: false };
1615
+ this.orm.insert(taskRead).values({ task_id: t.id, ...mark }).onConflictDoUpdate({ target: taskRead.task_id, set: mark }).run();
1616
+ this.markChanged(t.owner);
1617
+ }
1618
+ /** Marks a task unread until the owner next sees it. */
1619
+ markUnread(t) {
1620
+ this.orm.insert(taskRead).values({ task_id: t.id, through: 0, unread: true }).onConflictDoUpdate({ target: taskRead.task_id, set: { unread: true } }).run();
1621
+ this.markChanged(t.owner);
1622
+ }
1623
+ /** The id of a task's `task.turn_ended` event for a turn; absent until it ends. */
1624
+ turnEnded(id, turn) {
1625
+ return this.orm.select({ id: events.id }).from(events).where(
1626
+ and(
1627
+ eq(events.task_id, id),
1628
+ eq(events.type, "task.turn_ended"),
1629
+ eq(sql`json_extract(${events.data}, '$.turn')`, turn)
1630
+ )
1631
+ ).orderBy(events.id).limit(1).get()?.id;
1632
+ }
1633
+ /** A task's first event after `after` with one of `types`. */
1634
+ nextEventOfType(id, after, types) {
1635
+ return this.orm.select({ id: events.id, type: events.type }).from(events).where(
1636
+ and(
1637
+ eq(events.task_id, id),
1638
+ gt(events.id, after),
1639
+ inArray(events.type, types)
1640
+ )
1641
+ ).orderBy(events.id).limit(1).get();
1642
+ }
1643
+ /**
1644
+ * A task's events after `after`, and before `before` when given, a page at a
1645
+ * time. Internal: callers check the task's owner first.
1646
+ */
1647
+ taskEvents(id, after, before) {
1648
+ return this.orm.select(eventColumns).from(events).where(
1649
+ and(
1650
+ eq(events.task_id, id),
1651
+ gt(events.id, after),
1652
+ before === void 0 ? void 0 : lt(events.id, before)
1653
+ )
1654
+ ).orderBy(events.id).limit(PAGE).all().map(decodeEvent);
1655
+ }
1656
+ recentEvents(id, owner) {
1657
+ this.get(id, owner);
1658
+ return this.orm.select(eventColumns).from(events).where(eq(events.task_id, id)).orderBy(desc(events.id)).limit(200).all().reverse().map(decodeEvent);
1659
+ }
1660
+ /** The id of the latest event, or of a task's latest one; 0 before any. */
1661
+ lastEventId(id) {
1662
+ const row = this.orm.select({ id: max(events.id) }).from(events).where(id === void 0 ? void 0 : eq(events.task_id, id)).get();
1663
+ return row?.id ?? 0;
1664
+ }
1665
+ /** A task's latest event of a type, such as its latest `agent.reply`. */
1666
+ latestEvent(id, type) {
1667
+ const row = this.orm.select(eventColumns).from(events).where(and(eq(events.task_id, id), eq(events.type, type))).orderBy(desc(events.id)).limit(1).get();
1668
+ return row && decodeEvent(row);
1669
+ }
1670
+ /** Every event of the given types for a task, in order, with no page limit. */
1671
+ eventsOfTypes(id, types) {
1672
+ return this.orm.select(eventColumns).from(events).where(and(eq(events.task_id, id), inArray(events.type, types))).orderBy(events.id).all().map(decodeEvent);
1673
+ }
1674
+ /**
1675
+ * The events Chat is built from: those of the given types, and context
1676
+ * compactions, which Claude reports among its other system messages.
1677
+ */
1678
+ chatEvents(id, types) {
1679
+ return this.reads.rows("chat", () => chatEvents(this.orm, id, types));
1680
+ }
1681
+ close() {
1682
+ this.reads.flush();
1683
+ this.database.close();
1684
+ }
1685
+ };
1686
+
1687
+ export {
1688
+ now,
1689
+ createSelectSchema,
1690
+ checkStored,
1691
+ decodeStored,
1692
+ tasks,
1693
+ events,
1694
+ parentSeen,
1695
+ taskArchive,
1696
+ sendReceipts,
1697
+ eventColumns,
1698
+ decodeEvent,
1699
+ useIncrementalVacuum,
1700
+ Store
1701
+ };
1702
+ //# sourceMappingURL=chunk-ZSLXLKU2.js.map