@axiom-lattice/pg-stores 1.0.21 → 1.0.23
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +17 -0
- package/dist/index.d.mts +126 -58
- package/dist/index.d.ts +126 -58
- package/dist/index.js +551 -135
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +544 -135
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +7 -0
- package/src/migrations/assistant_migrations.ts +4 -2
- package/src/migrations/assistant_pk_migration.ts +101 -0
- package/src/migrations/assistant_tenant_migration.ts +29 -0
- package/src/migrations/schedule_tenant_migration.ts +75 -0
- package/src/migrations/skill_pk_migration.ts +97 -0
- package/src/migrations/skill_tenant_migration.ts +55 -0
- package/src/migrations/thread_pk_migration.ts +99 -0
- package/src/migrations/thread_tenant_migration.ts +55 -0
- package/src/stores/PostgreSQLAssistantStore.ts +55 -22
- package/src/stores/PostgreSQLScheduleStorage.ts +16 -0
- package/src/stores/PostgreSQLSkillStore.ts +146 -103
- package/src/stores/PostgreSQLThreadStore.ts +40 -30
package/dist/index.mjs
CHANGED
|
@@ -175,9 +175,111 @@ var createThreadsTable = {
|
|
|
175
175
|
}
|
|
176
176
|
};
|
|
177
177
|
|
|
178
|
+
// src/migrations/thread_tenant_migration.ts
|
|
179
|
+
var addThreadTenantId = {
|
|
180
|
+
version: 15,
|
|
181
|
+
name: "add_thread_tenant_id",
|
|
182
|
+
up: async (client) => {
|
|
183
|
+
await client.query(`
|
|
184
|
+
ALTER TABLE lattice_threads
|
|
185
|
+
ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(255) DEFAULT 'default'
|
|
186
|
+
`);
|
|
187
|
+
await client.query(`
|
|
188
|
+
UPDATE lattice_threads
|
|
189
|
+
SET tenant_id = 'default'
|
|
190
|
+
WHERE tenant_id IS NULL
|
|
191
|
+
`);
|
|
192
|
+
await client.query(`
|
|
193
|
+
ALTER TABLE lattice_threads
|
|
194
|
+
ALTER COLUMN tenant_id SET NOT NULL
|
|
195
|
+
`);
|
|
196
|
+
await client.query(`
|
|
197
|
+
ALTER TABLE lattice_threads
|
|
198
|
+
ALTER COLUMN tenant_id DROP DEFAULT
|
|
199
|
+
`);
|
|
200
|
+
await client.query(`
|
|
201
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_threads_tenant_id
|
|
202
|
+
ON lattice_threads(tenant_id)
|
|
203
|
+
`);
|
|
204
|
+
},
|
|
205
|
+
down: async (client) => {
|
|
206
|
+
await client.query(
|
|
207
|
+
"DROP INDEX IF EXISTS idx_lattice_threads_tenant_id"
|
|
208
|
+
);
|
|
209
|
+
await client.query(
|
|
210
|
+
"ALTER TABLE lattice_threads DROP COLUMN IF EXISTS tenant_id"
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// src/migrations/thread_pk_migration.ts
|
|
216
|
+
var changeThreadPrimaryKey = {
|
|
217
|
+
version: 19,
|
|
218
|
+
name: "change_thread_primary_key",
|
|
219
|
+
up: async (client) => {
|
|
220
|
+
const tableExists = await client.query(`
|
|
221
|
+
SELECT EXISTS (
|
|
222
|
+
SELECT FROM information_schema.tables
|
|
223
|
+
WHERE table_name = 'lattice_threads'
|
|
224
|
+
)
|
|
225
|
+
`);
|
|
226
|
+
if (!tableExists.rows[0].exists) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
const pkResult = await client.query(`
|
|
230
|
+
SELECT a.attname as column_name
|
|
231
|
+
FROM pg_index i
|
|
232
|
+
JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
|
|
233
|
+
WHERE i.indrelid = 'lattice_threads'::regclass
|
|
234
|
+
AND i.indisprimary
|
|
235
|
+
`);
|
|
236
|
+
const pkColumns = pkResult.rows.map((row) => row.column_name);
|
|
237
|
+
if (pkColumns.includes("tenant_id") && pkColumns.includes("id") && pkColumns.length === 2) {
|
|
238
|
+
console.log("Primary key already correct (id, tenant_id)");
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (pkColumns.includes("id") && pkColumns.includes("assistant_id")) {
|
|
242
|
+
console.log("Changing primary key from (id, assistant_id) to (id, tenant_id)");
|
|
243
|
+
const tenantIdExists = await client.query(`
|
|
244
|
+
SELECT EXISTS (
|
|
245
|
+
SELECT FROM information_schema.columns
|
|
246
|
+
WHERE table_name = 'lattice_threads'
|
|
247
|
+
AND column_name = 'tenant_id'
|
|
248
|
+
)
|
|
249
|
+
`);
|
|
250
|
+
if (!tenantIdExists.rows[0].exists) {
|
|
251
|
+
await client.query(`
|
|
252
|
+
ALTER TABLE lattice_threads
|
|
253
|
+
ADD COLUMN tenant_id VARCHAR(255) DEFAULT 'default'
|
|
254
|
+
`);
|
|
255
|
+
}
|
|
256
|
+
await client.query(`
|
|
257
|
+
UPDATE lattice_threads
|
|
258
|
+
SET tenant_id = 'default'
|
|
259
|
+
WHERE tenant_id IS NULL
|
|
260
|
+
`);
|
|
261
|
+
await client.query(`
|
|
262
|
+
ALTER TABLE lattice_threads
|
|
263
|
+
ALTER COLUMN tenant_id SET NOT NULL
|
|
264
|
+
`);
|
|
265
|
+
await client.query(`
|
|
266
|
+
ALTER TABLE lattice_threads
|
|
267
|
+
DROP CONSTRAINT IF EXISTS lattice_threads_pkey
|
|
268
|
+
`);
|
|
269
|
+
await client.query(`
|
|
270
|
+
ALTER TABLE lattice_threads
|
|
271
|
+
ADD PRIMARY KEY (id, tenant_id)
|
|
272
|
+
`);
|
|
273
|
+
console.log("Primary key changed successfully to (id, tenant_id)");
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
down: async (client) => {
|
|
277
|
+
console.warn("Down migration for changeThreadPrimaryKey is not supported");
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
178
281
|
// src/stores/PostgreSQLThreadStore.ts
|
|
179
282
|
var PostgreSQLThreadStore = class {
|
|
180
|
-
// Promise-based lock to prevent concurrent initialization
|
|
181
283
|
constructor(options) {
|
|
182
284
|
this.initialized = false;
|
|
183
285
|
this.ownsPool = true;
|
|
@@ -189,6 +291,8 @@ var PostgreSQLThreadStore = class {
|
|
|
189
291
|
}
|
|
190
292
|
this.migrationManager = new MigrationManager(this.pool);
|
|
191
293
|
this.migrationManager.register(createThreadsTable);
|
|
294
|
+
this.migrationManager.register(addThreadTenantId);
|
|
295
|
+
this.migrationManager.register(changeThreadPrimaryKey);
|
|
192
296
|
if (options.autoMigrate !== false) {
|
|
193
297
|
this.initialize().catch((error) => {
|
|
194
298
|
console.error("Failed to initialize PostgreSQLThreadStore:", error);
|
|
@@ -227,33 +331,33 @@ var PostgreSQLThreadStore = class {
|
|
|
227
331
|
return this.initPromise;
|
|
228
332
|
}
|
|
229
333
|
/**
|
|
230
|
-
* Get all threads for a specific assistant
|
|
334
|
+
* Get all threads for a specific tenant and assistant
|
|
231
335
|
*/
|
|
232
|
-
async getThreadsByAssistantId(assistantId) {
|
|
336
|
+
async getThreadsByAssistantId(tenantId, assistantId) {
|
|
233
337
|
await this.ensureInitialized();
|
|
234
338
|
const result = await this.pool.query(
|
|
235
339
|
`
|
|
236
|
-
SELECT id, assistant_id, metadata, created_at, updated_at
|
|
340
|
+
SELECT id, tenant_id, assistant_id, metadata, created_at, updated_at
|
|
237
341
|
FROM lattice_threads
|
|
238
|
-
WHERE assistant_id = $
|
|
342
|
+
WHERE tenant_id = $1 AND assistant_id = $2
|
|
239
343
|
ORDER BY created_at DESC
|
|
240
344
|
`,
|
|
241
|
-
[assistantId]
|
|
345
|
+
[tenantId, assistantId]
|
|
242
346
|
);
|
|
243
347
|
return result.rows.map(this.mapRowToThread);
|
|
244
348
|
}
|
|
245
349
|
/**
|
|
246
|
-
* Get a thread by ID for a specific
|
|
350
|
+
* Get a thread by ID for a specific tenant
|
|
247
351
|
*/
|
|
248
|
-
async getThreadById(
|
|
352
|
+
async getThreadById(tenantId, threadId) {
|
|
249
353
|
await this.ensureInitialized();
|
|
250
354
|
const result = await this.pool.query(
|
|
251
355
|
`
|
|
252
|
-
SELECT id, assistant_id, metadata, created_at, updated_at
|
|
356
|
+
SELECT id, tenant_id, assistant_id, metadata, created_at, updated_at
|
|
253
357
|
FROM lattice_threads
|
|
254
|
-
WHERE
|
|
358
|
+
WHERE tenant_id = $1 AND id = $2
|
|
255
359
|
`,
|
|
256
|
-
[
|
|
360
|
+
[tenantId, threadId]
|
|
257
361
|
);
|
|
258
362
|
if (result.rows.length === 0) {
|
|
259
363
|
return void 0;
|
|
@@ -261,24 +365,26 @@ var PostgreSQLThreadStore = class {
|
|
|
261
365
|
return this.mapRowToThread(result.rows[0]);
|
|
262
366
|
}
|
|
263
367
|
/**
|
|
264
|
-
* Create a new thread for
|
|
368
|
+
* Create a new thread for a tenant and assistant
|
|
265
369
|
*/
|
|
266
|
-
async createThread(assistantId, threadId, data) {
|
|
370
|
+
async createThread(tenantId, assistantId, threadId, data) {
|
|
267
371
|
await this.ensureInitialized();
|
|
268
372
|
const now = /* @__PURE__ */ new Date();
|
|
269
373
|
const metadata = data.metadata || {};
|
|
270
374
|
await this.pool.query(
|
|
271
375
|
`
|
|
272
|
-
INSERT INTO lattice_threads (id, assistant_id, metadata, created_at, updated_at)
|
|
273
|
-
VALUES ($1, $2, $3, $4, $5)
|
|
274
|
-
ON CONFLICT (id,
|
|
376
|
+
INSERT INTO lattice_threads (id, tenant_id, assistant_id, metadata, created_at, updated_at)
|
|
377
|
+
VALUES ($1, $2, $3, $4, $5, $6)
|
|
378
|
+
ON CONFLICT (id, tenant_id) DO UPDATE SET
|
|
379
|
+
assistant_id = EXCLUDED.assistant_id,
|
|
275
380
|
metadata = EXCLUDED.metadata,
|
|
276
381
|
updated_at = EXCLUDED.updated_at
|
|
277
382
|
`,
|
|
278
|
-
[threadId, assistantId, JSON.stringify(metadata), now, now]
|
|
383
|
+
[threadId, tenantId, assistantId, JSON.stringify(metadata), now, now]
|
|
279
384
|
);
|
|
280
385
|
return {
|
|
281
386
|
id: threadId,
|
|
387
|
+
tenantId,
|
|
282
388
|
assistantId,
|
|
283
389
|
metadata,
|
|
284
390
|
createdAt: now,
|
|
@@ -288,9 +394,9 @@ var PostgreSQLThreadStore = class {
|
|
|
288
394
|
/**
|
|
289
395
|
* Update an existing thread
|
|
290
396
|
*/
|
|
291
|
-
async updateThread(
|
|
397
|
+
async updateThread(tenantId, threadId, updates) {
|
|
292
398
|
await this.ensureInitialized();
|
|
293
|
-
const existing = await this.getThreadById(
|
|
399
|
+
const existing = await this.getThreadById(tenantId, threadId);
|
|
294
400
|
if (!existing) {
|
|
295
401
|
return null;
|
|
296
402
|
}
|
|
@@ -303,9 +409,9 @@ var PostgreSQLThreadStore = class {
|
|
|
303
409
|
`
|
|
304
410
|
UPDATE lattice_threads
|
|
305
411
|
SET metadata = $1, updated_at = $2
|
|
306
|
-
WHERE
|
|
412
|
+
WHERE tenant_id = $3 AND id = $4
|
|
307
413
|
`,
|
|
308
|
-
[JSON.stringify(updatedMetadata), now,
|
|
414
|
+
[JSON.stringify(updatedMetadata), now, tenantId, threadId]
|
|
309
415
|
);
|
|
310
416
|
return {
|
|
311
417
|
...existing,
|
|
@@ -316,29 +422,29 @@ var PostgreSQLThreadStore = class {
|
|
|
316
422
|
/**
|
|
317
423
|
* Delete a thread by ID
|
|
318
424
|
*/
|
|
319
|
-
async deleteThread(
|
|
425
|
+
async deleteThread(tenantId, threadId) {
|
|
320
426
|
await this.ensureInitialized();
|
|
321
427
|
const result = await this.pool.query(
|
|
322
428
|
`
|
|
323
429
|
DELETE FROM lattice_threads
|
|
324
|
-
WHERE
|
|
430
|
+
WHERE tenant_id = $1 AND id = $2
|
|
325
431
|
`,
|
|
326
|
-
[
|
|
432
|
+
[tenantId, threadId]
|
|
327
433
|
);
|
|
328
434
|
return result.rowCount !== null && result.rowCount > 0;
|
|
329
435
|
}
|
|
330
436
|
/**
|
|
331
437
|
* Check if thread exists
|
|
332
438
|
*/
|
|
333
|
-
async hasThread(
|
|
439
|
+
async hasThread(tenantId, threadId) {
|
|
334
440
|
await this.ensureInitialized();
|
|
335
441
|
const result = await this.pool.query(
|
|
336
442
|
`
|
|
337
443
|
SELECT 1 FROM lattice_threads
|
|
338
|
-
WHERE
|
|
444
|
+
WHERE tenant_id = $1 AND id = $2
|
|
339
445
|
LIMIT 1
|
|
340
446
|
`,
|
|
341
|
-
[
|
|
447
|
+
[tenantId, threadId]
|
|
342
448
|
);
|
|
343
449
|
return result.rows.length > 0;
|
|
344
450
|
}
|
|
@@ -356,6 +462,7 @@ var PostgreSQLThreadStore = class {
|
|
|
356
462
|
mapRowToThread(row) {
|
|
357
463
|
return {
|
|
358
464
|
id: row.id,
|
|
465
|
+
tenantId: row.tenant_id,
|
|
359
466
|
assistantId: row.assistant_id,
|
|
360
467
|
metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata) : row.metadata || {},
|
|
361
468
|
createdAt: row.created_at,
|
|
@@ -374,12 +481,14 @@ var createAssistantsTable = {
|
|
|
374
481
|
up: async (client) => {
|
|
375
482
|
await client.query(`
|
|
376
483
|
CREATE TABLE IF NOT EXISTS lattice_assistants (
|
|
377
|
-
id VARCHAR(255)
|
|
484
|
+
id VARCHAR(255) NOT NULL,
|
|
485
|
+
tenant_id VARCHAR(255) NOT NULL DEFAULT 'default',
|
|
378
486
|
name VARCHAR(255) NOT NULL,
|
|
379
487
|
description TEXT,
|
|
380
488
|
graph_definition JSONB NOT NULL,
|
|
381
489
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
382
|
-
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
490
|
+
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
491
|
+
PRIMARY KEY (tenant_id, id)
|
|
383
492
|
)
|
|
384
493
|
`);
|
|
385
494
|
await client.query(`
|
|
@@ -400,11 +509,95 @@ var createAssistantsTable = {
|
|
|
400
509
|
}
|
|
401
510
|
};
|
|
402
511
|
|
|
512
|
+
// src/migrations/assistant_tenant_migration.ts
|
|
513
|
+
var addAssistantTenantId = {
|
|
514
|
+
version: 14,
|
|
515
|
+
name: "add_assistant_tenant_id",
|
|
516
|
+
up: async (client) => {
|
|
517
|
+
await client.query(`
|
|
518
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_assistants_tenant_id
|
|
519
|
+
ON lattice_assistants(tenant_id)
|
|
520
|
+
`);
|
|
521
|
+
},
|
|
522
|
+
down: async (client) => {
|
|
523
|
+
await client.query(
|
|
524
|
+
"DROP INDEX IF EXISTS idx_lattice_assistants_tenant_id"
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
// src/migrations/assistant_pk_migration.ts
|
|
530
|
+
var changeAssistantPrimaryKey = {
|
|
531
|
+
version: 15,
|
|
532
|
+
name: "change_assistant_primary_key",
|
|
533
|
+
up: async (client) => {
|
|
534
|
+
const tableExists = await client.query(`
|
|
535
|
+
SELECT EXISTS (
|
|
536
|
+
SELECT FROM information_schema.tables
|
|
537
|
+
WHERE table_name = 'lattice_assistants'
|
|
538
|
+
)
|
|
539
|
+
`);
|
|
540
|
+
if (!tableExists.rows[0].exists) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
const pkResult = await client.query(`
|
|
544
|
+
SELECT a.attname as column_name
|
|
545
|
+
FROM pg_index i
|
|
546
|
+
JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
|
|
547
|
+
WHERE i.indrelid = 'lattice_assistants'::regclass
|
|
548
|
+
AND i.indisprimary
|
|
549
|
+
`);
|
|
550
|
+
const pkColumns = pkResult.rows.map((row) => row.column_name);
|
|
551
|
+
if (pkColumns.includes("tenant_id") && pkColumns.includes("id")) {
|
|
552
|
+
console.log("Primary key already correct (tenant_id, id)");
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
if (pkColumns.length === 1 && pkColumns[0] === "id") {
|
|
556
|
+
console.log("Changing primary key from (id) to (tenant_id, id)");
|
|
557
|
+
const tenantIdExists = await client.query(`
|
|
558
|
+
SELECT EXISTS (
|
|
559
|
+
SELECT FROM information_schema.columns
|
|
560
|
+
WHERE table_name = 'lattice_assistants'
|
|
561
|
+
AND column_name = 'tenant_id'
|
|
562
|
+
)
|
|
563
|
+
`);
|
|
564
|
+
if (!tenantIdExists.rows[0].exists) {
|
|
565
|
+
await client.query(`
|
|
566
|
+
ALTER TABLE lattice_assistants
|
|
567
|
+
ADD COLUMN tenant_id VARCHAR(255) DEFAULT 'default'
|
|
568
|
+
`);
|
|
569
|
+
}
|
|
570
|
+
await client.query(`
|
|
571
|
+
UPDATE lattice_assistants
|
|
572
|
+
SET tenant_id = 'default'
|
|
573
|
+
WHERE tenant_id IS NULL
|
|
574
|
+
`);
|
|
575
|
+
await client.query(`
|
|
576
|
+
ALTER TABLE lattice_assistants
|
|
577
|
+
ALTER COLUMN tenant_id SET NOT NULL
|
|
578
|
+
`);
|
|
579
|
+
await client.query(`
|
|
580
|
+
ALTER TABLE lattice_assistants
|
|
581
|
+
DROP CONSTRAINT IF EXISTS lattice_assistants_pkey
|
|
582
|
+
`);
|
|
583
|
+
await client.query(`
|
|
584
|
+
ALTER TABLE lattice_assistants
|
|
585
|
+
ADD PRIMARY KEY (tenant_id, id)
|
|
586
|
+
`);
|
|
587
|
+
console.log("Primary key changed successfully to (tenant_id, id)");
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
down: async (client) => {
|
|
591
|
+
console.warn("Down migration for changeAssistantPrimaryKey is not supported");
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
|
|
403
595
|
// src/stores/PostgreSQLAssistantStore.ts
|
|
404
596
|
var PostgreSQLAssistantStore = class {
|
|
405
597
|
constructor(options) {
|
|
406
598
|
this.initialized = false;
|
|
407
599
|
this.ownsPool = true;
|
|
600
|
+
this.initPromise = null;
|
|
408
601
|
if (typeof options.poolConfig === "string") {
|
|
409
602
|
this.pool = new Pool2({ connectionString: options.poolConfig });
|
|
410
603
|
} else {
|
|
@@ -412,6 +605,8 @@ var PostgreSQLAssistantStore = class {
|
|
|
412
605
|
}
|
|
413
606
|
this.migrationManager = new MigrationManager(this.pool);
|
|
414
607
|
this.migrationManager.register(createAssistantsTable);
|
|
608
|
+
this.migrationManager.register(addAssistantTenantId);
|
|
609
|
+
this.migrationManager.register(changeAssistantPrimaryKey);
|
|
415
610
|
if (options.autoMigrate !== false) {
|
|
416
611
|
this.initialize().catch((error) => {
|
|
417
612
|
console.error("Failed to initialize PostgreSQLAssistantStore:", error);
|
|
@@ -421,40 +616,53 @@ var PostgreSQLAssistantStore = class {
|
|
|
421
616
|
}
|
|
422
617
|
/**
|
|
423
618
|
* Initialize the store and run migrations
|
|
619
|
+
* Uses a promise-based lock to prevent concurrent initialization
|
|
424
620
|
*/
|
|
425
621
|
async initialize() {
|
|
426
622
|
if (this.initialized) {
|
|
427
623
|
return;
|
|
428
624
|
}
|
|
429
|
-
|
|
430
|
-
|
|
625
|
+
if (this.initPromise) {
|
|
626
|
+
return this.initPromise;
|
|
627
|
+
}
|
|
628
|
+
this.initPromise = (async () => {
|
|
629
|
+
try {
|
|
630
|
+
await this.migrationManager.migrate();
|
|
631
|
+
this.initialized = true;
|
|
632
|
+
} finally {
|
|
633
|
+
this.initPromise = null;
|
|
634
|
+
}
|
|
635
|
+
})();
|
|
636
|
+
return this.initPromise;
|
|
431
637
|
}
|
|
432
638
|
/**
|
|
433
|
-
* Get all assistants
|
|
639
|
+
* Get all assistants for a tenant
|
|
434
640
|
*/
|
|
435
|
-
async getAllAssistants() {
|
|
641
|
+
async getAllAssistants(tenantId) {
|
|
436
642
|
await this.ensureInitialized();
|
|
437
643
|
const result = await this.pool.query(
|
|
438
644
|
`
|
|
439
|
-
SELECT id, name, description, graph_definition, created_at, updated_at
|
|
645
|
+
SELECT id, tenant_id, name, description, graph_definition, created_at, updated_at
|
|
440
646
|
FROM lattice_assistants
|
|
647
|
+
WHERE tenant_id = $1
|
|
441
648
|
ORDER BY created_at DESC
|
|
442
|
-
|
|
649
|
+
`,
|
|
650
|
+
[tenantId]
|
|
443
651
|
);
|
|
444
652
|
return result.rows.map(this.mapRowToAssistant);
|
|
445
653
|
}
|
|
446
654
|
/**
|
|
447
655
|
* Get assistant by ID
|
|
448
656
|
*/
|
|
449
|
-
async getAssistantById(id) {
|
|
657
|
+
async getAssistantById(tenantId, id) {
|
|
450
658
|
await this.ensureInitialized();
|
|
451
659
|
const result = await this.pool.query(
|
|
452
660
|
`
|
|
453
|
-
SELECT id, name, description, graph_definition, created_at, updated_at
|
|
661
|
+
SELECT id, tenant_id, name, description, graph_definition, created_at, updated_at
|
|
454
662
|
FROM lattice_assistants
|
|
455
|
-
WHERE id = $
|
|
663
|
+
WHERE tenant_id = $1 AND id = $2
|
|
456
664
|
`,
|
|
457
|
-
[id]
|
|
665
|
+
[tenantId, id]
|
|
458
666
|
);
|
|
459
667
|
if (result.rows.length === 0) {
|
|
460
668
|
return null;
|
|
@@ -464,14 +672,15 @@ var PostgreSQLAssistantStore = class {
|
|
|
464
672
|
/**
|
|
465
673
|
* Create a new assistant
|
|
466
674
|
*/
|
|
467
|
-
async createAssistant(id, data) {
|
|
675
|
+
async createAssistant(tenantId, id, data) {
|
|
468
676
|
await this.ensureInitialized();
|
|
469
677
|
const now = /* @__PURE__ */ new Date();
|
|
470
678
|
await this.pool.query(
|
|
471
679
|
`
|
|
472
|
-
INSERT INTO lattice_assistants (id, name, description, graph_definition, created_at, updated_at)
|
|
473
|
-
VALUES ($1, $2, $3, $4, $5, $6)
|
|
680
|
+
INSERT INTO lattice_assistants (id, tenant_id, name, description, graph_definition, created_at, updated_at)
|
|
681
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
474
682
|
ON CONFLICT (id) DO UPDATE SET
|
|
683
|
+
tenant_id = EXCLUDED.tenant_id,
|
|
475
684
|
name = EXCLUDED.name,
|
|
476
685
|
description = EXCLUDED.description,
|
|
477
686
|
graph_definition = EXCLUDED.graph_definition,
|
|
@@ -479,6 +688,7 @@ var PostgreSQLAssistantStore = class {
|
|
|
479
688
|
`,
|
|
480
689
|
[
|
|
481
690
|
id,
|
|
691
|
+
tenantId,
|
|
482
692
|
data.name,
|
|
483
693
|
data.description || null,
|
|
484
694
|
JSON.stringify(data.graphDefinition),
|
|
@@ -488,6 +698,7 @@ var PostgreSQLAssistantStore = class {
|
|
|
488
698
|
);
|
|
489
699
|
return {
|
|
490
700
|
id,
|
|
701
|
+
tenantId,
|
|
491
702
|
name: data.name,
|
|
492
703
|
description: data.description,
|
|
493
704
|
graphDefinition: data.graphDefinition,
|
|
@@ -498,9 +709,9 @@ var PostgreSQLAssistantStore = class {
|
|
|
498
709
|
/**
|
|
499
710
|
* Update an existing assistant
|
|
500
711
|
*/
|
|
501
|
-
async updateAssistant(id, updates) {
|
|
712
|
+
async updateAssistant(tenantId, id, updates) {
|
|
502
713
|
await this.ensureInitialized();
|
|
503
|
-
const existing = await this.getAssistantById(id);
|
|
714
|
+
const existing = await this.getAssistantById(tenantId, id);
|
|
504
715
|
if (!existing) {
|
|
505
716
|
return null;
|
|
506
717
|
}
|
|
@@ -524,43 +735,44 @@ var PostgreSQLAssistantStore = class {
|
|
|
524
735
|
}
|
|
525
736
|
updateFields.push(`updated_at = $${paramIndex++}`);
|
|
526
737
|
updateValues.push(/* @__PURE__ */ new Date());
|
|
738
|
+
updateValues.push(tenantId);
|
|
527
739
|
updateValues.push(id);
|
|
528
740
|
await this.pool.query(
|
|
529
741
|
`
|
|
530
742
|
UPDATE lattice_assistants
|
|
531
743
|
SET ${updateFields.join(", ")}
|
|
532
|
-
WHERE id = $${paramIndex}
|
|
744
|
+
WHERE tenant_id = $${paramIndex++} AND id = $${paramIndex}
|
|
533
745
|
`,
|
|
534
746
|
updateValues
|
|
535
747
|
);
|
|
536
|
-
return await this.getAssistantById(id);
|
|
748
|
+
return await this.getAssistantById(tenantId, id);
|
|
537
749
|
}
|
|
538
750
|
/**
|
|
539
751
|
* Delete an assistant by ID
|
|
540
752
|
*/
|
|
541
|
-
async deleteAssistant(id) {
|
|
753
|
+
async deleteAssistant(tenantId, id) {
|
|
542
754
|
await this.ensureInitialized();
|
|
543
755
|
const result = await this.pool.query(
|
|
544
756
|
`
|
|
545
757
|
DELETE FROM lattice_assistants
|
|
546
|
-
WHERE id = $
|
|
758
|
+
WHERE tenant_id = $1 AND id = $2
|
|
547
759
|
`,
|
|
548
|
-
[id]
|
|
760
|
+
[tenantId, id]
|
|
549
761
|
);
|
|
550
762
|
return result.rowCount !== null && result.rowCount > 0;
|
|
551
763
|
}
|
|
552
764
|
/**
|
|
553
765
|
* Check if assistant exists
|
|
554
766
|
*/
|
|
555
|
-
async hasAssistant(id) {
|
|
767
|
+
async hasAssistant(tenantId, id) {
|
|
556
768
|
await this.ensureInitialized();
|
|
557
769
|
const result = await this.pool.query(
|
|
558
770
|
`
|
|
559
771
|
SELECT 1 FROM lattice_assistants
|
|
560
|
-
WHERE id = $
|
|
772
|
+
WHERE tenant_id = $1 AND id = $2
|
|
561
773
|
LIMIT 1
|
|
562
774
|
`,
|
|
563
|
-
[id]
|
|
775
|
+
[tenantId, id]
|
|
564
776
|
);
|
|
565
777
|
return result.rows.length > 0;
|
|
566
778
|
}
|
|
@@ -587,6 +799,7 @@ var PostgreSQLAssistantStore = class {
|
|
|
587
799
|
mapRowToAssistant(row) {
|
|
588
800
|
return {
|
|
589
801
|
id: row.id,
|
|
802
|
+
tenantId: row.tenant_id,
|
|
590
803
|
name: row.name,
|
|
591
804
|
description: row.description || void 0,
|
|
592
805
|
graphDefinition: typeof row.graph_definition === "string" ? JSON.parse(row.graph_definition) : row.graph_definition,
|
|
@@ -709,6 +922,59 @@ var createScheduledTasksTable = {
|
|
|
709
922
|
}
|
|
710
923
|
};
|
|
711
924
|
|
|
925
|
+
// src/migrations/schedule_tenant_migration.ts
|
|
926
|
+
var addScheduleTenantId = {
|
|
927
|
+
version: 18,
|
|
928
|
+
name: "add_schedule_tenant_id",
|
|
929
|
+
up: async (client) => {
|
|
930
|
+
await client.query(`
|
|
931
|
+
ALTER TABLE lattice_scheduled_tasks
|
|
932
|
+
ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(255) DEFAULT 'default'
|
|
933
|
+
`);
|
|
934
|
+
await client.query(`
|
|
935
|
+
UPDATE lattice_scheduled_tasks
|
|
936
|
+
SET tenant_id = 'default'
|
|
937
|
+
WHERE tenant_id IS NULL
|
|
938
|
+
`);
|
|
939
|
+
await client.query(`
|
|
940
|
+
ALTER TABLE lattice_scheduled_tasks
|
|
941
|
+
ALTER COLUMN tenant_id SET NOT NULL
|
|
942
|
+
`);
|
|
943
|
+
await client.query(`
|
|
944
|
+
ALTER TABLE lattice_scheduled_tasks
|
|
945
|
+
ALTER COLUMN tenant_id DROP DEFAULT
|
|
946
|
+
`);
|
|
947
|
+
await client.query(`
|
|
948
|
+
CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_tenant_id
|
|
949
|
+
ON lattice_scheduled_tasks(tenant_id)
|
|
950
|
+
`);
|
|
951
|
+
await client.query(`
|
|
952
|
+
CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_tenant_assistant
|
|
953
|
+
ON lattice_scheduled_tasks(tenant_id, assistant_id)
|
|
954
|
+
WHERE assistant_id IS NOT NULL
|
|
955
|
+
`);
|
|
956
|
+
await client.query(`
|
|
957
|
+
CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_tenant_thread
|
|
958
|
+
ON lattice_scheduled_tasks(tenant_id, thread_id)
|
|
959
|
+
WHERE thread_id IS NOT NULL
|
|
960
|
+
`);
|
|
961
|
+
},
|
|
962
|
+
down: async (client) => {
|
|
963
|
+
await client.query(
|
|
964
|
+
"DROP INDEX IF EXISTS idx_scheduled_tasks_tenant_thread"
|
|
965
|
+
);
|
|
966
|
+
await client.query(
|
|
967
|
+
"DROP INDEX IF EXISTS idx_scheduled_tasks_tenant_assistant"
|
|
968
|
+
);
|
|
969
|
+
await client.query(
|
|
970
|
+
"DROP INDEX IF EXISTS idx_scheduled_tasks_tenant_id"
|
|
971
|
+
);
|
|
972
|
+
await client.query(
|
|
973
|
+
"ALTER TABLE lattice_scheduled_tasks DROP COLUMN IF EXISTS tenant_id"
|
|
974
|
+
);
|
|
975
|
+
}
|
|
976
|
+
};
|
|
977
|
+
|
|
712
978
|
// src/stores/PostgreSQLScheduleStorage.ts
|
|
713
979
|
var PostgreSQLScheduleStorage = class {
|
|
714
980
|
constructor(options) {
|
|
@@ -720,6 +986,7 @@ var PostgreSQLScheduleStorage = class {
|
|
|
720
986
|
}
|
|
721
987
|
this.migrationManager = new MigrationManager(this.pool);
|
|
722
988
|
this.migrationManager.register(createScheduledTasksTable);
|
|
989
|
+
this.migrationManager.register(addScheduleTenantId);
|
|
723
990
|
if (options.autoMigrate !== false) {
|
|
724
991
|
this.initialize().catch((error) => {
|
|
725
992
|
console.error("Failed to initialize PostgreSQLScheduleStorage:", error);
|
|
@@ -1016,6 +1283,10 @@ var PostgreSQLScheduleStorage = class {
|
|
|
1016
1283
|
const whereClauses = [];
|
|
1017
1284
|
const values = [];
|
|
1018
1285
|
let paramIndex = 1;
|
|
1286
|
+
if (filters?.tenantId !== void 0) {
|
|
1287
|
+
whereClauses.push(`tenant_id = $${paramIndex++}`);
|
|
1288
|
+
values.push(filters.tenantId);
|
|
1289
|
+
}
|
|
1019
1290
|
if (filters?.status !== void 0) {
|
|
1020
1291
|
whereClauses.push(`status = $${paramIndex++}`);
|
|
1021
1292
|
values.push(filters.status);
|
|
@@ -1060,6 +1331,10 @@ var PostgreSQLScheduleStorage = class {
|
|
|
1060
1331
|
const whereClauses = [];
|
|
1061
1332
|
const values = [];
|
|
1062
1333
|
let paramIndex = 1;
|
|
1334
|
+
if (filters?.tenantId !== void 0) {
|
|
1335
|
+
whereClauses.push(`tenant_id = $${paramIndex++}`);
|
|
1336
|
+
values.push(filters.tenantId);
|
|
1337
|
+
}
|
|
1063
1338
|
if (filters?.status !== void 0) {
|
|
1064
1339
|
whereClauses.push(`status = $${paramIndex++}`);
|
|
1065
1340
|
values.push(filters.status);
|
|
@@ -1192,11 +1467,115 @@ var createSkillsTable = {
|
|
|
1192
1467
|
}
|
|
1193
1468
|
};
|
|
1194
1469
|
|
|
1470
|
+
// src/migrations/skill_tenant_migration.ts
|
|
1471
|
+
var addSkillTenantId = {
|
|
1472
|
+
version: 16,
|
|
1473
|
+
name: "add_skill_tenant_id",
|
|
1474
|
+
up: async (client) => {
|
|
1475
|
+
await client.query(`
|
|
1476
|
+
ALTER TABLE lattice_skills
|
|
1477
|
+
ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(255) DEFAULT 'default'
|
|
1478
|
+
`);
|
|
1479
|
+
await client.query(`
|
|
1480
|
+
UPDATE lattice_skills
|
|
1481
|
+
SET tenant_id = 'default'
|
|
1482
|
+
WHERE tenant_id IS NULL
|
|
1483
|
+
`);
|
|
1484
|
+
await client.query(`
|
|
1485
|
+
ALTER TABLE lattice_skills
|
|
1486
|
+
ALTER COLUMN tenant_id SET NOT NULL
|
|
1487
|
+
`);
|
|
1488
|
+
await client.query(`
|
|
1489
|
+
ALTER TABLE lattice_skills
|
|
1490
|
+
ALTER COLUMN tenant_id DROP DEFAULT
|
|
1491
|
+
`);
|
|
1492
|
+
await client.query(`
|
|
1493
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_skills_tenant_id
|
|
1494
|
+
ON lattice_skills(tenant_id)
|
|
1495
|
+
`);
|
|
1496
|
+
},
|
|
1497
|
+
down: async (client) => {
|
|
1498
|
+
await client.query(
|
|
1499
|
+
"DROP INDEX IF EXISTS idx_lattice_skills_tenant_id"
|
|
1500
|
+
);
|
|
1501
|
+
await client.query(
|
|
1502
|
+
"ALTER TABLE lattice_skills DROP COLUMN IF EXISTS tenant_id"
|
|
1503
|
+
);
|
|
1504
|
+
}
|
|
1505
|
+
};
|
|
1506
|
+
|
|
1507
|
+
// src/migrations/skill_pk_migration.ts
|
|
1508
|
+
var changeSkillPrimaryKey = {
|
|
1509
|
+
version: 17,
|
|
1510
|
+
name: "change_skill_primary_key",
|
|
1511
|
+
up: async (client) => {
|
|
1512
|
+
const tableExists = await client.query(`
|
|
1513
|
+
SELECT EXISTS (
|
|
1514
|
+
SELECT FROM information_schema.tables
|
|
1515
|
+
WHERE table_name = 'lattice_skills'
|
|
1516
|
+
)
|
|
1517
|
+
`);
|
|
1518
|
+
if (!tableExists.rows[0].exists) {
|
|
1519
|
+
return;
|
|
1520
|
+
}
|
|
1521
|
+
const pkResult = await client.query(`
|
|
1522
|
+
SELECT a.attname as column_name
|
|
1523
|
+
FROM pg_index i
|
|
1524
|
+
JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
|
|
1525
|
+
WHERE i.indrelid = 'lattice_skills'::regclass
|
|
1526
|
+
AND i.indisprimary
|
|
1527
|
+
`);
|
|
1528
|
+
const pkColumns = pkResult.rows.map((row) => row.column_name);
|
|
1529
|
+
if (pkColumns.includes("tenant_id") && pkColumns.includes("id")) {
|
|
1530
|
+
console.log("Skill table primary key already correct (tenant_id, id)");
|
|
1531
|
+
return;
|
|
1532
|
+
}
|
|
1533
|
+
if (pkColumns.length === 1 && pkColumns[0] === "id") {
|
|
1534
|
+
console.log("Changing skill table primary key from (id) to (tenant_id, id)");
|
|
1535
|
+
const tenantIdExists = await client.query(`
|
|
1536
|
+
SELECT EXISTS (
|
|
1537
|
+
SELECT FROM information_schema.columns
|
|
1538
|
+
WHERE table_name = 'lattice_skills'
|
|
1539
|
+
AND column_name = 'tenant_id'
|
|
1540
|
+
)
|
|
1541
|
+
`);
|
|
1542
|
+
if (!tenantIdExists.rows[0].exists) {
|
|
1543
|
+
await client.query(`
|
|
1544
|
+
ALTER TABLE lattice_skills
|
|
1545
|
+
ADD COLUMN tenant_id VARCHAR(255) DEFAULT 'default'
|
|
1546
|
+
`);
|
|
1547
|
+
}
|
|
1548
|
+
await client.query(`
|
|
1549
|
+
UPDATE lattice_skills
|
|
1550
|
+
SET tenant_id = 'default'
|
|
1551
|
+
WHERE tenant_id IS NULL
|
|
1552
|
+
`);
|
|
1553
|
+
await client.query(`
|
|
1554
|
+
ALTER TABLE lattice_skills
|
|
1555
|
+
ALTER COLUMN tenant_id SET NOT NULL
|
|
1556
|
+
`);
|
|
1557
|
+
await client.query(`
|
|
1558
|
+
ALTER TABLE lattice_skills
|
|
1559
|
+
DROP CONSTRAINT IF EXISTS lattice_skills_pkey
|
|
1560
|
+
`);
|
|
1561
|
+
await client.query(`
|
|
1562
|
+
ALTER TABLE lattice_skills
|
|
1563
|
+
ADD PRIMARY KEY (tenant_id, id)
|
|
1564
|
+
`);
|
|
1565
|
+
console.log("Skill table primary key changed successfully to (tenant_id, id)");
|
|
1566
|
+
}
|
|
1567
|
+
},
|
|
1568
|
+
down: async (client) => {
|
|
1569
|
+
console.warn("Down migration for changeSkillPrimaryKey is not supported");
|
|
1570
|
+
}
|
|
1571
|
+
};
|
|
1572
|
+
|
|
1195
1573
|
// src/stores/PostgreSQLSkillStore.ts
|
|
1196
1574
|
var PostgreSQLSkillStore = class {
|
|
1197
1575
|
constructor(options) {
|
|
1198
1576
|
this.initialized = false;
|
|
1199
1577
|
this.ownsPool = true;
|
|
1578
|
+
this.initPromise = null;
|
|
1200
1579
|
if (typeof options.poolConfig === "string") {
|
|
1201
1580
|
this.pool = new Pool4({ connectionString: options.poolConfig });
|
|
1202
1581
|
} else {
|
|
@@ -1204,6 +1583,8 @@ var PostgreSQLSkillStore = class {
|
|
|
1204
1583
|
}
|
|
1205
1584
|
this.migrationManager = new MigrationManager(this.pool);
|
|
1206
1585
|
this.migrationManager.register(createSkillsTable);
|
|
1586
|
+
this.migrationManager.register(addSkillTenantId);
|
|
1587
|
+
this.migrationManager.register(changeSkillPrimaryKey);
|
|
1207
1588
|
if (options.autoMigrate !== false) {
|
|
1208
1589
|
this.initialize().catch((error) => {
|
|
1209
1590
|
console.error("Failed to initialize PostgreSQLSkillStore:", error);
|
|
@@ -1211,28 +1592,32 @@ var PostgreSQLSkillStore = class {
|
|
|
1211
1592
|
});
|
|
1212
1593
|
}
|
|
1213
1594
|
}
|
|
1214
|
-
/**
|
|
1215
|
-
* Dispose resources and close the connection pool
|
|
1216
|
-
* Should be called when the store is no longer needed
|
|
1217
|
-
*/
|
|
1218
|
-
async dispose() {
|
|
1219
|
-
if (this.ownsPool && this.pool) {
|
|
1220
|
-
await this.pool.end();
|
|
1221
|
-
}
|
|
1222
|
-
}
|
|
1223
1595
|
/**
|
|
1224
1596
|
* Initialize the store and run migrations
|
|
1597
|
+
* Uses a promise-based lock to prevent concurrent initialization
|
|
1225
1598
|
*/
|
|
1226
1599
|
async initialize() {
|
|
1227
1600
|
if (this.initialized) {
|
|
1228
1601
|
return;
|
|
1229
1602
|
}
|
|
1230
|
-
|
|
1231
|
-
|
|
1603
|
+
if (this.initPromise) {
|
|
1604
|
+
return this.initPromise;
|
|
1605
|
+
}
|
|
1606
|
+
this.initPromise = (async () => {
|
|
1607
|
+
try {
|
|
1608
|
+
await this.migrationManager.migrate();
|
|
1609
|
+
this.initialized = true;
|
|
1610
|
+
} finally {
|
|
1611
|
+
this.initPromise = null;
|
|
1612
|
+
}
|
|
1613
|
+
})();
|
|
1614
|
+
return this.initPromise;
|
|
1615
|
+
}
|
|
1616
|
+
async dispose() {
|
|
1617
|
+
if (this.ownsPool && this.pool) {
|
|
1618
|
+
await this.pool.end();
|
|
1619
|
+
}
|
|
1232
1620
|
}
|
|
1233
|
-
/**
|
|
1234
|
-
* Ensure store is initialized
|
|
1235
|
-
*/
|
|
1236
1621
|
async ensureInitialized() {
|
|
1237
1622
|
if (!this.initialized) {
|
|
1238
1623
|
await this.initialize();
|
|
@@ -1244,43 +1629,46 @@ var PostgreSQLSkillStore = class {
|
|
|
1244
1629
|
mapRowToSkill(row) {
|
|
1245
1630
|
return {
|
|
1246
1631
|
id: row.id,
|
|
1632
|
+
tenantId: row.tenant_id,
|
|
1247
1633
|
name: row.name,
|
|
1248
1634
|
description: row.description,
|
|
1249
1635
|
license: row.license || void 0,
|
|
1250
1636
|
compatibility: row.compatibility || void 0,
|
|
1251
1637
|
metadata: row.metadata || {},
|
|
1252
1638
|
content: row.content || void 0,
|
|
1253
|
-
subSkills: Array.isArray(row.sub_skills)
|
|
1639
|
+
subSkills: Array.isArray(row.sub_skills) ? row.sub_skills : void 0,
|
|
1254
1640
|
createdAt: row.created_at,
|
|
1255
1641
|
updatedAt: row.updated_at
|
|
1256
1642
|
};
|
|
1257
1643
|
}
|
|
1258
1644
|
/**
|
|
1259
|
-
* Get all skills
|
|
1645
|
+
* Get all skills for a tenant
|
|
1260
1646
|
*/
|
|
1261
|
-
async getAllSkills() {
|
|
1647
|
+
async getAllSkills(tenantId) {
|
|
1262
1648
|
await this.ensureInitialized();
|
|
1263
1649
|
const result = await this.pool.query(
|
|
1264
1650
|
`
|
|
1265
|
-
SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
1651
|
+
SELECT id, tenant_id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
1266
1652
|
FROM lattice_skills
|
|
1653
|
+
WHERE tenant_id = $1
|
|
1267
1654
|
ORDER BY created_at DESC
|
|
1268
|
-
|
|
1655
|
+
`,
|
|
1656
|
+
[tenantId]
|
|
1269
1657
|
);
|
|
1270
1658
|
return result.rows.map(this.mapRowToSkill);
|
|
1271
1659
|
}
|
|
1272
1660
|
/**
|
|
1273
|
-
* Get skill by ID
|
|
1661
|
+
* Get skill by ID for a tenant
|
|
1274
1662
|
*/
|
|
1275
|
-
async getSkillById(id) {
|
|
1663
|
+
async getSkillById(tenantId, id) {
|
|
1276
1664
|
await this.ensureInitialized();
|
|
1277
1665
|
const result = await this.pool.query(
|
|
1278
1666
|
`
|
|
1279
|
-
SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
1667
|
+
SELECT id, tenant_id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
1280
1668
|
FROM lattice_skills
|
|
1281
|
-
WHERE id = $
|
|
1669
|
+
WHERE tenant_id = $1 AND id = $2
|
|
1282
1670
|
`,
|
|
1283
|
-
[id]
|
|
1671
|
+
[tenantId, id]
|
|
1284
1672
|
);
|
|
1285
1673
|
if (result.rows.length === 0) {
|
|
1286
1674
|
return null;
|
|
@@ -1288,17 +1676,17 @@ var PostgreSQLSkillStore = class {
|
|
|
1288
1676
|
return this.mapRowToSkill(result.rows[0]);
|
|
1289
1677
|
}
|
|
1290
1678
|
/**
|
|
1291
|
-
* Create a new skill
|
|
1679
|
+
* Create a new skill for a tenant
|
|
1292
1680
|
*/
|
|
1293
|
-
async createSkill(id, data) {
|
|
1681
|
+
async createSkill(tenantId, id, data) {
|
|
1294
1682
|
await this.ensureInitialized();
|
|
1295
1683
|
const now = /* @__PURE__ */ new Date();
|
|
1296
|
-
const metadata = data.metadata || {};
|
|
1297
1684
|
await this.pool.query(
|
|
1298
1685
|
`
|
|
1299
|
-
INSERT INTO lattice_skills (id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at)
|
|
1300
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
|
1686
|
+
INSERT INTO lattice_skills (id, tenant_id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at)
|
|
1687
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
|
|
1301
1688
|
ON CONFLICT (id) DO UPDATE SET
|
|
1689
|
+
tenant_id = EXCLUDED.tenant_id,
|
|
1302
1690
|
name = EXCLUDED.name,
|
|
1303
1691
|
description = EXCLUDED.description,
|
|
1304
1692
|
license = EXCLUDED.license,
|
|
@@ -1310,166 +1698,180 @@ var PostgreSQLSkillStore = class {
|
|
|
1310
1698
|
`,
|
|
1311
1699
|
[
|
|
1312
1700
|
id,
|
|
1701
|
+
tenantId,
|
|
1313
1702
|
data.name,
|
|
1314
1703
|
data.description,
|
|
1315
1704
|
data.license || null,
|
|
1316
1705
|
data.compatibility || null,
|
|
1317
|
-
JSON.stringify(metadata),
|
|
1706
|
+
JSON.stringify(data.metadata || {}),
|
|
1318
1707
|
data.content || null,
|
|
1319
1708
|
JSON.stringify(data.subSkills || []),
|
|
1320
1709
|
now,
|
|
1321
1710
|
now
|
|
1322
1711
|
]
|
|
1323
1712
|
);
|
|
1324
|
-
return
|
|
1713
|
+
return {
|
|
1714
|
+
id,
|
|
1715
|
+
tenantId,
|
|
1716
|
+
name: data.name,
|
|
1717
|
+
description: data.description,
|
|
1718
|
+
license: data.license,
|
|
1719
|
+
compatibility: data.compatibility,
|
|
1720
|
+
metadata: data.metadata || {},
|
|
1721
|
+
content: data.content,
|
|
1722
|
+
subSkills: data.subSkills,
|
|
1723
|
+
createdAt: now,
|
|
1724
|
+
updatedAt: now
|
|
1725
|
+
};
|
|
1325
1726
|
}
|
|
1326
1727
|
/**
|
|
1327
|
-
* Update an existing skill
|
|
1728
|
+
* Update an existing skill for a tenant
|
|
1328
1729
|
*/
|
|
1329
|
-
async updateSkill(id, updates) {
|
|
1730
|
+
async updateSkill(tenantId, id, updates) {
|
|
1330
1731
|
await this.ensureInitialized();
|
|
1732
|
+
const existing = await this.getSkillById(tenantId, id);
|
|
1733
|
+
if (!existing) {
|
|
1734
|
+
return null;
|
|
1735
|
+
}
|
|
1331
1736
|
const updateFields = [];
|
|
1332
|
-
const
|
|
1737
|
+
const updateValues = [];
|
|
1333
1738
|
let paramIndex = 1;
|
|
1334
1739
|
if (updates.name !== void 0) {
|
|
1335
1740
|
updateFields.push(`name = $${paramIndex++}`);
|
|
1336
|
-
|
|
1741
|
+
updateValues.push(updates.name);
|
|
1337
1742
|
}
|
|
1338
1743
|
if (updates.description !== void 0) {
|
|
1339
1744
|
updateFields.push(`description = $${paramIndex++}`);
|
|
1340
|
-
|
|
1745
|
+
updateValues.push(updates.description);
|
|
1341
1746
|
}
|
|
1342
1747
|
if (updates.license !== void 0) {
|
|
1343
1748
|
updateFields.push(`license = $${paramIndex++}`);
|
|
1344
|
-
|
|
1749
|
+
updateValues.push(updates.license || null);
|
|
1345
1750
|
}
|
|
1346
1751
|
if (updates.compatibility !== void 0) {
|
|
1347
1752
|
updateFields.push(`compatibility = $${paramIndex++}`);
|
|
1348
|
-
|
|
1753
|
+
updateValues.push(updates.compatibility || null);
|
|
1349
1754
|
}
|
|
1350
1755
|
if (updates.metadata !== void 0) {
|
|
1351
1756
|
updateFields.push(`metadata = $${paramIndex++}`);
|
|
1352
|
-
|
|
1757
|
+
updateValues.push(JSON.stringify(updates.metadata || {}));
|
|
1353
1758
|
}
|
|
1354
1759
|
if (updates.content !== void 0) {
|
|
1355
1760
|
updateFields.push(`content = $${paramIndex++}`);
|
|
1356
|
-
|
|
1761
|
+
updateValues.push(updates.content || null);
|
|
1357
1762
|
}
|
|
1358
1763
|
if (updates.subSkills !== void 0) {
|
|
1359
1764
|
updateFields.push(`sub_skills = $${paramIndex++}`);
|
|
1360
|
-
|
|
1765
|
+
updateValues.push(JSON.stringify(updates.subSkills || []));
|
|
1361
1766
|
}
|
|
1362
1767
|
if (updateFields.length === 0) {
|
|
1363
|
-
return
|
|
1768
|
+
return existing;
|
|
1364
1769
|
}
|
|
1365
1770
|
updateFields.push(`updated_at = $${paramIndex++}`);
|
|
1366
|
-
|
|
1367
|
-
|
|
1771
|
+
updateValues.push(/* @__PURE__ */ new Date());
|
|
1772
|
+
updateValues.push(tenantId);
|
|
1773
|
+
updateValues.push(id);
|
|
1368
1774
|
await this.pool.query(
|
|
1369
1775
|
`
|
|
1370
1776
|
UPDATE lattice_skills
|
|
1371
1777
|
SET ${updateFields.join(", ")}
|
|
1372
|
-
WHERE id = $${paramIndex}
|
|
1778
|
+
WHERE tenant_id = $${paramIndex++} AND id = $${paramIndex}
|
|
1373
1779
|
`,
|
|
1374
|
-
|
|
1780
|
+
updateValues
|
|
1375
1781
|
);
|
|
1376
|
-
return this.getSkillById(id);
|
|
1782
|
+
return await this.getSkillById(tenantId, id);
|
|
1377
1783
|
}
|
|
1378
1784
|
/**
|
|
1379
|
-
* Delete a skill by ID
|
|
1785
|
+
* Delete a skill by ID for a tenant
|
|
1380
1786
|
*/
|
|
1381
|
-
async deleteSkill(id) {
|
|
1787
|
+
async deleteSkill(tenantId, id) {
|
|
1382
1788
|
await this.ensureInitialized();
|
|
1383
1789
|
const result = await this.pool.query(
|
|
1384
1790
|
`
|
|
1385
1791
|
DELETE FROM lattice_skills
|
|
1386
|
-
WHERE id = $
|
|
1792
|
+
WHERE tenant_id = $1 AND id = $2
|
|
1387
1793
|
`,
|
|
1388
|
-
[id]
|
|
1794
|
+
[tenantId, id]
|
|
1389
1795
|
);
|
|
1390
1796
|
return result.rowCount !== null && result.rowCount > 0;
|
|
1391
1797
|
}
|
|
1392
1798
|
/**
|
|
1393
|
-
* Check if skill exists
|
|
1799
|
+
* Check if skill exists for a tenant
|
|
1394
1800
|
*/
|
|
1395
|
-
async hasSkill(id) {
|
|
1801
|
+
async hasSkill(tenantId, id) {
|
|
1396
1802
|
await this.ensureInitialized();
|
|
1397
1803
|
const result = await this.pool.query(
|
|
1398
1804
|
`
|
|
1399
|
-
SELECT
|
|
1400
|
-
|
|
1401
|
-
|
|
1805
|
+
SELECT 1 FROM lattice_skills
|
|
1806
|
+
WHERE tenant_id = $1 AND id = $2
|
|
1807
|
+
LIMIT 1
|
|
1402
1808
|
`,
|
|
1403
|
-
[id]
|
|
1809
|
+
[tenantId, id]
|
|
1404
1810
|
);
|
|
1405
|
-
return
|
|
1811
|
+
return result.rows.length > 0;
|
|
1406
1812
|
}
|
|
1407
1813
|
/**
|
|
1408
|
-
* Search skills by metadata
|
|
1814
|
+
* Search skills by metadata within a tenant
|
|
1409
1815
|
*/
|
|
1410
|
-
async searchByMetadata(metadataKey, metadataValue) {
|
|
1816
|
+
async searchByMetadata(tenantId, metadataKey, metadataValue) {
|
|
1411
1817
|
await this.ensureInitialized();
|
|
1412
1818
|
const result = await this.pool.query(
|
|
1413
1819
|
`
|
|
1414
|
-
SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
1820
|
+
SELECT id, tenant_id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
1415
1821
|
FROM lattice_skills
|
|
1416
|
-
WHERE
|
|
1822
|
+
WHERE tenant_id = $1 AND metadata ->> $2 = $3
|
|
1417
1823
|
ORDER BY created_at DESC
|
|
1418
1824
|
`,
|
|
1419
|
-
[metadataKey, metadataValue]
|
|
1825
|
+
[tenantId, metadataKey, metadataValue]
|
|
1420
1826
|
);
|
|
1421
1827
|
return result.rows.map(this.mapRowToSkill);
|
|
1422
1828
|
}
|
|
1423
1829
|
/**
|
|
1424
|
-
* Filter skills by compatibility
|
|
1830
|
+
* Filter skills by compatibility within a tenant
|
|
1425
1831
|
*/
|
|
1426
|
-
async filterByCompatibility(compatibility) {
|
|
1832
|
+
async filterByCompatibility(tenantId, compatibility) {
|
|
1427
1833
|
await this.ensureInitialized();
|
|
1428
1834
|
const result = await this.pool.query(
|
|
1429
1835
|
`
|
|
1430
|
-
SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
1836
|
+
SELECT id, tenant_id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
1431
1837
|
FROM lattice_skills
|
|
1432
|
-
WHERE compatibility = $
|
|
1838
|
+
WHERE tenant_id = $1 AND compatibility = $2
|
|
1433
1839
|
ORDER BY created_at DESC
|
|
1434
1840
|
`,
|
|
1435
|
-
[compatibility]
|
|
1841
|
+
[tenantId, compatibility]
|
|
1436
1842
|
);
|
|
1437
1843
|
return result.rows.map(this.mapRowToSkill);
|
|
1438
1844
|
}
|
|
1439
1845
|
/**
|
|
1440
|
-
* Filter skills by license
|
|
1846
|
+
* Filter skills by license within a tenant
|
|
1441
1847
|
*/
|
|
1442
|
-
async filterByLicense(license) {
|
|
1848
|
+
async filterByLicense(tenantId, license) {
|
|
1443
1849
|
await this.ensureInitialized();
|
|
1444
1850
|
const result = await this.pool.query(
|
|
1445
1851
|
`
|
|
1446
|
-
SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
1852
|
+
SELECT id, tenant_id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
1447
1853
|
FROM lattice_skills
|
|
1448
|
-
WHERE license = $
|
|
1854
|
+
WHERE tenant_id = $1 AND license = $2
|
|
1449
1855
|
ORDER BY created_at DESC
|
|
1450
1856
|
`,
|
|
1451
|
-
[license]
|
|
1857
|
+
[tenantId, license]
|
|
1452
1858
|
);
|
|
1453
1859
|
return result.rows.map(this.mapRowToSkill);
|
|
1454
1860
|
}
|
|
1455
1861
|
/**
|
|
1456
|
-
* Get sub-skills of a parent skill
|
|
1862
|
+
* Get sub-skills of a parent skill within a tenant
|
|
1863
|
+
* Note: This searches for skills that have the parent skill name in their subSkills array
|
|
1457
1864
|
*/
|
|
1458
|
-
async getSubSkills(parentSkillName) {
|
|
1865
|
+
async getSubSkills(tenantId, parentSkillName) {
|
|
1459
1866
|
await this.ensureInitialized();
|
|
1460
|
-
const parentSkill = await this.getSkillById(parentSkillName);
|
|
1461
|
-
if (!parentSkill || !parentSkill.subSkills || parentSkill.subSkills.length === 0) {
|
|
1462
|
-
return [];
|
|
1463
|
-
}
|
|
1464
|
-
const placeholders = parentSkill.subSkills.map((_, index) => `$${index + 1}`).join(", ");
|
|
1465
1867
|
const result = await this.pool.query(
|
|
1466
1868
|
`
|
|
1467
|
-
SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
1869
|
+
SELECT id, tenant_id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
1468
1870
|
FROM lattice_skills
|
|
1469
|
-
WHERE
|
|
1871
|
+
WHERE tenant_id = $1 AND sub_skills @> to_jsonb($2::text)
|
|
1470
1872
|
ORDER BY created_at DESC
|
|
1471
1873
|
`,
|
|
1472
|
-
|
|
1874
|
+
[tenantId, JSON.stringify([parentSkillName])]
|
|
1473
1875
|
);
|
|
1474
1876
|
return result.rows.map(this.mapRowToSkill);
|
|
1475
1877
|
}
|
|
@@ -3568,6 +3970,13 @@ export {
|
|
|
3568
3970
|
PostgreSQLUserStore,
|
|
3569
3971
|
PostgreSQLUserTenantLinkStore,
|
|
3570
3972
|
PostgreSQLWorkspaceStore,
|
|
3973
|
+
addAssistantTenantId,
|
|
3974
|
+
addScheduleTenantId,
|
|
3975
|
+
addSkillTenantId,
|
|
3976
|
+
addThreadTenantId,
|
|
3977
|
+
changeAssistantPrimaryKey,
|
|
3978
|
+
changeSkillPrimaryKey,
|
|
3979
|
+
changeThreadPrimaryKey,
|
|
3571
3980
|
createAssistantsTable,
|
|
3572
3981
|
createDatabaseConfigsTable,
|
|
3573
3982
|
createMcpServerConfigsTable,
|