@sourcepress/server 0.1.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/.omc/state/agent-replay-31d84b63-606a-4368-b9e6-93fe4f5ae0f7.jsonl +2 -0
- package/.omc/state/last-tool-error.json +7 -0
- package/.omc/state/mission-state.json +53 -0
- package/.omc/state/subagent-tracking.json +17 -0
- package/.turbo/turbo-build.log +4 -0
- package/.turbo/turbo-test.log +26 -0
- package/dist/__tests__/app-integration.test.d.ts +2 -0
- package/dist/__tests__/app-integration.test.d.ts.map +1 -0
- package/dist/__tests__/app-integration.test.js +71 -0
- package/dist/__tests__/app-integration.test.js.map +1 -0
- package/dist/__tests__/approval.test.d.ts +2 -0
- package/dist/__tests__/approval.test.d.ts.map +1 -0
- package/dist/__tests__/approval.test.js +170 -0
- package/dist/__tests__/approval.test.js.map +1 -0
- package/dist/__tests__/content.test.d.ts +2 -0
- package/dist/__tests__/content.test.d.ts.map +1 -0
- package/dist/__tests__/content.test.js +187 -0
- package/dist/__tests__/content.test.js.map +1 -0
- package/dist/__tests__/engine.test.d.ts +2 -0
- package/dist/__tests__/engine.test.d.ts.map +1 -0
- package/dist/__tests__/engine.test.js +77 -0
- package/dist/__tests__/engine.test.js.map +1 -0
- package/dist/__tests__/eval.test.d.ts +2 -0
- package/dist/__tests__/eval.test.d.ts.map +1 -0
- package/dist/__tests__/eval.test.js +320 -0
- package/dist/__tests__/eval.test.js.map +1 -0
- package/dist/__tests__/graph.test.d.ts +2 -0
- package/dist/__tests__/graph.test.d.ts.map +1 -0
- package/dist/__tests__/graph.test.js +169 -0
- package/dist/__tests__/graph.test.js.map +1 -0
- package/dist/__tests__/health.test.d.ts +2 -0
- package/dist/__tests__/health.test.d.ts.map +1 -0
- package/dist/__tests__/health.test.js +56 -0
- package/dist/__tests__/health.test.js.map +1 -0
- package/dist/__tests__/import.test.d.ts +2 -0
- package/dist/__tests__/import.test.d.ts.map +1 -0
- package/dist/__tests__/import.test.js +138 -0
- package/dist/__tests__/import.test.js.map +1 -0
- package/dist/__tests__/intent.test.d.ts +2 -0
- package/dist/__tests__/intent.test.d.ts.map +1 -0
- package/dist/__tests__/intent.test.js +122 -0
- package/dist/__tests__/intent.test.js.map +1 -0
- package/dist/__tests__/jobs.test.d.ts +2 -0
- package/dist/__tests__/jobs.test.d.ts.map +1 -0
- package/dist/__tests__/jobs.test.js +96 -0
- package/dist/__tests__/jobs.test.js.map +1 -0
- package/dist/__tests__/knowledge.test.d.ts +2 -0
- package/dist/__tests__/knowledge.test.d.ts.map +1 -0
- package/dist/__tests__/knowledge.test.js +110 -0
- package/dist/__tests__/knowledge.test.js.map +1 -0
- package/dist/__tests__/media-routes.test.d.ts +2 -0
- package/dist/__tests__/media-routes.test.d.ts.map +1 -0
- package/dist/__tests__/media-routes.test.js +88 -0
- package/dist/__tests__/media-routes.test.js.map +1 -0
- package/dist/__tests__/schema.test.d.ts +2 -0
- package/dist/__tests__/schema.test.d.ts.map +1 -0
- package/dist/__tests__/schema.test.js +92 -0
- package/dist/__tests__/schema.test.js.map +1 -0
- package/dist/app.d.ts +7 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +85 -0
- package/dist/app.js.map +1 -0
- package/dist/engine.d.ts +38 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +106 -0
- package/dist/engine.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/auth.d.ts +17 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +54 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/cors.d.ts +2 -0
- package/dist/middleware/cors.d.ts.map +1 -0
- package/dist/middleware/cors.js +13 -0
- package/dist/middleware/cors.js.map +1 -0
- package/dist/middleware/error-handler.d.ts +24 -0
- package/dist/middleware/error-handler.d.ts.map +1 -0
- package/dist/middleware/error-handler.js +30 -0
- package/dist/middleware/error-handler.js.map +1 -0
- package/dist/middleware/index.d.ts +7 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +5 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/rate-limit.d.ts +11 -0
- package/dist/middleware/rate-limit.d.ts.map +1 -0
- package/dist/middleware/rate-limit.js +26 -0
- package/dist/middleware/rate-limit.js.map +1 -0
- package/dist/middleware/route-error-handler.d.ts +12 -0
- package/dist/middleware/route-error-handler.d.ts.map +1 -0
- package/dist/middleware/route-error-handler.js +9 -0
- package/dist/middleware/route-error-handler.js.map +1 -0
- package/dist/routes/approval.d.ts +4 -0
- package/dist/routes/approval.d.ts.map +1 -0
- package/dist/routes/approval.js +70 -0
- package/dist/routes/approval.js.map +1 -0
- package/dist/routes/content.d.ts +4 -0
- package/dist/routes/content.d.ts.map +1 -0
- package/dist/routes/content.js +145 -0
- package/dist/routes/content.js.map +1 -0
- package/dist/routes/eval.d.ts +4 -0
- package/dist/routes/eval.d.ts.map +1 -0
- package/dist/routes/eval.js +178 -0
- package/dist/routes/eval.js.map +1 -0
- package/dist/routes/graph.d.ts +4 -0
- package/dist/routes/graph.d.ts.map +1 -0
- package/dist/routes/graph.js +90 -0
- package/dist/routes/graph.js.map +1 -0
- package/dist/routes/health.d.ts +13 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +19 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/import.d.ts +4 -0
- package/dist/routes/import.d.ts.map +1 -0
- package/dist/routes/import.js +85 -0
- package/dist/routes/import.js.map +1 -0
- package/dist/routes/index.d.ts +12 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +12 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/intent.d.ts +4 -0
- package/dist/routes/intent.d.ts.map +1 -0
- package/dist/routes/intent.js +80 -0
- package/dist/routes/intent.js.map +1 -0
- package/dist/routes/jobs.d.ts +4 -0
- package/dist/routes/jobs.d.ts.map +1 -0
- package/dist/routes/jobs.js +67 -0
- package/dist/routes/jobs.js.map +1 -0
- package/dist/routes/knowledge.d.ts +4 -0
- package/dist/routes/knowledge.d.ts.map +1 -0
- package/dist/routes/knowledge.js +48 -0
- package/dist/routes/knowledge.js.map +1 -0
- package/dist/routes/media.d.ts +4 -0
- package/dist/routes/media.d.ts.map +1 -0
- package/dist/routes/media.js +87 -0
- package/dist/routes/media.js.map +1 -0
- package/dist/routes/schema.d.ts +4 -0
- package/dist/routes/schema.d.ts.map +1 -0
- package/dist/routes/schema.js +54 -0
- package/dist/routes/schema.js.map +1 -0
- package/dist/standalone.d.ts +2 -0
- package/dist/standalone.d.ts.map +1 -0
- package/dist/standalone.js +115 -0
- package/dist/standalone.js.map +1 -0
- package/package.json +36 -0
- package/src/__tests__/app-integration.test.ts +80 -0
- package/src/__tests__/approval.test.ts +195 -0
- package/src/__tests__/content.test.ts +202 -0
- package/src/__tests__/engine.test.ts +86 -0
- package/src/__tests__/eval.test.ts +343 -0
- package/src/__tests__/graph.test.ts +182 -0
- package/src/__tests__/health.test.ts +68 -0
- package/src/__tests__/import.test.ts +148 -0
- package/src/__tests__/intent.test.ts +133 -0
- package/src/__tests__/jobs.test.ts +107 -0
- package/src/__tests__/knowledge.test.ts +121 -0
- package/src/__tests__/media-routes.test.ts +109 -0
- package/src/__tests__/schema.test.ts +100 -0
- package/src/app.ts +92 -0
- package/src/engine.ts +168 -0
- package/src/index.ts +31 -0
- package/src/middleware/auth.ts +66 -0
- package/src/middleware/cors.ts +15 -0
- package/src/middleware/error-handler.ts +42 -0
- package/src/middleware/index.ts +6 -0
- package/src/middleware/rate-limit.ts +27 -0
- package/src/middleware/route-error-handler.ts +13 -0
- package/src/routes/approval.ts +90 -0
- package/src/routes/content.ts +256 -0
- package/src/routes/eval.ts +262 -0
- package/src/routes/graph.ts +111 -0
- package/src/routes/health.ts +33 -0
- package/src/routes/import.ts +122 -0
- package/src/routes/index.ts +11 -0
- package/src/routes/intent.ts +105 -0
- package/src/routes/jobs.ts +84 -0
- package/src/routes/knowledge.ts +73 -0
- package/src/routes/media.ts +117 -0
- package/src/routes/schema.ts +75 -0
- package/src/standalone.ts +130 -0
- package/tsconfig.json +8 -0
- package/vitest.config.ts +7 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { SourcePressError } from "../middleware/error-handler.js";
|
|
3
|
+
import { handleRouteError } from "../middleware/route-error-handler.js";
|
|
4
|
+
export function graphRoutes(engine) {
|
|
5
|
+
const app = new Hono();
|
|
6
|
+
app.onError(handleRouteError);
|
|
7
|
+
// GET /graph — get full graph summary
|
|
8
|
+
app.get("/graph", async (c) => {
|
|
9
|
+
const graph = engine.knowledge.getGraph();
|
|
10
|
+
if (!graph) {
|
|
11
|
+
return c.json({
|
|
12
|
+
status: "empty",
|
|
13
|
+
message: "No graph built yet. POST /api/graph/rebuild to build.",
|
|
14
|
+
entities: 0,
|
|
15
|
+
relations: 0,
|
|
16
|
+
clusters: 0,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
// Serialize Map to array for JSON
|
|
20
|
+
const entities = Array.from(graph.entities.values()).map((e) => ({
|
|
21
|
+
name: e.name,
|
|
22
|
+
type: e.type,
|
|
23
|
+
aliases: e.aliases,
|
|
24
|
+
confidence: e.confidence,
|
|
25
|
+
source_file: e.source_file,
|
|
26
|
+
}));
|
|
27
|
+
return c.json({
|
|
28
|
+
status: "built",
|
|
29
|
+
built_at: graph.built_at,
|
|
30
|
+
file_count: graph.file_count,
|
|
31
|
+
entity_count: entities.length,
|
|
32
|
+
relation_count: graph.relations.length,
|
|
33
|
+
cluster_count: graph.clusters.length,
|
|
34
|
+
entities,
|
|
35
|
+
relations: graph.relations,
|
|
36
|
+
clusters: graph.clusters,
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
// GET /graph/entity/:name — query a specific entity
|
|
40
|
+
app.get("/graph/entity/:name", async (c) => {
|
|
41
|
+
const name = decodeURIComponent(c.req.param("name"));
|
|
42
|
+
const result = engine.knowledge.query(name);
|
|
43
|
+
if (!result) {
|
|
44
|
+
throw new SourcePressError(404, "ENTITY_NOT_FOUND", `Entity "${name}" not found in graph. Graph may need rebuilding.`);
|
|
45
|
+
}
|
|
46
|
+
return c.json(result);
|
|
47
|
+
});
|
|
48
|
+
// GET /graph/stale — find stale content
|
|
49
|
+
app.get("/graph/stale", async (c) => {
|
|
50
|
+
const collections = engine.listCollections();
|
|
51
|
+
const allContent = [];
|
|
52
|
+
for (const coll of collections) {
|
|
53
|
+
const files = await engine.listContent(coll);
|
|
54
|
+
allContent.push(...files);
|
|
55
|
+
}
|
|
56
|
+
// Build timestamps from knowledge store
|
|
57
|
+
const knowledgeFiles = await engine.knowledgeStore.list();
|
|
58
|
+
const timestamps = {};
|
|
59
|
+
for (const f of knowledgeFiles) {
|
|
60
|
+
timestamps[f.path] = f.ingested_at;
|
|
61
|
+
}
|
|
62
|
+
const stale = engine.knowledge.findStale(allContent, timestamps);
|
|
63
|
+
return c.json({ items: stale, total: stale.length });
|
|
64
|
+
});
|
|
65
|
+
// GET /graph/gaps — find knowledge gaps
|
|
66
|
+
app.get("/graph/gaps", async (c) => {
|
|
67
|
+
const collections = engine.listCollections();
|
|
68
|
+
const allContent = [];
|
|
69
|
+
for (const coll of collections) {
|
|
70
|
+
const files = await engine.listContent(coll);
|
|
71
|
+
allContent.push(...files);
|
|
72
|
+
}
|
|
73
|
+
const gaps = engine.knowledge.findGaps(allContent);
|
|
74
|
+
return c.json({ items: gaps, total: gaps.length });
|
|
75
|
+
});
|
|
76
|
+
// POST /graph/rebuild — rebuild the knowledge graph
|
|
77
|
+
app.post("/graph/rebuild", async (c) => {
|
|
78
|
+
const graph = await engine.knowledge.buildGraph();
|
|
79
|
+
return c.json({
|
|
80
|
+
rebuilt: true,
|
|
81
|
+
built_at: graph.built_at,
|
|
82
|
+
entity_count: graph.entities.size,
|
|
83
|
+
relation_count: graph.relations.length,
|
|
84
|
+
cluster_count: graph.clusters.length,
|
|
85
|
+
file_count: graph.file_count,
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
return app;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.js","sourceRoot":"","sources":["../../src/routes/graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
export interface HealthStatus {
|
|
3
|
+
status: "ok" | "degraded" | "error";
|
|
4
|
+
version: string;
|
|
5
|
+
timestamp: string;
|
|
6
|
+
services: {
|
|
7
|
+
github: "connected" | "disconnected" | "unknown";
|
|
8
|
+
knowledge: "ready" | "empty" | "unknown";
|
|
9
|
+
cache: "ready" | "unknown";
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export declare function healthRoutes(): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
13
|
+
//# sourceMappingURL=health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/routes/health.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,IAAI,GAAG,UAAU,GAAG,OAAO,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE;QACT,MAAM,EAAE,WAAW,GAAG,cAAc,GAAG,SAAS,CAAC;QACjD,SAAS,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;QACzC,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;KAC3B,CAAC;CACF;AAED,wBAAgB,YAAY,+EAmB3B"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
export function healthRoutes() {
|
|
3
|
+
const app = new Hono();
|
|
4
|
+
app.get("/health", (c) => {
|
|
5
|
+
const health = {
|
|
6
|
+
status: "ok",
|
|
7
|
+
version: "0.1.0",
|
|
8
|
+
timestamp: new Date().toISOString(),
|
|
9
|
+
services: {
|
|
10
|
+
github: "unknown",
|
|
11
|
+
knowledge: "unknown",
|
|
12
|
+
cache: "unknown",
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
return c.json(health);
|
|
16
|
+
});
|
|
17
|
+
return app;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/routes/health.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAa5B,MAAM,UAAU,YAAY;IAC3B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;QACxB,MAAM,MAAM,GAAiB;YAC5B,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,OAAO;YAChB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,QAAQ,EAAE;gBACT,MAAM,EAAE,SAAS;gBACjB,SAAS,EAAE,SAAS;gBACpB,KAAK,EAAE,SAAS;aAChB;SACD,CAAC;QAEF,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../src/routes/import.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAMlD,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,8EAkHjD"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { SourcePressError } from "../middleware/error-handler.js";
|
|
3
|
+
import { handleRouteError } from "../middleware/route-error-handler.js";
|
|
4
|
+
const MAX_BATCH_SIZE = 50;
|
|
5
|
+
export function importRoutes(engine) {
|
|
6
|
+
const app = new Hono();
|
|
7
|
+
app.onError(handleRouteError);
|
|
8
|
+
// POST /knowledge/import — scrape a single URL (synchronous)
|
|
9
|
+
app.post("/knowledge/import", async (c) => {
|
|
10
|
+
const body = await c.req.json();
|
|
11
|
+
if (!body.url) {
|
|
12
|
+
throw new SourcePressError(400, "INVALID_INPUT", "url is required");
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
const result = await engine.knowledge.importUrl(body.url);
|
|
16
|
+
return c.json({
|
|
17
|
+
imported: true,
|
|
18
|
+
path: result.path,
|
|
19
|
+
type: result.type,
|
|
20
|
+
quality: result.quality,
|
|
21
|
+
quality_score: result.quality_score,
|
|
22
|
+
entities: result.entities,
|
|
23
|
+
source_url: result.source_url,
|
|
24
|
+
}, 201);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
throw new SourcePressError(422, "IMPORT_FAILED", error instanceof Error ? error.message : "Failed to import URL");
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
// POST /knowledge/import/batch — import multiple URLs (async job)
|
|
31
|
+
app.post("/knowledge/import/batch", async (c) => {
|
|
32
|
+
if (!engine.jobs) {
|
|
33
|
+
throw new SourcePressError(501, "JOBS_NOT_CONFIGURED", "Job system not configured");
|
|
34
|
+
}
|
|
35
|
+
const body = await c.req.json();
|
|
36
|
+
if (!body.urls || !Array.isArray(body.urls) || body.urls.length === 0) {
|
|
37
|
+
throw new SourcePressError(400, "INVALID_INPUT", "urls array is required and must not be empty");
|
|
38
|
+
}
|
|
39
|
+
if (body.urls.length > MAX_BATCH_SIZE) {
|
|
40
|
+
throw new SourcePressError(400, "BATCH_TOO_LARGE", `Batch size ${body.urls.length} exceeds maximum of ${MAX_BATCH_SIZE}`);
|
|
41
|
+
}
|
|
42
|
+
const jobId = await engine.jobs.enqueue({
|
|
43
|
+
type: "import-batch",
|
|
44
|
+
params: { urls: body.urls },
|
|
45
|
+
});
|
|
46
|
+
const jobStatus = await engine.jobs.status(jobId);
|
|
47
|
+
return c.json(jobStatus, 202);
|
|
48
|
+
});
|
|
49
|
+
// POST /knowledge/import/sitemap — parse sitemap for interactive selection
|
|
50
|
+
app.post("/knowledge/import/sitemap", async (c) => {
|
|
51
|
+
const body = await c.req.json();
|
|
52
|
+
if (!body.url) {
|
|
53
|
+
throw new SourcePressError(400, "INVALID_INPUT", "url is required");
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const result = await engine.knowledge.parseSitemap(body.url);
|
|
57
|
+
return c.json(result);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
throw new SourcePressError(422, "SITEMAP_PARSE_FAILED", error instanceof Error ? error.message : "Failed to parse sitemap");
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
// POST /knowledge/import/sitemap/run — run sitemap import with filters (async job)
|
|
64
|
+
app.post("/knowledge/import/sitemap/run", async (c) => {
|
|
65
|
+
if (!engine.jobs) {
|
|
66
|
+
throw new SourcePressError(501, "JOBS_NOT_CONFIGURED", "Job system not configured");
|
|
67
|
+
}
|
|
68
|
+
const body = await c.req.json();
|
|
69
|
+
if (!body.sitemap_url) {
|
|
70
|
+
throw new SourcePressError(400, "INVALID_INPUT", "sitemap_url is required");
|
|
71
|
+
}
|
|
72
|
+
const jobId = await engine.jobs.enqueue({
|
|
73
|
+
type: "import-sitemap",
|
|
74
|
+
params: {
|
|
75
|
+
sitemap_url: body.sitemap_url,
|
|
76
|
+
include: body.include,
|
|
77
|
+
exclude: body.exclude,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
const jobStatus = await engine.jobs.status(jobId);
|
|
81
|
+
return c.json(jobStatus, 202);
|
|
82
|
+
});
|
|
83
|
+
return app;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import.js","sourceRoot":"","sources":["../../src/routes/import.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { approvalRoutes } from "./approval.js";
|
|
2
|
+
export { healthRoutes } from "./health.js";
|
|
3
|
+
export { contentRoutes } from "./content.js";
|
|
4
|
+
export { knowledgeRoutes } from "./knowledge.js";
|
|
5
|
+
export { graphRoutes } from "./graph.js";
|
|
6
|
+
export { schemaRoutes } from "./schema.js";
|
|
7
|
+
export { intentRoutes } from "./intent.js";
|
|
8
|
+
export { evalRoutes } from "./eval.js";
|
|
9
|
+
export { mediaRoutes } from "./media.js";
|
|
10
|
+
export { jobRoutes } from "./jobs.js";
|
|
11
|
+
export { importRoutes } from "./import.js";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/routes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { approvalRoutes } from "./approval.js";
|
|
2
|
+
export { healthRoutes } from "./health.js";
|
|
3
|
+
export { contentRoutes } from "./content.js";
|
|
4
|
+
export { knowledgeRoutes } from "./knowledge.js";
|
|
5
|
+
export { graphRoutes } from "./graph.js";
|
|
6
|
+
export { schemaRoutes } from "./schema.js";
|
|
7
|
+
export { intentRoutes } from "./intent.js";
|
|
8
|
+
export { evalRoutes } from "./eval.js";
|
|
9
|
+
export { mediaRoutes } from "./media.js";
|
|
10
|
+
export { jobRoutes } from "./jobs.js";
|
|
11
|
+
export { importRoutes } from "./import.js";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/routes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intent.d.ts","sourceRoot":"","sources":["../../src/routes/intent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAIlD,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,8EAmGjD"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { SourcePressError } from "../middleware/error-handler.js";
|
|
3
|
+
import { handleRouteError } from "../middleware/route-error-handler.js";
|
|
4
|
+
export function intentRoutes(engine) {
|
|
5
|
+
const app = new Hono();
|
|
6
|
+
// GET /intent — list intent files
|
|
7
|
+
app.get("/intent", async (c) => {
|
|
8
|
+
const intentPath = engine.config.intent.path;
|
|
9
|
+
const tree = await engine.github.getTree();
|
|
10
|
+
const intentFiles = tree
|
|
11
|
+
.filter((entry) => entry.path.startsWith(intentPath) && entry.type === "blob")
|
|
12
|
+
.map((entry) => ({
|
|
13
|
+
path: entry.path,
|
|
14
|
+
name: entry.path.replace(intentPath, "").replace(/\.(md|yaml|json)$/, ""),
|
|
15
|
+
}));
|
|
16
|
+
return c.json({ items: intentFiles, total: intentFiles.length });
|
|
17
|
+
});
|
|
18
|
+
// GET /intent/:name — get a single intent file
|
|
19
|
+
app.get("/intent/:name", async (c) => {
|
|
20
|
+
const name = c.req.param("name");
|
|
21
|
+
const intentPath = engine.config.intent.path;
|
|
22
|
+
const filePath = `${intentPath}${name}.md`;
|
|
23
|
+
const file = await engine.github.getFile(filePath);
|
|
24
|
+
if (!file) {
|
|
25
|
+
throw new SourcePressError(404, "INTENT_NOT_FOUND", `Intent "${name}" not found`);
|
|
26
|
+
}
|
|
27
|
+
return c.json({
|
|
28
|
+
name,
|
|
29
|
+
path: file.path,
|
|
30
|
+
content: file.content,
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
// PUT /intent/:name — update an intent file (direct commit, intent is human-owned)
|
|
34
|
+
app.put("/intent/:name", async (c) => {
|
|
35
|
+
const name = c.req.param("name");
|
|
36
|
+
const intentPath = engine.config.intent.path;
|
|
37
|
+
const filePath = `${intentPath}${name}.md`;
|
|
38
|
+
const body = await c.req.json();
|
|
39
|
+
if (!body.content) {
|
|
40
|
+
throw new SourcePressError(400, "INVALID_INPUT", "content is required");
|
|
41
|
+
}
|
|
42
|
+
// Check if file exists to get SHA
|
|
43
|
+
const existing = await engine.github.getFile(filePath);
|
|
44
|
+
const existingSha = existing?.sha;
|
|
45
|
+
const result = await engine.github.createOrUpdateFile(filePath, body.content, `update(intent): update ${name}`, undefined, existingSha);
|
|
46
|
+
return c.json({
|
|
47
|
+
updated: true,
|
|
48
|
+
path: filePath,
|
|
49
|
+
commit_sha: result.commit_sha,
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
// GET /intent/:name/impact — analyze which content is affected by this intent
|
|
53
|
+
app.get("/intent/:name/impact", async (c) => {
|
|
54
|
+
const name = c.req.param("name");
|
|
55
|
+
const intentPath = engine.config.intent.path;
|
|
56
|
+
const filePath = `${intentPath}${name}.md`;
|
|
57
|
+
const file = await engine.github.getFile(filePath);
|
|
58
|
+
if (!file) {
|
|
59
|
+
throw new SourcePressError(404, "INTENT_NOT_FOUND", `Intent "${name}" not found`);
|
|
60
|
+
}
|
|
61
|
+
// Collect all content
|
|
62
|
+
const collections = engine.listCollections();
|
|
63
|
+
const allContent = [];
|
|
64
|
+
for (const coll of collections) {
|
|
65
|
+
const files = await engine.listContent(coll);
|
|
66
|
+
allContent.push(...files);
|
|
67
|
+
}
|
|
68
|
+
// Return content count — full AI-based impact analysis requires
|
|
69
|
+
// the previous version of intent, which we defer to a future enhancement
|
|
70
|
+
return c.json({
|
|
71
|
+
intent: name,
|
|
72
|
+
content_count: allContent.length,
|
|
73
|
+
message: "Full AI-based intent impact analysis requires previous intent version. Use POST /api/intent/:name/impact with previous_content field for detailed analysis.",
|
|
74
|
+
content_paths: allContent.map((f) => f.path),
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
app.onError(handleRouteError);
|
|
78
|
+
return app;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=intent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intent.js","sourceRoot":"","sources":["../../src/routes/intent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jobs.d.ts","sourceRoot":"","sources":["../../src/routes/jobs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAIlD,wBAAgB,SAAS,CAAC,MAAM,EAAE,aAAa,8EA8E9C"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { SourcePressError } from "../middleware/error-handler.js";
|
|
3
|
+
import { handleRouteError } from "../middleware/route-error-handler.js";
|
|
4
|
+
export function jobRoutes(engine) {
|
|
5
|
+
const app = new Hono();
|
|
6
|
+
// GET /jobs — list all jobs
|
|
7
|
+
app.get("/jobs", async (c) => {
|
|
8
|
+
if (!engine.jobs) {
|
|
9
|
+
throw new SourcePressError(501, "JOBS_NOT_CONFIGURED", "Job system not configured");
|
|
10
|
+
}
|
|
11
|
+
const status = c.req.query("status");
|
|
12
|
+
const type = c.req.query("type");
|
|
13
|
+
const limitStr = c.req.query("limit");
|
|
14
|
+
const limit = limitStr ? Number.parseInt(limitStr, 10) : undefined;
|
|
15
|
+
const jobs = await engine.jobs.list({ status, type, limit });
|
|
16
|
+
return c.json({ items: jobs, total: jobs.length });
|
|
17
|
+
});
|
|
18
|
+
// GET /jobs/:id — get job status
|
|
19
|
+
app.get("/jobs/:id", async (c) => {
|
|
20
|
+
if (!engine.jobs) {
|
|
21
|
+
throw new SourcePressError(501, "JOBS_NOT_CONFIGURED", "Job system not configured");
|
|
22
|
+
}
|
|
23
|
+
const id = c.req.param("id");
|
|
24
|
+
const job = await engine.jobs.status(id);
|
|
25
|
+
if (!job) {
|
|
26
|
+
throw new SourcePressError(404, "JOB_NOT_FOUND", `Job "${id}" not found`);
|
|
27
|
+
}
|
|
28
|
+
return c.json(job);
|
|
29
|
+
});
|
|
30
|
+
// POST /jobs — start a new job
|
|
31
|
+
app.post("/jobs", async (c) => {
|
|
32
|
+
if (!engine.jobs) {
|
|
33
|
+
throw new SourcePressError(501, "JOBS_NOT_CONFIGURED", "Job system not configured");
|
|
34
|
+
}
|
|
35
|
+
const body = await c.req.json();
|
|
36
|
+
if (!body.type) {
|
|
37
|
+
throw new SourcePressError(400, "INVALID_INPUT", "type is required");
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const jobId = await engine.jobs.enqueue({ type: body.type, params: body.params ?? {} });
|
|
41
|
+
const jobStatus = await engine.jobs.status(jobId);
|
|
42
|
+
return c.json(jobStatus, 201);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
if (error instanceof Error && error.message.includes("No handler registered")) {
|
|
46
|
+
throw new SourcePressError(400, "UNKNOWN_JOB_TYPE", error.message);
|
|
47
|
+
}
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
// DELETE /jobs/:id — cancel a job
|
|
52
|
+
app.delete("/jobs/:id", async (c) => {
|
|
53
|
+
if (!engine.jobs) {
|
|
54
|
+
throw new SourcePressError(501, "JOBS_NOT_CONFIGURED", "Job system not configured");
|
|
55
|
+
}
|
|
56
|
+
const id = c.req.param("id");
|
|
57
|
+
const existing = await engine.jobs.status(id);
|
|
58
|
+
if (!existing) {
|
|
59
|
+
throw new SourcePressError(404, "JOB_NOT_FOUND", `Job "${id}" not found or already completed`);
|
|
60
|
+
}
|
|
61
|
+
await engine.jobs.cancel(id);
|
|
62
|
+
return c.json({ cancelled: true, id });
|
|
63
|
+
});
|
|
64
|
+
app.onError(handleRouteError);
|
|
65
|
+
return app;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=jobs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../src/routes/jobs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"knowledge.d.ts","sourceRoot":"","sources":["../../src/routes/knowledge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAIlD,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,8EAmEpD"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { SourcePressError } from "../middleware/error-handler.js";
|
|
3
|
+
import { handleRouteError } from "../middleware/route-error-handler.js";
|
|
4
|
+
export function knowledgeRoutes(engine) {
|
|
5
|
+
const app = new Hono();
|
|
6
|
+
app.onError(handleRouteError);
|
|
7
|
+
// GET /knowledge — list knowledge files
|
|
8
|
+
app.get("/knowledge", async (c) => {
|
|
9
|
+
const files = await engine.knowledgeStore.list();
|
|
10
|
+
const items = files.map((f) => ({
|
|
11
|
+
path: f.path,
|
|
12
|
+
type: f.type,
|
|
13
|
+
quality: f.quality,
|
|
14
|
+
quality_score: f.quality_score,
|
|
15
|
+
entities: f.entities,
|
|
16
|
+
ingested_at: f.ingested_at,
|
|
17
|
+
source: f.source,
|
|
18
|
+
}));
|
|
19
|
+
return c.json({ items, total: items.length });
|
|
20
|
+
});
|
|
21
|
+
// GET /knowledge/:path — get a single knowledge file (path is URL-encoded)
|
|
22
|
+
app.get("/knowledge/:path{.+}", async (c) => {
|
|
23
|
+
const path = c.req.param("path");
|
|
24
|
+
const file = await engine.knowledgeStore.retrieve(path);
|
|
25
|
+
if (!file) {
|
|
26
|
+
throw new SourcePressError(404, "KNOWLEDGE_NOT_FOUND", `Knowledge file "${path}" not found`);
|
|
27
|
+
}
|
|
28
|
+
return c.json(file);
|
|
29
|
+
});
|
|
30
|
+
// POST /knowledge — ingest new knowledge (classify + store)
|
|
31
|
+
app.post("/knowledge", async (c) => {
|
|
32
|
+
const body = await c.req.json();
|
|
33
|
+
if (!body.path || !body.body) {
|
|
34
|
+
throw new SourcePressError(400, "INVALID_INPUT", "path and body are required");
|
|
35
|
+
}
|
|
36
|
+
const knowledgeFile = await engine.knowledge.ingest(body.path, body.body, body.source ?? "manual", body.source_url);
|
|
37
|
+
return c.json({
|
|
38
|
+
ingested: true,
|
|
39
|
+
path: knowledgeFile.path,
|
|
40
|
+
type: knowledgeFile.type,
|
|
41
|
+
quality: knowledgeFile.quality,
|
|
42
|
+
quality_score: knowledgeFile.quality_score,
|
|
43
|
+
entities: knowledgeFile.entities,
|
|
44
|
+
}, 201);
|
|
45
|
+
});
|
|
46
|
+
return app;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=knowledge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"knowledge.js","sourceRoot":"","sources":["../../src/routes/knowledge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAExE,MAAM,UAAU,eAAe,CAAC,MAAqB;IACpD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAE9B,wCAAwC;IACxC,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACjC,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QACjD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC/B,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,aAAa,EAAE,CAAC,CAAC,aAAa;YAC9B,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,MAAM,EAAE,CAAC,CAAC,MAAM;SAChB,CAAC,CAAC,CAAC;QAEJ,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,2EAA2E;IAC3E,GAAG,CAAC,GAAG,CAAC,sBAAsB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC3C,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAExD,IAAI,CAAC,IAAI,EAAE,CAAC;YACX,MAAM,IAAI,gBAAgB,CAAC,GAAG,EAAE,qBAAqB,EAAE,mBAAmB,IAAI,aAAa,CAAC,CAAC;QAC9F,CAAC;QAED,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,4DAA4D;IAC5D,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,EAKzB,CAAC;QAEL,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,gBAAgB,CAAC,GAAG,EAAE,eAAe,EAAE,4BAA4B,CAAC,CAAC;QAChF,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,CAClD,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,MAAM,IAAI,QAAQ,EACvB,IAAI,CAAC,UAAU,CACf,CAAC;QAEF,OAAO,CAAC,CAAC,IAAI,CACZ;YACC,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE,aAAa,CAAC,IAAI;YACxB,IAAI,EAAE,aAAa,CAAC,IAAI;YACxB,OAAO,EAAE,aAAa,CAAC,OAAO;YAC9B,aAAa,EAAE,aAAa,CAAC,aAAa;YAC1C,QAAQ,EAAE,aAAa,CAAC,QAAQ;SAChC,EACD,GAAG,CACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../src/routes/media.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAIlD,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,8EA+GhD"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { SourcePressError } from "../middleware/error-handler.js";
|
|
3
|
+
import { handleRouteError } from "../middleware/route-error-handler.js";
|
|
4
|
+
export function mediaRoutes(engine) {
|
|
5
|
+
const app = new Hono();
|
|
6
|
+
app.onError(handleRouteError);
|
|
7
|
+
// GET /media — list all media with metadata
|
|
8
|
+
app.get("/media", async (c) => {
|
|
9
|
+
if (!engine.media) {
|
|
10
|
+
throw new SourcePressError(501, "MEDIA_NOT_CONFIGURED", "Media storage not configured");
|
|
11
|
+
}
|
|
12
|
+
const prefix = c.req.query("prefix");
|
|
13
|
+
const items = await engine.media.list(prefix ?? undefined);
|
|
14
|
+
return c.json({ items, total: items.length });
|
|
15
|
+
});
|
|
16
|
+
// POST /media/upload — upload a media file (multipart form)
|
|
17
|
+
app.post("/media/upload", async (c) => {
|
|
18
|
+
if (!engine.media) {
|
|
19
|
+
throw new SourcePressError(501, "MEDIA_NOT_CONFIGURED", "Media storage not configured");
|
|
20
|
+
}
|
|
21
|
+
const formData = await c.req.formData();
|
|
22
|
+
const file = formData.get("file");
|
|
23
|
+
const path = formData.get("path");
|
|
24
|
+
const source = formData.get("source");
|
|
25
|
+
if (!file || !(file instanceof File)) {
|
|
26
|
+
throw new SourcePressError(400, "INVALID_INPUT", "Missing file in form data");
|
|
27
|
+
}
|
|
28
|
+
if (!path || typeof path !== "string") {
|
|
29
|
+
throw new SourcePressError(400, "INVALID_INPUT", "Missing path in form data");
|
|
30
|
+
}
|
|
31
|
+
if (!source || typeof source !== "string") {
|
|
32
|
+
throw new SourcePressError(400, "INVALID_INPUT", "Missing source in form data");
|
|
33
|
+
}
|
|
34
|
+
const validSources = ["uploaded", "ai-generated", "scraped", "stock"];
|
|
35
|
+
if (!validSources.includes(source)) {
|
|
36
|
+
throw new SourcePressError(400, "INVALID_INPUT", `Invalid source. Must be one of: ${validSources.join(", ")}`);
|
|
37
|
+
}
|
|
38
|
+
const buffer = Buffer.from(await file.arrayBuffer());
|
|
39
|
+
const alt = formData.get("alt");
|
|
40
|
+
const generatedBy = formData.get("generated_by");
|
|
41
|
+
const prompt = formData.get("prompt");
|
|
42
|
+
const ref = await engine.media.upload({
|
|
43
|
+
file: buffer,
|
|
44
|
+
path,
|
|
45
|
+
content_type: file.type,
|
|
46
|
+
source: source,
|
|
47
|
+
alt: typeof alt === "string" ? alt : undefined,
|
|
48
|
+
generated_by: typeof generatedBy === "string" ? generatedBy : undefined,
|
|
49
|
+
prompt: typeof prompt === "string" ? prompt : undefined,
|
|
50
|
+
uploaded_by: "api", // TODO: use auth context when available
|
|
51
|
+
});
|
|
52
|
+
return c.json(ref, 201);
|
|
53
|
+
});
|
|
54
|
+
// GET /media/:path — get metadata for a specific file
|
|
55
|
+
app.get("/media/:path{.+}", async (c) => {
|
|
56
|
+
if (!engine.media) {
|
|
57
|
+
throw new SourcePressError(501, "MEDIA_NOT_CONFIGURED", "Media storage not configured");
|
|
58
|
+
}
|
|
59
|
+
const path = c.req.param("path");
|
|
60
|
+
const meta = await engine.media.getMeta(path);
|
|
61
|
+
if (!meta) {
|
|
62
|
+
throw new SourcePressError(404, "MEDIA_NOT_FOUND", `Media not found: ${path}`);
|
|
63
|
+
}
|
|
64
|
+
return c.json(meta);
|
|
65
|
+
});
|
|
66
|
+
// PUT /media/:path — update metadata for a media file
|
|
67
|
+
app.put("/media/:path{.+}", async (c) => {
|
|
68
|
+
if (!engine.media) {
|
|
69
|
+
throw new SourcePressError(501, "MEDIA_NOT_CONFIGURED", "Media storage not configured");
|
|
70
|
+
}
|
|
71
|
+
const path = c.req.param("path");
|
|
72
|
+
const body = await c.req.json();
|
|
73
|
+
const updated = await engine.media.updateMeta(path, body);
|
|
74
|
+
return c.json(updated);
|
|
75
|
+
});
|
|
76
|
+
// DELETE /media/:path — delete a media file
|
|
77
|
+
app.delete("/media/:path{.+}", async (c) => {
|
|
78
|
+
if (!engine.media) {
|
|
79
|
+
throw new SourcePressError(501, "MEDIA_NOT_CONFIGURED", "Media storage not configured");
|
|
80
|
+
}
|
|
81
|
+
const path = c.req.param("path");
|
|
82
|
+
await engine.media.delete(path);
|
|
83
|
+
return c.json({ deleted: true, path });
|
|
84
|
+
});
|
|
85
|
+
return app;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=media.js.map
|