@axiom-lattice/pg-stores 1.0.91 → 1.0.93
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 +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +201 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +201 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/createPgStoreConfig.ts +10 -1
- package/src/migrations/task_migration.ts +31 -0
- package/src/migrations/task_work_items_migration.ts +51 -0
- package/src/stores/PostgreSQLTaskStore.ts +60 -5
- package/src/stores/PostgreSQLTaskWorkItemStore.ts +67 -0
- package/src/stores/PostgreSQLTenantStore.ts +2 -2
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.93",
|
|
4
4
|
"description": "PG stores implementation for Axiom Lattice framework",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"@langchain/core": "1.1.30",
|
|
26
26
|
"pg": "^8.16.3",
|
|
27
27
|
"uuid": "^9.0.1",
|
|
28
|
-
"@axiom-lattice/core": "2.1.
|
|
29
|
-
"@axiom-lattice/protocols": "2.1.
|
|
28
|
+
"@axiom-lattice/core": "2.1.102",
|
|
29
|
+
"@axiom-lattice/protocols": "2.1.53"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/jest": "^29.5.14",
|
|
@@ -19,6 +19,7 @@ import { PostgreSQLChannelInstallationStore } from "./stores/PostgreSQLChannelIn
|
|
|
19
19
|
import { PostgreSQLA2AApiKeyStore } from "./stores/PostgreSQLA2AApiKeyStore";
|
|
20
20
|
import { PostgreSQLScheduleStorage } from "./stores/PostgreSQLScheduleStorage";
|
|
21
21
|
import { PostgreSQLTaskStore } from "./stores/PostgreSQLTaskStore";
|
|
22
|
+
import { PostgreSQLTaskWorkItemStore } from "./stores/PostgreSQLTaskWorkItemStore";
|
|
22
23
|
import { MenuStore } from "./stores/MenuStore";
|
|
23
24
|
import { PostgresSharedResourceStore } from "./stores/PostgresSharedResourceStore";
|
|
24
25
|
import { PostgreSQLCollectionStore } from "./stores/PostgreSQLCollectionStore";
|
|
@@ -62,11 +63,12 @@ import { addWorkspaceProjectToQueue } from "./migrations/add_workspace_project_t
|
|
|
62
63
|
import { createWorkflowTrackingTables, addStepThreadId, addWorkflowRunsTenantStatusUpdatedIndex } from "./migrations/workflow_tracking_migrations";
|
|
63
64
|
import { evalMigrations } from "./migrations/eval_migrations";
|
|
64
65
|
import { createA2AApiKeysTable } from "./migrations/a2a_api_key_migration";
|
|
65
|
-
import { createTasksTable } from "./migrations/task_migration";
|
|
66
|
+
import { createTasksTable, addTaskFieldsMigration, addTaskProjectFieldsMigration } from "./migrations/task_migration";
|
|
66
67
|
import { createMenuItemsTable } from "./migrations/menu_items_migration";
|
|
67
68
|
import { addFileContentType } from "./migrations/menu_items_add_file_type";
|
|
68
69
|
import { createSharedResourcesTable } from "./migrations/shared_resources_migration";
|
|
69
70
|
import { createCollectionsTable } from "./migrations/collection_migrations";
|
|
71
|
+
import { createTaskWorkItemsMigration, addWorkItemProjectFieldsMigration } from "./migrations/task_work_items_migration";
|
|
70
72
|
|
|
71
73
|
export async function createPgStoreConfig(connectionString: string) {
|
|
72
74
|
const pool = new Pool({ connectionString });
|
|
@@ -118,6 +120,10 @@ export async function createPgStoreConfig(connectionString: string) {
|
|
|
118
120
|
mm.register(createSharedResourcesTable); // v135
|
|
119
121
|
mm.register(addFileContentType); // v136
|
|
120
122
|
mm.register(createCollectionsTable); // v137
|
|
123
|
+
mm.register(addTaskFieldsMigration); // v139
|
|
124
|
+
mm.register(createTaskWorkItemsMigration); // v138
|
|
125
|
+
mm.register(addTaskProjectFieldsMigration); // v140
|
|
126
|
+
mm.register(addWorkItemProjectFieldsMigration); // v140
|
|
121
127
|
mm.register(createConnectionConfigsTable); // v160
|
|
122
128
|
mm.register(addWorkflowRunsTenantStatusUpdatedIndex); // v161
|
|
123
129
|
|
|
@@ -130,6 +136,8 @@ export async function createPgStoreConfig(connectionString: string) {
|
|
|
130
136
|
|
|
131
137
|
const opts = { pool };
|
|
132
138
|
|
|
139
|
+
const taskWorkItemStore = new PostgreSQLTaskWorkItemStore(pool);
|
|
140
|
+
|
|
133
141
|
return {
|
|
134
142
|
workspace: new PostgreSQLWorkspaceStore(opts),
|
|
135
143
|
project: new PostgreSQLProjectStore(opts),
|
|
@@ -148,6 +156,7 @@ export async function createPgStoreConfig(connectionString: string) {
|
|
|
148
156
|
workflowTracking: new PostgreSQLWorkflowTrackingStore(opts),
|
|
149
157
|
threadMessageQueue: new ThreadMessageQueueStore(opts),
|
|
150
158
|
task: new PostgreSQLTaskStore(opts),
|
|
159
|
+
taskWorkItem: taskWorkItemStore,
|
|
151
160
|
a2aApiKey: new PostgreSQLA2AApiKeyStore(opts),
|
|
152
161
|
schedule: new PostgreSQLScheduleStorage(opts),
|
|
153
162
|
menu: new MenuStore(opts),
|
|
@@ -49,3 +49,34 @@ export const createTasksTable: Migration = {
|
|
|
49
49
|
await client.query("DROP TABLE IF EXISTS lattice_tasks");
|
|
50
50
|
},
|
|
51
51
|
};
|
|
52
|
+
|
|
53
|
+
export const addTaskFieldsMigration: Migration = {
|
|
54
|
+
version: 139,
|
|
55
|
+
name: "add_task_fields_require_review_deps_result_failure",
|
|
56
|
+
up: async (client: PoolClient) => {
|
|
57
|
+
await client.query(`
|
|
58
|
+
ALTER TABLE lattice_tasks
|
|
59
|
+
ADD COLUMN IF NOT EXISTS require_review BOOLEAN DEFAULT FALSE,
|
|
60
|
+
ADD COLUMN IF NOT EXISTS dependencies JSONB,
|
|
61
|
+
ADD COLUMN IF NOT EXISTS result TEXT,
|
|
62
|
+
ADD COLUMN IF NOT EXISTS failure_reason TEXT
|
|
63
|
+
`);
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const addTaskProjectFieldsMigration: Migration = {
|
|
68
|
+
version: 140,
|
|
69
|
+
name: "add_task_project_workspace_fields",
|
|
70
|
+
up: async (client: PoolClient) => {
|
|
71
|
+
await client.query(`
|
|
72
|
+
ALTER TABLE lattice_tasks
|
|
73
|
+
ADD COLUMN IF NOT EXISTS workspace_id TEXT,
|
|
74
|
+
ADD COLUMN IF NOT EXISTS project_id TEXT
|
|
75
|
+
`);
|
|
76
|
+
|
|
77
|
+
await client.query(`
|
|
78
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_project
|
|
79
|
+
ON lattice_tasks (tenant_id, project_id)
|
|
80
|
+
`);
|
|
81
|
+
},
|
|
82
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { PoolClient } from "pg";
|
|
2
|
+
import type { Migration } from "./migration";
|
|
3
|
+
|
|
4
|
+
export const createTaskWorkItemsMigration: Migration = {
|
|
5
|
+
version: 138,
|
|
6
|
+
name: "create_task_work_items_table",
|
|
7
|
+
up: async (client: PoolClient) => {
|
|
8
|
+
await client.query(`
|
|
9
|
+
CREATE TABLE IF NOT EXISTS lattice_task_work_items (
|
|
10
|
+
id TEXT NOT NULL,
|
|
11
|
+
tenant_id TEXT NOT NULL,
|
|
12
|
+
task_id TEXT NOT NULL,
|
|
13
|
+
action TEXT NOT NULL,
|
|
14
|
+
actor TEXT NOT NULL,
|
|
15
|
+
thread_id TEXT,
|
|
16
|
+
summary TEXT,
|
|
17
|
+
detail JSONB,
|
|
18
|
+
attempt INTEGER,
|
|
19
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
20
|
+
PRIMARY KEY (tenant_id, id)
|
|
21
|
+
)
|
|
22
|
+
`);
|
|
23
|
+
|
|
24
|
+
await client.query(`
|
|
25
|
+
CREATE INDEX IF NOT EXISTS idx_task_work_items_task_id
|
|
26
|
+
ON lattice_task_work_items (tenant_id, task_id)
|
|
27
|
+
`);
|
|
28
|
+
|
|
29
|
+
await client.query(`
|
|
30
|
+
CREATE INDEX IF NOT EXISTS idx_task_work_items_action
|
|
31
|
+
ON lattice_task_work_items (tenant_id, task_id, action)
|
|
32
|
+
`);
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const addWorkItemProjectFieldsMigration: Migration = {
|
|
37
|
+
version: 140,
|
|
38
|
+
name: "add_task_work_item_project_fields",
|
|
39
|
+
up: async (client: PoolClient) => {
|
|
40
|
+
await client.query(`
|
|
41
|
+
ALTER TABLE lattice_task_work_items
|
|
42
|
+
ADD COLUMN IF NOT EXISTS workspace_id TEXT,
|
|
43
|
+
ADD COLUMN IF NOT EXISTS project_id TEXT
|
|
44
|
+
`);
|
|
45
|
+
|
|
46
|
+
await client.query(`
|
|
47
|
+
CREATE INDEX IF NOT EXISTS idx_task_work_items_project
|
|
48
|
+
ON lattice_task_work_items (tenant_id, project_id)
|
|
49
|
+
`);
|
|
50
|
+
},
|
|
51
|
+
};
|
|
@@ -12,7 +12,7 @@ import type {
|
|
|
12
12
|
TaskListFilter,
|
|
13
13
|
} from "@axiom-lattice/protocols";
|
|
14
14
|
import { MigrationManager } from "../migrations/migration";
|
|
15
|
-
import { createTasksTable } from "../migrations/task_migration";
|
|
15
|
+
import { createTasksTable, addTaskFieldsMigration, addTaskProjectFieldsMigration } from "../migrations/task_migration";
|
|
16
16
|
import { v4 as uuidv4 } from "uuid";
|
|
17
17
|
|
|
18
18
|
interface TaskRow {
|
|
@@ -29,6 +29,12 @@ interface TaskRow {
|
|
|
29
29
|
parent_id: string | null;
|
|
30
30
|
source_id: string | null;
|
|
31
31
|
context: Record<string, unknown> | null;
|
|
32
|
+
require_review: boolean | null;
|
|
33
|
+
dependencies: string[] | null;
|
|
34
|
+
result: string | null;
|
|
35
|
+
failure_reason: string | null;
|
|
36
|
+
workspace_id: string | null;
|
|
37
|
+
project_id: string | null;
|
|
32
38
|
created_at: string;
|
|
33
39
|
updated_at: string;
|
|
34
40
|
}
|
|
@@ -48,6 +54,12 @@ function mapRowToTask(row: TaskRow): TaskItem {
|
|
|
48
54
|
parentId: row.parent_id ?? undefined,
|
|
49
55
|
sourceId: row.source_id ?? undefined,
|
|
50
56
|
context: row.context ?? undefined,
|
|
57
|
+
requireReview: row.require_review ?? undefined,
|
|
58
|
+
dependencies: row.dependencies ?? undefined,
|
|
59
|
+
result: row.result ?? undefined,
|
|
60
|
+
failureReason: row.failure_reason ?? undefined,
|
|
61
|
+
workspaceId: row.workspace_id ?? undefined,
|
|
62
|
+
projectId: row.project_id ?? undefined,
|
|
51
63
|
createdAt: new Date(row.created_at),
|
|
52
64
|
updatedAt: new Date(row.updated_at),
|
|
53
65
|
};
|
|
@@ -85,6 +97,8 @@ export class PostgreSQLTaskStore implements TaskStore {
|
|
|
85
97
|
|
|
86
98
|
this.migrationManager = new MigrationManager(this.pool);
|
|
87
99
|
this.migrationManager.register(createTasksTable);
|
|
100
|
+
this.migrationManager.register(addTaskFieldsMigration);
|
|
101
|
+
this.migrationManager.register(addTaskProjectFieldsMigration);
|
|
88
102
|
|
|
89
103
|
if (options.autoMigrate !== false) {
|
|
90
104
|
this.initialize().catch((error) => {
|
|
@@ -123,8 +137,8 @@ export class PostgreSQLTaskStore implements TaskStore {
|
|
|
123
137
|
const now = new Date().toISOString();
|
|
124
138
|
|
|
125
139
|
await this.pool.query(
|
|
126
|
-
`INSERT INTO lattice_tasks (id, tenant_id, owner_type, owner_id, title, description, status, priority, due_date, metadata, parent_id, source_id, context, created_at, updated_at)
|
|
127
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)`,
|
|
140
|
+
`INSERT INTO lattice_tasks (id, tenant_id, owner_type, owner_id, title, description, status, priority, due_date, metadata, parent_id, source_id, context, require_review, dependencies, result, failure_reason, workspace_id, project_id, created_at, updated_at)
|
|
141
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21)`,
|
|
128
142
|
[
|
|
129
143
|
id,
|
|
130
144
|
params.tenantId,
|
|
@@ -139,6 +153,12 @@ export class PostgreSQLTaskStore implements TaskStore {
|
|
|
139
153
|
params.parentId || null,
|
|
140
154
|
params.sourceId || null,
|
|
141
155
|
params.context ? JSON.stringify(params.context) : null,
|
|
156
|
+
params.requireReview ?? null,
|
|
157
|
+
params.dependencies ? JSON.stringify(params.dependencies) : null,
|
|
158
|
+
params.result ?? null,
|
|
159
|
+
params.failureReason ?? null,
|
|
160
|
+
params.workspaceId || null,
|
|
161
|
+
params.projectId || null,
|
|
142
162
|
now,
|
|
143
163
|
now,
|
|
144
164
|
],
|
|
@@ -172,13 +192,24 @@ export class PostgreSQLTaskStore implements TaskStore {
|
|
|
172
192
|
params.push(filter.ownerId);
|
|
173
193
|
}
|
|
174
194
|
if (filter.status) {
|
|
175
|
-
|
|
176
|
-
|
|
195
|
+
const statuses = filter.status.split(',').map(s => s.trim()).filter(Boolean);
|
|
196
|
+
const placeholders = statuses.map((_, i) => `$${paramIndex + i}`).join(', ');
|
|
197
|
+
conditions.push(`status IN (${placeholders})`);
|
|
198
|
+
params.push(...statuses);
|
|
199
|
+
paramIndex += statuses.length;
|
|
177
200
|
}
|
|
178
201
|
if (filter.priority) {
|
|
179
202
|
conditions.push(`priority = $${paramIndex++}`);
|
|
180
203
|
params.push(filter.priority);
|
|
181
204
|
}
|
|
205
|
+
if (filter.workspaceId) {
|
|
206
|
+
conditions.push(`workspace_id = $${paramIndex++}`);
|
|
207
|
+
params.push(filter.workspaceId);
|
|
208
|
+
}
|
|
209
|
+
if (filter.projectId) {
|
|
210
|
+
conditions.push(`project_id = $${paramIndex++}`);
|
|
211
|
+
params.push(filter.projectId);
|
|
212
|
+
}
|
|
182
213
|
if (filter.parentId) {
|
|
183
214
|
conditions.push(`parent_id = $${paramIndex++}`);
|
|
184
215
|
params.push(filter.parentId);
|
|
@@ -265,6 +296,30 @@ export class PostgreSQLTaskStore implements TaskStore {
|
|
|
265
296
|
setClauses.push(`owner_id = $${paramIndex++}`);
|
|
266
297
|
params.push(updates.ownerId);
|
|
267
298
|
}
|
|
299
|
+
if (updates.requireReview !== undefined) {
|
|
300
|
+
setClauses.push(`require_review = $${paramIndex++}`);
|
|
301
|
+
params.push(updates.requireReview);
|
|
302
|
+
}
|
|
303
|
+
if (updates.dependencies !== undefined) {
|
|
304
|
+
setClauses.push(`dependencies = $${paramIndex++}`);
|
|
305
|
+
params.push(JSON.stringify(updates.dependencies));
|
|
306
|
+
}
|
|
307
|
+
if (updates.result !== undefined) {
|
|
308
|
+
setClauses.push(`result = $${paramIndex++}`);
|
|
309
|
+
params.push(updates.result);
|
|
310
|
+
}
|
|
311
|
+
if (updates.failureReason !== undefined) {
|
|
312
|
+
setClauses.push(`failure_reason = $${paramIndex++}`);
|
|
313
|
+
params.push(updates.failureReason);
|
|
314
|
+
}
|
|
315
|
+
if (updates.workspaceId !== undefined) {
|
|
316
|
+
setClauses.push(`workspace_id = $${paramIndex++}`);
|
|
317
|
+
params.push(updates.workspaceId);
|
|
318
|
+
}
|
|
319
|
+
if (updates.projectId !== undefined) {
|
|
320
|
+
setClauses.push(`project_id = $${paramIndex++}`);
|
|
321
|
+
params.push(updates.projectId);
|
|
322
|
+
}
|
|
268
323
|
|
|
269
324
|
if (setClauses.length === 0) {
|
|
270
325
|
return existing;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Pool } from "pg";
|
|
2
|
+
import type { TaskWorkItemStore, TaskWorkItem, CreateWorkItemRequest, TaskWorkItemListFilter } from "@axiom-lattice/protocols";
|
|
3
|
+
import { v4 } from "uuid";
|
|
4
|
+
|
|
5
|
+
export class PostgreSQLTaskWorkItemStore implements TaskWorkItemStore {
|
|
6
|
+
constructor(private pool: Pool) {}
|
|
7
|
+
|
|
8
|
+
async create(params: CreateWorkItemRequest): Promise<TaskWorkItem> {
|
|
9
|
+
const id = v4();
|
|
10
|
+
const result = await this.pool.query(
|
|
11
|
+
`INSERT INTO lattice_task_work_items
|
|
12
|
+
(id, tenant_id, task_id, action, actor, thread_id, summary, detail, attempt, workspace_id, project_id)
|
|
13
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
|
|
14
|
+
RETURNING *`,
|
|
15
|
+
[
|
|
16
|
+
id, params.tenantId, params.taskId, params.action, params.actor,
|
|
17
|
+
params.threadId || null, params.summary || null,
|
|
18
|
+
params.detail ? JSON.stringify(params.detail) : null,
|
|
19
|
+
params.attempt || null,
|
|
20
|
+
params.workspaceId || null,
|
|
21
|
+
params.projectId || null,
|
|
22
|
+
]
|
|
23
|
+
);
|
|
24
|
+
return this.rowToItem(result.rows[0]);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async list(filter: TaskWorkItemListFilter): Promise<TaskWorkItem[]> {
|
|
28
|
+
let query = `SELECT * FROM lattice_task_work_items WHERE tenant_id = $1 AND task_id = $2`;
|
|
29
|
+
const params: unknown[] = [filter.tenantId, filter.taskId];
|
|
30
|
+
|
|
31
|
+
if (filter.action) {
|
|
32
|
+
query += ` AND action = $${params.length + 1}`;
|
|
33
|
+
params.push(filter.action);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
query += ` ORDER BY created_at ASC`;
|
|
37
|
+
|
|
38
|
+
if (filter.limit) {
|
|
39
|
+
query += ` LIMIT $${params.length + 1}`;
|
|
40
|
+
params.push(filter.limit);
|
|
41
|
+
}
|
|
42
|
+
if (filter.offset) {
|
|
43
|
+
query += ` OFFSET $${params.length + 1}`;
|
|
44
|
+
params.push(filter.offset);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const result = await this.pool.query(query, params);
|
|
48
|
+
return result.rows.map((row: Record<string, unknown>) => this.rowToItem(row));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private rowToItem(row: Record<string, unknown>): TaskWorkItem {
|
|
52
|
+
return {
|
|
53
|
+
id: row.id as string,
|
|
54
|
+
taskId: row.task_id as string,
|
|
55
|
+
tenantId: row.tenant_id as string,
|
|
56
|
+
action: row.action as string,
|
|
57
|
+
actor: row.actor as string,
|
|
58
|
+
threadId: row.thread_id as string | undefined,
|
|
59
|
+
summary: row.summary as string | undefined,
|
|
60
|
+
detail: row.detail as Record<string, unknown> | undefined,
|
|
61
|
+
attempt: row.attempt as number | undefined,
|
|
62
|
+
workspaceId: row.workspace_id as string | undefined,
|
|
63
|
+
projectId: row.project_id as string | undefined,
|
|
64
|
+
createdAt: new Date(row.created_at as string),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -261,8 +261,8 @@ export class PostgreSQLTenantStore implements TenantStore {
|
|
|
261
261
|
}
|
|
262
262
|
|
|
263
263
|
if (updates.metadata !== undefined) {
|
|
264
|
-
updateFields.push(`metadata = $${paramIndex++}`);
|
|
265
|
-
updateValues.push(updates.metadata);
|
|
264
|
+
updateFields.push(`metadata = COALESCE(lattice_tenants.metadata, '{}'::jsonb) || $${paramIndex++}::jsonb`);
|
|
265
|
+
updateValues.push(JSON.stringify(updates.metadata));
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
if (updateFields.length === 0) {
|