@axiom-lattice/local-stores 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,3372 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ DatabaseWrapper: () => DatabaseWrapper,
34
+ LocalA2AApiKeyStore: () => LocalA2AApiKeyStore,
35
+ LocalAssistantStore: () => LocalAssistantStore,
36
+ LocalChannelBindingStore: () => LocalChannelBindingStore,
37
+ LocalChannelInstallationStore: () => LocalChannelInstallationStore,
38
+ LocalDatabaseConfigStore: () => LocalDatabaseConfigStore,
39
+ LocalEvalStore: () => LocalEvalStore,
40
+ LocalMcpServerConfigStore: () => LocalMcpServerConfigStore,
41
+ LocalMetricsServerConfigStore: () => LocalMetricsServerConfigStore,
42
+ LocalProjectStore: () => LocalProjectStore,
43
+ LocalScheduleStorage: () => LocalScheduleStorage,
44
+ LocalSkillStore: () => LocalSkillStore,
45
+ LocalTenantStore: () => LocalTenantStore,
46
+ LocalThreadMessageQueueStore: () => LocalThreadMessageQueueStore,
47
+ LocalThreadStore: () => LocalThreadStore,
48
+ LocalUserStore: () => LocalUserStore,
49
+ LocalUserTenantLinkStore: () => LocalUserTenantLinkStore,
50
+ LocalWorkflowTrackingStore: () => LocalWorkflowTrackingStore,
51
+ LocalWorkspaceStore: () => LocalWorkspaceStore,
52
+ RunResult: () => RunResult,
53
+ StatementWrapper: () => StatementWrapper,
54
+ closeDatabase: () => closeDatabase,
55
+ createLocalStoreConfig: () => createLocalStoreConfig,
56
+ ensureTable: () => ensureTable,
57
+ getDatabase: () => getDatabase,
58
+ initDatabase: () => initDatabase,
59
+ nowISO: () => nowISO,
60
+ parseISO: () => parseISO
61
+ });
62
+ module.exports = __toCommonJS(index_exports);
63
+
64
+ // src/database.ts
65
+ var import_sql = __toESM(require("sql.js"));
66
+ var path = __toESM(require("path"));
67
+ var os = __toESM(require("os"));
68
+ var fs = __toESM(require("fs"));
69
+ var _SQL = null;
70
+ var _db = null;
71
+ function expandHome(filePath) {
72
+ if (filePath.startsWith("~")) {
73
+ return path.join(os.homedir(), filePath.slice(1));
74
+ }
75
+ return filePath;
76
+ }
77
+ var DatabaseWrapper = class {
78
+ constructor(sql, dbPath) {
79
+ this.dbPath = dbPath;
80
+ if (fs.existsSync(dbPath)) {
81
+ const buffer = fs.readFileSync(dbPath);
82
+ this.db = new sql.Database(buffer);
83
+ } else {
84
+ this.db = new sql.Database();
85
+ }
86
+ }
87
+ /**
88
+ * Execute a SQL statement and return the wrapper for chaining (run).
89
+ * Automatically persists changes to disk.
90
+ */
91
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
92
+ run(sql, ...params) {
93
+ this.db.run(sql, params);
94
+ this.save();
95
+ return new RunResult(this.db);
96
+ }
97
+ /**
98
+ * Prepare and execute a query returning all matching rows as objects.
99
+ */
100
+ prepare(sql) {
101
+ return new StatementWrapper(this.db, sql, this);
102
+ }
103
+ /**
104
+ * Execute raw SQL (for DDL statements).
105
+ */
106
+ exec(sql) {
107
+ this.db.exec(sql);
108
+ }
109
+ /**
110
+ * Persist the database to disk.
111
+ */
112
+ save() {
113
+ const data = this.db.export();
114
+ const buffer = Buffer.from(data);
115
+ fs.writeFileSync(this.dbPath, buffer);
116
+ }
117
+ /**
118
+ * Close the database.
119
+ */
120
+ close() {
121
+ this.db.close();
122
+ }
123
+ /**
124
+ * Get the underlying sql.js database instance.
125
+ */
126
+ getRawDb() {
127
+ return this.db;
128
+ }
129
+ };
130
+ var StatementWrapper = class {
131
+ constructor(db, sql, parent) {
132
+ this.db = db;
133
+ this.sql = sql;
134
+ this.parent = parent || null;
135
+ }
136
+ /**
137
+ * Execute and return all rows as objects.
138
+ */
139
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
140
+ all(...params) {
141
+ const stmt = this.db.prepare(this.sql);
142
+ try {
143
+ if (params.length > 0) {
144
+ stmt.bind(params);
145
+ }
146
+ const rows = [];
147
+ while (stmt.step()) {
148
+ rows.push(stmt.getAsObject());
149
+ }
150
+ return rows;
151
+ } finally {
152
+ stmt.free();
153
+ }
154
+ }
155
+ /**
156
+ * Execute and return the first row as an object, or undefined.
157
+ */
158
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
159
+ get(...params) {
160
+ const stmt = this.db.prepare(this.sql);
161
+ try {
162
+ if (params.length > 0) {
163
+ stmt.bind(params);
164
+ }
165
+ if (stmt.step()) {
166
+ return stmt.getAsObject();
167
+ }
168
+ return void 0;
169
+ } finally {
170
+ stmt.free();
171
+ }
172
+ }
173
+ /**
174
+ * Execute without returning rows (INSERT/UPDATE/DELETE).
175
+ * Automatically persists changes to disk.
176
+ */
177
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
178
+ run(...params) {
179
+ this.db.run(this.sql, params);
180
+ if (this.parent) {
181
+ this.parent.save();
182
+ }
183
+ return new RunResult(this.db);
184
+ }
185
+ };
186
+ var RunResult = class {
187
+ constructor(db) {
188
+ this.db = db;
189
+ }
190
+ /** Number of rows modified by the last INSERT/UPDATE/DELETE. */
191
+ get changes() {
192
+ return this.db.getRowsModified();
193
+ }
194
+ };
195
+ async function initDatabase(options = {}) {
196
+ if (_db) return _db;
197
+ if (!_SQL) {
198
+ _SQL = await (0, import_sql.default)();
199
+ }
200
+ const rawPath = options.dbPath || "~/.axiom/lattice.db";
201
+ const dbPath = expandHome(rawPath);
202
+ const dir = path.dirname(dbPath);
203
+ if (!fs.existsSync(dir)) {
204
+ fs.mkdirSync(dir, { recursive: true });
205
+ }
206
+ _db = new DatabaseWrapper(_SQL, dbPath);
207
+ _db.exec("PRAGMA journal_mode = WAL;");
208
+ _db.exec("PRAGMA foreign_keys = ON;");
209
+ return _db;
210
+ }
211
+ function getDatabase() {
212
+ if (!_db) {
213
+ throw new Error("Database not initialized. Call await initDatabase() first.");
214
+ }
215
+ return _db;
216
+ }
217
+ function closeDatabase() {
218
+ if (_db) {
219
+ _db.save();
220
+ _db.close();
221
+ _db = null;
222
+ }
223
+ }
224
+ function ensureTable(db, ddl) {
225
+ db.exec(ddl);
226
+ }
227
+ function nowISO() {
228
+ return (/* @__PURE__ */ new Date()).toISOString();
229
+ }
230
+ function parseISO(iso) {
231
+ return new Date(iso);
232
+ }
233
+
234
+ // src/createLocalStoreConfig.ts
235
+ var import_langgraph_checkpoint_sqlite = require("@langchain/langgraph-checkpoint-sqlite");
236
+
237
+ // src/stores/LocalThreadStore.ts
238
+ var DDL = `
239
+ CREATE TABLE IF NOT EXISTS lt_threads (
240
+ id TEXT NOT NULL,
241
+ tenant_id TEXT NOT NULL,
242
+ assistant_id TEXT NOT NULL,
243
+ metadata TEXT DEFAULT '{}',
244
+ created_at TEXT NOT NULL,
245
+ updated_at TEXT NOT NULL,
246
+ PRIMARY KEY (tenant_id, id)
247
+ );
248
+ CREATE INDEX IF NOT EXISTS idx_lt_threads_assistant ON lt_threads(tenant_id, assistant_id);
249
+ `;
250
+ var LocalThreadStore = class {
251
+ constructor(db) {
252
+ this.db = db;
253
+ ensureTable(db, DDL);
254
+ }
255
+ async getThreadsByAssistantId(tenantId, assistantId, metadataFilter) {
256
+ const rows = this.db.prepare(
257
+ `SELECT * FROM lt_threads WHERE tenant_id = ? AND assistant_id = ? ORDER BY created_at DESC`
258
+ ).all(tenantId, assistantId);
259
+ let threads = rows.map(mapRowToThread);
260
+ if (metadataFilter && Object.keys(metadataFilter).length > 0) {
261
+ threads = threads.filter(
262
+ (t) => Object.entries(metadataFilter).every(
263
+ ([key, value]) => t.metadata?.[key] === value
264
+ )
265
+ );
266
+ }
267
+ return threads;
268
+ }
269
+ async getThreadById(tenantId, threadId) {
270
+ const row = this.db.prepare(
271
+ `SELECT * FROM lt_threads WHERE tenant_id = ? AND id = ?`
272
+ ).get(tenantId, threadId);
273
+ return row ? mapRowToThread(row) : void 0;
274
+ }
275
+ async createThread(tenantId, assistantId, threadId, data) {
276
+ const now = nowISO();
277
+ const metadata = JSON.stringify(data.metadata || {});
278
+ this.db.prepare(
279
+ `INSERT INTO lt_threads (id, tenant_id, assistant_id, metadata, created_at, updated_at)
280
+ VALUES (?, ?, ?, ?, ?, ?)
281
+ ON CONFLICT(tenant_id, id) DO UPDATE SET
282
+ assistant_id = excluded.assistant_id,
283
+ metadata = excluded.metadata,
284
+ updated_at = excluded.updated_at`
285
+ ).run(threadId, tenantId, assistantId, metadata, now, now);
286
+ return {
287
+ id: threadId,
288
+ tenantId,
289
+ assistantId,
290
+ metadata: data.metadata || {},
291
+ createdAt: parseISO(now),
292
+ updatedAt: parseISO(now)
293
+ };
294
+ }
295
+ async updateThread(tenantId, threadId, updates) {
296
+ const existing = await this.getThreadById(tenantId, threadId);
297
+ if (!existing) return null;
298
+ const updatedMetadata = {
299
+ ...existing.metadata,
300
+ ...updates.metadata || {}
301
+ };
302
+ const now = nowISO();
303
+ this.db.prepare(
304
+ `UPDATE lt_threads SET metadata = ?, updated_at = ? WHERE tenant_id = ? AND id = ?`
305
+ ).run(JSON.stringify(updatedMetadata), now, tenantId, threadId);
306
+ return {
307
+ ...existing,
308
+ metadata: updatedMetadata,
309
+ updatedAt: parseISO(now)
310
+ };
311
+ }
312
+ async deleteThread(tenantId, threadId) {
313
+ const result = this.db.prepare(
314
+ `DELETE FROM lt_threads WHERE tenant_id = ? AND id = ?`
315
+ ).run(tenantId, threadId);
316
+ return result.changes > 0;
317
+ }
318
+ async hasThread(tenantId, threadId) {
319
+ const row = this.db.prepare(
320
+ `SELECT 1 FROM lt_threads WHERE tenant_id = ? AND id = ? LIMIT 1`
321
+ ).get(tenantId, threadId);
322
+ return row !== void 0;
323
+ }
324
+ };
325
+ function mapRowToThread(row) {
326
+ return {
327
+ id: row.id,
328
+ tenantId: row.tenant_id,
329
+ assistantId: row.assistant_id,
330
+ metadata: JSON.parse(row.metadata || "{}"),
331
+ createdAt: parseISO(row.created_at),
332
+ updatedAt: parseISO(row.updated_at)
333
+ };
334
+ }
335
+
336
+ // src/stores/LocalAssistantStore.ts
337
+ var DDL2 = `
338
+ CREATE TABLE IF NOT EXISTS lt_assistants (
339
+ id TEXT NOT NULL,
340
+ tenant_id TEXT NOT NULL,
341
+ name TEXT NOT NULL,
342
+ description TEXT,
343
+ graph_definition TEXT NOT NULL,
344
+ created_at TEXT NOT NULL,
345
+ updated_at TEXT NOT NULL,
346
+ PRIMARY KEY (tenant_id, id)
347
+ );
348
+ `;
349
+ var LocalAssistantStore = class {
350
+ constructor(db) {
351
+ this.db = db;
352
+ ensureTable(db, DDL2);
353
+ }
354
+ async getAllAssistants(tenantId) {
355
+ const rows = this.db.prepare(
356
+ `SELECT * FROM lt_assistants WHERE tenant_id = ? ORDER BY created_at DESC`
357
+ ).all(tenantId);
358
+ return rows.map(mapRowToAssistant);
359
+ }
360
+ async getAssistantById(tenantId, id) {
361
+ const row = this.db.prepare(
362
+ `SELECT * FROM lt_assistants WHERE tenant_id = ? AND id = ?`
363
+ ).get(tenantId, id);
364
+ return row ? mapRowToAssistant(row) : null;
365
+ }
366
+ async createAssistant(tenantId, id, data) {
367
+ const now = nowISO();
368
+ this.db.prepare(
369
+ `INSERT INTO lt_assistants (id, tenant_id, name, description, graph_definition, created_at, updated_at)
370
+ VALUES (?, ?, ?, ?, ?, ?, ?)
371
+ ON CONFLICT(tenant_id, id) DO UPDATE SET
372
+ name = excluded.name,
373
+ description = excluded.description,
374
+ graph_definition = excluded.graph_definition,
375
+ updated_at = excluded.updated_at`
376
+ ).run(id, tenantId, data.name, data.description || null, JSON.stringify(data.graphDefinition), now, now);
377
+ return {
378
+ id,
379
+ tenantId,
380
+ name: data.name,
381
+ description: data.description,
382
+ graphDefinition: data.graphDefinition,
383
+ createdAt: parseISO(now),
384
+ updatedAt: parseISO(now)
385
+ };
386
+ }
387
+ async updateAssistant(tenantId, id, updates) {
388
+ const existing = await this.getAssistantById(tenantId, id);
389
+ if (!existing) return null;
390
+ const setClauses = [];
391
+ const values = [];
392
+ if (updates.name !== void 0) {
393
+ setClauses.push("name = ?");
394
+ values.push(updates.name);
395
+ }
396
+ if (updates.description !== void 0) {
397
+ setClauses.push("description = ?");
398
+ values.push(updates.description || null);
399
+ }
400
+ if (updates.graphDefinition !== void 0) {
401
+ setClauses.push("graph_definition = ?");
402
+ values.push(JSON.stringify(updates.graphDefinition));
403
+ }
404
+ if (setClauses.length === 0) return existing;
405
+ const now = nowISO();
406
+ setClauses.push("updated_at = ?");
407
+ values.push(now);
408
+ values.push(tenantId, id);
409
+ this.db.prepare(
410
+ `UPDATE lt_assistants SET ${setClauses.join(", ")} WHERE tenant_id = ? AND id = ?`
411
+ ).run(...values);
412
+ return this.getAssistantById(tenantId, id);
413
+ }
414
+ async deleteAssistant(tenantId, id) {
415
+ const result = this.db.prepare(
416
+ `DELETE FROM lt_assistants WHERE tenant_id = ? AND id = ?`
417
+ ).run(tenantId, id);
418
+ return result.changes > 0;
419
+ }
420
+ async hasAssistant(tenantId, id) {
421
+ const row = this.db.prepare(
422
+ `SELECT 1 FROM lt_assistants WHERE tenant_id = ? AND id = ? LIMIT 1`
423
+ ).get(tenantId, id);
424
+ return row !== void 0;
425
+ }
426
+ };
427
+ function mapRowToAssistant(row) {
428
+ return {
429
+ id: row.id,
430
+ tenantId: row.tenant_id,
431
+ name: row.name,
432
+ description: row.description || void 0,
433
+ graphDefinition: JSON.parse(row.graph_definition),
434
+ createdAt: parseISO(row.created_at),
435
+ updatedAt: parseISO(row.updated_at)
436
+ };
437
+ }
438
+
439
+ // src/stores/LocalWorkspaceStore.ts
440
+ var DDL3 = `
441
+ CREATE TABLE IF NOT EXISTS lt_workspaces (
442
+ id TEXT NOT NULL,
443
+ tenant_id TEXT NOT NULL,
444
+ name TEXT NOT NULL,
445
+ description TEXT,
446
+ storage_type TEXT NOT NULL,
447
+ created_at TEXT NOT NULL,
448
+ updated_at TEXT NOT NULL,
449
+ PRIMARY KEY (tenant_id, id)
450
+ );
451
+ `;
452
+ var LocalWorkspaceStore = class {
453
+ constructor(db) {
454
+ this.db = db;
455
+ ensureTable(db, DDL3);
456
+ }
457
+ async getAllWorkspaces(tenantId) {
458
+ const rows = this.db.prepare(
459
+ `SELECT * FROM lt_workspaces WHERE tenant_id = ? ORDER BY created_at DESC`
460
+ ).all(tenantId);
461
+ return rows.map(mapRowToWorkspace);
462
+ }
463
+ async getWorkspaceById(tenantId, id) {
464
+ const row = this.db.prepare(
465
+ `SELECT * FROM lt_workspaces WHERE tenant_id = ? AND id = ?`
466
+ ).get(tenantId, id);
467
+ return row ? mapRowToWorkspace(row) : null;
468
+ }
469
+ async createWorkspace(tenantId, id, data) {
470
+ const now = nowISO();
471
+ this.db.prepare(
472
+ `INSERT INTO lt_workspaces (id, tenant_id, name, description, storage_type, created_at, updated_at)
473
+ VALUES (?, ?, ?, ?, ?, ?, ?)
474
+ ON CONFLICT(tenant_id, id) DO UPDATE SET
475
+ name = excluded.name,
476
+ description = excluded.description,
477
+ storage_type = excluded.storage_type,
478
+ updated_at = excluded.updated_at`
479
+ ).run(id, tenantId, data.name, data.description || null, data.storageType, now, now);
480
+ return {
481
+ id,
482
+ tenantId,
483
+ name: data.name,
484
+ description: data.description,
485
+ storageType: data.storageType,
486
+ createdAt: parseISO(now),
487
+ updatedAt: parseISO(now)
488
+ };
489
+ }
490
+ async updateWorkspace(tenantId, id, updates) {
491
+ const existing = await this.getWorkspaceById(tenantId, id);
492
+ if (!existing) return null;
493
+ const setClauses = [];
494
+ const values = [];
495
+ if (updates.name !== void 0) {
496
+ setClauses.push("name = ?");
497
+ values.push(updates.name);
498
+ }
499
+ if (updates.description !== void 0) {
500
+ setClauses.push("description = ?");
501
+ values.push(updates.description || null);
502
+ }
503
+ if (updates.storageType !== void 0) {
504
+ setClauses.push("storage_type = ?");
505
+ values.push(updates.storageType);
506
+ }
507
+ if (setClauses.length === 0) return existing;
508
+ const now = nowISO();
509
+ setClauses.push("updated_at = ?");
510
+ values.push(now);
511
+ values.push(tenantId, id);
512
+ this.db.prepare(
513
+ `UPDATE lt_workspaces SET ${setClauses.join(", ")} WHERE tenant_id = ? AND id = ?`
514
+ ).run(...values);
515
+ return this.getWorkspaceById(tenantId, id);
516
+ }
517
+ async deleteWorkspace(tenantId, id) {
518
+ const result = this.db.prepare(
519
+ `DELETE FROM lt_workspaces WHERE tenant_id = ? AND id = ?`
520
+ ).run(tenantId, id);
521
+ return result.changes > 0;
522
+ }
523
+ };
524
+ function mapRowToWorkspace(row) {
525
+ return {
526
+ id: row.id,
527
+ tenantId: row.tenant_id,
528
+ name: row.name,
529
+ description: row.description || void 0,
530
+ storageType: row.storage_type,
531
+ createdAt: parseISO(row.created_at),
532
+ updatedAt: parseISO(row.updated_at)
533
+ };
534
+ }
535
+
536
+ // src/stores/LocalProjectStore.ts
537
+ var DDL4 = `
538
+ CREATE TABLE IF NOT EXISTS lt_projects (
539
+ id TEXT NOT NULL,
540
+ tenant_id TEXT NOT NULL,
541
+ workspace_id TEXT NOT NULL,
542
+ name TEXT NOT NULL,
543
+ description TEXT,
544
+ config TEXT,
545
+ created_at TEXT NOT NULL,
546
+ updated_at TEXT NOT NULL,
547
+ PRIMARY KEY (tenant_id, id)
548
+ );
549
+ CREATE INDEX IF NOT EXISTS idx_lt_projects_workspace ON lt_projects(tenant_id, workspace_id);
550
+ `;
551
+ var LocalProjectStore = class {
552
+ constructor(db) {
553
+ this.db = db;
554
+ ensureTable(db, DDL4);
555
+ }
556
+ async getProjectsByWorkspace(tenantId, workspaceId) {
557
+ const rows = this.db.prepare(
558
+ `SELECT * FROM lt_projects WHERE tenant_id = ? AND workspace_id = ? ORDER BY created_at DESC`
559
+ ).all(tenantId, workspaceId);
560
+ return rows.map(mapRowToProject);
561
+ }
562
+ async getProjectById(tenantId, id) {
563
+ const row = this.db.prepare(
564
+ `SELECT * FROM lt_projects WHERE tenant_id = ? AND id = ?`
565
+ ).get(tenantId, id);
566
+ return row ? mapRowToProject(row) : null;
567
+ }
568
+ async createProject(tenantId, workspaceId, id, data) {
569
+ const now = nowISO();
570
+ this.db.prepare(
571
+ `INSERT INTO lt_projects (id, tenant_id, workspace_id, name, description, config, created_at, updated_at)
572
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
573
+ ON CONFLICT(tenant_id, id) DO UPDATE SET
574
+ workspace_id = excluded.workspace_id,
575
+ name = excluded.name,
576
+ description = excluded.description,
577
+ config = excluded.config,
578
+ updated_at = excluded.updated_at`
579
+ ).run(id, tenantId, workspaceId, data.name, data.description || null, data.config ? JSON.stringify(data.config) : null, now, now);
580
+ return {
581
+ id,
582
+ tenantId,
583
+ workspaceId,
584
+ name: data.name,
585
+ description: data.description,
586
+ config: data.config,
587
+ createdAt: parseISO(now),
588
+ updatedAt: parseISO(now)
589
+ };
590
+ }
591
+ async updateProject(tenantId, id, updates) {
592
+ const existing = await this.getProjectById(tenantId, id);
593
+ if (!existing) return null;
594
+ const setClauses = [];
595
+ const values = [];
596
+ if (updates.name !== void 0) {
597
+ setClauses.push("name = ?");
598
+ values.push(updates.name);
599
+ }
600
+ if (updates.description !== void 0) {
601
+ setClauses.push("description = ?");
602
+ values.push(updates.description || null);
603
+ }
604
+ if (updates.config !== void 0) {
605
+ setClauses.push("config = ?");
606
+ values.push(updates.config ? JSON.stringify(updates.config) : null);
607
+ }
608
+ if (setClauses.length === 0) return existing;
609
+ const now = nowISO();
610
+ setClauses.push("updated_at = ?");
611
+ values.push(now);
612
+ values.push(tenantId, id);
613
+ this.db.prepare(
614
+ `UPDATE lt_projects SET ${setClauses.join(", ")} WHERE tenant_id = ? AND id = ?`
615
+ ).run(...values);
616
+ return this.getProjectById(tenantId, id);
617
+ }
618
+ async deleteProject(tenantId, id) {
619
+ const result = this.db.prepare(
620
+ `DELETE FROM lt_projects WHERE tenant_id = ? AND id = ?`
621
+ ).run(tenantId, id);
622
+ return result.changes > 0;
623
+ }
624
+ };
625
+ function mapRowToProject(row) {
626
+ return {
627
+ id: row.id,
628
+ tenantId: row.tenant_id,
629
+ workspaceId: row.workspace_id,
630
+ name: row.name,
631
+ description: row.description || void 0,
632
+ config: row.config ? JSON.parse(row.config) : void 0,
633
+ createdAt: parseISO(row.created_at),
634
+ updatedAt: parseISO(row.updated_at)
635
+ };
636
+ }
637
+
638
+ // src/stores/LocalUserStore.ts
639
+ var DDL5 = `
640
+ CREATE TABLE IF NOT EXISTS lt_users (
641
+ id TEXT PRIMARY KEY,
642
+ email TEXT NOT NULL,
643
+ name TEXT NOT NULL,
644
+ status TEXT NOT NULL DEFAULT 'pending',
645
+ metadata TEXT DEFAULT '{}',
646
+ created_at TEXT NOT NULL,
647
+ updated_at TEXT NOT NULL
648
+ );
649
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_lt_users_email ON lt_users(email);
650
+ `;
651
+ var LocalUserStore = class {
652
+ constructor(db) {
653
+ this.db = db;
654
+ ensureTable(db, DDL5);
655
+ }
656
+ async getAllUsers() {
657
+ const rows = this.db.prepare(
658
+ `SELECT * FROM lt_users ORDER BY created_at DESC`
659
+ ).all();
660
+ return rows.map(mapRowToUser);
661
+ }
662
+ async getUserById(id) {
663
+ const row = this.db.prepare(
664
+ `SELECT * FROM lt_users WHERE id = ?`
665
+ ).get(id);
666
+ return row ? mapRowToUser(row) : null;
667
+ }
668
+ async getUserByEmail(email) {
669
+ const row = this.db.prepare(
670
+ `SELECT * FROM lt_users WHERE email = ?`
671
+ ).get(email);
672
+ return row ? mapRowToUser(row) : null;
673
+ }
674
+ async createUser(id, data) {
675
+ const now = nowISO();
676
+ const status = data.status || "pending";
677
+ const metadata = JSON.stringify(data.metadata || {});
678
+ this.db.prepare(
679
+ `INSERT INTO lt_users (id, email, name, status, metadata, created_at, updated_at)
680
+ VALUES (?, ?, ?, ?, ?, ?, ?)
681
+ ON CONFLICT(id) DO UPDATE SET
682
+ email = excluded.email,
683
+ name = excluded.name,
684
+ status = excluded.status,
685
+ metadata = excluded.metadata,
686
+ updated_at = excluded.updated_at`
687
+ ).run(id, data.email, data.name, status, metadata, now, now);
688
+ return {
689
+ id,
690
+ email: data.email,
691
+ name: data.name,
692
+ status,
693
+ metadata: data.metadata,
694
+ createdAt: parseISO(now),
695
+ updatedAt: parseISO(now)
696
+ };
697
+ }
698
+ async updateUser(id, updates) {
699
+ const existing = await this.getUserById(id);
700
+ if (!existing) return null;
701
+ const setClauses = [];
702
+ const values = [];
703
+ if (updates.email !== void 0) {
704
+ setClauses.push("email = ?");
705
+ values.push(updates.email);
706
+ }
707
+ if (updates.name !== void 0) {
708
+ setClauses.push("name = ?");
709
+ values.push(updates.name);
710
+ }
711
+ if (updates.status !== void 0) {
712
+ setClauses.push("status = ?");
713
+ values.push(updates.status);
714
+ }
715
+ if (updates.metadata !== void 0) {
716
+ setClauses.push("metadata = ?");
717
+ values.push(JSON.stringify(updates.metadata));
718
+ }
719
+ if (setClauses.length === 0) return existing;
720
+ const now = nowISO();
721
+ setClauses.push("updated_at = ?");
722
+ values.push(now);
723
+ values.push(id);
724
+ this.db.prepare(
725
+ `UPDATE lt_users SET ${setClauses.join(", ")} WHERE id = ?`
726
+ ).run(...values);
727
+ return this.getUserById(id);
728
+ }
729
+ async deleteUser(id) {
730
+ const result = this.db.prepare(`DELETE FROM lt_users WHERE id = ?`).run(id);
731
+ return result.changes > 0;
732
+ }
733
+ };
734
+ function mapRowToUser(row) {
735
+ return {
736
+ id: row.id,
737
+ email: row.email,
738
+ name: row.name,
739
+ status: row.status,
740
+ metadata: JSON.parse(row.metadata || "{}"),
741
+ createdAt: parseISO(row.created_at),
742
+ updatedAt: parseISO(row.updated_at)
743
+ };
744
+ }
745
+
746
+ // src/stores/LocalTenantStore.ts
747
+ var DDL6 = `
748
+ CREATE TABLE IF NOT EXISTS lt_tenants (
749
+ id TEXT PRIMARY KEY,
750
+ name TEXT NOT NULL,
751
+ description TEXT,
752
+ status TEXT NOT NULL DEFAULT 'active',
753
+ metadata TEXT DEFAULT '{}',
754
+ created_at TEXT NOT NULL,
755
+ updated_at TEXT NOT NULL
756
+ );
757
+ `;
758
+ var LocalTenantStore = class {
759
+ constructor(db) {
760
+ this.db = db;
761
+ ensureTable(db, DDL6);
762
+ }
763
+ async getAllTenants() {
764
+ const rows = this.db.prepare(
765
+ `SELECT * FROM lt_tenants ORDER BY created_at DESC`
766
+ ).all();
767
+ return rows.map(mapRowToTenant);
768
+ }
769
+ async getTenantById(id) {
770
+ const row = this.db.prepare(
771
+ `SELECT * FROM lt_tenants WHERE id = ?`
772
+ ).get(id);
773
+ return row ? mapRowToTenant(row) : null;
774
+ }
775
+ async createTenant(id, data) {
776
+ const now = nowISO();
777
+ const status = data.status || "active";
778
+ const metadata = JSON.stringify(data.metadata || {});
779
+ this.db.prepare(
780
+ `INSERT INTO lt_tenants (id, name, description, status, metadata, created_at, updated_at)
781
+ VALUES (?, ?, ?, ?, ?, ?, ?)
782
+ ON CONFLICT(id) DO UPDATE SET
783
+ name = excluded.name,
784
+ description = excluded.description,
785
+ status = excluded.status,
786
+ metadata = excluded.metadata,
787
+ updated_at = excluded.updated_at`
788
+ ).run(id, data.name, data.description || null, status, metadata, now, now);
789
+ return {
790
+ id,
791
+ name: data.name,
792
+ description: data.description,
793
+ status,
794
+ metadata: data.metadata,
795
+ createdAt: parseISO(now),
796
+ updatedAt: parseISO(now)
797
+ };
798
+ }
799
+ async updateTenant(id, updates) {
800
+ const existing = await this.getTenantById(id);
801
+ if (!existing) return null;
802
+ const setClauses = [];
803
+ const values = [];
804
+ if (updates.name !== void 0) {
805
+ setClauses.push("name = ?");
806
+ values.push(updates.name);
807
+ }
808
+ if (updates.description !== void 0) {
809
+ setClauses.push("description = ?");
810
+ values.push(updates.description || null);
811
+ }
812
+ if (updates.status !== void 0) {
813
+ setClauses.push("status = ?");
814
+ values.push(updates.status);
815
+ }
816
+ if (updates.metadata !== void 0) {
817
+ setClauses.push("metadata = ?");
818
+ values.push(JSON.stringify(updates.metadata));
819
+ }
820
+ if (setClauses.length === 0) return existing;
821
+ const now = nowISO();
822
+ setClauses.push("updated_at = ?");
823
+ values.push(now);
824
+ values.push(id);
825
+ this.db.prepare(
826
+ `UPDATE lt_tenants SET ${setClauses.join(", ")} WHERE id = ?`
827
+ ).run(...values);
828
+ return this.getTenantById(id);
829
+ }
830
+ async deleteTenant(id) {
831
+ const result = this.db.prepare(`DELETE FROM lt_tenants WHERE id = ?`).run(id);
832
+ return result.changes > 0;
833
+ }
834
+ };
835
+ function mapRowToTenant(row) {
836
+ return {
837
+ id: row.id,
838
+ name: row.name,
839
+ description: row.description || void 0,
840
+ status: row.status,
841
+ metadata: JSON.parse(row.metadata || "{}"),
842
+ createdAt: parseISO(row.created_at),
843
+ updatedAt: parseISO(row.updated_at)
844
+ };
845
+ }
846
+
847
+ // src/stores/LocalUserTenantLinkStore.ts
848
+ var DDL7 = `
849
+ CREATE TABLE IF NOT EXISTS lt_user_tenant_links (
850
+ user_id TEXT NOT NULL,
851
+ tenant_id TEXT NOT NULL,
852
+ role TEXT NOT NULL DEFAULT 'member',
853
+ joined_at TEXT NOT NULL,
854
+ metadata TEXT DEFAULT '{}',
855
+ PRIMARY KEY (user_id, tenant_id)
856
+ );
857
+ CREATE INDEX IF NOT EXISTS idx_lt_utl_user ON lt_user_tenant_links(user_id);
858
+ CREATE INDEX IF NOT EXISTS idx_lt_utl_tenant ON lt_user_tenant_links(tenant_id);
859
+ `;
860
+ var LocalUserTenantLinkStore = class {
861
+ constructor(db) {
862
+ this.db = db;
863
+ ensureTable(db, DDL7);
864
+ }
865
+ async getTenantsByUser(userId) {
866
+ const rows = this.db.prepare(
867
+ `SELECT * FROM lt_user_tenant_links WHERE user_id = ? ORDER BY joined_at DESC`
868
+ ).all(userId);
869
+ return rows.map(mapRowToLink);
870
+ }
871
+ async getUsersByTenant(tenantId) {
872
+ const rows = this.db.prepare(
873
+ `SELECT * FROM lt_user_tenant_links WHERE tenant_id = ? ORDER BY joined_at DESC`
874
+ ).all(tenantId);
875
+ return rows.map(mapRowToLink);
876
+ }
877
+ async getLink(userId, tenantId) {
878
+ const row = this.db.prepare(
879
+ `SELECT * FROM lt_user_tenant_links WHERE user_id = ? AND tenant_id = ?`
880
+ ).get(userId, tenantId);
881
+ return row ? mapRowToLink(row) : null;
882
+ }
883
+ async createLink(data) {
884
+ const now = nowISO();
885
+ const role = data.role || "member";
886
+ const metadata = JSON.stringify(data.metadata || {});
887
+ this.db.prepare(
888
+ `INSERT INTO lt_user_tenant_links (user_id, tenant_id, role, joined_at, metadata)
889
+ VALUES (?, ?, ?, ?, ?)
890
+ ON CONFLICT(user_id, tenant_id) DO UPDATE SET
891
+ role = excluded.role,
892
+ metadata = excluded.metadata`
893
+ ).run(data.userId, data.tenantId, role, now, metadata);
894
+ return {
895
+ userId: data.userId,
896
+ tenantId: data.tenantId,
897
+ role,
898
+ joinedAt: parseISO(now),
899
+ metadata: data.metadata
900
+ };
901
+ }
902
+ async updateLink(userId, tenantId, updates) {
903
+ const existing = await this.getLink(userId, tenantId);
904
+ if (!existing) return null;
905
+ const setClauses = [];
906
+ const values = [];
907
+ if (updates.role !== void 0) {
908
+ setClauses.push("role = ?");
909
+ values.push(updates.role);
910
+ }
911
+ if (updates.metadata !== void 0) {
912
+ setClauses.push("metadata = ?");
913
+ values.push(JSON.stringify(updates.metadata));
914
+ }
915
+ if (setClauses.length === 0) return existing;
916
+ values.push(userId, tenantId);
917
+ this.db.prepare(
918
+ `UPDATE lt_user_tenant_links SET ${setClauses.join(", ")} WHERE user_id = ? AND tenant_id = ?`
919
+ ).run(...values);
920
+ return this.getLink(userId, tenantId);
921
+ }
922
+ async deleteLink(userId, tenantId) {
923
+ const result = this.db.prepare(
924
+ `DELETE FROM lt_user_tenant_links WHERE user_id = ? AND tenant_id = ?`
925
+ ).run(userId, tenantId);
926
+ return result.changes > 0;
927
+ }
928
+ async hasLink(userId, tenantId) {
929
+ const row = this.db.prepare(
930
+ `SELECT 1 FROM lt_user_tenant_links WHERE user_id = ? AND tenant_id = ? LIMIT 1`
931
+ ).get(userId, tenantId);
932
+ return row !== void 0;
933
+ }
934
+ };
935
+ function mapRowToLink(row) {
936
+ return {
937
+ userId: row.user_id,
938
+ tenantId: row.tenant_id,
939
+ role: row.role,
940
+ joinedAt: parseISO(row.joined_at),
941
+ metadata: JSON.parse(row.metadata || "{}")
942
+ };
943
+ }
944
+
945
+ // src/stores/LocalDatabaseConfigStore.ts
946
+ var import_core = require("@axiom-lattice/core");
947
+ var DDL8 = `
948
+ CREATE TABLE IF NOT EXISTS lt_database_configs (
949
+ id TEXT NOT NULL,
950
+ tenant_id TEXT NOT NULL,
951
+ key TEXT NOT NULL,
952
+ name TEXT,
953
+ description TEXT,
954
+ config TEXT NOT NULL,
955
+ created_at TEXT NOT NULL,
956
+ updated_at TEXT NOT NULL,
957
+ PRIMARY KEY (tenant_id, id)
958
+ );
959
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_lt_dbconfig_key ON lt_database_configs(tenant_id, key);
960
+ `;
961
+ var LocalDatabaseConfigStore = class {
962
+ constructor(db) {
963
+ this.db = db;
964
+ ensureTable(db, DDL8);
965
+ }
966
+ async getAllConfigs(tenantId) {
967
+ const rows = this.db.prepare(
968
+ `SELECT * FROM lt_database_configs WHERE tenant_id = ? ORDER BY created_at DESC`
969
+ ).all(tenantId);
970
+ return rows.map((r) => mapRowToEntry(r));
971
+ }
972
+ async getAllConfigsWithoutTenant() {
973
+ const rows = this.db.prepare(
974
+ `SELECT * FROM lt_database_configs ORDER BY created_at DESC`
975
+ ).all();
976
+ return rows.map((r) => mapRowToEntry(r));
977
+ }
978
+ async getConfigById(tenantId, id) {
979
+ const row = this.db.prepare(
980
+ `SELECT * FROM lt_database_configs WHERE tenant_id = ? AND id = ?`
981
+ ).get(tenantId, id);
982
+ return row ? mapRowToEntry(row) : null;
983
+ }
984
+ async getConfigByKey(tenantId, key) {
985
+ const row = this.db.prepare(
986
+ `SELECT * FROM lt_database_configs WHERE tenant_id = ? AND key = ?`
987
+ ).get(tenantId, key);
988
+ return row ? mapRowToEntry(row) : null;
989
+ }
990
+ async createConfig(tenantId, id, data) {
991
+ const now = nowISO();
992
+ const configWithEncrypted = encryptPasswordInConfig(data.config);
993
+ this.db.prepare(
994
+ `INSERT INTO lt_database_configs (id, tenant_id, key, name, description, config, created_at, updated_at)
995
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
996
+ ON CONFLICT(tenant_id, id) DO UPDATE SET
997
+ key = excluded.key,
998
+ name = excluded.name,
999
+ description = excluded.description,
1000
+ config = excluded.config,
1001
+ updated_at = excluded.updated_at`
1002
+ ).run(id, tenantId, data.key, data.name || null, data.description || null, JSON.stringify(configWithEncrypted), now, now);
1003
+ return {
1004
+ id,
1005
+ tenantId,
1006
+ key: data.key,
1007
+ config: data.config,
1008
+ name: data.name,
1009
+ description: data.description,
1010
+ createdAt: parseISO(now),
1011
+ updatedAt: parseISO(now)
1012
+ };
1013
+ }
1014
+ async updateConfig(tenantId, id, updates) {
1015
+ const existing = await this.getConfigById(tenantId, id);
1016
+ if (!existing) return null;
1017
+ const setClauses = [];
1018
+ const values = [];
1019
+ if (updates.key !== void 0) {
1020
+ setClauses.push("key = ?");
1021
+ values.push(updates.key);
1022
+ }
1023
+ if (updates.name !== void 0) {
1024
+ setClauses.push("name = ?");
1025
+ values.push(updates.name || null);
1026
+ }
1027
+ if (updates.description !== void 0) {
1028
+ setClauses.push("description = ?");
1029
+ values.push(updates.description || null);
1030
+ }
1031
+ if (updates.config !== void 0) {
1032
+ setClauses.push("config = ?");
1033
+ values.push(JSON.stringify(encryptPasswordInConfig(updates.config)));
1034
+ }
1035
+ if (setClauses.length === 0) return existing;
1036
+ const now = nowISO();
1037
+ setClauses.push("updated_at = ?");
1038
+ values.push(now);
1039
+ values.push(tenantId, id);
1040
+ this.db.prepare(
1041
+ `UPDATE lt_database_configs SET ${setClauses.join(", ")} WHERE tenant_id = ? AND id = ?`
1042
+ ).run(...values);
1043
+ return this.getConfigById(tenantId, id);
1044
+ }
1045
+ async deleteConfig(tenantId, id) {
1046
+ const result = this.db.prepare(
1047
+ `DELETE FROM lt_database_configs WHERE tenant_id = ? AND id = ?`
1048
+ ).run(tenantId, id);
1049
+ return result.changes > 0;
1050
+ }
1051
+ async hasConfig(tenantId, id) {
1052
+ const row = this.db.prepare(
1053
+ `SELECT 1 FROM lt_database_configs WHERE tenant_id = ? AND id = ? LIMIT 1`
1054
+ ).get(tenantId, id);
1055
+ return row !== void 0;
1056
+ }
1057
+ };
1058
+ function mapRowToEntry(row) {
1059
+ const config = JSON.parse(row.config);
1060
+ if (config.password) {
1061
+ try {
1062
+ config.password = (0, import_core.decrypt)(config.password);
1063
+ } catch {
1064
+ }
1065
+ }
1066
+ return {
1067
+ id: row.id,
1068
+ tenantId: row.tenant_id,
1069
+ key: row.key,
1070
+ config,
1071
+ name: row.name || void 0,
1072
+ description: row.description || void 0,
1073
+ createdAt: parseISO(row.created_at),
1074
+ updatedAt: parseISO(row.updated_at)
1075
+ };
1076
+ }
1077
+ function encryptPasswordInConfig(config) {
1078
+ if (config.password) {
1079
+ return { ...config, password: (0, import_core.encrypt)(config.password) };
1080
+ }
1081
+ return config;
1082
+ }
1083
+
1084
+ // src/stores/LocalMetricsServerConfigStore.ts
1085
+ var DDL9 = `
1086
+ CREATE TABLE IF NOT EXISTS lt_metrics_configs (
1087
+ id TEXT NOT NULL,
1088
+ tenant_id TEXT NOT NULL,
1089
+ key TEXT NOT NULL,
1090
+ name TEXT,
1091
+ description TEXT,
1092
+ config TEXT NOT NULL,
1093
+ created_at TEXT NOT NULL,
1094
+ updated_at TEXT NOT NULL,
1095
+ PRIMARY KEY (tenant_id, id)
1096
+ );
1097
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_lt_metrics_key ON lt_metrics_configs(tenant_id, key);
1098
+ `;
1099
+ var LocalMetricsServerConfigStore = class {
1100
+ constructor(db) {
1101
+ this.db = db;
1102
+ ensureTable(db, DDL9);
1103
+ }
1104
+ async getAllConfigs(tenantId) {
1105
+ const rows = this.db.prepare(
1106
+ `SELECT * FROM lt_metrics_configs WHERE tenant_id = ? ORDER BY created_at DESC`
1107
+ ).all(tenantId);
1108
+ return rows.map(mapRowToEntry2);
1109
+ }
1110
+ async getAllConfigsWithoutTenant() {
1111
+ const rows = this.db.prepare(
1112
+ `SELECT * FROM lt_metrics_configs ORDER BY created_at DESC`
1113
+ ).all();
1114
+ return rows.map(mapRowToEntry2);
1115
+ }
1116
+ async getConfigById(tenantId, id) {
1117
+ const row = this.db.prepare(
1118
+ `SELECT * FROM lt_metrics_configs WHERE tenant_id = ? AND id = ?`
1119
+ ).get(tenantId, id);
1120
+ return row ? mapRowToEntry2(row) : null;
1121
+ }
1122
+ async getConfigByKey(tenantId, key) {
1123
+ const row = this.db.prepare(
1124
+ `SELECT * FROM lt_metrics_configs WHERE tenant_id = ? AND key = ?`
1125
+ ).get(tenantId, key);
1126
+ return row ? mapRowToEntry2(row) : null;
1127
+ }
1128
+ async createConfig(tenantId, id, data) {
1129
+ const now = nowISO();
1130
+ this.db.prepare(
1131
+ `INSERT INTO lt_metrics_configs (id, tenant_id, key, name, description, config, created_at, updated_at)
1132
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
1133
+ ON CONFLICT(tenant_id, id) DO UPDATE SET
1134
+ key = excluded.key,
1135
+ name = excluded.name,
1136
+ description = excluded.description,
1137
+ config = excluded.config,
1138
+ updated_at = excluded.updated_at`
1139
+ ).run(id, tenantId, data.key, data.name || null, data.description || null, JSON.stringify(data.config), now, now);
1140
+ return {
1141
+ id,
1142
+ tenantId,
1143
+ key: data.key,
1144
+ config: data.config,
1145
+ name: data.name,
1146
+ description: data.description,
1147
+ createdAt: parseISO(now),
1148
+ updatedAt: parseISO(now)
1149
+ };
1150
+ }
1151
+ async updateConfig(tenantId, id, updates) {
1152
+ const existing = await this.getConfigById(tenantId, id);
1153
+ if (!existing) return null;
1154
+ const setClauses = [];
1155
+ const values = [];
1156
+ if (updates.key !== void 0) {
1157
+ setClauses.push("key = ?");
1158
+ values.push(updates.key);
1159
+ }
1160
+ if (updates.name !== void 0) {
1161
+ setClauses.push("name = ?");
1162
+ values.push(updates.name || null);
1163
+ }
1164
+ if (updates.description !== void 0) {
1165
+ setClauses.push("description = ?");
1166
+ values.push(updates.description || null);
1167
+ }
1168
+ if (updates.config !== void 0) {
1169
+ setClauses.push("config = ?");
1170
+ values.push(JSON.stringify(updates.config));
1171
+ }
1172
+ if (setClauses.length === 0) return existing;
1173
+ const now = nowISO();
1174
+ setClauses.push("updated_at = ?");
1175
+ values.push(now);
1176
+ values.push(tenantId, id);
1177
+ this.db.prepare(
1178
+ `UPDATE lt_metrics_configs SET ${setClauses.join(", ")} WHERE tenant_id = ? AND id = ?`
1179
+ ).run(...values);
1180
+ return this.getConfigById(tenantId, id);
1181
+ }
1182
+ async deleteConfig(tenantId, id) {
1183
+ const result = this.db.prepare(
1184
+ `DELETE FROM lt_metrics_configs WHERE tenant_id = ? AND id = ?`
1185
+ ).run(tenantId, id);
1186
+ return result.changes > 0;
1187
+ }
1188
+ async hasConfig(tenantId, id) {
1189
+ const row = this.db.prepare(
1190
+ `SELECT 1 FROM lt_metrics_configs WHERE tenant_id = ? AND id = ? LIMIT 1`
1191
+ ).get(tenantId, id);
1192
+ return row !== void 0;
1193
+ }
1194
+ };
1195
+ function mapRowToEntry2(row) {
1196
+ return {
1197
+ id: row.id,
1198
+ tenantId: row.tenant_id,
1199
+ key: row.key,
1200
+ config: JSON.parse(row.config),
1201
+ name: row.name || void 0,
1202
+ description: row.description || void 0,
1203
+ createdAt: parseISO(row.created_at),
1204
+ updatedAt: parseISO(row.updated_at)
1205
+ };
1206
+ }
1207
+
1208
+ // src/stores/LocalMcpServerConfigStore.ts
1209
+ var import_core2 = require("@axiom-lattice/core");
1210
+ var DDL10 = `
1211
+ CREATE TABLE IF NOT EXISTS lt_mcp_configs (
1212
+ id TEXT NOT NULL,
1213
+ tenant_id TEXT NOT NULL,
1214
+ key TEXT NOT NULL,
1215
+ name TEXT,
1216
+ description TEXT,
1217
+ config TEXT NOT NULL,
1218
+ selected_tools TEXT DEFAULT '[]',
1219
+ is_env_encrypted INTEGER NOT NULL DEFAULT 0,
1220
+ status TEXT NOT NULL DEFAULT 'disconnected',
1221
+ created_at TEXT NOT NULL,
1222
+ updated_at TEXT NOT NULL,
1223
+ PRIMARY KEY (tenant_id, id)
1224
+ );
1225
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_lt_mcp_key ON lt_mcp_configs(tenant_id, key);
1226
+ `;
1227
+ var LocalMcpServerConfigStore = class {
1228
+ constructor(db) {
1229
+ this.db = db;
1230
+ ensureTable(db, DDL10);
1231
+ }
1232
+ async getAllConfigs(tenantId) {
1233
+ const rows = this.db.prepare(
1234
+ `SELECT * FROM lt_mcp_configs WHERE tenant_id = ? ORDER BY created_at DESC`
1235
+ ).all(tenantId);
1236
+ return rows.map(mapRowToEntry3);
1237
+ }
1238
+ async getAllConfigsWithoutTenant() {
1239
+ const rows = this.db.prepare(
1240
+ `SELECT * FROM lt_mcp_configs ORDER BY created_at DESC`
1241
+ ).all();
1242
+ return rows.map(mapRowToEntry3);
1243
+ }
1244
+ async getConfigById(tenantId, id) {
1245
+ const row = this.db.prepare(
1246
+ `SELECT * FROM lt_mcp_configs WHERE tenant_id = ? AND id = ?`
1247
+ ).get(tenantId, id);
1248
+ return row ? mapRowToEntry3(row) : null;
1249
+ }
1250
+ async getConfigByKey(tenantId, key) {
1251
+ const row = this.db.prepare(
1252
+ `SELECT * FROM lt_mcp_configs WHERE tenant_id = ? AND key = ?`
1253
+ ).get(tenantId, key);
1254
+ return row ? mapRowToEntry3(row) : null;
1255
+ }
1256
+ async createConfig(tenantId, id, data) {
1257
+ const now = nowISO();
1258
+ const { config: configWithEncryptedEnv, isEnvEncrypted } = encryptEnvInConfig(data.config);
1259
+ this.db.prepare(
1260
+ `INSERT INTO lt_mcp_configs (id, tenant_id, key, name, description, config, selected_tools, is_env_encrypted, status, created_at, updated_at)
1261
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1262
+ ON CONFLICT(tenant_id, id) DO UPDATE SET
1263
+ key = excluded.key,
1264
+ name = excluded.name,
1265
+ description = excluded.description,
1266
+ config = excluded.config,
1267
+ selected_tools = excluded.selected_tools,
1268
+ is_env_encrypted = excluded.is_env_encrypted,
1269
+ status = excluded.status,
1270
+ updated_at = excluded.updated_at`
1271
+ ).run(
1272
+ id,
1273
+ tenantId,
1274
+ data.key,
1275
+ data.name || null,
1276
+ data.description || null,
1277
+ JSON.stringify(configWithEncryptedEnv),
1278
+ JSON.stringify(data.selectedTools || []),
1279
+ isEnvEncrypted ? 1 : 0,
1280
+ "disconnected",
1281
+ now,
1282
+ now
1283
+ );
1284
+ return {
1285
+ id,
1286
+ tenantId,
1287
+ key: data.key,
1288
+ config: data.config,
1289
+ name: data.name,
1290
+ description: data.description,
1291
+ selectedTools: data.selectedTools || [],
1292
+ isEnvEncrypted,
1293
+ status: "disconnected",
1294
+ createdAt: parseISO(now),
1295
+ updatedAt: parseISO(now)
1296
+ };
1297
+ }
1298
+ async updateConfig(tenantId, id, updates) {
1299
+ const existing = await this.getConfigById(tenantId, id);
1300
+ if (!existing) return null;
1301
+ const setClauses = [];
1302
+ const values = [];
1303
+ if (updates.key !== void 0) {
1304
+ setClauses.push("key = ?");
1305
+ values.push(updates.key);
1306
+ }
1307
+ if (updates.name !== void 0) {
1308
+ setClauses.push("name = ?");
1309
+ values.push(updates.name || null);
1310
+ }
1311
+ if (updates.description !== void 0) {
1312
+ setClauses.push("description = ?");
1313
+ values.push(updates.description || null);
1314
+ }
1315
+ if (updates.config !== void 0) {
1316
+ const { config: configWithEncryptedEnv, isEnvEncrypted } = encryptEnvInConfig(updates.config);
1317
+ setClauses.push("config = ?");
1318
+ values.push(JSON.stringify(configWithEncryptedEnv));
1319
+ setClauses.push("is_env_encrypted = ?");
1320
+ values.push(isEnvEncrypted ? 1 : 0);
1321
+ }
1322
+ if (updates.selectedTools !== void 0) {
1323
+ setClauses.push("selected_tools = ?");
1324
+ values.push(JSON.stringify(updates.selectedTools));
1325
+ }
1326
+ if (updates.status !== void 0) {
1327
+ setClauses.push("status = ?");
1328
+ values.push(updates.status);
1329
+ }
1330
+ if (setClauses.length === 0) return existing;
1331
+ const now = nowISO();
1332
+ setClauses.push("updated_at = ?");
1333
+ values.push(now);
1334
+ values.push(tenantId, id);
1335
+ this.db.prepare(
1336
+ `UPDATE lt_mcp_configs SET ${setClauses.join(", ")} WHERE tenant_id = ? AND id = ?`
1337
+ ).run(...values);
1338
+ return this.getConfigById(tenantId, id);
1339
+ }
1340
+ async deleteConfig(tenantId, id) {
1341
+ const result = this.db.prepare(
1342
+ `DELETE FROM lt_mcp_configs WHERE tenant_id = ? AND id = ?`
1343
+ ).run(tenantId, id);
1344
+ return result.changes > 0;
1345
+ }
1346
+ async hasConfig(tenantId, id) {
1347
+ const row = this.db.prepare(
1348
+ `SELECT 1 FROM lt_mcp_configs WHERE tenant_id = ? AND id = ? LIMIT 1`
1349
+ ).get(tenantId, id);
1350
+ return row !== void 0;
1351
+ }
1352
+ };
1353
+ function mapRowToEntry3(row) {
1354
+ const config = JSON.parse(row.config);
1355
+ if (config.env && row.is_env_encrypted) {
1356
+ try {
1357
+ const decryptedEnv = {};
1358
+ for (const [key, value] of Object.entries(config.env)) {
1359
+ decryptedEnv[key] = (0, import_core2.decrypt)(value);
1360
+ }
1361
+ config.env = decryptedEnv;
1362
+ } catch (error) {
1363
+ console.error("Failed to decrypt MCP server env:", error);
1364
+ throw new Error("Failed to decrypt MCP server configuration");
1365
+ }
1366
+ }
1367
+ return {
1368
+ id: row.id,
1369
+ tenantId: row.tenant_id,
1370
+ key: row.key,
1371
+ config,
1372
+ name: row.name || void 0,
1373
+ description: row.description || void 0,
1374
+ selectedTools: JSON.parse(row.selected_tools || "[]"),
1375
+ isEnvEncrypted: row.is_env_encrypted === 1,
1376
+ status: row.status,
1377
+ createdAt: parseISO(row.created_at),
1378
+ updatedAt: parseISO(row.updated_at)
1379
+ };
1380
+ }
1381
+ function encryptEnvInConfig(config) {
1382
+ const configCopy = { ...config };
1383
+ let isEnvEncrypted = false;
1384
+ if (configCopy.env && Object.keys(configCopy.env).length > 0) {
1385
+ const encryptedEnv = {};
1386
+ for (const [key, value] of Object.entries(configCopy.env)) {
1387
+ encryptedEnv[key] = (0, import_core2.encrypt)(value);
1388
+ }
1389
+ configCopy.env = encryptedEnv;
1390
+ isEnvEncrypted = true;
1391
+ }
1392
+ return { config: configCopy, isEnvEncrypted };
1393
+ }
1394
+
1395
+ // src/stores/LocalWorkflowTrackingStore.ts
1396
+ var DDL11 = `
1397
+ CREATE TABLE IF NOT EXISTS lt_workflow_runs (
1398
+ id TEXT PRIMARY KEY,
1399
+ tenant_id TEXT NOT NULL,
1400
+ assistant_id TEXT NOT NULL,
1401
+ thread_id TEXT NOT NULL,
1402
+ status TEXT NOT NULL DEFAULT 'running',
1403
+ topology_edges TEXT NOT NULL DEFAULT '[]',
1404
+ total_edges INTEGER NOT NULL DEFAULT 0,
1405
+ completed_edges INTEGER NOT NULL DEFAULT 0,
1406
+ error_message TEXT,
1407
+ metadata TEXT DEFAULT '{}',
1408
+ started_at TEXT NOT NULL,
1409
+ completed_at TEXT,
1410
+ created_at TEXT NOT NULL,
1411
+ updated_at TEXT NOT NULL
1412
+ );
1413
+ CREATE INDEX IF NOT EXISTS idx_lt_wr_thread ON lt_workflow_runs(tenant_id, thread_id);
1414
+ CREATE INDEX IF NOT EXISTS idx_lt_wr_assistant ON lt_workflow_runs(tenant_id, assistant_id);
1415
+
1416
+ CREATE TABLE IF NOT EXISTS lt_workflow_steps (
1417
+ id TEXT NOT NULL,
1418
+ run_id TEXT NOT NULL,
1419
+ tenant_id TEXT NOT NULL,
1420
+ step_type TEXT NOT NULL,
1421
+ step_name TEXT NOT NULL,
1422
+ edge_from TEXT,
1423
+ edge_to TEXT,
1424
+ edge_purpose TEXT,
1425
+ input TEXT,
1426
+ output TEXT,
1427
+ status TEXT NOT NULL DEFAULT 'running',
1428
+ error_message TEXT,
1429
+ started_at TEXT NOT NULL,
1430
+ completed_at TEXT,
1431
+ duration_ms INTEGER,
1432
+ created_at TEXT NOT NULL,
1433
+ updated_at TEXT NOT NULL,
1434
+ PRIMARY KEY (run_id, id)
1435
+ );
1436
+ CREATE INDEX IF NOT EXISTS idx_lt_ws_type ON lt_workflow_steps(run_id, step_type);
1437
+ `;
1438
+ var LocalWorkflowTrackingStore = class {
1439
+ constructor(db) {
1440
+ this.db = db;
1441
+ ensureTable(db, DDL11);
1442
+ }
1443
+ async createWorkflowRun(request) {
1444
+ const now = nowISO();
1445
+ const id = `${request.threadId}_${Date.now()}`;
1446
+ this.db.prepare(
1447
+ `INSERT INTO lt_workflow_runs (id, tenant_id, assistant_id, thread_id, status, topology_edges, total_edges, completed_edges, metadata, started_at, created_at, updated_at)
1448
+ VALUES (?, ?, ?, ?, 'running', ?, ?, 0, ?, ?, ?, ?)`
1449
+ ).run(
1450
+ id,
1451
+ request.tenantId,
1452
+ request.assistantId,
1453
+ request.threadId,
1454
+ JSON.stringify(request.topologyEdges),
1455
+ request.topologyEdges.length,
1456
+ JSON.stringify(request.metadata || {}),
1457
+ now,
1458
+ now,
1459
+ now
1460
+ );
1461
+ return {
1462
+ id,
1463
+ tenantId: request.tenantId,
1464
+ assistantId: request.assistantId,
1465
+ threadId: request.threadId,
1466
+ status: "running",
1467
+ topologyEdges: request.topologyEdges,
1468
+ totalEdges: request.topologyEdges.length,
1469
+ completedEdges: 0,
1470
+ metadata: request.metadata,
1471
+ startedAt: parseISO(now),
1472
+ completedAt: void 0,
1473
+ createdAt: parseISO(now),
1474
+ updatedAt: parseISO(now)
1475
+ };
1476
+ }
1477
+ async getWorkflowRun(runId) {
1478
+ const row = this.db.prepare(`SELECT * FROM lt_workflow_runs WHERE id = ?`).get(runId);
1479
+ return row ? mapRowToRun(row) : null;
1480
+ }
1481
+ async updateWorkflowRun(runId, updates) {
1482
+ const existing = await this.getWorkflowRun(runId);
1483
+ if (!existing) return null;
1484
+ const setClauses = [];
1485
+ const values = [];
1486
+ if (updates.status !== void 0) {
1487
+ setClauses.push("status = ?");
1488
+ values.push(updates.status);
1489
+ }
1490
+ if (updates.completedEdges !== void 0) {
1491
+ setClauses.push("completed_edges = ?");
1492
+ values.push(updates.completedEdges);
1493
+ }
1494
+ if (updates.errorMessage !== void 0) {
1495
+ setClauses.push("error_message = ?");
1496
+ values.push(updates.errorMessage);
1497
+ }
1498
+ if (updates.completedAt !== void 0) {
1499
+ setClauses.push("completed_at = ?");
1500
+ values.push(updates.completedAt ? updates.completedAt.toISOString() : null);
1501
+ }
1502
+ if (updates.metadata !== void 0) {
1503
+ setClauses.push("metadata = ?");
1504
+ values.push(JSON.stringify(updates.metadata));
1505
+ }
1506
+ if (setClauses.length === 0) return existing;
1507
+ const now = nowISO();
1508
+ setClauses.push("updated_at = ?");
1509
+ values.push(now);
1510
+ values.push(runId);
1511
+ this.db.prepare(
1512
+ `UPDATE lt_workflow_runs SET ${setClauses.join(", ")} WHERE id = ?`
1513
+ ).run(...values);
1514
+ return this.getWorkflowRun(runId);
1515
+ }
1516
+ async deleteWorkflowRun(runId) {
1517
+ this.db.prepare(`DELETE FROM lt_workflow_runs WHERE id = ?`).run(runId);
1518
+ }
1519
+ async getWorkflowRunsByThreadId(tenantId, threadId) {
1520
+ const rows = this.db.prepare(
1521
+ `SELECT * FROM lt_workflow_runs WHERE tenant_id = ? AND thread_id = ? ORDER BY created_at DESC`
1522
+ ).all(tenantId, threadId);
1523
+ return rows.map(mapRowToRun);
1524
+ }
1525
+ async getWorkflowRunsByAssistantId(tenantId, assistantId) {
1526
+ const rows = this.db.prepare(
1527
+ `SELECT * FROM lt_workflow_runs WHERE tenant_id = ? AND assistant_id = ? ORDER BY created_at DESC`
1528
+ ).all(tenantId, assistantId);
1529
+ return rows.map(mapRowToRun);
1530
+ }
1531
+ async getWorkflowRunsByTenantId(tenantId) {
1532
+ const rows = this.db.prepare(
1533
+ `SELECT * FROM lt_workflow_runs WHERE tenant_id = ? ORDER BY created_at DESC`
1534
+ ).all(tenantId);
1535
+ return rows.map(mapRowToRun);
1536
+ }
1537
+ async createRunStep(request) {
1538
+ const now = nowISO();
1539
+ const id = `step_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
1540
+ this.db.prepare(
1541
+ `INSERT INTO lt_workflow_steps (id, run_id, tenant_id, step_type, step_name, edge_from, edge_to, edge_purpose, input, status, started_at, created_at, updated_at)
1542
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'running', ?, ?, ?)`
1543
+ ).run(
1544
+ id,
1545
+ request.runId,
1546
+ request.tenantId,
1547
+ request.stepType,
1548
+ request.stepName,
1549
+ request.edgeFrom || null,
1550
+ request.edgeTo || null,
1551
+ request.edgePurpose || null,
1552
+ request.input ? JSON.stringify(request.input) : null,
1553
+ now,
1554
+ now,
1555
+ now
1556
+ );
1557
+ return {
1558
+ id,
1559
+ runId: request.runId,
1560
+ tenantId: request.tenantId,
1561
+ stepType: request.stepType,
1562
+ stepName: request.stepName,
1563
+ edgeFrom: request.edgeFrom,
1564
+ edgeTo: request.edgeTo,
1565
+ edgePurpose: request.edgePurpose,
1566
+ input: request.input,
1567
+ status: "running",
1568
+ startedAt: parseISO(now),
1569
+ createdAt: parseISO(now),
1570
+ updatedAt: parseISO(now)
1571
+ };
1572
+ }
1573
+ async updateRunStep(runId, stepId, updates) {
1574
+ const setClauses = [];
1575
+ const values = [];
1576
+ if (updates.status !== void 0) {
1577
+ setClauses.push("status = ?");
1578
+ values.push(updates.status);
1579
+ }
1580
+ if (updates.output !== void 0) {
1581
+ setClauses.push("output = ?");
1582
+ values.push(JSON.stringify(updates.output));
1583
+ }
1584
+ if (updates.errorMessage !== void 0) {
1585
+ setClauses.push("error_message = ?");
1586
+ values.push(updates.errorMessage);
1587
+ }
1588
+ if (updates.completedAt !== void 0) {
1589
+ setClauses.push("completed_at = ?");
1590
+ values.push(updates.completedAt ? updates.completedAt.toISOString() : null);
1591
+ }
1592
+ if (updates.durationMs !== void 0) {
1593
+ setClauses.push("duration_ms = ?");
1594
+ values.push(updates.durationMs);
1595
+ }
1596
+ if (setClauses.length === 0) {
1597
+ return this.getStepById(runId, stepId);
1598
+ }
1599
+ const now = nowISO();
1600
+ setClauses.push("updated_at = ?");
1601
+ values.push(now);
1602
+ values.push(runId, stepId);
1603
+ this.db.prepare(
1604
+ `UPDATE lt_workflow_steps SET ${setClauses.join(", ")} WHERE run_id = ? AND id = ?`
1605
+ ).run(...values);
1606
+ return this.getStepById(runId, stepId);
1607
+ }
1608
+ async getRunSteps(runId) {
1609
+ const rows = this.db.prepare(
1610
+ `SELECT * FROM lt_workflow_steps WHERE run_id = ? ORDER BY created_at ASC`
1611
+ ).all(runId);
1612
+ return rows.map(mapRowToStep);
1613
+ }
1614
+ async getRunStepsByType(runId, stepType) {
1615
+ const rows = this.db.prepare(
1616
+ `SELECT * FROM lt_workflow_steps WHERE run_id = ? AND step_type = ? ORDER BY created_at ASC`
1617
+ ).all(runId, stepType);
1618
+ return rows.map(mapRowToStep);
1619
+ }
1620
+ async getInterruptedSteps(runId) {
1621
+ const rows = this.db.prepare(
1622
+ `SELECT * FROM lt_workflow_steps WHERE run_id = ? AND status = 'interrupted' ORDER BY created_at ASC`
1623
+ ).all(runId);
1624
+ return rows.map(mapRowToStep);
1625
+ }
1626
+ getStepById(runId, id) {
1627
+ const row = this.db.prepare(
1628
+ `SELECT * FROM lt_workflow_steps WHERE run_id = ? AND id = ?`
1629
+ ).get(runId, id);
1630
+ return row ? mapRowToStep(row) : null;
1631
+ }
1632
+ };
1633
+ function mapRowToRun(row) {
1634
+ return {
1635
+ id: row.id,
1636
+ tenantId: row.tenant_id,
1637
+ assistantId: row.assistant_id,
1638
+ threadId: row.thread_id,
1639
+ status: row.status,
1640
+ topologyEdges: JSON.parse(row.topology_edges || "[]"),
1641
+ totalEdges: row.total_edges,
1642
+ completedEdges: row.completed_edges,
1643
+ errorMessage: row.error_message || void 0,
1644
+ metadata: JSON.parse(row.metadata || "{}"),
1645
+ startedAt: parseISO(row.started_at),
1646
+ completedAt: row.completed_at ? parseISO(row.completed_at) : void 0,
1647
+ createdAt: parseISO(row.created_at),
1648
+ updatedAt: parseISO(row.updated_at)
1649
+ };
1650
+ }
1651
+ function mapRowToStep(row) {
1652
+ return {
1653
+ id: row.id,
1654
+ runId: row.run_id,
1655
+ tenantId: row.tenant_id,
1656
+ stepType: row.step_type,
1657
+ stepName: row.step_name,
1658
+ edgeFrom: row.edge_from || void 0,
1659
+ edgeTo: row.edge_to || void 0,
1660
+ edgePurpose: row.edge_purpose || void 0,
1661
+ input: row.input ? JSON.parse(row.input) : void 0,
1662
+ output: row.output ? JSON.parse(row.output) : void 0,
1663
+ status: row.status,
1664
+ errorMessage: row.error_message || void 0,
1665
+ startedAt: parseISO(row.started_at),
1666
+ completedAt: row.completed_at ? parseISO(row.completed_at) : void 0,
1667
+ durationMs: row.duration_ms ?? void 0,
1668
+ createdAt: parseISO(row.created_at),
1669
+ updatedAt: parseISO(row.updated_at)
1670
+ };
1671
+ }
1672
+
1673
+ // src/stores/LocalEvalStore.ts
1674
+ var import_crypto = require("crypto");
1675
+ var DDL12 = `
1676
+ CREATE TABLE IF NOT EXISTS lt_eval_projects (
1677
+ id TEXT NOT NULL,
1678
+ tenant_id TEXT NOT NULL,
1679
+ name TEXT NOT NULL,
1680
+ description TEXT,
1681
+ version TEXT,
1682
+ judge_model_config TEXT NOT NULL DEFAULT '{}',
1683
+ target_server_config TEXT NOT NULL DEFAULT '{}',
1684
+ concurrency INTEGER NOT NULL DEFAULT 3,
1685
+ report_config TEXT,
1686
+ created_at TEXT NOT NULL,
1687
+ updated_at TEXT NOT NULL,
1688
+ PRIMARY KEY (tenant_id, id)
1689
+ );
1690
+
1691
+ CREATE TABLE IF NOT EXISTS lt_eval_suites (
1692
+ id TEXT NOT NULL,
1693
+ tenant_id TEXT NOT NULL,
1694
+ project_id TEXT NOT NULL,
1695
+ name TEXT NOT NULL,
1696
+ created_at TEXT NOT NULL,
1697
+ updated_at TEXT NOT NULL,
1698
+ PRIMARY KEY (tenant_id, id)
1699
+ );
1700
+ CREATE INDEX IF NOT EXISTS idx_lt_es_project ON lt_eval_suites(tenant_id, project_id);
1701
+
1702
+ CREATE TABLE IF NOT EXISTS lt_eval_cases (
1703
+ id TEXT NOT NULL,
1704
+ tenant_id TEXT NOT NULL,
1705
+ suite_id TEXT NOT NULL,
1706
+ input_message TEXT NOT NULL,
1707
+ input_files TEXT,
1708
+ steps TEXT NOT NULL DEFAULT '[]',
1709
+ output_type TEXT NOT NULL DEFAULT 'message_content',
1710
+ content_assertion TEXT NOT NULL DEFAULT '',
1711
+ rubrics TEXT,
1712
+ created_at TEXT NOT NULL,
1713
+ updated_at TEXT NOT NULL,
1714
+ PRIMARY KEY (tenant_id, id)
1715
+ );
1716
+ CREATE INDEX IF NOT EXISTS idx_lt_ec_suite ON lt_eval_cases(tenant_id, suite_id);
1717
+
1718
+ CREATE TABLE IF NOT EXISTS lt_eval_runs (
1719
+ id TEXT NOT NULL,
1720
+ project_id TEXT NOT NULL,
1721
+ tenant_id TEXT NOT NULL,
1722
+ status TEXT NOT NULL DEFAULT 'running',
1723
+ concurrency INTEGER NOT NULL DEFAULT 3,
1724
+ total_cases INTEGER NOT NULL DEFAULT 0,
1725
+ passed_cases INTEGER NOT NULL DEFAULT 0,
1726
+ failed_cases INTEGER NOT NULL DEFAULT 0,
1727
+ avg_score REAL NOT NULL DEFAULT 0,
1728
+ error TEXT,
1729
+ created_at TEXT NOT NULL,
1730
+ started_at TEXT,
1731
+ completed_at TEXT,
1732
+ PRIMARY KEY (tenant_id, id)
1733
+ );
1734
+ CREATE INDEX IF NOT EXISTS idx_lt_er_project ON lt_eval_runs(tenant_id, project_id);
1735
+
1736
+ CREATE TABLE IF NOT EXISTS lt_eval_run_results (
1737
+ id TEXT NOT NULL,
1738
+ run_id TEXT NOT NULL,
1739
+ suite_name TEXT NOT NULL,
1740
+ case_id TEXT,
1741
+ pass INTEGER NOT NULL DEFAULT 0,
1742
+ score REAL NOT NULL DEFAULT 0,
1743
+ summary TEXT,
1744
+ dimension_results TEXT DEFAULT '[]',
1745
+ duration_ms INTEGER,
1746
+ messages TEXT DEFAULT '[]',
1747
+ logs TEXT DEFAULT '[]',
1748
+ error TEXT,
1749
+ created_at TEXT NOT NULL,
1750
+ PRIMARY KEY (run_id, id)
1751
+ );
1752
+ `;
1753
+ function parseJson(val, fallback) {
1754
+ if (val == null) return fallback;
1755
+ if (typeof val === "string") {
1756
+ try {
1757
+ return JSON.parse(val);
1758
+ } catch {
1759
+ return fallback;
1760
+ }
1761
+ }
1762
+ return val;
1763
+ }
1764
+ function parseOptionalJson(val) {
1765
+ if (val == null) return void 0;
1766
+ if (typeof val === "string") {
1767
+ try {
1768
+ return JSON.parse(val);
1769
+ } catch {
1770
+ return void 0;
1771
+ }
1772
+ }
1773
+ return val;
1774
+ }
1775
+ var LocalEvalStore = class {
1776
+ constructor(db) {
1777
+ this.db = db;
1778
+ ensureTable(db, DDL12);
1779
+ }
1780
+ // -------------------------------------------------------------------------
1781
+ // Projects
1782
+ // -------------------------------------------------------------------------
1783
+ async getProjectsByTenant(tenantId) {
1784
+ const rows = this.db.prepare(
1785
+ `SELECT * FROM lt_eval_projects WHERE tenant_id = ? ORDER BY created_at DESC`
1786
+ ).all(tenantId);
1787
+ return rows.map(this.mapRowToProject);
1788
+ }
1789
+ async getProjectById(tenantId, id) {
1790
+ const row = this.db.prepare(
1791
+ `SELECT * FROM lt_eval_projects WHERE tenant_id = ? AND id = ?`
1792
+ ).get(tenantId, id);
1793
+ return row ? this.mapRowToProject(row) : null;
1794
+ }
1795
+ async createProject(tenantId, id, data) {
1796
+ const actualId = id || (0, import_crypto.randomUUID)();
1797
+ this.db.prepare(
1798
+ `INSERT INTO lt_eval_projects (id, tenant_id, name, description, version, judge_model_config, target_server_config, concurrency, report_config, created_at, updated_at)
1799
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
1800
+ ).run(
1801
+ actualId,
1802
+ tenantId,
1803
+ data.name,
1804
+ data.description || null,
1805
+ data.version || null,
1806
+ JSON.stringify(data.judgeModelConfig),
1807
+ JSON.stringify(data.targetServerConfig),
1808
+ data.concurrency ?? 3,
1809
+ data.reportConfig === void 0 ? null : JSON.stringify(data.reportConfig),
1810
+ nowISO(),
1811
+ nowISO()
1812
+ );
1813
+ return await this.getProjectById(tenantId, actualId);
1814
+ }
1815
+ async updateProject(tenantId, id, updates) {
1816
+ const existing = await this.getProjectById(tenantId, id);
1817
+ if (!existing) return null;
1818
+ const set = [];
1819
+ const vals = [];
1820
+ if (updates.name !== void 0) {
1821
+ set.push("name = ?");
1822
+ vals.push(updates.name);
1823
+ }
1824
+ if (updates.description !== void 0) {
1825
+ set.push("description = ?");
1826
+ vals.push(updates.description || null);
1827
+ }
1828
+ if (updates.version !== void 0) {
1829
+ set.push("version = ?");
1830
+ vals.push(updates.version || null);
1831
+ }
1832
+ if (updates.judgeModelConfig !== void 0) {
1833
+ set.push("judge_model_config = ?");
1834
+ vals.push(JSON.stringify(updates.judgeModelConfig));
1835
+ }
1836
+ if (updates.targetServerConfig !== void 0) {
1837
+ set.push("target_server_config = ?");
1838
+ vals.push(JSON.stringify(updates.targetServerConfig));
1839
+ }
1840
+ if (updates.concurrency !== void 0) {
1841
+ set.push("concurrency = ?");
1842
+ vals.push(updates.concurrency);
1843
+ }
1844
+ if (updates.reportConfig !== void 0) {
1845
+ set.push("report_config = ?");
1846
+ vals.push(JSON.stringify(updates.reportConfig));
1847
+ }
1848
+ set.push("updated_at = ?");
1849
+ vals.push(nowISO());
1850
+ vals.push(tenantId, id);
1851
+ this.db.prepare(
1852
+ `UPDATE lt_eval_projects SET ${set.join(", ")} WHERE tenant_id = ? AND id = ?`
1853
+ ).run(...vals);
1854
+ return this.getProjectById(tenantId, id);
1855
+ }
1856
+ async deleteProject(tenantId, id) {
1857
+ const result = this.db.prepare(`DELETE FROM lt_eval_projects WHERE tenant_id = ? AND id = ?`).run(tenantId, id);
1858
+ return result.changes > 0;
1859
+ }
1860
+ // -------------------------------------------------------------------------
1861
+ // Suites
1862
+ // -------------------------------------------------------------------------
1863
+ async getSuitesByProject(tenantId, projectId) {
1864
+ const rows = this.db.prepare(
1865
+ `SELECT s.*, (SELECT COUNT(*) FROM lt_eval_cases c WHERE c.suite_id = s.id AND c.tenant_id = s.tenant_id) as case_count
1866
+ FROM lt_eval_suites s WHERE s.tenant_id = ? AND s.project_id = ? ORDER BY s.created_at DESC`
1867
+ ).all(tenantId, projectId);
1868
+ return rows.map(this.mapRowToSuite);
1869
+ }
1870
+ async getSuiteById(tenantId, id) {
1871
+ const row = this.db.prepare(
1872
+ `SELECT s.*, (SELECT COUNT(*) FROM lt_eval_cases c WHERE c.suite_id = s.id AND c.tenant_id = s.tenant_id) as case_count
1873
+ FROM lt_eval_suites s WHERE s.tenant_id = ? AND s.id = ?`
1874
+ ).get(tenantId, id);
1875
+ return row ? this.mapRowToSuite(row) : null;
1876
+ }
1877
+ async createSuite(tenantId, projectId, id, data) {
1878
+ const actualId = id || (0, import_crypto.randomUUID)();
1879
+ this.db.prepare(
1880
+ `INSERT INTO lt_eval_suites (id, tenant_id, project_id, name, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)`
1881
+ ).run(actualId, tenantId, projectId, data.name, nowISO(), nowISO());
1882
+ return await this.getSuiteById(tenantId, actualId);
1883
+ }
1884
+ async updateSuite(tenantId, id, updates) {
1885
+ const existing = await this.getSuiteById(tenantId, id);
1886
+ if (!existing) return null;
1887
+ const set = [];
1888
+ const vals = [];
1889
+ if (updates.name !== void 0) {
1890
+ set.push("name = ?");
1891
+ vals.push(updates.name);
1892
+ }
1893
+ set.push("updated_at = ?");
1894
+ vals.push(nowISO());
1895
+ vals.push(tenantId, id);
1896
+ this.db.prepare(
1897
+ `UPDATE lt_eval_suites SET ${set.join(", ")} WHERE tenant_id = ? AND id = ?`
1898
+ ).run(...vals);
1899
+ return this.getSuiteById(tenantId, id);
1900
+ }
1901
+ async deleteSuite(tenantId, id) {
1902
+ const result = this.db.prepare(`DELETE FROM lt_eval_suites WHERE tenant_id = ? AND id = ?`).run(tenantId, id);
1903
+ return result.changes > 0;
1904
+ }
1905
+ // -------------------------------------------------------------------------
1906
+ // Cases
1907
+ // -------------------------------------------------------------------------
1908
+ async getCasesBySuite(tenantId, suiteId) {
1909
+ const rows = this.db.prepare(
1910
+ `SELECT * FROM lt_eval_cases WHERE tenant_id = ? AND suite_id = ? ORDER BY created_at DESC`
1911
+ ).all(tenantId, suiteId);
1912
+ return rows.map(this.mapRowToCase);
1913
+ }
1914
+ async getCaseById(tenantId, id) {
1915
+ const row = this.db.prepare(
1916
+ `SELECT * FROM lt_eval_cases WHERE tenant_id = ? AND id = ?`
1917
+ ).get(tenantId, id);
1918
+ return row ? this.mapRowToCase(row) : null;
1919
+ }
1920
+ async createCase(tenantId, suiteId, id, data) {
1921
+ const actualId = id || (0, import_crypto.randomUUID)();
1922
+ this.db.prepare(
1923
+ `INSERT INTO lt_eval_cases (id, tenant_id, suite_id, input_message, input_files, steps, output_type, content_assertion, rubrics, created_at, updated_at)
1924
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
1925
+ ).run(
1926
+ actualId,
1927
+ tenantId,
1928
+ suiteId,
1929
+ data.inputMessage,
1930
+ data.inputFiles ? JSON.stringify(data.inputFiles) : null,
1931
+ JSON.stringify(data.steps),
1932
+ data.outputType || "message_content",
1933
+ data.contentAssertion || "",
1934
+ data.rubrics ? JSON.stringify(data.rubrics) : null,
1935
+ nowISO(),
1936
+ nowISO()
1937
+ );
1938
+ return await this.getCaseById(tenantId, actualId);
1939
+ }
1940
+ async updateCase(tenantId, id, updates) {
1941
+ const existing = await this.getCaseById(tenantId, id);
1942
+ if (!existing) return null;
1943
+ const set = [];
1944
+ const vals = [];
1945
+ if (updates.inputMessage !== void 0) {
1946
+ set.push("input_message = ?");
1947
+ vals.push(updates.inputMessage);
1948
+ }
1949
+ if (updates.inputFiles !== void 0) {
1950
+ set.push("input_files = ?");
1951
+ vals.push(JSON.stringify(updates.inputFiles));
1952
+ }
1953
+ if (updates.steps !== void 0) {
1954
+ set.push("steps = ?");
1955
+ vals.push(JSON.stringify(updates.steps));
1956
+ }
1957
+ if (updates.outputType !== void 0) {
1958
+ set.push("output_type = ?");
1959
+ vals.push(updates.outputType);
1960
+ }
1961
+ if (updates.contentAssertion !== void 0) {
1962
+ set.push("content_assertion = ?");
1963
+ vals.push(updates.contentAssertion);
1964
+ }
1965
+ if (updates.rubrics !== void 0) {
1966
+ set.push("rubrics = ?");
1967
+ vals.push(JSON.stringify(updates.rubrics));
1968
+ }
1969
+ set.push("updated_at = ?");
1970
+ vals.push(nowISO());
1971
+ vals.push(tenantId, id);
1972
+ this.db.prepare(
1973
+ `UPDATE lt_eval_cases SET ${set.join(", ")} WHERE tenant_id = ? AND id = ?`
1974
+ ).run(...vals);
1975
+ return this.getCaseById(tenantId, id);
1976
+ }
1977
+ async deleteCase(tenantId, id) {
1978
+ const result = this.db.prepare(`DELETE FROM lt_eval_cases WHERE tenant_id = ? AND id = ?`).run(tenantId, id);
1979
+ return result.changes > 0;
1980
+ }
1981
+ // -------------------------------------------------------------------------
1982
+ // Runs
1983
+ // -------------------------------------------------------------------------
1984
+ async getRunsByTenant(tenantId, opts) {
1985
+ let query = `SELECT * FROM lt_eval_runs WHERE tenant_id = ?`;
1986
+ const vals = [tenantId];
1987
+ if (opts?.projectId) {
1988
+ query += ` AND project_id = ?`;
1989
+ vals.push(opts.projectId);
1990
+ }
1991
+ if (opts?.status) {
1992
+ query += ` AND status = ?`;
1993
+ vals.push(opts.status);
1994
+ }
1995
+ query += ` ORDER BY created_at DESC`;
1996
+ const rows = this.db.prepare(query).all(...vals);
1997
+ return rows.map(this.mapRowToRun);
1998
+ }
1999
+ async getRunById(tenantId, id) {
2000
+ const row = this.db.prepare(
2001
+ `SELECT * FROM lt_eval_runs WHERE tenant_id = ? AND id = ?`
2002
+ ).get(tenantId, id);
2003
+ return row ? this.mapRowToRun(row) : null;
2004
+ }
2005
+ async createRun(tenantId, projectId, id, data) {
2006
+ const actualId = id || (0, import_crypto.randomUUID)();
2007
+ this.db.prepare(
2008
+ `INSERT INTO lt_eval_runs (id, project_id, tenant_id, status, concurrency, total_cases, passed_cases, failed_cases, avg_score, created_at)
2009
+ VALUES (?, ?, ?, 'running', ?, ?, 0, 0, 0, ?)`
2010
+ ).run(actualId, projectId, tenantId, data.concurrency, data.totalCases, nowISO());
2011
+ return await this.getRunById(tenantId, actualId);
2012
+ }
2013
+ async updateRunStatus(tenantId, id, updates) {
2014
+ const existing = await this.getRunById(tenantId, id);
2015
+ if (!existing) return null;
2016
+ const set = [];
2017
+ const vals = [];
2018
+ if (updates.status !== void 0) {
2019
+ set.push("status = ?");
2020
+ vals.push(updates.status);
2021
+ }
2022
+ if (updates.passedCases !== void 0) {
2023
+ set.push("passed_cases = ?");
2024
+ vals.push(updates.passedCases);
2025
+ }
2026
+ if (updates.failedCases !== void 0) {
2027
+ set.push("failed_cases = ?");
2028
+ vals.push(updates.failedCases);
2029
+ }
2030
+ if (updates.avgScore !== void 0) {
2031
+ set.push("avg_score = ?");
2032
+ vals.push(updates.avgScore);
2033
+ }
2034
+ if (updates.error !== void 0) {
2035
+ set.push("error = ?");
2036
+ vals.push(updates.error || null);
2037
+ }
2038
+ if (updates.completedAt !== void 0) {
2039
+ set.push("completed_at = ?");
2040
+ vals.push(updates.completedAt ? updates.completedAt.toISOString() : null);
2041
+ }
2042
+ vals.push(tenantId, id);
2043
+ this.db.prepare(
2044
+ `UPDATE lt_eval_runs SET ${set.join(", ")} WHERE tenant_id = ? AND id = ?`
2045
+ ).run(...vals);
2046
+ return this.getRunById(tenantId, id);
2047
+ }
2048
+ async deleteRun(tenantId, id) {
2049
+ const result = this.db.prepare(`DELETE FROM lt_eval_runs WHERE tenant_id = ? AND id = ?`).run(tenantId, id);
2050
+ return result.changes > 0;
2051
+ }
2052
+ // -------------------------------------------------------------------------
2053
+ // Run Results
2054
+ // -------------------------------------------------------------------------
2055
+ async getResultsByRun(tenantId, runId) {
2056
+ const rows = this.db.prepare(
2057
+ `SELECT rr.* FROM lt_eval_run_results rr
2058
+ INNER JOIN lt_eval_runs r ON r.id = rr.run_id
2059
+ WHERE r.tenant_id = ? AND rr.run_id = ? ORDER BY rr.created_at ASC`
2060
+ ).all(tenantId, runId);
2061
+ return rows.map(this.mapRowToRunResult);
2062
+ }
2063
+ async getRunResultById(tenantId, id) {
2064
+ const row = this.db.prepare(
2065
+ `SELECT rr.* FROM lt_eval_run_results rr
2066
+ INNER JOIN lt_eval_runs r ON r.id = rr.run_id
2067
+ WHERE r.tenant_id = ? AND rr.id = ?`
2068
+ ).get(tenantId, id);
2069
+ return row ? this.mapRowToRunResult(row) : null;
2070
+ }
2071
+ async createRunResult(tenantId, runId, id, data) {
2072
+ const actualId = id || (0, import_crypto.randomUUID)();
2073
+ this.db.prepare(
2074
+ `INSERT INTO lt_eval_run_results (id, run_id, suite_name, case_id, pass, score, summary, dimension_results, duration_ms, messages, logs, error, created_at)
2075
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
2076
+ ).run(
2077
+ actualId,
2078
+ runId,
2079
+ data.suiteName,
2080
+ data.caseId || null,
2081
+ data.pass ? 1 : 0,
2082
+ data.score,
2083
+ data.summary || null,
2084
+ JSON.stringify(data.dimensionResults || []),
2085
+ data.durationMs ?? null,
2086
+ JSON.stringify(data.messages || []),
2087
+ JSON.stringify(data.logs || []),
2088
+ data.error || null,
2089
+ nowISO()
2090
+ );
2091
+ return await this.getRunResultById(tenantId, actualId);
2092
+ }
2093
+ async updateRunResult(tenantId, id, updates) {
2094
+ if (updates.runId !== void 0) throw new Error("runId cannot be updated on an existing result");
2095
+ const set = [];
2096
+ const vals = [];
2097
+ if (updates.suiteName !== void 0) {
2098
+ set.push("suite_name = ?");
2099
+ vals.push(updates.suiteName);
2100
+ }
2101
+ if (updates.caseId !== void 0) {
2102
+ set.push("case_id = ?");
2103
+ vals.push(updates.caseId);
2104
+ }
2105
+ if (updates.pass !== void 0) {
2106
+ set.push("pass = ?");
2107
+ vals.push(updates.pass ? 1 : 0);
2108
+ }
2109
+ if (updates.score !== void 0) {
2110
+ set.push("score = ?");
2111
+ vals.push(updates.score);
2112
+ }
2113
+ if (updates.summary !== void 0) {
2114
+ set.push("summary = ?");
2115
+ vals.push(updates.summary || null);
2116
+ }
2117
+ if (updates.dimensionResults !== void 0) {
2118
+ set.push("dimension_results = ?");
2119
+ vals.push(JSON.stringify(updates.dimensionResults));
2120
+ }
2121
+ if (updates.durationMs !== void 0) {
2122
+ set.push("duration_ms = ?");
2123
+ vals.push(updates.durationMs ?? null);
2124
+ }
2125
+ if (updates.messages !== void 0) {
2126
+ set.push("messages = ?");
2127
+ vals.push(JSON.stringify(updates.messages));
2128
+ }
2129
+ if (updates.logs !== void 0) {
2130
+ set.push("logs = ?");
2131
+ vals.push(JSON.stringify(updates.logs));
2132
+ }
2133
+ if (updates.error !== void 0) {
2134
+ set.push("error = ?");
2135
+ vals.push(updates.error || null);
2136
+ }
2137
+ if (set.length === 0) return this.getRunResultById(tenantId, id);
2138
+ vals.push(id, tenantId);
2139
+ this.db.prepare(
2140
+ `UPDATE lt_eval_run_results SET ${set.join(", ")}
2141
+ WHERE id = ? AND run_id IN (SELECT id FROM lt_eval_runs WHERE tenant_id = ?)`
2142
+ ).run(...vals);
2143
+ return this.getRunResultById(tenantId, id);
2144
+ }
2145
+ // -------------------------------------------------------------------------
2146
+ // Reports
2147
+ // -------------------------------------------------------------------------
2148
+ async getProjectReport(tenantId, projectId) {
2149
+ const project = await this.getProjectById(tenantId, projectId);
2150
+ if (!project) return null;
2151
+ const runs = await this.getRunsByTenant(tenantId, { projectId });
2152
+ const totalRuns = runs.length;
2153
+ const latestPassRate = runs.length > 0 ? runs[0].totalCases > 0 ? runs[0].passedCases / runs[0].totalCases : 0 : 0;
2154
+ const avgScore = runs.length > 0 ? runs.reduce((sum, r) => sum + r.avgScore, 0) / runs.length : 0;
2155
+ return { projectId: project.id, projectName: project.name, totalRuns, latestPassRate, avgScore, runs };
2156
+ }
2157
+ // -------------------------------------------------------------------------
2158
+ // Row mappers
2159
+ // -------------------------------------------------------------------------
2160
+ mapRowToProject(row) {
2161
+ return {
2162
+ id: row.id,
2163
+ tenantId: row.tenant_id,
2164
+ name: row.name,
2165
+ description: row.description,
2166
+ version: row.version,
2167
+ judgeModelConfig: parseJson(row.judge_model_config, {}),
2168
+ targetServerConfig: parseJson(row.target_server_config, {}),
2169
+ concurrency: row.concurrency ?? 3,
2170
+ reportConfig: parseOptionalJson(row.report_config),
2171
+ createdAt: parseISO(row.created_at),
2172
+ updatedAt: parseISO(row.updated_at)
2173
+ };
2174
+ }
2175
+ mapRowToSuite(row) {
2176
+ return {
2177
+ id: row.id,
2178
+ tenantId: row.tenant_id,
2179
+ projectId: row.project_id,
2180
+ name: row.name,
2181
+ createdAt: parseISO(row.created_at),
2182
+ updatedAt: parseISO(row.updated_at),
2183
+ caseCount: row.case_count !== void 0 ? row.case_count : void 0
2184
+ };
2185
+ }
2186
+ mapRowToCase(row) {
2187
+ return {
2188
+ id: row.id,
2189
+ tenantId: row.tenant_id,
2190
+ suiteId: row.suite_id,
2191
+ inputMessage: row.input_message,
2192
+ inputFiles: parseOptionalJson(row.input_files),
2193
+ steps: parseJson(row.steps, []),
2194
+ outputType: row.output_type || "message_content",
2195
+ contentAssertion: row.content_assertion || "",
2196
+ rubrics: parseOptionalJson(row.rubrics),
2197
+ createdAt: parseISO(row.created_at),
2198
+ updatedAt: parseISO(row.updated_at)
2199
+ };
2200
+ }
2201
+ mapRowToRun(row) {
2202
+ return {
2203
+ id: row.id,
2204
+ projectId: row.project_id,
2205
+ tenantId: row.tenant_id,
2206
+ status: row.status,
2207
+ concurrency: row.concurrency ?? 3,
2208
+ totalCases: row.total_cases ?? 0,
2209
+ passedCases: row.passed_cases ?? 0,
2210
+ failedCases: row.failed_cases ?? 0,
2211
+ avgScore: row.avg_score ?? 0,
2212
+ error: row.error,
2213
+ createdAt: parseISO(row.created_at),
2214
+ startedAt: row.started_at ? parseISO(row.started_at) : void 0,
2215
+ completedAt: row.completed_at ? parseISO(row.completed_at) : void 0
2216
+ };
2217
+ }
2218
+ mapRowToRunResult(row) {
2219
+ return {
2220
+ id: row.id,
2221
+ runId: row.run_id,
2222
+ suiteName: row.suite_name,
2223
+ caseId: row.case_id,
2224
+ pass: row.pass === 1,
2225
+ score: row.score ?? 0,
2226
+ summary: row.summary,
2227
+ dimensionResults: parseOptionalJson(row.dimension_results),
2228
+ durationMs: row.duration_ms,
2229
+ messages: parseOptionalJson(row.messages),
2230
+ logs: parseOptionalJson(row.logs),
2231
+ error: row.error,
2232
+ createdAt: parseISO(row.created_at)
2233
+ };
2234
+ }
2235
+ };
2236
+
2237
+ // src/stores/LocalChannelBindingStore.ts
2238
+ var import_crypto2 = require("crypto");
2239
+ var DDL13 = `
2240
+ CREATE TABLE IF NOT EXISTS lt_channel_bindings (
2241
+ id TEXT PRIMARY KEY,
2242
+ channel TEXT NOT NULL,
2243
+ channel_installation_id TEXT NOT NULL,
2244
+ tenant_id TEXT NOT NULL,
2245
+ sender_id TEXT NOT NULL,
2246
+ agent_id TEXT NOT NULL,
2247
+ thread_id TEXT,
2248
+ workspace_id TEXT,
2249
+ project_id TEXT,
2250
+ thread_mode TEXT NOT NULL DEFAULT 'fixed',
2251
+ sender_display_name TEXT,
2252
+ sender_metadata TEXT,
2253
+ enabled INTEGER NOT NULL DEFAULT 1,
2254
+ created_at TEXT NOT NULL,
2255
+ updated_at TEXT NOT NULL
2256
+ );
2257
+ CREATE INDEX IF NOT EXISTS idx_lt_cb_resolve ON lt_channel_bindings(channel, sender_id, channel_installation_id, tenant_id);
2258
+ `;
2259
+ var LocalChannelBindingStore = class {
2260
+ constructor(db) {
2261
+ this.db = db;
2262
+ ensureTable(db, DDL13);
2263
+ }
2264
+ async resolve(params) {
2265
+ const row = this.db.prepare(
2266
+ `SELECT * FROM lt_channel_bindings
2267
+ WHERE channel = ? AND sender_id = ? AND channel_installation_id = ? AND tenant_id = ? AND enabled = 1
2268
+ LIMIT 1`
2269
+ ).get(params.channel, params.senderId, params.channelInstallationId, params.tenantId);
2270
+ return row ? mapRowToBinding(row) : null;
2271
+ }
2272
+ async create(input) {
2273
+ const id = (0, import_crypto2.randomUUID)();
2274
+ const now = nowISO();
2275
+ this.db.prepare(
2276
+ `INSERT INTO lt_channel_bindings
2277
+ (id, channel, channel_installation_id, tenant_id, sender_id, agent_id,
2278
+ thread_mode, sender_display_name, sender_metadata, workspace_id, project_id, created_at, updated_at)
2279
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
2280
+ ).run(
2281
+ id,
2282
+ input.channel,
2283
+ input.channelInstallationId,
2284
+ input.tenantId,
2285
+ input.senderId,
2286
+ input.agentId,
2287
+ input.threadMode || "fixed",
2288
+ input.senderDisplayName || null,
2289
+ input.senderMetadata ? JSON.stringify(input.senderMetadata) : null,
2290
+ input.workspaceId || null,
2291
+ input.projectId || null,
2292
+ now,
2293
+ now
2294
+ );
2295
+ return await this.getById(id);
2296
+ }
2297
+ async update(id, patch) {
2298
+ const existing = await this.getById(id);
2299
+ if (!existing) throw new Error(`Binding ${id} not found`);
2300
+ const updated = {
2301
+ channel: patch.channel ?? existing.channel,
2302
+ channelInstallationId: patch.channelInstallationId ?? existing.channelInstallationId,
2303
+ senderId: patch.senderId ?? existing.senderId,
2304
+ agentId: patch.agentId ?? existing.agentId,
2305
+ threadId: patch.threadId !== void 0 ? patch.threadId : existing.threadId,
2306
+ workspaceId: patch.workspaceId !== void 0 ? patch.workspaceId : existing.workspaceId,
2307
+ projectId: patch.projectId !== void 0 ? patch.projectId : existing.projectId,
2308
+ threadMode: patch.threadMode ?? existing.threadMode,
2309
+ senderDisplayName: patch.senderDisplayName !== void 0 ? patch.senderDisplayName : existing.senderDisplayName,
2310
+ senderMetadata: patch.senderMetadata !== void 0 ? patch.senderMetadata : existing.senderMetadata,
2311
+ enabled: patch.enabled ?? existing.enabled
2312
+ };
2313
+ const now = nowISO();
2314
+ this.db.prepare(
2315
+ `UPDATE lt_channel_bindings SET
2316
+ channel = ?, channel_installation_id = ?, sender_id = ?, agent_id = ?,
2317
+ thread_id = ?, workspace_id = ?, project_id = ?, thread_mode = ?,
2318
+ sender_display_name = ?, sender_metadata = ?, enabled = ?, updated_at = ?
2319
+ WHERE id = ?`
2320
+ ).run(
2321
+ updated.channel,
2322
+ updated.channelInstallationId,
2323
+ updated.senderId,
2324
+ updated.agentId,
2325
+ updated.threadId || null,
2326
+ updated.workspaceId || null,
2327
+ updated.projectId || null,
2328
+ updated.threadMode,
2329
+ updated.senderDisplayName || null,
2330
+ updated.senderMetadata ? JSON.stringify(updated.senderMetadata) : null,
2331
+ updated.enabled ? 1 : 0,
2332
+ now,
2333
+ id
2334
+ );
2335
+ return await this.getById(id);
2336
+ }
2337
+ async delete(id) {
2338
+ this.db.prepare(`DELETE FROM lt_channel_bindings WHERE id = ?`).run(id);
2339
+ }
2340
+ async list(params) {
2341
+ const conditions = ["tenant_id = ?"];
2342
+ const values = [params.tenantId];
2343
+ if (params.channel) {
2344
+ conditions.push("channel = ?");
2345
+ values.push(params.channel);
2346
+ }
2347
+ if (params.agentId) {
2348
+ conditions.push("agent_id = ?");
2349
+ values.push(params.agentId);
2350
+ }
2351
+ if (params.channelInstallationId) {
2352
+ conditions.push("channel_installation_id = ?");
2353
+ values.push(params.channelInstallationId);
2354
+ }
2355
+ const limit = params.limit ?? 50;
2356
+ const offset = params.offset ?? 0;
2357
+ values.push(limit, offset);
2358
+ const rows = this.db.prepare(
2359
+ `SELECT * FROM lt_channel_bindings
2360
+ WHERE ${conditions.join(" AND ")}
2361
+ ORDER BY created_at DESC
2362
+ LIMIT ? OFFSET ?`
2363
+ ).all(...values);
2364
+ return rows.map(mapRowToBinding);
2365
+ }
2366
+ async import(bindings) {
2367
+ const result = [];
2368
+ for (const input of bindings) {
2369
+ result.push(await this.create(input));
2370
+ }
2371
+ return result;
2372
+ }
2373
+ async export(params) {
2374
+ return this.list({ tenantId: params.tenantId, limit: 1e4, offset: 0 });
2375
+ }
2376
+ async getById(id) {
2377
+ const row = this.db.prepare(
2378
+ `SELECT * FROM lt_channel_bindings WHERE id = ?`
2379
+ ).get(id);
2380
+ return row ? mapRowToBinding(row) : null;
2381
+ }
2382
+ };
2383
+ function mapRowToBinding(row) {
2384
+ return {
2385
+ id: row.id,
2386
+ channel: row.channel,
2387
+ channelInstallationId: row.channel_installation_id,
2388
+ tenantId: row.tenant_id,
2389
+ senderId: row.sender_id,
2390
+ agentId: row.agent_id,
2391
+ threadId: row.thread_id || void 0,
2392
+ workspaceId: row.workspace_id || void 0,
2393
+ projectId: row.project_id || void 0,
2394
+ threadMode: row.thread_mode,
2395
+ senderDisplayName: row.sender_display_name || void 0,
2396
+ senderMetadata: row.sender_metadata ? JSON.parse(row.sender_metadata) : void 0,
2397
+ enabled: row.enabled === 1,
2398
+ createdAt: parseISO(row.created_at),
2399
+ updatedAt: parseISO(row.updated_at)
2400
+ };
2401
+ }
2402
+
2403
+ // src/stores/LocalChannelInstallationStore.ts
2404
+ var DDL14 = `
2405
+ CREATE TABLE IF NOT EXISTS lt_channel_installations (
2406
+ id TEXT PRIMARY KEY,
2407
+ tenant_id TEXT NOT NULL,
2408
+ channel TEXT NOT NULL,
2409
+ name TEXT,
2410
+ config TEXT NOT NULL,
2411
+ enabled INTEGER NOT NULL DEFAULT 1,
2412
+ fallback_agent_id TEXT,
2413
+ reject_when_no_binding INTEGER NOT NULL DEFAULT 0,
2414
+ created_at TEXT NOT NULL,
2415
+ updated_at TEXT NOT NULL
2416
+ );
2417
+ CREATE INDEX IF NOT EXISTS idx_lt_ci_tenant ON lt_channel_installations(tenant_id);
2418
+ `;
2419
+ var LocalChannelInstallationStore = class {
2420
+ constructor(db) {
2421
+ this.db = db;
2422
+ ensureTable(db, DDL14);
2423
+ }
2424
+ async getInstallationById(installationId) {
2425
+ const row = this.db.prepare(
2426
+ `SELECT * FROM lt_channel_installations WHERE id = ?`
2427
+ ).get(installationId);
2428
+ return row ? mapRow(row) : null;
2429
+ }
2430
+ async getInstallationsByTenant(tenantId, channel) {
2431
+ let rows;
2432
+ if (channel) {
2433
+ rows = this.db.prepare(
2434
+ `SELECT * FROM lt_channel_installations WHERE tenant_id = ? AND channel = ? ORDER BY created_at DESC`
2435
+ ).all(tenantId, channel);
2436
+ } else {
2437
+ rows = this.db.prepare(
2438
+ `SELECT * FROM lt_channel_installations WHERE tenant_id = ? ORDER BY created_at DESC`
2439
+ ).all(tenantId);
2440
+ }
2441
+ return rows.map(mapRow);
2442
+ }
2443
+ async createInstallation(tenantId, installationId, data) {
2444
+ const now = nowISO();
2445
+ this.db.prepare(
2446
+ `INSERT INTO lt_channel_installations
2447
+ (id, tenant_id, channel, name, config, enabled, fallback_agent_id, reject_when_no_binding, created_at, updated_at)
2448
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2449
+ ON CONFLICT(id) DO UPDATE SET
2450
+ channel = excluded.channel,
2451
+ name = excluded.name,
2452
+ config = excluded.config,
2453
+ enabled = excluded.enabled,
2454
+ fallback_agent_id = excluded.fallback_agent_id,
2455
+ reject_when_no_binding = excluded.reject_when_no_binding,
2456
+ updated_at = excluded.updated_at`
2457
+ ).run(
2458
+ installationId,
2459
+ tenantId,
2460
+ data.channel,
2461
+ data.name || null,
2462
+ JSON.stringify(data.config),
2463
+ data.enabled !== false ? 1 : 0,
2464
+ data.fallbackAgentId || null,
2465
+ data.rejectWhenNoBinding ? 1 : 0,
2466
+ now,
2467
+ now
2468
+ );
2469
+ return {
2470
+ id: installationId,
2471
+ tenantId,
2472
+ channel: data.channel,
2473
+ name: data.name,
2474
+ config: data.config,
2475
+ enabled: data.enabled !== false,
2476
+ fallbackAgentId: data.fallbackAgentId,
2477
+ rejectWhenNoBinding: data.rejectWhenNoBinding ?? false,
2478
+ createdAt: parseISO(now),
2479
+ updatedAt: parseISO(now)
2480
+ };
2481
+ }
2482
+ async updateInstallation(tenantId, installationId, updates) {
2483
+ const existing = await this.getInstallationById(installationId);
2484
+ if (!existing) return null;
2485
+ const setClauses = [];
2486
+ const values = [];
2487
+ if (updates.name !== void 0) {
2488
+ setClauses.push("name = ?");
2489
+ values.push(updates.name || null);
2490
+ }
2491
+ if (updates.config !== void 0) {
2492
+ setClauses.push("config = ?");
2493
+ values.push(JSON.stringify(updates.config));
2494
+ }
2495
+ if (updates.enabled !== void 0) {
2496
+ setClauses.push("enabled = ?");
2497
+ values.push(updates.enabled ? 1 : 0);
2498
+ }
2499
+ if (updates.fallbackAgentId !== void 0) {
2500
+ setClauses.push("fallback_agent_id = ?");
2501
+ values.push(updates.fallbackAgentId || null);
2502
+ }
2503
+ if (updates.rejectWhenNoBinding !== void 0) {
2504
+ setClauses.push("reject_when_no_binding = ?");
2505
+ values.push(updates.rejectWhenNoBinding ? 1 : 0);
2506
+ }
2507
+ if (setClauses.length === 0) return existing;
2508
+ const now = nowISO();
2509
+ setClauses.push("updated_at = ?");
2510
+ values.push(now);
2511
+ values.push(installationId);
2512
+ this.db.prepare(
2513
+ `UPDATE lt_channel_installations SET ${setClauses.join(", ")} WHERE id = ?`
2514
+ ).run(...values);
2515
+ return this.getInstallationById(installationId);
2516
+ }
2517
+ async deleteInstallation(tenantId, installationId) {
2518
+ const result = this.db.prepare(
2519
+ `DELETE FROM lt_channel_installations WHERE id = ? AND tenant_id = ?`
2520
+ ).run(installationId, tenantId);
2521
+ return result.changes > 0;
2522
+ }
2523
+ };
2524
+ function mapRow(row) {
2525
+ return {
2526
+ id: row.id,
2527
+ tenantId: row.tenant_id,
2528
+ channel: row.channel,
2529
+ name: row.name || void 0,
2530
+ config: JSON.parse(row.config),
2531
+ enabled: row.enabled === 1,
2532
+ fallbackAgentId: row.fallback_agent_id || void 0,
2533
+ rejectWhenNoBinding: row.reject_when_no_binding === 1,
2534
+ createdAt: parseISO(row.created_at),
2535
+ updatedAt: parseISO(row.updated_at)
2536
+ };
2537
+ }
2538
+
2539
+ // src/stores/LocalA2AApiKeyStore.ts
2540
+ var import_core3 = require("@axiom-lattice/core");
2541
+ var import_crypto3 = require("crypto");
2542
+ var DDL15 = `
2543
+ CREATE TABLE IF NOT EXISTS lt_a2a_api_keys (
2544
+ id TEXT PRIMARY KEY,
2545
+ key_value TEXT NOT NULL,
2546
+ tenant_id TEXT NOT NULL,
2547
+ project_id TEXT,
2548
+ workspace_id TEXT,
2549
+ label TEXT,
2550
+ enabled INTEGER NOT NULL DEFAULT 1,
2551
+ created_at TEXT NOT NULL,
2552
+ updated_at TEXT NOT NULL
2553
+ );
2554
+ `;
2555
+ function generateApiKey() {
2556
+ return `a2a_${(0, import_crypto3.randomUUID)().replace(/-/g, "")}`;
2557
+ }
2558
+ var LocalA2AApiKeyStore = class {
2559
+ constructor(db) {
2560
+ this.db = db;
2561
+ ensureTable(db, DDL15);
2562
+ }
2563
+ async findByKey(key) {
2564
+ const rows = this.db.prepare(
2565
+ `SELECT * FROM lt_a2a_api_keys WHERE enabled = 1`
2566
+ ).all();
2567
+ for (const row of rows) {
2568
+ try {
2569
+ if ((0, import_core3.decrypt)(row.key_value) === key) return mapRowToRecord(row);
2570
+ } catch {
2571
+ }
2572
+ }
2573
+ return null;
2574
+ }
2575
+ async list(params) {
2576
+ const limit = params.limit || 100;
2577
+ const offset = params.offset || 0;
2578
+ let rows;
2579
+ if (params.tenantId) {
2580
+ rows = this.db.prepare(
2581
+ `SELECT * FROM lt_a2a_api_keys WHERE tenant_id = ? ORDER BY created_at DESC LIMIT ? OFFSET ?`
2582
+ ).all(params.tenantId, limit, offset);
2583
+ } else {
2584
+ rows = this.db.prepare(
2585
+ `SELECT * FROM lt_a2a_api_keys ORDER BY created_at DESC LIMIT ? OFFSET ?`
2586
+ ).all(limit, offset);
2587
+ }
2588
+ return rows.map(mapRowToRecord);
2589
+ }
2590
+ async create(input) {
2591
+ const key = generateApiKey();
2592
+ const now = nowISO();
2593
+ this.db.prepare(
2594
+ `INSERT INTO lt_a2a_api_keys (key_value, tenant_id, project_id, workspace_id, label, created_at, updated_at)
2595
+ VALUES (?, ?, ?, ?, ?, ?, ?)`
2596
+ ).run((0, import_core3.encrypt)(key), input.tenantId, input.projectId || null, input.workspaceId || null, input.label || null, now, now);
2597
+ const lastId = this.db.prepare(`SELECT last_insert_rowid() as id`).get();
2598
+ const record = {
2599
+ id: String(lastId.id),
2600
+ key,
2601
+ tenantId: input.tenantId,
2602
+ projectId: input.projectId,
2603
+ workspaceId: input.workspaceId,
2604
+ label: input.label,
2605
+ enabled: true,
2606
+ createdAt: parseISO(now),
2607
+ updatedAt: parseISO(now)
2608
+ };
2609
+ return record;
2610
+ }
2611
+ async disable(id) {
2612
+ const now = nowISO();
2613
+ this.db.prepare(
2614
+ `UPDATE lt_a2a_api_keys SET enabled = 0, updated_at = ? WHERE id = ?`
2615
+ ).run(now, id);
2616
+ const row = this.db.prepare(`SELECT * FROM lt_a2a_api_keys WHERE id = ?`).get(id);
2617
+ if (!row) throw new Error(`A2A API key not found: ${id}`);
2618
+ return mapRowToRecord(row);
2619
+ }
2620
+ async enable(id) {
2621
+ const now = nowISO();
2622
+ this.db.prepare(
2623
+ `UPDATE lt_a2a_api_keys SET enabled = 1, updated_at = ? WHERE id = ?`
2624
+ ).run(now, id);
2625
+ const row = this.db.prepare(`SELECT * FROM lt_a2a_api_keys WHERE id = ?`).get(id);
2626
+ if (!row) throw new Error(`A2A API key not found: ${id}`);
2627
+ return mapRowToRecord(row);
2628
+ }
2629
+ async rotate(id) {
2630
+ const key = generateApiKey();
2631
+ const now = nowISO();
2632
+ this.db.prepare(
2633
+ `UPDATE lt_a2a_api_keys SET key_value = ?, updated_at = ? WHERE id = ?`
2634
+ ).run((0, import_core3.encrypt)(key), now, id);
2635
+ const row = this.db.prepare(`SELECT * FROM lt_a2a_api_keys WHERE id = ?`).get(id);
2636
+ if (!row) throw new Error(`A2A API key not found: ${id}`);
2637
+ const record = mapRowToRecord(row);
2638
+ record.key = key;
2639
+ return record;
2640
+ }
2641
+ async delete(id) {
2642
+ this.db.prepare(`DELETE FROM lt_a2a_api_keys WHERE id = ?`).run(id);
2643
+ }
2644
+ async loadIntoMap() {
2645
+ const rows = this.db.prepare(
2646
+ `SELECT * FROM lt_a2a_api_keys WHERE enabled = 1`
2647
+ ).all();
2648
+ const map = /* @__PURE__ */ new Map();
2649
+ for (const row of rows) {
2650
+ try {
2651
+ const key = (0, import_core3.decrypt)(row.key_value);
2652
+ map.set(key, {
2653
+ key,
2654
+ tenantId: row.tenant_id,
2655
+ projectId: row.project_id || void 0,
2656
+ workspaceId: row.workspace_id || void 0
2657
+ });
2658
+ } catch {
2659
+ }
2660
+ }
2661
+ return map;
2662
+ }
2663
+ };
2664
+ function mapRowToRecord(row) {
2665
+ let key = "";
2666
+ try {
2667
+ key = (0, import_core3.decrypt)(row.key_value);
2668
+ } catch {
2669
+ key = row.key_value;
2670
+ }
2671
+ return {
2672
+ id: row.id,
2673
+ key,
2674
+ tenantId: row.tenant_id,
2675
+ projectId: row.project_id || void 0,
2676
+ workspaceId: row.workspace_id || void 0,
2677
+ label: row.label || void 0,
2678
+ enabled: row.enabled === 1,
2679
+ createdAt: parseISO(row.created_at),
2680
+ updatedAt: parseISO(row.updated_at)
2681
+ };
2682
+ }
2683
+
2684
+ // src/stores/LocalThreadMessageQueueStore.ts
2685
+ var import_crypto4 = require("crypto");
2686
+ var DDL16 = `
2687
+ CREATE TABLE IF NOT EXISTS lt_thread_message_queue (
2688
+ id TEXT PRIMARY KEY,
2689
+ thread_id TEXT NOT NULL,
2690
+ tenant_id TEXT NOT NULL,
2691
+ assistant_id TEXT NOT NULL,
2692
+ message_content TEXT NOT NULL,
2693
+ message_type TEXT NOT NULL DEFAULT 'human',
2694
+ sequence_order INTEGER NOT NULL DEFAULT 0,
2695
+ priority INTEGER NOT NULL DEFAULT 0,
2696
+ status TEXT NOT NULL DEFAULT 'pending',
2697
+ command TEXT,
2698
+ custom_run_config TEXT,
2699
+ created_at TEXT NOT NULL
2700
+ );
2701
+ CREATE INDEX IF NOT EXISTS idx_lt_tmq_thread ON lt_thread_message_queue(thread_id, status);
2702
+ CREATE INDEX IF NOT EXISTS idx_lt_tmq_pending ON lt_thread_message_queue(status, priority DESC, sequence_order ASC);
2703
+ `;
2704
+ var LocalThreadMessageQueueStore = class {
2705
+ constructor(db) {
2706
+ this.db = db;
2707
+ ensureTable(db, DDL16);
2708
+ }
2709
+ async addMessage(params) {
2710
+ const now = nowISO();
2711
+ const id = params.id || (0, import_crypto4.randomUUID)();
2712
+ const seqRow = this.db.prepare(
2713
+ `SELECT COALESCE(MAX(sequence_order), 0) + 1 as next_seq FROM lt_thread_message_queue WHERE thread_id = ?`
2714
+ ).get(params.threadId);
2715
+ const nextSeq = seqRow.next_seq;
2716
+ this.db.prepare(
2717
+ `INSERT INTO lt_thread_message_queue (id, thread_id, tenant_id, assistant_id, message_content, message_type, sequence_order, priority, command, custom_run_config, created_at)
2718
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
2719
+ ).run(
2720
+ id,
2721
+ params.threadId,
2722
+ params.tenantId,
2723
+ params.assistantId,
2724
+ JSON.stringify(params.content),
2725
+ params.type || "human",
2726
+ nextSeq,
2727
+ params.priority || 0,
2728
+ params.command ? JSON.stringify(params.command) : null,
2729
+ params.custom_run_config ? JSON.stringify(params.custom_run_config) : null,
2730
+ now
2731
+ );
2732
+ return this.getById(id);
2733
+ }
2734
+ async addMessageAtHead(params) {
2735
+ const now = nowISO();
2736
+ const id = params.id || (0, import_crypto4.randomUUID)();
2737
+ const seqRow = this.db.prepare(
2738
+ `SELECT COALESCE(MAX(sequence_order), 0) + 1 as next_seq FROM lt_thread_message_queue WHERE thread_id = ?`
2739
+ ).get(params.threadId);
2740
+ this.db.prepare(
2741
+ `INSERT INTO lt_thread_message_queue (id, thread_id, tenant_id, assistant_id, message_content, message_type, sequence_order, priority, command, custom_run_config, created_at)
2742
+ VALUES (?, ?, ?, ?, ?, ?, ?, 100, ?, ?, ?)`
2743
+ ).run(
2744
+ id,
2745
+ params.threadId,
2746
+ params.tenantId,
2747
+ params.assistantId,
2748
+ JSON.stringify(params.content),
2749
+ params.type || "human",
2750
+ seqRow.next_seq,
2751
+ params.command ? JSON.stringify(params.command) : null,
2752
+ params.custom_run_config ? JSON.stringify(params.custom_run_config) : null,
2753
+ now
2754
+ );
2755
+ return this.getById(id);
2756
+ }
2757
+ async getPendingMessages(threadId) {
2758
+ const rows = this.db.prepare(
2759
+ `SELECT * FROM lt_thread_message_queue WHERE thread_id = ? AND status = 'pending' ORDER BY priority DESC, sequence_order ASC`
2760
+ ).all(threadId);
2761
+ return rows.map(rowToMessage);
2762
+ }
2763
+ async getProcessingMessages(threadId) {
2764
+ const rows = this.db.prepare(
2765
+ `SELECT * FROM lt_thread_message_queue WHERE thread_id = ? AND status = 'processing' ORDER BY priority DESC, sequence_order ASC`
2766
+ ).all(threadId);
2767
+ return rows.map(rowToMessage);
2768
+ }
2769
+ async getQueueSize(threadId) {
2770
+ const row = this.db.prepare(
2771
+ `SELECT COUNT(*) as count FROM lt_thread_message_queue WHERE thread_id = ? AND status = 'pending'`
2772
+ ).get(threadId);
2773
+ return row.count;
2774
+ }
2775
+ async getThreadsWithPendingMessages() {
2776
+ const rows = this.db.prepare(
2777
+ `SELECT DISTINCT tenant_id, assistant_id, thread_id FROM lt_thread_message_queue WHERE status IN ('pending', 'processing') ORDER BY thread_id`
2778
+ ).all();
2779
+ return rows.map((r) => ({
2780
+ tenantId: r.tenant_id,
2781
+ assistantId: r.assistant_id,
2782
+ threadId: r.thread_id
2783
+ }));
2784
+ }
2785
+ async removeMessage(messageId) {
2786
+ const result = this.db.prepare(`DELETE FROM lt_thread_message_queue WHERE id = ?`).run(messageId);
2787
+ return result.changes > 0;
2788
+ }
2789
+ async clearMessages(threadId) {
2790
+ this.db.prepare(`DELETE FROM lt_thread_message_queue WHERE thread_id = ?`).run(threadId);
2791
+ }
2792
+ async markProcessing(messageId) {
2793
+ this.db.prepare(`UPDATE lt_thread_message_queue SET status = 'processing' WHERE id = ?`).run(messageId);
2794
+ }
2795
+ async resetProcessingToPending(threadId) {
2796
+ const result = this.db.prepare(
2797
+ `UPDATE lt_thread_message_queue SET status = 'pending' WHERE thread_id = ? AND status = 'processing'`
2798
+ ).run(threadId);
2799
+ return result.changes;
2800
+ }
2801
+ getById(id) {
2802
+ const row = this.db.prepare(`SELECT * FROM lt_thread_message_queue WHERE id = ?`).get(id);
2803
+ return rowToMessage(row);
2804
+ }
2805
+ };
2806
+ function rowToMessage(row) {
2807
+ return {
2808
+ id: row.id,
2809
+ content: JSON.parse(row.message_content),
2810
+ type: row.message_type,
2811
+ sequence: row.sequence_order,
2812
+ createdAt: parseISO(row.created_at),
2813
+ priority: row.priority || 0,
2814
+ command: row.command ? JSON.parse(row.command) : void 0,
2815
+ custom_run_config: row.custom_run_config ? JSON.parse(row.custom_run_config) : void 0
2816
+ };
2817
+ }
2818
+
2819
+ // src/stores/LocalSkillStore.ts
2820
+ var DDL17 = `
2821
+ CREATE TABLE IF NOT EXISTS lt_skills (
2822
+ id TEXT NOT NULL,
2823
+ tenant_id TEXT NOT NULL,
2824
+ name TEXT NOT NULL,
2825
+ description TEXT NOT NULL,
2826
+ license TEXT,
2827
+ compatibility TEXT,
2828
+ metadata TEXT DEFAULT '{}',
2829
+ content TEXT,
2830
+ sub_skills TEXT DEFAULT '[]',
2831
+ created_at TEXT NOT NULL,
2832
+ updated_at TEXT NOT NULL,
2833
+ PRIMARY KEY (tenant_id, id)
2834
+ );
2835
+ `;
2836
+ var LocalSkillStore = class {
2837
+ constructor(db) {
2838
+ this.db = db;
2839
+ ensureTable(db, DDL17);
2840
+ }
2841
+ async getAllSkills(tenantId, _context) {
2842
+ const rows = this.db.prepare(
2843
+ `SELECT * FROM lt_skills WHERE tenant_id = ? ORDER BY created_at DESC`
2844
+ ).all(tenantId);
2845
+ return rows.map(mapRowToSkill);
2846
+ }
2847
+ async getSkillById(tenantId, id, _context) {
2848
+ const row = this.db.prepare(
2849
+ `SELECT * FROM lt_skills WHERE tenant_id = ? AND id = ?`
2850
+ ).get(tenantId, id);
2851
+ return row ? mapRowToSkill(row) : null;
2852
+ }
2853
+ async createSkill(tenantId, id, data, _context) {
2854
+ const now = nowISO();
2855
+ this.db.prepare(
2856
+ `INSERT INTO lt_skills (id, tenant_id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at)
2857
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2858
+ ON CONFLICT(tenant_id, id) DO UPDATE SET
2859
+ name = excluded.name, description = excluded.description,
2860
+ license = excluded.license, compatibility = excluded.compatibility,
2861
+ metadata = excluded.metadata, content = excluded.content,
2862
+ sub_skills = excluded.sub_skills, updated_at = excluded.updated_at`
2863
+ ).run(
2864
+ id,
2865
+ tenantId,
2866
+ data.name,
2867
+ data.description,
2868
+ data.license || null,
2869
+ data.compatibility || null,
2870
+ JSON.stringify(data.metadata || {}),
2871
+ data.content || null,
2872
+ JSON.stringify(data.subSkills || []),
2873
+ now,
2874
+ now
2875
+ );
2876
+ return {
2877
+ id,
2878
+ tenantId,
2879
+ name: data.name,
2880
+ description: data.description,
2881
+ license: data.license,
2882
+ compatibility: data.compatibility,
2883
+ metadata: data.metadata || {},
2884
+ content: data.content,
2885
+ subSkills: data.subSkills,
2886
+ createdAt: parseISO(now),
2887
+ updatedAt: parseISO(now)
2888
+ };
2889
+ }
2890
+ async updateSkill(tenantId, id, updates, _context) {
2891
+ const existing = await this.getSkillById(tenantId, id);
2892
+ if (!existing) return null;
2893
+ const setClauses = [];
2894
+ const values = [];
2895
+ if (updates.name !== void 0) {
2896
+ setClauses.push("name = ?");
2897
+ values.push(updates.name);
2898
+ }
2899
+ if (updates.description !== void 0) {
2900
+ setClauses.push("description = ?");
2901
+ values.push(updates.description);
2902
+ }
2903
+ if (updates.license !== void 0) {
2904
+ setClauses.push("license = ?");
2905
+ values.push(updates.license || null);
2906
+ }
2907
+ if (updates.compatibility !== void 0) {
2908
+ setClauses.push("compatibility = ?");
2909
+ values.push(updates.compatibility || null);
2910
+ }
2911
+ if (updates.metadata !== void 0) {
2912
+ setClauses.push("metadata = ?");
2913
+ values.push(JSON.stringify(updates.metadata || {}));
2914
+ }
2915
+ if (updates.content !== void 0) {
2916
+ setClauses.push("content = ?");
2917
+ values.push(updates.content || null);
2918
+ }
2919
+ if (updates.subSkills !== void 0) {
2920
+ setClauses.push("sub_skills = ?");
2921
+ values.push(JSON.stringify(updates.subSkills || []));
2922
+ }
2923
+ if (setClauses.length === 0) return existing;
2924
+ const now = nowISO();
2925
+ setClauses.push("updated_at = ?");
2926
+ values.push(now);
2927
+ values.push(tenantId, id);
2928
+ this.db.prepare(
2929
+ `UPDATE lt_skills SET ${setClauses.join(", ")} WHERE tenant_id = ? AND id = ?`
2930
+ ).run(...values);
2931
+ return this.getSkillById(tenantId, id);
2932
+ }
2933
+ async deleteSkill(tenantId, id, _context) {
2934
+ const result = this.db.prepare(
2935
+ `DELETE FROM lt_skills WHERE tenant_id = ? AND id = ?`
2936
+ ).run(tenantId, id);
2937
+ return result.changes > 0;
2938
+ }
2939
+ async hasSkill(tenantId, id, _context) {
2940
+ const row = this.db.prepare(
2941
+ `SELECT 1 FROM lt_skills WHERE tenant_id = ? AND id = ? LIMIT 1`
2942
+ ).get(tenantId, id);
2943
+ return row !== void 0;
2944
+ }
2945
+ async searchByMetadata(tenantId, metadataKey, metadataValue, _context) {
2946
+ const all = await this.getAllSkills(tenantId);
2947
+ return all.filter((s) => s.metadata?.[metadataKey] === metadataValue);
2948
+ }
2949
+ async filterByCompatibility(tenantId, compatibility, _context) {
2950
+ const rows = this.db.prepare(
2951
+ `SELECT * FROM lt_skills WHERE tenant_id = ? AND compatibility = ? ORDER BY created_at DESC`
2952
+ ).all(tenantId, compatibility);
2953
+ return rows.map(mapRowToSkill);
2954
+ }
2955
+ async filterByLicense(tenantId, license, _context) {
2956
+ const rows = this.db.prepare(
2957
+ `SELECT * FROM lt_skills WHERE tenant_id = ? AND license = ? ORDER BY created_at DESC`
2958
+ ).all(tenantId, license);
2959
+ return rows.map(mapRowToSkill);
2960
+ }
2961
+ async getSubSkills(tenantId, parentSkillName, _context) {
2962
+ const all = await this.getAllSkills(tenantId);
2963
+ return all.filter((s) => s.subSkills?.includes(parentSkillName));
2964
+ }
2965
+ async listSkillResources(_tenantId, _id, _context) {
2966
+ return [];
2967
+ }
2968
+ async loadSkillResource(_tenantId, _id, _resourcePath, _context) {
2969
+ return null;
2970
+ }
2971
+ };
2972
+ function mapRowToSkill(row) {
2973
+ return {
2974
+ id: row.id,
2975
+ tenantId: row.tenant_id,
2976
+ name: row.name,
2977
+ description: row.description,
2978
+ license: row.license || void 0,
2979
+ compatibility: row.compatibility || void 0,
2980
+ metadata: JSON.parse(row.metadata || "{}"),
2981
+ content: row.content || void 0,
2982
+ subSkills: JSON.parse(row.sub_skills || "[]"),
2983
+ createdAt: parseISO(row.created_at),
2984
+ updatedAt: parseISO(row.updated_at)
2985
+ };
2986
+ }
2987
+
2988
+ // src/stores/LocalScheduleStorage.ts
2989
+ var DDL18 = `
2990
+ CREATE TABLE IF NOT EXISTS lt_scheduled_tasks (
2991
+ task_id TEXT PRIMARY KEY,
2992
+ task_type TEXT NOT NULL,
2993
+ tenant_id TEXT NOT NULL,
2994
+ payload TEXT NOT NULL DEFAULT '{}',
2995
+ assistant_id TEXT,
2996
+ thread_id TEXT,
2997
+ execution_type TEXT NOT NULL,
2998
+ execute_at TEXT,
2999
+ delay_ms INTEGER,
3000
+ cron_expression TEXT,
3001
+ timezone TEXT,
3002
+ next_run_at TEXT,
3003
+ last_run_at TEXT,
3004
+ status TEXT NOT NULL DEFAULT 'pending',
3005
+ run_count INTEGER NOT NULL DEFAULT 0,
3006
+ max_runs INTEGER,
3007
+ retry_count INTEGER NOT NULL DEFAULT 0,
3008
+ max_retries INTEGER NOT NULL DEFAULT 0,
3009
+ last_error TEXT,
3010
+ created_at TEXT NOT NULL,
3011
+ updated_at TEXT NOT NULL,
3012
+ expires_at TEXT,
3013
+ metadata TEXT
3014
+ );
3015
+ CREATE INDEX IF NOT EXISTS idx_lt_st_status ON lt_scheduled_tasks(status);
3016
+ CREATE INDEX IF NOT EXISTS idx_lt_st_type ON lt_scheduled_tasks(task_type);
3017
+ CREATE INDEX IF NOT EXISTS idx_lt_st_tenant ON lt_scheduled_tasks(tenant_id);
3018
+ `;
3019
+ var LocalScheduleStorage = class {
3020
+ constructor(db) {
3021
+ this.db = db;
3022
+ ensureTable(db, DDL18);
3023
+ }
3024
+ async save(task) {
3025
+ this.db.prepare(
3026
+ `INSERT INTO lt_scheduled_tasks (
3027
+ task_id, task_type, tenant_id, payload, assistant_id, thread_id, execution_type,
3028
+ execute_at, delay_ms, cron_expression, timezone, next_run_at, last_run_at,
3029
+ status, run_count, max_runs, retry_count, max_retries, last_error,
3030
+ created_at, updated_at, expires_at, metadata
3031
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
3032
+ ON CONFLICT(task_id) DO UPDATE SET
3033
+ task_type = excluded.task_type, tenant_id = excluded.tenant_id,
3034
+ payload = excluded.payload, assistant_id = excluded.assistant_id,
3035
+ thread_id = excluded.thread_id, execution_type = excluded.execution_type,
3036
+ execute_at = excluded.execute_at, delay_ms = excluded.delay_ms,
3037
+ cron_expression = excluded.cron_expression, timezone = excluded.timezone,
3038
+ next_run_at = excluded.next_run_at, last_run_at = excluded.last_run_at,
3039
+ status = excluded.status, run_count = excluded.run_count,
3040
+ max_runs = excluded.max_runs, retry_count = excluded.retry_count,
3041
+ max_retries = excluded.max_retries, last_error = excluded.last_error,
3042
+ updated_at = excluded.updated_at, expires_at = excluded.expires_at,
3043
+ metadata = excluded.metadata`
3044
+ ).run(
3045
+ task.taskId,
3046
+ task.taskType,
3047
+ task.tenantId,
3048
+ JSON.stringify(task.payload),
3049
+ task.assistantId ?? null,
3050
+ task.threadId ?? null,
3051
+ task.executionType,
3052
+ task.executeAt ? new Date(task.executeAt).toISOString() : null,
3053
+ task.delayMs ?? null,
3054
+ task.cronExpression ?? null,
3055
+ task.timezone ?? null,
3056
+ task.nextRunAt ? new Date(task.nextRunAt).toISOString() : null,
3057
+ task.lastRunAt ? new Date(task.lastRunAt).toISOString() : null,
3058
+ task.status,
3059
+ task.runCount,
3060
+ task.maxRuns ?? null,
3061
+ task.retryCount,
3062
+ task.maxRetries,
3063
+ task.lastError ?? null,
3064
+ new Date(task.createdAt).toISOString(),
3065
+ new Date(task.updatedAt).toISOString(),
3066
+ task.expiresAt ? new Date(task.expiresAt).toISOString() : null,
3067
+ task.metadata ? JSON.stringify(task.metadata) : null
3068
+ );
3069
+ }
3070
+ async get(taskId) {
3071
+ const row = this.db.prepare(
3072
+ `SELECT * FROM lt_scheduled_tasks WHERE task_id = ?`
3073
+ ).get(taskId);
3074
+ return row ? mapRowToTask(row) : null;
3075
+ }
3076
+ async update(taskId, updates) {
3077
+ const setClauses = [];
3078
+ const values = [];
3079
+ if (updates.taskType !== void 0) {
3080
+ setClauses.push("task_type = ?");
3081
+ values.push(updates.taskType);
3082
+ }
3083
+ if (updates.tenantId !== void 0) {
3084
+ setClauses.push("tenant_id = ?");
3085
+ values.push(updates.tenantId);
3086
+ }
3087
+ if (updates.payload !== void 0) {
3088
+ setClauses.push("payload = ?");
3089
+ values.push(JSON.stringify(updates.payload));
3090
+ }
3091
+ if (updates.assistantId !== void 0) {
3092
+ setClauses.push("assistant_id = ?");
3093
+ values.push(updates.assistantId ?? null);
3094
+ }
3095
+ if (updates.threadId !== void 0) {
3096
+ setClauses.push("thread_id = ?");
3097
+ values.push(updates.threadId ?? null);
3098
+ }
3099
+ if (updates.executionType !== void 0) {
3100
+ setClauses.push("execution_type = ?");
3101
+ values.push(updates.executionType);
3102
+ }
3103
+ if (updates.executeAt !== void 0) {
3104
+ setClauses.push("execute_at = ?");
3105
+ values.push(updates.executeAt ? new Date(updates.executeAt).toISOString() : null);
3106
+ }
3107
+ if (updates.delayMs !== void 0) {
3108
+ setClauses.push("delay_ms = ?");
3109
+ values.push(updates.delayMs ?? null);
3110
+ }
3111
+ if (updates.cronExpression !== void 0) {
3112
+ setClauses.push("cron_expression = ?");
3113
+ values.push(updates.cronExpression ?? null);
3114
+ }
3115
+ if (updates.timezone !== void 0) {
3116
+ setClauses.push("timezone = ?");
3117
+ values.push(updates.timezone ?? null);
3118
+ }
3119
+ if (updates.nextRunAt !== void 0) {
3120
+ setClauses.push("next_run_at = ?");
3121
+ values.push(updates.nextRunAt ? new Date(updates.nextRunAt).toISOString() : null);
3122
+ }
3123
+ if (updates.lastRunAt !== void 0) {
3124
+ setClauses.push("last_run_at = ?");
3125
+ values.push(updates.lastRunAt ? new Date(updates.lastRunAt).toISOString() : null);
3126
+ }
3127
+ if (updates.status !== void 0) {
3128
+ setClauses.push("status = ?");
3129
+ values.push(updates.status);
3130
+ }
3131
+ if (updates.runCount !== void 0) {
3132
+ setClauses.push("run_count = ?");
3133
+ values.push(updates.runCount);
3134
+ }
3135
+ if (updates.maxRuns !== void 0) {
3136
+ setClauses.push("max_runs = ?");
3137
+ values.push(updates.maxRuns ?? null);
3138
+ }
3139
+ if (updates.retryCount !== void 0) {
3140
+ setClauses.push("retry_count = ?");
3141
+ values.push(updates.retryCount);
3142
+ }
3143
+ if (updates.maxRetries !== void 0) {
3144
+ setClauses.push("max_retries = ?");
3145
+ values.push(updates.maxRetries);
3146
+ }
3147
+ if (updates.lastError !== void 0) {
3148
+ setClauses.push("last_error = ?");
3149
+ values.push(updates.lastError ?? null);
3150
+ }
3151
+ if (updates.expiresAt !== void 0) {
3152
+ setClauses.push("expires_at = ?");
3153
+ values.push(updates.expiresAt ? new Date(updates.expiresAt).toISOString() : null);
3154
+ }
3155
+ if (updates.metadata !== void 0) {
3156
+ setClauses.push("metadata = ?");
3157
+ values.push(updates.metadata ? JSON.stringify(updates.metadata) : null);
3158
+ }
3159
+ if (setClauses.length === 0) return;
3160
+ setClauses.push("updated_at = ?");
3161
+ values.push((/* @__PURE__ */ new Date()).toISOString());
3162
+ values.push(taskId);
3163
+ this.db.prepare(
3164
+ `UPDATE lt_scheduled_tasks SET ${setClauses.join(", ")} WHERE task_id = ?`
3165
+ ).run(...values);
3166
+ }
3167
+ async delete(taskId) {
3168
+ this.db.prepare(`DELETE FROM lt_scheduled_tasks WHERE task_id = ?`).run(taskId);
3169
+ }
3170
+ async getActiveTasks() {
3171
+ const rows = this.db.prepare(
3172
+ `SELECT * FROM lt_scheduled_tasks WHERE status IN ('pending', 'paused') ORDER BY created_at ASC`
3173
+ ).all();
3174
+ return rows.map(mapRowToTask);
3175
+ }
3176
+ async getTasksByType(taskType) {
3177
+ const rows = this.db.prepare(
3178
+ `SELECT * FROM lt_scheduled_tasks WHERE task_type = ? ORDER BY created_at DESC`
3179
+ ).all(taskType);
3180
+ return rows.map(mapRowToTask);
3181
+ }
3182
+ async getTasksByStatus(status) {
3183
+ const rows = this.db.prepare(
3184
+ `SELECT * FROM lt_scheduled_tasks WHERE status = ? ORDER BY created_at DESC`
3185
+ ).all(status);
3186
+ return rows.map(mapRowToTask);
3187
+ }
3188
+ async getTasksByExecutionType(executionType) {
3189
+ const rows = this.db.prepare(
3190
+ `SELECT * FROM lt_scheduled_tasks WHERE execution_type = ? ORDER BY created_at DESC`
3191
+ ).all(executionType);
3192
+ return rows.map(mapRowToTask);
3193
+ }
3194
+ async getTasksByAssistantId(assistantId) {
3195
+ const rows = this.db.prepare(
3196
+ `SELECT * FROM lt_scheduled_tasks WHERE assistant_id = ? ORDER BY created_at DESC`
3197
+ ).all(assistantId);
3198
+ return rows.map(mapRowToTask);
3199
+ }
3200
+ async getTasksByThreadId(threadId) {
3201
+ const rows = this.db.prepare(
3202
+ `SELECT * FROM lt_scheduled_tasks WHERE thread_id = ? ORDER BY created_at DESC`
3203
+ ).all(threadId);
3204
+ return rows.map(mapRowToTask);
3205
+ }
3206
+ async getAllTasks(filters) {
3207
+ const conditions = [];
3208
+ const values = [];
3209
+ if (filters?.tenantId !== void 0) {
3210
+ conditions.push("tenant_id = ?");
3211
+ values.push(filters.tenantId);
3212
+ }
3213
+ if (filters?.status !== void 0) {
3214
+ conditions.push("status = ?");
3215
+ values.push(filters.status);
3216
+ }
3217
+ if (filters?.executionType !== void 0) {
3218
+ conditions.push("execution_type = ?");
3219
+ values.push(filters.executionType);
3220
+ }
3221
+ if (filters?.taskType !== void 0) {
3222
+ conditions.push("task_type = ?");
3223
+ values.push(filters.taskType);
3224
+ }
3225
+ if (filters?.assistantId !== void 0) {
3226
+ conditions.push("assistant_id = ?");
3227
+ values.push(filters.assistantId);
3228
+ }
3229
+ if (filters?.threadId !== void 0) {
3230
+ conditions.push("thread_id = ?");
3231
+ values.push(filters.threadId);
3232
+ }
3233
+ let query = `SELECT * FROM lt_scheduled_tasks`;
3234
+ if (conditions.length > 0) query += ` WHERE ${conditions.join(" AND ")}`;
3235
+ query += ` ORDER BY created_at DESC`;
3236
+ if (filters?.limit !== void 0) {
3237
+ query += ` LIMIT ?`;
3238
+ values.push(filters.limit);
3239
+ }
3240
+ if (filters?.offset !== void 0) {
3241
+ query += ` OFFSET ?`;
3242
+ values.push(filters.offset);
3243
+ }
3244
+ const rows = this.db.prepare(query).all(...values);
3245
+ return rows.map(mapRowToTask);
3246
+ }
3247
+ async countTasks(filters) {
3248
+ const conditions = [];
3249
+ const values = [];
3250
+ if (filters?.tenantId !== void 0) {
3251
+ conditions.push("tenant_id = ?");
3252
+ values.push(filters.tenantId);
3253
+ }
3254
+ if (filters?.status !== void 0) {
3255
+ conditions.push("status = ?");
3256
+ values.push(filters.status);
3257
+ }
3258
+ if (filters?.executionType !== void 0) {
3259
+ conditions.push("execution_type = ?");
3260
+ values.push(filters.executionType);
3261
+ }
3262
+ if (filters?.taskType !== void 0) {
3263
+ conditions.push("task_type = ?");
3264
+ values.push(filters.taskType);
3265
+ }
3266
+ if (filters?.assistantId !== void 0) {
3267
+ conditions.push("assistant_id = ?");
3268
+ values.push(filters.assistantId);
3269
+ }
3270
+ if (filters?.threadId !== void 0) {
3271
+ conditions.push("thread_id = ?");
3272
+ values.push(filters.threadId);
3273
+ }
3274
+ let query = `SELECT COUNT(*) as count FROM lt_scheduled_tasks`;
3275
+ if (conditions.length > 0) query += ` WHERE ${conditions.join(" AND ")}`;
3276
+ const row = this.db.prepare(query).get(...values);
3277
+ return row.count;
3278
+ }
3279
+ async deleteOldTasks(olderThanMs) {
3280
+ const cutoff = new Date(Date.now() - olderThanMs).toISOString();
3281
+ const result = this.db.prepare(
3282
+ `DELETE FROM lt_scheduled_tasks WHERE status IN ('completed', 'cancelled', 'failed') AND updated_at < ?`
3283
+ ).run(cutoff);
3284
+ return result.changes;
3285
+ }
3286
+ };
3287
+ function mapRowToTask(row) {
3288
+ return {
3289
+ taskId: row.task_id,
3290
+ taskType: row.task_type,
3291
+ tenantId: row.tenant_id,
3292
+ payload: JSON.parse(row.payload || "{}"),
3293
+ assistantId: row.assistant_id ?? void 0,
3294
+ threadId: row.thread_id ?? void 0,
3295
+ executionType: row.execution_type,
3296
+ executeAt: row.execute_at ? new Date(row.execute_at).getTime() : void 0,
3297
+ delayMs: row.delay_ms ?? void 0,
3298
+ cronExpression: row.cron_expression ?? void 0,
3299
+ timezone: row.timezone ?? void 0,
3300
+ nextRunAt: row.next_run_at ? new Date(row.next_run_at).getTime() : void 0,
3301
+ lastRunAt: row.last_run_at ? new Date(row.last_run_at).getTime() : void 0,
3302
+ status: row.status,
3303
+ runCount: row.run_count,
3304
+ maxRuns: row.max_runs ?? void 0,
3305
+ retryCount: row.retry_count,
3306
+ maxRetries: row.max_retries,
3307
+ lastError: row.last_error ?? void 0,
3308
+ createdAt: new Date(row.created_at).getTime(),
3309
+ updatedAt: new Date(row.updated_at).getTime(),
3310
+ expiresAt: row.expires_at ? new Date(row.expires_at).getTime() : void 0,
3311
+ metadata: row.metadata ? JSON.parse(row.metadata) : void 0
3312
+ };
3313
+ }
3314
+
3315
+ // src/createLocalStoreConfig.ts
3316
+ async function createLocalStoreConfig(options = {}) {
3317
+ const dbPath = options.dbPath || "~/.axiom/lattice.db";
3318
+ const db = await initDatabase({ dbPath });
3319
+ return {
3320
+ thread: new LocalThreadStore(db),
3321
+ assistant: new LocalAssistantStore(db),
3322
+ workspace: new LocalWorkspaceStore(db),
3323
+ project: new LocalProjectStore(db),
3324
+ user: new LocalUserStore(db),
3325
+ tenant: new LocalTenantStore(db),
3326
+ userTenantLink: new LocalUserTenantLinkStore(db),
3327
+ database: new LocalDatabaseConfigStore(db),
3328
+ metrics: new LocalMetricsServerConfigStore(db),
3329
+ mcp: new LocalMcpServerConfigStore(db),
3330
+ workflowTracking: new LocalWorkflowTrackingStore(db),
3331
+ eval: new LocalEvalStore(db),
3332
+ channelBinding: new LocalChannelBindingStore(db),
3333
+ channelInstallation: new LocalChannelInstallationStore(db),
3334
+ a2aApiKey: new LocalA2AApiKeyStore(db),
3335
+ threadMessageQueue: new LocalThreadMessageQueueStore(db),
3336
+ skill: new LocalSkillStore(db),
3337
+ schedule: new LocalScheduleStorage(db),
3338
+ checkpoint: import_langgraph_checkpoint_sqlite.SqliteSaver.fromConnString(dbPath)
3339
+ };
3340
+ }
3341
+ // Annotate the CommonJS export names for ESM import in node:
3342
+ 0 && (module.exports = {
3343
+ DatabaseWrapper,
3344
+ LocalA2AApiKeyStore,
3345
+ LocalAssistantStore,
3346
+ LocalChannelBindingStore,
3347
+ LocalChannelInstallationStore,
3348
+ LocalDatabaseConfigStore,
3349
+ LocalEvalStore,
3350
+ LocalMcpServerConfigStore,
3351
+ LocalMetricsServerConfigStore,
3352
+ LocalProjectStore,
3353
+ LocalScheduleStorage,
3354
+ LocalSkillStore,
3355
+ LocalTenantStore,
3356
+ LocalThreadMessageQueueStore,
3357
+ LocalThreadStore,
3358
+ LocalUserStore,
3359
+ LocalUserTenantLinkStore,
3360
+ LocalWorkflowTrackingStore,
3361
+ LocalWorkspaceStore,
3362
+ RunResult,
3363
+ StatementWrapper,
3364
+ closeDatabase,
3365
+ createLocalStoreConfig,
3366
+ ensureTable,
3367
+ getDatabase,
3368
+ initDatabase,
3369
+ nowISO,
3370
+ parseISO
3371
+ });
3372
+ //# sourceMappingURL=index.js.map