@agentlensai/server 0.3.0 → 0.6.0
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/dist/db/embedding-store.d.ts +74 -0
- package/dist/db/embedding-store.d.ts.map +1 -0
- package/dist/db/embedding-store.js +177 -0
- package/dist/db/embedding-store.js.map +1 -0
- package/dist/db/health-snapshot-store.d.ts +33 -0
- package/dist/db/health-snapshot-store.d.ts.map +1 -0
- package/dist/db/health-snapshot-store.js +112 -0
- package/dist/db/health-snapshot-store.js.map +1 -0
- package/dist/db/lesson-store.d.ts +57 -0
- package/dist/db/lesson-store.d.ts.map +1 -0
- package/dist/db/lesson-store.js +217 -0
- package/dist/db/lesson-store.js.map +1 -0
- package/dist/db/migrate.d.ts.map +1 -1
- package/dist/db/migrate.js +256 -8
- package/dist/db/migrate.js.map +1 -1
- package/dist/db/schema.sqlite.d.ts +822 -47
- package/dist/db/schema.sqlite.d.ts.map +1 -1
- package/dist/db/schema.sqlite.js +79 -4
- package/dist/db/schema.sqlite.js.map +1 -1
- package/dist/db/session-summary-store.d.ts +45 -0
- package/dist/db/session-summary-store.d.ts.map +1 -0
- package/dist/db/session-summary-store.js +112 -0
- package/dist/db/session-summary-store.js.map +1 -0
- package/dist/db/sqlite-store.d.ts +19 -12
- package/dist/db/sqlite-store.d.ts.map +1 -1
- package/dist/db/sqlite-store.js +145 -44
- package/dist/db/sqlite-store.js.map +1 -1
- package/dist/db/tenant-scoped-store.d.ts +61 -0
- package/dist/db/tenant-scoped-store.d.ts.map +1 -0
- package/dist/db/tenant-scoped-store.js +94 -0
- package/dist/db/tenant-scoped-store.js.map +1 -0
- package/dist/index.d.ts +18 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +78 -5
- package/dist/index.js.map +1 -1
- package/dist/lib/alert-engine.d.ts +11 -0
- package/dist/lib/alert-engine.d.ts.map +1 -1
- package/dist/lib/alert-engine.js +65 -24
- package/dist/lib/alert-engine.js.map +1 -1
- package/dist/lib/analysis/cost-analysis.d.ts +20 -0
- package/dist/lib/analysis/cost-analysis.d.ts.map +1 -0
- package/dist/lib/analysis/cost-analysis.js +161 -0
- package/dist/lib/analysis/cost-analysis.js.map +1 -0
- package/dist/lib/analysis/error-patterns.d.ts +26 -0
- package/dist/lib/analysis/error-patterns.d.ts.map +1 -0
- package/dist/lib/analysis/error-patterns.js +158 -0
- package/dist/lib/analysis/error-patterns.js.map +1 -0
- package/dist/lib/analysis/index.d.ts +23 -0
- package/dist/lib/analysis/index.d.ts.map +1 -0
- package/dist/lib/analysis/index.js +144 -0
- package/dist/lib/analysis/index.js.map +1 -0
- package/dist/lib/analysis/performance-trends.d.ts +19 -0
- package/dist/lib/analysis/performance-trends.d.ts.map +1 -0
- package/dist/lib/analysis/performance-trends.js +121 -0
- package/dist/lib/analysis/performance-trends.js.map +1 -0
- package/dist/lib/analysis/tool-sequences.d.ts +19 -0
- package/dist/lib/analysis/tool-sequences.d.ts.map +1 -0
- package/dist/lib/analysis/tool-sequences.js +148 -0
- package/dist/lib/analysis/tool-sequences.js.map +1 -0
- package/dist/lib/context/index.d.ts +5 -0
- package/dist/lib/context/index.d.ts.map +1 -0
- package/dist/lib/context/index.js +5 -0
- package/dist/lib/context/index.js.map +1 -0
- package/dist/lib/context/retrieval.d.ts +60 -0
- package/dist/lib/context/retrieval.d.ts.map +1 -0
- package/dist/lib/context/retrieval.js +233 -0
- package/dist/lib/context/retrieval.js.map +1 -0
- package/dist/lib/embeddings/index.d.ts +31 -0
- package/dist/lib/embeddings/index.d.ts.map +1 -0
- package/dist/lib/embeddings/index.js +31 -0
- package/dist/lib/embeddings/index.js.map +1 -0
- package/dist/lib/embeddings/local.d.ts +15 -0
- package/dist/lib/embeddings/local.d.ts.map +1 -0
- package/dist/lib/embeddings/local.js +65 -0
- package/dist/lib/embeddings/local.js.map +1 -0
- package/dist/lib/embeddings/math.d.ts +13 -0
- package/dist/lib/embeddings/math.d.ts.map +1 -0
- package/dist/lib/embeddings/math.js +35 -0
- package/dist/lib/embeddings/math.js.map +1 -0
- package/dist/lib/embeddings/openai.d.ts +15 -0
- package/dist/lib/embeddings/openai.d.ts.map +1 -0
- package/dist/lib/embeddings/openai.js +58 -0
- package/dist/lib/embeddings/openai.js.map +1 -0
- package/dist/lib/embeddings/summarizer.d.ts +26 -0
- package/dist/lib/embeddings/summarizer.d.ts.map +1 -0
- package/dist/lib/embeddings/summarizer.js +181 -0
- package/dist/lib/embeddings/summarizer.js.map +1 -0
- package/dist/lib/embeddings/types.d.ts +17 -0
- package/dist/lib/embeddings/types.d.ts.map +1 -0
- package/dist/lib/embeddings/types.js +5 -0
- package/dist/lib/embeddings/types.js.map +1 -0
- package/dist/lib/embeddings/worker.d.ts +56 -0
- package/dist/lib/embeddings/worker.d.ts.map +1 -0
- package/dist/lib/embeddings/worker.js +109 -0
- package/dist/lib/embeddings/worker.js.map +1 -0
- package/dist/lib/health/computer.d.ts +28 -0
- package/dist/lib/health/computer.d.ts.map +1 -0
- package/dist/lib/health/computer.js +270 -0
- package/dist/lib/health/computer.js.map +1 -0
- package/dist/lib/optimization/classifier.d.ts +34 -0
- package/dist/lib/optimization/classifier.d.ts.map +1 -0
- package/dist/lib/optimization/classifier.js +108 -0
- package/dist/lib/optimization/classifier.js.map +1 -0
- package/dist/lib/optimization/engine.d.ts +24 -0
- package/dist/lib/optimization/engine.d.ts.map +1 -0
- package/dist/lib/optimization/engine.js +202 -0
- package/dist/lib/optimization/engine.js.map +1 -0
- package/dist/lib/optimization/index.d.ts +10 -0
- package/dist/lib/optimization/index.d.ts.map +1 -0
- package/dist/lib/optimization/index.js +9 -0
- package/dist/lib/optimization/index.js.map +1 -0
- package/dist/lib/sse.d.ts +1 -0
- package/dist/lib/sse.d.ts.map +1 -1
- package/dist/lib/sse.js +8 -1
- package/dist/lib/sse.js.map +1 -1
- package/dist/middleware/auth.d.ts +1 -0
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +2 -1
- package/dist/middleware/auth.js.map +1 -1
- package/dist/routes/agents.d.ts.map +1 -1
- package/dist/routes/agents.js +6 -3
- package/dist/routes/agents.js.map +1 -1
- package/dist/routes/alerts.d.ts.map +1 -1
- package/dist/routes/alerts.js +15 -7
- package/dist/routes/alerts.js.map +1 -1
- package/dist/routes/analytics.d.ts.map +1 -1
- package/dist/routes/analytics.js +16 -2
- package/dist/routes/analytics.js.map +1 -1
- package/dist/routes/api-keys.d.ts.map +1 -1
- package/dist/routes/api-keys.js +30 -5
- package/dist/routes/api-keys.js.map +1 -1
- package/dist/routes/context.d.ts +23 -0
- package/dist/routes/context.d.ts.map +1 -0
- package/dist/routes/context.js +52 -0
- package/dist/routes/context.js.map +1 -0
- package/dist/routes/events.d.ts +6 -1
- package/dist/routes/events.d.ts.map +1 -1
- package/dist/routes/events.js +61 -6
- package/dist/routes/events.js.map +1 -1
- package/dist/routes/health.d.ts +21 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +142 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/ingest.d.ts +6 -0
- package/dist/routes/ingest.d.ts.map +1 -1
- package/dist/routes/ingest.js +23 -4
- package/dist/routes/ingest.js.map +1 -1
- package/dist/routes/lessons.d.ts +19 -0
- package/dist/routes/lessons.d.ts.map +1 -0
- package/dist/routes/lessons.js +164 -0
- package/dist/routes/lessons.js.map +1 -0
- package/dist/routes/optimize.d.ts +15 -0
- package/dist/routes/optimize.d.ts.map +1 -0
- package/dist/routes/optimize.js +55 -0
- package/dist/routes/optimize.js.map +1 -0
- package/dist/routes/recall.d.ts +22 -0
- package/dist/routes/recall.d.ts.map +1 -0
- package/dist/routes/recall.js +91 -0
- package/dist/routes/recall.js.map +1 -0
- package/dist/routes/reflect.d.ts +15 -0
- package/dist/routes/reflect.d.ts.map +1 -0
- package/dist/routes/reflect.js +54 -0
- package/dist/routes/reflect.js.map +1 -0
- package/dist/routes/sessions.d.ts.map +1 -1
- package/dist/routes/sessions.js +8 -6
- package/dist/routes/sessions.js.map +1 -1
- package/dist/routes/stats.d.ts.map +1 -1
- package/dist/routes/stats.js +3 -1
- package/dist/routes/stats.js.map +1 -1
- package/dist/routes/stream.d.ts +9 -2
- package/dist/routes/stream.d.ts.map +1 -1
- package/dist/routes/stream.js +55 -2
- package/dist/routes/stream.js.map +1 -1
- package/dist/routes/tenant-helper.d.ts +20 -0
- package/dist/routes/tenant-helper.d.ts.map +1 -0
- package/dist/routes/tenant-helper.js +35 -0
- package/dist/routes/tenant-helper.js.map +1 -0
- package/package.json +11 -11
- package/LICENSE +0 -21
- package/dist/__tests__/agents-stats.test.d.ts +0 -5
- package/dist/__tests__/agents-stats.test.d.ts.map +0 -1
- package/dist/__tests__/agents-stats.test.js +0 -134
- package/dist/__tests__/agents-stats.test.js.map +0 -1
- package/dist/__tests__/alerts.test.d.ts +0 -5
- package/dist/__tests__/alerts.test.d.ts.map +0 -1
- package/dist/__tests__/alerts.test.js +0 -245
- package/dist/__tests__/alerts.test.js.map +0 -1
- package/dist/__tests__/analytics.test.d.ts +0 -5
- package/dist/__tests__/analytics.test.d.ts.map +0 -1
- package/dist/__tests__/analytics.test.js +0 -218
- package/dist/__tests__/analytics.test.js.map +0 -1
- package/dist/__tests__/api-keys.test.d.ts +0 -5
- package/dist/__tests__/api-keys.test.d.ts.map +0 -1
- package/dist/__tests__/api-keys.test.js +0 -118
- package/dist/__tests__/api-keys.test.js.map +0 -1
- package/dist/__tests__/auth-no-db.test.d.ts +0 -2
- package/dist/__tests__/auth-no-db.test.d.ts.map +0 -1
- package/dist/__tests__/auth-no-db.test.js +0 -43
- package/dist/__tests__/auth-no-db.test.js.map +0 -1
- package/dist/__tests__/auth.test.d.ts +0 -5
- package/dist/__tests__/auth.test.d.ts.map +0 -1
- package/dist/__tests__/auth.test.js +0 -86
- package/dist/__tests__/auth.test.js.map +0 -1
- package/dist/__tests__/config.test.d.ts +0 -2
- package/dist/__tests__/config.test.d.ts.map +0 -1
- package/dist/__tests__/config.test.js +0 -37
- package/dist/__tests__/config.test.js.map +0 -1
- package/dist/__tests__/events-ingest.test.d.ts +0 -5
- package/dist/__tests__/events-ingest.test.d.ts.map +0 -1
- package/dist/__tests__/events-ingest.test.js +0 -248
- package/dist/__tests__/events-ingest.test.js.map +0 -1
- package/dist/__tests__/events-query.test.d.ts +0 -5
- package/dist/__tests__/events-query.test.d.ts.map +0 -1
- package/dist/__tests__/events-query.test.js +0 -205
- package/dist/__tests__/events-query.test.js.map +0 -1
- package/dist/__tests__/health.test.d.ts +0 -5
- package/dist/__tests__/health.test.d.ts.map +0 -1
- package/dist/__tests__/health.test.js +0 -40
- package/dist/__tests__/health.test.js.map +0 -1
- package/dist/__tests__/ingest.test.d.ts +0 -8
- package/dist/__tests__/ingest.test.d.ts.map +0 -1
- package/dist/__tests__/ingest.test.js +0 -469
- package/dist/__tests__/ingest.test.js.map +0 -1
- package/dist/__tests__/llm-tracking.test.d.ts +0 -10
- package/dist/__tests__/llm-tracking.test.d.ts.map +0 -1
- package/dist/__tests__/llm-tracking.test.js +0 -602
- package/dist/__tests__/llm-tracking.test.js.map +0 -1
- package/dist/__tests__/sessions.test.d.ts +0 -5
- package/dist/__tests__/sessions.test.d.ts.map +0 -1
- package/dist/__tests__/sessions.test.js +0 -176
- package/dist/__tests__/sessions.test.js.map +0 -1
- package/dist/__tests__/stream.test.d.ts +0 -5
- package/dist/__tests__/stream.test.d.ts.map +0 -1
- package/dist/__tests__/stream.test.js +0 -352
- package/dist/__tests__/stream.test.js.map +0 -1
- package/dist/__tests__/test-helpers.d.ts +0 -24
- package/dist/__tests__/test-helpers.d.ts.map +0 -1
- package/dist/__tests__/test-helpers.js +0 -45
- package/dist/__tests__/test-helpers.js.map +0 -1
- package/dist/db/__tests__/init.test.d.ts +0 -2
- package/dist/db/__tests__/init.test.d.ts.map +0 -1
- package/dist/db/__tests__/init.test.js +0 -73
- package/dist/db/__tests__/init.test.js.map +0 -1
- package/dist/db/__tests__/sqlite-store-read.test.d.ts +0 -2
- package/dist/db/__tests__/sqlite-store-read.test.d.ts.map +0 -1
- package/dist/db/__tests__/sqlite-store-read.test.js +0 -749
- package/dist/db/__tests__/sqlite-store-read.test.js.map +0 -1
- package/dist/db/__tests__/sqlite-store-write.test.d.ts +0 -2
- package/dist/db/__tests__/sqlite-store-write.test.d.ts.map +0 -1
- package/dist/db/__tests__/sqlite-store-write.test.js +0 -418
- package/dist/db/__tests__/sqlite-store-write.test.js.map +0 -1
- package/dist/lib/__tests__/alert-engine.test.d.ts +0 -5
- package/dist/lib/__tests__/alert-engine.test.d.ts.map +0 -1
- package/dist/lib/__tests__/alert-engine.test.js +0 -211
- package/dist/lib/__tests__/alert-engine.test.js.map +0 -1
- package/dist/lib/__tests__/retention.test.d.ts +0 -2
- package/dist/lib/__tests__/retention.test.d.ts.map +0 -1
- package/dist/lib/__tests__/retention.test.js +0 -238
- package/dist/lib/__tests__/retention.test.js.map +0 -1
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lesson Store (Story 3.1)
|
|
3
|
+
*
|
|
4
|
+
* CRUD operations for the lessons table with tenant isolation.
|
|
5
|
+
*/
|
|
6
|
+
import { randomUUID } from 'node:crypto';
|
|
7
|
+
import { eq, and, or, sql, isNull } from 'drizzle-orm';
|
|
8
|
+
import { lessons } from './schema.sqlite.js';
|
|
9
|
+
import { NotFoundError } from './errors.js';
|
|
10
|
+
/** Valid importance values for runtime validation */
|
|
11
|
+
const VALID_IMPORTANCE = new Set(['low', 'normal', 'high', 'critical']);
|
|
12
|
+
/** Escape LIKE wildcard characters to prevent injection */
|
|
13
|
+
function escapeLike(s) {
|
|
14
|
+
return s.replace(/[%_]/g, '\\$&');
|
|
15
|
+
}
|
|
16
|
+
/** Parse a DB row into a Lesson */
|
|
17
|
+
function rowToLesson(row) {
|
|
18
|
+
return {
|
|
19
|
+
id: row.id,
|
|
20
|
+
tenantId: row.tenantId,
|
|
21
|
+
agentId: row.agentId ?? undefined,
|
|
22
|
+
category: row.category,
|
|
23
|
+
title: row.title,
|
|
24
|
+
content: row.content,
|
|
25
|
+
context: JSON.parse(row.context),
|
|
26
|
+
importance: VALID_IMPORTANCE.has(row.importance) ? row.importance : 'normal',
|
|
27
|
+
sourceSessionId: row.sourceSessionId ?? undefined,
|
|
28
|
+
sourceEventId: row.sourceEventId ?? undefined,
|
|
29
|
+
accessCount: row.accessCount,
|
|
30
|
+
lastAccessedAt: row.lastAccessedAt ?? undefined,
|
|
31
|
+
createdAt: row.createdAt,
|
|
32
|
+
updatedAt: row.updatedAt,
|
|
33
|
+
archivedAt: row.archivedAt ?? undefined,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export class LessonStore {
|
|
37
|
+
db;
|
|
38
|
+
constructor(db) {
|
|
39
|
+
this.db = db;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create a new lesson.
|
|
43
|
+
*/
|
|
44
|
+
create(tenantId, input) {
|
|
45
|
+
const now = new Date().toISOString();
|
|
46
|
+
const id = randomUUID();
|
|
47
|
+
const row = {
|
|
48
|
+
id,
|
|
49
|
+
tenantId,
|
|
50
|
+
agentId: input.agentId ?? null,
|
|
51
|
+
category: input.category ?? 'general',
|
|
52
|
+
title: input.title,
|
|
53
|
+
content: input.content,
|
|
54
|
+
context: JSON.stringify(input.context ?? {}),
|
|
55
|
+
importance: input.importance ?? 'normal',
|
|
56
|
+
sourceSessionId: input.sourceSessionId ?? null,
|
|
57
|
+
sourceEventId: input.sourceEventId ?? null,
|
|
58
|
+
accessCount: 0,
|
|
59
|
+
lastAccessedAt: null,
|
|
60
|
+
createdAt: now,
|
|
61
|
+
updatedAt: now,
|
|
62
|
+
archivedAt: null,
|
|
63
|
+
};
|
|
64
|
+
this.db.insert(lessons).values(row).run();
|
|
65
|
+
return rowToLesson(row);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get a lesson by ID. Increments access_count and updates last_accessed_at.
|
|
69
|
+
* Wrapped in a transaction for atomicity.
|
|
70
|
+
*/
|
|
71
|
+
get(tenantId, id) {
|
|
72
|
+
return this.db.transaction((tx) => {
|
|
73
|
+
const row = tx
|
|
74
|
+
.select()
|
|
75
|
+
.from(lessons)
|
|
76
|
+
.where(and(eq(lessons.id, id), eq(lessons.tenantId, tenantId)))
|
|
77
|
+
.get();
|
|
78
|
+
if (!row)
|
|
79
|
+
return null;
|
|
80
|
+
// Atomic increment — uses SQL expression to avoid read-then-write race
|
|
81
|
+
const now = new Date().toISOString();
|
|
82
|
+
tx.update(lessons)
|
|
83
|
+
.set({
|
|
84
|
+
accessCount: sql `${lessons.accessCount} + 1`,
|
|
85
|
+
lastAccessedAt: now,
|
|
86
|
+
})
|
|
87
|
+
.where(and(eq(lessons.id, id), eq(lessons.tenantId, tenantId)))
|
|
88
|
+
.run();
|
|
89
|
+
return rowToLesson({
|
|
90
|
+
...row,
|
|
91
|
+
accessCount: row.accessCount + 1,
|
|
92
|
+
lastAccessedAt: now,
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* List lessons with optional filters.
|
|
98
|
+
*/
|
|
99
|
+
list(tenantId, query) {
|
|
100
|
+
const conditions = [eq(lessons.tenantId, tenantId)];
|
|
101
|
+
if (!query?.includeArchived) {
|
|
102
|
+
conditions.push(isNull(lessons.archivedAt));
|
|
103
|
+
}
|
|
104
|
+
if (query?.agentId) {
|
|
105
|
+
conditions.push(eq(lessons.agentId, query.agentId));
|
|
106
|
+
}
|
|
107
|
+
if (query?.category) {
|
|
108
|
+
conditions.push(eq(lessons.category, query.category));
|
|
109
|
+
}
|
|
110
|
+
if (query?.importance) {
|
|
111
|
+
conditions.push(eq(lessons.importance, query.importance));
|
|
112
|
+
}
|
|
113
|
+
if (query?.search) {
|
|
114
|
+
const pattern = `%${escapeLike(query.search)}%`;
|
|
115
|
+
conditions.push(or(sql `${lessons.title} LIKE ${pattern} ESCAPE '\\'`, sql `${lessons.content} LIKE ${pattern} ESCAPE '\\'`));
|
|
116
|
+
}
|
|
117
|
+
const limit = query?.limit ?? 50;
|
|
118
|
+
const offset = query?.offset ?? 0;
|
|
119
|
+
const rows = this.db
|
|
120
|
+
.select()
|
|
121
|
+
.from(lessons)
|
|
122
|
+
.where(and(...conditions))
|
|
123
|
+
.limit(limit)
|
|
124
|
+
.offset(offset)
|
|
125
|
+
.orderBy(sql `${lessons.createdAt} DESC`)
|
|
126
|
+
.all();
|
|
127
|
+
return rows.map(rowToLesson);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Update a lesson (partial update).
|
|
131
|
+
*/
|
|
132
|
+
update(tenantId, id, updates) {
|
|
133
|
+
// Check existence
|
|
134
|
+
const existing = this.db
|
|
135
|
+
.select()
|
|
136
|
+
.from(lessons)
|
|
137
|
+
.where(and(eq(lessons.id, id), eq(lessons.tenantId, tenantId)))
|
|
138
|
+
.get();
|
|
139
|
+
if (!existing) {
|
|
140
|
+
throw new NotFoundError(`Lesson ${id} not found`);
|
|
141
|
+
}
|
|
142
|
+
const now = new Date().toISOString();
|
|
143
|
+
const setValues = { updatedAt: now };
|
|
144
|
+
if (updates.title !== undefined)
|
|
145
|
+
setValues['title'] = updates.title;
|
|
146
|
+
if (updates.content !== undefined)
|
|
147
|
+
setValues['content'] = updates.content;
|
|
148
|
+
if (updates.category !== undefined)
|
|
149
|
+
setValues['category'] = updates.category;
|
|
150
|
+
if (updates.importance !== undefined)
|
|
151
|
+
setValues['importance'] = updates.importance;
|
|
152
|
+
if (updates.agentId !== undefined)
|
|
153
|
+
setValues['agentId'] = updates.agentId;
|
|
154
|
+
if (updates.context !== undefined)
|
|
155
|
+
setValues['context'] = JSON.stringify(updates.context);
|
|
156
|
+
this.db
|
|
157
|
+
.update(lessons)
|
|
158
|
+
.set(setValues)
|
|
159
|
+
.where(and(eq(lessons.id, id), eq(lessons.tenantId, tenantId)))
|
|
160
|
+
.run();
|
|
161
|
+
// Fetch updated row
|
|
162
|
+
const updated = this.db
|
|
163
|
+
.select()
|
|
164
|
+
.from(lessons)
|
|
165
|
+
.where(and(eq(lessons.id, id), eq(lessons.tenantId, tenantId)))
|
|
166
|
+
.get();
|
|
167
|
+
return rowToLesson(updated);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Soft-delete (archive) a lesson.
|
|
171
|
+
*/
|
|
172
|
+
archive(tenantId, id) {
|
|
173
|
+
const existing = this.db
|
|
174
|
+
.select()
|
|
175
|
+
.from(lessons)
|
|
176
|
+
.where(and(eq(lessons.id, id), eq(lessons.tenantId, tenantId)))
|
|
177
|
+
.get();
|
|
178
|
+
if (!existing) {
|
|
179
|
+
throw new NotFoundError(`Lesson ${id} not found`);
|
|
180
|
+
}
|
|
181
|
+
const now = new Date().toISOString();
|
|
182
|
+
this.db
|
|
183
|
+
.update(lessons)
|
|
184
|
+
.set({ archivedAt: now, updatedAt: now })
|
|
185
|
+
.where(and(eq(lessons.id, id), eq(lessons.tenantId, tenantId)))
|
|
186
|
+
.run();
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Count lessons matching filters.
|
|
190
|
+
*/
|
|
191
|
+
count(tenantId, query) {
|
|
192
|
+
const conditions = [eq(lessons.tenantId, tenantId)];
|
|
193
|
+
if (!query?.includeArchived) {
|
|
194
|
+
conditions.push(isNull(lessons.archivedAt));
|
|
195
|
+
}
|
|
196
|
+
if (query?.agentId) {
|
|
197
|
+
conditions.push(eq(lessons.agentId, query.agentId));
|
|
198
|
+
}
|
|
199
|
+
if (query?.category) {
|
|
200
|
+
conditions.push(eq(lessons.category, query.category));
|
|
201
|
+
}
|
|
202
|
+
if (query?.importance) {
|
|
203
|
+
conditions.push(eq(lessons.importance, query.importance));
|
|
204
|
+
}
|
|
205
|
+
if (query?.search) {
|
|
206
|
+
const pattern = `%${escapeLike(query.search)}%`;
|
|
207
|
+
conditions.push(or(sql `${lessons.title} LIKE ${pattern} ESCAPE '\\'`, sql `${lessons.content} LIKE ${pattern} ESCAPE '\\'`));
|
|
208
|
+
}
|
|
209
|
+
const result = this.db
|
|
210
|
+
.select({ count: sql `count(*)` })
|
|
211
|
+
.from(lessons)
|
|
212
|
+
.where(and(...conditions))
|
|
213
|
+
.get();
|
|
214
|
+
return result?.count ?? 0;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=lesson-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lesson-store.js","sourceRoot":"","sources":["../../src/db/lesson-store.ts"],"names":[],"mappings":"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"}
|
package/dist/db/migrate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/db/migrate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/db/migrate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CA4YhD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,GAAG;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;CACtB,CAoBA"}
|
package/dist/db/migrate.js
CHANGED
|
@@ -32,7 +32,7 @@ export function runMigrations(db) {
|
|
|
32
32
|
`);
|
|
33
33
|
db.run(sql `
|
|
34
34
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
35
|
-
id TEXT
|
|
35
|
+
id TEXT NOT NULL,
|
|
36
36
|
agent_id TEXT NOT NULL,
|
|
37
37
|
agent_name TEXT,
|
|
38
38
|
started_at TEXT NOT NULL,
|
|
@@ -45,17 +45,21 @@ export function runMigrations(db) {
|
|
|
45
45
|
llm_call_count INTEGER NOT NULL DEFAULT 0,
|
|
46
46
|
total_input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
47
47
|
total_output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
48
|
-
tags TEXT NOT NULL DEFAULT '[]'
|
|
48
|
+
tags TEXT NOT NULL DEFAULT '[]',
|
|
49
|
+
tenant_id TEXT NOT NULL DEFAULT 'default',
|
|
50
|
+
PRIMARY KEY (id, tenant_id)
|
|
49
51
|
)
|
|
50
52
|
`);
|
|
51
53
|
db.run(sql `
|
|
52
54
|
CREATE TABLE IF NOT EXISTS agents (
|
|
53
|
-
id TEXT
|
|
55
|
+
id TEXT NOT NULL,
|
|
54
56
|
name TEXT NOT NULL,
|
|
55
57
|
description TEXT,
|
|
56
58
|
first_seen_at TEXT NOT NULL,
|
|
57
59
|
last_seen_at TEXT NOT NULL,
|
|
58
|
-
session_count INTEGER NOT NULL DEFAULT 0
|
|
60
|
+
session_count INTEGER NOT NULL DEFAULT 0,
|
|
61
|
+
tenant_id TEXT NOT NULL DEFAULT 'default',
|
|
62
|
+
PRIMARY KEY (id, tenant_id)
|
|
59
63
|
)
|
|
60
64
|
`);
|
|
61
65
|
db.run(sql `
|
|
@@ -111,16 +115,260 @@ export function runMigrations(db) {
|
|
|
111
115
|
// Add LLM tracking columns to sessions (v0.3.0)
|
|
112
116
|
// SQLite doesn't support ADD COLUMN IF NOT EXISTS, so we check first
|
|
113
117
|
const sessionColumns = db.all(sql `PRAGMA table_info(sessions)`);
|
|
114
|
-
const
|
|
115
|
-
if (!
|
|
118
|
+
const sessionColumnNames = new Set(sessionColumns.map((c) => c.name));
|
|
119
|
+
if (!sessionColumnNames.has('llm_call_count')) {
|
|
116
120
|
db.run(sql `ALTER TABLE sessions ADD COLUMN llm_call_count INTEGER NOT NULL DEFAULT 0`);
|
|
117
121
|
}
|
|
118
|
-
if (!
|
|
122
|
+
if (!sessionColumnNames.has('total_input_tokens')) {
|
|
119
123
|
db.run(sql `ALTER TABLE sessions ADD COLUMN total_input_tokens INTEGER NOT NULL DEFAULT 0`);
|
|
120
124
|
}
|
|
121
|
-
if (!
|
|
125
|
+
if (!sessionColumnNames.has('total_output_tokens')) {
|
|
122
126
|
db.run(sql `ALTER TABLE sessions ADD COLUMN total_output_tokens INTEGER NOT NULL DEFAULT 0`);
|
|
123
127
|
}
|
|
128
|
+
// ─── Tenant isolation migration (Epic 1) ──────────────────
|
|
129
|
+
// Add tenant_id to all data tables for multi-tenant support
|
|
130
|
+
// api_keys.tenant_id
|
|
131
|
+
const apiKeyColumns = db.all(sql `PRAGMA table_info(api_keys)`);
|
|
132
|
+
const apiKeyColumnNames = new Set(apiKeyColumns.map((c) => c.name));
|
|
133
|
+
if (!apiKeyColumnNames.has('tenant_id')) {
|
|
134
|
+
db.run(sql `ALTER TABLE api_keys ADD COLUMN tenant_id TEXT NOT NULL DEFAULT 'default'`);
|
|
135
|
+
}
|
|
136
|
+
// events.tenant_id
|
|
137
|
+
const eventColumns = db.all(sql `PRAGMA table_info(events)`);
|
|
138
|
+
const eventColumnNames = new Set(eventColumns.map((c) => c.name));
|
|
139
|
+
if (!eventColumnNames.has('tenant_id')) {
|
|
140
|
+
db.run(sql `ALTER TABLE events ADD COLUMN tenant_id TEXT NOT NULL DEFAULT 'default'`);
|
|
141
|
+
}
|
|
142
|
+
// sessions.tenant_id
|
|
143
|
+
if (!sessionColumnNames.has('tenant_id')) {
|
|
144
|
+
db.run(sql `ALTER TABLE sessions ADD COLUMN tenant_id TEXT NOT NULL DEFAULT 'default'`);
|
|
145
|
+
}
|
|
146
|
+
// agents.tenant_id
|
|
147
|
+
const agentColumns = db.all(sql `PRAGMA table_info(agents)`);
|
|
148
|
+
const agentColumnNames = new Set(agentColumns.map((c) => c.name));
|
|
149
|
+
if (!agentColumnNames.has('tenant_id')) {
|
|
150
|
+
db.run(sql `ALTER TABLE agents ADD COLUMN tenant_id TEXT NOT NULL DEFAULT 'default'`);
|
|
151
|
+
}
|
|
152
|
+
// alert_rules.tenant_id
|
|
153
|
+
const alertRuleColumns = db.all(sql `PRAGMA table_info(alert_rules)`);
|
|
154
|
+
const alertRuleColumnNames = new Set(alertRuleColumns.map((c) => c.name));
|
|
155
|
+
if (!alertRuleColumnNames.has('tenant_id')) {
|
|
156
|
+
db.run(sql `ALTER TABLE alert_rules ADD COLUMN tenant_id TEXT NOT NULL DEFAULT 'default'`);
|
|
157
|
+
}
|
|
158
|
+
// alert_history.tenant_id
|
|
159
|
+
const alertHistoryColumns = db.all(sql `PRAGMA table_info(alert_history)`);
|
|
160
|
+
const alertHistoryColumnNames = new Set(alertHistoryColumns.map((c) => c.name));
|
|
161
|
+
if (!alertHistoryColumnNames.has('tenant_id')) {
|
|
162
|
+
db.run(sql `ALTER TABLE alert_history ADD COLUMN tenant_id TEXT NOT NULL DEFAULT 'default'`);
|
|
163
|
+
}
|
|
164
|
+
// Tenant isolation indexes
|
|
165
|
+
db.run(sql `CREATE INDEX IF NOT EXISTS idx_events_tenant_id ON events(tenant_id)`);
|
|
166
|
+
db.run(sql `CREATE INDEX IF NOT EXISTS idx_events_tenant_session ON events(tenant_id, session_id)`);
|
|
167
|
+
db.run(sql `CREATE INDEX IF NOT EXISTS idx_events_tenant_agent_ts ON events(tenant_id, agent_id, timestamp)`);
|
|
168
|
+
db.run(sql `CREATE INDEX IF NOT EXISTS idx_sessions_tenant_id ON sessions(tenant_id)`);
|
|
169
|
+
db.run(sql `CREATE INDEX IF NOT EXISTS idx_sessions_tenant_agent ON sessions(tenant_id, agent_id)`);
|
|
170
|
+
db.run(sql `CREATE INDEX IF NOT EXISTS idx_sessions_tenant_started ON sessions(tenant_id, started_at)`);
|
|
171
|
+
db.run(sql `CREATE INDEX IF NOT EXISTS idx_agents_tenant_id ON agents(tenant_id)`);
|
|
172
|
+
// ─── Embeddings table (Epic 2 — Story 2.2) ──────────────────
|
|
173
|
+
db.run(sql `
|
|
174
|
+
CREATE TABLE IF NOT EXISTS embeddings (
|
|
175
|
+
id TEXT PRIMARY KEY,
|
|
176
|
+
tenant_id TEXT NOT NULL,
|
|
177
|
+
source_type TEXT NOT NULL,
|
|
178
|
+
source_id TEXT NOT NULL,
|
|
179
|
+
content_hash TEXT NOT NULL,
|
|
180
|
+
text_content TEXT NOT NULL,
|
|
181
|
+
embedding BLOB NOT NULL,
|
|
182
|
+
embedding_model TEXT NOT NULL,
|
|
183
|
+
dimensions INTEGER NOT NULL,
|
|
184
|
+
created_at TEXT NOT NULL
|
|
185
|
+
)
|
|
186
|
+
`);
|
|
187
|
+
db.run(sql `CREATE INDEX IF NOT EXISTS idx_embeddings_tenant ON embeddings(tenant_id)`);
|
|
188
|
+
db.run(sql `CREATE INDEX IF NOT EXISTS idx_embeddings_source ON embeddings(source_type, source_id)`);
|
|
189
|
+
db.run(sql `CREATE INDEX IF NOT EXISTS idx_embeddings_content_hash ON embeddings(tenant_id, content_hash)`);
|
|
190
|
+
// ─── Session Summaries table (Epic 2 — Story 2.2) ──────────────────
|
|
191
|
+
db.run(sql `
|
|
192
|
+
CREATE TABLE IF NOT EXISTS session_summaries (
|
|
193
|
+
session_id TEXT NOT NULL,
|
|
194
|
+
tenant_id TEXT NOT NULL,
|
|
195
|
+
summary TEXT NOT NULL,
|
|
196
|
+
topics TEXT NOT NULL DEFAULT '[]',
|
|
197
|
+
tool_sequence TEXT NOT NULL DEFAULT '[]',
|
|
198
|
+
error_summary TEXT,
|
|
199
|
+
outcome TEXT,
|
|
200
|
+
created_at TEXT NOT NULL,
|
|
201
|
+
updated_at TEXT NOT NULL,
|
|
202
|
+
PRIMARY KEY (session_id, tenant_id)
|
|
203
|
+
)
|
|
204
|
+
`);
|
|
205
|
+
db.run(sql `CREATE INDEX IF NOT EXISTS idx_session_summaries_tenant ON session_summaries(tenant_id)`);
|
|
206
|
+
// ─── Composite PK migration (CRITICAL-2) ──────────────────
|
|
207
|
+
// SQLite doesn't support ALTER TABLE to change PKs, so we recreate
|
|
208
|
+
// tables with composite PKs (id, tenant_id) for tenant isolation.
|
|
209
|
+
// Check if sessions table still has single-column PK
|
|
210
|
+
// by looking at the CREATE TABLE statement
|
|
211
|
+
const sessionsSchema = db.get(sql `SELECT sql FROM sqlite_master WHERE type='table' AND name='sessions'`);
|
|
212
|
+
if (sessionsSchema && sessionsSchema.sql.includes('id TEXT PRIMARY KEY')) {
|
|
213
|
+
// Drop old indexes that reference sessions (they'll be recreated)
|
|
214
|
+
db.run(sql `DROP INDEX IF EXISTS idx_sessions_agent_id`);
|
|
215
|
+
db.run(sql `DROP INDEX IF EXISTS idx_sessions_started_at`);
|
|
216
|
+
db.run(sql `DROP INDEX IF EXISTS idx_sessions_status`);
|
|
217
|
+
db.run(sql `DROP INDEX IF EXISTS idx_sessions_tenant_id`);
|
|
218
|
+
db.run(sql `DROP INDEX IF EXISTS idx_sessions_tenant_agent`);
|
|
219
|
+
db.run(sql `DROP INDEX IF EXISTS idx_sessions_tenant_started`);
|
|
220
|
+
db.run(sql `
|
|
221
|
+
CREATE TABLE sessions_new (
|
|
222
|
+
id TEXT NOT NULL,
|
|
223
|
+
agent_id TEXT NOT NULL,
|
|
224
|
+
agent_name TEXT,
|
|
225
|
+
started_at TEXT NOT NULL,
|
|
226
|
+
ended_at TEXT,
|
|
227
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
228
|
+
event_count INTEGER NOT NULL DEFAULT 0,
|
|
229
|
+
tool_call_count INTEGER NOT NULL DEFAULT 0,
|
|
230
|
+
error_count INTEGER NOT NULL DEFAULT 0,
|
|
231
|
+
total_cost_usd REAL NOT NULL DEFAULT 0,
|
|
232
|
+
llm_call_count INTEGER NOT NULL DEFAULT 0,
|
|
233
|
+
total_input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
234
|
+
total_output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
235
|
+
tags TEXT NOT NULL DEFAULT '[]',
|
|
236
|
+
tenant_id TEXT NOT NULL DEFAULT 'default',
|
|
237
|
+
PRIMARY KEY (id, tenant_id)
|
|
238
|
+
)
|
|
239
|
+
`);
|
|
240
|
+
db.run(sql `
|
|
241
|
+
INSERT INTO sessions_new
|
|
242
|
+
SELECT id, agent_id, agent_name, started_at, ended_at, status,
|
|
243
|
+
event_count, tool_call_count, error_count, total_cost_usd,
|
|
244
|
+
llm_call_count, total_input_tokens, total_output_tokens,
|
|
245
|
+
tags, tenant_id
|
|
246
|
+
FROM sessions
|
|
247
|
+
`);
|
|
248
|
+
db.run(sql `DROP TABLE sessions`);
|
|
249
|
+
db.run(sql `ALTER TABLE sessions_new RENAME TO sessions`);
|
|
250
|
+
// Recreate indexes
|
|
251
|
+
db.run(sql `CREATE INDEX idx_sessions_agent_id ON sessions(agent_id)`);
|
|
252
|
+
db.run(sql `CREATE INDEX idx_sessions_started_at ON sessions(started_at)`);
|
|
253
|
+
db.run(sql `CREATE INDEX idx_sessions_status ON sessions(status)`);
|
|
254
|
+
db.run(sql `CREATE INDEX idx_sessions_tenant_id ON sessions(tenant_id)`);
|
|
255
|
+
db.run(sql `CREATE INDEX idx_sessions_tenant_agent ON sessions(tenant_id, agent_id)`);
|
|
256
|
+
db.run(sql `CREATE INDEX idx_sessions_tenant_started ON sessions(tenant_id, started_at)`);
|
|
257
|
+
}
|
|
258
|
+
// Check if agents table still has single-column PK
|
|
259
|
+
const agentsSchema = db.get(sql `SELECT sql FROM sqlite_master WHERE type='table' AND name='agents'`);
|
|
260
|
+
if (agentsSchema && agentsSchema.sql.includes('id TEXT PRIMARY KEY')) {
|
|
261
|
+
db.run(sql `DROP INDEX IF EXISTS idx_agents_tenant_id`);
|
|
262
|
+
db.run(sql `
|
|
263
|
+
CREATE TABLE agents_new (
|
|
264
|
+
id TEXT NOT NULL,
|
|
265
|
+
name TEXT NOT NULL,
|
|
266
|
+
description TEXT,
|
|
267
|
+
first_seen_at TEXT NOT NULL,
|
|
268
|
+
last_seen_at TEXT NOT NULL,
|
|
269
|
+
session_count INTEGER NOT NULL DEFAULT 0,
|
|
270
|
+
tenant_id TEXT NOT NULL DEFAULT 'default',
|
|
271
|
+
PRIMARY KEY (id, tenant_id)
|
|
272
|
+
)
|
|
273
|
+
`);
|
|
274
|
+
db.run(sql `
|
|
275
|
+
INSERT INTO agents_new
|
|
276
|
+
SELECT id, name, description, first_seen_at, last_seen_at,
|
|
277
|
+
session_count, tenant_id
|
|
278
|
+
FROM agents
|
|
279
|
+
`);
|
|
280
|
+
db.run(sql `DROP TABLE agents`);
|
|
281
|
+
db.run(sql `ALTER TABLE agents_new RENAME TO agents`);
|
|
282
|
+
db.run(sql `CREATE INDEX idx_agents_tenant_id ON agents(tenant_id)`);
|
|
283
|
+
}
|
|
284
|
+
// ─── Lessons table (Epic 3) ──────────────────────────────
|
|
285
|
+
db.run(sql `
|
|
286
|
+
CREATE TABLE IF NOT EXISTS lessons (
|
|
287
|
+
id TEXT NOT NULL,
|
|
288
|
+
tenant_id TEXT NOT NULL,
|
|
289
|
+
agent_id TEXT,
|
|
290
|
+
category TEXT NOT NULL DEFAULT 'general',
|
|
291
|
+
title TEXT NOT NULL,
|
|
292
|
+
content TEXT NOT NULL,
|
|
293
|
+
context TEXT NOT NULL DEFAULT '{}',
|
|
294
|
+
importance TEXT NOT NULL DEFAULT 'normal',
|
|
295
|
+
source_session_id TEXT,
|
|
296
|
+
source_event_id TEXT,
|
|
297
|
+
access_count INTEGER NOT NULL DEFAULT 0,
|
|
298
|
+
last_accessed_at TEXT,
|
|
299
|
+
created_at TEXT NOT NULL,
|
|
300
|
+
updated_at TEXT NOT NULL,
|
|
301
|
+
archived_at TEXT,
|
|
302
|
+
PRIMARY KEY (id, tenant_id)
|
|
303
|
+
)
|
|
304
|
+
`);
|
|
305
|
+
db.run(sql `CREATE INDEX IF NOT EXISTS idx_lessons_tenant ON lessons(tenant_id)`);
|
|
306
|
+
db.run(sql `CREATE INDEX IF NOT EXISTS idx_lessons_tenant_agent ON lessons(tenant_id, agent_id)`);
|
|
307
|
+
db.run(sql `CREATE INDEX IF NOT EXISTS idx_lessons_tenant_category ON lessons(tenant_id, category)`);
|
|
308
|
+
db.run(sql `CREATE INDEX IF NOT EXISTS idx_lessons_tenant_importance ON lessons(tenant_id, importance)`);
|
|
309
|
+
// ─── Lessons PK migration (H5) ──────────────────────────
|
|
310
|
+
// Migrate existing lessons tables from single-column PK to composite PK
|
|
311
|
+
const lessonsSchema = db.get(sql `SELECT sql FROM sqlite_master WHERE type='table' AND name='lessons'`);
|
|
312
|
+
if (lessonsSchema && lessonsSchema.sql.includes('id TEXT PRIMARY KEY')) {
|
|
313
|
+
db.run(sql `DROP INDEX IF EXISTS idx_lessons_tenant`);
|
|
314
|
+
db.run(sql `DROP INDEX IF EXISTS idx_lessons_tenant_agent`);
|
|
315
|
+
db.run(sql `DROP INDEX IF EXISTS idx_lessons_tenant_category`);
|
|
316
|
+
db.run(sql `DROP INDEX IF EXISTS idx_lessons_tenant_importance`);
|
|
317
|
+
db.run(sql `
|
|
318
|
+
CREATE TABLE lessons_new (
|
|
319
|
+
id TEXT NOT NULL,
|
|
320
|
+
tenant_id TEXT NOT NULL,
|
|
321
|
+
agent_id TEXT,
|
|
322
|
+
category TEXT NOT NULL DEFAULT 'general',
|
|
323
|
+
title TEXT NOT NULL,
|
|
324
|
+
content TEXT NOT NULL,
|
|
325
|
+
context TEXT NOT NULL DEFAULT '{}',
|
|
326
|
+
importance TEXT NOT NULL DEFAULT 'normal',
|
|
327
|
+
source_session_id TEXT,
|
|
328
|
+
source_event_id TEXT,
|
|
329
|
+
access_count INTEGER NOT NULL DEFAULT 0,
|
|
330
|
+
last_accessed_at TEXT,
|
|
331
|
+
created_at TEXT NOT NULL,
|
|
332
|
+
updated_at TEXT NOT NULL,
|
|
333
|
+
archived_at TEXT,
|
|
334
|
+
PRIMARY KEY (id, tenant_id)
|
|
335
|
+
)
|
|
336
|
+
`);
|
|
337
|
+
db.run(sql `
|
|
338
|
+
INSERT INTO lessons_new
|
|
339
|
+
SELECT id, tenant_id, agent_id, category, title, content, context,
|
|
340
|
+
importance, source_session_id, source_event_id, access_count,
|
|
341
|
+
last_accessed_at, created_at, updated_at, archived_at
|
|
342
|
+
FROM lessons
|
|
343
|
+
`);
|
|
344
|
+
db.run(sql `DROP TABLE lessons`);
|
|
345
|
+
db.run(sql `ALTER TABLE lessons_new RENAME TO lessons`);
|
|
346
|
+
db.run(sql `CREATE INDEX idx_lessons_tenant ON lessons(tenant_id)`);
|
|
347
|
+
db.run(sql `CREATE INDEX idx_lessons_tenant_agent ON lessons(tenant_id, agent_id)`);
|
|
348
|
+
db.run(sql `CREATE INDEX idx_lessons_tenant_category ON lessons(tenant_id, category)`);
|
|
349
|
+
db.run(sql `CREATE INDEX idx_lessons_tenant_importance ON lessons(tenant_id, importance)`);
|
|
350
|
+
}
|
|
351
|
+
// ─── Composite index for similarity search (M6) ──────────────────
|
|
352
|
+
db.run(sql `CREATE INDEX IF NOT EXISTS idx_embeddings_tenant_source_time ON embeddings(tenant_id, source_type, created_at)`);
|
|
353
|
+
// ─── Health Snapshots table (Epic 6 — Story 1.3) ──────────────────
|
|
354
|
+
db.run(sql `
|
|
355
|
+
CREATE TABLE IF NOT EXISTS health_snapshots (
|
|
356
|
+
id TEXT NOT NULL,
|
|
357
|
+
tenant_id TEXT NOT NULL,
|
|
358
|
+
agent_id TEXT NOT NULL,
|
|
359
|
+
date TEXT NOT NULL,
|
|
360
|
+
overall_score REAL NOT NULL,
|
|
361
|
+
error_rate_score REAL NOT NULL,
|
|
362
|
+
cost_efficiency_score REAL NOT NULL,
|
|
363
|
+
tool_success_score REAL NOT NULL,
|
|
364
|
+
latency_score REAL NOT NULL,
|
|
365
|
+
completion_rate_score REAL NOT NULL,
|
|
366
|
+
session_count INTEGER NOT NULL,
|
|
367
|
+
created_at TEXT NOT NULL,
|
|
368
|
+
PRIMARY KEY (tenant_id, agent_id, date)
|
|
369
|
+
)
|
|
370
|
+
`);
|
|
371
|
+
db.run(sql `CREATE INDEX IF NOT EXISTS idx_health_snapshots_agent ON health_snapshots(tenant_id, agent_id, date DESC)`);
|
|
124
372
|
}
|
|
125
373
|
/**
|
|
126
374
|
* Verify that WAL mode is enabled.
|
package/dist/db/migrate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/db/migrate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,EAAY;IACxC,2DAA2D;IAC3D,gEAAgE;IAChE,oDAAoD;IACpD,EAAE,CAAC,GAAG,CAAC,GAAG,CAAA;;;;;;;;;;;;;GAaT,CAAC,CAAC;IAEH,EAAE,CAAC,GAAG,CAAC,GAAG,CAAA
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/db/migrate.ts"],"names":[],"mappings":"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"}
|