@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 { createThreadsTable } from "../migrations/thread_migrations";
|
|
13
|
+
import { addThreadTenantId } from "../migrations/thread_tenant_migration";
|
|
14
|
+
import { changeThreadPrimaryKey } from "../migrations/thread_pk_migration";
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
17
|
* PostgreSQL ThreadStore options
|
|
@@ -30,13 +32,16 @@ export interface PostgreSQLThreadStoreOptions {
|
|
|
30
32
|
|
|
31
33
|
/**
|
|
32
34
|
* PostgreSQL implementation of ThreadStore
|
|
35
|
+
*
|
|
36
|
+
* Features:
|
|
37
|
+
* - Multi-tenant isolation via tenant_id
|
|
33
38
|
*/
|
|
34
39
|
export class PostgreSQLThreadStore implements ThreadStore {
|
|
35
40
|
private pool: Pool;
|
|
36
41
|
private migrationManager: MigrationManager;
|
|
37
42
|
private initialized: boolean = false;
|
|
38
43
|
private ownsPool: boolean = true;
|
|
39
|
-
private initPromise: Promise<void> | null = null;
|
|
44
|
+
private initPromise: Promise<void> | null = null;
|
|
40
45
|
|
|
41
46
|
constructor(options: PostgreSQLThreadStoreOptions) {
|
|
42
47
|
// Create Pool from config
|
|
@@ -48,6 +53,8 @@ export class PostgreSQLThreadStore implements ThreadStore {
|
|
|
48
53
|
|
|
49
54
|
this.migrationManager = new MigrationManager(this.pool);
|
|
50
55
|
this.migrationManager.register(createThreadsTable);
|
|
56
|
+
this.migrationManager.register(addThreadTenantId);
|
|
57
|
+
this.migrationManager.register(changeThreadPrimaryKey);
|
|
51
58
|
|
|
52
59
|
// Auto-migrate by default
|
|
53
60
|
if (options.autoMigrate !== false) {
|
|
@@ -73,23 +80,19 @@ export class PostgreSQLThreadStore implements ThreadStore {
|
|
|
73
80
|
* Uses a promise-based lock to prevent concurrent initialization
|
|
74
81
|
*/
|
|
75
82
|
async initialize(): Promise<void> {
|
|
76
|
-
// If already initialized, return immediately
|
|
77
83
|
if (this.initialized) {
|
|
78
84
|
return;
|
|
79
85
|
}
|
|
80
86
|
|
|
81
|
-
// If initialization is in progress, wait for it
|
|
82
87
|
if (this.initPromise) {
|
|
83
88
|
return this.initPromise;
|
|
84
89
|
}
|
|
85
90
|
|
|
86
|
-
// Start initialization and store the promise
|
|
87
91
|
this.initPromise = (async () => {
|
|
88
92
|
try {
|
|
89
93
|
await this.migrationManager.migrate();
|
|
90
94
|
this.initialized = true;
|
|
91
95
|
} finally {
|
|
92
|
-
// Clear the promise after completion (success or failure)
|
|
93
96
|
this.initPromise = null;
|
|
94
97
|
}
|
|
95
98
|
})();
|
|
@@ -98,52 +101,54 @@ export class PostgreSQLThreadStore implements ThreadStore {
|
|
|
98
101
|
}
|
|
99
102
|
|
|
100
103
|
/**
|
|
101
|
-
* Get all threads for a specific assistant
|
|
104
|
+
* Get all threads for a specific tenant and assistant
|
|
102
105
|
*/
|
|
103
|
-
async getThreadsByAssistantId(assistantId: string): Promise<Thread[]> {
|
|
106
|
+
async getThreadsByAssistantId(tenantId: string, assistantId: string): Promise<Thread[]> {
|
|
104
107
|
await this.ensureInitialized();
|
|
105
108
|
|
|
106
109
|
const result = await this.pool.query<{
|
|
107
110
|
id: string;
|
|
111
|
+
tenant_id: string;
|
|
108
112
|
assistant_id: string;
|
|
109
113
|
metadata: any;
|
|
110
114
|
created_at: Date;
|
|
111
115
|
updated_at: Date;
|
|
112
116
|
}>(
|
|
113
117
|
`
|
|
114
|
-
SELECT id, assistant_id, metadata, created_at, updated_at
|
|
118
|
+
SELECT id, tenant_id, assistant_id, metadata, created_at, updated_at
|
|
115
119
|
FROM lattice_threads
|
|
116
|
-
WHERE assistant_id = $
|
|
120
|
+
WHERE tenant_id = $1 AND assistant_id = $2
|
|
117
121
|
ORDER BY created_at DESC
|
|
118
122
|
`,
|
|
119
|
-
[assistantId]
|
|
123
|
+
[tenantId, assistantId]
|
|
120
124
|
);
|
|
121
125
|
|
|
122
126
|
return result.rows.map(this.mapRowToThread);
|
|
123
127
|
}
|
|
124
128
|
|
|
125
129
|
/**
|
|
126
|
-
* Get a thread by ID for a specific
|
|
130
|
+
* Get a thread by ID for a specific tenant
|
|
127
131
|
*/
|
|
128
132
|
async getThreadById(
|
|
129
|
-
|
|
133
|
+
tenantId: string,
|
|
130
134
|
threadId: string
|
|
131
135
|
): Promise<Thread | undefined> {
|
|
132
136
|
await this.ensureInitialized();
|
|
133
137
|
|
|
134
138
|
const result = await this.pool.query<{
|
|
135
139
|
id: string;
|
|
140
|
+
tenant_id: string;
|
|
136
141
|
assistant_id: string;
|
|
137
142
|
metadata: any;
|
|
138
143
|
created_at: Date;
|
|
139
144
|
updated_at: Date;
|
|
140
145
|
}>(
|
|
141
146
|
`
|
|
142
|
-
SELECT id, assistant_id, metadata, created_at, updated_at
|
|
147
|
+
SELECT id, tenant_id, assistant_id, metadata, created_at, updated_at
|
|
143
148
|
FROM lattice_threads
|
|
144
|
-
WHERE
|
|
149
|
+
WHERE tenant_id = $1 AND id = $2
|
|
145
150
|
`,
|
|
146
|
-
[
|
|
151
|
+
[tenantId, threadId]
|
|
147
152
|
);
|
|
148
153
|
|
|
149
154
|
if (result.rows.length === 0) {
|
|
@@ -154,9 +159,10 @@ export class PostgreSQLThreadStore implements ThreadStore {
|
|
|
154
159
|
}
|
|
155
160
|
|
|
156
161
|
/**
|
|
157
|
-
* Create a new thread for
|
|
162
|
+
* Create a new thread for a tenant and assistant
|
|
158
163
|
*/
|
|
159
164
|
async createThread(
|
|
165
|
+
tenantId: string,
|
|
160
166
|
assistantId: string,
|
|
161
167
|
threadId: string,
|
|
162
168
|
data: CreateThreadRequest
|
|
@@ -168,17 +174,19 @@ export class PostgreSQLThreadStore implements ThreadStore {
|
|
|
168
174
|
|
|
169
175
|
await this.pool.query(
|
|
170
176
|
`
|
|
171
|
-
INSERT INTO lattice_threads (id, assistant_id, metadata, created_at, updated_at)
|
|
172
|
-
VALUES ($1, $2, $3, $4, $5)
|
|
173
|
-
ON CONFLICT (id,
|
|
177
|
+
INSERT INTO lattice_threads (id, tenant_id, assistant_id, metadata, created_at, updated_at)
|
|
178
|
+
VALUES ($1, $2, $3, $4, $5, $6)
|
|
179
|
+
ON CONFLICT (id, tenant_id) DO UPDATE SET
|
|
180
|
+
assistant_id = EXCLUDED.assistant_id,
|
|
174
181
|
metadata = EXCLUDED.metadata,
|
|
175
182
|
updated_at = EXCLUDED.updated_at
|
|
176
183
|
`,
|
|
177
|
-
[threadId, assistantId, JSON.stringify(metadata), now, now]
|
|
184
|
+
[threadId, tenantId, assistantId, JSON.stringify(metadata), now, now]
|
|
178
185
|
);
|
|
179
186
|
|
|
180
187
|
return {
|
|
181
188
|
id: threadId,
|
|
189
|
+
tenantId,
|
|
182
190
|
assistantId,
|
|
183
191
|
metadata,
|
|
184
192
|
createdAt: now,
|
|
@@ -190,14 +198,14 @@ export class PostgreSQLThreadStore implements ThreadStore {
|
|
|
190
198
|
* Update an existing thread
|
|
191
199
|
*/
|
|
192
200
|
async updateThread(
|
|
193
|
-
|
|
201
|
+
tenantId: string,
|
|
194
202
|
threadId: string,
|
|
195
203
|
updates: Partial<CreateThreadRequest>
|
|
196
204
|
): Promise<Thread | null> {
|
|
197
205
|
await this.ensureInitialized();
|
|
198
206
|
|
|
199
207
|
// Get existing thread
|
|
200
|
-
const existing = await this.getThreadById(
|
|
208
|
+
const existing = await this.getThreadById(tenantId, threadId);
|
|
201
209
|
if (!existing) {
|
|
202
210
|
return null;
|
|
203
211
|
}
|
|
@@ -214,9 +222,9 @@ export class PostgreSQLThreadStore implements ThreadStore {
|
|
|
214
222
|
`
|
|
215
223
|
UPDATE lattice_threads
|
|
216
224
|
SET metadata = $1, updated_at = $2
|
|
217
|
-
WHERE
|
|
225
|
+
WHERE tenant_id = $3 AND id = $4
|
|
218
226
|
`,
|
|
219
|
-
[JSON.stringify(updatedMetadata), now,
|
|
227
|
+
[JSON.stringify(updatedMetadata), now, tenantId, threadId]
|
|
220
228
|
);
|
|
221
229
|
|
|
222
230
|
return {
|
|
@@ -229,15 +237,15 @@ export class PostgreSQLThreadStore implements ThreadStore {
|
|
|
229
237
|
/**
|
|
230
238
|
* Delete a thread by ID
|
|
231
239
|
*/
|
|
232
|
-
async deleteThread(
|
|
240
|
+
async deleteThread(tenantId: string, threadId: string): Promise<boolean> {
|
|
233
241
|
await this.ensureInitialized();
|
|
234
242
|
|
|
235
243
|
const result = await this.pool.query(
|
|
236
244
|
`
|
|
237
245
|
DELETE FROM lattice_threads
|
|
238
|
-
WHERE
|
|
246
|
+
WHERE tenant_id = $1 AND id = $2
|
|
239
247
|
`,
|
|
240
|
-
[
|
|
248
|
+
[tenantId, threadId]
|
|
241
249
|
);
|
|
242
250
|
|
|
243
251
|
return result.rowCount !== null && result.rowCount > 0;
|
|
@@ -246,16 +254,16 @@ export class PostgreSQLThreadStore implements ThreadStore {
|
|
|
246
254
|
/**
|
|
247
255
|
* Check if thread exists
|
|
248
256
|
*/
|
|
249
|
-
async hasThread(
|
|
257
|
+
async hasThread(tenantId: string, threadId: string): Promise<boolean> {
|
|
250
258
|
await this.ensureInitialized();
|
|
251
259
|
|
|
252
260
|
const result = await this.pool.query(
|
|
253
261
|
`
|
|
254
262
|
SELECT 1 FROM lattice_threads
|
|
255
|
-
WHERE
|
|
263
|
+
WHERE tenant_id = $1 AND id = $2
|
|
256
264
|
LIMIT 1
|
|
257
265
|
`,
|
|
258
|
-
[
|
|
266
|
+
[tenantId, threadId]
|
|
259
267
|
);
|
|
260
268
|
|
|
261
269
|
return result.rows.length > 0;
|
|
@@ -275,6 +283,7 @@ export class PostgreSQLThreadStore implements ThreadStore {
|
|
|
275
283
|
*/
|
|
276
284
|
private mapRowToThread(row: {
|
|
277
285
|
id: string;
|
|
286
|
+
tenant_id: string;
|
|
278
287
|
assistant_id: string;
|
|
279
288
|
metadata: any;
|
|
280
289
|
created_at: Date;
|
|
@@ -282,6 +291,7 @@ export class PostgreSQLThreadStore implements ThreadStore {
|
|
|
282
291
|
}): Thread {
|
|
283
292
|
return {
|
|
284
293
|
id: row.id,
|
|
294
|
+
tenantId: row.tenant_id,
|
|
285
295
|
assistantId: row.assistant_id,
|
|
286
296
|
metadata:
|
|
287
297
|
typeof row.metadata === "string"
|