@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
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
} from "@axiom-lattice/protocols";
|
|
11
11
|
import { MigrationManager } from "../migrations/migration";
|
|
12
12
|
import { createAssistantsTable } from "../migrations/assistant_migrations";
|
|
13
|
+
import { addAssistantTenantId } from "../migrations/assistant_tenant_migration";
|
|
14
|
+
import { changeAssistantPrimaryKey } from "../migrations/assistant_pk_migration";
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
17
|
* PostgreSQL AssistantStore options
|
|
@@ -30,12 +32,16 @@ export interface PostgreSQLAssistantStoreOptions {
|
|
|
30
32
|
|
|
31
33
|
/**
|
|
32
34
|
* PostgreSQL implementation of AssistantStore
|
|
35
|
+
*
|
|
36
|
+
* Features:
|
|
37
|
+
* - Multi-tenant isolation via tenant_id
|
|
33
38
|
*/
|
|
34
39
|
export class PostgreSQLAssistantStore implements AssistantStore {
|
|
35
40
|
private pool: Pool;
|
|
36
41
|
private migrationManager: MigrationManager;
|
|
37
42
|
private initialized: boolean = false;
|
|
38
43
|
private ownsPool: boolean = true;
|
|
44
|
+
private initPromise: Promise<void> | null = null;
|
|
39
45
|
|
|
40
46
|
constructor(options: PostgreSQLAssistantStoreOptions) {
|
|
41
47
|
// Create Pool from config
|
|
@@ -47,6 +53,8 @@ export class PostgreSQLAssistantStore implements AssistantStore {
|
|
|
47
53
|
|
|
48
54
|
this.migrationManager = new MigrationManager(this.pool);
|
|
49
55
|
this.migrationManager.register(createAssistantsTable);
|
|
56
|
+
this.migrationManager.register(addAssistantTenantId);
|
|
57
|
+
this.migrationManager.register(changeAssistantPrimaryKey);
|
|
50
58
|
|
|
51
59
|
// Auto-migrate by default
|
|
52
60
|
if (options.autoMigrate !== false) {
|
|
@@ -59,24 +67,38 @@ export class PostgreSQLAssistantStore implements AssistantStore {
|
|
|
59
67
|
|
|
60
68
|
/**
|
|
61
69
|
* Initialize the store and run migrations
|
|
70
|
+
* Uses a promise-based lock to prevent concurrent initialization
|
|
62
71
|
*/
|
|
63
72
|
async initialize(): Promise<void> {
|
|
64
73
|
if (this.initialized) {
|
|
65
74
|
return;
|
|
66
75
|
}
|
|
67
76
|
|
|
68
|
-
|
|
69
|
-
|
|
77
|
+
if (this.initPromise) {
|
|
78
|
+
return this.initPromise;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
this.initPromise = (async () => {
|
|
82
|
+
try {
|
|
83
|
+
await this.migrationManager.migrate();
|
|
84
|
+
this.initialized = true;
|
|
85
|
+
} finally {
|
|
86
|
+
this.initPromise = null;
|
|
87
|
+
}
|
|
88
|
+
})();
|
|
89
|
+
|
|
90
|
+
return this.initPromise;
|
|
70
91
|
}
|
|
71
92
|
|
|
72
93
|
/**
|
|
73
|
-
* Get all assistants
|
|
94
|
+
* Get all assistants for a tenant
|
|
74
95
|
*/
|
|
75
|
-
async getAllAssistants(): Promise<Assistant[]> {
|
|
96
|
+
async getAllAssistants(tenantId: string): Promise<Assistant[]> {
|
|
76
97
|
await this.ensureInitialized();
|
|
77
98
|
|
|
78
99
|
const result = await this.pool.query<{
|
|
79
100
|
id: string;
|
|
101
|
+
tenant_id: string;
|
|
80
102
|
name: string;
|
|
81
103
|
description: string | null;
|
|
82
104
|
graph_definition: any;
|
|
@@ -84,10 +106,12 @@ export class PostgreSQLAssistantStore implements AssistantStore {
|
|
|
84
106
|
updated_at: Date;
|
|
85
107
|
}>(
|
|
86
108
|
`
|
|
87
|
-
SELECT id, name, description, graph_definition, created_at, updated_at
|
|
109
|
+
SELECT id, tenant_id, name, description, graph_definition, created_at, updated_at
|
|
88
110
|
FROM lattice_assistants
|
|
111
|
+
WHERE tenant_id = $1
|
|
89
112
|
ORDER BY created_at DESC
|
|
90
|
-
|
|
113
|
+
`,
|
|
114
|
+
[tenantId]
|
|
91
115
|
);
|
|
92
116
|
|
|
93
117
|
return result.rows.map(this.mapRowToAssistant);
|
|
@@ -96,11 +120,12 @@ export class PostgreSQLAssistantStore implements AssistantStore {
|
|
|
96
120
|
/**
|
|
97
121
|
* Get assistant by ID
|
|
98
122
|
*/
|
|
99
|
-
async getAssistantById(id: string): Promise<Assistant | null> {
|
|
123
|
+
async getAssistantById(tenantId: string, id: string): Promise<Assistant | null> {
|
|
100
124
|
await this.ensureInitialized();
|
|
101
125
|
|
|
102
126
|
const result = await this.pool.query<{
|
|
103
127
|
id: string;
|
|
128
|
+
tenant_id: string;
|
|
104
129
|
name: string;
|
|
105
130
|
description: string | null;
|
|
106
131
|
graph_definition: any;
|
|
@@ -108,11 +133,11 @@ export class PostgreSQLAssistantStore implements AssistantStore {
|
|
|
108
133
|
updated_at: Date;
|
|
109
134
|
}>(
|
|
110
135
|
`
|
|
111
|
-
SELECT id, name, description, graph_definition, created_at, updated_at
|
|
136
|
+
SELECT id, tenant_id, name, description, graph_definition, created_at, updated_at
|
|
112
137
|
FROM lattice_assistants
|
|
113
|
-
WHERE id = $
|
|
138
|
+
WHERE tenant_id = $1 AND id = $2
|
|
114
139
|
`,
|
|
115
|
-
[id]
|
|
140
|
+
[tenantId, id]
|
|
116
141
|
);
|
|
117
142
|
|
|
118
143
|
if (result.rows.length === 0) {
|
|
@@ -126,6 +151,7 @@ export class PostgreSQLAssistantStore implements AssistantStore {
|
|
|
126
151
|
* Create a new assistant
|
|
127
152
|
*/
|
|
128
153
|
async createAssistant(
|
|
154
|
+
tenantId: string,
|
|
129
155
|
id: string,
|
|
130
156
|
data: CreateAssistantRequest
|
|
131
157
|
): Promise<Assistant> {
|
|
@@ -135,9 +161,10 @@ export class PostgreSQLAssistantStore implements AssistantStore {
|
|
|
135
161
|
|
|
136
162
|
await this.pool.query(
|
|
137
163
|
`
|
|
138
|
-
INSERT INTO lattice_assistants (id, name, description, graph_definition, created_at, updated_at)
|
|
139
|
-
VALUES ($1, $2, $3, $4, $5, $6)
|
|
164
|
+
INSERT INTO lattice_assistants (id, tenant_id, name, description, graph_definition, created_at, updated_at)
|
|
165
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
140
166
|
ON CONFLICT (id) DO UPDATE SET
|
|
167
|
+
tenant_id = EXCLUDED.tenant_id,
|
|
141
168
|
name = EXCLUDED.name,
|
|
142
169
|
description = EXCLUDED.description,
|
|
143
170
|
graph_definition = EXCLUDED.graph_definition,
|
|
@@ -145,6 +172,7 @@ export class PostgreSQLAssistantStore implements AssistantStore {
|
|
|
145
172
|
`,
|
|
146
173
|
[
|
|
147
174
|
id,
|
|
175
|
+
tenantId,
|
|
148
176
|
data.name,
|
|
149
177
|
data.description || null,
|
|
150
178
|
JSON.stringify(data.graphDefinition),
|
|
@@ -155,6 +183,7 @@ export class PostgreSQLAssistantStore implements AssistantStore {
|
|
|
155
183
|
|
|
156
184
|
return {
|
|
157
185
|
id,
|
|
186
|
+
tenantId,
|
|
158
187
|
name: data.name,
|
|
159
188
|
description: data.description,
|
|
160
189
|
graphDefinition: data.graphDefinition,
|
|
@@ -167,13 +196,14 @@ export class PostgreSQLAssistantStore implements AssistantStore {
|
|
|
167
196
|
* Update an existing assistant
|
|
168
197
|
*/
|
|
169
198
|
async updateAssistant(
|
|
199
|
+
tenantId: string,
|
|
170
200
|
id: string,
|
|
171
201
|
updates: Partial<CreateAssistantRequest>
|
|
172
202
|
): Promise<Assistant | null> {
|
|
173
203
|
await this.ensureInitialized();
|
|
174
204
|
|
|
175
205
|
// Get existing assistant
|
|
176
|
-
const existing = await this.getAssistantById(id);
|
|
206
|
+
const existing = await this.getAssistantById(tenantId, id);
|
|
177
207
|
if (!existing) {
|
|
178
208
|
return null;
|
|
179
209
|
}
|
|
@@ -207,34 +237,35 @@ export class PostgreSQLAssistantStore implements AssistantStore {
|
|
|
207
237
|
updateFields.push(`updated_at = $${paramIndex++}`);
|
|
208
238
|
updateValues.push(new Date());
|
|
209
239
|
|
|
210
|
-
// Add id for WHERE clause
|
|
240
|
+
// Add tenant_id and id for WHERE clause
|
|
241
|
+
updateValues.push(tenantId);
|
|
211
242
|
updateValues.push(id);
|
|
212
243
|
|
|
213
244
|
await this.pool.query(
|
|
214
245
|
`
|
|
215
246
|
UPDATE lattice_assistants
|
|
216
247
|
SET ${updateFields.join(", ")}
|
|
217
|
-
WHERE id = $${paramIndex}
|
|
248
|
+
WHERE tenant_id = $${paramIndex++} AND id = $${paramIndex}
|
|
218
249
|
`,
|
|
219
250
|
updateValues
|
|
220
251
|
);
|
|
221
252
|
|
|
222
253
|
// Return updated assistant
|
|
223
|
-
return await this.getAssistantById(id);
|
|
254
|
+
return await this.getAssistantById(tenantId, id);
|
|
224
255
|
}
|
|
225
256
|
|
|
226
257
|
/**
|
|
227
258
|
* Delete an assistant by ID
|
|
228
259
|
*/
|
|
229
|
-
async deleteAssistant(id: string): Promise<boolean> {
|
|
260
|
+
async deleteAssistant(tenantId: string, id: string): Promise<boolean> {
|
|
230
261
|
await this.ensureInitialized();
|
|
231
262
|
|
|
232
263
|
const result = await this.pool.query(
|
|
233
264
|
`
|
|
234
265
|
DELETE FROM lattice_assistants
|
|
235
|
-
WHERE id = $
|
|
266
|
+
WHERE tenant_id = $1 AND id = $2
|
|
236
267
|
`,
|
|
237
|
-
[id]
|
|
268
|
+
[tenantId, id]
|
|
238
269
|
);
|
|
239
270
|
|
|
240
271
|
return result.rowCount !== null && result.rowCount > 0;
|
|
@@ -243,16 +274,16 @@ export class PostgreSQLAssistantStore implements AssistantStore {
|
|
|
243
274
|
/**
|
|
244
275
|
* Check if assistant exists
|
|
245
276
|
*/
|
|
246
|
-
async hasAssistant(id: string): Promise<boolean> {
|
|
277
|
+
async hasAssistant(tenantId: string, id: string): Promise<boolean> {
|
|
247
278
|
await this.ensureInitialized();
|
|
248
279
|
|
|
249
280
|
const result = await this.pool.query(
|
|
250
281
|
`
|
|
251
282
|
SELECT 1 FROM lattice_assistants
|
|
252
|
-
WHERE id = $
|
|
283
|
+
WHERE tenant_id = $1 AND id = $2
|
|
253
284
|
LIMIT 1
|
|
254
285
|
`,
|
|
255
|
-
[id]
|
|
286
|
+
[tenantId, id]
|
|
256
287
|
);
|
|
257
288
|
|
|
258
289
|
return result.rows.length > 0;
|
|
@@ -282,6 +313,7 @@ export class PostgreSQLAssistantStore implements AssistantStore {
|
|
|
282
313
|
*/
|
|
283
314
|
private mapRowToAssistant(row: {
|
|
284
315
|
id: string;
|
|
316
|
+
tenant_id: string;
|
|
285
317
|
name: string;
|
|
286
318
|
description: string | null;
|
|
287
319
|
graph_definition: any;
|
|
@@ -290,6 +322,7 @@ export class PostgreSQLAssistantStore implements AssistantStore {
|
|
|
290
322
|
}): Assistant {
|
|
291
323
|
return {
|
|
292
324
|
id: row.id,
|
|
325
|
+
tenantId: row.tenant_id,
|
|
293
326
|
name: row.name,
|
|
294
327
|
description: row.description || undefined,
|
|
295
328
|
graphDefinition:
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from "@axiom-lattice/protocols";
|
|
15
15
|
import { MigrationManager } from "../migrations/migration";
|
|
16
16
|
import { createScheduledTasksTable } from "../migrations/schedule_migrations";
|
|
17
|
+
import { addScheduleTenantId } from "../migrations/schedule_tenant_migration";
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* PostgreSQL ScheduleStorage options
|
|
@@ -78,6 +79,7 @@ export class PostgreSQLScheduleStorage implements ScheduleStorage {
|
|
|
78
79
|
|
|
79
80
|
this.migrationManager = new MigrationManager(this.pool);
|
|
80
81
|
this.migrationManager.register(createScheduledTasksTable);
|
|
82
|
+
this.migrationManager.register(addScheduleTenantId);
|
|
81
83
|
|
|
82
84
|
// Auto-migrate by default
|
|
83
85
|
if (options.autoMigrate !== false) {
|
|
@@ -424,6 +426,7 @@ export class PostgreSQLScheduleStorage implements ScheduleStorage {
|
|
|
424
426
|
* Get all tasks with optional filters
|
|
425
427
|
*/
|
|
426
428
|
async getAllTasks(filters?: {
|
|
429
|
+
tenantId?: string;
|
|
427
430
|
status?: ScheduledTaskStatus;
|
|
428
431
|
executionType?: ScheduleExecutionType;
|
|
429
432
|
taskType?: string;
|
|
@@ -438,6 +441,12 @@ export class PostgreSQLScheduleStorage implements ScheduleStorage {
|
|
|
438
441
|
const values: any[] = [];
|
|
439
442
|
let paramIndex = 1;
|
|
440
443
|
|
|
444
|
+
// Always filter by tenantId if provided
|
|
445
|
+
if (filters?.tenantId !== undefined) {
|
|
446
|
+
whereClauses.push(`tenant_id = $${paramIndex++}`);
|
|
447
|
+
values.push(filters.tenantId);
|
|
448
|
+
}
|
|
449
|
+
|
|
441
450
|
if (filters?.status !== undefined) {
|
|
442
451
|
whereClauses.push(`status = $${paramIndex++}`);
|
|
443
452
|
values.push(filters.status);
|
|
@@ -483,6 +492,7 @@ export class PostgreSQLScheduleStorage implements ScheduleStorage {
|
|
|
483
492
|
* Count tasks with optional filters
|
|
484
493
|
*/
|
|
485
494
|
async countTasks(filters?: {
|
|
495
|
+
tenantId?: string;
|
|
486
496
|
status?: ScheduledTaskStatus;
|
|
487
497
|
executionType?: ScheduleExecutionType;
|
|
488
498
|
taskType?: string;
|
|
@@ -495,6 +505,12 @@ export class PostgreSQLScheduleStorage implements ScheduleStorage {
|
|
|
495
505
|
const values: any[] = [];
|
|
496
506
|
let paramIndex = 1;
|
|
497
507
|
|
|
508
|
+
// Always filter by tenantId if provided
|
|
509
|
+
if (filters?.tenantId !== undefined) {
|
|
510
|
+
whereClauses.push(`tenant_id = $${paramIndex++}`);
|
|
511
|
+
values.push(filters.tenantId);
|
|
512
|
+
}
|
|
513
|
+
|
|
498
514
|
if (filters?.status !== undefined) {
|
|
499
515
|
whereClauses.push(`status = $${paramIndex++}`);
|
|
500
516
|
values.push(filters.status);
|