@axiom-lattice/local-stores 1.0.21 → 1.0.24

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axiom-lattice/local-stores",
3
- "version": "1.0.21",
3
+ "version": "1.0.24",
4
4
  "description": "Local SQLite-based stores for Axiom Lattice framework",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -25,8 +25,8 @@
25
25
  "@types/sql.js": "^1.4.11",
26
26
  "sql.js": "^1.14.1",
27
27
  "uuid": "^14.0.1",
28
- "@axiom-lattice/core": "2.1.99",
29
- "@axiom-lattice/protocols": "2.1.51"
28
+ "@axiom-lattice/core": "2.1.102",
29
+ "@axiom-lattice/protocols": "2.1.53"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^20.11.24",
@@ -36,6 +36,7 @@ import { LocalThreadMessageQueueStore } from "./stores/LocalThreadMessageQueueSt
36
36
  import { LocalSkillStore } from "./stores/LocalSkillStore";
37
37
  import { LocalScheduleStorage } from "./stores/LocalScheduleStorage";
38
38
  import { LocalTaskStore } from "./stores/LocalTaskStore";
39
+ import { LocalTaskWorkItemStore } from "./stores/LocalTaskWorkItemStore";
39
40
 
40
41
  export interface LocalStoreConfigOptions {
41
42
  /**
@@ -80,6 +81,7 @@ export async function createLocalStoreConfig(options: LocalStoreConfigOptions =
80
81
  skill: new LocalSkillStore(db),
81
82
  schedule: new LocalScheduleStorage(db),
82
83
  task: new LocalTaskStore(db),
84
+ taskWorkItem: new LocalTaskWorkItemStore(db),
83
85
  checkpoint: SqliteSaver.fromConnString(dbPath),
84
86
  };
85
87
  }
package/src/index.ts CHANGED
@@ -47,3 +47,4 @@ export { LocalThreadMessageQueueStore } from "./stores/LocalThreadMessageQueueSt
47
47
  export { LocalSkillStore } from "./stores/LocalSkillStore";
48
48
  export { LocalScheduleStorage } from "./stores/LocalScheduleStorage";
49
49
  export { LocalTaskStore } from "./stores/LocalTaskStore";
50
+ export { LocalTaskWorkItemStore } from "./stores/LocalTaskWorkItemStore";
@@ -42,6 +42,13 @@ export class LocalConnectionStore implements ConnectionStore {
42
42
  ensureTable(db, DDL);
43
43
  }
44
44
 
45
+ async listByTenant(tenantId: string): Promise<ConnectionEntry[]> {
46
+ const rows = this.db.prepare(
47
+ `SELECT * FROM connection_configs WHERE tenant_id = ? ORDER BY created_at`,
48
+ ).all(tenantId) as unknown as ConnectionRow[];
49
+ return rows.map((r) => this.mapRow(r));
50
+ }
51
+
45
52
  async listByType(tenantId: string, type: string): Promise<ConnectionEntry[]> {
46
53
  const rows = this.db.prepare(
47
54
  `SELECT * FROM connection_configs WHERE tenant_id = ? AND type = ? ORDER BY created_at`,
@@ -404,6 +404,14 @@ export class LocalEvalStore implements EvalStore {
404
404
  return this.getRunResultById(tenantId, id);
405
405
  }
406
406
 
407
+ async deleteRunResult(tenantId: string, id: string): Promise<boolean> {
408
+ const result = this.db.prepare(
409
+ `DELETE FROM lt_eval_run_results
410
+ WHERE id = ? AND run_id IN (SELECT id FROM lt_eval_runs WHERE tenant_id = ?)`,
411
+ ).run(id, tenantId);
412
+ return result.changes > 0;
413
+ }
414
+
407
415
  // -------------------------------------------------------------------------
408
416
  // Reports
409
417
  // -------------------------------------------------------------------------
@@ -28,6 +28,12 @@ CREATE TABLE IF NOT EXISTS lt_tasks (
28
28
  parent_id TEXT,
29
29
  source_id TEXT,
30
30
  context TEXT,
31
+ require_review INTEGER DEFAULT 0,
32
+ dependencies TEXT,
33
+ result TEXT,
34
+ failure_reason TEXT,
35
+ workspace_id TEXT,
36
+ project_id TEXT,
31
37
  created_at TEXT NOT NULL,
32
38
  updated_at TEXT NOT NULL,
33
39
  PRIMARY KEY (tenant_id, id)
@@ -48,6 +54,12 @@ interface TaskRow {
48
54
  parent_id: string | null;
49
55
  source_id: string | null;
50
56
  context: string | null;
57
+ require_review: number | null;
58
+ dependencies: string | null;
59
+ result: string | null;
60
+ failure_reason: string | null;
61
+ workspace_id: string | null;
62
+ project_id: string | null;
51
63
  created_at: string;
52
64
  updated_at: string;
53
65
  }
@@ -67,6 +79,12 @@ function mapRowToTask(row: TaskRow): TaskItem {
67
79
  parentId: row.parent_id ?? undefined,
68
80
  sourceId: row.source_id ?? undefined,
69
81
  context: row.context ? JSON.parse(row.context) : undefined,
82
+ requireReview: row.require_review === 1 ? true : (row.require_review ? true : undefined),
83
+ dependencies: row.dependencies ? JSON.parse(row.dependencies) : undefined,
84
+ result: row.result || undefined,
85
+ failureReason: row.failure_reason || undefined,
86
+ workspaceId: row.workspace_id ?? undefined,
87
+ projectId: row.project_id ?? undefined,
70
88
  createdAt: parseISO(row.created_at),
71
89
  updatedAt: parseISO(row.updated_at),
72
90
  };
@@ -78,6 +96,12 @@ export class LocalTaskStore implements TaskStore {
78
96
  constructor(db: DatabaseWrapper) {
79
97
  this.db = db;
80
98
  ensureTable(db, DDL);
99
+ this.db.exec(`ALTER TABLE lt_tasks ADD COLUMN require_review INTEGER DEFAULT 0;`);
100
+ this.db.exec(`ALTER TABLE lt_tasks ADD COLUMN dependencies TEXT;`);
101
+ this.db.exec(`ALTER TABLE lt_tasks ADD COLUMN result TEXT;`);
102
+ this.db.exec(`ALTER TABLE lt_tasks ADD COLUMN failure_reason TEXT;`);
103
+ this.db.exec(`ALTER TABLE lt_tasks ADD COLUMN workspace_id TEXT;`);
104
+ this.db.exec(`ALTER TABLE lt_tasks ADD COLUMN project_id TEXT;`);
81
105
  }
82
106
 
83
107
  async create(
@@ -87,14 +111,19 @@ export class LocalTaskStore implements TaskStore {
87
111
  const now = nowISO();
88
112
 
89
113
  this.db.prepare(
90
- `INSERT INTO lt_tasks (id, tenant_id, owner_type, owner_id, title, description, status, priority, due_date, metadata, parent_id, source_id, context, created_at, updated_at)
91
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
114
+ `INSERT INTO lt_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)
115
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
92
116
  ).run(
93
117
  id, params.tenantId, params.ownerType, params.ownerId, params.title,
94
118
  params.description || null, params.status || 'pending', params.priority || 'medium',
95
119
  params.dueDate || null, params.metadata ? JSON.stringify(params.metadata) : null,
96
120
  params.parentId || null, params.sourceId || null,
97
- params.context ? JSON.stringify(params.context) : null, now, now,
121
+ params.context ? JSON.stringify(params.context) : null,
122
+ params.requireReview ? 1 : 0,
123
+ params.dependencies ? JSON.stringify(params.dependencies) : null,
124
+ params.result || null, params.failureReason || null,
125
+ params.workspaceId || null, params.projectId || null,
126
+ now, now,
98
127
  );
99
128
 
100
129
  return (await this.getById(params.tenantId, id))!;
@@ -113,8 +142,15 @@ export class LocalTaskStore implements TaskStore {
113
142
 
114
143
  if (filter.ownerType) { conditions.push('owner_type = ?'); params.push(filter.ownerType); }
115
144
  if (filter.ownerId) { conditions.push('owner_id = ?'); params.push(filter.ownerId); }
116
- if (filter.status) { conditions.push('status = ?'); params.push(filter.status); }
145
+ if (filter.status) {
146
+ const statuses = filter.status.split(',').map(s => s.trim()).filter(Boolean);
147
+ const placeholders = statuses.map(() => '?').join(', ');
148
+ conditions.push(`status IN (${placeholders})`);
149
+ params.push(...statuses);
150
+ }
117
151
  if (filter.priority) { conditions.push('priority = ?'); params.push(filter.priority); }
152
+ if (filter.workspaceId) { conditions.push('workspace_id = ?'); params.push(filter.workspaceId); }
153
+ if (filter.projectId) { conditions.push('project_id = ?'); params.push(filter.projectId); }
118
154
  if (filter.parentId) { conditions.push('parent_id = ?'); params.push(filter.parentId); }
119
155
  if (filter.sourceId) { conditions.push('source_id = ?'); params.push(filter.sourceId); }
120
156
  if (filter.metadata) {
@@ -160,6 +196,12 @@ export class LocalTaskStore implements TaskStore {
160
196
  if (updates.context !== undefined) { setClauses.push('context = ?'); values.push(JSON.stringify(updates.context)); }
161
197
  if (updates.ownerType !== undefined) { setClauses.push('owner_type = ?'); values.push(updates.ownerType); }
162
198
  if (updates.ownerId !== undefined) { setClauses.push('owner_id = ?'); values.push(updates.ownerId); }
199
+ if (updates.requireReview !== undefined) { setClauses.push('require_review = ?'); values.push(updates.requireReview ? 1 : 0); }
200
+ if (updates.dependencies !== undefined) { setClauses.push('dependencies = ?'); values.push(JSON.stringify(updates.dependencies)); }
201
+ if (updates.result !== undefined) { setClauses.push('result = ?'); values.push(updates.result); }
202
+ if (updates.failureReason !== undefined) { setClauses.push('failure_reason = ?'); values.push(updates.failureReason); }
203
+ if (updates.workspaceId !== undefined) { setClauses.push('workspace_id = ?'); values.push(updates.workspaceId); }
204
+ if (updates.projectId !== undefined) { setClauses.push('project_id = ?'); values.push(updates.projectId); }
163
205
 
164
206
  if (setClauses.length === 1) return existing;
165
207
 
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Local SQLite implementation of TaskWorkItemStore.
3
+ */
4
+
5
+ import { DatabaseWrapper } from "../database";
6
+ import type {
7
+ TaskWorkItemStore,
8
+ TaskWorkItem,
9
+ CreateWorkItemRequest,
10
+ TaskWorkItemListFilter,
11
+ } from "@axiom-lattice/protocols";
12
+ import { ensureTable, nowISO, parseISO } from "../database";
13
+ import { v4 as uuid } from "uuid";
14
+
15
+ const DDL = `
16
+ CREATE TABLE IF NOT EXISTS lt_task_work_items (
17
+ id TEXT NOT NULL,
18
+ tenant_id TEXT NOT NULL,
19
+ task_id TEXT NOT NULL,
20
+ action TEXT NOT NULL,
21
+ actor TEXT NOT NULL,
22
+ thread_id TEXT,
23
+ summary TEXT,
24
+ detail TEXT,
25
+ attempt INTEGER,
26
+ workspace_id TEXT,
27
+ project_id TEXT,
28
+ created_at TEXT NOT NULL,
29
+ PRIMARY KEY (tenant_id, id)
30
+ );
31
+ `;
32
+
33
+ interface WorkItemRow {
34
+ id: string;
35
+ tenant_id: string;
36
+ task_id: string;
37
+ action: string;
38
+ actor: string;
39
+ thread_id: string | null;
40
+ summary: string | null;
41
+ detail: string | null;
42
+ attempt: number | null;
43
+ workspace_id: string | null;
44
+ project_id: string | null;
45
+ created_at: string;
46
+ }
47
+
48
+ function mapRowToWorkItem(row: WorkItemRow): TaskWorkItem {
49
+ return {
50
+ id: row.id,
51
+ tenantId: row.tenant_id,
52
+ taskId: row.task_id,
53
+ action: row.action,
54
+ actor: row.actor,
55
+ threadId: row.thread_id ?? undefined,
56
+ summary: row.summary ?? undefined,
57
+ detail: row.detail ? JSON.parse(row.detail) : undefined,
58
+ attempt: row.attempt ?? undefined,
59
+ workspaceId: row.workspace_id ?? undefined,
60
+ projectId: row.project_id ?? undefined,
61
+ createdAt: parseISO(row.created_at),
62
+ };
63
+ }
64
+
65
+ export class LocalTaskWorkItemStore implements TaskWorkItemStore {
66
+ private db: DatabaseWrapper;
67
+
68
+ constructor(db: DatabaseWrapper) {
69
+ this.db = db;
70
+ ensureTable(db, DDL);
71
+ this.db.exec(`ALTER TABLE lt_task_work_items ADD COLUMN workspace_id TEXT;`);
72
+ this.db.exec(`ALTER TABLE lt_task_work_items ADD COLUMN project_id TEXT;`);
73
+ }
74
+
75
+ async create(params: CreateWorkItemRequest): Promise<TaskWorkItem> {
76
+ const id = uuid();
77
+ const now = nowISO();
78
+
79
+ this.db.prepare(
80
+ `INSERT INTO lt_task_work_items (id, tenant_id, task_id, action, actor, thread_id, summary, detail, attempt, workspace_id, project_id, created_at)
81
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
82
+ ).run(
83
+ id, params.tenantId, params.taskId, params.action, params.actor,
84
+ params.threadId || null, params.summary || null,
85
+ params.detail ? JSON.stringify(params.detail) : null,
86
+ params.attempt ?? null,
87
+ params.workspaceId || null,
88
+ params.projectId || null,
89
+ now,
90
+ );
91
+
92
+ const row = this.db.prepare(
93
+ `SELECT * FROM lt_task_work_items WHERE tenant_id = ? AND id = ?`,
94
+ ).get(params.tenantId, id) as unknown as WorkItemRow | undefined;
95
+ return mapRowToWorkItem(row!);
96
+ }
97
+
98
+ async list(filter: TaskWorkItemListFilter): Promise<TaskWorkItem[]> {
99
+ const conditions: string[] = ['tenant_id = ?', 'task_id = ?'];
100
+ const params: unknown[] = [filter.tenantId, filter.taskId];
101
+
102
+ if (filter.action) { conditions.push('action = ?'); params.push(filter.action); }
103
+
104
+ const where = conditions.join(' AND ');
105
+ const limit = filter.limit || 100;
106
+ const offset = filter.offset || 0;
107
+
108
+ const rows = this.db.prepare(
109
+ `SELECT * FROM lt_task_work_items WHERE ${where} ORDER BY created_at DESC LIMIT ? OFFSET ?`,
110
+ ).all(...params, limit, offset) as unknown as WorkItemRow[];
111
+ return rows.map(mapRowToWorkItem);
112
+ }
113
+ }