@axiom-lattice/pg-stores 1.0.34 → 1.0.36
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 +16 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +41 -24
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +41 -24
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/ThreadMessageQueueStore.test.ts +61 -2
- package/src/migrations/add_custom_run_config_column.ts +25 -0
- package/src/stores/PostgreSQLThreadStore.ts +17 -2
- package/src/stores/ThreadMessageQueueStore.ts +18 -30
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axiom-lattice/pg-stores",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.36",
|
|
4
4
|
"description": "PG stores implementation for Axiom Lattice framework",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"pg": "^8.16.3",
|
|
24
|
-
"@axiom-lattice/protocols": "2.1.
|
|
25
|
-
"@axiom-lattice/core": "2.1.
|
|
24
|
+
"@axiom-lattice/protocols": "2.1.24",
|
|
25
|
+
"@axiom-lattice/core": "2.1.46"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^20.11.24",
|
|
@@ -89,6 +89,46 @@ describe('ThreadMessageQueueStore', () => {
|
|
|
89
89
|
|
|
90
90
|
expect(result.sequence).toBe(5);
|
|
91
91
|
});
|
|
92
|
+
|
|
93
|
+
it('should persist custom_run_config in insert query', async () => {
|
|
94
|
+
const customRunConfig = {
|
|
95
|
+
modelConfig: {
|
|
96
|
+
modelKey: 'default',
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
mockQuery
|
|
101
|
+
.mockResolvedValueOnce({ rows: [{ next_seq: 1 }] })
|
|
102
|
+
.mockResolvedValueOnce({
|
|
103
|
+
rows: [{
|
|
104
|
+
id: 'msg-1',
|
|
105
|
+
thread_id: mockThreadId,
|
|
106
|
+
tenant_id: mockTenantId,
|
|
107
|
+
assistant_id: mockAssistantId,
|
|
108
|
+
message_content: JSON.stringify('test content'),
|
|
109
|
+
message_type: 'human',
|
|
110
|
+
sequence_order: 1,
|
|
111
|
+
status: 'pending',
|
|
112
|
+
created_at: new Date(),
|
|
113
|
+
custom_run_config: JSON.stringify(customRunConfig),
|
|
114
|
+
}],
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
await store.addMessage({
|
|
118
|
+
threadId: mockThreadId,
|
|
119
|
+
tenantId: mockTenantId,
|
|
120
|
+
assistantId: mockAssistantId,
|
|
121
|
+
content: 'test content',
|
|
122
|
+
type: 'human',
|
|
123
|
+
custom_run_config: customRunConfig,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
expect(mockQuery).toHaveBeenNthCalledWith(
|
|
127
|
+
2,
|
|
128
|
+
expect.stringContaining('custom_run_config'),
|
|
129
|
+
expect.arrayContaining([JSON.stringify(customRunConfig)])
|
|
130
|
+
);
|
|
131
|
+
});
|
|
92
132
|
});
|
|
93
133
|
|
|
94
134
|
describe('addMessageAtHead', () => {
|
|
@@ -106,7 +146,13 @@ describe('ThreadMessageQueueStore', () => {
|
|
|
106
146
|
}]
|
|
107
147
|
}); // Insert
|
|
108
148
|
|
|
109
|
-
const result = await store.addMessageAtHead(
|
|
149
|
+
const result = await store.addMessageAtHead({
|
|
150
|
+
threadId: mockThreadId,
|
|
151
|
+
tenantId: mockTenantId,
|
|
152
|
+
assistantId: mockAssistantId,
|
|
153
|
+
content: 'head content',
|
|
154
|
+
type: 'system',
|
|
155
|
+
});
|
|
110
156
|
|
|
111
157
|
expect(result.priority).toBe(100);
|
|
112
158
|
expect(result.sequence).toBe(1);
|
|
@@ -127,7 +173,13 @@ describe('ThreadMessageQueueStore', () => {
|
|
|
127
173
|
}]
|
|
128
174
|
});
|
|
129
175
|
|
|
130
|
-
const result = await store.addMessageAtHead(
|
|
176
|
+
const result = await store.addMessageAtHead({
|
|
177
|
+
threadId: mockThreadId,
|
|
178
|
+
tenantId: mockTenantId,
|
|
179
|
+
assistantId: mockAssistantId,
|
|
180
|
+
content: 'head content',
|
|
181
|
+
type: 'system',
|
|
182
|
+
});
|
|
131
183
|
|
|
132
184
|
expect(result.priority).toBe(100);
|
|
133
185
|
});
|
|
@@ -175,6 +227,11 @@ describe('ThreadMessageQueueStore', () => {
|
|
|
175
227
|
action: 'submit',
|
|
176
228
|
},
|
|
177
229
|
};
|
|
230
|
+
const customRunConfig = {
|
|
231
|
+
modelConfig: {
|
|
232
|
+
modelKey: 'default',
|
|
233
|
+
},
|
|
234
|
+
};
|
|
178
235
|
|
|
179
236
|
mockQuery.mockResolvedValueOnce({
|
|
180
237
|
rows: [
|
|
@@ -191,6 +248,7 @@ describe('ThreadMessageQueueStore', () => {
|
|
|
191
248
|
},
|
|
192
249
|
}),
|
|
193
250
|
command: JSON.stringify(command),
|
|
251
|
+
custom_run_config: JSON.stringify(customRunConfig),
|
|
194
252
|
message_type: 'human',
|
|
195
253
|
sequence_order: 1,
|
|
196
254
|
created_at: new Date('2024-01-01'),
|
|
@@ -202,6 +260,7 @@ describe('ThreadMessageQueueStore', () => {
|
|
|
202
260
|
const result = await store.getPendingMessages(mockThreadId);
|
|
203
261
|
|
|
204
262
|
expect(result[0].command).toEqual(command);
|
|
263
|
+
expect(result[0].custom_run_config).toEqual(customRunConfig);
|
|
205
264
|
expect((result[0].content as { command?: unknown }).command).toBeUndefined();
|
|
206
265
|
});
|
|
207
266
|
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Add custom_run_config column to thread message queue
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { PoolClient } from "pg";
|
|
6
|
+
import { Migration } from "./migration";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Migration: Add custom_run_config column
|
|
10
|
+
*/
|
|
11
|
+
export const addCustomRunConfigColumn: Migration = {
|
|
12
|
+
version: 102,
|
|
13
|
+
name: "add_custom_run_config_column",
|
|
14
|
+
up: async (client: PoolClient) => {
|
|
15
|
+
await client.query(`
|
|
16
|
+
ALTER TABLE lattice_thread_message_queue
|
|
17
|
+
ADD COLUMN IF NOT EXISTS custom_run_config JSONB
|
|
18
|
+
`);
|
|
19
|
+
},
|
|
20
|
+
down: async (client: PoolClient) => {
|
|
21
|
+
await client.query(
|
|
22
|
+
"ALTER TABLE lattice_thread_message_queue DROP COLUMN IF EXISTS custom_run_config"
|
|
23
|
+
);
|
|
24
|
+
},
|
|
25
|
+
};
|
|
@@ -103,7 +103,11 @@ export class PostgreSQLThreadStore implements ThreadStore {
|
|
|
103
103
|
/**
|
|
104
104
|
* Get all threads for a specific tenant and assistant
|
|
105
105
|
*/
|
|
106
|
-
async getThreadsByAssistantId(
|
|
106
|
+
async getThreadsByAssistantId(
|
|
107
|
+
tenantId: string,
|
|
108
|
+
assistantId: string,
|
|
109
|
+
metadataFilter?: Record<string, string>
|
|
110
|
+
): Promise<Thread[]> {
|
|
107
111
|
await this.ensureInitialized();
|
|
108
112
|
|
|
109
113
|
const result = await this.pool.query<{
|
|
@@ -123,7 +127,18 @@ export class PostgreSQLThreadStore implements ThreadStore {
|
|
|
123
127
|
[tenantId, assistantId]
|
|
124
128
|
);
|
|
125
129
|
|
|
126
|
-
|
|
130
|
+
let threads = result.rows.map(this.mapRowToThread);
|
|
131
|
+
|
|
132
|
+
// Apply metadata filtering if provided
|
|
133
|
+
if (metadataFilter && Object.keys(metadataFilter).length > 0) {
|
|
134
|
+
threads = threads.filter((thread) =>
|
|
135
|
+
Object.entries(metadataFilter).every(
|
|
136
|
+
([key, value]) => thread.metadata?.[key] === value
|
|
137
|
+
)
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return threads;
|
|
127
142
|
}
|
|
128
143
|
|
|
129
144
|
/**
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
import { MigrationManager } from "../migrations/migration";
|
|
16
16
|
import { createThreadMessageQueueTable } from "../migrations/thread_message_queue_migrations";
|
|
17
17
|
import { addPriorityAndCommandColumns } from "../migrations/add_priority_command_columns";
|
|
18
|
+
import { addCustomRunConfigColumn } from "../migrations/add_custom_run_config_column";
|
|
18
19
|
import { alterMessageQueueIdColumn } from "../migrations/alter_message_queue_id_column";
|
|
19
20
|
|
|
20
21
|
export { PendingMessage, AddMessageParams, ThreadInfo };
|
|
@@ -45,6 +46,7 @@ export class ThreadMessageQueueStore implements IMessageQueueStore {
|
|
|
45
46
|
const migrationManager = new MigrationManager(pool);
|
|
46
47
|
migrationManager.register(createThreadMessageQueueTable);
|
|
47
48
|
migrationManager.register(addPriorityAndCommandColumns);
|
|
49
|
+
migrationManager.register(addCustomRunConfigColumn);
|
|
48
50
|
migrationManager.register(alterMessageQueueIdColumn);
|
|
49
51
|
await migrationManager.migrate();
|
|
50
52
|
this.initialized = true;
|
|
@@ -63,7 +65,7 @@ export class ThreadMessageQueueStore implements IMessageQueueStore {
|
|
|
63
65
|
*/
|
|
64
66
|
async addMessage(params: AddMessageParams): Promise<PendingMessage> {
|
|
65
67
|
const pool = this.getPool();
|
|
66
|
-
const { threadId, tenantId, assistantId, content, type = "human", priority = 0, command, id } = params;
|
|
68
|
+
const { threadId, tenantId, assistantId, content, type = "human", priority = 0, command, custom_run_config, id } = params;
|
|
67
69
|
|
|
68
70
|
// Get current max sequence (no lock needed without unique constraint)
|
|
69
71
|
const seqResult = await pool.query(
|
|
@@ -76,10 +78,10 @@ export class ThreadMessageQueueStore implements IMessageQueueStore {
|
|
|
76
78
|
|
|
77
79
|
const result = await pool.query(
|
|
78
80
|
`INSERT INTO lattice_thread_message_queue
|
|
79
|
-
(id, thread_id, tenant_id, assistant_id, message_content, message_type, sequence_order, priority, command)
|
|
80
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
|
81
|
+
(id, thread_id, tenant_id, assistant_id, message_content, message_type, sequence_order, priority, command, custom_run_config)
|
|
82
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
|
81
83
|
RETURNING *`,
|
|
82
|
-
[id || crypto.randomUUID(), threadId, tenantId, assistantId, JSON.stringify(content), type, nextSeq, priority, command ? JSON.stringify(command) : null]
|
|
84
|
+
[id || crypto.randomUUID(), threadId, tenantId, assistantId, JSON.stringify(content), type, nextSeq, priority, command ? JSON.stringify(command) : null, custom_run_config ? JSON.stringify(custom_run_config) : null]
|
|
83
85
|
);
|
|
84
86
|
|
|
85
87
|
return this.rowToMessage(result.rows[0]);
|
|
@@ -89,31 +91,14 @@ export class ThreadMessageQueueStore implements IMessageQueueStore {
|
|
|
89
91
|
* Add message at head of queue (high priority, e.g., STEER/Command messages)
|
|
90
92
|
* Uses priority=100 to ensure message is processed first
|
|
91
93
|
*/
|
|
92
|
-
async addMessageAtHead(
|
|
93
|
-
threadId: string,
|
|
94
|
-
content: PendingMessage["content"],
|
|
95
|
-
type: "human" | "system" = "system",
|
|
96
|
-
id?: string,
|
|
97
|
-
command?: PendingMessage["command"]
|
|
98
|
-
): Promise<PendingMessage> {
|
|
94
|
+
async addMessageAtHead(params: AddMessageParams): Promise<PendingMessage> {
|
|
99
95
|
const pool = this.getPool();
|
|
96
|
+
const { threadId, tenantId, assistantId, content, type = "human", command, custom_run_config, id } = params;
|
|
100
97
|
|
|
101
|
-
//
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
WHERE thread_id = $1
|
|
106
|
-
LIMIT 1`,
|
|
107
|
-
[threadId]
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
let tenantId = "default";
|
|
111
|
-
let assistantId = "";
|
|
112
|
-
|
|
113
|
-
if (threadResult.rows.length > 0) {
|
|
114
|
-
tenantId = threadResult.rows[0].tenant_id;
|
|
115
|
-
assistantId = threadResult.rows[0].assistant_id;
|
|
116
|
-
}
|
|
98
|
+
// Use provided tenantId and assistantId directly
|
|
99
|
+
// These should always be provided by the caller (Agent)
|
|
100
|
+
const resolvedTenantId = tenantId!;
|
|
101
|
+
const resolvedAssistantId = assistantId!;
|
|
117
102
|
|
|
118
103
|
// Get current max sequence for ordering within same priority
|
|
119
104
|
const seqResult = await pool.query(
|
|
@@ -127,10 +112,10 @@ export class ThreadMessageQueueStore implements IMessageQueueStore {
|
|
|
127
112
|
// Insert with high priority (100)
|
|
128
113
|
const result = await pool.query(
|
|
129
114
|
`INSERT INTO lattice_thread_message_queue
|
|
130
|
-
(id, thread_id, tenant_id, assistant_id, message_content, message_type, sequence_order, priority, command)
|
|
131
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, 100, $8)
|
|
115
|
+
(id, thread_id, tenant_id, assistant_id, message_content, message_type, sequence_order, priority, command, custom_run_config)
|
|
116
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, 100, $8, $9)
|
|
132
117
|
RETURNING *`,
|
|
133
|
-
[id || crypto.randomUUID(), threadId,
|
|
118
|
+
[id || crypto.randomUUID(), threadId, resolvedTenantId, resolvedAssistantId, JSON.stringify(content), type, nextSeq, command ? JSON.stringify(command) : null, custom_run_config ? JSON.stringify(custom_run_config) : null]
|
|
134
119
|
);
|
|
135
120
|
|
|
136
121
|
return this.rowToMessage(result.rows[0]);
|
|
@@ -284,6 +269,9 @@ export class ThreadMessageQueueStore implements IMessageQueueStore {
|
|
|
284
269
|
createdAt: new Date(row.created_at),
|
|
285
270
|
priority: row.priority || 0,
|
|
286
271
|
command: row.command ? (typeof row.command === "string" ? JSON.parse(row.command) : row.command) : undefined,
|
|
272
|
+
custom_run_config: row.custom_run_config
|
|
273
|
+
? (typeof row.custom_run_config === "string" ? JSON.parse(row.custom_run_config) : row.custom_run_config)
|
|
274
|
+
: undefined,
|
|
287
275
|
};
|
|
288
276
|
}
|
|
289
277
|
}
|