@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,1479 @@
1
+ // packages/storage/src/postgres/pool.ts
2
+ import { createRequire } from "node:module";
3
+ function createPool(url) {
4
+ const require2 = createRequire(import.meta.url);
5
+ const { Pool } = require2("pg");
6
+ return new Pool({ connectionString: url });
7
+ }
8
+
9
+ // packages/storage/src/postgres/migrations.ts
10
+ async function runMigrations(pool) {
11
+ await pool.query(
12
+ "CREATE TABLE IF NOT EXISTS sessions (id TEXT PRIMARY KEY, key TEXT UNIQUE, created_at TEXT, updated_at TEXT, user_id TEXT, channel TEXT, chat_type TEXT, chat_id TEXT, peer_id TEXT, account_id TEXT, thread_id TEXT, label TEXT, current_provider TEXT, current_model TEXT, providers_used TEXT, provider_switches INTEGER)"
13
+ );
14
+ await pool.query("ALTER TABLE sessions ADD COLUMN IF NOT EXISTS user_id TEXT");
15
+ await pool.query("ALTER TABLE sessions ADD COLUMN IF NOT EXISTS channel TEXT");
16
+ await pool.query("ALTER TABLE sessions ADD COLUMN IF NOT EXISTS chat_type TEXT");
17
+ await pool.query("ALTER TABLE sessions ADD COLUMN IF NOT EXISTS chat_id TEXT");
18
+ await pool.query("ALTER TABLE sessions ADD COLUMN IF NOT EXISTS peer_id TEXT");
19
+ await pool.query("ALTER TABLE sessions ADD COLUMN IF NOT EXISTS account_id TEXT");
20
+ await pool.query("ALTER TABLE sessions ADD COLUMN IF NOT EXISTS thread_id TEXT");
21
+ await pool.query("ALTER TABLE sessions ADD COLUMN IF NOT EXISTS label TEXT");
22
+ await pool.query("ALTER TABLE sessions ADD COLUMN IF NOT EXISTS current_provider TEXT");
23
+ await pool.query("ALTER TABLE sessions ADD COLUMN IF NOT EXISTS current_model TEXT");
24
+ await pool.query("ALTER TABLE sessions ADD COLUMN IF NOT EXISTS providers_used TEXT");
25
+ await pool.query("ALTER TABLE sessions ADD COLUMN IF NOT EXISTS provider_switches INTEGER");
26
+ await pool.query(
27
+ "CREATE TABLE IF NOT EXISTS audit (id TEXT PRIMARY KEY, time TEXT, type TEXT, payload TEXT)"
28
+ );
29
+ await pool.query(
30
+ "CREATE TABLE IF NOT EXISTS session_events (id TEXT PRIMARY KEY, session_id TEXT, role TEXT, content TEXT, metadata TEXT, created_at TEXT)"
31
+ );
32
+ await pool.query(
33
+ "CREATE TABLE IF NOT EXISTS session_summaries (session_id TEXT PRIMARY KEY, summary TEXT, event_count INTEGER, updated_at TEXT)"
34
+ );
35
+ await pool.query(
36
+ "CREATE TABLE IF NOT EXISTS tool_policy (id TEXT PRIMARY KEY, allow TEXT, deny TEXT, updated_at TEXT)"
37
+ );
38
+ await pool.query(
39
+ "CREATE TABLE IF NOT EXISTS session_prefs (session_id TEXT PRIMARY KEY, provider_id TEXT, model TEXT, system TEXT, auto_routing BOOLEAN, language TEXT, language_updated_at TEXT, continuity_preferred_device_id TEXT, continuity_mode TEXT, proactive_allowed BOOLEAN, proactive_observe BOOLEAN, proactive_deliver BOOLEAN, proactive_allowed_channels TEXT, proactive_paused_until TEXT, proactive_max_per_day INTEGER, proactive_cooldown_ms INTEGER, proactive_delivered_day TEXT, proactive_delivered_count INTEGER, proactive_last_delivered_at TEXT, updated_at TEXT)"
40
+ );
41
+ await pool.query("ALTER TABLE session_prefs ADD COLUMN IF NOT EXISTS auto_routing BOOLEAN");
42
+ await pool.query("ALTER TABLE session_prefs ADD COLUMN IF NOT EXISTS language TEXT");
43
+ await pool.query("ALTER TABLE session_prefs ADD COLUMN IF NOT EXISTS language_updated_at TEXT");
44
+ await pool.query(
45
+ "ALTER TABLE session_prefs ADD COLUMN IF NOT EXISTS continuity_preferred_device_id TEXT"
46
+ );
47
+ await pool.query(
48
+ "ALTER TABLE session_prefs ADD COLUMN IF NOT EXISTS continuity_mode TEXT"
49
+ );
50
+ await pool.query(
51
+ "ALTER TABLE session_prefs ADD COLUMN IF NOT EXISTS proactive_allowed BOOLEAN"
52
+ );
53
+ await pool.query(
54
+ "ALTER TABLE session_prefs ADD COLUMN IF NOT EXISTS proactive_observe BOOLEAN"
55
+ );
56
+ await pool.query(
57
+ "ALTER TABLE session_prefs ADD COLUMN IF NOT EXISTS proactive_deliver BOOLEAN"
58
+ );
59
+ await pool.query(
60
+ "ALTER TABLE session_prefs ADD COLUMN IF NOT EXISTS proactive_allowed_channels TEXT"
61
+ );
62
+ await pool.query(
63
+ "ALTER TABLE session_prefs ADD COLUMN IF NOT EXISTS proactive_paused_until TEXT"
64
+ );
65
+ await pool.query(
66
+ "ALTER TABLE session_prefs ADD COLUMN IF NOT EXISTS proactive_max_per_day INTEGER"
67
+ );
68
+ await pool.query(
69
+ "ALTER TABLE session_prefs ADD COLUMN IF NOT EXISTS proactive_cooldown_ms INTEGER"
70
+ );
71
+ await pool.query(
72
+ "ALTER TABLE session_prefs ADD COLUMN IF NOT EXISTS proactive_delivered_day TEXT"
73
+ );
74
+ await pool.query(
75
+ "ALTER TABLE session_prefs ADD COLUMN IF NOT EXISTS proactive_delivered_count INTEGER"
76
+ );
77
+ await pool.query(
78
+ "ALTER TABLE session_prefs ADD COLUMN IF NOT EXISTS proactive_last_delivered_at TEXT"
79
+ );
80
+ await pool.query(
81
+ "CREATE TABLE IF NOT EXISTS session_providers (session_id TEXT NOT NULL, provider_id TEXT NOT NULL, model TEXT, first_used_at TEXT, last_used_at TEXT, usage_count INTEGER, PRIMARY KEY (session_id, provider_id))"
82
+ );
83
+ await pool.query(
84
+ "CREATE TABLE IF NOT EXISTS provider_switches (id TEXT PRIMARY KEY, session_id TEXT, from_provider_id TEXT, to_provider_id TEXT, from_model TEXT, to_model TEXT, reason TEXT, created_at TEXT)"
85
+ );
86
+ await pool.query(
87
+ "CREATE TABLE IF NOT EXISTS devices (id TEXT PRIMARY KEY, name TEXT, type TEXT, role TEXT, caps TEXT, status TEXT, scopes TEXT, auth_type TEXT, token_hash TEXT UNIQUE, token_hint TEXT, public_key TEXT, public_key_alg TEXT, created_at TEXT, updated_at TEXT, last_seen_at TEXT)"
88
+ );
89
+ await pool.query(
90
+ "CREATE TABLE IF NOT EXISTS channel_allows (id TEXT PRIMARY KEY, channel TEXT, chat_id TEXT, user_id TEXT, status TEXT, note TEXT, created_at TEXT, updated_at TEXT)"
91
+ );
92
+ await pool.query(
93
+ "CREATE UNIQUE INDEX IF NOT EXISTS channel_allows_key ON channel_allows(channel, chat_id, user_id)"
94
+ );
95
+ await pool.query(
96
+ "CREATE TABLE IF NOT EXISTS approval_requests (id TEXT PRIMARY KEY, status TEXT, kind TEXT, tool_name TEXT, tool_input TEXT, session_id TEXT, channel TEXT, chat_id TEXT, user_id TEXT, user_text TEXT, risk TEXT, reason TEXT, created_at TEXT, updated_at TEXT, expires_at TEXT, decided_at TEXT, decided_by TEXT, result TEXT)"
97
+ );
98
+ await pool.query(
99
+ "CREATE INDEX IF NOT EXISTS approval_requests_status_idx ON approval_requests(status, created_at)"
100
+ );
101
+ await pool.query("ALTER TABLE devices ADD COLUMN IF NOT EXISTS auth_type TEXT");
102
+ await pool.query("ALTER TABLE devices ADD COLUMN IF NOT EXISTS public_key TEXT");
103
+ await pool.query("ALTER TABLE devices ADD COLUMN IF NOT EXISTS public_key_alg TEXT");
104
+ await pool.query("ALTER TABLE devices ADD COLUMN IF NOT EXISTS role TEXT");
105
+ await pool.query("ALTER TABLE devices ADD COLUMN IF NOT EXISTS caps TEXT");
106
+ await pool.query(
107
+ "CREATE TABLE IF NOT EXISTS agent_runs (id TEXT PRIMARY KEY, session_id TEXT, agent_id TEXT, parent_agent_id TEXT, parent_run_id TEXT, lane TEXT, status TEXT, created_at TEXT, started_at TEXT, ended_at TEXT, timeout_ms INTEGER, channel TEXT, chat_id TEXT, user_id TEXT, provider_id TEXT, model TEXT, system TEXT, text TEXT, metadata TEXT, metrics TEXT, result_summary TEXT, error TEXT)"
108
+ );
109
+ await pool.query(
110
+ "CREATE INDEX IF NOT EXISTS agent_runs_status_idx ON agent_runs(status, created_at)"
111
+ );
112
+ await pool.query(
113
+ "CREATE INDEX IF NOT EXISTS agent_runs_session_idx ON agent_runs(session_id, created_at)"
114
+ );
115
+ await pool.query(
116
+ "CREATE INDEX IF NOT EXISTS agent_runs_lane_idx ON agent_runs(lane, created_at)"
117
+ );
118
+ await pool.query(
119
+ "CREATE TABLE IF NOT EXISTS agent_queue (id TEXT PRIMARY KEY, session_id TEXT, agent_id TEXT, parent_agent_id TEXT, parent_run_id TEXT, lane TEXT, status TEXT, created_at TEXT, started_at TEXT, ended_at TEXT, lease_until TEXT, priority INTEGER, channel TEXT, chat_id TEXT, user_id TEXT, provider_id TEXT, model TEXT, system TEXT, text TEXT, timeout_ms INTEGER, tool_policy TEXT, metadata TEXT, error TEXT)"
120
+ );
121
+ await pool.query(
122
+ "CREATE INDEX IF NOT EXISTS agent_queue_status_idx ON agent_queue(status, created_at)"
123
+ );
124
+ await pool.query(
125
+ "CREATE INDEX IF NOT EXISTS agent_queue_lane_idx ON agent_queue(lane, created_at)"
126
+ );
127
+ await pool.query(
128
+ "CREATE INDEX IF NOT EXISTS agent_queue_session_idx ON agent_queue(session_id, created_at)"
129
+ );
130
+ await pool.query("ALTER TABLE agent_queue ADD COLUMN IF NOT EXISTS lease_until TEXT");
131
+ await pool.query("ALTER TABLE agent_queue ADD COLUMN IF NOT EXISTS agent_id TEXT");
132
+ await pool.query("ALTER TABLE agent_queue ADD COLUMN IF NOT EXISTS parent_agent_id TEXT");
133
+ await pool.query("ALTER TABLE agent_runs ADD COLUMN IF NOT EXISTS agent_id TEXT");
134
+ await pool.query("ALTER TABLE agent_runs ADD COLUMN IF NOT EXISTS parent_agent_id TEXT");
135
+ await pool.query(
136
+ "CREATE TABLE IF NOT EXISTS session_routes (session_id TEXT PRIMARY KEY, agent_id TEXT, lane_id TEXT, queue_mode TEXT, announce_mode TEXT, updated_at TEXT)"
137
+ );
138
+ await pool.query(
139
+ "CREATE INDEX IF NOT EXISTS session_routes_updated_idx ON session_routes(updated_at)"
140
+ );
141
+ await pool.query(
142
+ "CREATE TABLE IF NOT EXISTS agent_run_events (id TEXT PRIMARY KEY, run_id TEXT, time TEXT, type TEXT, payload TEXT)"
143
+ );
144
+ await pool.query(
145
+ "CREATE INDEX IF NOT EXISTS agent_run_events_run_idx ON agent_run_events(run_id, time)"
146
+ );
147
+ await pool.query(
148
+ "CREATE TABLE IF NOT EXISTS session_inbox (id TEXT PRIMARY KEY, session_id TEXT NOT NULL, status TEXT, created_at TEXT, started_at TEXT, ended_at TEXT, channel TEXT, chat_id TEXT, user_id TEXT, text TEXT, metadata TEXT, error TEXT)"
149
+ );
150
+ await pool.query(
151
+ "CREATE INDEX IF NOT EXISTS session_inbox_session_idx ON session_inbox(session_id, created_at)"
152
+ );
153
+ await pool.query(
154
+ "CREATE INDEX IF NOT EXISTS session_inbox_status_idx ON session_inbox(status, created_at)"
155
+ );
156
+ }
157
+
158
+ // packages/storage/src/postgres/sessions.ts
159
+ import { randomUUID } from "node:crypto";
160
+
161
+ // packages/storage/src/postgres/mappers.ts
162
+ var parseJson = (value) => {
163
+ if (typeof value !== "string" || !value) return void 0;
164
+ try {
165
+ return JSON.parse(value);
166
+ } catch {
167
+ return void 0;
168
+ }
169
+ };
170
+ function mapSession(row) {
171
+ const providersUsedRaw = row.providers_used ? String(row.providers_used) : "";
172
+ let providersUsed;
173
+ if (providersUsedRaw) {
174
+ try {
175
+ const parsed = JSON.parse(providersUsedRaw);
176
+ providersUsed = Array.isArray(parsed) ? parsed.map((value) => String(value)) : void 0;
177
+ } catch {
178
+ providersUsed = void 0;
179
+ }
180
+ }
181
+ return {
182
+ id: String(row.id),
183
+ key: String(row.key),
184
+ createdAt: String(row.created_at),
185
+ updatedAt: String(row.updated_at),
186
+ userId: row.user_id ? String(row.user_id) : void 0,
187
+ channel: row.channel ? String(row.channel) : void 0,
188
+ chatType: row.chat_type ? String(row.chat_type) : void 0,
189
+ chatId: row.chat_id ? String(row.chat_id) : void 0,
190
+ peerId: row.peer_id ? String(row.peer_id) : void 0,
191
+ accountId: row.account_id ? String(row.account_id) : void 0,
192
+ threadId: row.thread_id ? String(row.thread_id) : void 0,
193
+ label: row.label ? String(row.label) : void 0,
194
+ currentProviderId: row.current_provider ? String(row.current_provider) : void 0,
195
+ currentModel: row.current_model ? String(row.current_model) : void 0,
196
+ providersUsed,
197
+ providerSwitches: row.provider_switches === null || row.provider_switches === void 0 ? void 0 : Number(row.provider_switches)
198
+ };
199
+ }
200
+ function mapPrefs(row) {
201
+ let proactiveAllowedChannels;
202
+ if (row.proactive_allowed_channels) {
203
+ try {
204
+ const parsed = JSON.parse(String(row.proactive_allowed_channels));
205
+ if (Array.isArray(parsed)) {
206
+ proactiveAllowedChannels = parsed.filter((item) => typeof item === "string");
207
+ }
208
+ } catch {
209
+ proactiveAllowedChannels = void 0;
210
+ }
211
+ }
212
+ return {
213
+ sessionId: String(row.session_id),
214
+ providerId: row.provider_id ? String(row.provider_id) : void 0,
215
+ model: row.model ? String(row.model) : void 0,
216
+ system: row.system ? String(row.system) : void 0,
217
+ autoRouting: row.auto_routing === null || row.auto_routing === void 0 ? void 0 : Boolean(row.auto_routing),
218
+ language: row.language ? String(row.language) : void 0,
219
+ languageUpdatedAt: row.language_updated_at ? String(row.language_updated_at) : void 0,
220
+ continuityPreferredDeviceId: row.continuity_preferred_device_id ? String(row.continuity_preferred_device_id) : void 0,
221
+ continuityMode: row.continuity_mode === "auto" || row.continuity_mode === "prompt" || row.continuity_mode === "off" ? row.continuity_mode : void 0,
222
+ proactiveAllowed: row.proactive_allowed === null || row.proactive_allowed === void 0 ? void 0 : Boolean(row.proactive_allowed),
223
+ proactiveObserve: row.proactive_observe === null || row.proactive_observe === void 0 ? void 0 : Boolean(row.proactive_observe),
224
+ proactiveDeliver: row.proactive_deliver === null || row.proactive_deliver === void 0 ? void 0 : Boolean(row.proactive_deliver),
225
+ proactiveAllowedChannels,
226
+ proactivePausedUntil: row.proactive_paused_until ? String(row.proactive_paused_until) : void 0,
227
+ proactiveMaxPerDay: row.proactive_max_per_day === null || row.proactive_max_per_day === void 0 ? void 0 : Number(row.proactive_max_per_day),
228
+ proactiveCooldownMs: row.proactive_cooldown_ms === null || row.proactive_cooldown_ms === void 0 ? void 0 : Number(row.proactive_cooldown_ms),
229
+ proactiveDeliveredDay: row.proactive_delivered_day ? String(row.proactive_delivered_day) : void 0,
230
+ proactiveDeliveredCount: row.proactive_delivered_count === null || row.proactive_delivered_count === void 0 ? void 0 : Number(row.proactive_delivered_count),
231
+ proactiveLastDeliveredAt: row.proactive_last_delivered_at ? String(row.proactive_last_delivered_at) : void 0,
232
+ updatedAt: String(row.updated_at)
233
+ };
234
+ }
235
+ function mapEvent(row) {
236
+ return {
237
+ id: String(row.id),
238
+ sessionId: String(row.session_id),
239
+ role: String(row.role),
240
+ content: String(row.content),
241
+ metadata: row.metadata ? parseJson(String(row.metadata)) : void 0,
242
+ createdAt: String(row.created_at)
243
+ };
244
+ }
245
+ function mapSummary(row) {
246
+ return {
247
+ sessionId: String(row.session_id),
248
+ summary: String(row.summary),
249
+ eventCount: row.event_count === null || row.event_count === void 0 ? void 0 : Number(row.event_count),
250
+ updatedAt: String(row.updated_at)
251
+ };
252
+ }
253
+ function mapDevice(row) {
254
+ return {
255
+ id: String(row.id),
256
+ name: row.name ? String(row.name) : void 0,
257
+ type: row.type ? String(row.type) : void 0,
258
+ role: row.role ? String(row.role) : void 0,
259
+ caps: row.caps ? parseJson(String(row.caps)) : void 0,
260
+ status: row.status === "revoked" ? "revoked" : "active",
261
+ scopes: row.scopes ? parseJson(String(row.scopes)) : void 0,
262
+ authType: row.auth_type === "keypair" ? "keypair" : "token",
263
+ tokenHash: row.token_hash ? String(row.token_hash) : void 0,
264
+ tokenHint: row.token_hint ? String(row.token_hint) : void 0,
265
+ publicKey: row.public_key ? String(row.public_key) : void 0,
266
+ publicKeyAlgorithm: row.public_key_alg ? String(row.public_key_alg) : void 0,
267
+ createdAt: String(row.created_at),
268
+ updatedAt: String(row.updated_at),
269
+ lastSeenAt: row.last_seen_at ? String(row.last_seen_at) : void 0
270
+ };
271
+ }
272
+ function mapChannelAllow(row) {
273
+ const userId = row.user_id ? String(row.user_id) : "";
274
+ return {
275
+ id: String(row.id),
276
+ channel: String(row.channel),
277
+ chatId: String(row.chat_id),
278
+ userId: userId.length > 0 ? userId : void 0,
279
+ status: row.status === "revoked" ? "revoked" : "allowed",
280
+ note: row.note ? String(row.note) : void 0,
281
+ createdAt: String(row.created_at),
282
+ updatedAt: String(row.updated_at)
283
+ };
284
+ }
285
+ function mapApproval(row) {
286
+ const toolInput = parseJson(row.tool_input);
287
+ const decidedBy = parseJson(row.decided_by);
288
+ const result = parseJson(row.result);
289
+ const kind = typeof row.kind === "string" && row.kind.trim() ? row.kind : "tool";
290
+ return {
291
+ id: String(row.id),
292
+ status: String(row.status),
293
+ kind,
294
+ toolName: String(row.tool_name),
295
+ toolInput: toolInput ?? {},
296
+ sessionId: String(row.session_id),
297
+ channel: String(row.channel),
298
+ chatId: String(row.chat_id),
299
+ userId: row.user_id ? String(row.user_id) : void 0,
300
+ userText: row.user_text ? String(row.user_text) : void 0,
301
+ risk: row.risk ? String(row.risk) : void 0,
302
+ reason: row.reason ? String(row.reason) : void 0,
303
+ createdAt: String(row.created_at),
304
+ updatedAt: String(row.updated_at),
305
+ expiresAt: row.expires_at ? String(row.expires_at) : void 0,
306
+ decidedAt: row.decided_at ? String(row.decided_at) : void 0,
307
+ decidedBy: decidedBy ?? void 0,
308
+ result: result ?? void 0
309
+ };
310
+ }
311
+
312
+ // packages/storage/src/postgres/sessions.ts
313
+ var createSessionStore = (pool) => {
314
+ const sessionSelect = "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 ";
315
+ return {
316
+ async getSessionByKey(key) {
317
+ const result = await pool.query(`${sessionSelect}FROM sessions WHERE key = $1`, [key]);
318
+ return result.rows[0] ? mapSession(result.rows[0]) : void 0;
319
+ },
320
+ async getSessionById(id) {
321
+ const result = await pool.query(`${sessionSelect}FROM sessions WHERE id = $1`, [id]);
322
+ return result.rows[0] ? mapSession(result.rows[0]) : void 0;
323
+ },
324
+ async listSessions() {
325
+ const result = await pool.query(`${sessionSelect}FROM sessions ORDER BY created_at DESC`);
326
+ return result.rows.map(mapSession);
327
+ },
328
+ async createSession(key, meta) {
329
+ const existing = await this.getSessionByKey(key);
330
+ if (existing) {
331
+ return existing;
332
+ }
333
+ const now = (/* @__PURE__ */ new Date()).toISOString();
334
+ const record = {
335
+ id: randomUUID(),
336
+ key,
337
+ createdAt: now,
338
+ updatedAt: now,
339
+ userId: meta?.userId,
340
+ channel: meta?.channel,
341
+ chatType: meta?.chatType,
342
+ chatId: meta?.chatId,
343
+ peerId: meta?.peerId,
344
+ accountId: meta?.accountId,
345
+ threadId: meta?.threadId,
346
+ label: meta?.label,
347
+ currentProviderId: meta?.currentProviderId,
348
+ currentModel: meta?.currentModel,
349
+ providersUsed: meta?.providersUsed,
350
+ providerSwitches: meta?.providerSwitches
351
+ };
352
+ await pool.query(
353
+ "INSERT 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 ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) ON CONFLICT (key) DO NOTHING",
354
+ [
355
+ record.id,
356
+ record.key,
357
+ record.createdAt,
358
+ record.updatedAt,
359
+ record.userId ?? null,
360
+ record.channel ?? null,
361
+ record.chatType ?? null,
362
+ record.chatId ?? null,
363
+ record.peerId ?? null,
364
+ record.accountId ?? null,
365
+ record.threadId ?? null,
366
+ record.label ?? null,
367
+ record.currentProviderId ?? null,
368
+ record.currentModel ?? null,
369
+ record.providersUsed ? JSON.stringify(record.providersUsed) : null,
370
+ record.providerSwitches ?? null
371
+ ]
372
+ );
373
+ const stored = await this.getSessionByKey(key);
374
+ return stored ?? record;
375
+ },
376
+ async updateSession(id, update) {
377
+ const existing = await this.getSessionById(id);
378
+ if (!existing) {
379
+ return void 0;
380
+ }
381
+ const merged = {
382
+ ...existing,
383
+ ...update,
384
+ updatedAt: update.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
385
+ };
386
+ await pool.query(
387
+ "UPDATE sessions SET key = $1, updated_at = $2, user_id = $3, channel = $4, chat_type = $5, chat_id = $6, peer_id = $7, account_id = $8, thread_id = $9, label = $10, current_provider = $11, current_model = $12, providers_used = $13, provider_switches = $14 WHERE id = $15",
388
+ [
389
+ merged.key,
390
+ merged.updatedAt,
391
+ merged.userId ?? null,
392
+ merged.channel ?? null,
393
+ merged.chatType ?? null,
394
+ merged.chatId ?? null,
395
+ merged.peerId ?? null,
396
+ merged.accountId ?? null,
397
+ merged.threadId ?? null,
398
+ merged.label ?? null,
399
+ merged.currentProviderId ?? null,
400
+ merged.currentModel ?? null,
401
+ merged.providersUsed ? JSON.stringify(merged.providersUsed) : null,
402
+ merged.providerSwitches ?? null,
403
+ merged.id
404
+ ]
405
+ );
406
+ return merged;
407
+ },
408
+ async appendProviderSwitch(record) {
409
+ await pool.query(
410
+ "INSERT INTO provider_switches (id, session_id, from_provider_id, to_provider_id, from_model, to_model, reason, created_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)",
411
+ [
412
+ record.id,
413
+ record.sessionId,
414
+ record.fromProviderId ?? null,
415
+ record.toProviderId ?? null,
416
+ record.fromModel ?? null,
417
+ record.toModel ?? null,
418
+ record.reason ?? null,
419
+ record.createdAt
420
+ ]
421
+ );
422
+ },
423
+ async upsertSessionProviderUsage(entry) {
424
+ const usedAt = entry.usedAt ?? (/* @__PURE__ */ new Date()).toISOString();
425
+ await pool.query(
426
+ "INSERT INTO session_providers (session_id, provider_id, model, first_used_at, last_used_at, usage_count) VALUES ($1, $2, $3, $4, $5, $6) 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",
427
+ [
428
+ entry.sessionId,
429
+ entry.providerId,
430
+ entry.model ?? null,
431
+ usedAt,
432
+ usedAt,
433
+ 1
434
+ ]
435
+ );
436
+ },
437
+ async appendSessionEvent(event) {
438
+ await pool.query(
439
+ "INSERT INTO session_events (id, session_id, role, content, metadata, created_at) VALUES ($1, $2, $3, $4, $5, $6)",
440
+ [
441
+ event.id,
442
+ event.sessionId,
443
+ event.role,
444
+ event.content,
445
+ event.metadata ? JSON.stringify(event.metadata) : null,
446
+ event.createdAt
447
+ ]
448
+ );
449
+ },
450
+ async listSessionEvents(sessionId, options) {
451
+ const limit = options?.limit ?? 50;
452
+ const result = await pool.query(
453
+ "SELECT id, session_id, role, content, metadata, created_at FROM session_events WHERE session_id = $1 ORDER BY created_at DESC LIMIT $2",
454
+ [sessionId, limit]
455
+ );
456
+ return result.rows.map(mapEvent).reverse();
457
+ },
458
+ async countSessionEvents(sessionId) {
459
+ const result = await pool.query(
460
+ "SELECT COUNT(*) as count FROM session_events WHERE session_id = $1",
461
+ [sessionId]
462
+ );
463
+ const value = result.rows[0]?.count;
464
+ return typeof value === "number" ? value : Number(value ?? 0);
465
+ },
466
+ async getSessionSummary(sessionId) {
467
+ const result = await pool.query(
468
+ "SELECT session_id, summary, event_count, updated_at FROM session_summaries WHERE session_id = $1",
469
+ [sessionId]
470
+ );
471
+ return result.rows[0] ? mapSummary(result.rows[0]) : void 0;
472
+ },
473
+ async setSessionSummary(sessionId, summary, eventCount) {
474
+ const now = (/* @__PURE__ */ new Date()).toISOString();
475
+ await pool.query(
476
+ "INSERT INTO session_summaries (session_id, summary, event_count, updated_at) VALUES ($1, $2, $3, $4) ON CONFLICT (session_id) DO UPDATE SET summary = EXCLUDED.summary, event_count = EXCLUDED.event_count, updated_at = EXCLUDED.updated_at",
477
+ [sessionId, summary, eventCount ?? null, now]
478
+ );
479
+ return await this.getSessionSummary(sessionId) ?? {
480
+ sessionId,
481
+ summary,
482
+ eventCount,
483
+ updatedAt: now
484
+ };
485
+ }
486
+ };
487
+ };
488
+
489
+ // packages/storage/src/postgres/prefs.ts
490
+ var createSessionPrefsStore = (pool) => {
491
+ return {
492
+ async getSessionPrefs(sessionId) {
493
+ const result = await pool.query(
494
+ "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 = $1",
495
+ [sessionId]
496
+ );
497
+ return result.rows[0] ? mapPrefs(result.rows[0]) : void 0;
498
+ },
499
+ async setSessionPrefs(sessionId, prefs) {
500
+ const existing = await this.getSessionPrefs(sessionId);
501
+ const now = (/* @__PURE__ */ new Date()).toISOString();
502
+ const providerId = prefs.providerId ?? existing?.providerId ?? null;
503
+ const model = prefs.model ?? existing?.model ?? null;
504
+ const system = prefs.system ?? existing?.system ?? null;
505
+ const autoRouting = prefs.autoRouting ?? existing?.autoRouting ?? null;
506
+ const hasLanguage = Object.prototype.hasOwnProperty.call(prefs, "language");
507
+ const language = hasLanguage ? prefs.language ?? null : existing?.language ?? null;
508
+ const hasLanguageUpdatedAt = Object.prototype.hasOwnProperty.call(prefs, "languageUpdatedAt");
509
+ const languageUpdatedAt = hasLanguage ? prefs.language ? prefs.languageUpdatedAt ?? now : null : hasLanguageUpdatedAt ? prefs.languageUpdatedAt ?? null : existing?.languageUpdatedAt ?? null;
510
+ const hasContinuityDevice = Object.prototype.hasOwnProperty.call(
511
+ prefs,
512
+ "continuityPreferredDeviceId"
513
+ );
514
+ const continuityPreferredDeviceId = hasContinuityDevice ? prefs.continuityPreferredDeviceId ?? null : existing?.continuityPreferredDeviceId ?? null;
515
+ const hasContinuityMode = Object.prototype.hasOwnProperty.call(prefs, "continuityMode");
516
+ const continuityMode = hasContinuityMode ? prefs.continuityMode ?? null : existing?.continuityMode ?? null;
517
+ const proactiveAllowed = prefs.proactiveAllowed ?? existing?.proactiveAllowed ?? null;
518
+ const proactiveObserve = prefs.proactiveObserve ?? existing?.proactiveObserve ?? null;
519
+ const proactiveDeliver = prefs.proactiveDeliver ?? existing?.proactiveDeliver ?? null;
520
+ const hasAllowedChannels = Object.prototype.hasOwnProperty.call(
521
+ prefs,
522
+ "proactiveAllowedChannels"
523
+ );
524
+ const proactiveAllowedChannels = hasAllowedChannels ? prefs.proactiveAllowedChannels ?? null : existing?.proactiveAllowedChannels ?? null;
525
+ const hasPausedUntil = Object.prototype.hasOwnProperty.call(
526
+ prefs,
527
+ "proactivePausedUntil"
528
+ );
529
+ const proactivePausedUntil = hasPausedUntil ? prefs.proactivePausedUntil ?? null : existing?.proactivePausedUntil ?? null;
530
+ const hasMaxPerDay = Object.prototype.hasOwnProperty.call(
531
+ prefs,
532
+ "proactiveMaxPerDay"
533
+ );
534
+ const proactiveMaxPerDay = hasMaxPerDay ? prefs.proactiveMaxPerDay ?? null : existing?.proactiveMaxPerDay ?? null;
535
+ const hasCooldown = Object.prototype.hasOwnProperty.call(
536
+ prefs,
537
+ "proactiveCooldownMs"
538
+ );
539
+ const proactiveCooldownMs = hasCooldown ? prefs.proactiveCooldownMs ?? null : existing?.proactiveCooldownMs ?? null;
540
+ const hasDeliveredDay = Object.prototype.hasOwnProperty.call(
541
+ prefs,
542
+ "proactiveDeliveredDay"
543
+ );
544
+ const proactiveDeliveredDay = hasDeliveredDay ? prefs.proactiveDeliveredDay ?? null : existing?.proactiveDeliveredDay ?? null;
545
+ const hasDeliveredCount = Object.prototype.hasOwnProperty.call(
546
+ prefs,
547
+ "proactiveDeliveredCount"
548
+ );
549
+ const proactiveDeliveredCount = hasDeliveredCount ? prefs.proactiveDeliveredCount ?? null : existing?.proactiveDeliveredCount ?? null;
550
+ const hasLastDelivered = Object.prototype.hasOwnProperty.call(
551
+ prefs,
552
+ "proactiveLastDeliveredAt"
553
+ );
554
+ const proactiveLastDeliveredAt = hasLastDelivered ? prefs.proactiveLastDeliveredAt ?? null : existing?.proactiveLastDeliveredAt ?? null;
555
+ await pool.query(
556
+ "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 ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20) 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",
557
+ [
558
+ sessionId,
559
+ providerId,
560
+ model,
561
+ system,
562
+ autoRouting,
563
+ language,
564
+ languageUpdatedAt,
565
+ continuityPreferredDeviceId,
566
+ continuityMode,
567
+ proactiveAllowed,
568
+ proactiveObserve,
569
+ proactiveDeliver,
570
+ Array.isArray(proactiveAllowedChannels) ? JSON.stringify(proactiveAllowedChannels) : null,
571
+ proactivePausedUntil,
572
+ proactiveMaxPerDay,
573
+ proactiveCooldownMs,
574
+ proactiveDeliveredDay,
575
+ proactiveDeliveredCount,
576
+ proactiveLastDeliveredAt,
577
+ now
578
+ ]
579
+ );
580
+ return await this.getSessionPrefs(sessionId) ?? {
581
+ sessionId,
582
+ providerId: providerId ?? void 0,
583
+ model: model ?? void 0,
584
+ system: system ?? void 0,
585
+ autoRouting: autoRouting ?? void 0,
586
+ language: language ?? void 0,
587
+ languageUpdatedAt: languageUpdatedAt ?? void 0,
588
+ continuityPreferredDeviceId: continuityPreferredDeviceId ?? void 0,
589
+ continuityMode: continuityMode ?? void 0,
590
+ updatedAt: now
591
+ };
592
+ },
593
+ async clearSessionPrefs(sessionId) {
594
+ await pool.query("DELETE FROM session_prefs WHERE session_id = $1", [sessionId]);
595
+ }
596
+ };
597
+ };
598
+
599
+ // packages/storage/src/postgres/tool-policy.ts
600
+ var createToolPolicyStore = (pool) => {
601
+ return {
602
+ async getToolPolicy() {
603
+ const result = await pool.query(
604
+ "SELECT id, allow, deny, updated_at FROM tool_policy WHERE id = $1",
605
+ ["global"]
606
+ );
607
+ const row = result.rows[0];
608
+ if (!row) {
609
+ return void 0;
610
+ }
611
+ return {
612
+ allow: row.allow ? JSON.parse(String(row.allow)) : void 0,
613
+ deny: row.deny ? JSON.parse(String(row.deny)) : void 0,
614
+ updatedAt: row.updated_at ? String(row.updated_at) : void 0
615
+ };
616
+ },
617
+ async setToolPolicy(policy) {
618
+ const record = {
619
+ allow: policy.allow ?? [],
620
+ deny: policy.deny ?? [],
621
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
622
+ };
623
+ await pool.query(
624
+ "INSERT INTO tool_policy (id, allow, deny, updated_at) VALUES ($1, $2, $3, $4) ON CONFLICT (id) DO UPDATE SET allow = EXCLUDED.allow, deny = EXCLUDED.deny, updated_at = EXCLUDED.updated_at",
625
+ [
626
+ "global",
627
+ JSON.stringify(record.allow ?? []),
628
+ JSON.stringify(record.deny ?? []),
629
+ record.updatedAt
630
+ ]
631
+ );
632
+ return record;
633
+ }
634
+ };
635
+ };
636
+
637
+ // packages/storage/src/postgres/devices.ts
638
+ var createDeviceStore = (pool) => {
639
+ const selectDevices = "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 ";
640
+ return {
641
+ async listDevices() {
642
+ const result = await pool.query(`${selectDevices}FROM devices ORDER BY created_at DESC`);
643
+ return result.rows.map(mapDevice);
644
+ },
645
+ async getDeviceById(id) {
646
+ const result = await pool.query(`${selectDevices}FROM devices WHERE id = $1`, [id]);
647
+ return result.rows[0] ? mapDevice(result.rows[0]) : void 0;
648
+ },
649
+ async getDeviceByTokenHash(tokenHash) {
650
+ const result = await pool.query(`${selectDevices}FROM devices WHERE token_hash = $1`, [tokenHash]);
651
+ return result.rows[0] ? mapDevice(result.rows[0]) : void 0;
652
+ },
653
+ async createDevice(record) {
654
+ await pool.query(
655
+ "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 ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)",
656
+ [
657
+ record.id,
658
+ record.name ?? null,
659
+ record.type ?? null,
660
+ record.role ?? null,
661
+ record.caps ? JSON.stringify(record.caps) : null,
662
+ record.status,
663
+ record.scopes ? JSON.stringify(record.scopes) : null,
664
+ record.authType,
665
+ record.tokenHash ?? null,
666
+ record.tokenHint ?? null,
667
+ record.publicKey ?? null,
668
+ record.publicKeyAlgorithm ?? null,
669
+ record.createdAt,
670
+ record.updatedAt,
671
+ record.lastSeenAt ?? null
672
+ ]
673
+ );
674
+ return record;
675
+ },
676
+ async updateDevice(id, update) {
677
+ const existing = await this.getDeviceById(id);
678
+ if (!existing) {
679
+ return void 0;
680
+ }
681
+ const updated = {
682
+ ...existing,
683
+ name: update.name ?? existing.name,
684
+ type: update.type ?? existing.type,
685
+ scopes: update.scopes ?? existing.scopes,
686
+ role: update.role ?? existing.role,
687
+ caps: update.caps ?? existing.caps,
688
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
689
+ };
690
+ await pool.query(
691
+ "UPDATE devices SET name = $1, type = $2, role = $3, caps = $4, scopes = $5, updated_at = $6 WHERE id = $7",
692
+ [
693
+ updated.name ?? null,
694
+ updated.type ?? null,
695
+ updated.role ?? null,
696
+ updated.caps ? JSON.stringify(updated.caps) : null,
697
+ updated.scopes ? JSON.stringify(updated.scopes) : null,
698
+ updated.updatedAt,
699
+ id
700
+ ]
701
+ );
702
+ return updated;
703
+ },
704
+ async revokeDevice(id) {
705
+ const existing = await this.getDeviceById(id);
706
+ if (!existing) {
707
+ return void 0;
708
+ }
709
+ const updated = {
710
+ ...existing,
711
+ status: "revoked",
712
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
713
+ };
714
+ await pool.query(
715
+ "UPDATE devices SET status = $1, updated_at = $2 WHERE id = $3",
716
+ [updated.status, updated.updatedAt, id]
717
+ );
718
+ return updated;
719
+ },
720
+ async touchDevice(id) {
721
+ const now = (/* @__PURE__ */ new Date()).toISOString();
722
+ await pool.query(
723
+ "UPDATE devices SET last_seen_at = $1, updated_at = $2 WHERE id = $3",
724
+ [now, now, id]
725
+ );
726
+ }
727
+ };
728
+ };
729
+
730
+ // packages/storage/src/postgres/channels.ts
731
+ import { randomUUID as randomUUID2 } from "node:crypto";
732
+ var createChannelAllowStore = (pool) => {
733
+ const selectAllows = "SELECT id, channel, chat_id, user_id, status, note, created_at, updated_at ";
734
+ return {
735
+ async listChannelAllows(channel) {
736
+ const result = channel ? await pool.query(
737
+ `${selectAllows}FROM channel_allows WHERE channel = $1 ORDER BY created_at DESC`,
738
+ [channel]
739
+ ) : await pool.query(`${selectAllows}FROM channel_allows ORDER BY created_at DESC`);
740
+ return result.rows.map(mapChannelAllow);
741
+ },
742
+ async getChannelAllow(channel, chatId, userId) {
743
+ const userKey = userId ?? "";
744
+ let result = await pool.query(
745
+ `${selectAllows}FROM channel_allows WHERE channel = $1 AND chat_id = $2 AND user_id = $3`,
746
+ [channel, chatId, userKey]
747
+ );
748
+ if (result.rows[0]) {
749
+ return mapChannelAllow(result.rows[0]);
750
+ }
751
+ if (userId) {
752
+ result = await pool.query(
753
+ `${selectAllows}FROM channel_allows WHERE channel = $1 AND chat_id = $2 AND user_id = $3`,
754
+ [channel, chatId, ""]
755
+ );
756
+ return result.rows[0] ? mapChannelAllow(result.rows[0]) : void 0;
757
+ }
758
+ return void 0;
759
+ },
760
+ async allowChannel(record) {
761
+ const now = (/* @__PURE__ */ new Date()).toISOString();
762
+ const userKey = record.userId ?? "";
763
+ await pool.query(
764
+ "INSERT INTO channel_allows (id, channel, chat_id, user_id, status, note, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) ON CONFLICT (channel, chat_id, user_id) DO UPDATE SET status = EXCLUDED.status, note = EXCLUDED.note, updated_at = EXCLUDED.updated_at",
765
+ [
766
+ randomUUID2(),
767
+ record.channel,
768
+ record.chatId,
769
+ userKey,
770
+ "allowed",
771
+ record.note ?? null,
772
+ now,
773
+ now
774
+ ]
775
+ );
776
+ const stored = await this.getChannelAllow(record.channel, record.chatId, record.userId);
777
+ return stored ?? {
778
+ id: randomUUID2(),
779
+ channel: record.channel,
780
+ chatId: record.chatId,
781
+ userId: record.userId,
782
+ note: record.note,
783
+ status: "allowed",
784
+ createdAt: now,
785
+ updatedAt: now
786
+ };
787
+ },
788
+ async revokeChannel(id) {
789
+ const result = await pool.query(
790
+ "UPDATE channel_allows SET status = $1, updated_at = $2 WHERE id = $3 RETURNING id, channel, chat_id, user_id, status, note, created_at, updated_at",
791
+ ["revoked", (/* @__PURE__ */ new Date()).toISOString(), id]
792
+ );
793
+ return result.rows[0] ? mapChannelAllow(result.rows[0]) : void 0;
794
+ }
795
+ };
796
+ };
797
+
798
+ // packages/storage/src/postgres/approvals.ts
799
+ import { randomUUID as randomUUID3 } from "node:crypto";
800
+ var createApprovalStore = (pool) => {
801
+ const selectApproval = "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 ";
802
+ return {
803
+ async createApprovalRequest(request) {
804
+ const now = (/* @__PURE__ */ new Date()).toISOString();
805
+ const id = request.id ?? randomUUID3();
806
+ const record = {
807
+ id,
808
+ status: request.status ?? "pending",
809
+ kind: request.kind ?? "tool",
810
+ toolName: request.toolName,
811
+ toolInput: request.toolInput ?? {},
812
+ sessionId: request.sessionId,
813
+ channel: request.channel,
814
+ chatId: request.chatId,
815
+ userId: request.userId,
816
+ userText: request.userText,
817
+ risk: request.risk,
818
+ reason: request.reason,
819
+ createdAt: request.createdAt ?? now,
820
+ updatedAt: request.updatedAt ?? now,
821
+ expiresAt: request.expiresAt,
822
+ decidedAt: request.decidedAt,
823
+ decidedBy: request.decidedBy,
824
+ result: request.result
825
+ };
826
+ const result = await pool.query(
827
+ `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 ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18) 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 RETURNING ${selectApproval.replace("SELECT ", "")}`,
828
+ [
829
+ record.id,
830
+ record.status,
831
+ record.kind,
832
+ record.toolName,
833
+ JSON.stringify(record.toolInput ?? {}),
834
+ record.sessionId,
835
+ record.channel,
836
+ record.chatId,
837
+ record.userId ?? null,
838
+ record.userText ?? null,
839
+ record.risk ?? null,
840
+ record.reason ?? null,
841
+ record.createdAt,
842
+ record.updatedAt,
843
+ record.expiresAt ?? null,
844
+ record.decidedAt ?? null,
845
+ record.decidedBy ? JSON.stringify(record.decidedBy) : null,
846
+ record.result ? JSON.stringify(record.result) : null
847
+ ]
848
+ );
849
+ return result.rows[0] ? mapApproval(result.rows[0]) : record;
850
+ },
851
+ async getApprovalRequest(id) {
852
+ const result = await pool.query(`${selectApproval}FROM approval_requests WHERE id = $1`, [id]);
853
+ return result.rows[0] ? mapApproval(result.rows[0]) : void 0;
854
+ },
855
+ async listApprovalRequests(options) {
856
+ const limit = options?.limit ?? 50;
857
+ const status = options?.status;
858
+ if (status) {
859
+ const result2 = await pool.query(
860
+ `${selectApproval}FROM approval_requests WHERE status = $1 ORDER BY created_at DESC LIMIT $2`,
861
+ [status, limit]
862
+ );
863
+ return result2.rows.map(mapApproval);
864
+ }
865
+ const result = await pool.query(
866
+ `${selectApproval}FROM approval_requests ORDER BY created_at DESC LIMIT $1`,
867
+ [limit]
868
+ );
869
+ return result.rows.map(mapApproval);
870
+ },
871
+ async updateApprovalRequest(id, update) {
872
+ const existing = await this.getApprovalRequest(id);
873
+ if (!existing) return void 0;
874
+ const merged = {
875
+ ...existing,
876
+ ...update,
877
+ id: existing.id,
878
+ createdAt: existing.createdAt,
879
+ updatedAt: update.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
880
+ };
881
+ return this.createApprovalRequest({
882
+ ...merged,
883
+ id: merged.id,
884
+ status: merged.status,
885
+ createdAt: merged.createdAt,
886
+ updatedAt: merged.updatedAt
887
+ });
888
+ }
889
+ };
890
+ };
891
+
892
+ // packages/storage/src/postgres/audit.ts
893
+ var createAuditStore = (pool) => {
894
+ return {
895
+ async appendAudit(event) {
896
+ await pool.query(
897
+ "INSERT INTO audit (id, time, type, payload) VALUES ($1, $2, $3, $4)",
898
+ [
899
+ event.id,
900
+ event.time,
901
+ event.type,
902
+ event.payload ? JSON.stringify(event.payload) : null
903
+ ]
904
+ );
905
+ }
906
+ };
907
+ };
908
+
909
+ // packages/storage/src/postgres/agent-runs.ts
910
+ var selectRun = "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 ";
911
+ var mapRun = (row) => {
912
+ const parseJson2 = (value) => {
913
+ if (!value) return void 0;
914
+ try {
915
+ return JSON.parse(String(value));
916
+ } catch {
917
+ return void 0;
918
+ }
919
+ };
920
+ return {
921
+ id: String(row.id),
922
+ sessionId: row.session_id ? String(row.session_id) : void 0,
923
+ agentId: row.agent_id ? String(row.agent_id) : void 0,
924
+ parentAgentId: row.parent_agent_id ? String(row.parent_agent_id) : void 0,
925
+ parentRunId: row.parent_run_id ? String(row.parent_run_id) : void 0,
926
+ lane: String(row.lane),
927
+ status: String(row.status),
928
+ createdAt: String(row.created_at),
929
+ startedAt: row.started_at ? String(row.started_at) : void 0,
930
+ endedAt: row.ended_at ? String(row.ended_at) : void 0,
931
+ timeoutMs: row.timeout_ms === null || row.timeout_ms === void 0 ? void 0 : Number(row.timeout_ms),
932
+ channel: row.channel ? String(row.channel) : void 0,
933
+ chatId: row.chat_id ? String(row.chat_id) : void 0,
934
+ userId: row.user_id ? String(row.user_id) : void 0,
935
+ providerId: row.provider_id ? String(row.provider_id) : void 0,
936
+ model: row.model ? String(row.model) : void 0,
937
+ system: row.system ? String(row.system) : void 0,
938
+ text: row.text ? String(row.text) : void 0,
939
+ metadata: parseJson2(row.metadata),
940
+ metrics: parseJson2(row.metrics),
941
+ resultSummary: row.result_summary ? String(row.result_summary) : void 0,
942
+ error: row.error ? String(row.error) : void 0
943
+ };
944
+ };
945
+ var mapEvent2 = (row) => ({
946
+ id: String(row.id),
947
+ runId: String(row.run_id),
948
+ time: String(row.time),
949
+ type: String(row.type),
950
+ payload: row.payload ? JSON.parse(String(row.payload)) : void 0
951
+ });
952
+ var createAgentRunStore = (pool) => {
953
+ return {
954
+ async upsertAgentRun(record) {
955
+ const result = await pool.query(
956
+ `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 ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22) 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 RETURNING ${selectRun.replace("SELECT ", "")}`,
957
+ [
958
+ record.id,
959
+ record.sessionId ?? null,
960
+ record.agentId ?? null,
961
+ record.parentAgentId ?? null,
962
+ record.parentRunId ?? null,
963
+ record.lane,
964
+ record.status,
965
+ record.createdAt,
966
+ record.startedAt ?? null,
967
+ record.endedAt ?? null,
968
+ record.timeoutMs ?? null,
969
+ record.channel ?? null,
970
+ record.chatId ?? null,
971
+ record.userId ?? null,
972
+ record.providerId ?? null,
973
+ record.model ?? null,
974
+ record.system ?? null,
975
+ record.text ?? null,
976
+ record.metadata ? JSON.stringify(record.metadata) : null,
977
+ record.metrics ? JSON.stringify(record.metrics) : null,
978
+ record.resultSummary ?? null,
979
+ record.error ?? null
980
+ ]
981
+ );
982
+ return result.rows[0] ? mapRun(result.rows[0]) : record;
983
+ },
984
+ async updateAgentRun(id, update) {
985
+ const existing = await this.getAgentRun(id);
986
+ if (!existing) return void 0;
987
+ const merged = { ...existing, ...update };
988
+ return this.upsertAgentRun(merged);
989
+ },
990
+ async getAgentRun(id) {
991
+ const result = await pool.query(`${selectRun}FROM agent_runs WHERE id = $1`, [id]);
992
+ return result.rows[0] ? mapRun(result.rows[0]) : void 0;
993
+ },
994
+ async listAgentRuns(options) {
995
+ const limit = options?.limit ?? 50;
996
+ const filters = [];
997
+ const params = [];
998
+ if (options?.status) {
999
+ params.push(options.status);
1000
+ filters.push(`status = $${params.length}`);
1001
+ }
1002
+ if (options?.lane) {
1003
+ params.push(options.lane);
1004
+ filters.push(`lane = $${params.length}`);
1005
+ }
1006
+ if (options?.sessionId) {
1007
+ params.push(options.sessionId);
1008
+ filters.push(`session_id = $${params.length}`);
1009
+ }
1010
+ if (options?.since) {
1011
+ params.push(options.since);
1012
+ filters.push(`created_at >= $${params.length}`);
1013
+ }
1014
+ params.push(limit);
1015
+ const where = filters.length ? `WHERE ${filters.join(" AND ")}` : "";
1016
+ const result = await pool.query(
1017
+ `${selectRun}FROM agent_runs ${where} ORDER BY created_at DESC LIMIT $${params.length}`,
1018
+ params
1019
+ );
1020
+ return result.rows.map(mapRun);
1021
+ },
1022
+ async appendAgentRunEvent(event) {
1023
+ await pool.query(
1024
+ "INSERT INTO agent_run_events (id, run_id, time, type, payload) VALUES ($1,$2,$3,$4,$5)",
1025
+ [
1026
+ event.id,
1027
+ event.runId,
1028
+ event.time,
1029
+ event.type,
1030
+ event.payload ? JSON.stringify(event.payload) : null
1031
+ ]
1032
+ );
1033
+ },
1034
+ async listAgentRunEvents(runId, options) {
1035
+ const limit = options?.limit ?? 50;
1036
+ const result = await pool.query(
1037
+ "SELECT id, run_id, time, type, payload FROM agent_run_events WHERE run_id = $1 ORDER BY time DESC LIMIT $2",
1038
+ [runId, limit]
1039
+ );
1040
+ return result.rows.map(mapEvent2).reverse();
1041
+ }
1042
+ };
1043
+ };
1044
+
1045
+ // packages/storage/src/postgres/agent-queue.ts
1046
+ var selectQueue = "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 ";
1047
+ var mapRecord = (row) => {
1048
+ const parseJson2 = (value) => {
1049
+ if (!value) return void 0;
1050
+ try {
1051
+ return JSON.parse(String(value));
1052
+ } catch {
1053
+ return void 0;
1054
+ }
1055
+ };
1056
+ return {
1057
+ id: String(row.id),
1058
+ sessionId: row.session_id ? String(row.session_id) : void 0,
1059
+ agentId: row.agent_id ? String(row.agent_id) : void 0,
1060
+ parentAgentId: row.parent_agent_id ? String(row.parent_agent_id) : void 0,
1061
+ parentRunId: row.parent_run_id ? String(row.parent_run_id) : void 0,
1062
+ lane: String(row.lane),
1063
+ status: String(row.status),
1064
+ createdAt: String(row.created_at),
1065
+ startedAt: row.started_at ? String(row.started_at) : void 0,
1066
+ endedAt: row.ended_at ? String(row.ended_at) : void 0,
1067
+ leaseUntil: row.lease_until ? String(row.lease_until) : void 0,
1068
+ priority: row.priority === null || row.priority === void 0 ? void 0 : Number(row.priority),
1069
+ channel: row.channel ? String(row.channel) : void 0,
1070
+ chatId: row.chat_id ? String(row.chat_id) : void 0,
1071
+ userId: row.user_id ? String(row.user_id) : void 0,
1072
+ providerId: row.provider_id ? String(row.provider_id) : void 0,
1073
+ model: row.model ? String(row.model) : void 0,
1074
+ system: row.system ? String(row.system) : void 0,
1075
+ text: row.text ? String(row.text) : void 0,
1076
+ timeoutMs: row.timeout_ms === null || row.timeout_ms === void 0 ? void 0 : Number(row.timeout_ms),
1077
+ toolPolicy: parseJson2(row.tool_policy),
1078
+ metadata: parseJson2(row.metadata),
1079
+ error: row.error ? String(row.error) : void 0
1080
+ };
1081
+ };
1082
+ var createAgentQueueStore = (pool) => {
1083
+ return {
1084
+ async enqueueAgentQueue(record) {
1085
+ const result = await pool.query(
1086
+ `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 ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23) 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 RETURNING ${selectQueue.replace("SELECT ", "")}`,
1087
+ [
1088
+ record.id,
1089
+ record.sessionId ?? null,
1090
+ record.agentId ?? null,
1091
+ record.parentAgentId ?? null,
1092
+ record.parentRunId ?? null,
1093
+ record.lane,
1094
+ record.status,
1095
+ record.createdAt,
1096
+ record.startedAt ?? null,
1097
+ record.endedAt ?? null,
1098
+ record.leaseUntil ?? null,
1099
+ record.priority ?? null,
1100
+ record.channel ?? null,
1101
+ record.chatId ?? null,
1102
+ record.userId ?? null,
1103
+ record.providerId ?? null,
1104
+ record.model ?? null,
1105
+ record.system ?? null,
1106
+ record.text ?? null,
1107
+ record.timeoutMs ?? null,
1108
+ record.toolPolicy ? JSON.stringify(record.toolPolicy) : null,
1109
+ record.metadata ? JSON.stringify(record.metadata) : null,
1110
+ record.error ?? null
1111
+ ]
1112
+ );
1113
+ return result.rows[0] ? mapRecord(result.rows[0]) : record;
1114
+ },
1115
+ async updateAgentQueue(id, update) {
1116
+ const existing = await this.getAgentQueue(id);
1117
+ if (!existing) return void 0;
1118
+ const merged = { ...existing, ...update };
1119
+ return this.enqueueAgentQueue(merged);
1120
+ },
1121
+ async getAgentQueue(id) {
1122
+ const result = await pool.query(`${selectQueue}FROM agent_queue WHERE id = $1`, [id]);
1123
+ return result.rows[0] ? mapRecord(result.rows[0]) : void 0;
1124
+ },
1125
+ async listAgentQueue(options) {
1126
+ const limit = options?.limit ?? 50;
1127
+ const order = options?.order === "asc" ? "ASC" : "DESC";
1128
+ const orderBy = options?.orderBy === "priority" ? "COALESCE(priority, 0) DESC, created_at" : "created_at";
1129
+ const filters = [];
1130
+ const params = [];
1131
+ if (options?.status) {
1132
+ params.push(options.status);
1133
+ filters.push(`status = $${params.length}`);
1134
+ }
1135
+ if (options?.lane) {
1136
+ params.push(options.lane);
1137
+ filters.push(`lane = $${params.length}`);
1138
+ }
1139
+ if (options?.sessionId) {
1140
+ params.push(options.sessionId);
1141
+ filters.push(`session_id = $${params.length}`);
1142
+ }
1143
+ if (options?.agentId) {
1144
+ params.push(options.agentId);
1145
+ filters.push(`agent_id = $${params.length}`);
1146
+ }
1147
+ params.push(limit);
1148
+ const where = filters.length ? `WHERE ${filters.join(" AND ")}` : "";
1149
+ const result = await pool.query(
1150
+ `${selectQueue}FROM agent_queue ${where} ORDER BY ${orderBy} ${order} LIMIT $${params.length}`,
1151
+ params
1152
+ );
1153
+ return result.rows.map(mapRecord);
1154
+ }
1155
+ };
1156
+ };
1157
+
1158
+ // packages/storage/src/postgres/session-inbox.ts
1159
+ var mapInbox = (row) => {
1160
+ const parseJson2 = (value) => {
1161
+ if (!value) return void 0;
1162
+ try {
1163
+ return JSON.parse(String(value));
1164
+ } catch {
1165
+ return void 0;
1166
+ }
1167
+ };
1168
+ return {
1169
+ id: String(row.id),
1170
+ sessionId: String(row.session_id),
1171
+ status: String(row.status),
1172
+ createdAt: String(row.created_at),
1173
+ startedAt: row.started_at ? String(row.started_at) : void 0,
1174
+ endedAt: row.ended_at ? String(row.ended_at) : void 0,
1175
+ channel: row.channel ? String(row.channel) : void 0,
1176
+ chatId: row.chat_id ? String(row.chat_id) : void 0,
1177
+ userId: row.user_id ? String(row.user_id) : void 0,
1178
+ text: row.text ? String(row.text) : void 0,
1179
+ metadata: parseJson2(row.metadata),
1180
+ error: row.error ? String(row.error) : void 0
1181
+ };
1182
+ };
1183
+ var selectInbox = "SELECT id, session_id, status, created_at, started_at, ended_at, channel, chat_id, user_id, text, metadata, error ";
1184
+ var createSessionInboxStore = (pool) => {
1185
+ return {
1186
+ async enqueueSessionInbox(record) {
1187
+ const result = await pool.query(
1188
+ `INSERT INTO session_inbox (id, session_id, status, created_at, started_at, ended_at, channel, chat_id, user_id, text, metadata, error) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12) 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 RETURNING ${selectInbox.replace("SELECT ", "")}`,
1189
+ [
1190
+ record.id,
1191
+ record.sessionId,
1192
+ record.status,
1193
+ record.createdAt,
1194
+ record.startedAt ?? null,
1195
+ record.endedAt ?? null,
1196
+ record.channel ?? null,
1197
+ record.chatId ?? null,
1198
+ record.userId ?? null,
1199
+ record.text ?? null,
1200
+ record.metadata ? JSON.stringify(record.metadata) : null,
1201
+ record.error ?? null
1202
+ ]
1203
+ );
1204
+ return result.rows[0] ? mapInbox(result.rows[0]) : record;
1205
+ },
1206
+ async updateSessionInbox(id, update) {
1207
+ const existing = await this.getSessionInbox(id);
1208
+ if (!existing) return void 0;
1209
+ const merged = { ...existing, ...update };
1210
+ return this.enqueueSessionInbox(merged);
1211
+ },
1212
+ async getSessionInbox(id) {
1213
+ const result = await pool.query(`${selectInbox}FROM session_inbox WHERE id = $1`, [id]);
1214
+ return result.rows[0] ? mapInbox(result.rows[0]) : void 0;
1215
+ },
1216
+ async listSessionInbox(options) {
1217
+ const limit = options?.limit ?? 50;
1218
+ const order = options?.order === "asc" ? "ASC" : "DESC";
1219
+ const filters = [];
1220
+ const params = [];
1221
+ if (options?.sessionId) {
1222
+ params.push(options.sessionId);
1223
+ filters.push(`session_id = $${params.length}`);
1224
+ }
1225
+ if (options?.status) {
1226
+ params.push(options.status);
1227
+ filters.push(`status = $${params.length}`);
1228
+ }
1229
+ params.push(limit);
1230
+ const where = filters.length ? `WHERE ${filters.join(" AND ")}` : "";
1231
+ const result = await pool.query(
1232
+ `${selectInbox}FROM session_inbox ${where} ORDER BY created_at ${order} LIMIT $${params.length}`,
1233
+ params
1234
+ );
1235
+ return result.rows.map(mapInbox);
1236
+ }
1237
+ };
1238
+ };
1239
+
1240
+ // packages/storage/src/postgres/session-routes.ts
1241
+ var selectRoute = "SELECT session_id, agent_id, lane_id, queue_mode, announce_mode, updated_at ";
1242
+ var mapRoute = (row) => {
1243
+ return {
1244
+ sessionId: String(row.session_id),
1245
+ agentId: row.agent_id ? String(row.agent_id) : void 0,
1246
+ laneId: row.lane_id ? String(row.lane_id) : void 0,
1247
+ queueMode: row.queue_mode ? String(row.queue_mode) : void 0,
1248
+ announceMode: row.announce_mode ? String(row.announce_mode) : void 0,
1249
+ updatedAt: row.updated_at ? String(row.updated_at) : (/* @__PURE__ */ new Date()).toISOString()
1250
+ };
1251
+ };
1252
+ var createSessionRouteStore = (pool) => {
1253
+ return {
1254
+ async getSessionRoute(sessionId) {
1255
+ const result = await pool.query(`${selectRoute}FROM session_routes WHERE session_id = $1`, [
1256
+ sessionId
1257
+ ]);
1258
+ return result.rows[0] ? mapRoute(result.rows[0]) : void 0;
1259
+ },
1260
+ async setSessionRoute(sessionId, route) {
1261
+ const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1262
+ const result = await pool.query(
1263
+ `INSERT INTO session_routes (session_id, agent_id, lane_id, queue_mode, announce_mode, updated_at) VALUES ($1,$2,$3,$4,$5,$6) 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 RETURNING ${selectRoute.replace("SELECT ", "")}`,
1264
+ [
1265
+ sessionId,
1266
+ route.agentId ?? null,
1267
+ route.laneId ?? null,
1268
+ route.queueMode ?? null,
1269
+ route.announceMode ?? null,
1270
+ updatedAt
1271
+ ]
1272
+ );
1273
+ return result.rows[0] ? mapRoute(result.rows[0]) : { sessionId, ...route, updatedAt };
1274
+ },
1275
+ async listSessionRoutes(options) {
1276
+ const limit = options?.limit ?? 100;
1277
+ const result = await pool.query(
1278
+ `${selectRoute}FROM session_routes ORDER BY updated_at DESC LIMIT $1`,
1279
+ [limit]
1280
+ );
1281
+ return result.rows.map(mapRoute);
1282
+ }
1283
+ };
1284
+ };
1285
+
1286
+ // packages/storage/src/postgres.ts
1287
+ var PostgresStorage = class _PostgresStorage {
1288
+ pool;
1289
+ sessions;
1290
+ prefs;
1291
+ toolPolicy;
1292
+ devices;
1293
+ channels;
1294
+ approvals;
1295
+ audit;
1296
+ agentRuns;
1297
+ agentQueue;
1298
+ sessionInbox;
1299
+ sessionRoutes;
1300
+ constructor(pool) {
1301
+ this.pool = pool;
1302
+ this.sessions = createSessionStore(pool);
1303
+ this.prefs = createSessionPrefsStore(pool);
1304
+ this.toolPolicy = createToolPolicyStore(pool);
1305
+ this.devices = createDeviceStore(pool);
1306
+ this.channels = createChannelAllowStore(pool);
1307
+ this.approvals = createApprovalStore(pool);
1308
+ this.audit = createAuditStore(pool);
1309
+ this.agentRuns = createAgentRunStore(pool);
1310
+ this.agentQueue = createAgentQueueStore(pool);
1311
+ this.sessionInbox = createSessionInboxStore(pool);
1312
+ this.sessionRoutes = createSessionRouteStore(pool);
1313
+ }
1314
+ static async create(options) {
1315
+ const pool = createPool(options.url);
1316
+ await runMigrations(pool);
1317
+ return new _PostgresStorage(pool);
1318
+ }
1319
+ getSessionByKey(key) {
1320
+ return this.sessions.getSessionByKey(key);
1321
+ }
1322
+ getSessionById(id) {
1323
+ return this.sessions.getSessionById(id);
1324
+ }
1325
+ listSessions() {
1326
+ return this.sessions.listSessions();
1327
+ }
1328
+ createSession(key, meta) {
1329
+ return this.sessions.createSession(key, meta);
1330
+ }
1331
+ updateSession(id, update) {
1332
+ return this.sessions.updateSession(id, update);
1333
+ }
1334
+ appendProviderSwitch(record) {
1335
+ return this.sessions.appendProviderSwitch(record);
1336
+ }
1337
+ upsertSessionProviderUsage(entry) {
1338
+ return this.sessions.upsertSessionProviderUsage(entry);
1339
+ }
1340
+ appendSessionEvent(event) {
1341
+ return this.sessions.appendSessionEvent(event);
1342
+ }
1343
+ listSessionEvents(sessionId, options) {
1344
+ return this.sessions.listSessionEvents(sessionId, options);
1345
+ }
1346
+ countSessionEvents(sessionId) {
1347
+ return this.sessions.countSessionEvents(sessionId);
1348
+ }
1349
+ getSessionSummary(sessionId) {
1350
+ return this.sessions.getSessionSummary(sessionId);
1351
+ }
1352
+ setSessionSummary(sessionId, summary, eventCount) {
1353
+ return this.sessions.setSessionSummary(sessionId, summary, eventCount);
1354
+ }
1355
+ getToolPolicy() {
1356
+ return this.toolPolicy.getToolPolicy();
1357
+ }
1358
+ setToolPolicy(policy) {
1359
+ return this.toolPolicy.setToolPolicy(policy);
1360
+ }
1361
+ getSessionPrefs(sessionId) {
1362
+ return this.prefs.getSessionPrefs(sessionId);
1363
+ }
1364
+ setSessionPrefs(sessionId, prefs) {
1365
+ return this.prefs.setSessionPrefs(sessionId, prefs);
1366
+ }
1367
+ clearSessionPrefs(sessionId) {
1368
+ return this.prefs.clearSessionPrefs(sessionId);
1369
+ }
1370
+ getSessionRoute(sessionId) {
1371
+ return this.sessionRoutes.getSessionRoute(sessionId);
1372
+ }
1373
+ setSessionRoute(sessionId, route) {
1374
+ return this.sessionRoutes.setSessionRoute(sessionId, route);
1375
+ }
1376
+ listSessionRoutes(options) {
1377
+ return this.sessionRoutes.listSessionRoutes(options);
1378
+ }
1379
+ listDevices() {
1380
+ return this.devices.listDevices();
1381
+ }
1382
+ getDeviceById(id) {
1383
+ return this.devices.getDeviceById(id);
1384
+ }
1385
+ getDeviceByTokenHash(tokenHash) {
1386
+ return this.devices.getDeviceByTokenHash(tokenHash);
1387
+ }
1388
+ createDevice(record) {
1389
+ return this.devices.createDevice(record);
1390
+ }
1391
+ updateDevice(id, update) {
1392
+ return this.devices.updateDevice(id, update);
1393
+ }
1394
+ revokeDevice(id) {
1395
+ return this.devices.revokeDevice(id);
1396
+ }
1397
+ touchDevice(id) {
1398
+ return this.devices.touchDevice(id);
1399
+ }
1400
+ listChannelAllows(channel) {
1401
+ return this.channels.listChannelAllows(channel);
1402
+ }
1403
+ getChannelAllow(channel, chatId, userId) {
1404
+ return this.channels.getChannelAllow(channel, chatId, userId);
1405
+ }
1406
+ allowChannel(record) {
1407
+ return this.channels.allowChannel(record);
1408
+ }
1409
+ revokeChannel(id) {
1410
+ return this.channels.revokeChannel(id);
1411
+ }
1412
+ createApprovalRequest(request) {
1413
+ return this.approvals.createApprovalRequest(request);
1414
+ }
1415
+ getApprovalRequest(id) {
1416
+ return this.approvals.getApprovalRequest(id);
1417
+ }
1418
+ listApprovalRequests(options) {
1419
+ return this.approvals.listApprovalRequests(options);
1420
+ }
1421
+ updateApprovalRequest(id, update) {
1422
+ return this.approvals.updateApprovalRequest(id, update);
1423
+ }
1424
+ appendAudit(event) {
1425
+ return this.audit.appendAudit(event);
1426
+ }
1427
+ // -- Kaala Agent Runs ---------------------------------------------------
1428
+ upsertAgentRun(record) {
1429
+ return this.agentRuns.upsertAgentRun(record);
1430
+ }
1431
+ updateAgentRun(id, update) {
1432
+ return this.agentRuns.updateAgentRun(id, update);
1433
+ }
1434
+ getAgentRun(id) {
1435
+ return this.agentRuns.getAgentRun(id);
1436
+ }
1437
+ listAgentRuns(options) {
1438
+ return this.agentRuns.listAgentRuns(options);
1439
+ }
1440
+ appendAgentRunEvent(event) {
1441
+ return this.agentRuns.appendAgentRunEvent(event);
1442
+ }
1443
+ listAgentRunEvents(runId, options) {
1444
+ return this.agentRuns.listAgentRunEvents(runId, options);
1445
+ }
1446
+ // -- Session Inbox ---------------------------------------------------
1447
+ enqueueSessionInbox(record) {
1448
+ return this.sessionInbox.enqueueSessionInbox(record);
1449
+ }
1450
+ updateSessionInbox(id, update) {
1451
+ return this.sessionInbox.updateSessionInbox(id, update);
1452
+ }
1453
+ getSessionInbox(id) {
1454
+ return this.sessionInbox.getSessionInbox(id);
1455
+ }
1456
+ listSessionInbox(options) {
1457
+ return this.sessionInbox.listSessionInbox(options);
1458
+ }
1459
+ enqueueAgentQueue(record) {
1460
+ return this.agentQueue.enqueueAgentQueue(record);
1461
+ }
1462
+ updateAgentQueue(id, update) {
1463
+ return this.agentQueue.updateAgentQueue(id, update);
1464
+ }
1465
+ getAgentQueue(id) {
1466
+ return this.agentQueue.getAgentQueue(id);
1467
+ }
1468
+ listAgentQueue(options) {
1469
+ return this.agentQueue.listAgentQueue(options);
1470
+ }
1471
+ async close() {
1472
+ await this.pool.end();
1473
+ }
1474
+ };
1475
+
1476
+ export {
1477
+ PostgresStorage
1478
+ };
1479
+ //# sourceMappingURL=chunk-MINFB5LT.js.map