@agentlensai/server 0.2.0 → 0.5.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/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 +250 -4
- package/dist/db/migrate.js.map +1 -1
- package/dist/db/schema.sqlite.d.ts +881 -55
- package/dist/db/schema.sqlite.d.ts.map +1 -1
- package/dist/db/schema.sqlite.js +82 -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 +25 -13
- package/dist/db/sqlite-store.d.ts.map +1 -1
- package/dist/db/sqlite-store.js +224 -47
- 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 +25 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +99 -5
- package/dist/index.js.map +1 -1
- package/dist/lib/alert-engine.d.ts +72 -0
- package/dist/lib/alert-engine.d.ts.map +1 -0
- package/dist/lib/alert-engine.js +318 -0
- package/dist/lib/alert-engine.js.map +1 -0
- 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 +158 -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 +155 -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 +118 -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 +145 -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 +56 -0
- package/dist/lib/context/retrieval.d.ts.map +1 -0
- package/dist/lib/context/retrieval.js +229 -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/event-bus.d.ts +48 -0
- package/dist/lib/event-bus.d.ts.map +1 -0
- package/dist/lib/event-bus.js +34 -0
- package/dist/lib/event-bus.js.map +1 -0
- package/dist/lib/retention.d.ts +1 -1
- package/dist/lib/retention.d.ts.map +1 -1
- package/dist/lib/sse.d.ts +22 -0
- package/dist/lib/sse.d.ts.map +1 -0
- package/dist/lib/sse.js +121 -0
- package/dist/lib/sse.js.map +1 -0
- 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 +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 +17 -0
- package/dist/routes/alerts.d.ts.map +1 -0
- package/dist/routes/alerts.js +141 -0
- package/dist/routes/alerts.js.map +1 -0
- package/dist/routes/analytics.d.ts +16 -0
- package/dist/routes/analytics.d.ts.map +1 -0
- package/dist/routes/analytics.js +307 -0
- package/dist/routes/analytics.js.map +1 -0
- 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/config.d.ts +5 -0
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +27 -7
- package/dist/routes/config.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 +7 -2
- package/dist/routes/events.d.ts.map +1 -1
- package/dist/routes/events.js +76 -8
- package/dist/routes/events.js.map +1 -1
- package/dist/routes/ingest.d.ts +36 -0
- package/dist/routes/ingest.d.ts.map +1 -0
- package/dist/routes/ingest.js +280 -0
- package/dist/routes/ingest.js.map +1 -0
- 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/recall.d.ts +20 -0
- package/dist/routes/recall.d.ts.map +1 -0
- package/dist/routes/recall.js +71 -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 +55 -0
- package/dist/routes/reflect.js.map +1 -0
- package/dist/routes/sessions.d.ts +1 -1
- package/dist/routes/sessions.d.ts.map +1 -1
- package/dist/routes/sessions.js +9 -7
- package/dist/routes/sessions.js.map +1 -1
- package/dist/routes/stats.d.ts +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 +23 -0
- package/dist/routes/stream.d.ts.map +1 -0
- package/dist/routes/stream.js +94 -0
- package/dist/routes/stream.js.map +1 -0
- 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 +23 -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__/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__/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__/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__/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,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lessons REST Endpoints (Story 3.2)
|
|
3
|
+
*
|
|
4
|
+
* POST /api/lessons — Create lesson
|
|
5
|
+
* GET /api/lessons — List lessons with filters
|
|
6
|
+
* GET /api/lessons/:id — Get single lesson (increments access_count)
|
|
7
|
+
* PUT /api/lessons/:id — Update lesson
|
|
8
|
+
* DELETE /api/lessons/:id — Archive (soft delete)
|
|
9
|
+
*/
|
|
10
|
+
import { Hono } from 'hono';
|
|
11
|
+
import { LessonStore } from '../db/lesson-store.js';
|
|
12
|
+
import { NotFoundError } from '../db/errors.js';
|
|
13
|
+
export function lessonsRoutes(db, deps) {
|
|
14
|
+
const app = new Hono();
|
|
15
|
+
const store = new LessonStore(db);
|
|
16
|
+
// POST /api/lessons — Create lesson
|
|
17
|
+
app.post('/', async (c) => {
|
|
18
|
+
const apiKeyInfo = c.get('apiKey');
|
|
19
|
+
const tenantId = apiKeyInfo?.tenantId ?? 'default';
|
|
20
|
+
const rawBody = await c.req.json().catch(() => null);
|
|
21
|
+
if (!rawBody) {
|
|
22
|
+
return c.json({ error: 'Invalid JSON body', status: 400 }, 400);
|
|
23
|
+
}
|
|
24
|
+
const { title, content, category, importance, agentId, context, sourceSessionId, sourceEventId } = rawBody;
|
|
25
|
+
if (!title || typeof title !== 'string' || title.length > 500) {
|
|
26
|
+
return c.json({ error: 'title required, max 500 chars', status: 400 }, 400);
|
|
27
|
+
}
|
|
28
|
+
if (!content || typeof content !== 'string' || content.length > 50000) {
|
|
29
|
+
return c.json({ error: 'content required, max 50000 chars', status: 400 }, 400);
|
|
30
|
+
}
|
|
31
|
+
// Validate importance if provided
|
|
32
|
+
const validImportance = ['low', 'normal', 'high', 'critical'];
|
|
33
|
+
if (importance !== undefined && !validImportance.includes(importance)) {
|
|
34
|
+
return c.json({ error: `importance must be one of: ${validImportance.join(', ')}`, status: 400 }, 400);
|
|
35
|
+
}
|
|
36
|
+
const lesson = store.create(tenantId, {
|
|
37
|
+
title: title,
|
|
38
|
+
content: content,
|
|
39
|
+
category: category,
|
|
40
|
+
importance: importance,
|
|
41
|
+
agentId: agentId,
|
|
42
|
+
context: context,
|
|
43
|
+
sourceSessionId: sourceSessionId,
|
|
44
|
+
sourceEventId: sourceEventId,
|
|
45
|
+
});
|
|
46
|
+
// Enqueue lesson for embedding
|
|
47
|
+
try {
|
|
48
|
+
deps?.embeddingWorker?.enqueue({
|
|
49
|
+
tenantId,
|
|
50
|
+
sourceType: 'lesson',
|
|
51
|
+
sourceId: lesson.id,
|
|
52
|
+
textContent: `${lesson.title}: ${lesson.content}`,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// Never crash on embedding failures
|
|
57
|
+
}
|
|
58
|
+
return c.json(lesson, 201);
|
|
59
|
+
});
|
|
60
|
+
// GET /api/lessons — List with query params
|
|
61
|
+
app.get('/', async (c) => {
|
|
62
|
+
const apiKeyInfo = c.get('apiKey');
|
|
63
|
+
const tenantId = apiKeyInfo?.tenantId ?? 'default';
|
|
64
|
+
const category = c.req.query('category');
|
|
65
|
+
const agentId = c.req.query('agentId');
|
|
66
|
+
const importance = c.req.query('importance');
|
|
67
|
+
const search = c.req.query('search');
|
|
68
|
+
const limitStr = c.req.query('limit');
|
|
69
|
+
const offsetStr = c.req.query('offset');
|
|
70
|
+
const includeArchived = c.req.query('includeArchived') === 'true';
|
|
71
|
+
const limit = limitStr ? Math.max(1, Math.min(parseInt(limitStr, 10) || 50, 500)) : 50;
|
|
72
|
+
const offset = offsetStr ? Math.max(0, parseInt(offsetStr, 10) || 0) : 0;
|
|
73
|
+
const query = {
|
|
74
|
+
category: category ?? undefined,
|
|
75
|
+
agentId: agentId ?? undefined,
|
|
76
|
+
importance: importance ?? undefined,
|
|
77
|
+
search: search ?? undefined,
|
|
78
|
+
limit,
|
|
79
|
+
offset,
|
|
80
|
+
includeArchived,
|
|
81
|
+
};
|
|
82
|
+
const items = store.list(tenantId, query);
|
|
83
|
+
const total = store.count(tenantId, query);
|
|
84
|
+
return c.json({
|
|
85
|
+
lessons: items,
|
|
86
|
+
total,
|
|
87
|
+
hasMore: offset + items.length < total,
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
// GET /api/lessons/:id — Get single lesson
|
|
91
|
+
app.get('/:id', async (c) => {
|
|
92
|
+
const apiKeyInfo = c.get('apiKey');
|
|
93
|
+
const tenantId = apiKeyInfo?.tenantId ?? 'default';
|
|
94
|
+
const id = c.req.param('id');
|
|
95
|
+
const lesson = store.get(tenantId, id);
|
|
96
|
+
if (!lesson) {
|
|
97
|
+
return c.json({ error: 'Lesson not found', status: 404 }, 404);
|
|
98
|
+
}
|
|
99
|
+
return c.json(lesson);
|
|
100
|
+
});
|
|
101
|
+
// PUT /api/lessons/:id — Update lesson
|
|
102
|
+
app.put('/:id', async (c) => {
|
|
103
|
+
const apiKeyInfo = c.get('apiKey');
|
|
104
|
+
const tenantId = apiKeyInfo?.tenantId ?? 'default';
|
|
105
|
+
const id = c.req.param('id');
|
|
106
|
+
const rawBody = await c.req.json().catch(() => null);
|
|
107
|
+
if (!rawBody) {
|
|
108
|
+
return c.json({ error: 'Invalid JSON body', status: 400 }, 400);
|
|
109
|
+
}
|
|
110
|
+
const { title, content, category, importance, agentId, context } = rawBody;
|
|
111
|
+
// Validate importance if provided
|
|
112
|
+
const validImportance = ['low', 'normal', 'high', 'critical'];
|
|
113
|
+
if (importance !== undefined && !validImportance.includes(importance)) {
|
|
114
|
+
return c.json({ error: `importance must be one of: ${validImportance.join(', ')}`, status: 400 }, 400);
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const lesson = store.update(tenantId, id, {
|
|
118
|
+
title: title,
|
|
119
|
+
content: content,
|
|
120
|
+
category: category,
|
|
121
|
+
importance: importance,
|
|
122
|
+
agentId: agentId,
|
|
123
|
+
context: context,
|
|
124
|
+
});
|
|
125
|
+
// Re-enqueue lesson for embedding after update
|
|
126
|
+
try {
|
|
127
|
+
deps?.embeddingWorker?.enqueue({
|
|
128
|
+
tenantId,
|
|
129
|
+
sourceType: 'lesson',
|
|
130
|
+
sourceId: lesson.id,
|
|
131
|
+
textContent: `${lesson.title}: ${lesson.content}`,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// Never crash on embedding failures
|
|
136
|
+
}
|
|
137
|
+
return c.json(lesson);
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
if (err instanceof NotFoundError) {
|
|
141
|
+
return c.json({ error: 'Lesson not found', status: 404 }, 404);
|
|
142
|
+
}
|
|
143
|
+
throw err;
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
// DELETE /api/lessons/:id — Archive (soft delete)
|
|
147
|
+
app.delete('/:id', async (c) => {
|
|
148
|
+
const apiKeyInfo = c.get('apiKey');
|
|
149
|
+
const tenantId = apiKeyInfo?.tenantId ?? 'default';
|
|
150
|
+
const id = c.req.param('id');
|
|
151
|
+
try {
|
|
152
|
+
store.archive(tenantId, id);
|
|
153
|
+
return c.json({ id, archived: true });
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
if (err instanceof NotFoundError) {
|
|
157
|
+
return c.json({ error: 'Lesson not found', status: 404 }, 404);
|
|
158
|
+
}
|
|
159
|
+
throw err;
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
return app;
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=lessons.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lessons.js","sourceRoot":"","sources":["../../src/routes/lessons.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recall REST Endpoint (Story 2.6)
|
|
3
|
+
*
|
|
4
|
+
* GET /api/recall — Semantic search over embeddings
|
|
5
|
+
*
|
|
6
|
+
* Embeds the query text, performs cosine similarity search,
|
|
7
|
+
* and returns enriched results.
|
|
8
|
+
*/
|
|
9
|
+
import { Hono } from 'hono';
|
|
10
|
+
import type { AuthVariables } from '../middleware/auth.js';
|
|
11
|
+
import type { EmbeddingService } from '../lib/embeddings/index.js';
|
|
12
|
+
import type { EmbeddingStore } from '../db/embedding-store.js';
|
|
13
|
+
export interface RecallRouteDeps {
|
|
14
|
+
embeddingService: EmbeddingService | null;
|
|
15
|
+
embeddingStore: EmbeddingStore | null;
|
|
16
|
+
}
|
|
17
|
+
export declare function recallRoutes(deps: RecallRouteDeps): Hono<{
|
|
18
|
+
Variables: AuthVariables;
|
|
19
|
+
}, import("hono/types").BlankSchema, "/">;
|
|
20
|
+
//# sourceMappingURL=recall.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recall.d.ts","sourceRoot":"","sources":["../../src/routes/recall.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,0BAA0B,CAAC;AAExF,MAAM,WAAW,eAAe;IAC9B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,cAAc,EAAE,cAAc,GAAG,IAAI,CAAC;CACvC;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,eAAe;eACd,aAAa;0CAgFhD"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recall REST Endpoint (Story 2.6)
|
|
3
|
+
*
|
|
4
|
+
* GET /api/recall — Semantic search over embeddings
|
|
5
|
+
*
|
|
6
|
+
* Embeds the query text, performs cosine similarity search,
|
|
7
|
+
* and returns enriched results.
|
|
8
|
+
*/
|
|
9
|
+
import { Hono } from 'hono';
|
|
10
|
+
export function recallRoutes(deps) {
|
|
11
|
+
const app = new Hono();
|
|
12
|
+
// GET /api/recall?query=...&scope=...&limit=...&minScore=...&agentId=...&from=...&to=...
|
|
13
|
+
app.get('/', async (c) => {
|
|
14
|
+
const { embeddingService, embeddingStore } = deps;
|
|
15
|
+
if (!embeddingService || !embeddingStore) {
|
|
16
|
+
return c.json({ error: 'Embedding service not configured', status: 503 }, 503);
|
|
17
|
+
}
|
|
18
|
+
const query = c.req.query('query');
|
|
19
|
+
if (!query) {
|
|
20
|
+
return c.json({ error: 'query parameter is required', status: 400 }, 400);
|
|
21
|
+
}
|
|
22
|
+
const scope = c.req.query('scope'); // 'events' | 'sessions' | 'lessons' | 'all'
|
|
23
|
+
const limitStr = c.req.query('limit');
|
|
24
|
+
const minScoreStr = c.req.query('minScore');
|
|
25
|
+
const from = c.req.query('from');
|
|
26
|
+
const to = c.req.query('to');
|
|
27
|
+
const limit = limitStr ? Math.max(1, Math.min(parseInt(limitStr, 10) || 10, 100)) : 10;
|
|
28
|
+
const minScore = minScoreStr ? Math.max(0, Math.min(parseFloat(minScoreStr) || 0, 1)) : 0;
|
|
29
|
+
// Get tenantId from auth context
|
|
30
|
+
const apiKeyInfo = c.get('apiKey');
|
|
31
|
+
const tenantId = apiKeyInfo?.tenantId ?? 'default';
|
|
32
|
+
try {
|
|
33
|
+
// Embed the query text
|
|
34
|
+
const queryVector = await embeddingService.embed(query);
|
|
35
|
+
// Map scope to sourceType for the store
|
|
36
|
+
let sourceType;
|
|
37
|
+
if (scope && scope !== 'all') {
|
|
38
|
+
// Normalize: 'events' -> 'event', 'sessions' -> 'session', 'lessons' -> 'lesson'
|
|
39
|
+
sourceType = scope.replace(/s$/, '');
|
|
40
|
+
}
|
|
41
|
+
const searchOpts = {
|
|
42
|
+
sourceType,
|
|
43
|
+
from: from ?? undefined,
|
|
44
|
+
to: to ?? undefined,
|
|
45
|
+
limit,
|
|
46
|
+
minScore,
|
|
47
|
+
};
|
|
48
|
+
const results = await embeddingStore.similaritySearch(tenantId, queryVector, searchOpts);
|
|
49
|
+
return c.json({
|
|
50
|
+
results: results.map((r) => ({
|
|
51
|
+
sourceType: r.sourceType,
|
|
52
|
+
sourceId: r.sourceId,
|
|
53
|
+
score: Math.round(r.score * 10000) / 10000, // 4 decimal places
|
|
54
|
+
text: r.text,
|
|
55
|
+
metadata: {
|
|
56
|
+
embeddingModel: r.embeddingModel,
|
|
57
|
+
createdAt: r.createdAt,
|
|
58
|
+
},
|
|
59
|
+
})),
|
|
60
|
+
query,
|
|
61
|
+
totalResults: results.length,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
console.error('[recall] Search failed:', err instanceof Error ? err.message : err);
|
|
66
|
+
return c.json({ error: 'Recall search failed', status: 500 }, 500);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
return app;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=recall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recall.js","sourceRoot":"","sources":["../../src/routes/recall.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reflect REST Endpoint (Story 4.6)
|
|
3
|
+
*
|
|
4
|
+
* GET /api/reflect?analysis=error_patterns&agentId=X&from=...&to=...&limit=...
|
|
5
|
+
*
|
|
6
|
+
* Dispatches to the appropriate analysis function based on the `analysis` param.
|
|
7
|
+
* Requires auth (tenant-scoped).
|
|
8
|
+
*/
|
|
9
|
+
import { Hono } from 'hono';
|
|
10
|
+
import type { IEventStore } from '@agentlensai/core';
|
|
11
|
+
import type { AuthVariables } from '../middleware/auth.js';
|
|
12
|
+
export declare function reflectRoutes(store: IEventStore): Hono<{
|
|
13
|
+
Variables: AuthVariables;
|
|
14
|
+
}, import("hono/types").BlankSchema, "/">;
|
|
15
|
+
//# sourceMappingURL=reflect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reflect.d.ts","sourceRoot":"","sources":["../../src/routes/reflect.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAY3D,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW;eACZ,aAAa;0CA8ChD"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reflect REST Endpoint (Story 4.6)
|
|
3
|
+
*
|
|
4
|
+
* GET /api/reflect?analysis=error_patterns&agentId=X&from=...&to=...&limit=...
|
|
5
|
+
*
|
|
6
|
+
* Dispatches to the appropriate analysis function based on the `analysis` param.
|
|
7
|
+
* Requires auth (tenant-scoped).
|
|
8
|
+
*/
|
|
9
|
+
import { Hono } from 'hono';
|
|
10
|
+
import { getTenantStore } from './tenant-helper.js';
|
|
11
|
+
import { runAnalysis } from '../lib/analysis/index.js';
|
|
12
|
+
const VALID_ANALYSES = [
|
|
13
|
+
'error_patterns',
|
|
14
|
+
'tool_sequences',
|
|
15
|
+
'cost_analysis',
|
|
16
|
+
'performance_trends',
|
|
17
|
+
'session_comparison',
|
|
18
|
+
];
|
|
19
|
+
export function reflectRoutes(store) {
|
|
20
|
+
const app = new Hono();
|
|
21
|
+
// GET /api/reflect
|
|
22
|
+
app.get('/', async (c) => {
|
|
23
|
+
const tenantStore = getTenantStore(store, c);
|
|
24
|
+
const analysis = c.req.query('analysis');
|
|
25
|
+
if (!analysis) {
|
|
26
|
+
return c.json({ error: 'Missing required query parameter: analysis', status: 400 }, 400);
|
|
27
|
+
}
|
|
28
|
+
if (!VALID_ANALYSES.includes(analysis)) {
|
|
29
|
+
return c.json({
|
|
30
|
+
error: `Invalid analysis type: ${analysis}. Must be one of: ${VALID_ANALYSES.join(', ')}`,
|
|
31
|
+
status: 400,
|
|
32
|
+
}, 400);
|
|
33
|
+
}
|
|
34
|
+
const agentId = c.req.query('agentId') || undefined;
|
|
35
|
+
const from = c.req.query('from') || undefined;
|
|
36
|
+
const to = c.req.query('to') || undefined;
|
|
37
|
+
const limitStr = c.req.query('limit');
|
|
38
|
+
const limit = limitStr ? parseInt(limitStr, 10) : undefined;
|
|
39
|
+
try {
|
|
40
|
+
const result = await runAnalysis(analysis, tenantStore, {
|
|
41
|
+
agentId,
|
|
42
|
+
from,
|
|
43
|
+
to,
|
|
44
|
+
limit,
|
|
45
|
+
});
|
|
46
|
+
return c.json(result);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const message = error instanceof Error ? error.message : 'Internal error';
|
|
50
|
+
return c.json({ error: message, status: 500 }, 500);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
return app;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=reflect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reflect.js","sourceRoot":"","sources":["../../src/routes/reflect.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,MAAM,cAAc,GAAG;IACrB,gBAAgB;IAChB,gBAAgB;IAChB,eAAe;IACf,oBAAoB;IACpB,oBAAoB;CACrB,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,KAAkB;IAC9C,MAAM,GAAG,GAAG,IAAI,IAAI,EAAgC,CAAC;IAErD,mBAAmB;IACnB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACvB,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAE7C,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACzC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,KAAK,EAAE,4CAA4C,EAAE,MAAM,EAAE,GAAG,EAAE,EACpE,GAAG,CACJ,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvC,OAAO,CAAC,CAAC,IAAI,CACX;gBACE,KAAK,EAAE,0BAA0B,QAAQ,qBAAqB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACzF,MAAM,EAAE,GAAG;aACZ,EACD,GAAG,CACJ,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC;QACpD,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC;QAC9C,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;QAC1C,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE5D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,WAAW,EAAE;gBACtD,OAAO;gBACP,IAAI;gBACJ,EAAE;gBACF,KAAK;aACN,CAAC,CAAC;YAEH,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC;YAC1E,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;QACtD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* GET /api/sessions/:id/timeline — all events ascending + chainValid
|
|
7
7
|
*/
|
|
8
8
|
import { Hono } from 'hono';
|
|
9
|
-
import type { IEventStore } from '@
|
|
9
|
+
import type { IEventStore } from '@agentlensai/core';
|
|
10
10
|
import type { AuthVariables } from '../middleware/auth.js';
|
|
11
11
|
export declare function sessionsRoutes(store: IEventStore): Hono<{
|
|
12
12
|
Variables: AuthVariables;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAG3D,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW;eACb,aAAa;0CA2EhD"}
|
package/dist/routes/sessions.js
CHANGED
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
* GET /api/sessions/:id/timeline — all events ascending + chainValid
|
|
7
7
|
*/
|
|
8
8
|
import { Hono } from 'hono';
|
|
9
|
-
import { verifyChain, DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE } from '@
|
|
9
|
+
import { verifyChain, DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE } from '@agentlensai/core';
|
|
10
|
+
import { getTenantStore } from './tenant-helper.js';
|
|
10
11
|
export function sessionsRoutes(store) {
|
|
11
12
|
const app = new Hono();
|
|
12
13
|
// GET /api/sessions — list sessions
|
|
13
14
|
app.get('/', async (c) => {
|
|
15
|
+
const tenantStore = getTenantStore(store, c);
|
|
14
16
|
const query = {};
|
|
15
17
|
const agentId = c.req.query('agentId');
|
|
16
18
|
if (agentId)
|
|
@@ -35,7 +37,7 @@ export function sessionsRoutes(store) {
|
|
|
35
37
|
: DEFAULT_PAGE_SIZE;
|
|
36
38
|
const offsetStr = c.req.query('offset');
|
|
37
39
|
query.offset = offsetStr ? Math.max(0, parseInt(offsetStr, 10) || 0) : 0;
|
|
38
|
-
const result = await
|
|
40
|
+
const result = await tenantStore.querySessions(query);
|
|
39
41
|
return c.json({
|
|
40
42
|
sessions: result.sessions,
|
|
41
43
|
total: result.total,
|
|
@@ -44,10 +46,9 @@ export function sessionsRoutes(store) {
|
|
|
44
46
|
});
|
|
45
47
|
// GET /api/sessions/:id — session detail
|
|
46
48
|
app.get('/:id', async (c) => {
|
|
49
|
+
const tenantStore = getTenantStore(store, c);
|
|
47
50
|
const id = c.req.param('id');
|
|
48
|
-
|
|
49
|
-
// but we have a separate route for /:id/timeline below.
|
|
50
|
-
const session = await store.getSession(id);
|
|
51
|
+
const session = await tenantStore.getSession(id);
|
|
51
52
|
if (!session) {
|
|
52
53
|
return c.json({ error: 'Session not found', status: 404 }, 404);
|
|
53
54
|
}
|
|
@@ -55,12 +56,13 @@ export function sessionsRoutes(store) {
|
|
|
55
56
|
});
|
|
56
57
|
// GET /api/sessions/:id/timeline — all events ascending + chain verification
|
|
57
58
|
app.get('/:id/timeline', async (c) => {
|
|
59
|
+
const tenantStore = getTenantStore(store, c);
|
|
58
60
|
const id = c.req.param('id');
|
|
59
|
-
const session = await
|
|
61
|
+
const session = await tenantStore.getSession(id);
|
|
60
62
|
if (!session) {
|
|
61
63
|
return c.json({ error: 'Session not found', status: 404 }, 404);
|
|
62
64
|
}
|
|
63
|
-
const timeline = await
|
|
65
|
+
const timeline = await tenantStore.getSessionTimeline(id);
|
|
64
66
|
const chainResult = verifyChain(timeline);
|
|
65
67
|
return c.json({
|
|
66
68
|
events: timeline,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"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"}
|
package/dist/routes/stats.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* GET /api/stats — storage statistics
|
|
5
5
|
*/
|
|
6
6
|
import { Hono } from 'hono';
|
|
7
|
-
import type { IEventStore } from '@
|
|
7
|
+
import type { IEventStore } from '@agentlensai/core';
|
|
8
8
|
import type { AuthVariables } from '../middleware/auth.js';
|
|
9
9
|
export declare function statsRoutes(store: IEventStore): Hono<{
|
|
10
10
|
Variables: AuthVariables;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/routes/stats.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/routes/stats.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAG3D,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW;eACV,aAAa;0CAUhD"}
|
package/dist/routes/stats.js
CHANGED
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
* GET /api/stats — storage statistics
|
|
5
5
|
*/
|
|
6
6
|
import { Hono } from 'hono';
|
|
7
|
+
import { getTenantStore } from './tenant-helper.js';
|
|
7
8
|
export function statsRoutes(store) {
|
|
8
9
|
const app = new Hono();
|
|
9
10
|
// GET /api/stats — storage statistics
|
|
10
11
|
app.get('/', async (c) => {
|
|
11
|
-
const
|
|
12
|
+
const tenantStore = getTenantStore(store, c);
|
|
13
|
+
const stats = await tenantStore.getStats();
|
|
12
14
|
return c.json(stats);
|
|
13
15
|
});
|
|
14
16
|
return app;
|
package/dist/routes/stats.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/routes/stats.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/routes/stats.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,UAAU,WAAW,CAAC,KAAkB;IAC5C,MAAM,GAAG,GAAG,IAAI,IAAI,EAAgC,CAAC;IAErD,sCAAsC;IACtC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACvB,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC7C,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,CAAC;QAC3C,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE Stream Endpoint (Story 14.1, Arch §7.2)
|
|
3
|
+
*
|
|
4
|
+
* GET /api/stream — Server-Sent Events endpoint for real-time dashboard updates.
|
|
5
|
+
*
|
|
6
|
+
* Authentication:
|
|
7
|
+
* - Bearer token via Authorization header, OR
|
|
8
|
+
* - ?token=als_xxx query param (for EventSource compatibility — browsers can't set headers)
|
|
9
|
+
* - In dev mode (authDisabled), authentication is skipped
|
|
10
|
+
*
|
|
11
|
+
* Query params:
|
|
12
|
+
* token? — API key for auth (EventSource compat)
|
|
13
|
+
* sessionId? — filter to a specific session
|
|
14
|
+
* agentId? — filter to a specific agent
|
|
15
|
+
* eventType? — filter by event type (comma-separated)
|
|
16
|
+
*/
|
|
17
|
+
import { Hono } from 'hono';
|
|
18
|
+
import type { SqliteDb } from '../db/index.js';
|
|
19
|
+
import { type AuthVariables } from '../middleware/auth.js';
|
|
20
|
+
export declare function streamRoutes(db?: SqliteDb, authDisabled?: boolean): Hono<{
|
|
21
|
+
Variables: AuthVariables;
|
|
22
|
+
}, import("hono/types").BlankSchema, "/">;
|
|
23
|
+
//# sourceMappingURL=stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/routes/stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG/C,OAAO,EAAc,KAAK,aAAa,EAAmB,MAAM,uBAAuB,CAAC;AAGxF,wBAAgB,YAAY,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,OAAO;eAC9B,aAAa;0CA4EhD"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE Stream Endpoint (Story 14.1, Arch §7.2)
|
|
3
|
+
*
|
|
4
|
+
* GET /api/stream — Server-Sent Events endpoint for real-time dashboard updates.
|
|
5
|
+
*
|
|
6
|
+
* Authentication:
|
|
7
|
+
* - Bearer token via Authorization header, OR
|
|
8
|
+
* - ?token=als_xxx query param (for EventSource compatibility — browsers can't set headers)
|
|
9
|
+
* - In dev mode (authDisabled), authentication is skipped
|
|
10
|
+
*
|
|
11
|
+
* Query params:
|
|
12
|
+
* token? — API key for auth (EventSource compat)
|
|
13
|
+
* sessionId? — filter to a specific session
|
|
14
|
+
* agentId? — filter to a specific agent
|
|
15
|
+
* eventType? — filter by event type (comma-separated)
|
|
16
|
+
*/
|
|
17
|
+
import { Hono } from 'hono';
|
|
18
|
+
import { apiKeys } from '../db/schema.sqlite.js';
|
|
19
|
+
import { eq, and, isNull } from 'drizzle-orm';
|
|
20
|
+
import { hashApiKey } from '../middleware/auth.js';
|
|
21
|
+
import { createSSEStream } from '../lib/sse.js';
|
|
22
|
+
export function streamRoutes(db, authDisabled) {
|
|
23
|
+
const app = new Hono();
|
|
24
|
+
app.get('/', (c) => {
|
|
25
|
+
// ─── Authenticate ────────────────────────────────────
|
|
26
|
+
let apiKeyInfo;
|
|
27
|
+
if (authDisabled) {
|
|
28
|
+
// Dev mode: allow unauthenticated access with default tenant
|
|
29
|
+
apiKeyInfo = { id: 'dev', name: 'dev-mode', scopes: ['*'], tenantId: 'default' };
|
|
30
|
+
}
|
|
31
|
+
else if (db) {
|
|
32
|
+
// Try Authorization header first
|
|
33
|
+
const authHeader = c.req.header('Authorization');
|
|
34
|
+
const headerMatch = authHeader?.match(/^Bearer\s+(als_\w+)$/);
|
|
35
|
+
const rawKey = headerMatch?.[1] ?? c.req.query('token');
|
|
36
|
+
if (!rawKey || !rawKey.startsWith('als_')) {
|
|
37
|
+
return c.json({ error: 'Authentication required. Provide Bearer token or ?token=als_xxx query param.', status: 401 }, 401);
|
|
38
|
+
}
|
|
39
|
+
const keyHash = hashApiKey(rawKey);
|
|
40
|
+
const row = db
|
|
41
|
+
.select()
|
|
42
|
+
.from(apiKeys)
|
|
43
|
+
.where(and(eq(apiKeys.keyHash, keyHash), isNull(apiKeys.revokedAt)))
|
|
44
|
+
.get();
|
|
45
|
+
if (!row) {
|
|
46
|
+
return c.json({ error: 'Invalid or revoked API key', status: 401 }, 401);
|
|
47
|
+
}
|
|
48
|
+
const scopes = (() => {
|
|
49
|
+
try {
|
|
50
|
+
return JSON.parse(row.scopes);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
})();
|
|
56
|
+
apiKeyInfo = {
|
|
57
|
+
id: row.id,
|
|
58
|
+
name: row.name,
|
|
59
|
+
scopes,
|
|
60
|
+
tenantId: row.tenantId,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
// No db and not dev mode — cannot authenticate
|
|
65
|
+
return c.json({ error: 'Authentication not available', status: 500 }, 500);
|
|
66
|
+
}
|
|
67
|
+
// ─── Parse filter params ─────────────────────────────
|
|
68
|
+
const filters = {};
|
|
69
|
+
const sessionId = c.req.query('sessionId');
|
|
70
|
+
if (sessionId)
|
|
71
|
+
filters.sessionId = sessionId;
|
|
72
|
+
const agentId = c.req.query('agentId');
|
|
73
|
+
if (agentId)
|
|
74
|
+
filters.agentId = agentId;
|
|
75
|
+
const eventType = c.req.query('eventType');
|
|
76
|
+
if (eventType) {
|
|
77
|
+
filters.eventTypes = eventType.split(',').filter(Boolean);
|
|
78
|
+
}
|
|
79
|
+
// Tenant filtering — ALWAYS from authenticated context, never from query param
|
|
80
|
+
filters.tenantId = apiKeyInfo.tenantId;
|
|
81
|
+
// Create SSE stream
|
|
82
|
+
const stream = createSSEStream(filters, c.req.raw.signal);
|
|
83
|
+
return new Response(stream, {
|
|
84
|
+
headers: {
|
|
85
|
+
'Content-Type': 'text/event-stream',
|
|
86
|
+
'Cache-Control': 'no-cache',
|
|
87
|
+
Connection: 'keep-alive',
|
|
88
|
+
'X-Accel-Buffering': 'no', // Disable nginx buffering
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
return app;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/routes/stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper to create a TenantScopedStore from request context.
|
|
3
|
+
*
|
|
4
|
+
* If the store is a SqliteEventStore and the request has an API key
|
|
5
|
+
* with a tenantId, returns a TenantScopedStore. Otherwise returns
|
|
6
|
+
* the store as-is (backward compatibility for tests, etc.).
|
|
7
|
+
*/
|
|
8
|
+
import type { Context } from 'hono';
|
|
9
|
+
import type { IEventStore } from '@agentlensai/core';
|
|
10
|
+
import type { AuthVariables } from '../middleware/auth.js';
|
|
11
|
+
/**
|
|
12
|
+
* Get a tenant-scoped store from the request context.
|
|
13
|
+
*
|
|
14
|
+
* For SqliteEventStore: wraps in TenantScopedStore with the tenant from auth.
|
|
15
|
+
* For other IEventStore impls (tests, mocks): returns as-is.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getTenantStore(store: IEventStore, c: Context<{
|
|
18
|
+
Variables: AuthVariables;
|
|
19
|
+
}>): IEventStore;
|
|
20
|
+
//# sourceMappingURL=tenant-helper.d.ts.map
|