@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.
Files changed (184) hide show
  1. package/.omc/state/agent-replay-31d84b63-606a-4368-b9e6-93fe4f5ae0f7.jsonl +2 -0
  2. package/.omc/state/last-tool-error.json +7 -0
  3. package/.omc/state/mission-state.json +53 -0
  4. package/.omc/state/subagent-tracking.json +17 -0
  5. package/.turbo/turbo-build.log +4 -0
  6. package/.turbo/turbo-test.log +26 -0
  7. package/dist/__tests__/app-integration.test.d.ts +2 -0
  8. package/dist/__tests__/app-integration.test.d.ts.map +1 -0
  9. package/dist/__tests__/app-integration.test.js +71 -0
  10. package/dist/__tests__/app-integration.test.js.map +1 -0
  11. package/dist/__tests__/approval.test.d.ts +2 -0
  12. package/dist/__tests__/approval.test.d.ts.map +1 -0
  13. package/dist/__tests__/approval.test.js +170 -0
  14. package/dist/__tests__/approval.test.js.map +1 -0
  15. package/dist/__tests__/content.test.d.ts +2 -0
  16. package/dist/__tests__/content.test.d.ts.map +1 -0
  17. package/dist/__tests__/content.test.js +187 -0
  18. package/dist/__tests__/content.test.js.map +1 -0
  19. package/dist/__tests__/engine.test.d.ts +2 -0
  20. package/dist/__tests__/engine.test.d.ts.map +1 -0
  21. package/dist/__tests__/engine.test.js +77 -0
  22. package/dist/__tests__/engine.test.js.map +1 -0
  23. package/dist/__tests__/eval.test.d.ts +2 -0
  24. package/dist/__tests__/eval.test.d.ts.map +1 -0
  25. package/dist/__tests__/eval.test.js +320 -0
  26. package/dist/__tests__/eval.test.js.map +1 -0
  27. package/dist/__tests__/graph.test.d.ts +2 -0
  28. package/dist/__tests__/graph.test.d.ts.map +1 -0
  29. package/dist/__tests__/graph.test.js +169 -0
  30. package/dist/__tests__/graph.test.js.map +1 -0
  31. package/dist/__tests__/health.test.d.ts +2 -0
  32. package/dist/__tests__/health.test.d.ts.map +1 -0
  33. package/dist/__tests__/health.test.js +56 -0
  34. package/dist/__tests__/health.test.js.map +1 -0
  35. package/dist/__tests__/import.test.d.ts +2 -0
  36. package/dist/__tests__/import.test.d.ts.map +1 -0
  37. package/dist/__tests__/import.test.js +138 -0
  38. package/dist/__tests__/import.test.js.map +1 -0
  39. package/dist/__tests__/intent.test.d.ts +2 -0
  40. package/dist/__tests__/intent.test.d.ts.map +1 -0
  41. package/dist/__tests__/intent.test.js +122 -0
  42. package/dist/__tests__/intent.test.js.map +1 -0
  43. package/dist/__tests__/jobs.test.d.ts +2 -0
  44. package/dist/__tests__/jobs.test.d.ts.map +1 -0
  45. package/dist/__tests__/jobs.test.js +96 -0
  46. package/dist/__tests__/jobs.test.js.map +1 -0
  47. package/dist/__tests__/knowledge.test.d.ts +2 -0
  48. package/dist/__tests__/knowledge.test.d.ts.map +1 -0
  49. package/dist/__tests__/knowledge.test.js +110 -0
  50. package/dist/__tests__/knowledge.test.js.map +1 -0
  51. package/dist/__tests__/media-routes.test.d.ts +2 -0
  52. package/dist/__tests__/media-routes.test.d.ts.map +1 -0
  53. package/dist/__tests__/media-routes.test.js +88 -0
  54. package/dist/__tests__/media-routes.test.js.map +1 -0
  55. package/dist/__tests__/schema.test.d.ts +2 -0
  56. package/dist/__tests__/schema.test.d.ts.map +1 -0
  57. package/dist/__tests__/schema.test.js +92 -0
  58. package/dist/__tests__/schema.test.js.map +1 -0
  59. package/dist/app.d.ts +7 -0
  60. package/dist/app.d.ts.map +1 -0
  61. package/dist/app.js +85 -0
  62. package/dist/app.js.map +1 -0
  63. package/dist/engine.d.ts +38 -0
  64. package/dist/engine.d.ts.map +1 -0
  65. package/dist/engine.js +106 -0
  66. package/dist/engine.js.map +1 -0
  67. package/dist/index.d.ts +8 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +9 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/middleware/auth.d.ts +17 -0
  72. package/dist/middleware/auth.d.ts.map +1 -0
  73. package/dist/middleware/auth.js +54 -0
  74. package/dist/middleware/auth.js.map +1 -0
  75. package/dist/middleware/cors.d.ts +2 -0
  76. package/dist/middleware/cors.d.ts.map +1 -0
  77. package/dist/middleware/cors.js +13 -0
  78. package/dist/middleware/cors.js.map +1 -0
  79. package/dist/middleware/error-handler.d.ts +24 -0
  80. package/dist/middleware/error-handler.d.ts.map +1 -0
  81. package/dist/middleware/error-handler.js +30 -0
  82. package/dist/middleware/error-handler.js.map +1 -0
  83. package/dist/middleware/index.d.ts +7 -0
  84. package/dist/middleware/index.d.ts.map +1 -0
  85. package/dist/middleware/index.js +5 -0
  86. package/dist/middleware/index.js.map +1 -0
  87. package/dist/middleware/rate-limit.d.ts +11 -0
  88. package/dist/middleware/rate-limit.d.ts.map +1 -0
  89. package/dist/middleware/rate-limit.js +26 -0
  90. package/dist/middleware/rate-limit.js.map +1 -0
  91. package/dist/middleware/route-error-handler.d.ts +12 -0
  92. package/dist/middleware/route-error-handler.d.ts.map +1 -0
  93. package/dist/middleware/route-error-handler.js +9 -0
  94. package/dist/middleware/route-error-handler.js.map +1 -0
  95. package/dist/routes/approval.d.ts +4 -0
  96. package/dist/routes/approval.d.ts.map +1 -0
  97. package/dist/routes/approval.js +70 -0
  98. package/dist/routes/approval.js.map +1 -0
  99. package/dist/routes/content.d.ts +4 -0
  100. package/dist/routes/content.d.ts.map +1 -0
  101. package/dist/routes/content.js +145 -0
  102. package/dist/routes/content.js.map +1 -0
  103. package/dist/routes/eval.d.ts +4 -0
  104. package/dist/routes/eval.d.ts.map +1 -0
  105. package/dist/routes/eval.js +178 -0
  106. package/dist/routes/eval.js.map +1 -0
  107. package/dist/routes/graph.d.ts +4 -0
  108. package/dist/routes/graph.d.ts.map +1 -0
  109. package/dist/routes/graph.js +90 -0
  110. package/dist/routes/graph.js.map +1 -0
  111. package/dist/routes/health.d.ts +13 -0
  112. package/dist/routes/health.d.ts.map +1 -0
  113. package/dist/routes/health.js +19 -0
  114. package/dist/routes/health.js.map +1 -0
  115. package/dist/routes/import.d.ts +4 -0
  116. package/dist/routes/import.d.ts.map +1 -0
  117. package/dist/routes/import.js +85 -0
  118. package/dist/routes/import.js.map +1 -0
  119. package/dist/routes/index.d.ts +12 -0
  120. package/dist/routes/index.d.ts.map +1 -0
  121. package/dist/routes/index.js +12 -0
  122. package/dist/routes/index.js.map +1 -0
  123. package/dist/routes/intent.d.ts +4 -0
  124. package/dist/routes/intent.d.ts.map +1 -0
  125. package/dist/routes/intent.js +80 -0
  126. package/dist/routes/intent.js.map +1 -0
  127. package/dist/routes/jobs.d.ts +4 -0
  128. package/dist/routes/jobs.d.ts.map +1 -0
  129. package/dist/routes/jobs.js +67 -0
  130. package/dist/routes/jobs.js.map +1 -0
  131. package/dist/routes/knowledge.d.ts +4 -0
  132. package/dist/routes/knowledge.d.ts.map +1 -0
  133. package/dist/routes/knowledge.js +48 -0
  134. package/dist/routes/knowledge.js.map +1 -0
  135. package/dist/routes/media.d.ts +4 -0
  136. package/dist/routes/media.d.ts.map +1 -0
  137. package/dist/routes/media.js +87 -0
  138. package/dist/routes/media.js.map +1 -0
  139. package/dist/routes/schema.d.ts +4 -0
  140. package/dist/routes/schema.d.ts.map +1 -0
  141. package/dist/routes/schema.js +54 -0
  142. package/dist/routes/schema.js.map +1 -0
  143. package/dist/standalone.d.ts +2 -0
  144. package/dist/standalone.d.ts.map +1 -0
  145. package/dist/standalone.js +115 -0
  146. package/dist/standalone.js.map +1 -0
  147. package/package.json +36 -0
  148. package/src/__tests__/app-integration.test.ts +80 -0
  149. package/src/__tests__/approval.test.ts +195 -0
  150. package/src/__tests__/content.test.ts +202 -0
  151. package/src/__tests__/engine.test.ts +86 -0
  152. package/src/__tests__/eval.test.ts +343 -0
  153. package/src/__tests__/graph.test.ts +182 -0
  154. package/src/__tests__/health.test.ts +68 -0
  155. package/src/__tests__/import.test.ts +148 -0
  156. package/src/__tests__/intent.test.ts +133 -0
  157. package/src/__tests__/jobs.test.ts +107 -0
  158. package/src/__tests__/knowledge.test.ts +121 -0
  159. package/src/__tests__/media-routes.test.ts +109 -0
  160. package/src/__tests__/schema.test.ts +100 -0
  161. package/src/app.ts +92 -0
  162. package/src/engine.ts +168 -0
  163. package/src/index.ts +31 -0
  164. package/src/middleware/auth.ts +66 -0
  165. package/src/middleware/cors.ts +15 -0
  166. package/src/middleware/error-handler.ts +42 -0
  167. package/src/middleware/index.ts +6 -0
  168. package/src/middleware/rate-limit.ts +27 -0
  169. package/src/middleware/route-error-handler.ts +13 -0
  170. package/src/routes/approval.ts +90 -0
  171. package/src/routes/content.ts +256 -0
  172. package/src/routes/eval.ts +262 -0
  173. package/src/routes/graph.ts +111 -0
  174. package/src/routes/health.ts +33 -0
  175. package/src/routes/import.ts +122 -0
  176. package/src/routes/index.ts +11 -0
  177. package/src/routes/intent.ts +105 -0
  178. package/src/routes/jobs.ts +84 -0
  179. package/src/routes/knowledge.ts +73 -0
  180. package/src/routes/media.ts +117 -0
  181. package/src/routes/schema.ts +75 -0
  182. package/src/standalone.ts +130 -0
  183. package/tsconfig.json +8 -0
  184. 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,4 @@
1
+ import { Hono } from "hono";
2
+ import type { EngineContext } from "../engine.js";
3
+ export declare function importRoutes(engine: EngineContext): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
4
+ //# sourceMappingURL=import.d.ts.map
@@ -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,4 @@
1
+ import { Hono } from "hono";
2
+ import type { EngineContext } from "../engine.js";
3
+ export declare function intentRoutes(engine: EngineContext): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
4
+ //# sourceMappingURL=intent.d.ts.map
@@ -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,4 @@
1
+ import { Hono } from "hono";
2
+ import type { EngineContext } from "../engine.js";
3
+ export declare function jobRoutes(engine: EngineContext): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
4
+ //# sourceMappingURL=jobs.d.ts.map
@@ -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,4 @@
1
+ import { Hono } from "hono";
2
+ import type { EngineContext } from "../engine.js";
3
+ export declare function knowledgeRoutes(engine: EngineContext): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
4
+ //# sourceMappingURL=knowledge.d.ts.map
@@ -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,4 @@
1
+ import { Hono } from "hono";
2
+ import type { EngineContext } from "../engine.js";
3
+ export declare function mediaRoutes(engine: EngineContext): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
4
+ //# sourceMappingURL=media.d.ts.map
@@ -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