@yugenlab/vaayu 0.1.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 (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +365 -0
  3. package/chunks/chunk-E5A3SCDJ.js +246 -0
  4. package/chunks/chunk-G5VYCA6O.js +69 -0
  5. package/chunks/chunk-H76V36OF.js +1029 -0
  6. package/chunks/chunk-HAPVUJ6A.js +238 -0
  7. package/chunks/chunk-IEKAYVA3.js +137 -0
  8. package/chunks/chunk-IGKYKEKT.js +43 -0
  9. package/chunks/chunk-IIET2K6D.js +7728 -0
  10. package/chunks/chunk-ITIVYGUG.js +347 -0
  11. package/chunks/chunk-JAWZ7ANC.js +208 -0
  12. package/chunks/chunk-JZU37VQ5.js +714 -0
  13. package/chunks/chunk-KC6NRZ7U.js +198 -0
  14. package/chunks/chunk-KDRROLVN.js +433 -0
  15. package/chunks/chunk-L7JICQBW.js +1006 -0
  16. package/chunks/chunk-MINFB5LT.js +1479 -0
  17. package/chunks/chunk-MJ74G5RB.js +5816 -0
  18. package/chunks/chunk-S4TBVCL2.js +2158 -0
  19. package/chunks/chunk-SMVJRPAH.js +2753 -0
  20. package/chunks/chunk-U6OLJ36B.js +438 -0
  21. package/chunks/chunk-URGEODS5.js +752 -0
  22. package/chunks/chunk-YSU3BWV6.js +123 -0
  23. package/chunks/consolidation-indexer-TOTTDZXW.js +21 -0
  24. package/chunks/day-consolidation-NKO63HZQ.js +24 -0
  25. package/chunks/graphrag-ZI2FSU7S.js +13 -0
  26. package/chunks/hierarchical-temporal-search-ZD46UMKR.js +8 -0
  27. package/chunks/hybrid-search-ZVLZVGFS.js +19 -0
  28. package/chunks/memory-store-KNJPMBLQ.js +17 -0
  29. package/chunks/periodic-consolidation-BPKOZDGB.js +10 -0
  30. package/chunks/postgres-3ZXBYTPC.js +8 -0
  31. package/chunks/recall-GMVHWQWW.js +20 -0
  32. package/chunks/search-7HZETVMZ.js +18 -0
  33. package/chunks/session-store-XKPGKXUS.js +44 -0
  34. package/chunks/sqlite-JPF5TICX.js +152 -0
  35. package/chunks/src-6GVZTUH6.js +12 -0
  36. package/chunks/src-QAXOD5SB.js +273 -0
  37. package/chunks/suncalc-NOHGYHDU.js +186 -0
  38. package/chunks/tree-RSHKDTCR.js +10 -0
  39. package/gateway.js +61944 -0
  40. package/package.json +51 -0
  41. package/pair-cli.js +133 -0
@@ -0,0 +1,2753 @@
1
+ // packages/storage/src/sqlite/connection.ts
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { createRequire } from "node:module";
5
+ function createConnection(dbPath) {
6
+ const dir = path.dirname(dbPath);
7
+ fs.mkdirSync(dir, { recursive: true });
8
+ const require3 = createRequire(import.meta.url);
9
+ const Database = require3("better-sqlite3");
10
+ const db = new Database(dbPath);
11
+ db.exec("PRAGMA journal_mode=WAL;");
12
+ return db;
13
+ }
14
+
15
+ // packages/storage/src/sqlite/schema-agent.ts
16
+ function initAgentSchema(db) {
17
+ db.exec(`
18
+ CREATE TABLE IF NOT EXISTS session_inbox (
19
+ id TEXT PRIMARY KEY,
20
+ session_id TEXT NOT NULL,
21
+ status TEXT,
22
+ created_at TEXT,
23
+ started_at TEXT,
24
+ ended_at TEXT,
25
+ channel TEXT,
26
+ chat_id TEXT,
27
+ user_id TEXT,
28
+ text TEXT,
29
+ metadata TEXT,
30
+ error TEXT
31
+ )
32
+ `);
33
+ db.exec(`CREATE INDEX IF NOT EXISTS session_inbox_session_idx ON session_inbox(session_id, created_at)`);
34
+ db.exec(`CREATE INDEX IF NOT EXISTS session_inbox_status_idx ON session_inbox(status, created_at)`);
35
+ db.exec(`
36
+ CREATE TABLE IF NOT EXISTS agent_queue (
37
+ id TEXT PRIMARY KEY,
38
+ session_id TEXT,
39
+ agent_id TEXT,
40
+ parent_agent_id TEXT,
41
+ parent_run_id TEXT,
42
+ lane TEXT,
43
+ status TEXT,
44
+ created_at TEXT,
45
+ started_at TEXT,
46
+ ended_at TEXT,
47
+ lease_until TEXT,
48
+ priority INTEGER,
49
+ channel TEXT,
50
+ chat_id TEXT,
51
+ user_id TEXT,
52
+ provider_id TEXT,
53
+ model TEXT,
54
+ system TEXT,
55
+ text TEXT,
56
+ timeout_ms INTEGER,
57
+ tool_policy TEXT,
58
+ metadata TEXT,
59
+ error TEXT
60
+ )
61
+ `);
62
+ db.exec(`CREATE INDEX IF NOT EXISTS agent_queue_status_idx ON agent_queue(status, created_at)`);
63
+ db.exec(`CREATE INDEX IF NOT EXISTS agent_queue_lane_idx ON agent_queue(lane, created_at)`);
64
+ db.exec(`CREATE INDEX IF NOT EXISTS agent_queue_session_idx ON agent_queue(session_id, created_at)`);
65
+ try {
66
+ db.exec(`ALTER TABLE agent_queue ADD COLUMN lease_until TEXT`);
67
+ } catch {
68
+ }
69
+ try {
70
+ db.exec(`ALTER TABLE agent_queue ADD COLUMN agent_id TEXT`);
71
+ } catch {
72
+ }
73
+ try {
74
+ db.exec(`ALTER TABLE agent_queue ADD COLUMN parent_agent_id TEXT`);
75
+ } catch {
76
+ }
77
+ db.exec(`
78
+ CREATE TABLE IF NOT EXISTS agent_runs (
79
+ id TEXT PRIMARY KEY,
80
+ session_id TEXT,
81
+ agent_id TEXT,
82
+ parent_agent_id TEXT,
83
+ parent_run_id TEXT,
84
+ lane TEXT,
85
+ status TEXT,
86
+ created_at TEXT,
87
+ started_at TEXT,
88
+ ended_at TEXT,
89
+ timeout_ms INTEGER,
90
+ channel TEXT,
91
+ chat_id TEXT,
92
+ user_id TEXT,
93
+ provider_id TEXT,
94
+ model TEXT,
95
+ system TEXT,
96
+ text TEXT,
97
+ metadata TEXT,
98
+ metrics TEXT,
99
+ result_summary TEXT,
100
+ error TEXT
101
+ )
102
+ `);
103
+ db.exec(`CREATE INDEX IF NOT EXISTS agent_runs_status_idx ON agent_runs(status, created_at)`);
104
+ db.exec(`CREATE INDEX IF NOT EXISTS agent_runs_session_idx ON agent_runs(session_id, created_at)`);
105
+ db.exec(`CREATE INDEX IF NOT EXISTS agent_runs_lane_idx ON agent_runs(lane, created_at)`);
106
+ try {
107
+ db.exec(`ALTER TABLE agent_runs ADD COLUMN agent_id TEXT`);
108
+ } catch {
109
+ }
110
+ try {
111
+ db.exec(`ALTER TABLE agent_runs ADD COLUMN parent_agent_id TEXT`);
112
+ } catch {
113
+ }
114
+ db.exec(`
115
+ CREATE TABLE IF NOT EXISTS session_routes (
116
+ session_id TEXT PRIMARY KEY,
117
+ agent_id TEXT,
118
+ lane_id TEXT,
119
+ queue_mode TEXT,
120
+ announce_mode TEXT,
121
+ updated_at TEXT
122
+ )
123
+ `);
124
+ db.exec(`CREATE INDEX IF NOT EXISTS session_routes_updated_idx ON session_routes(updated_at)`);
125
+ db.exec(`
126
+ CREATE TABLE IF NOT EXISTS agent_run_events (
127
+ id TEXT PRIMARY KEY,
128
+ run_id TEXT,
129
+ time TEXT,
130
+ type TEXT,
131
+ payload TEXT
132
+ )
133
+ `);
134
+ db.exec(`CREATE INDEX IF NOT EXISTS agent_run_events_run_idx ON agent_run_events(run_id, time)`);
135
+ }
136
+
137
+ // packages/storage/src/sqlite/schema/utils.ts
138
+ import { createRequire as createRequire2 } from "node:module";
139
+ var require2 = createRequire2(import.meta.url);
140
+ function initVectorExtension(db) {
141
+ try {
142
+ const sqliteVec = require2("sqlite-vec");
143
+ sqliteVec.load(db);
144
+ return true;
145
+ } catch {
146
+ return false;
147
+ }
148
+ }
149
+ function hasColumn(db, table, column) {
150
+ const rows = db.prepare(`PRAGMA table_info(${table})`).all();
151
+ return rows.some((row) => String(row.name) === column);
152
+ }
153
+ function ensureColumn(db, table, column, definition) {
154
+ if (hasColumn(db, table, column)) return;
155
+ db.exec(`ALTER TABLE ${table} ADD COLUMN ${definition}`);
156
+ }
157
+
158
+ // packages/storage/src/sqlite/schema/core.ts
159
+ function initCoreSchema(db) {
160
+ db.exec(`
161
+ CREATE TABLE IF NOT EXISTS sessions (
162
+ id TEXT PRIMARY KEY,
163
+ key TEXT UNIQUE,
164
+ created_at TEXT,
165
+ updated_at TEXT,
166
+ user_id TEXT,
167
+ channel TEXT,
168
+ chat_type TEXT,
169
+ chat_id TEXT,
170
+ peer_id TEXT,
171
+ account_id TEXT,
172
+ thread_id TEXT,
173
+ label TEXT,
174
+ current_provider TEXT,
175
+ current_model TEXT,
176
+ providers_used TEXT,
177
+ provider_switches INTEGER
178
+ )
179
+ `);
180
+ ensureColumn(db, "sessions", "user_id", "user_id TEXT");
181
+ ensureColumn(db, "sessions", "current_provider", "current_provider TEXT");
182
+ ensureColumn(db, "sessions", "current_model", "current_model TEXT");
183
+ ensureColumn(db, "sessions", "providers_used", "providers_used TEXT");
184
+ ensureColumn(db, "sessions", "provider_switches", "provider_switches INTEGER");
185
+ db.exec(`
186
+ CREATE TABLE IF NOT EXISTS session_events (
187
+ id TEXT PRIMARY KEY,
188
+ session_id TEXT,
189
+ role TEXT,
190
+ content TEXT,
191
+ metadata TEXT,
192
+ created_at TEXT
193
+ )
194
+ `);
195
+ db.exec(
196
+ `CREATE INDEX IF NOT EXISTS session_events_session_idx ON session_events(session_id, created_at)`
197
+ );
198
+ db.exec(`
199
+ CREATE TABLE IF NOT EXISTS session_summaries (
200
+ session_id TEXT PRIMARY KEY,
201
+ summary TEXT,
202
+ event_count INTEGER,
203
+ updated_at TEXT
204
+ )
205
+ `);
206
+ db.exec(`
207
+ CREATE TABLE IF NOT EXISTS session_prefs (
208
+ session_id TEXT PRIMARY KEY,
209
+ provider_id TEXT,
210
+ model TEXT,
211
+ system TEXT,
212
+ auto_routing INTEGER,
213
+ language TEXT,
214
+ language_updated_at TEXT,
215
+ continuity_preferred_device_id TEXT,
216
+ continuity_mode TEXT,
217
+ proactive_allowed INTEGER,
218
+ proactive_observe INTEGER,
219
+ proactive_deliver INTEGER,
220
+ proactive_allowed_channels TEXT,
221
+ proactive_paused_until TEXT,
222
+ proactive_max_per_day INTEGER,
223
+ proactive_cooldown_ms INTEGER,
224
+ proactive_delivered_day TEXT,
225
+ proactive_delivered_count INTEGER,
226
+ proactive_last_delivered_at TEXT,
227
+ updated_at TEXT
228
+ )
229
+ `);
230
+ ensureColumn(db, "session_prefs", "language", "language TEXT");
231
+ ensureColumn(db, "session_prefs", "language_updated_at", "language_updated_at TEXT");
232
+ ensureColumn(
233
+ db,
234
+ "session_prefs",
235
+ "continuity_preferred_device_id",
236
+ "continuity_preferred_device_id TEXT"
237
+ );
238
+ ensureColumn(db, "session_prefs", "continuity_mode", "continuity_mode TEXT");
239
+ ensureColumn(db, "session_prefs", "proactive_allowed", "proactive_allowed INTEGER");
240
+ ensureColumn(db, "session_prefs", "proactive_observe", "proactive_observe INTEGER");
241
+ ensureColumn(db, "session_prefs", "proactive_deliver", "proactive_deliver INTEGER");
242
+ ensureColumn(
243
+ db,
244
+ "session_prefs",
245
+ "proactive_allowed_channels",
246
+ "proactive_allowed_channels TEXT"
247
+ );
248
+ ensureColumn(db, "session_prefs", "proactive_paused_until", "proactive_paused_until TEXT");
249
+ ensureColumn(db, "session_prefs", "proactive_max_per_day", "proactive_max_per_day INTEGER");
250
+ ensureColumn(db, "session_prefs", "proactive_cooldown_ms", "proactive_cooldown_ms INTEGER");
251
+ ensureColumn(db, "session_prefs", "proactive_delivered_day", "proactive_delivered_day TEXT");
252
+ ensureColumn(
253
+ db,
254
+ "session_prefs",
255
+ "proactive_delivered_count",
256
+ "proactive_delivered_count INTEGER"
257
+ );
258
+ ensureColumn(
259
+ db,
260
+ "session_prefs",
261
+ "proactive_last_delivered_at",
262
+ "proactive_last_delivered_at TEXT"
263
+ );
264
+ db.exec(`
265
+ CREATE TABLE IF NOT EXISTS session_providers (
266
+ session_id TEXT NOT NULL,
267
+ provider_id TEXT NOT NULL,
268
+ model TEXT,
269
+ first_used_at TEXT,
270
+ last_used_at TEXT,
271
+ usage_count INTEGER,
272
+ PRIMARY KEY (session_id, provider_id)
273
+ )
274
+ `);
275
+ db.exec(
276
+ `CREATE INDEX IF NOT EXISTS session_providers_last_idx ON session_providers(last_used_at)`
277
+ );
278
+ db.exec(`
279
+ CREATE TABLE IF NOT EXISTS provider_switches (
280
+ id TEXT PRIMARY KEY,
281
+ session_id TEXT,
282
+ from_provider_id TEXT,
283
+ to_provider_id TEXT,
284
+ from_model TEXT,
285
+ to_model TEXT,
286
+ reason TEXT,
287
+ created_at TEXT
288
+ )
289
+ `);
290
+ db.exec(
291
+ `CREATE INDEX IF NOT EXISTS provider_switches_session_idx ON provider_switches(session_id, created_at)`
292
+ );
293
+ db.exec(`
294
+ CREATE TABLE IF NOT EXISTS devices (
295
+ id TEXT PRIMARY KEY,
296
+ name TEXT,
297
+ type TEXT,
298
+ role TEXT,
299
+ caps TEXT,
300
+ status TEXT,
301
+ scopes TEXT,
302
+ auth_type TEXT,
303
+ token_hash TEXT UNIQUE,
304
+ token_hint TEXT,
305
+ public_key TEXT,
306
+ public_key_alg TEXT,
307
+ created_at TEXT,
308
+ updated_at TEXT,
309
+ last_seen_at TEXT
310
+ )
311
+ `);
312
+ db.exec(`
313
+ CREATE TABLE IF NOT EXISTS channel_allows (
314
+ id TEXT PRIMARY KEY,
315
+ channel TEXT,
316
+ chat_id TEXT,
317
+ user_id TEXT,
318
+ status TEXT,
319
+ note TEXT,
320
+ created_at TEXT,
321
+ updated_at TEXT
322
+ )
323
+ `);
324
+ db.exec(
325
+ `CREATE UNIQUE INDEX IF NOT EXISTS channel_allows_key ON channel_allows(channel, chat_id, user_id)`
326
+ );
327
+ db.exec(`
328
+ CREATE TABLE IF NOT EXISTS approval_requests (
329
+ id TEXT PRIMARY KEY,
330
+ status TEXT,
331
+ kind TEXT,
332
+ tool_name TEXT,
333
+ tool_input TEXT,
334
+ session_id TEXT,
335
+ channel TEXT,
336
+ chat_id TEXT,
337
+ user_id TEXT,
338
+ user_text TEXT,
339
+ risk TEXT,
340
+ reason TEXT,
341
+ created_at TEXT,
342
+ updated_at TEXT,
343
+ expires_at TEXT,
344
+ decided_at TEXT,
345
+ decided_by TEXT,
346
+ result TEXT
347
+ )
348
+ `);
349
+ db.exec(
350
+ `CREATE INDEX IF NOT EXISTS approval_requests_status_idx ON approval_requests(status, created_at)`
351
+ );
352
+ db.exec(`
353
+ CREATE TABLE IF NOT EXISTS audit (
354
+ id TEXT PRIMARY KEY,
355
+ time TEXT,
356
+ type TEXT,
357
+ payload TEXT
358
+ )
359
+ `);
360
+ db.exec(`
361
+ CREATE TABLE IF NOT EXISTS tool_policy (
362
+ id TEXT PRIMARY KEY,
363
+ allow TEXT,
364
+ deny TEXT,
365
+ updated_at TEXT
366
+ )
367
+ `);
368
+ db.exec(`
369
+ CREATE TABLE IF NOT EXISTS device_sync_state (
370
+ id TEXT PRIMARY KEY,
371
+ device_id TEXT NOT NULL UNIQUE,
372
+ user_id TEXT NOT NULL,
373
+ last_sync_at INTEGER,
374
+ pending_changes INTEGER DEFAULT 0,
375
+ created_at TEXT NOT NULL,
376
+ updated_at TEXT NOT NULL
377
+ )
378
+ `);
379
+ db.exec(`CREATE INDEX IF NOT EXISTS device_sync_state_user_idx ON device_sync_state(user_id)`);
380
+ db.exec(`
381
+ CREATE TABLE IF NOT EXISTS token_usage (
382
+ id TEXT PRIMARY KEY,
383
+ session_id TEXT,
384
+ provider_id TEXT,
385
+ model TEXT,
386
+ input_tokens INTEGER,
387
+ output_tokens INTEGER,
388
+ total_tokens INTEGER,
389
+ cost_micro INTEGER,
390
+ source TEXT,
391
+ created_at TEXT
392
+ )
393
+ `);
394
+ db.exec(
395
+ `CREATE INDEX IF NOT EXISTS token_usage_session_idx ON token_usage(session_id, created_at)`
396
+ );
397
+ db.exec(
398
+ `CREATE INDEX IF NOT EXISTS token_usage_provider_idx ON token_usage(provider_id, created_at)`
399
+ );
400
+ db.exec(`
401
+ CREATE TABLE IF NOT EXISTS message_reactions (
402
+ id TEXT PRIMARY KEY,
403
+ session_id TEXT NOT NULL,
404
+ message_id TEXT NOT NULL,
405
+ reaction TEXT NOT NULL,
406
+ created_at TEXT NOT NULL
407
+ )
408
+ `);
409
+ db.exec(
410
+ `CREATE INDEX IF NOT EXISTS message_reactions_session_idx ON message_reactions(session_id)`
411
+ );
412
+ db.exec(
413
+ `CREATE UNIQUE INDEX IF NOT EXISTS message_reactions_message_idx ON message_reactions(message_id)`
414
+ );
415
+ }
416
+
417
+ // packages/storage/src/sqlite/schema/fts.ts
418
+ function initFtsSchema(db) {
419
+ try {
420
+ db.exec(`
421
+ CREATE VIRTUAL TABLE IF NOT EXISTS memory_messages_fts USING fts5(
422
+ content,
423
+ content_rowid='id',
424
+ tokenize='porter unicode61'
425
+ )
426
+ `);
427
+ } catch {
428
+ }
429
+ try {
430
+ db.exec(`
431
+ CREATE VIRTUAL TABLE IF NOT EXISTS knowledge_base_fts USING fts5(
432
+ fact,
433
+ content_rowid='id',
434
+ tokenize='porter unicode61'
435
+ )
436
+ `);
437
+ } catch {
438
+ }
439
+ }
440
+
441
+ // packages/storage/src/sqlite/schema/memory.ts
442
+ function initMemorySchema(db) {
443
+ db.exec(`
444
+ CREATE TABLE IF NOT EXISTS memory_sessions (
445
+ id TEXT PRIMARY KEY,
446
+ user_id TEXT NOT NULL,
447
+ started_at INTEGER NOT NULL,
448
+ ended_at INTEGER,
449
+ topic TEXT,
450
+ message_count INTEGER DEFAULT 0,
451
+ summary TEXT,
452
+ key_entities TEXT,
453
+ importance_score REAL DEFAULT 0.5,
454
+ tier INTEGER DEFAULT 1,
455
+ archived INTEGER DEFAULT 0,
456
+ created_at TEXT,
457
+ updated_at TEXT
458
+ )
459
+ `);
460
+ db.exec(
461
+ `CREATE INDEX IF NOT EXISTS memory_sessions_user_tier_idx ON memory_sessions(user_id, tier, started_at)`
462
+ );
463
+ db.exec(
464
+ `CREATE INDEX IF NOT EXISTS memory_sessions_tier_age_idx ON memory_sessions(tier, started_at)`
465
+ );
466
+ db.exec(`
467
+ CREATE TABLE IF NOT EXISTS memory_messages (
468
+ id TEXT PRIMARY KEY,
469
+ session_id TEXT NOT NULL REFERENCES memory_sessions(id),
470
+ content TEXT NOT NULL,
471
+ embedding BLOB,
472
+ embedding_dim INTEGER,
473
+ timestamp INTEGER NOT NULL,
474
+ role TEXT NOT NULL,
475
+ entities TEXT,
476
+ importance REAL DEFAULT 0.5,
477
+ pruned INTEGER DEFAULT 0,
478
+ created_at TEXT
479
+ )
480
+ `);
481
+ db.exec(
482
+ `CREATE INDEX IF NOT EXISTS memory_messages_session_idx ON memory_messages(session_id, timestamp)`
483
+ );
484
+ db.exec(
485
+ `CREATE INDEX IF NOT EXISTS memory_messages_pruned_idx ON memory_messages(pruned, importance)`
486
+ );
487
+ db.exec(`
488
+ CREATE TABLE IF NOT EXISTS memory_summaries (
489
+ id TEXT PRIMARY KEY,
490
+ session_id TEXT NOT NULL REFERENCES memory_sessions(id),
491
+ level INTEGER NOT NULL,
492
+ content TEXT NOT NULL,
493
+ embedding BLOB,
494
+ embedding_dim INTEGER,
495
+ created_at TEXT
496
+ )
497
+ `);
498
+ db.exec(
499
+ `CREATE INDEX IF NOT EXISTS memory_summaries_session_idx ON memory_summaries(session_id, level)`
500
+ );
501
+ db.exec(`
502
+ CREATE TABLE IF NOT EXISTS knowledge_base (
503
+ id TEXT PRIMARY KEY,
504
+ user_id TEXT NOT NULL,
505
+ fact TEXT NOT NULL,
506
+ source_session_id TEXT,
507
+ confidence REAL DEFAULT 0.8,
508
+ category TEXT,
509
+ embedding BLOB,
510
+ embedding_dim INTEGER,
511
+ last_verified INTEGER,
512
+ created_at TEXT,
513
+ updated_at TEXT
514
+ )
515
+ `);
516
+ db.exec(
517
+ `CREATE INDEX IF NOT EXISTS knowledge_base_user_idx ON knowledge_base(user_id, category)`
518
+ );
519
+ db.exec(
520
+ `CREATE INDEX IF NOT EXISTS knowledge_base_confidence_idx ON knowledge_base(confidence DESC)`
521
+ );
522
+ db.exec(`
523
+ CREATE TABLE IF NOT EXISTS memory_search_cache (
524
+ id TEXT PRIMARY KEY,
525
+ query_hash TEXT NOT NULL,
526
+ user_id TEXT NOT NULL,
527
+ results TEXT NOT NULL,
528
+ created_at TEXT,
529
+ expires_at TEXT
530
+ )
531
+ `);
532
+ db.exec(
533
+ `CREATE INDEX IF NOT EXISTS memory_search_cache_hash_idx ON memory_search_cache(query_hash, user_id)`
534
+ );
535
+ }
536
+
537
+ // packages/storage/src/sqlite/schema/vector.ts
538
+ function initVectorSchema(db, enabled) {
539
+ if (!enabled) return;
540
+ try {
541
+ db.exec(`
542
+ CREATE VIRTUAL TABLE IF NOT EXISTS memory_messages_vec USING vec0(
543
+ id TEXT PRIMARY KEY,
544
+ embedding FLOAT[1024]
545
+ )
546
+ `);
547
+ db.exec(`
548
+ CREATE VIRTUAL TABLE IF NOT EXISTS knowledge_base_vec USING vec0(
549
+ id TEXT PRIMARY KEY,
550
+ embedding FLOAT[1024]
551
+ )
552
+ `);
553
+ } catch {
554
+ }
555
+ }
556
+
557
+ // packages/storage/src/sqlite/schema.ts
558
+ function initSchema(db) {
559
+ const hasVec = initVectorExtension(db);
560
+ initCoreSchema(db);
561
+ initAgentSchema(db);
562
+ initMemorySchema(db);
563
+ initFtsSchema(db);
564
+ initVectorSchema(db, hasVec);
565
+ }
566
+ function resetMemoryTables(db) {
567
+ db.exec(`DROP TABLE IF EXISTS memory_search_cache`);
568
+ db.exec(`DROP TABLE IF EXISTS memory_messages_fts`);
569
+ db.exec(`DROP TABLE IF EXISTS knowledge_base_fts`);
570
+ db.exec(`DROP TABLE IF EXISTS memory_messages_vec`);
571
+ db.exec(`DROP TABLE IF EXISTS knowledge_base_vec`);
572
+ db.exec(`DROP TABLE IF EXISTS memory_summaries`);
573
+ db.exec(`DROP TABLE IF EXISTS memory_messages`);
574
+ db.exec(`DROP TABLE IF EXISTS knowledge_base`);
575
+ db.exec(`DROP TABLE IF EXISTS memory_sessions`);
576
+ initSchema(db);
577
+ }
578
+ function getSchemaInfo(db) {
579
+ const rows = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' ORDER BY name`).all();
580
+ const tables = rows.map((row) => row.name);
581
+ const hasVec = tables.some((t) => t.endsWith("_vec"));
582
+ const hasFts = tables.some((t) => t.endsWith("_fts"));
583
+ return { tables, hasVec, hasFts };
584
+ }
585
+
586
+ // packages/storage/src/sqlite/sessions/statements.ts
587
+ function prepareSessionStatements(db) {
588
+ return {
589
+ getByKey: db.prepare(
590
+ "SELECT id, key, created_at, updated_at, user_id, channel, chat_type, chat_id, peer_id, account_id, thread_id, label, current_provider, current_model, providers_used, provider_switches FROM sessions WHERE key = @key"
591
+ ),
592
+ getById: db.prepare(
593
+ "SELECT id, key, created_at, updated_at, user_id, channel, chat_type, chat_id, peer_id, account_id, thread_id, label, current_provider, current_model, providers_used, provider_switches FROM sessions WHERE id = @id"
594
+ ),
595
+ list: db.prepare(
596
+ "SELECT id, key, created_at, updated_at, user_id, channel, chat_type, chat_id, peer_id, account_id, thread_id, label, current_provider, current_model, providers_used, provider_switches FROM sessions ORDER BY created_at DESC"
597
+ ),
598
+ insert: db.prepare(
599
+ "INSERT OR IGNORE INTO sessions (id, key, created_at, updated_at, user_id, channel, chat_type, chat_id, peer_id, account_id, thread_id, label, current_provider, current_model, providers_used, provider_switches) VALUES (@id, @key, @created_at, @updated_at, @user_id, @channel, @chat_type, @chat_id, @peer_id, @account_id, @thread_id, @label, @current_provider, @current_model, @providers_used, @provider_switches)"
600
+ ),
601
+ update: db.prepare(
602
+ "UPDATE sessions SET key = @key, updated_at = @updated_at, user_id = @user_id, channel = @channel, chat_type = @chat_type, chat_id = @chat_id, peer_id = @peer_id, account_id = @account_id, thread_id = @thread_id, label = @label, current_provider = @current_provider, current_model = @current_model, providers_used = @providers_used, provider_switches = @provider_switches WHERE id = @id"
603
+ ),
604
+ eventInsert: db.prepare(
605
+ "INSERT INTO session_events (id, session_id, role, content, metadata, created_at) VALUES (@id, @session_id, @role, @content, @metadata, @created_at)"
606
+ ),
607
+ eventList: db.prepare(
608
+ "SELECT id, session_id, role, content, metadata, created_at FROM session_events WHERE session_id = @session_id ORDER BY created_at DESC LIMIT @limit"
609
+ ),
610
+ eventCount: db.prepare("SELECT COUNT(*) as count FROM session_events WHERE session_id = @session_id"),
611
+ summaryGet: db.prepare(
612
+ "SELECT session_id, summary, event_count, updated_at FROM session_summaries WHERE session_id = @session_id"
613
+ ),
614
+ summaryUpsert: db.prepare(
615
+ "INSERT INTO session_summaries (session_id, summary, event_count, updated_at) VALUES (@session_id, @summary, @event_count, @updated_at) ON CONFLICT(session_id) DO UPDATE SET summary = excluded.summary, event_count = excluded.event_count, updated_at = excluded.updated_at"
616
+ ),
617
+ toolPolicyGet: db.prepare("SELECT id, allow, deny, updated_at FROM tool_policy WHERE id = @id"),
618
+ toolPolicyUpsert: db.prepare(
619
+ "INSERT INTO tool_policy (id, allow, deny, updated_at) VALUES (@id, @allow, @deny, @updated_at) ON CONFLICT(id) DO UPDATE SET allow = excluded.allow, deny = excluded.deny, updated_at = excluded.updated_at"
620
+ ),
621
+ getPrefs: db.prepare(
622
+ "SELECT session_id, provider_id, model, system, auto_routing, language, language_updated_at, continuity_preferred_device_id, continuity_mode, proactive_allowed, proactive_observe, proactive_deliver, proactive_allowed_channels, proactive_paused_until, proactive_max_per_day, proactive_cooldown_ms, proactive_delivered_day, proactive_delivered_count, proactive_last_delivered_at, updated_at FROM session_prefs WHERE session_id = @session_id"
623
+ ),
624
+ upsertPrefs: db.prepare(
625
+ "INSERT INTO session_prefs (session_id, provider_id, model, system, auto_routing, language, language_updated_at, continuity_preferred_device_id, continuity_mode, proactive_allowed, proactive_observe, proactive_deliver, proactive_allowed_channels, proactive_paused_until, proactive_max_per_day, proactive_cooldown_ms, proactive_delivered_day, proactive_delivered_count, proactive_last_delivered_at, updated_at) VALUES (@session_id, @provider_id, @model, @system, @auto_routing, @language, @language_updated_at, @continuity_preferred_device_id, @continuity_mode, @proactive_allowed, @proactive_observe, @proactive_deliver, @proactive_allowed_channels, @proactive_paused_until, @proactive_max_per_day, @proactive_cooldown_ms, @proactive_delivered_day, @proactive_delivered_count, @proactive_last_delivered_at, @updated_at) ON CONFLICT(session_id) DO UPDATE SET provider_id = excluded.provider_id, model = excluded.model, system = excluded.system, auto_routing = excluded.auto_routing, language = excluded.language, language_updated_at = excluded.language_updated_at, continuity_preferred_device_id = excluded.continuity_preferred_device_id, continuity_mode = excluded.continuity_mode, proactive_allowed = excluded.proactive_allowed, proactive_observe = excluded.proactive_observe, proactive_deliver = excluded.proactive_deliver, proactive_allowed_channels = excluded.proactive_allowed_channels, proactive_paused_until = excluded.proactive_paused_until, proactive_max_per_day = excluded.proactive_max_per_day, proactive_cooldown_ms = excluded.proactive_cooldown_ms, proactive_delivered_day = excluded.proactive_delivered_day, proactive_delivered_count = excluded.proactive_delivered_count, proactive_last_delivered_at = excluded.proactive_last_delivered_at, updated_at = excluded.updated_at"
626
+ ),
627
+ deletePrefs: db.prepare("DELETE FROM session_prefs WHERE session_id = @session_id")
628
+ };
629
+ }
630
+
631
+ // packages/storage/src/sqlite/sessions/session-crud.ts
632
+ import { randomUUID } from "node:crypto";
633
+
634
+ // packages/storage/src/sqlite/sessions/mappers.ts
635
+ function mapSession(row) {
636
+ const providersUsedRaw = row.providers_used ? String(row.providers_used) : "";
637
+ let providersUsed;
638
+ if (providersUsedRaw) {
639
+ try {
640
+ const parsed = JSON.parse(providersUsedRaw);
641
+ providersUsed = Array.isArray(parsed) ? parsed.map((value) => String(value)) : void 0;
642
+ } catch {
643
+ providersUsed = void 0;
644
+ }
645
+ }
646
+ return {
647
+ id: String(row.id),
648
+ key: String(row.key),
649
+ createdAt: String(row.created_at),
650
+ updatedAt: String(row.updated_at),
651
+ userId: row.user_id ? String(row.user_id) : void 0,
652
+ channel: row.channel ? String(row.channel) : void 0,
653
+ chatType: row.chat_type ? String(row.chat_type) : void 0,
654
+ chatId: row.chat_id ? String(row.chat_id) : void 0,
655
+ peerId: row.peer_id ? String(row.peer_id) : void 0,
656
+ accountId: row.account_id ? String(row.account_id) : void 0,
657
+ threadId: row.thread_id ? String(row.thread_id) : void 0,
658
+ label: row.label ? String(row.label) : void 0,
659
+ currentProviderId: row.current_provider ? String(row.current_provider) : void 0,
660
+ currentModel: row.current_model ? String(row.current_model) : void 0,
661
+ providersUsed,
662
+ providerSwitches: row.provider_switches === null || row.provider_switches === void 0 ? void 0 : Number(row.provider_switches)
663
+ };
664
+ }
665
+ function mapEvent(row) {
666
+ return {
667
+ id: String(row.id),
668
+ sessionId: String(row.session_id),
669
+ role: String(row.role),
670
+ content: String(row.content),
671
+ metadata: row.metadata ? JSON.parse(String(row.metadata)) : void 0,
672
+ createdAt: String(row.created_at)
673
+ };
674
+ }
675
+ function mapSummary(row) {
676
+ return {
677
+ sessionId: String(row.session_id),
678
+ summary: String(row.summary),
679
+ eventCount: row.event_count === null || row.event_count === void 0 ? void 0 : Number(row.event_count),
680
+ updatedAt: String(row.updated_at)
681
+ };
682
+ }
683
+ function mapPrefs(row) {
684
+ let proactiveAllowedChannels;
685
+ if (row.proactive_allowed_channels) {
686
+ try {
687
+ const parsed = JSON.parse(String(row.proactive_allowed_channels));
688
+ if (Array.isArray(parsed)) {
689
+ proactiveAllowedChannels = parsed.filter((item) => typeof item === "string");
690
+ }
691
+ } catch {
692
+ proactiveAllowedChannels = void 0;
693
+ }
694
+ }
695
+ return {
696
+ sessionId: String(row.session_id),
697
+ providerId: row.provider_id ? String(row.provider_id) : void 0,
698
+ model: row.model ? String(row.model) : void 0,
699
+ system: row.system ? String(row.system) : void 0,
700
+ autoRouting: row.auto_routing === null || row.auto_routing === void 0 ? void 0 : Boolean(row.auto_routing),
701
+ language: row.language ? String(row.language) : void 0,
702
+ languageUpdatedAt: row.language_updated_at ? String(row.language_updated_at) : void 0,
703
+ continuityPreferredDeviceId: row.continuity_preferred_device_id ? String(row.continuity_preferred_device_id) : void 0,
704
+ continuityMode: row.continuity_mode === "auto" || row.continuity_mode === "prompt" || row.continuity_mode === "off" ? row.continuity_mode : void 0,
705
+ proactiveAllowed: row.proactive_allowed === null || row.proactive_allowed === void 0 ? void 0 : Boolean(row.proactive_allowed),
706
+ proactiveObserve: row.proactive_observe === null || row.proactive_observe === void 0 ? void 0 : Boolean(row.proactive_observe),
707
+ proactiveDeliver: row.proactive_deliver === null || row.proactive_deliver === void 0 ? void 0 : Boolean(row.proactive_deliver),
708
+ proactiveAllowedChannels,
709
+ proactivePausedUntil: row.proactive_paused_until ? String(row.proactive_paused_until) : void 0,
710
+ proactiveMaxPerDay: row.proactive_max_per_day === null || row.proactive_max_per_day === void 0 ? void 0 : Number(row.proactive_max_per_day),
711
+ proactiveCooldownMs: row.proactive_cooldown_ms === null || row.proactive_cooldown_ms === void 0 ? void 0 : Number(row.proactive_cooldown_ms),
712
+ proactiveDeliveredDay: row.proactive_delivered_day ? String(row.proactive_delivered_day) : void 0,
713
+ proactiveDeliveredCount: row.proactive_delivered_count === null || row.proactive_delivered_count === void 0 ? void 0 : Number(row.proactive_delivered_count),
714
+ proactiveLastDeliveredAt: row.proactive_last_delivered_at ? String(row.proactive_last_delivered_at) : void 0,
715
+ updatedAt: String(row.updated_at)
716
+ };
717
+ }
718
+
719
+ // packages/storage/src/sqlite/sessions/session-crud.ts
720
+ async function getSessionByKey(s, key) {
721
+ const row = s.getByKey.get({ key });
722
+ return row ? mapSession(row) : void 0;
723
+ }
724
+ async function getSessionById(s, id) {
725
+ const row = s.getById.get({ id });
726
+ return row ? mapSession(row) : void 0;
727
+ }
728
+ async function listSessions(s) {
729
+ const rows = s.list.all();
730
+ return rows.map(mapSession);
731
+ }
732
+ async function createSession(s, key, meta) {
733
+ const now2 = (/* @__PURE__ */ new Date()).toISOString();
734
+ const record = {
735
+ id: randomUUID(),
736
+ key,
737
+ createdAt: now2,
738
+ updatedAt: now2,
739
+ userId: meta?.userId,
740
+ channel: meta?.channel,
741
+ chatType: meta?.chatType,
742
+ chatId: meta?.chatId,
743
+ peerId: meta?.peerId,
744
+ accountId: meta?.accountId,
745
+ threadId: meta?.threadId,
746
+ label: meta?.label,
747
+ currentProviderId: meta?.currentProviderId,
748
+ currentModel: meta?.currentModel,
749
+ providersUsed: meta?.providersUsed,
750
+ providerSwitches: meta?.providerSwitches
751
+ };
752
+ s.insert.run({
753
+ id: record.id,
754
+ key: record.key,
755
+ created_at: record.createdAt,
756
+ updated_at: record.updatedAt,
757
+ user_id: record.userId ?? null,
758
+ channel: record.channel ?? null,
759
+ chat_type: record.chatType ?? null,
760
+ chat_id: record.chatId ?? null,
761
+ peer_id: record.peerId ?? null,
762
+ account_id: record.accountId ?? null,
763
+ thread_id: record.threadId ?? null,
764
+ label: record.label ?? null,
765
+ current_provider: record.currentProviderId ?? null,
766
+ current_model: record.currentModel ?? null,
767
+ providers_used: record.providersUsed ? JSON.stringify(record.providersUsed) : null,
768
+ provider_switches: record.providerSwitches ?? null
769
+ });
770
+ const stored = await getSessionByKey(s, key);
771
+ return stored ?? record;
772
+ }
773
+ async function updateSession(s, id, update) {
774
+ const existing = await getSessionById(s, id);
775
+ if (!existing) return void 0;
776
+ const merged = {
777
+ ...existing,
778
+ ...update,
779
+ updatedAt: update.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
780
+ };
781
+ s.update.run({
782
+ id: merged.id,
783
+ key: merged.key,
784
+ updated_at: merged.updatedAt,
785
+ user_id: merged.userId ?? null,
786
+ channel: merged.channel ?? null,
787
+ chat_type: merged.chatType ?? null,
788
+ chat_id: merged.chatId ?? null,
789
+ peer_id: merged.peerId ?? null,
790
+ account_id: merged.accountId ?? null,
791
+ thread_id: merged.threadId ?? null,
792
+ label: merged.label ?? null,
793
+ current_provider: merged.currentProviderId ?? null,
794
+ current_model: merged.currentModel ?? null,
795
+ providers_used: merged.providersUsed ? JSON.stringify(merged.providersUsed) : null,
796
+ provider_switches: merged.providerSwitches ?? null
797
+ });
798
+ return merged;
799
+ }
800
+
801
+ // packages/storage/src/sqlite/sessions/events.ts
802
+ async function appendSessionEvent(s, event) {
803
+ s.eventInsert.run({
804
+ id: event.id,
805
+ session_id: event.sessionId,
806
+ role: event.role,
807
+ content: event.content,
808
+ metadata: event.metadata ? JSON.stringify(event.metadata) : null,
809
+ created_at: event.createdAt
810
+ });
811
+ }
812
+ async function listSessionEvents(s, sessionId, options) {
813
+ const limit = options?.limit ?? 50;
814
+ const rows = s.eventList.all({ session_id: sessionId, limit });
815
+ return rows.map(mapEvent).reverse();
816
+ }
817
+ async function countSessionEvents(s, sessionId) {
818
+ const row = s.eventCount.get({ session_id: sessionId });
819
+ const value = row?.count;
820
+ return typeof value === "number" ? value : Number(value ?? 0);
821
+ }
822
+
823
+ // packages/storage/src/sqlite/sessions/summaries.ts
824
+ async function getSessionSummary(s, sessionId) {
825
+ const row = s.summaryGet.get({ session_id: sessionId });
826
+ return row ? mapSummary(row) : void 0;
827
+ }
828
+ async function setSessionSummary(s, sessionId, summary, eventCount) {
829
+ const now2 = (/* @__PURE__ */ new Date()).toISOString();
830
+ s.summaryUpsert.run({
831
+ session_id: sessionId,
832
+ summary,
833
+ event_count: eventCount ?? null,
834
+ updated_at: now2
835
+ });
836
+ return await getSessionSummary(s, sessionId) ?? { sessionId, summary, eventCount, updatedAt: now2 };
837
+ }
838
+
839
+ // packages/storage/src/sqlite/sessions/tool-policy.ts
840
+ async function getToolPolicy(s) {
841
+ const row = s.toolPolicyGet.get({ id: "global" });
842
+ if (!row) return void 0;
843
+ return {
844
+ allow: row.allow ? JSON.parse(String(row.allow)) : void 0,
845
+ deny: row.deny ? JSON.parse(String(row.deny)) : void 0,
846
+ updatedAt: row.updated_at ? String(row.updated_at) : void 0
847
+ };
848
+ }
849
+ async function setToolPolicy(s, policy) {
850
+ const record = {
851
+ allow: policy.allow ?? [],
852
+ deny: policy.deny ?? [],
853
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
854
+ };
855
+ s.toolPolicyUpsert.run({
856
+ id: "global",
857
+ allow: JSON.stringify(record.allow ?? []),
858
+ deny: JSON.stringify(record.deny ?? []),
859
+ updated_at: record.updatedAt
860
+ });
861
+ return record;
862
+ }
863
+
864
+ // packages/storage/src/sqlite/sessions/prefs.ts
865
+ async function getSessionPrefs(s, sessionId) {
866
+ const row = s.getPrefs.get({ session_id: sessionId });
867
+ return row ? mapPrefs(row) : void 0;
868
+ }
869
+ async function setSessionPrefs(s, sessionId, prefs) {
870
+ const existing = await getSessionPrefs(s, sessionId);
871
+ const now2 = (/* @__PURE__ */ new Date()).toISOString();
872
+ const providerId = prefs.providerId ?? existing?.providerId ?? null;
873
+ const model = prefs.model ?? existing?.model ?? null;
874
+ const system = prefs.system ?? existing?.system ?? null;
875
+ const autoRouting = prefs.autoRouting ?? existing?.autoRouting;
876
+ const hasLanguage = Object.prototype.hasOwnProperty.call(prefs, "language");
877
+ const language = hasLanguage ? prefs.language ?? null : existing?.language ?? null;
878
+ const hasLanguageUpdatedAt = Object.prototype.hasOwnProperty.call(prefs, "languageUpdatedAt");
879
+ const languageUpdatedAt = hasLanguage ? prefs.language ? prefs.languageUpdatedAt ?? now2 : null : hasLanguageUpdatedAt ? prefs.languageUpdatedAt ?? null : existing?.languageUpdatedAt ?? null;
880
+ const hasContinuityDevice = Object.prototype.hasOwnProperty.call(prefs, "continuityPreferredDeviceId");
881
+ const continuityPreferredDeviceId = hasContinuityDevice ? prefs.continuityPreferredDeviceId ?? null : existing?.continuityPreferredDeviceId ?? null;
882
+ const hasContinuityMode = Object.prototype.hasOwnProperty.call(prefs, "continuityMode");
883
+ const continuityMode = hasContinuityMode ? prefs.continuityMode ?? null : existing?.continuityMode ?? null;
884
+ const proactiveAllowed = prefs.proactiveAllowed ?? existing?.proactiveAllowed;
885
+ const proactiveObserve = prefs.proactiveObserve ?? existing?.proactiveObserve;
886
+ const proactiveDeliver = prefs.proactiveDeliver ?? existing?.proactiveDeliver;
887
+ const hasAllowedChannels = Object.prototype.hasOwnProperty.call(prefs, "proactiveAllowedChannels");
888
+ const proactiveAllowedChannels = hasAllowedChannels ? prefs.proactiveAllowedChannels ?? null : existing?.proactiveAllowedChannels ?? null;
889
+ const hasPausedUntil = Object.prototype.hasOwnProperty.call(prefs, "proactivePausedUntil");
890
+ const proactivePausedUntil = hasPausedUntil ? prefs.proactivePausedUntil ?? null : existing?.proactivePausedUntil ?? null;
891
+ const hasMaxPerDay = Object.prototype.hasOwnProperty.call(prefs, "proactiveMaxPerDay");
892
+ const proactiveMaxPerDay = hasMaxPerDay ? prefs.proactiveMaxPerDay ?? null : existing?.proactiveMaxPerDay ?? null;
893
+ const hasCooldown = Object.prototype.hasOwnProperty.call(prefs, "proactiveCooldownMs");
894
+ const proactiveCooldownMs = hasCooldown ? prefs.proactiveCooldownMs ?? null : existing?.proactiveCooldownMs ?? null;
895
+ const hasDeliveredDay = Object.prototype.hasOwnProperty.call(prefs, "proactiveDeliveredDay");
896
+ const proactiveDeliveredDay = hasDeliveredDay ? prefs.proactiveDeliveredDay ?? null : existing?.proactiveDeliveredDay ?? null;
897
+ const hasDeliveredCount = Object.prototype.hasOwnProperty.call(prefs, "proactiveDeliveredCount");
898
+ const proactiveDeliveredCount = hasDeliveredCount ? prefs.proactiveDeliveredCount ?? null : existing?.proactiveDeliveredCount ?? null;
899
+ const hasLastDelivered = Object.prototype.hasOwnProperty.call(prefs, "proactiveLastDeliveredAt");
900
+ const proactiveLastDeliveredAt = hasLastDelivered ? prefs.proactiveLastDeliveredAt ?? null : existing?.proactiveLastDeliveredAt ?? null;
901
+ s.upsertPrefs.run({
902
+ session_id: sessionId,
903
+ provider_id: providerId,
904
+ model,
905
+ system,
906
+ auto_routing: autoRouting === void 0 ? null : autoRouting ? 1 : 0,
907
+ language,
908
+ language_updated_at: languageUpdatedAt,
909
+ continuity_preferred_device_id: continuityPreferredDeviceId,
910
+ continuity_mode: continuityMode,
911
+ proactive_allowed: proactiveAllowed === void 0 ? null : proactiveAllowed ? 1 : 0,
912
+ proactive_observe: proactiveObserve === void 0 ? null : proactiveObserve ? 1 : 0,
913
+ proactive_deliver: proactiveDeliver === void 0 ? null : proactiveDeliver ? 1 : 0,
914
+ proactive_allowed_channels: Array.isArray(proactiveAllowedChannels) ? JSON.stringify(proactiveAllowedChannels) : null,
915
+ proactive_paused_until: proactivePausedUntil,
916
+ proactive_max_per_day: proactiveMaxPerDay,
917
+ proactive_cooldown_ms: proactiveCooldownMs,
918
+ proactive_delivered_day: proactiveDeliveredDay,
919
+ proactive_delivered_count: proactiveDeliveredCount,
920
+ proactive_last_delivered_at: proactiveLastDeliveredAt,
921
+ updated_at: now2
922
+ });
923
+ const stored = await getSessionPrefs(s, sessionId);
924
+ return stored ?? {
925
+ sessionId,
926
+ providerId: providerId ?? void 0,
927
+ model: model ?? void 0,
928
+ system: system ?? void 0,
929
+ autoRouting,
930
+ language: language ?? void 0,
931
+ languageUpdatedAt: languageUpdatedAt ?? void 0,
932
+ continuityPreferredDeviceId: continuityPreferredDeviceId ?? void 0,
933
+ continuityMode: continuityMode ?? void 0,
934
+ proactiveAllowed,
935
+ proactiveObserve,
936
+ proactiveDeliver,
937
+ proactiveAllowedChannels: Array.isArray(proactiveAllowedChannels) ? proactiveAllowedChannels : void 0,
938
+ proactivePausedUntil: proactivePausedUntil ?? void 0,
939
+ proactiveMaxPerDay: proactiveMaxPerDay ?? void 0,
940
+ proactiveCooldownMs: proactiveCooldownMs ?? void 0,
941
+ proactiveDeliveredDay: proactiveDeliveredDay ?? void 0,
942
+ proactiveDeliveredCount: proactiveDeliveredCount ?? void 0,
943
+ proactiveLastDeliveredAt: proactiveLastDeliveredAt ?? void 0,
944
+ updatedAt: now2
945
+ };
946
+ }
947
+ async function clearSessionPrefs(s, sessionId) {
948
+ s.deletePrefs.run({ session_id: sessionId });
949
+ }
950
+
951
+ // packages/storage/src/sqlite/devices.ts
952
+ function prepareDeviceStatements(db) {
953
+ return {
954
+ list: db.prepare(
955
+ "SELECT id, name, type, role, caps, status, scopes, auth_type, token_hash, token_hint, public_key, public_key_alg, created_at, updated_at, last_seen_at FROM devices ORDER BY created_at DESC"
956
+ ),
957
+ getById: db.prepare(
958
+ "SELECT id, name, type, role, caps, status, scopes, auth_type, token_hash, token_hint, public_key, public_key_alg, created_at, updated_at, last_seen_at FROM devices WHERE id = @id"
959
+ ),
960
+ getByToken: db.prepare(
961
+ "SELECT id, name, type, role, caps, status, scopes, auth_type, token_hash, token_hint, public_key, public_key_alg, created_at, updated_at, last_seen_at FROM devices WHERE token_hash = @token_hash"
962
+ ),
963
+ insert: db.prepare(
964
+ "INSERT INTO devices (id, name, type, role, caps, status, scopes, auth_type, token_hash, token_hint, public_key, public_key_alg, created_at, updated_at, last_seen_at) VALUES (@id, @name, @type, @role, @caps, @status, @scopes, @auth_type, @token_hash, @token_hint, @public_key, @public_key_alg, @created_at, @updated_at, @last_seen_at)"
965
+ ),
966
+ update: db.prepare(
967
+ "UPDATE devices SET name = @name, type = @type, role = @role, caps = @caps, scopes = @scopes, updated_at = @updated_at WHERE id = @id"
968
+ ),
969
+ revoke: db.prepare(
970
+ "UPDATE devices SET status = @status, updated_at = @updated_at WHERE id = @id"
971
+ ),
972
+ touch: db.prepare(
973
+ "UPDATE devices SET last_seen_at = @last_seen_at, updated_at = @updated_at WHERE id = @id"
974
+ )
975
+ };
976
+ }
977
+ function mapDevice(row) {
978
+ return {
979
+ id: String(row.id),
980
+ name: row.name ? String(row.name) : void 0,
981
+ type: row.type ? String(row.type) : void 0,
982
+ role: row.role ? String(row.role) : void 0,
983
+ caps: row.caps ? JSON.parse(String(row.caps)) : void 0,
984
+ status: row.status === "revoked" ? "revoked" : "active",
985
+ scopes: row.scopes ? JSON.parse(String(row.scopes)) : void 0,
986
+ authType: row.auth_type === "keypair" ? "keypair" : "token",
987
+ tokenHash: row.token_hash ? String(row.token_hash) : void 0,
988
+ tokenHint: row.token_hint ? String(row.token_hint) : void 0,
989
+ publicKey: row.public_key ? String(row.public_key) : void 0,
990
+ publicKeyAlgorithm: row.public_key_alg ? String(row.public_key_alg) : void 0,
991
+ createdAt: String(row.created_at),
992
+ updatedAt: String(row.updated_at),
993
+ lastSeenAt: row.last_seen_at ? String(row.last_seen_at) : void 0
994
+ };
995
+ }
996
+ async function listDevices(s) {
997
+ const rows = s.list.all();
998
+ return rows.map(mapDevice);
999
+ }
1000
+ async function getDeviceById(s, id) {
1001
+ const row = s.getById.get({ id });
1002
+ return row ? mapDevice(row) : void 0;
1003
+ }
1004
+ async function getDeviceByTokenHash(s, tokenHash) {
1005
+ const row = s.getByToken.get({ token_hash: tokenHash });
1006
+ return row ? mapDevice(row) : void 0;
1007
+ }
1008
+ async function createDevice(s, record) {
1009
+ s.insert.run({
1010
+ id: record.id,
1011
+ name: record.name ?? null,
1012
+ type: record.type ?? null,
1013
+ role: record.role ?? null,
1014
+ caps: record.caps ? JSON.stringify(record.caps) : null,
1015
+ status: record.status,
1016
+ scopes: record.scopes ? JSON.stringify(record.scopes) : null,
1017
+ auth_type: record.authType,
1018
+ token_hash: record.tokenHash ?? null,
1019
+ token_hint: record.tokenHint ?? null,
1020
+ public_key: record.publicKey ?? null,
1021
+ public_key_alg: record.publicKeyAlgorithm ?? null,
1022
+ created_at: record.createdAt,
1023
+ updated_at: record.updatedAt,
1024
+ last_seen_at: record.lastSeenAt ?? null
1025
+ });
1026
+ return record;
1027
+ }
1028
+ async function updateDevice(s, id, update) {
1029
+ const existing = await getDeviceById(s, id);
1030
+ if (!existing) {
1031
+ return void 0;
1032
+ }
1033
+ const updated = {
1034
+ ...existing,
1035
+ name: update.name ?? existing.name,
1036
+ type: update.type ?? existing.type,
1037
+ scopes: update.scopes ?? existing.scopes,
1038
+ role: update.role ?? existing.role,
1039
+ caps: update.caps ?? existing.caps,
1040
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1041
+ };
1042
+ s.update.run({
1043
+ id,
1044
+ name: updated.name ?? null,
1045
+ type: updated.type ?? null,
1046
+ role: updated.role ?? null,
1047
+ caps: updated.caps ? JSON.stringify(updated.caps) : null,
1048
+ scopes: updated.scopes ? JSON.stringify(updated.scopes) : null,
1049
+ updated_at: updated.updatedAt
1050
+ });
1051
+ return updated;
1052
+ }
1053
+ async function revokeDevice(s, id) {
1054
+ const existing = await getDeviceById(s, id);
1055
+ if (!existing) {
1056
+ return void 0;
1057
+ }
1058
+ const updated = {
1059
+ ...existing,
1060
+ status: "revoked",
1061
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1062
+ };
1063
+ s.revoke.run({
1064
+ id,
1065
+ status: updated.status,
1066
+ updated_at: updated.updatedAt
1067
+ });
1068
+ return updated;
1069
+ }
1070
+ async function touchDevice(s, id) {
1071
+ s.touch.run({
1072
+ id,
1073
+ last_seen_at: (/* @__PURE__ */ new Date()).toISOString(),
1074
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
1075
+ });
1076
+ }
1077
+
1078
+ // packages/storage/src/sqlite/channels.ts
1079
+ import { randomUUID as randomUUID2 } from "node:crypto";
1080
+ function prepareChannelStatements(db) {
1081
+ return {
1082
+ list: db.prepare(
1083
+ "SELECT id, channel, chat_id, user_id, status, note, created_at, updated_at FROM channel_allows ORDER BY created_at DESC"
1084
+ ),
1085
+ listByChannel: db.prepare(
1086
+ "SELECT id, channel, chat_id, user_id, status, note, created_at, updated_at FROM channel_allows WHERE channel = @channel ORDER BY created_at DESC"
1087
+ ),
1088
+ get: db.prepare(
1089
+ "SELECT id, channel, chat_id, user_id, status, note, created_at, updated_at FROM channel_allows WHERE channel = @channel AND chat_id = @chat_id AND user_id = @user_id"
1090
+ ),
1091
+ insert: db.prepare(
1092
+ "INSERT OR IGNORE INTO channel_allows (id, channel, chat_id, user_id, status, note, created_at, updated_at) VALUES (@id, @channel, @chat_id, @user_id, @status, @note, @created_at, @updated_at)"
1093
+ ),
1094
+ update: db.prepare(
1095
+ "UPDATE channel_allows SET status = @status, note = @note, updated_at = @updated_at WHERE channel = @channel AND chat_id = @chat_id AND user_id = @user_id"
1096
+ ),
1097
+ revoke: db.prepare(
1098
+ "UPDATE channel_allows SET status = @status, updated_at = @updated_at WHERE id = @id"
1099
+ )
1100
+ };
1101
+ }
1102
+ function mapChannelAllow(row) {
1103
+ const userId = row.user_id ? String(row.user_id) : "";
1104
+ return {
1105
+ id: String(row.id),
1106
+ channel: String(row.channel),
1107
+ chatId: String(row.chat_id),
1108
+ userId: userId.length > 0 ? userId : void 0,
1109
+ status: row.status === "revoked" ? "revoked" : "allowed",
1110
+ note: row.note ? String(row.note) : void 0,
1111
+ createdAt: String(row.created_at),
1112
+ updatedAt: String(row.updated_at)
1113
+ };
1114
+ }
1115
+ async function listChannelAllows(s, channel) {
1116
+ const rows = channel ? s.listByChannel.all({ channel }) : s.list.all();
1117
+ return rows.map(mapChannelAllow);
1118
+ }
1119
+ async function getChannelAllow(s, channel, chatId, userId) {
1120
+ const userKey = userId ?? "";
1121
+ const row = s.get.get({
1122
+ channel,
1123
+ chat_id: chatId,
1124
+ user_id: userKey
1125
+ });
1126
+ if (row) {
1127
+ return mapChannelAllow(row);
1128
+ }
1129
+ if (userId) {
1130
+ const fallback = s.get.get({
1131
+ channel,
1132
+ chat_id: chatId,
1133
+ user_id: ""
1134
+ });
1135
+ return fallback ? mapChannelAllow(fallback) : void 0;
1136
+ }
1137
+ return void 0;
1138
+ }
1139
+ async function allowChannel(s, record) {
1140
+ const now2 = (/* @__PURE__ */ new Date()).toISOString();
1141
+ const userKey = record.userId ?? "";
1142
+ const existing = s.get.get({
1143
+ channel: record.channel,
1144
+ chat_id: record.chatId,
1145
+ user_id: userKey
1146
+ });
1147
+ if (!existing) {
1148
+ s.insert.run({
1149
+ id: randomUUID2(),
1150
+ channel: record.channel,
1151
+ chat_id: record.chatId,
1152
+ user_id: userKey,
1153
+ status: "allowed",
1154
+ note: record.note ?? null,
1155
+ created_at: now2,
1156
+ updated_at: now2
1157
+ });
1158
+ }
1159
+ s.update.run({
1160
+ channel: record.channel,
1161
+ chat_id: record.chatId,
1162
+ user_id: userKey,
1163
+ status: "allowed",
1164
+ note: record.note ?? null,
1165
+ updated_at: now2
1166
+ });
1167
+ const stored = s.get.get({
1168
+ channel: record.channel,
1169
+ chat_id: record.chatId,
1170
+ user_id: userKey
1171
+ });
1172
+ return stored ? mapChannelAllow(stored) : {
1173
+ id: randomUUID2(),
1174
+ channel: record.channel,
1175
+ chatId: record.chatId,
1176
+ userId: record.userId,
1177
+ note: record.note,
1178
+ status: "allowed",
1179
+ createdAt: now2,
1180
+ updatedAt: now2
1181
+ };
1182
+ }
1183
+ async function revokeChannel(s, id) {
1184
+ const rows = s.list.all();
1185
+ const existing = rows.find((row) => String(row.id) === id);
1186
+ if (!existing) {
1187
+ return void 0;
1188
+ }
1189
+ const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1190
+ s.revoke.run({
1191
+ id,
1192
+ status: "revoked",
1193
+ updated_at: updatedAt
1194
+ });
1195
+ return { ...mapChannelAllow(existing), status: "revoked", updatedAt };
1196
+ }
1197
+
1198
+ // packages/storage/src/sqlite/approvals.ts
1199
+ import { randomUUID as randomUUID3 } from "node:crypto";
1200
+ function prepareApprovalStatements(db) {
1201
+ return {
1202
+ get: db.prepare(
1203
+ "SELECT id, status, kind, tool_name, tool_input, session_id, channel, chat_id, user_id, user_text, risk, reason, created_at, updated_at, expires_at, decided_at, decided_by, result FROM approval_requests WHERE id = @id"
1204
+ ),
1205
+ list: db.prepare(
1206
+ "SELECT id, status, kind, tool_name, tool_input, session_id, channel, chat_id, user_id, user_text, risk, reason, created_at, updated_at, expires_at, decided_at, decided_by, result FROM approval_requests ORDER BY created_at DESC LIMIT @limit"
1207
+ ),
1208
+ listByStatus: db.prepare(
1209
+ "SELECT id, status, kind, tool_name, tool_input, session_id, channel, chat_id, user_id, user_text, risk, reason, created_at, updated_at, expires_at, decided_at, decided_by, result FROM approval_requests WHERE status = @status ORDER BY created_at DESC LIMIT @limit"
1210
+ ),
1211
+ upsert: db.prepare(
1212
+ "INSERT INTO approval_requests (id, status, kind, tool_name, tool_input, session_id, channel, chat_id, user_id, user_text, risk, reason, created_at, updated_at, expires_at, decided_at, decided_by, result) VALUES (@id, @status, @kind, @tool_name, @tool_input, @session_id, @channel, @chat_id, @user_id, @user_text, @risk, @reason, @created_at, @updated_at, @expires_at, @decided_at, @decided_by, @result) ON CONFLICT(id) DO UPDATE SET status = excluded.status, kind = excluded.kind, tool_name = excluded.tool_name, tool_input = excluded.tool_input, session_id = excluded.session_id, channel = excluded.channel, chat_id = excluded.chat_id, user_id = excluded.user_id, user_text = excluded.user_text, risk = excluded.risk, reason = excluded.reason, updated_at = excluded.updated_at, expires_at = excluded.expires_at, decided_at = excluded.decided_at, decided_by = excluded.decided_by, result = excluded.result"
1213
+ )
1214
+ };
1215
+ }
1216
+ function mapApproval(row) {
1217
+ const parseJson = (value) => {
1218
+ if (typeof value !== "string" || !value) return void 0;
1219
+ try {
1220
+ return JSON.parse(value);
1221
+ } catch {
1222
+ return void 0;
1223
+ }
1224
+ };
1225
+ const toolInput = parseJson(row.tool_input);
1226
+ const decidedBy = parseJson(row.decided_by);
1227
+ const result = parseJson(row.result);
1228
+ const kind = typeof row.kind === "string" && row.kind.trim() ? row.kind : "tool";
1229
+ return {
1230
+ id: String(row.id),
1231
+ status: String(row.status),
1232
+ kind,
1233
+ toolName: String(row.tool_name),
1234
+ toolInput: toolInput ?? {},
1235
+ sessionId: String(row.session_id),
1236
+ channel: String(row.channel),
1237
+ chatId: String(row.chat_id),
1238
+ userId: row.user_id ? String(row.user_id) : void 0,
1239
+ userText: row.user_text ? String(row.user_text) : void 0,
1240
+ risk: row.risk ? String(row.risk) : void 0,
1241
+ reason: row.reason ? String(row.reason) : void 0,
1242
+ createdAt: String(row.created_at),
1243
+ updatedAt: String(row.updated_at),
1244
+ expiresAt: row.expires_at ? String(row.expires_at) : void 0,
1245
+ decidedAt: row.decided_at ? String(row.decided_at) : void 0,
1246
+ decidedBy: decidedBy ?? void 0,
1247
+ result: result ?? void 0
1248
+ };
1249
+ }
1250
+ function toParams(record) {
1251
+ return {
1252
+ id: record.id,
1253
+ status: record.status,
1254
+ kind: record.kind,
1255
+ tool_name: record.toolName,
1256
+ tool_input: JSON.stringify(record.toolInput ?? {}),
1257
+ session_id: record.sessionId,
1258
+ channel: record.channel,
1259
+ chat_id: record.chatId,
1260
+ user_id: record.userId ?? null,
1261
+ user_text: record.userText ?? null,
1262
+ risk: record.risk ?? null,
1263
+ reason: record.reason ?? null,
1264
+ created_at: record.createdAt,
1265
+ updated_at: record.updatedAt,
1266
+ expires_at: record.expiresAt ?? null,
1267
+ decided_at: record.decidedAt ?? null,
1268
+ decided_by: record.decidedBy ? JSON.stringify(record.decidedBy) : null,
1269
+ result: record.result ? JSON.stringify(record.result) : null
1270
+ };
1271
+ }
1272
+ async function createApprovalRequest(s, request) {
1273
+ const now2 = (/* @__PURE__ */ new Date()).toISOString();
1274
+ const id = request.id ?? randomUUID3();
1275
+ const existing = await getApprovalRequest(s, id);
1276
+ if (existing) {
1277
+ return existing;
1278
+ }
1279
+ const record = {
1280
+ id,
1281
+ status: request.status ?? "pending",
1282
+ kind: request.kind ?? "tool",
1283
+ toolName: request.toolName,
1284
+ toolInput: request.toolInput ?? {},
1285
+ sessionId: request.sessionId,
1286
+ channel: request.channel,
1287
+ chatId: request.chatId,
1288
+ userId: request.userId,
1289
+ userText: request.userText,
1290
+ risk: request.risk,
1291
+ reason: request.reason,
1292
+ createdAt: request.createdAt ?? now2,
1293
+ updatedAt: request.updatedAt ?? now2,
1294
+ expiresAt: request.expiresAt,
1295
+ decidedAt: request.decidedAt,
1296
+ decidedBy: request.decidedBy,
1297
+ result: request.result
1298
+ };
1299
+ s.upsert.run(toParams(record));
1300
+ return record;
1301
+ }
1302
+ async function getApprovalRequest(s, id) {
1303
+ const row = s.get.get({ id });
1304
+ return row ? mapApproval(row) : void 0;
1305
+ }
1306
+ async function listApprovalRequests(s, options) {
1307
+ const limit = options?.limit ?? 50;
1308
+ const status = options?.status;
1309
+ const rows = status ? s.listByStatus.all({ status, limit }) : s.list.all({ limit });
1310
+ return rows.map(mapApproval);
1311
+ }
1312
+ async function updateApprovalRequest(s, id, update) {
1313
+ const existing = await getApprovalRequest(s, id);
1314
+ if (!existing) {
1315
+ return void 0;
1316
+ }
1317
+ const merged = {
1318
+ ...existing,
1319
+ ...update,
1320
+ id: existing.id,
1321
+ createdAt: existing.createdAt,
1322
+ updatedAt: update.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
1323
+ };
1324
+ s.upsert.run(toParams(merged));
1325
+ return merged;
1326
+ }
1327
+
1328
+ // packages/storage/src/sqlite/audit.ts
1329
+ function prepareAuditStatements(db) {
1330
+ return {
1331
+ insert: db.prepare(
1332
+ "INSERT INTO audit (id, time, type, payload) VALUES (@id, @time, @type, @payload)"
1333
+ )
1334
+ };
1335
+ }
1336
+ async function appendAudit(s, event) {
1337
+ s.insert.run({
1338
+ id: event.id,
1339
+ time: event.time,
1340
+ type: event.type,
1341
+ payload: event.payload ? JSON.stringify(event.payload) : null
1342
+ });
1343
+ }
1344
+
1345
+ // packages/storage/src/sqlite/token-usage.ts
1346
+ function prepareTokenUsageStatements(db) {
1347
+ return {
1348
+ insert: db.prepare(
1349
+ "INSERT INTO token_usage (id, session_id, provider_id, model, input_tokens, output_tokens, total_tokens, cost_micro, source, created_at) VALUES (@id, @session_id, @provider_id, @model, @input_tokens, @output_tokens, @total_tokens, @cost_micro, @source, @created_at)"
1350
+ ),
1351
+ list: db.prepare(
1352
+ "SELECT id, session_id, provider_id, model, input_tokens, output_tokens, total_tokens, cost_micro, source, created_at FROM token_usage WHERE created_at >= @since ORDER BY created_at DESC LIMIT @limit"
1353
+ ),
1354
+ listBySession: db.prepare(
1355
+ "SELECT id, session_id, provider_id, model, input_tokens, output_tokens, total_tokens, cost_micro, source, created_at FROM token_usage WHERE session_id = @session_id AND created_at >= @since ORDER BY created_at DESC LIMIT @limit"
1356
+ ),
1357
+ listByProvider: db.prepare(
1358
+ "SELECT id, session_id, provider_id, model, input_tokens, output_tokens, total_tokens, cost_micro, source, created_at FROM token_usage WHERE provider_id = @provider_id AND created_at >= @since ORDER BY created_at DESC LIMIT @limit"
1359
+ ),
1360
+ summary: db.prepare(
1361
+ "SELECT provider_id, model, SUM(input_tokens) as total_input_tokens, SUM(output_tokens) as total_output_tokens, SUM(total_tokens) as total_tokens, SUM(COALESCE(cost_micro, 0)) as total_cost_micro, COUNT(*) as call_count FROM token_usage WHERE created_at >= @since GROUP BY provider_id, model ORDER BY total_tokens DESC"
1362
+ ),
1363
+ summaryByProvider: db.prepare(
1364
+ "SELECT provider_id, model, SUM(input_tokens) as total_input_tokens, SUM(output_tokens) as total_output_tokens, SUM(total_tokens) as total_tokens, SUM(COALESCE(cost_micro, 0)) as total_cost_micro, COUNT(*) as call_count FROM token_usage WHERE provider_id = @provider_id AND created_at >= @since GROUP BY provider_id, model ORDER BY total_tokens DESC"
1365
+ )
1366
+ };
1367
+ }
1368
+ function mapTokenUsage(row) {
1369
+ return {
1370
+ id: String(row.id),
1371
+ sessionId: String(row.session_id),
1372
+ providerId: String(row.provider_id),
1373
+ model: String(row.model),
1374
+ inputTokens: Number(row.input_tokens ?? 0),
1375
+ outputTokens: Number(row.output_tokens ?? 0),
1376
+ totalTokens: Number(row.total_tokens ?? 0),
1377
+ costMicro: row.cost_micro != null ? Number(row.cost_micro) : void 0,
1378
+ source: row.source ? String(row.source) : void 0,
1379
+ createdAt: String(row.created_at)
1380
+ };
1381
+ }
1382
+ function mapTokenUsageSummary(row, period) {
1383
+ return {
1384
+ providerId: String(row.provider_id),
1385
+ model: String(row.model),
1386
+ totalInputTokens: Number(row.total_input_tokens ?? 0),
1387
+ totalOutputTokens: Number(row.total_output_tokens ?? 0),
1388
+ totalTokens: Number(row.total_tokens ?? 0),
1389
+ totalCostMicro: Number(row.total_cost_micro ?? 0),
1390
+ callCount: Number(row.call_count ?? 0),
1391
+ period
1392
+ };
1393
+ }
1394
+ var EPOCH = "1970-01-01T00:00:00.000Z";
1395
+ async function appendTokenUsage(s, record) {
1396
+ s.insert.run({
1397
+ id: record.id,
1398
+ session_id: record.sessionId,
1399
+ provider_id: record.providerId,
1400
+ model: record.model,
1401
+ input_tokens: record.inputTokens,
1402
+ output_tokens: record.outputTokens,
1403
+ total_tokens: record.totalTokens,
1404
+ cost_micro: record.costMicro ?? null,
1405
+ source: record.source ?? null,
1406
+ created_at: record.createdAt
1407
+ });
1408
+ }
1409
+ async function listTokenUsage(s, options) {
1410
+ const since = options?.since ?? EPOCH;
1411
+ const limit = options?.limit ?? 100;
1412
+ let rows;
1413
+ if (options?.sessionId) {
1414
+ rows = s.listBySession.all({
1415
+ session_id: options.sessionId,
1416
+ since,
1417
+ limit
1418
+ });
1419
+ } else if (options?.providerId) {
1420
+ rows = s.listByProvider.all({
1421
+ provider_id: options.providerId,
1422
+ since,
1423
+ limit
1424
+ });
1425
+ } else {
1426
+ rows = s.list.all({ since, limit });
1427
+ }
1428
+ return rows.map(mapTokenUsage);
1429
+ }
1430
+ async function getTokenUsageSummary(s, options) {
1431
+ const since = options?.since ?? EPOCH;
1432
+ const period = options?.since ? `since:${options.since}` : "all-time";
1433
+ let rows;
1434
+ if (options?.providerId) {
1435
+ rows = s.summaryByProvider.all({
1436
+ provider_id: options.providerId,
1437
+ since
1438
+ });
1439
+ } else {
1440
+ rows = s.summary.all({ since });
1441
+ }
1442
+ return rows.map((row) => mapTokenUsageSummary(row, period));
1443
+ }
1444
+
1445
+ // packages/storage/src/sqlite/memory-utils.ts
1446
+ function generateId() {
1447
+ return `${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
1448
+ }
1449
+ function now() {
1450
+ return (/* @__PURE__ */ new Date()).toISOString();
1451
+ }
1452
+ function serializeEmbedding(embedding) {
1453
+ if (!embedding) return null;
1454
+ return Buffer.from(embedding.buffer);
1455
+ }
1456
+ function deserializeEmbedding(blob) {
1457
+ if (!blob) return void 0;
1458
+ return new Float32Array(blob.buffer, blob.byteOffset, blob.length / 4);
1459
+ }
1460
+ function serializeArray(arr) {
1461
+ if (!arr || arr.length === 0) return null;
1462
+ return JSON.stringify(arr);
1463
+ }
1464
+ function deserializeArray(json) {
1465
+ if (!json) return void 0;
1466
+ try {
1467
+ return JSON.parse(json);
1468
+ } catch {
1469
+ return void 0;
1470
+ }
1471
+ }
1472
+
1473
+ // packages/storage/src/sqlite/memory-stats.ts
1474
+ function getMemoryStats(db) {
1475
+ const tierStatsQuery = db.prepare(`
1476
+ SELECT
1477
+ ms.tier,
1478
+ COUNT(DISTINCT ms.id) as session_count,
1479
+ COALESCE(SUM(ms.message_count), 0) as message_count
1480
+ FROM memory_sessions ms
1481
+ GROUP BY ms.tier
1482
+ `);
1483
+ const tierRows = tierStatsQuery.all();
1484
+ const tierMap = /* @__PURE__ */ new Map();
1485
+ for (const row of tierRows) {
1486
+ tierMap.set(row.tier, {
1487
+ sessions: row.session_count,
1488
+ messages: row.message_count
1489
+ });
1490
+ }
1491
+ const factsCountQuery = db.prepare(`SELECT COUNT(*) as count FROM knowledge_base`);
1492
+ const factsRow = factsCountQuery.get();
1493
+ const totalFacts = factsRow?.count ?? 0;
1494
+ const sessionBoundsQuery = db.prepare(`
1495
+ SELECT
1496
+ MIN(created_at) as oldest,
1497
+ MAX(created_at) as newest
1498
+ FROM memory_sessions
1499
+ `);
1500
+ const boundsRow = sessionBoundsQuery.get();
1501
+ let totalSessions = 0;
1502
+ let totalMessages = 0;
1503
+ for (const stats of tierMap.values()) {
1504
+ totalSessions += stats.sessions;
1505
+ totalMessages += stats.messages;
1506
+ }
1507
+ const emptyTier = { sessions: 0, messages: 0 };
1508
+ return {
1509
+ tiers: {
1510
+ tier1: tierMap.get(1) ?? emptyTier,
1511
+ tier2: tierMap.get(2) ?? emptyTier,
1512
+ tier3: tierMap.get(3) ?? emptyTier,
1513
+ tier4: tierMap.get(4) ?? emptyTier,
1514
+ tier5: tierMap.get(5) ?? emptyTier
1515
+ },
1516
+ totalSessions,
1517
+ totalMessages,
1518
+ totalFacts,
1519
+ oldestSession: boundsRow?.oldest ?? null,
1520
+ newestSession: boundsRow?.newest ?? null
1521
+ };
1522
+ }
1523
+
1524
+ // packages/storage/src/sqlite/memory.ts
1525
+ function prepareMemoryStatements(db) {
1526
+ return {
1527
+ // Sessions
1528
+ getSessionById: db.prepare(`
1529
+ SELECT * FROM memory_sessions WHERE id = ?
1530
+ `),
1531
+ getActiveSession: db.prepare(`
1532
+ SELECT * FROM memory_sessions
1533
+ WHERE user_id = ? AND ended_at IS NULL
1534
+ ORDER BY started_at DESC LIMIT 1
1535
+ `),
1536
+ listSessions: db.prepare(`
1537
+ SELECT * FROM memory_sessions
1538
+ WHERE user_id = ?
1539
+ ORDER BY started_at DESC
1540
+ LIMIT ?
1541
+ `),
1542
+ listSessionsByTier: db.prepare(`
1543
+ SELECT * FROM memory_sessions
1544
+ WHERE user_id = ? AND tier = ?
1545
+ ORDER BY started_at DESC
1546
+ LIMIT ?
1547
+ `),
1548
+ insertSession: db.prepare(`
1549
+ INSERT INTO memory_sessions
1550
+ (id, user_id, started_at, ended_at, topic, message_count, summary, key_entities, importance_score, tier, archived, created_at, updated_at)
1551
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1552
+ `),
1553
+ updateSession: db.prepare(`
1554
+ UPDATE memory_sessions SET
1555
+ ended_at = COALESCE(?, ended_at),
1556
+ topic = COALESCE(?, topic),
1557
+ message_count = COALESCE(?, message_count),
1558
+ summary = COALESCE(?, summary),
1559
+ key_entities = COALESCE(?, key_entities),
1560
+ importance_score = COALESCE(?, importance_score),
1561
+ tier = COALESCE(?, tier),
1562
+ archived = COALESCE(?, archived),
1563
+ updated_at = ?
1564
+ WHERE id = ?
1565
+ `),
1566
+ // Messages
1567
+ getMessageById: db.prepare(`
1568
+ SELECT * FROM memory_messages WHERE id = ?
1569
+ `),
1570
+ listMessages: db.prepare(`
1571
+ SELECT * FROM memory_messages
1572
+ WHERE session_id = ?
1573
+ ORDER BY timestamp ASC
1574
+ LIMIT ?
1575
+ `),
1576
+ listUnprunedMessages: db.prepare(`
1577
+ SELECT * FROM memory_messages
1578
+ WHERE session_id = ? AND pruned = 0
1579
+ ORDER BY timestamp ASC
1580
+ LIMIT ?
1581
+ `),
1582
+ insertMessage: db.prepare(`
1583
+ INSERT INTO memory_messages
1584
+ (id, session_id, content, embedding, embedding_dim, timestamp, role, entities, importance, pruned, created_at)
1585
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1586
+ `),
1587
+ updateMessageImportance: db.prepare(`
1588
+ UPDATE memory_messages SET importance = ? WHERE id = ?
1589
+ `),
1590
+ pruneMessages: db.prepare(`
1591
+ UPDATE memory_messages SET pruned = 1 WHERE session_id = ? AND id NOT IN (SELECT value FROM json_each(?))
1592
+ `),
1593
+ // Summaries
1594
+ getSummary: db.prepare(`
1595
+ SELECT * FROM memory_summaries WHERE session_id = ? AND level = ?
1596
+ `),
1597
+ listSummaries: db.prepare(`
1598
+ SELECT * FROM memory_summaries WHERE session_id = ? ORDER BY level ASC
1599
+ `),
1600
+ insertSummary: db.prepare(`
1601
+ INSERT OR REPLACE INTO memory_summaries
1602
+ (id, session_id, level, content, embedding, embedding_dim, created_at)
1603
+ VALUES (?, ?, ?, ?, ?, ?, ?)
1604
+ `),
1605
+ // Knowledge
1606
+ getFactById: db.prepare(`
1607
+ SELECT * FROM knowledge_base WHERE id = ?
1608
+ `),
1609
+ listFacts: db.prepare(`
1610
+ SELECT * FROM knowledge_base
1611
+ WHERE user_id = ?
1612
+ ORDER BY confidence DESC, updated_at DESC
1613
+ LIMIT ?
1614
+ `),
1615
+ searchFacts: db.prepare(`
1616
+ SELECT * FROM knowledge_base
1617
+ WHERE user_id = ? AND fact LIKE ?
1618
+ ORDER BY confidence DESC
1619
+ LIMIT ?
1620
+ `),
1621
+ insertFact: db.prepare(`
1622
+ INSERT INTO knowledge_base
1623
+ (id, user_id, fact, source_session_id, confidence, category, embedding, embedding_dim, last_verified, created_at, updated_at)
1624
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1625
+ `),
1626
+ updateFact: db.prepare(`
1627
+ UPDATE knowledge_base SET
1628
+ fact = COALESCE(?, fact),
1629
+ confidence = COALESCE(?, confidence),
1630
+ category = COALESCE(?, category),
1631
+ embedding = COALESCE(?, embedding),
1632
+ embedding_dim = COALESCE(?, embedding_dim),
1633
+ last_verified = COALESCE(?, last_verified),
1634
+ updated_at = ?
1635
+ WHERE id = ?
1636
+ `),
1637
+ deleteFact: db.prepare(`
1638
+ DELETE FROM knowledge_base WHERE id = ?
1639
+ `)
1640
+ };
1641
+ }
1642
+ function getSessionById2(s, id) {
1643
+ const row = s.getSessionById.get(id);
1644
+ if (!row) return void 0;
1645
+ return mapSessionRow(row);
1646
+ }
1647
+ function getActiveSession(s, userId) {
1648
+ const row = s.getActiveSession.get(userId);
1649
+ if (!row) return void 0;
1650
+ return mapSessionRow(row);
1651
+ }
1652
+ function listSessions2(s, userId, options) {
1653
+ const limit = options?.limit ?? 100;
1654
+ let rows;
1655
+ if (options?.tier) {
1656
+ rows = s.listSessionsByTier.all(userId, options.tier, limit);
1657
+ } else {
1658
+ rows = s.listSessions.all(userId, limit);
1659
+ }
1660
+ return rows.map(mapSessionRow);
1661
+ }
1662
+ function createSession2(s, session) {
1663
+ const id = generateId();
1664
+ const timestamp = now();
1665
+ s.insertSession.run(
1666
+ id,
1667
+ session.userId,
1668
+ session.startedAt,
1669
+ session.endedAt ?? null,
1670
+ session.topic ?? null,
1671
+ session.messageCount,
1672
+ session.summary ?? null,
1673
+ serializeArray(session.keyEntities),
1674
+ session.importanceScore,
1675
+ session.tier,
1676
+ session.archived ? 1 : 0,
1677
+ timestamp,
1678
+ timestamp
1679
+ );
1680
+ return { ...session, id, createdAt: timestamp, updatedAt: timestamp };
1681
+ }
1682
+ function updateSession2(s, id, update) {
1683
+ s.updateSession.run(
1684
+ update.endedAt ?? null,
1685
+ update.topic ?? null,
1686
+ update.messageCount ?? null,
1687
+ update.summary ?? null,
1688
+ update.keyEntities ? serializeArray(update.keyEntities) : null,
1689
+ update.importanceScore ?? null,
1690
+ update.tier ?? null,
1691
+ update.archived !== void 0 ? update.archived ? 1 : 0 : null,
1692
+ now(),
1693
+ id
1694
+ );
1695
+ }
1696
+ function mapSessionRow(row) {
1697
+ return {
1698
+ id: row.id,
1699
+ userId: row.user_id,
1700
+ startedAt: row.started_at,
1701
+ endedAt: row.ended_at,
1702
+ topic: row.topic,
1703
+ messageCount: row.message_count,
1704
+ summary: row.summary,
1705
+ keyEntities: deserializeArray(row.key_entities),
1706
+ importanceScore: row.importance_score,
1707
+ tier: row.tier,
1708
+ archived: Boolean(row.archived),
1709
+ createdAt: row.created_at,
1710
+ updatedAt: row.updated_at
1711
+ };
1712
+ }
1713
+ function listMessages(s, sessionId, options) {
1714
+ const limit = options?.limit ?? 1e3;
1715
+ const stmt = options?.includePruned ? s.listMessages : s.listUnprunedMessages;
1716
+ const rows = stmt.all(sessionId, limit);
1717
+ return rows.map(mapMessageRow);
1718
+ }
1719
+ function createMessage(s, message) {
1720
+ const id = generateId();
1721
+ const timestamp = now();
1722
+ s.insertMessage.run(
1723
+ id,
1724
+ message.sessionId,
1725
+ message.content,
1726
+ serializeEmbedding(message.embedding),
1727
+ message.embeddingDim ?? null,
1728
+ message.timestamp,
1729
+ message.role,
1730
+ serializeArray(message.entities),
1731
+ message.importance,
1732
+ message.pruned ? 1 : 0,
1733
+ timestamp
1734
+ );
1735
+ return { ...message, id, createdAt: timestamp };
1736
+ }
1737
+ function pruneMessages(s, sessionId, keepIds) {
1738
+ const result = s.pruneMessages.run(sessionId, JSON.stringify(keepIds));
1739
+ return result.changes;
1740
+ }
1741
+ function mapMessageRow(row) {
1742
+ return {
1743
+ id: row.id,
1744
+ sessionId: row.session_id,
1745
+ content: row.content,
1746
+ embedding: deserializeEmbedding(row.embedding),
1747
+ embeddingDim: row.embedding_dim,
1748
+ timestamp: row.timestamp,
1749
+ role: row.role,
1750
+ entities: deserializeArray(row.entities),
1751
+ importance: row.importance,
1752
+ pruned: Boolean(row.pruned),
1753
+ createdAt: row.created_at
1754
+ };
1755
+ }
1756
+ function getSummary(s, sessionId, level) {
1757
+ const row = s.getSummary.get(sessionId, level);
1758
+ if (!row) return void 0;
1759
+ return mapSummaryRow(row);
1760
+ }
1761
+ function createSummary(s, summary) {
1762
+ const id = `${summary.sessionId}_L${summary.level}`;
1763
+ const timestamp = now();
1764
+ s.insertSummary.run(
1765
+ id,
1766
+ summary.sessionId,
1767
+ summary.level,
1768
+ summary.content,
1769
+ serializeEmbedding(summary.embedding),
1770
+ summary.embeddingDim ?? null,
1771
+ timestamp
1772
+ );
1773
+ return { ...summary, id, createdAt: timestamp };
1774
+ }
1775
+ function mapSummaryRow(row) {
1776
+ return {
1777
+ id: row.id,
1778
+ sessionId: row.session_id,
1779
+ level: row.level,
1780
+ content: row.content,
1781
+ embedding: deserializeEmbedding(row.embedding),
1782
+ embeddingDim: row.embedding_dim,
1783
+ createdAt: row.created_at
1784
+ };
1785
+ }
1786
+ function listFacts(s, userId, limit = 100) {
1787
+ const rows = s.listFacts.all(userId, limit);
1788
+ return rows.map(mapFactRow);
1789
+ }
1790
+ function searchFacts(s, userId, query, limit = 10) {
1791
+ const rows = s.searchFacts.all(userId, `%${query}%`, limit);
1792
+ return rows.map(mapFactRow);
1793
+ }
1794
+ function createFact(s, fact) {
1795
+ const id = generateId();
1796
+ const timestamp = now();
1797
+ s.insertFact.run(
1798
+ id,
1799
+ fact.userId,
1800
+ fact.fact,
1801
+ fact.sourceSessionId ?? null,
1802
+ fact.confidence,
1803
+ fact.category ?? null,
1804
+ serializeEmbedding(fact.embedding),
1805
+ fact.embeddingDim ?? null,
1806
+ fact.lastVerified ?? null,
1807
+ timestamp,
1808
+ timestamp
1809
+ );
1810
+ return { ...fact, id, createdAt: timestamp, updatedAt: timestamp };
1811
+ }
1812
+ function deleteFact(s, id) {
1813
+ const result = s.deleteFact.run(id);
1814
+ return result.changes > 0;
1815
+ }
1816
+ function mapFactRow(row) {
1817
+ return {
1818
+ id: row.id,
1819
+ userId: row.user_id,
1820
+ fact: row.fact,
1821
+ sourceSessionId: row.source_session_id,
1822
+ confidence: row.confidence,
1823
+ category: row.category,
1824
+ embedding: deserializeEmbedding(row.embedding),
1825
+ embeddingDim: row.embedding_dim,
1826
+ lastVerified: row.last_verified,
1827
+ createdAt: row.created_at,
1828
+ updatedAt: row.updated_at
1829
+ };
1830
+ }
1831
+
1832
+ // packages/storage/src/sqlite/sync.ts
1833
+ function prepareSyncStatements(db) {
1834
+ return {
1835
+ getByDeviceId: db.prepare(
1836
+ "SELECT id, device_id, user_id, last_sync_at, pending_changes, created_at, updated_at FROM device_sync_state WHERE device_id = @device_id"
1837
+ ),
1838
+ listByUserId: db.prepare(
1839
+ "SELECT id, device_id, user_id, last_sync_at, pending_changes, created_at, updated_at FROM device_sync_state WHERE user_id = @user_id ORDER BY updated_at DESC"
1840
+ ),
1841
+ insert: db.prepare(
1842
+ "INSERT INTO device_sync_state (id, device_id, user_id, last_sync_at, pending_changes, created_at, updated_at) VALUES (@id, @device_id, @user_id, @last_sync_at, @pending_changes, @created_at, @updated_at)"
1843
+ ),
1844
+ update: db.prepare(
1845
+ "UPDATE device_sync_state SET last_sync_at = @last_sync_at, pending_changes = @pending_changes, updated_at = @updated_at WHERE device_id = @device_id"
1846
+ ),
1847
+ delete: db.prepare("DELETE FROM device_sync_state WHERE device_id = @device_id"),
1848
+ incrementPending: db.prepare(
1849
+ "UPDATE device_sync_state SET pending_changes = pending_changes + @delta, updated_at = @updated_at WHERE user_id = @user_id AND device_id != @excluded_device_id"
1850
+ )
1851
+ };
1852
+ }
1853
+ function mapSyncState(row) {
1854
+ return {
1855
+ id: String(row.id),
1856
+ deviceId: String(row.device_id),
1857
+ userId: String(row.user_id),
1858
+ lastSyncAt: row.last_sync_at != null ? Number(row.last_sync_at) : void 0,
1859
+ pendingChanges: Number(row.pending_changes ?? 0),
1860
+ createdAt: String(row.created_at),
1861
+ updatedAt: String(row.updated_at)
1862
+ };
1863
+ }
1864
+ function getSyncState(s, deviceId) {
1865
+ const row = s.getByDeviceId.get({ device_id: deviceId });
1866
+ return row ? mapSyncState(row) : void 0;
1867
+ }
1868
+ function updateSyncState(s, deviceId, userId, update) {
1869
+ const existing = getSyncState(s, deviceId);
1870
+ const now2 = (/* @__PURE__ */ new Date()).toISOString();
1871
+ if (existing) {
1872
+ const updatedState = {
1873
+ ...existing,
1874
+ lastSyncAt: update.lastSyncAt ?? existing.lastSyncAt,
1875
+ pendingChanges: update.pendingChanges ?? existing.pendingChanges,
1876
+ updatedAt: now2
1877
+ };
1878
+ s.update.run({
1879
+ device_id: deviceId,
1880
+ last_sync_at: updatedState.lastSyncAt ?? null,
1881
+ pending_changes: updatedState.pendingChanges,
1882
+ updated_at: now2
1883
+ });
1884
+ return updatedState;
1885
+ }
1886
+ const id = crypto.randomUUID();
1887
+ const newState = {
1888
+ id,
1889
+ deviceId,
1890
+ userId,
1891
+ lastSyncAt: update.lastSyncAt,
1892
+ pendingChanges: update.pendingChanges ?? 0,
1893
+ createdAt: now2,
1894
+ updatedAt: now2
1895
+ };
1896
+ s.insert.run({
1897
+ id,
1898
+ device_id: deviceId,
1899
+ user_id: userId,
1900
+ last_sync_at: newState.lastSyncAt ?? null,
1901
+ pending_changes: newState.pendingChanges,
1902
+ created_at: now2,
1903
+ updated_at: now2
1904
+ });
1905
+ return newState;
1906
+ }
1907
+ function listSyncStates(s, userId) {
1908
+ const rows = s.listByUserId.all({ user_id: userId });
1909
+ return rows.map(mapSyncState);
1910
+ }
1911
+ function deleteSyncState(s, deviceId) {
1912
+ const result = s.delete.run({ device_id: deviceId });
1913
+ return result.changes > 0;
1914
+ }
1915
+ function incrementPendingChanges(s, userId, excludedDeviceId, delta = 1) {
1916
+ s.incrementPending.run({
1917
+ user_id: userId,
1918
+ excluded_device_id: excludedDeviceId,
1919
+ delta,
1920
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
1921
+ });
1922
+ }
1923
+ function markDeviceSynced(s, deviceId, userId) {
1924
+ return updateSyncState(s, deviceId, userId, {
1925
+ lastSyncAt: Date.now(),
1926
+ pendingChanges: 0
1927
+ });
1928
+ }
1929
+
1930
+ // packages/storage/src/sqlite/reactions.ts
1931
+ import { randomUUID as randomUUID4 } from "node:crypto";
1932
+ function prepareReactionStatements(db) {
1933
+ return {
1934
+ upsert: db.prepare(
1935
+ "INSERT INTO message_reactions (id, session_id, message_id, reaction, created_at) VALUES (@id, @session_id, @message_id, @reaction, @created_at) ON CONFLICT(message_id) DO UPDATE SET reaction = excluded.reaction, created_at = excluded.created_at"
1936
+ ),
1937
+ getByMessageId: db.prepare(
1938
+ "SELECT id, session_id, message_id, reaction, created_at FROM message_reactions WHERE message_id = @message_id"
1939
+ ),
1940
+ listBySession: db.prepare(
1941
+ "SELECT id, session_id, message_id, reaction, created_at FROM message_reactions WHERE session_id = @session_id ORDER BY created_at DESC"
1942
+ ),
1943
+ deleteByMessageId: db.prepare(
1944
+ "DELETE FROM message_reactions WHERE message_id = @message_id"
1945
+ )
1946
+ };
1947
+ }
1948
+ function mapReaction(row) {
1949
+ return {
1950
+ id: String(row.id),
1951
+ sessionId: String(row.session_id),
1952
+ messageId: String(row.message_id),
1953
+ reaction: String(row.reaction),
1954
+ createdAt: String(row.created_at)
1955
+ };
1956
+ }
1957
+ function setReaction(s, sessionId, messageId, reaction) {
1958
+ const now2 = (/* @__PURE__ */ new Date()).toISOString();
1959
+ const id = randomUUID4();
1960
+ s.upsert.run({
1961
+ id,
1962
+ session_id: sessionId,
1963
+ message_id: messageId,
1964
+ reaction,
1965
+ created_at: now2
1966
+ });
1967
+ const stored = getReactionByMessageId(s, messageId);
1968
+ return stored ?? {
1969
+ id,
1970
+ sessionId,
1971
+ messageId,
1972
+ reaction,
1973
+ createdAt: now2
1974
+ };
1975
+ }
1976
+ function getReactionByMessageId(s, messageId) {
1977
+ const row = s.getByMessageId.get({ message_id: messageId });
1978
+ return row ? mapReaction(row) : void 0;
1979
+ }
1980
+ function listReactionsBySession(s, sessionId) {
1981
+ const rows = s.listBySession.all({ session_id: sessionId });
1982
+ return rows.map(mapReaction);
1983
+ }
1984
+ function deleteReaction(s, messageId) {
1985
+ const result = s.deleteByMessageId.run({ message_id: messageId });
1986
+ return result.changes > 0;
1987
+ }
1988
+
1989
+ // packages/storage/src/sqlite/session-providers.ts
1990
+ import { randomUUID as randomUUID5 } from "node:crypto";
1991
+ function prepareSessionProviderStatements(db) {
1992
+ return {
1993
+ upsertUsage: db.prepare(
1994
+ "INSERT INTO session_providers (session_id, provider_id, model, first_used_at, last_used_at, usage_count) VALUES (@session_id, @provider_id, @model, @first_used_at, @last_used_at, @usage_count) ON CONFLICT(session_id, provider_id) DO UPDATE SET model = excluded.model, last_used_at = excluded.last_used_at, usage_count = session_providers.usage_count + 1"
1995
+ ),
1996
+ insertSwitch: db.prepare(
1997
+ "INSERT INTO provider_switches (id, session_id, from_provider_id, to_provider_id, from_model, to_model, reason, created_at) VALUES (@id, @session_id, @from_provider_id, @to_provider_id, @from_model, @to_model, @reason, @created_at)"
1998
+ )
1999
+ };
2000
+ }
2001
+ async function upsertSessionProviderUsage(s, entry) {
2002
+ const usedAt = entry.usedAt ?? (/* @__PURE__ */ new Date()).toISOString();
2003
+ s.upsertUsage.run({
2004
+ session_id: entry.sessionId,
2005
+ provider_id: entry.providerId,
2006
+ model: entry.model ?? null,
2007
+ first_used_at: usedAt,
2008
+ last_used_at: usedAt,
2009
+ usage_count: 1
2010
+ });
2011
+ }
2012
+ async function appendProviderSwitch(s, record) {
2013
+ const id = record.id ?? randomUUID5();
2014
+ const createdAt = record.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
2015
+ s.insertSwitch.run({
2016
+ id,
2017
+ session_id: record.sessionId,
2018
+ from_provider_id: record.fromProviderId ?? null,
2019
+ to_provider_id: record.toProviderId ?? null,
2020
+ from_model: record.fromModel ?? null,
2021
+ to_model: record.toModel ?? null,
2022
+ reason: record.reason ?? null,
2023
+ created_at: createdAt
2024
+ });
2025
+ return {
2026
+ id,
2027
+ sessionId: record.sessionId,
2028
+ fromProviderId: record.fromProviderId,
2029
+ toProviderId: record.toProviderId,
2030
+ fromModel: record.fromModel,
2031
+ toModel: record.toModel,
2032
+ reason: record.reason,
2033
+ createdAt
2034
+ };
2035
+ }
2036
+
2037
+ // packages/storage/src/sqlite/agent-runs.ts
2038
+ function prepareAgentRunStatements(db) {
2039
+ return {
2040
+ get: db.prepare(
2041
+ "SELECT id, session_id, agent_id, parent_agent_id, parent_run_id, lane, status, created_at, started_at, ended_at, timeout_ms, channel, chat_id, user_id, provider_id, model, system, text, metadata, metrics, result_summary, error FROM agent_runs WHERE id = @id"
2042
+ ),
2043
+ upsert: db.prepare(
2044
+ "INSERT INTO agent_runs (id, session_id, agent_id, parent_agent_id, parent_run_id, lane, status, created_at, started_at, ended_at, timeout_ms, channel, chat_id, user_id, provider_id, model, system, text, metadata, metrics, result_summary, error) VALUES (@id, @session_id, @agent_id, @parent_agent_id, @parent_run_id, @lane, @status, @created_at, @started_at, @ended_at, @timeout_ms, @channel, @chat_id, @user_id, @provider_id, @model, @system, @text, @metadata, @metrics, @result_summary, @error) ON CONFLICT(id) DO UPDATE SET session_id = excluded.session_id, agent_id = excluded.agent_id, parent_agent_id = excluded.parent_agent_id, parent_run_id = excluded.parent_run_id, lane = excluded.lane, status = excluded.status, created_at = excluded.created_at, started_at = excluded.started_at, ended_at = excluded.ended_at, timeout_ms = excluded.timeout_ms, channel = excluded.channel, chat_id = excluded.chat_id, user_id = excluded.user_id, provider_id = excluded.provider_id, model = excluded.model, system = excluded.system, text = excluded.text, metadata = excluded.metadata, metrics = excluded.metrics, result_summary = excluded.result_summary, error = excluded.error"
2045
+ ),
2046
+ eventInsert: db.prepare(
2047
+ "INSERT INTO agent_run_events (id, run_id, time, type, payload) VALUES (@id, @run_id, @time, @type, @payload)"
2048
+ ),
2049
+ eventList: db.prepare(
2050
+ "SELECT id, run_id, time, type, payload FROM agent_run_events WHERE run_id = @run_id ORDER BY time DESC LIMIT @limit"
2051
+ )
2052
+ };
2053
+ }
2054
+ function mapAgentRun(row) {
2055
+ const parseJson = (value) => {
2056
+ if (!value) return void 0;
2057
+ try {
2058
+ return JSON.parse(String(value));
2059
+ } catch {
2060
+ return void 0;
2061
+ }
2062
+ };
2063
+ return {
2064
+ id: String(row.id),
2065
+ sessionId: row.session_id ? String(row.session_id) : void 0,
2066
+ agentId: row.agent_id ? String(row.agent_id) : void 0,
2067
+ parentAgentId: row.parent_agent_id ? String(row.parent_agent_id) : void 0,
2068
+ parentRunId: row.parent_run_id ? String(row.parent_run_id) : void 0,
2069
+ lane: String(row.lane),
2070
+ status: String(row.status),
2071
+ createdAt: String(row.created_at),
2072
+ startedAt: row.started_at ? String(row.started_at) : void 0,
2073
+ endedAt: row.ended_at ? String(row.ended_at) : void 0,
2074
+ timeoutMs: row.timeout_ms === null || row.timeout_ms === void 0 ? void 0 : Number(row.timeout_ms),
2075
+ channel: row.channel ? String(row.channel) : void 0,
2076
+ chatId: row.chat_id ? String(row.chat_id) : void 0,
2077
+ userId: row.user_id ? String(row.user_id) : void 0,
2078
+ providerId: row.provider_id ? String(row.provider_id) : void 0,
2079
+ model: row.model ? String(row.model) : void 0,
2080
+ system: row.system ? String(row.system) : void 0,
2081
+ text: row.text ? String(row.text) : void 0,
2082
+ metadata: parseJson(row.metadata),
2083
+ metrics: parseJson(row.metrics),
2084
+ resultSummary: row.result_summary ? String(row.result_summary) : void 0,
2085
+ error: row.error ? String(row.error) : void 0
2086
+ };
2087
+ }
2088
+ function mapAgentRunEvent(row) {
2089
+ return {
2090
+ id: String(row.id),
2091
+ runId: String(row.run_id),
2092
+ time: String(row.time),
2093
+ type: String(row.type),
2094
+ payload: row.payload ? JSON.parse(String(row.payload)) : void 0
2095
+ };
2096
+ }
2097
+ async function getAgentRun(s, id) {
2098
+ const row = s.get.get({ id });
2099
+ return row ? mapAgentRun(row) : void 0;
2100
+ }
2101
+ async function upsertAgentRun(s, record) {
2102
+ s.upsert.run({
2103
+ id: record.id,
2104
+ session_id: record.sessionId ?? null,
2105
+ agent_id: record.agentId ?? null,
2106
+ parent_agent_id: record.parentAgentId ?? null,
2107
+ parent_run_id: record.parentRunId ?? null,
2108
+ lane: record.lane,
2109
+ status: record.status,
2110
+ created_at: record.createdAt,
2111
+ started_at: record.startedAt ?? null,
2112
+ ended_at: record.endedAt ?? null,
2113
+ timeout_ms: record.timeoutMs ?? null,
2114
+ channel: record.channel ?? null,
2115
+ chat_id: record.chatId ?? null,
2116
+ user_id: record.userId ?? null,
2117
+ provider_id: record.providerId ?? null,
2118
+ model: record.model ?? null,
2119
+ system: record.system ?? null,
2120
+ text: record.text ?? null,
2121
+ metadata: record.metadata ? JSON.stringify(record.metadata) : null,
2122
+ metrics: record.metrics ? JSON.stringify(record.metrics) : null,
2123
+ result_summary: record.resultSummary ?? null,
2124
+ error: record.error ?? null
2125
+ });
2126
+ return record;
2127
+ }
2128
+ async function listAgentRuns(db, options) {
2129
+ const clauses = [];
2130
+ const params = {};
2131
+ if (options?.status) {
2132
+ clauses.push("status = @status");
2133
+ params.status = options.status;
2134
+ }
2135
+ if (options?.lane) {
2136
+ clauses.push("lane = @lane");
2137
+ params.lane = options.lane;
2138
+ }
2139
+ if (options?.sessionId) {
2140
+ clauses.push("session_id = @session_id");
2141
+ params.session_id = options.sessionId;
2142
+ }
2143
+ if (options?.since) {
2144
+ clauses.push("created_at >= @since");
2145
+ params.since = options.since;
2146
+ }
2147
+ const limit = options?.limit ?? 50;
2148
+ const where = clauses.length ? `WHERE ${clauses.join(" AND ")}` : "";
2149
+ const query = `SELECT id, session_id, agent_id, parent_agent_id, parent_run_id, lane, status, created_at, started_at, ended_at, timeout_ms, channel, chat_id, user_id, provider_id, model, system, text, metadata, metrics, result_summary, error FROM agent_runs ${where} ORDER BY created_at DESC LIMIT @limit`;
2150
+ const stmt = db.prepare(query);
2151
+ const rows = stmt.all({ ...params, limit });
2152
+ return rows.map(mapAgentRun);
2153
+ }
2154
+ async function appendAgentRunEvent(s, event) {
2155
+ s.eventInsert.run({
2156
+ id: event.id,
2157
+ run_id: event.runId,
2158
+ time: event.time,
2159
+ type: event.type,
2160
+ payload: event.payload ? JSON.stringify(event.payload) : null
2161
+ });
2162
+ }
2163
+ async function listAgentRunEvents(s, runId, options) {
2164
+ const limit = options?.limit ?? 50;
2165
+ const rows = s.eventList.all({ run_id: runId, limit });
2166
+ return rows.map(mapAgentRunEvent).reverse();
2167
+ }
2168
+
2169
+ // packages/storage/src/sqlite/agent-queue.ts
2170
+ function prepareAgentQueueStatements(db) {
2171
+ return {
2172
+ get: db.prepare(
2173
+ "SELECT id, session_id, agent_id, parent_agent_id, parent_run_id, lane, status, created_at, started_at, ended_at, lease_until, priority, channel, chat_id, user_id, provider_id, model, system, text, timeout_ms, tool_policy, metadata, error FROM agent_queue WHERE id = @id"
2174
+ ),
2175
+ upsert: db.prepare(
2176
+ "INSERT INTO agent_queue (id, session_id, agent_id, parent_agent_id, parent_run_id, lane, status, created_at, started_at, ended_at, lease_until, priority, channel, chat_id, user_id, provider_id, model, system, text, timeout_ms, tool_policy, metadata, error) VALUES (@id, @session_id, @agent_id, @parent_agent_id, @parent_run_id, @lane, @status, @created_at, @started_at, @ended_at, @lease_until, @priority, @channel, @chat_id, @user_id, @provider_id, @model, @system, @text, @timeout_ms, @tool_policy, @metadata, @error) ON CONFLICT(id) DO UPDATE SET session_id = excluded.session_id, agent_id = excluded.agent_id, parent_agent_id = excluded.parent_agent_id, parent_run_id = excluded.parent_run_id, lane = excluded.lane, status = excluded.status, created_at = excluded.created_at, started_at = excluded.started_at, ended_at = excluded.ended_at, lease_until = excluded.lease_until, priority = excluded.priority, channel = excluded.channel, chat_id = excluded.chat_id, user_id = excluded.user_id, provider_id = excluded.provider_id, model = excluded.model, system = excluded.system, text = excluded.text, timeout_ms = excluded.timeout_ms, tool_policy = excluded.tool_policy, metadata = excluded.metadata, error = excluded.error"
2177
+ )
2178
+ };
2179
+ }
2180
+ var mapRecord = (row) => {
2181
+ const parseJson = (value) => {
2182
+ if (!value) return void 0;
2183
+ try {
2184
+ return JSON.parse(String(value));
2185
+ } catch {
2186
+ return void 0;
2187
+ }
2188
+ };
2189
+ return {
2190
+ id: String(row.id),
2191
+ sessionId: row.session_id ? String(row.session_id) : void 0,
2192
+ agentId: row.agent_id ? String(row.agent_id) : void 0,
2193
+ parentAgentId: row.parent_agent_id ? String(row.parent_agent_id) : void 0,
2194
+ parentRunId: row.parent_run_id ? String(row.parent_run_id) : void 0,
2195
+ lane: String(row.lane),
2196
+ status: String(row.status),
2197
+ createdAt: String(row.created_at),
2198
+ startedAt: row.started_at ? String(row.started_at) : void 0,
2199
+ endedAt: row.ended_at ? String(row.ended_at) : void 0,
2200
+ leaseUntil: row.lease_until ? String(row.lease_until) : void 0,
2201
+ priority: row.priority === null || row.priority === void 0 ? void 0 : Number(row.priority),
2202
+ channel: row.channel ? String(row.channel) : void 0,
2203
+ chatId: row.chat_id ? String(row.chat_id) : void 0,
2204
+ userId: row.user_id ? String(row.user_id) : void 0,
2205
+ providerId: row.provider_id ? String(row.provider_id) : void 0,
2206
+ model: row.model ? String(row.model) : void 0,
2207
+ system: row.system ? String(row.system) : void 0,
2208
+ text: row.text ? String(row.text) : void 0,
2209
+ timeoutMs: row.timeout_ms === null || row.timeout_ms === void 0 ? void 0 : Number(row.timeout_ms),
2210
+ toolPolicy: parseJson(row.tool_policy),
2211
+ metadata: parseJson(row.metadata),
2212
+ error: row.error ? String(row.error) : void 0
2213
+ };
2214
+ };
2215
+ async function getAgentQueue(s, id) {
2216
+ const row = s.get.get({ id });
2217
+ return row ? mapRecord(row) : void 0;
2218
+ }
2219
+ async function upsertAgentQueue(s, record) {
2220
+ s.upsert.run({
2221
+ id: record.id,
2222
+ session_id: record.sessionId ?? null,
2223
+ agent_id: record.agentId ?? null,
2224
+ parent_agent_id: record.parentAgentId ?? null,
2225
+ parent_run_id: record.parentRunId ?? null,
2226
+ lane: record.lane,
2227
+ status: record.status,
2228
+ created_at: record.createdAt,
2229
+ started_at: record.startedAt ?? null,
2230
+ ended_at: record.endedAt ?? null,
2231
+ lease_until: record.leaseUntil ?? null,
2232
+ priority: record.priority ?? null,
2233
+ channel: record.channel ?? null,
2234
+ chat_id: record.chatId ?? null,
2235
+ user_id: record.userId ?? null,
2236
+ provider_id: record.providerId ?? null,
2237
+ model: record.model ?? null,
2238
+ system: record.system ?? null,
2239
+ text: record.text ?? null,
2240
+ timeout_ms: record.timeoutMs ?? null,
2241
+ tool_policy: record.toolPolicy ? JSON.stringify(record.toolPolicy) : null,
2242
+ metadata: record.metadata ? JSON.stringify(record.metadata) : null,
2243
+ error: record.error ?? null
2244
+ });
2245
+ return record;
2246
+ }
2247
+ async function listAgentQueue(db, options) {
2248
+ const clauses = [];
2249
+ const params = {};
2250
+ if (options?.status) {
2251
+ clauses.push("status = @status");
2252
+ params.status = options.status;
2253
+ }
2254
+ if (options?.lane) {
2255
+ clauses.push("lane = @lane");
2256
+ params.lane = options.lane;
2257
+ }
2258
+ if (options?.sessionId) {
2259
+ clauses.push("session_id = @session_id");
2260
+ params.session_id = options.sessionId;
2261
+ }
2262
+ if (options?.agentId) {
2263
+ clauses.push("agent_id = @agent_id");
2264
+ params.agent_id = options.agentId;
2265
+ }
2266
+ const limit = options?.limit ?? 50;
2267
+ const order = options?.order === "asc" ? "ASC" : "DESC";
2268
+ const orderBy = options?.orderBy === "priority" ? "COALESCE(priority, 0) DESC, created_at" : "created_at";
2269
+ const where = clauses.length ? `WHERE ${clauses.join(" AND ")}` : "";
2270
+ const query = `SELECT id, session_id, agent_id, parent_agent_id, parent_run_id, lane, status, created_at, started_at, ended_at, lease_until, priority, channel, chat_id, user_id, provider_id, model, system, text, timeout_ms, tool_policy, metadata, error FROM agent_queue ${where} ORDER BY ${orderBy} ${order} LIMIT @limit`;
2271
+ const stmt = db.prepare(query);
2272
+ const rows = stmt.all({ ...params, limit });
2273
+ return rows.map(mapRecord);
2274
+ }
2275
+
2276
+ // packages/storage/src/sqlite/session-inbox.ts
2277
+ function prepareSessionInboxStatements(db) {
2278
+ return {
2279
+ get: db.prepare(
2280
+ "SELECT id, session_id, status, created_at, started_at, ended_at, channel, chat_id, user_id, text, metadata, error FROM session_inbox WHERE id = @id"
2281
+ ),
2282
+ upsert: db.prepare(
2283
+ "INSERT INTO session_inbox (id, session_id, status, created_at, started_at, ended_at, channel, chat_id, user_id, text, metadata, error) VALUES (@id, @session_id, @status, @created_at, @started_at, @ended_at, @channel, @chat_id, @user_id, @text, @metadata, @error) ON CONFLICT(id) DO UPDATE SET session_id = excluded.session_id, status = excluded.status, created_at = excluded.created_at, started_at = excluded.started_at, ended_at = excluded.ended_at, channel = excluded.channel, chat_id = excluded.chat_id, user_id = excluded.user_id, text = excluded.text, metadata = excluded.metadata, error = excluded.error"
2284
+ )
2285
+ };
2286
+ }
2287
+ var mapRecord2 = (row) => {
2288
+ const parseJson = (value) => {
2289
+ if (!value) return void 0;
2290
+ try {
2291
+ return JSON.parse(String(value));
2292
+ } catch {
2293
+ return void 0;
2294
+ }
2295
+ };
2296
+ return {
2297
+ id: String(row.id),
2298
+ sessionId: String(row.session_id),
2299
+ status: String(row.status),
2300
+ createdAt: String(row.created_at),
2301
+ startedAt: row.started_at ? String(row.started_at) : void 0,
2302
+ endedAt: row.ended_at ? String(row.ended_at) : void 0,
2303
+ channel: row.channel ? String(row.channel) : void 0,
2304
+ chatId: row.chat_id ? String(row.chat_id) : void 0,
2305
+ userId: row.user_id ? String(row.user_id) : void 0,
2306
+ text: row.text ? String(row.text) : void 0,
2307
+ metadata: parseJson(row.metadata),
2308
+ error: row.error ? String(row.error) : void 0
2309
+ };
2310
+ };
2311
+ async function getSessionInbox(s, id) {
2312
+ const row = s.get.get({ id });
2313
+ return row ? mapRecord2(row) : void 0;
2314
+ }
2315
+ async function upsertSessionInbox(s, record) {
2316
+ s.upsert.run({
2317
+ id: record.id,
2318
+ session_id: record.sessionId,
2319
+ status: record.status,
2320
+ created_at: record.createdAt,
2321
+ started_at: record.startedAt ?? null,
2322
+ ended_at: record.endedAt ?? null,
2323
+ channel: record.channel ?? null,
2324
+ chat_id: record.chatId ?? null,
2325
+ user_id: record.userId ?? null,
2326
+ text: record.text ?? null,
2327
+ metadata: record.metadata ? JSON.stringify(record.metadata) : null,
2328
+ error: record.error ?? null
2329
+ });
2330
+ return record;
2331
+ }
2332
+ async function listSessionInbox(db, options) {
2333
+ const clauses = [];
2334
+ const params = {};
2335
+ if (options?.sessionId) {
2336
+ clauses.push("session_id = @session_id");
2337
+ params.session_id = options.sessionId;
2338
+ }
2339
+ if (options?.status) {
2340
+ clauses.push("status = @status");
2341
+ params.status = options.status;
2342
+ }
2343
+ const limit = options?.limit ?? 50;
2344
+ const order = options?.order === "asc" ? "ASC" : "DESC";
2345
+ const where = clauses.length ? `WHERE ${clauses.join(" AND ")}` : "";
2346
+ const query = `SELECT id, session_id, status, created_at, started_at, ended_at, channel, chat_id, user_id, text, metadata, error FROM session_inbox ${where} ORDER BY created_at ${order} LIMIT @limit`;
2347
+ const stmt = db.prepare(query);
2348
+ const rows = stmt.all({ ...params, limit });
2349
+ return rows.map(mapRecord2);
2350
+ }
2351
+
2352
+ // packages/storage/src/sqlite/session-routes.ts
2353
+ function prepareSessionRouteStatements(db) {
2354
+ return {
2355
+ get: db.prepare(
2356
+ "SELECT session_id, agent_id, lane_id, queue_mode, announce_mode, updated_at FROM session_routes WHERE session_id = @session_id"
2357
+ ),
2358
+ upsert: db.prepare(
2359
+ "INSERT INTO session_routes (session_id, agent_id, lane_id, queue_mode, announce_mode, updated_at) VALUES (@session_id, @agent_id, @lane_id, @queue_mode, @announce_mode, @updated_at) ON CONFLICT(session_id) DO UPDATE SET agent_id = excluded.agent_id, lane_id = excluded.lane_id, queue_mode = excluded.queue_mode, announce_mode = excluded.announce_mode, updated_at = excluded.updated_at"
2360
+ ),
2361
+ list: db.prepare(
2362
+ "SELECT session_id, agent_id, lane_id, queue_mode, announce_mode, updated_at FROM session_routes ORDER BY updated_at DESC LIMIT @limit"
2363
+ )
2364
+ };
2365
+ }
2366
+ var mapRoute = (row) => {
2367
+ return {
2368
+ sessionId: String(row.session_id),
2369
+ agentId: row.agent_id ? String(row.agent_id) : void 0,
2370
+ laneId: row.lane_id ? String(row.lane_id) : void 0,
2371
+ queueMode: row.queue_mode ? String(row.queue_mode) : void 0,
2372
+ announceMode: row.announce_mode ? String(row.announce_mode) : void 0,
2373
+ updatedAt: row.updated_at ? String(row.updated_at) : (/* @__PURE__ */ new Date()).toISOString()
2374
+ };
2375
+ };
2376
+ async function getSessionRoute(s, sessionId) {
2377
+ const row = s.get.get({ session_id: sessionId });
2378
+ return row ? mapRoute(row) : void 0;
2379
+ }
2380
+ async function upsertSessionRoute(s, record) {
2381
+ s.upsert.run({
2382
+ session_id: record.sessionId,
2383
+ agent_id: record.agentId ?? null,
2384
+ lane_id: record.laneId ?? null,
2385
+ queue_mode: record.queueMode ?? null,
2386
+ announce_mode: record.announceMode ?? null,
2387
+ updated_at: record.updatedAt
2388
+ });
2389
+ return record;
2390
+ }
2391
+ async function listSessionRoutes(s, options) {
2392
+ const limit = options?.limit ?? 100;
2393
+ const rows = s.list.all({ limit });
2394
+ return rows.map(mapRoute);
2395
+ }
2396
+
2397
+ // packages/storage/src/sqlite/agent-store.ts
2398
+ var createSqliteAgentStore = (db, agentRunStmts, agentQueueStmts, inboxStmts) => {
2399
+ return {
2400
+ async upsertAgentRun(record) {
2401
+ return upsertAgentRun(agentRunStmts, record);
2402
+ },
2403
+ async updateAgentRun(id, update) {
2404
+ const existing = await getAgentRun(agentRunStmts, id);
2405
+ if (!existing) return void 0;
2406
+ const merged = { ...existing, ...update };
2407
+ await upsertAgentRun(agentRunStmts, merged);
2408
+ return merged;
2409
+ },
2410
+ async getAgentRun(id) {
2411
+ return getAgentRun(agentRunStmts, id);
2412
+ },
2413
+ async listAgentRuns(options) {
2414
+ return listAgentRuns(db, options);
2415
+ },
2416
+ async enqueueAgentQueue(record) {
2417
+ return upsertAgentQueue(agentQueueStmts, record);
2418
+ },
2419
+ async updateAgentQueue(id, update) {
2420
+ const existing = await getAgentQueue(agentQueueStmts, id);
2421
+ if (!existing) return void 0;
2422
+ const merged = { ...existing, ...update };
2423
+ await upsertAgentQueue(agentQueueStmts, merged);
2424
+ return merged;
2425
+ },
2426
+ async getAgentQueue(id) {
2427
+ return getAgentQueue(agentQueueStmts, id);
2428
+ },
2429
+ async listAgentQueue(options) {
2430
+ return listAgentQueue(db, options);
2431
+ },
2432
+ async appendAgentRunEvent(event) {
2433
+ return appendAgentRunEvent(agentRunStmts, event);
2434
+ },
2435
+ async listAgentRunEvents(runId, options) {
2436
+ return listAgentRunEvents(agentRunStmts, runId, options);
2437
+ },
2438
+ async enqueueSessionInbox(record) {
2439
+ return upsertSessionInbox(inboxStmts, record);
2440
+ },
2441
+ async updateSessionInbox(id, update) {
2442
+ const existing = await getSessionInbox(inboxStmts, id);
2443
+ if (!existing) return void 0;
2444
+ const merged = { ...existing, ...update };
2445
+ await upsertSessionInbox(inboxStmts, merged);
2446
+ return merged;
2447
+ },
2448
+ async getSessionInbox(id) {
2449
+ return getSessionInbox(inboxStmts, id);
2450
+ },
2451
+ async listSessionInbox(options) {
2452
+ return listSessionInbox(db, options);
2453
+ }
2454
+ };
2455
+ };
2456
+
2457
+ // packages/storage/src/sqlite/memory-store.ts
2458
+ var createSqliteMemoryStore = (db, memoryStmts, syncStmts, reactionStmts) => {
2459
+ return {
2460
+ getMemorySession: (id) => getSessionById2(memoryStmts, id),
2461
+ getActiveMemorySession: (userId) => getActiveSession(memoryStmts, userId),
2462
+ listMemorySessions: (userId, options) => listSessions2(memoryStmts, userId, options),
2463
+ createMemorySession: (session) => createSession2(memoryStmts, session),
2464
+ updateMemorySession: (id, update) => updateSession2(memoryStmts, id, update),
2465
+ listMemoryMessages: (sessionId, options) => listMessages(memoryStmts, sessionId, options),
2466
+ createMemoryMessage: (message) => createMessage(memoryStmts, message),
2467
+ pruneMemoryMessages: (sessionId, keepIds) => pruneMessages(memoryStmts, sessionId, keepIds),
2468
+ createMemorySummary: (summary) => createSummary(memoryStmts, summary),
2469
+ listKnowledgeFacts: (userId, limit) => listFacts(memoryStmts, userId, limit),
2470
+ searchKnowledgeFacts: (userId, query, limit) => searchFacts(memoryStmts, userId, query, limit),
2471
+ createKnowledgeFact: (fact) => createFact(memoryStmts, fact),
2472
+ deleteKnowledgeFact: (id) => deleteFact(memoryStmts, id),
2473
+ getMemoryStats: () => getMemoryStats(db),
2474
+ getSyncState: (deviceId) => getSyncState(syncStmts, deviceId),
2475
+ updateSyncState: (deviceId, userId, update) => updateSyncState(syncStmts, deviceId, userId, update),
2476
+ listSyncStates: (userId) => listSyncStates(syncStmts, userId),
2477
+ deleteSyncState: (deviceId) => deleteSyncState(syncStmts, deviceId),
2478
+ incrementPendingChanges: (userId, excludedDeviceId, delta = 1) => incrementPendingChanges(syncStmts, userId, excludedDeviceId, delta),
2479
+ markDeviceSynced: (deviceId, userId) => markDeviceSynced(syncStmts, deviceId, userId),
2480
+ setMessageReaction: (sessionId, messageId, reaction) => setReaction(reactionStmts, sessionId, messageId, reaction),
2481
+ getMessageReaction: (messageId) => getReactionByMessageId(reactionStmts, messageId),
2482
+ listMessageReactions: (sessionId) => listReactionsBySession(reactionStmts, sessionId),
2483
+ deleteMessageReaction: (messageId) => deleteReaction(reactionStmts, messageId)
2484
+ };
2485
+ };
2486
+
2487
+ // packages/storage/src/sqlite/session-route-store.ts
2488
+ var createSqliteSessionRouteStore = (routeStmts) => {
2489
+ return {
2490
+ async getSessionRoute(sessionId) {
2491
+ return getSessionRoute(routeStmts, sessionId);
2492
+ },
2493
+ async setSessionRoute(sessionId, route) {
2494
+ const record = {
2495
+ sessionId,
2496
+ ...route,
2497
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
2498
+ };
2499
+ return upsertSessionRoute(routeStmts, record);
2500
+ },
2501
+ async listSessionRoutes(options) {
2502
+ return listSessionRoutes(routeStmts, options);
2503
+ }
2504
+ };
2505
+ };
2506
+
2507
+ // packages/storage/src/sqlite/storage.ts
2508
+ var SqliteStorage = class {
2509
+ db;
2510
+ sessionStmts;
2511
+ deviceStmts;
2512
+ channelStmts;
2513
+ approvalStmts;
2514
+ auditStmts;
2515
+ tokenUsageStmts;
2516
+ memoryStmts;
2517
+ syncStmts;
2518
+ reactionStmts;
2519
+ sessionProviderStmts;
2520
+ agentRunStmts;
2521
+ agentQueueStmts;
2522
+ sessionInboxStmts;
2523
+ sessionRouteStmts;
2524
+ constructor(options) {
2525
+ this.db = createConnection(options.sqlitePath);
2526
+ initSchema(this.db);
2527
+ this.sessionStmts = prepareSessionStatements(this.db);
2528
+ this.deviceStmts = prepareDeviceStatements(this.db);
2529
+ this.channelStmts = prepareChannelStatements(this.db);
2530
+ this.approvalStmts = prepareApprovalStatements(this.db);
2531
+ this.auditStmts = prepareAuditStatements(this.db);
2532
+ this.tokenUsageStmts = prepareTokenUsageStatements(this.db);
2533
+ this.memoryStmts = prepareMemoryStatements(this.db);
2534
+ this.syncStmts = prepareSyncStatements(this.db);
2535
+ this.reactionStmts = prepareReactionStatements(this.db);
2536
+ this.sessionProviderStmts = prepareSessionProviderStatements(this.db);
2537
+ this.agentRunStmts = prepareAgentRunStatements(this.db);
2538
+ this.agentQueueStmts = prepareAgentQueueStatements(this.db);
2539
+ this.sessionInboxStmts = prepareSessionInboxStatements(this.db);
2540
+ this.sessionRouteStmts = prepareSessionRouteStatements(this.db);
2541
+ Object.assign(
2542
+ this,
2543
+ createSqliteAgentStore(
2544
+ this.db,
2545
+ this.agentRunStmts,
2546
+ this.agentQueueStmts,
2547
+ this.sessionInboxStmts
2548
+ )
2549
+ );
2550
+ Object.assign(this, createSqliteSessionRouteStore(this.sessionRouteStmts));
2551
+ Object.assign(
2552
+ this,
2553
+ createSqliteMemoryStore(this.db, this.memoryStmts, this.syncStmts, this.reactionStmts)
2554
+ );
2555
+ }
2556
+ // -- Sessions -----------------------------------------------------------
2557
+ async getSessionByKey(key) {
2558
+ return getSessionByKey(this.sessionStmts, key);
2559
+ }
2560
+ async getSessionById(id) {
2561
+ return getSessionById(this.sessionStmts, id);
2562
+ }
2563
+ async listSessions() {
2564
+ return listSessions(this.sessionStmts);
2565
+ }
2566
+ async createSession(key, meta) {
2567
+ return createSession(this.sessionStmts, key, meta);
2568
+ }
2569
+ async updateSession(id, update) {
2570
+ return updateSession(this.sessionStmts, id, update);
2571
+ }
2572
+ async appendSessionEvent(event) {
2573
+ return appendSessionEvent(this.sessionStmts, event);
2574
+ }
2575
+ async listSessionEvents(sessionId, options) {
2576
+ return listSessionEvents(this.sessionStmts, sessionId, options);
2577
+ }
2578
+ async countSessionEvents(sessionId) {
2579
+ return countSessionEvents(this.sessionStmts, sessionId);
2580
+ }
2581
+ async getSessionSummary(sessionId) {
2582
+ return getSessionSummary(this.sessionStmts, sessionId);
2583
+ }
2584
+ async setSessionSummary(sessionId, summary, eventCount) {
2585
+ return setSessionSummary(this.sessionStmts, sessionId, summary, eventCount);
2586
+ }
2587
+ async getToolPolicy() {
2588
+ return getToolPolicy(this.sessionStmts);
2589
+ }
2590
+ async setToolPolicy(policy) {
2591
+ return setToolPolicy(this.sessionStmts, policy);
2592
+ }
2593
+ async appendProviderSwitch(record) {
2594
+ await appendProviderSwitch(this.sessionProviderStmts, record);
2595
+ }
2596
+ async upsertSessionProviderUsage(entry) {
2597
+ await upsertSessionProviderUsage(this.sessionProviderStmts, entry);
2598
+ }
2599
+ async getSessionPrefs(sessionId) {
2600
+ return getSessionPrefs(this.sessionStmts, sessionId);
2601
+ }
2602
+ async setSessionPrefs(sessionId, prefs) {
2603
+ return setSessionPrefs(this.sessionStmts, sessionId, prefs);
2604
+ }
2605
+ async clearSessionPrefs(sessionId) {
2606
+ return clearSessionPrefs(this.sessionStmts, sessionId);
2607
+ }
2608
+ // -- Devices ------------------------------------------------------------
2609
+ async listDevices() {
2610
+ return listDevices(this.deviceStmts);
2611
+ }
2612
+ async getDeviceById(id) {
2613
+ return getDeviceById(this.deviceStmts, id);
2614
+ }
2615
+ async getDeviceByTokenHash(tokenHash) {
2616
+ return getDeviceByTokenHash(this.deviceStmts, tokenHash);
2617
+ }
2618
+ async createDevice(record) {
2619
+ return createDevice(this.deviceStmts, record);
2620
+ }
2621
+ async updateDevice(id, update) {
2622
+ return updateDevice(this.deviceStmts, id, update);
2623
+ }
2624
+ async revokeDevice(id) {
2625
+ return revokeDevice(this.deviceStmts, id);
2626
+ }
2627
+ async touchDevice(id) {
2628
+ return touchDevice(this.deviceStmts, id);
2629
+ }
2630
+ // -- Channel Allows -----------------------------------------------------
2631
+ async listChannelAllows(channel) {
2632
+ return listChannelAllows(this.channelStmts, channel);
2633
+ }
2634
+ async getChannelAllow(channel, chatId, userId) {
2635
+ return getChannelAllow(this.channelStmts, channel, chatId, userId);
2636
+ }
2637
+ async allowChannel(record) {
2638
+ return allowChannel(this.channelStmts, record);
2639
+ }
2640
+ async revokeChannel(id) {
2641
+ return revokeChannel(this.channelStmts, id);
2642
+ }
2643
+ // -- Approval Requests --------------------------------------------------
2644
+ async createApprovalRequest(request) {
2645
+ return createApprovalRequest(this.approvalStmts, request);
2646
+ }
2647
+ async getApprovalRequest(id) {
2648
+ return getApprovalRequest(this.approvalStmts, id);
2649
+ }
2650
+ async listApprovalRequests(options) {
2651
+ return listApprovalRequests(this.approvalStmts, options);
2652
+ }
2653
+ async updateApprovalRequest(id, update) {
2654
+ return updateApprovalRequest(this.approvalStmts, id, update);
2655
+ }
2656
+ // -- Audit --------------------------------------------------------------
2657
+ async appendAudit(event) {
2658
+ return appendAudit(this.auditStmts, event);
2659
+ }
2660
+ // -- Session Inbox (methods provided via createSqliteAgentStore) ---------
2661
+ // -- Token Usage --------------------------------------------------------
2662
+ async appendTokenUsage(record) {
2663
+ return appendTokenUsage(this.tokenUsageStmts, record);
2664
+ }
2665
+ async listTokenUsage(options) {
2666
+ return listTokenUsage(this.tokenUsageStmts, options);
2667
+ }
2668
+ async getTokenUsageSummary(options) {
2669
+ return getTokenUsageSummary(this.tokenUsageStmts, options);
2670
+ }
2671
+ // -- Memory/Sync/Reactions (methods provided via createSqliteMemoryStore) --
2672
+ // -- Lifecycle ----------------------------------------------------------
2673
+ async close() {
2674
+ this.db.close();
2675
+ }
2676
+ };
2677
+
2678
+ export {
2679
+ createConnection,
2680
+ initSchema,
2681
+ resetMemoryTables,
2682
+ getSchemaInfo,
2683
+ prepareSessionStatements,
2684
+ getSessionByKey,
2685
+ getSessionById,
2686
+ listSessions,
2687
+ createSession,
2688
+ updateSession,
2689
+ appendSessionEvent,
2690
+ listSessionEvents,
2691
+ countSessionEvents,
2692
+ getSessionSummary,
2693
+ setSessionSummary,
2694
+ getToolPolicy,
2695
+ setToolPolicy,
2696
+ getSessionPrefs,
2697
+ setSessionPrefs,
2698
+ clearSessionPrefs,
2699
+ prepareDeviceStatements,
2700
+ listDevices,
2701
+ getDeviceById,
2702
+ getDeviceByTokenHash,
2703
+ createDevice,
2704
+ updateDevice,
2705
+ revokeDevice,
2706
+ touchDevice,
2707
+ prepareChannelStatements,
2708
+ listChannelAllows,
2709
+ getChannelAllow,
2710
+ allowChannel,
2711
+ revokeChannel,
2712
+ prepareApprovalStatements,
2713
+ createApprovalRequest,
2714
+ getApprovalRequest,
2715
+ listApprovalRequests,
2716
+ updateApprovalRequest,
2717
+ prepareAuditStatements,
2718
+ appendAudit,
2719
+ prepareTokenUsageStatements,
2720
+ appendTokenUsage,
2721
+ listTokenUsage,
2722
+ getTokenUsageSummary,
2723
+ getMemoryStats,
2724
+ prepareMemoryStatements,
2725
+ getSessionById2,
2726
+ getActiveSession,
2727
+ listSessions2,
2728
+ createSession2,
2729
+ updateSession2,
2730
+ listMessages,
2731
+ createMessage,
2732
+ pruneMessages,
2733
+ getSummary,
2734
+ createSummary,
2735
+ listFacts,
2736
+ searchFacts,
2737
+ createFact,
2738
+ deleteFact,
2739
+ prepareSyncStatements,
2740
+ getSyncState,
2741
+ updateSyncState,
2742
+ listSyncStates,
2743
+ deleteSyncState,
2744
+ incrementPendingChanges,
2745
+ markDeviceSynced,
2746
+ prepareReactionStatements,
2747
+ setReaction,
2748
+ getReactionByMessageId,
2749
+ listReactionsBySession,
2750
+ deleteReaction,
2751
+ SqliteStorage
2752
+ };
2753
+ //# sourceMappingURL=chunk-SMVJRPAH.js.map