@agentlensai/server 0.7.0 → 0.9.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/anonymous-id-manager.d.ts +44 -0
- package/dist/db/anonymous-id-manager.d.ts.map +1 -0
- package/dist/db/anonymous-id-manager.js +90 -0
- package/dist/db/anonymous-id-manager.js.map +1 -0
- package/dist/db/capability-store.d.ts +78 -0
- package/dist/db/capability-store.d.ts.map +1 -0
- package/dist/db/capability-store.js +201 -0
- package/dist/db/capability-store.js.map +1 -0
- package/dist/db/guardrail-store.d.ts +34 -0
- package/dist/db/guardrail-store.d.ts.map +1 -0
- package/dist/db/guardrail-store.js +221 -0
- package/dist/db/guardrail-store.js.map +1 -0
- package/dist/db/migrate.d.ts.map +1 -1
- package/dist/db/migrate.js +200 -0
- package/dist/db/migrate.js.map +1 -1
- package/dist/db/schema.sqlite.d.ts +1719 -1
- package/dist/db/schema.sqlite.d.ts.map +1 -1
- package/dist/db/schema.sqlite.js +141 -1
- package/dist/db/schema.sqlite.js.map +1 -1
- package/dist/db/sqlite-store.d.ts +12 -0
- package/dist/db/sqlite-store.d.ts.map +1 -1
- package/dist/db/sqlite-store.js +47 -0
- package/dist/db/sqlite-store.js.map +1 -1
- package/dist/db/tenant-scoped-store.d.ts +1 -0
- package/dist/db/tenant-scoped-store.d.ts.map +1 -1
- package/dist/db/tenant-scoped-store.js +3 -0
- package/dist/db/tenant-scoped-store.js.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/guardrails/actions.d.ts +28 -0
- package/dist/lib/guardrails/actions.d.ts.map +1 -0
- package/dist/lib/guardrails/actions.js +126 -0
- package/dist/lib/guardrails/actions.js.map +1 -0
- package/dist/lib/guardrails/conditions.d.ts +13 -0
- package/dist/lib/guardrails/conditions.d.ts.map +1 -0
- package/dist/lib/guardrails/conditions.js +188 -0
- package/dist/lib/guardrails/conditions.js.map +1 -0
- package/dist/lib/guardrails/engine.d.ts +24 -0
- package/dist/lib/guardrails/engine.d.ts.map +1 -0
- package/dist/lib/guardrails/engine.js +122 -0
- package/dist/lib/guardrails/engine.js.map +1 -0
- package/dist/lib/redaction/human-review-layer.d.ts +37 -0
- package/dist/lib/redaction/human-review-layer.d.ts.map +1 -0
- package/dist/lib/redaction/human-review-layer.js +62 -0
- package/dist/lib/redaction/human-review-layer.js.map +1 -0
- package/dist/lib/redaction/index.d.ts +12 -0
- package/dist/lib/redaction/index.d.ts.map +1 -0
- package/dist/lib/redaction/index.js +12 -0
- package/dist/lib/redaction/index.js.map +1 -0
- package/dist/lib/redaction/pii-detection-layer.d.ts +30 -0
- package/dist/lib/redaction/pii-detection-layer.d.ts.map +1 -0
- package/dist/lib/redaction/pii-detection-layer.js +183 -0
- package/dist/lib/redaction/pii-detection-layer.js.map +1 -0
- package/dist/lib/redaction/pipeline.d.ts +26 -0
- package/dist/lib/redaction/pipeline.d.ts.map +1 -0
- package/dist/lib/redaction/pipeline.js +91 -0
- package/dist/lib/redaction/pipeline.js.map +1 -0
- package/dist/lib/redaction/secret-detection-layer.d.ts +10 -0
- package/dist/lib/redaction/secret-detection-layer.d.ts.map +1 -0
- package/dist/lib/redaction/secret-detection-layer.js +79 -0
- package/dist/lib/redaction/secret-detection-layer.js.map +1 -0
- package/dist/lib/redaction/secret-patterns.d.ts +29 -0
- package/dist/lib/redaction/secret-patterns.d.ts.map +1 -0
- package/dist/lib/redaction/secret-patterns.js +133 -0
- package/dist/lib/redaction/secret-patterns.js.map +1 -0
- package/dist/lib/redaction/semantic-denylist-layer.d.ts +10 -0
- package/dist/lib/redaction/semantic-denylist-layer.d.ts.map +1 -0
- package/dist/lib/redaction/semantic-denylist-layer.js +64 -0
- package/dist/lib/redaction/semantic-denylist-layer.js.map +1 -0
- package/dist/lib/redaction/tenant-deidentification-layer.d.ts +10 -0
- package/dist/lib/redaction/tenant-deidentification-layer.d.ts.map +1 -0
- package/dist/lib/redaction/tenant-deidentification-layer.js +64 -0
- package/dist/lib/redaction/tenant-deidentification-layer.js.map +1 -0
- package/dist/lib/redaction/url-path-scrubbing-layer.d.ts +14 -0
- package/dist/lib/redaction/url-path-scrubbing-layer.d.ts.map +1 -0
- package/dist/lib/redaction/url-path-scrubbing-layer.js +156 -0
- package/dist/lib/redaction/url-path-scrubbing-layer.js.map +1 -0
- package/dist/routes/agents.d.ts +4 -3
- package/dist/routes/agents.d.ts.map +1 -1
- package/dist/routes/agents.js +31 -12
- package/dist/routes/agents.js.map +1 -1
- package/dist/routes/audit.d.ts +15 -0
- package/dist/routes/audit.d.ts.map +1 -0
- package/dist/routes/audit.js +177 -0
- package/dist/routes/audit.js.map +1 -0
- package/dist/routes/capabilities.d.ts +15 -0
- package/dist/routes/capabilities.d.ts.map +1 -0
- package/dist/routes/capabilities.js +86 -0
- package/dist/routes/capabilities.js.map +1 -0
- package/dist/routes/community.d.ts +24 -0
- package/dist/routes/community.d.ts.map +1 -0
- package/dist/routes/community.js +190 -0
- package/dist/routes/community.js.map +1 -0
- package/dist/routes/delegation.d.ts +20 -0
- package/dist/routes/delegation.d.ts.map +1 -0
- package/dist/routes/delegation.js +108 -0
- package/dist/routes/delegation.js.map +1 -0
- package/dist/routes/discovery.d.ts +19 -0
- package/dist/routes/discovery.d.ts.map +1 -0
- package/dist/routes/discovery.js +96 -0
- package/dist/routes/discovery.js.map +1 -0
- package/dist/routes/guardrails.d.ts +18 -0
- package/dist/routes/guardrails.d.ts.map +1 -0
- package/dist/routes/guardrails.js +184 -0
- package/dist/routes/guardrails.js.map +1 -0
- package/dist/routes/redaction-test.d.ts +14 -0
- package/dist/routes/redaction-test.d.ts.map +1 -0
- package/dist/routes/redaction-test.js +33 -0
- package/dist/routes/redaction-test.js.map +1 -0
- package/dist/routes/trust.d.ts +16 -0
- package/dist/routes/trust.d.ts.map +1 -0
- package/dist/routes/trust.js +23 -0
- package/dist/routes/trust.js.map +1 -0
- package/dist/services/community-service.d.ts +277 -0
- package/dist/services/community-service.d.ts.map +1 -0
- package/dist/services/community-service.js +785 -0
- package/dist/services/community-service.js.map +1 -0
- package/dist/services/delegation-service.d.ts +149 -0
- package/dist/services/delegation-service.d.ts.map +1 -0
- package/dist/services/delegation-service.js +605 -0
- package/dist/services/delegation-service.js.map +1 -0
- package/dist/services/discovery-service.d.ts +39 -0
- package/dist/services/discovery-service.d.ts.map +1 -0
- package/dist/services/discovery-service.js +186 -0
- package/dist/services/discovery-service.js.map +1 -0
- package/dist/services/trust-service.d.ts +59 -0
- package/dist/services/trust-service.d.ts.map +1 -0
- package/dist/services/trust-service.js +139 -0
- package/dist/services/trust-service.js.map +1 -0
- package/package.json +2 -2
package/dist/routes/agents.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Agent Endpoints (Story 4.7)
|
|
2
|
+
* Agent Endpoints (Story 4.7 + B1 — Story 1.2)
|
|
3
3
|
*
|
|
4
|
-
* GET
|
|
5
|
-
* GET
|
|
4
|
+
* GET /api/agents — list all agents (with error rate from sessions)
|
|
5
|
+
* GET /api/agents/:id — single agent
|
|
6
|
+
* PUT /api/agents/:id/unpause — unpause an agent (clear paused_at, pause_reason, optionally model_override)
|
|
6
7
|
*/
|
|
7
8
|
import { Hono } from 'hono';
|
|
8
9
|
import type { IEventStore } from '@agentlensai/core';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;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,YAAY,CAAC,KAAK,EAAE,WAAW;eACX,aAAa;0CAsDhD"}
|
package/dist/routes/agents.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Agent Endpoints (Story 4.7)
|
|
2
|
+
* Agent Endpoints (Story 4.7 + B1 — Story 1.2)
|
|
3
3
|
*
|
|
4
|
-
* GET
|
|
5
|
-
* GET
|
|
4
|
+
* GET /api/agents — list all agents (with error rate from sessions)
|
|
5
|
+
* GET /api/agents/:id — single agent
|
|
6
|
+
* PUT /api/agents/:id/unpause — unpause an agent (clear paused_at, pause_reason, optionally model_override)
|
|
6
7
|
*/
|
|
7
8
|
import { Hono } from 'hono';
|
|
8
9
|
import { getTenantStore } from './tenant-helper.js';
|
|
@@ -12,15 +13,33 @@ export function agentsRoutes(store) {
|
|
|
12
13
|
app.get('/', async (c) => {
|
|
13
14
|
const tenantStore = getTenantStore(store, c);
|
|
14
15
|
const agents = await tenantStore.listAgents();
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
return c.json({ agents });
|
|
17
|
+
});
|
|
18
|
+
// PUT /api/agents/:id/unpause — Unpause an agent (B1 — Story 1.2)
|
|
19
|
+
app.put('/:id/unpause', async (c) => {
|
|
20
|
+
const tenantStore = getTenantStore(store, c);
|
|
21
|
+
const id = c.req.param('id');
|
|
22
|
+
// Verify agent exists (tenant-scoped)
|
|
23
|
+
const agent = await tenantStore.getAgent(id);
|
|
24
|
+
if (!agent) {
|
|
25
|
+
return c.json({ error: 'Agent not found', status: 404 }, 404);
|
|
26
|
+
}
|
|
27
|
+
// Parse optional body for clearModelOverride
|
|
28
|
+
let clearModelOverride = false;
|
|
29
|
+
try {
|
|
30
|
+
const body = await c.req.json().catch(() => ({}));
|
|
31
|
+
clearModelOverride = body?.clearModelOverride === true;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// No body or invalid JSON — that's fine
|
|
35
|
+
}
|
|
36
|
+
// Unpause by clearing pause fields via dedicated method
|
|
37
|
+
if ('unpauseAgent' in tenantStore && typeof tenantStore.unpauseAgent === 'function') {
|
|
38
|
+
await tenantStore.unpauseAgent(id, clearModelOverride);
|
|
39
|
+
}
|
|
40
|
+
// Return the updated agent
|
|
41
|
+
const updated = await tenantStore.getAgent(id);
|
|
42
|
+
return c.json(updated);
|
|
24
43
|
});
|
|
25
44
|
// GET /api/agents/:id — single agent
|
|
26
45
|
app.get('/:id', async (c) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,UAAU,YAAY,CAAC,KAAkB;IAC7C,MAAM,GAAG,GAAG,IAAI,IAAI,EAAgC,CAAC;IAErD,8DAA8D;IAC9D,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACvB,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,UAAU,EAAE,CAAC;QAE9C,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,kEAAkE;IAClE,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAClC,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC7C,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAE7B,sCAAsC;QACtC,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;QAChE,CAAC;QAED,6CAA6C;QAC7C,IAAI,kBAAkB,GAAG,KAAK,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAClD,kBAAkB,GAAG,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACP,wCAAwC;QAC1C,CAAC;QAED,wDAAwD;QACxD,IAAI,cAAc,IAAI,WAAW,IAAI,OAAO,WAAW,CAAC,YAAY,KAAK,UAAU,EAAE,CAAC;YACpF,MAAO,WAAmF,CAAC,YAAY,CAAC,EAAE,EAAE,kBAAkB,CAAC,CAAC;QAClI,CAAC;QAED,2BAA2B;QAC3B,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC/C,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,qCAAqC;IACrC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC1B,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC7C,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAE7C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;QAChE,CAAC;QAED,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sharing Audit & Export Routes (Story 7.4)
|
|
3
|
+
*
|
|
4
|
+
* GET /api/community/audit — query audit log with filters
|
|
5
|
+
* GET /api/community/audit/export — JSON export of sharing audit events
|
|
6
|
+
* GET /api/community/alerts — get volume alert config
|
|
7
|
+
* PUT /api/community/alerts — update volume alert config
|
|
8
|
+
*/
|
|
9
|
+
import { Hono } from 'hono';
|
|
10
|
+
import type { AuthVariables } from '../middleware/auth.js';
|
|
11
|
+
import type { SqliteDb } from '../db/index.js';
|
|
12
|
+
export declare function auditRoutes(db: SqliteDb): Hono<{
|
|
13
|
+
Variables: AuthVariables;
|
|
14
|
+
}, import("hono/types").BlankSchema, "/">;
|
|
15
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/routes/audit.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAI/C,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ;eACJ,aAAa;0CA4LhD"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sharing Audit & Export Routes (Story 7.4)
|
|
3
|
+
*
|
|
4
|
+
* GET /api/community/audit — query audit log with filters
|
|
5
|
+
* GET /api/community/audit/export — JSON export of sharing audit events
|
|
6
|
+
* GET /api/community/alerts — get volume alert config
|
|
7
|
+
* PUT /api/community/alerts — update volume alert config
|
|
8
|
+
*/
|
|
9
|
+
import { Hono } from 'hono';
|
|
10
|
+
import { eq, and, gte, lte, desc } from 'drizzle-orm';
|
|
11
|
+
import * as schema from '../db/schema.sqlite.js';
|
|
12
|
+
export function auditRoutes(db) {
|
|
13
|
+
const app = new Hono();
|
|
14
|
+
function getTenantId(c) {
|
|
15
|
+
return c.get('apiKey')?.tenantId ?? 'default';
|
|
16
|
+
}
|
|
17
|
+
// ─── GET /audit — query audit log with filters ─────
|
|
18
|
+
app.get('/', async (c) => {
|
|
19
|
+
const tenantId = getTenantId(c);
|
|
20
|
+
const eventType = c.req.query('type');
|
|
21
|
+
const agentId = c.req.query('agentId');
|
|
22
|
+
const dateFrom = c.req.query('dateFrom');
|
|
23
|
+
const dateTo = c.req.query('dateTo');
|
|
24
|
+
const limitStr = c.req.query('limit');
|
|
25
|
+
const offsetStr = c.req.query('offset');
|
|
26
|
+
const limit = limitStr ? Math.min(Math.max(1, parseInt(limitStr, 10) || 50), 500) : 50;
|
|
27
|
+
const offset = offsetStr ? Math.max(0, parseInt(offsetStr, 10) || 0) : 0;
|
|
28
|
+
// Query all rows for this tenant, then filter in JS (sqlite doesn't have great dynamic WHERE)
|
|
29
|
+
let rows = db
|
|
30
|
+
.select()
|
|
31
|
+
.from(schema.sharingAuditLog)
|
|
32
|
+
.where(eq(schema.sharingAuditLog.tenantId, tenantId))
|
|
33
|
+
.all();
|
|
34
|
+
// Apply filters
|
|
35
|
+
if (eventType) {
|
|
36
|
+
rows = rows.filter((r) => r.eventType === eventType);
|
|
37
|
+
}
|
|
38
|
+
if (agentId) {
|
|
39
|
+
// agentId filtering: match initiatedBy field
|
|
40
|
+
rows = rows.filter((r) => r.initiatedBy === agentId);
|
|
41
|
+
}
|
|
42
|
+
if (dateFrom) {
|
|
43
|
+
rows = rows.filter((r) => r.timestamp >= dateFrom);
|
|
44
|
+
}
|
|
45
|
+
if (dateTo) {
|
|
46
|
+
rows = rows.filter((r) => r.timestamp <= dateTo);
|
|
47
|
+
}
|
|
48
|
+
// Sort by timestamp descending
|
|
49
|
+
rows.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
50
|
+
const total = rows.length;
|
|
51
|
+
const paged = rows.slice(offset, offset + limit);
|
|
52
|
+
const events = paged.map((r) => ({
|
|
53
|
+
id: r.id,
|
|
54
|
+
tenantId: r.tenantId,
|
|
55
|
+
eventType: r.eventType,
|
|
56
|
+
lessonId: r.lessonId ?? undefined,
|
|
57
|
+
anonymousLessonId: r.anonymousLessonId ?? undefined,
|
|
58
|
+
lessonHash: r.lessonHash ?? undefined,
|
|
59
|
+
redactionFindings: r.redactionFindings ? JSON.parse(r.redactionFindings) : undefined,
|
|
60
|
+
queryText: r.queryText ?? undefined,
|
|
61
|
+
resultIds: r.resultIds ? JSON.parse(r.resultIds) : undefined,
|
|
62
|
+
poolEndpoint: r.poolEndpoint ?? undefined,
|
|
63
|
+
initiatedBy: r.initiatedBy ?? 'system',
|
|
64
|
+
timestamp: r.timestamp,
|
|
65
|
+
}));
|
|
66
|
+
return c.json({ events, total, hasMore: offset + paged.length < total });
|
|
67
|
+
});
|
|
68
|
+
// ─── GET /audit/export — JSON export ───────────────
|
|
69
|
+
app.get('/export', async (c) => {
|
|
70
|
+
const tenantId = getTenantId(c);
|
|
71
|
+
const type = c.req.query('type'); // optional filter by event type
|
|
72
|
+
let rows = db
|
|
73
|
+
.select()
|
|
74
|
+
.from(schema.sharingAuditLog)
|
|
75
|
+
.where(eq(schema.sharingAuditLog.tenantId, tenantId))
|
|
76
|
+
.all();
|
|
77
|
+
if (type) {
|
|
78
|
+
rows = rows.filter((r) => r.eventType === type);
|
|
79
|
+
}
|
|
80
|
+
rows.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
81
|
+
const events = rows.map((r) => ({
|
|
82
|
+
id: r.id,
|
|
83
|
+
tenantId: r.tenantId,
|
|
84
|
+
eventType: r.eventType,
|
|
85
|
+
lessonId: r.lessonId,
|
|
86
|
+
anonymousLessonId: r.anonymousLessonId,
|
|
87
|
+
lessonHash: r.lessonHash,
|
|
88
|
+
redactionFindings: r.redactionFindings ? JSON.parse(r.redactionFindings) : null,
|
|
89
|
+
queryText: r.queryText,
|
|
90
|
+
resultIds: r.resultIds ? JSON.parse(r.resultIds) : null,
|
|
91
|
+
poolEndpoint: r.poolEndpoint,
|
|
92
|
+
initiatedBy: r.initiatedBy,
|
|
93
|
+
timestamp: r.timestamp,
|
|
94
|
+
}));
|
|
95
|
+
c.header('Content-Type', 'application/json');
|
|
96
|
+
c.header('Content-Disposition', `attachment; filename="audit-export-${tenantId}-${new Date().toISOString().slice(0, 10)}.json"`);
|
|
97
|
+
return c.json({ exportedAt: new Date().toISOString(), tenantId, count: events.length, events });
|
|
98
|
+
});
|
|
99
|
+
// ─── GET /alerts — get volume alert config ─────────
|
|
100
|
+
app.get('/alerts', async (c) => {
|
|
101
|
+
const tenantId = getTenantId(c);
|
|
102
|
+
const config = db
|
|
103
|
+
.select()
|
|
104
|
+
.from(schema.sharingConfig)
|
|
105
|
+
.where(eq(schema.sharingConfig.tenantId, tenantId))
|
|
106
|
+
.get();
|
|
107
|
+
return c.json({
|
|
108
|
+
threshold: config?.volumeAlertThreshold ?? 100,
|
|
109
|
+
rateLimitPerHour: config?.rateLimitPerHour ?? 50,
|
|
110
|
+
enabled: config?.enabled ?? false,
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
// ─── PUT /alerts — update volume alert config ──────
|
|
114
|
+
app.put('/alerts', async (c) => {
|
|
115
|
+
const tenantId = getTenantId(c);
|
|
116
|
+
let body;
|
|
117
|
+
try {
|
|
118
|
+
body = await c.req.json();
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return c.json({ error: 'Invalid JSON body' }, 400);
|
|
122
|
+
}
|
|
123
|
+
const updates = {};
|
|
124
|
+
if (body.threshold !== undefined) {
|
|
125
|
+
const val = Number(body.threshold);
|
|
126
|
+
if (isNaN(val) || val < 1)
|
|
127
|
+
return c.json({ error: 'threshold must be >= 1' }, 400);
|
|
128
|
+
updates.volumeAlertThreshold = val;
|
|
129
|
+
}
|
|
130
|
+
if (body.rateLimitPerHour !== undefined) {
|
|
131
|
+
const val = Number(body.rateLimitPerHour);
|
|
132
|
+
if (isNaN(val) || val < 1)
|
|
133
|
+
return c.json({ error: 'rateLimitPerHour must be >= 1' }, 400);
|
|
134
|
+
updates.rateLimitPerHour = val;
|
|
135
|
+
}
|
|
136
|
+
if (Object.keys(updates).length === 0) {
|
|
137
|
+
return c.json({ error: 'No valid fields to update' }, 400);
|
|
138
|
+
}
|
|
139
|
+
const existing = db
|
|
140
|
+
.select()
|
|
141
|
+
.from(schema.sharingConfig)
|
|
142
|
+
.where(eq(schema.sharingConfig.tenantId, tenantId))
|
|
143
|
+
.get();
|
|
144
|
+
const now = new Date().toISOString();
|
|
145
|
+
if (existing) {
|
|
146
|
+
db.update(schema.sharingConfig)
|
|
147
|
+
.set({ ...updates, updatedAt: now })
|
|
148
|
+
.where(eq(schema.sharingConfig.tenantId, tenantId))
|
|
149
|
+
.run();
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
db.insert(schema.sharingConfig).values({
|
|
153
|
+
tenantId,
|
|
154
|
+
enabled: false,
|
|
155
|
+
humanReviewEnabled: false,
|
|
156
|
+
poolEndpoint: null,
|
|
157
|
+
anonymousContributorId: null,
|
|
158
|
+
purgeToken: null,
|
|
159
|
+
rateLimitPerHour: updates.rateLimitPerHour ?? 50,
|
|
160
|
+
volumeAlertThreshold: updates.volumeAlertThreshold ?? 100,
|
|
161
|
+
updatedAt: now,
|
|
162
|
+
}).run();
|
|
163
|
+
}
|
|
164
|
+
const config = db
|
|
165
|
+
.select()
|
|
166
|
+
.from(schema.sharingConfig)
|
|
167
|
+
.where(eq(schema.sharingConfig.tenantId, tenantId))
|
|
168
|
+
.get();
|
|
169
|
+
return c.json({
|
|
170
|
+
threshold: config?.volumeAlertThreshold ?? 100,
|
|
171
|
+
rateLimitPerHour: config?.rateLimitPerHour ?? 50,
|
|
172
|
+
enabled: config?.enabled ?? false,
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
return app;
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/routes/audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability Registration REST API (Story 5.2)
|
|
3
|
+
*
|
|
4
|
+
* PUT /api/agents/:id/capabilities — register a new capability
|
|
5
|
+
* GET /api/agents/:id/capabilities — list agent's capabilities
|
|
6
|
+
* DELETE /api/agents/:id/capabilities/:capabilityId — remove a capability
|
|
7
|
+
*/
|
|
8
|
+
import { Hono } from 'hono';
|
|
9
|
+
import type { IEventStore } from '@agentlensai/core';
|
|
10
|
+
import type { AuthVariables } from '../middleware/auth.js';
|
|
11
|
+
import type { SqliteDb } from '../db/index.js';
|
|
12
|
+
export declare function capabilityRoutes(store: IEventStore, db: SqliteDb): Hono<{
|
|
13
|
+
Variables: AuthVariables;
|
|
14
|
+
}, import("hono/types").BlankSchema, "/">;
|
|
15
|
+
//# sourceMappingURL=capabilities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../src/routes/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;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;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAK/C,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ;eAC7B,aAAa;0CAmFhD"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability Registration REST API (Story 5.2)
|
|
3
|
+
*
|
|
4
|
+
* PUT /api/agents/:id/capabilities — register a new capability
|
|
5
|
+
* GET /api/agents/:id/capabilities — list agent's capabilities
|
|
6
|
+
* DELETE /api/agents/:id/capabilities/:capabilityId — remove a capability
|
|
7
|
+
*/
|
|
8
|
+
import { Hono } from 'hono';
|
|
9
|
+
import { CapabilityStore, ValidationError } from '../db/capability-store.js';
|
|
10
|
+
import { AnonymousIdManager } from '../db/anonymous-id-manager.js';
|
|
11
|
+
import { getTenantStore } from './tenant-helper.js';
|
|
12
|
+
export function capabilityRoutes(store, db) {
|
|
13
|
+
const app = new Hono();
|
|
14
|
+
const capStore = new CapabilityStore(db);
|
|
15
|
+
const anonIdManager = new AnonymousIdManager(db);
|
|
16
|
+
/**
|
|
17
|
+
* Helper to get tenant ID from auth context.
|
|
18
|
+
*/
|
|
19
|
+
function getTenantId(c) {
|
|
20
|
+
return c.get('apiKey')?.tenantId ?? 'default';
|
|
21
|
+
}
|
|
22
|
+
// PUT /:id/capabilities — register or update a capability
|
|
23
|
+
app.put('/:id/capabilities', async (c) => {
|
|
24
|
+
const tenantId = getTenantId(c);
|
|
25
|
+
const agentId = c.req.param('id');
|
|
26
|
+
// Verify agent exists
|
|
27
|
+
const tenantStore = getTenantStore(store, c);
|
|
28
|
+
const agent = await tenantStore.getAgent(agentId);
|
|
29
|
+
if (!agent) {
|
|
30
|
+
return c.json({ error: 'Agent not found', status: 404 }, 404);
|
|
31
|
+
}
|
|
32
|
+
let body;
|
|
33
|
+
try {
|
|
34
|
+
body = await c.req.json();
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return c.json({ error: 'Invalid JSON body', status: 400 }, 400);
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const capability = capStore.create(tenantId, agentId, body);
|
|
41
|
+
const anonymousAgentId = anonIdManager.getOrRotateAnonymousId(tenantId, agentId);
|
|
42
|
+
return c.json({ capability, anonymousAgentId }, 201);
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
if (err instanceof ValidationError) {
|
|
46
|
+
return c.json({ error: err.message, status: 400 }, 400);
|
|
47
|
+
}
|
|
48
|
+
throw err;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
// GET /:id/capabilities — list agent's capabilities
|
|
52
|
+
app.get('/:id/capabilities', async (c) => {
|
|
53
|
+
const tenantId = getTenantId(c);
|
|
54
|
+
const agentId = c.req.param('id');
|
|
55
|
+
// Verify agent exists
|
|
56
|
+
const tenantStore = getTenantStore(store, c);
|
|
57
|
+
const agent = await tenantStore.getAgent(agentId);
|
|
58
|
+
if (!agent) {
|
|
59
|
+
return c.json({ error: 'Agent not found', status: 404 }, 404);
|
|
60
|
+
}
|
|
61
|
+
const capabilities = capStore.listByAgent(tenantId, agentId);
|
|
62
|
+
const anonymousAgentId = anonIdManager.getOrRotateAnonymousId(tenantId, agentId);
|
|
63
|
+
return c.json({ capabilities, anonymousAgentId });
|
|
64
|
+
});
|
|
65
|
+
// DELETE /:id/capabilities/:capabilityId — remove a capability
|
|
66
|
+
app.delete('/:id/capabilities/:capabilityId', async (c) => {
|
|
67
|
+
const tenantId = getTenantId(c);
|
|
68
|
+
const agentId = c.req.param('id');
|
|
69
|
+
const capabilityId = c.req.param('capabilityId');
|
|
70
|
+
// Verify agent exists
|
|
71
|
+
const tenantStore = getTenantStore(store, c);
|
|
72
|
+
const agent = await tenantStore.getAgent(agentId);
|
|
73
|
+
if (!agent) {
|
|
74
|
+
return c.json({ error: 'Agent not found', status: 404 }, 404);
|
|
75
|
+
}
|
|
76
|
+
// Verify the capability belongs to this agent
|
|
77
|
+
const existing = capStore.getById(tenantId, capabilityId);
|
|
78
|
+
if (!existing || existing.agentId !== agentId) {
|
|
79
|
+
return c.json({ error: 'Capability not found', status: 404 }, 404);
|
|
80
|
+
}
|
|
81
|
+
capStore.delete(tenantId, capabilityId);
|
|
82
|
+
return c.json({ deleted: true });
|
|
83
|
+
});
|
|
84
|
+
return app;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=capabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/routes/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,UAAU,gBAAgB,CAAC,KAAkB,EAAE,EAAY;IAC/D,MAAM,GAAG,GAAG,IAAI,IAAI,EAAgC,CAAC;IACrD,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,EAAE,CAAC,CAAC;IACzC,MAAM,aAAa,GAAG,IAAI,kBAAkB,CAAC,EAAE,CAAC,CAAC;IAEjD;;OAEG;IACH,SAAS,WAAW,CAAC,CAA4D;QAC/E,OAAO,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,QAAQ,IAAI,SAAS,CAAC;IAChD,CAAC;IAED,0DAA0D;IAC1D,GAAG,CAAC,GAAG,CAAC,mBAAmB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACvC,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,sBAAsB;QACtB,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC7C,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAClD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;QAChE,CAAC;QAED,IAAI,IAA6B,CAAC;QAClC,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;QAClE,CAAC;QAED,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAwD,CAAC,CAAC;YAChH,MAAM,gBAAgB,GAAG,aAAa,CAAC,sBAAsB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACjF,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,gBAAgB,EAAE,EAAE,GAAG,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,eAAe,EAAE,CAAC;gBACnC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;YAC1D,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,oDAAoD;IACpD,GAAG,CAAC,GAAG,CAAC,mBAAmB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACvC,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,sBAAsB;QACtB,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC7C,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAClD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,YAAY,GAAG,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC7D,MAAM,gBAAgB,GAAG,aAAa,CAAC,sBAAsB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACjF,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,+DAA+D;IAC/D,GAAG,CAAC,MAAM,CAAC,iCAAiC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACxD,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,YAAY,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAEjD,sBAAsB;QACtB,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC7C,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAClD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;QAChE,CAAC;QAED,8CAA8C;QAC9C,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QAC1D,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;YAC9C,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;QACrE,CAAC;QAED,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QACxC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Community Sharing REST API (Stories 4.1–4.3)
|
|
3
|
+
*
|
|
4
|
+
* POST /api/community/share — share a lesson
|
|
5
|
+
* GET /api/community/search — search shared lessons
|
|
6
|
+
* GET /api/community/config — get tenant sharing config
|
|
7
|
+
* PUT /api/community/config — update tenant sharing config
|
|
8
|
+
* GET /api/community/config/agents/:agentId — get agent sharing config
|
|
9
|
+
* PUT /api/community/config/agents/:agentId — update agent sharing config
|
|
10
|
+
* GET /api/community/deny-list — list deny-list rules
|
|
11
|
+
* POST /api/community/deny-list — add deny-list rule
|
|
12
|
+
* DELETE /api/community/deny-list/:id — delete deny-list rule
|
|
13
|
+
*/
|
|
14
|
+
import { Hono } from 'hono';
|
|
15
|
+
import type { AuthVariables } from '../middleware/auth.js';
|
|
16
|
+
import type { SqliteDb } from '../db/index.js';
|
|
17
|
+
import { CommunityService, type PoolTransport } from '../services/community-service.js';
|
|
18
|
+
export declare function communityRoutes(db: SqliteDb, transport?: PoolTransport): {
|
|
19
|
+
app: Hono<{
|
|
20
|
+
Variables: AuthVariables;
|
|
21
|
+
}, import("hono/types").BlankSchema, "/">;
|
|
22
|
+
service: CommunityService;
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=community.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"community.d.ts","sourceRoot":"","sources":["../../src/routes/community.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAA+B,KAAK,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAKrH,wBAAgB,eAAe,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,aAAa;;mBACnC,aAAa;;;EAyLhD"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Community Sharing REST API (Stories 4.1–4.3)
|
|
3
|
+
*
|
|
4
|
+
* POST /api/community/share — share a lesson
|
|
5
|
+
* GET /api/community/search — search shared lessons
|
|
6
|
+
* GET /api/community/config — get tenant sharing config
|
|
7
|
+
* PUT /api/community/config — update tenant sharing config
|
|
8
|
+
* GET /api/community/config/agents/:agentId — get agent sharing config
|
|
9
|
+
* PUT /api/community/config/agents/:agentId — update agent sharing config
|
|
10
|
+
* GET /api/community/deny-list — list deny-list rules
|
|
11
|
+
* POST /api/community/deny-list — add deny-list rule
|
|
12
|
+
* DELETE /api/community/deny-list/:id — delete deny-list rule
|
|
13
|
+
*/
|
|
14
|
+
import { Hono } from 'hono';
|
|
15
|
+
import { CommunityService, LocalCommunityPoolTransport } from '../services/community-service.js';
|
|
16
|
+
import { LESSON_SHARING_CATEGORIES } from '@agentlensai/core';
|
|
17
|
+
const VALID_CATEGORIES = new Set(LESSON_SHARING_CATEGORIES);
|
|
18
|
+
export function communityRoutes(db, transport) {
|
|
19
|
+
const app = new Hono();
|
|
20
|
+
const poolTransport = transport ?? new LocalCommunityPoolTransport();
|
|
21
|
+
const service = new CommunityService(db, { transport: poolTransport });
|
|
22
|
+
function getTenantId(c) {
|
|
23
|
+
return c.get('apiKey')?.tenantId ?? 'default';
|
|
24
|
+
}
|
|
25
|
+
// ─── Share ─────────────────────────────────────────
|
|
26
|
+
app.post('/share', async (c) => {
|
|
27
|
+
const tenantId = getTenantId(c);
|
|
28
|
+
let body;
|
|
29
|
+
try {
|
|
30
|
+
body = await c.req.json();
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return c.json({ error: 'Invalid JSON body' }, 400);
|
|
34
|
+
}
|
|
35
|
+
const lessonId = body.lessonId;
|
|
36
|
+
if (!lessonId || typeof lessonId !== 'string') {
|
|
37
|
+
return c.json({ error: 'lessonId is required' }, 400);
|
|
38
|
+
}
|
|
39
|
+
const result = await service.share(tenantId, lessonId, 'api');
|
|
40
|
+
switch (result.status) {
|
|
41
|
+
case 'shared':
|
|
42
|
+
return c.json(result, 201);
|
|
43
|
+
case 'rate_limited':
|
|
44
|
+
return c.json({ error: 'Rate limit exceeded', status: 'rate_limited' }, 429);
|
|
45
|
+
case 'disabled':
|
|
46
|
+
return c.json({ error: result.reason, status: 'disabled' }, 403);
|
|
47
|
+
case 'blocked':
|
|
48
|
+
return c.json({ error: result.reason, status: 'blocked' }, 422);
|
|
49
|
+
case 'pending_review':
|
|
50
|
+
return c.json(result, 202);
|
|
51
|
+
case 'error':
|
|
52
|
+
return c.json({ error: result.error, status: 'error' }, 500);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
// ─── Search ────────────────────────────────────────
|
|
56
|
+
app.get('/search', async (c) => {
|
|
57
|
+
const tenantId = getTenantId(c);
|
|
58
|
+
const query = c.req.query('q');
|
|
59
|
+
if (!query) {
|
|
60
|
+
return c.json({ error: 'q (query) parameter is required' }, 400);
|
|
61
|
+
}
|
|
62
|
+
const category = c.req.query('category') || undefined;
|
|
63
|
+
if (category && !VALID_CATEGORIES.has(category)) {
|
|
64
|
+
return c.json({ error: `Invalid category. Must be one of: ${LESSON_SHARING_CATEGORIES.join(', ')}` }, 400);
|
|
65
|
+
}
|
|
66
|
+
const minReputation = c.req.query('minReputation') ? Number(c.req.query('minReputation')) : undefined;
|
|
67
|
+
const limit = c.req.query('limit') ? Math.min(Number(c.req.query('limit')), 50) : 50;
|
|
68
|
+
const result = await service.search(tenantId, query, { category, minReputation, limit }, 'api');
|
|
69
|
+
return c.json(result);
|
|
70
|
+
});
|
|
71
|
+
// ─── Tenant Config ────────────────────────────────
|
|
72
|
+
app.get('/config', async (c) => {
|
|
73
|
+
const tenantId = getTenantId(c);
|
|
74
|
+
const config = service.getSharingConfig(tenantId);
|
|
75
|
+
return c.json({ config });
|
|
76
|
+
});
|
|
77
|
+
app.put('/config', async (c) => {
|
|
78
|
+
const tenantId = getTenantId(c);
|
|
79
|
+
let body;
|
|
80
|
+
try {
|
|
81
|
+
body = await c.req.json();
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return c.json({ error: 'Invalid JSON body' }, 400);
|
|
85
|
+
}
|
|
86
|
+
const updates = {};
|
|
87
|
+
if (body.enabled !== undefined)
|
|
88
|
+
updates.enabled = Boolean(body.enabled);
|
|
89
|
+
if (body.humanReviewEnabled !== undefined)
|
|
90
|
+
updates.humanReviewEnabled = Boolean(body.humanReviewEnabled);
|
|
91
|
+
if (body.poolEndpoint !== undefined)
|
|
92
|
+
updates.poolEndpoint = body.poolEndpoint;
|
|
93
|
+
if (body.rateLimitPerHour !== undefined) {
|
|
94
|
+
const val = Number(body.rateLimitPerHour);
|
|
95
|
+
if (isNaN(val) || val < 1)
|
|
96
|
+
return c.json({ error: 'rateLimitPerHour must be >= 1' }, 400);
|
|
97
|
+
updates.rateLimitPerHour = val;
|
|
98
|
+
}
|
|
99
|
+
if (body.volumeAlertThreshold !== undefined) {
|
|
100
|
+
const val = Number(body.volumeAlertThreshold);
|
|
101
|
+
if (isNaN(val) || val < 1)
|
|
102
|
+
return c.json({ error: 'volumeAlertThreshold must be >= 1' }, 400);
|
|
103
|
+
updates.volumeAlertThreshold = val;
|
|
104
|
+
}
|
|
105
|
+
if (body.categories !== undefined) {
|
|
106
|
+
if (!Array.isArray(body.categories))
|
|
107
|
+
return c.json({ error: 'categories must be an array' }, 400);
|
|
108
|
+
for (const cat of body.categories) {
|
|
109
|
+
if (!VALID_CATEGORIES.has(cat)) {
|
|
110
|
+
return c.json({ error: `Invalid category: ${cat}` }, 400);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const config = service.updateSharingConfig(tenantId, updates);
|
|
115
|
+
return c.json({ config });
|
|
116
|
+
});
|
|
117
|
+
// ─── Agent Config ──────────────────────────────────
|
|
118
|
+
app.get('/config/agents/:agentId', async (c) => {
|
|
119
|
+
const tenantId = getTenantId(c);
|
|
120
|
+
const agentId = c.req.param('agentId');
|
|
121
|
+
const config = service.getAgentSharingConfig(tenantId, agentId);
|
|
122
|
+
return c.json({ config });
|
|
123
|
+
});
|
|
124
|
+
app.put('/config/agents/:agentId', async (c) => {
|
|
125
|
+
const tenantId = getTenantId(c);
|
|
126
|
+
const agentId = c.req.param('agentId');
|
|
127
|
+
let body;
|
|
128
|
+
try {
|
|
129
|
+
body = await c.req.json();
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return c.json({ error: 'Invalid JSON body' }, 400);
|
|
133
|
+
}
|
|
134
|
+
const updates = {};
|
|
135
|
+
if (body.enabled !== undefined)
|
|
136
|
+
updates.enabled = Boolean(body.enabled);
|
|
137
|
+
if (body.categories !== undefined) {
|
|
138
|
+
if (!Array.isArray(body.categories))
|
|
139
|
+
return c.json({ error: 'categories must be an array' }, 400);
|
|
140
|
+
for (const cat of body.categories) {
|
|
141
|
+
if (!VALID_CATEGORIES.has(cat)) {
|
|
142
|
+
return c.json({ error: `Invalid category: ${cat}` }, 400);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
updates.categories = body.categories;
|
|
146
|
+
}
|
|
147
|
+
const config = service.updateAgentSharingConfig(tenantId, agentId, updates);
|
|
148
|
+
return c.json({ config });
|
|
149
|
+
});
|
|
150
|
+
// ─── Deny List ─────────────────────────────────────
|
|
151
|
+
app.get('/deny-list', async (c) => {
|
|
152
|
+
const tenantId = getTenantId(c);
|
|
153
|
+
const rules = service.getDenyList(tenantId);
|
|
154
|
+
return c.json({ rules });
|
|
155
|
+
});
|
|
156
|
+
app.post('/deny-list', async (c) => {
|
|
157
|
+
const tenantId = getTenantId(c);
|
|
158
|
+
let body;
|
|
159
|
+
try {
|
|
160
|
+
body = await c.req.json();
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
return c.json({ error: 'Invalid JSON body' }, 400);
|
|
164
|
+
}
|
|
165
|
+
const pattern = body.pattern;
|
|
166
|
+
if (!pattern || typeof pattern !== 'string') {
|
|
167
|
+
return c.json({ error: 'pattern is required' }, 400);
|
|
168
|
+
}
|
|
169
|
+
const reason = body.reason || 'No reason provided';
|
|
170
|
+
const isRegex = Boolean(body.isRegex);
|
|
171
|
+
try {
|
|
172
|
+
const rule = service.addDenyListRule(tenantId, pattern, isRegex, reason);
|
|
173
|
+
return c.json({ rule }, 201);
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
return c.json({ error: err instanceof Error ? err.message : String(err) }, 400);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
app.delete('/deny-list/:id', async (c) => {
|
|
180
|
+
const tenantId = getTenantId(c);
|
|
181
|
+
const ruleId = c.req.param('id');
|
|
182
|
+
const ok = service.deleteDenyListRule(tenantId, ruleId);
|
|
183
|
+
if (!ok) {
|
|
184
|
+
return c.json({ error: 'Rule not found' }, 404);
|
|
185
|
+
}
|
|
186
|
+
return c.json({ deleted: true });
|
|
187
|
+
});
|
|
188
|
+
return { app, service };
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=community.js.map
|