@axiom-lattice/pg-stores 1.0.90 → 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 +25 -0
- package/dist/index.d.mts +13 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +220 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +220 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/PostgreSQLWorkflowTrackingStore.test.ts +1 -1
- 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/PostgreSQLConnectionStore.ts +8 -0
- package/src/stores/PostgreSQLEvalStore.ts +12 -0
- package/src/stores/PostgreSQLTaskStore.ts +60 -5
- package/src/stores/PostgreSQLTaskWorkItemStore.ts +67 -0
- package/src/stores/PostgreSQLTenantStore.ts +2 -2
- package/src/stores/PostgreSQLWorkflowTrackingStore.ts +3 -1
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",
|
|
@@ -220,7 +220,7 @@ describe("mapRowToRunStep", () => {
|
|
|
220
220
|
output: "also invalid",
|
|
221
221
|
});
|
|
222
222
|
expect(result.input).toBeUndefined();
|
|
223
|
-
expect(result.output).
|
|
223
|
+
expect(result.output).toEqual("also invalid"); // text output preserved as-is (jsonb column)
|
|
224
224
|
});
|
|
225
225
|
|
|
226
226
|
test("handles deeply nested objects", () => {
|
|
@@ -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
|
+
};
|
|
@@ -30,6 +30,14 @@ export class PostgreSQLConnectionStore implements ConnectionStore {
|
|
|
30
30
|
this.db = db;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
async listByTenant(tenantId: string): Promise<ConnectionEntry[]> {
|
|
34
|
+
const result = await this.db.query<ConnectionRow>(
|
|
35
|
+
`SELECT * FROM ${TABLE} WHERE tenant_id = $1 ORDER BY created_at`,
|
|
36
|
+
[tenantId],
|
|
37
|
+
);
|
|
38
|
+
return result.rows.map((row) => this.mapRow(row));
|
|
39
|
+
}
|
|
40
|
+
|
|
33
41
|
async listByType(tenantId: string, type: string): Promise<ConnectionEntry[]> {
|
|
34
42
|
const result = await this.db.query<ConnectionRow>(
|
|
35
43
|
`SELECT * FROM ${TABLE} WHERE tenant_id = $1 AND type = $2 ORDER BY created_at`,
|
|
@@ -828,6 +828,18 @@ export class PostgreSQLEvalStore implements EvalStore {
|
|
|
828
828
|
return rows.length ? this.mapRowToRunResult(rows[0] as unknown as Record<string, unknown>) : null;
|
|
829
829
|
}
|
|
830
830
|
|
|
831
|
+
/** Delete a run result by ID */
|
|
832
|
+
async deleteRunResult(tenantId: string, id: string): Promise<boolean> {
|
|
833
|
+
await this.ensureInitialized();
|
|
834
|
+
const result = await this.pool.query(
|
|
835
|
+
`DELETE FROM lattice_eval_run_results
|
|
836
|
+
WHERE id = $1
|
|
837
|
+
AND run_id IN (SELECT id FROM lattice_eval_runs WHERE tenant_id = $2)`,
|
|
838
|
+
[id, tenantId],
|
|
839
|
+
);
|
|
840
|
+
return (result.rowCount ?? 0) > 0;
|
|
841
|
+
}
|
|
842
|
+
|
|
831
843
|
/** Get a single run result by ID with tenant isolation */
|
|
832
844
|
private async getRunResultById(tenantId: string, id: string): Promise<EvalRunResult | null> {
|
|
833
845
|
await this.ensureInitialized();
|
|
@@ -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) {
|
|
@@ -374,7 +374,9 @@ export function mapRowToRunStep(row: any): RunStep {
|
|
|
374
374
|
edgeTo: row.edge_to,
|
|
375
375
|
edgePurpose: row.edge_purpose,
|
|
376
376
|
input: safeParse(row.input, undefined),
|
|
377
|
-
output:
|
|
377
|
+
output: typeof row.output === "string"
|
|
378
|
+
? safeParse(row.output, row.output as any)
|
|
379
|
+
: row.output ?? undefined,
|
|
378
380
|
status: row.status,
|
|
379
381
|
errorMessage: row.error_message,
|
|
380
382
|
startedAt: row.started_at,
|