@amodalai/runtime 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 (277) hide show
  1. package/LICENSE +21 -0
  2. package/dist/.last_build +0 -0
  3. package/dist/src/agent/agent-runner.d.ts +13 -0
  4. package/dist/src/agent/agent-runner.js +827 -0
  5. package/dist/src/agent/agent-runner.js.map +1 -0
  6. package/dist/src/agent/agent-runner.test.d.ts +6 -0
  7. package/dist/src/agent/agent-runner.test.js +552 -0
  8. package/dist/src/agent/agent-runner.test.js.map +1 -0
  9. package/dist/src/agent/agent-types.d.ts +57 -0
  10. package/dist/src/agent/agent-types.js +17 -0
  11. package/dist/src/agent/agent-types.js.map +1 -0
  12. package/dist/src/agent/agent-types.test.d.ts +6 -0
  13. package/dist/src/agent/agent-types.test.js +44 -0
  14. package/dist/src/agent/agent-types.test.js.map +1 -0
  15. package/dist/src/agent/automation-bridge.d.ts +24 -0
  16. package/dist/src/agent/automation-bridge.js +24 -0
  17. package/dist/src/agent/automation-bridge.js.map +1 -0
  18. package/dist/src/agent/automation-bridge.test.d.ts +6 -0
  19. package/dist/src/agent/automation-bridge.test.js +67 -0
  20. package/dist/src/agent/automation-bridge.test.js.map +1 -0
  21. package/dist/src/agent/config-watcher.d.ts +20 -0
  22. package/dist/src/agent/config-watcher.js +68 -0
  23. package/dist/src/agent/config-watcher.js.map +1 -0
  24. package/dist/src/agent/config-watcher.test.d.ts +6 -0
  25. package/dist/src/agent/config-watcher.test.js +83 -0
  26. package/dist/src/agent/config-watcher.test.js.map +1 -0
  27. package/dist/src/agent/custom-tools-e2e.test.d.ts +6 -0
  28. package/dist/src/agent/custom-tools-e2e.test.js +566 -0
  29. package/dist/src/agent/custom-tools-e2e.test.js.map +1 -0
  30. package/dist/src/agent/local-server.d.ts +15 -0
  31. package/dist/src/agent/local-server.js +158 -0
  32. package/dist/src/agent/local-server.js.map +1 -0
  33. package/dist/src/agent/local-server.test.d.ts +6 -0
  34. package/dist/src/agent/local-server.test.js +126 -0
  35. package/dist/src/agent/local-server.test.js.map +1 -0
  36. package/dist/src/agent/proactive/delivery.d.ts +21 -0
  37. package/dist/src/agent/proactive/delivery.js +68 -0
  38. package/dist/src/agent/proactive/delivery.js.map +1 -0
  39. package/dist/src/agent/proactive/delivery.test.d.ts +6 -0
  40. package/dist/src/agent/proactive/delivery.test.js +65 -0
  41. package/dist/src/agent/proactive/delivery.test.js.map +1 -0
  42. package/dist/src/agent/proactive/proactive-runner.d.ts +76 -0
  43. package/dist/src/agent/proactive/proactive-runner.js +201 -0
  44. package/dist/src/agent/proactive/proactive-runner.js.map +1 -0
  45. package/dist/src/agent/proactive/proactive-runner.test.d.ts +6 -0
  46. package/dist/src/agent/proactive/proactive-runner.test.js +265 -0
  47. package/dist/src/agent/proactive/proactive-runner.test.js.map +1 -0
  48. package/dist/src/agent/request-helper.d.ts +16 -0
  49. package/dist/src/agent/request-helper.js +87 -0
  50. package/dist/src/agent/request-helper.js.map +1 -0
  51. package/dist/src/agent/routes/automations.d.ts +19 -0
  52. package/dist/src/agent/routes/automations.js +58 -0
  53. package/dist/src/agent/routes/automations.js.map +1 -0
  54. package/dist/src/agent/routes/automations.test.d.ts +6 -0
  55. package/dist/src/agent/routes/automations.test.js +117 -0
  56. package/dist/src/agent/routes/automations.test.js.map +1 -0
  57. package/dist/src/agent/routes/chat.d.ts +35 -0
  58. package/dist/src/agent/routes/chat.js +88 -0
  59. package/dist/src/agent/routes/chat.js.map +1 -0
  60. package/dist/src/agent/routes/chat.test.d.ts +6 -0
  61. package/dist/src/agent/routes/chat.test.js +115 -0
  62. package/dist/src/agent/routes/chat.test.js.map +1 -0
  63. package/dist/src/agent/routes/inspect.d.ts +12 -0
  64. package/dist/src/agent/routes/inspect.js +40 -0
  65. package/dist/src/agent/routes/inspect.js.map +1 -0
  66. package/dist/src/agent/routes/inspect.test.d.ts +6 -0
  67. package/dist/src/agent/routes/inspect.test.js +80 -0
  68. package/dist/src/agent/routes/inspect.test.js.map +1 -0
  69. package/dist/src/agent/routes/stores.d.ts +20 -0
  70. package/dist/src/agent/routes/stores.js +137 -0
  71. package/dist/src/agent/routes/stores.js.map +1 -0
  72. package/dist/src/agent/routes/stores.test.d.ts +6 -0
  73. package/dist/src/agent/routes/stores.test.js +191 -0
  74. package/dist/src/agent/routes/stores.test.js.map +1 -0
  75. package/dist/src/agent/routes/task.d.ts +11 -0
  76. package/dist/src/agent/routes/task.js +116 -0
  77. package/dist/src/agent/routes/task.js.map +1 -0
  78. package/dist/src/agent/routes/task.test.d.ts +6 -0
  79. package/dist/src/agent/routes/task.test.js +91 -0
  80. package/dist/src/agent/routes/task.test.js.map +1 -0
  81. package/dist/src/agent/routes/webhooks.d.ts +17 -0
  82. package/dist/src/agent/routes/webhooks.js +53 -0
  83. package/dist/src/agent/routes/webhooks.js.map +1 -0
  84. package/dist/src/agent/routes/webhooks.test.d.ts +6 -0
  85. package/dist/src/agent/routes/webhooks.test.js +100 -0
  86. package/dist/src/agent/routes/webhooks.test.js.map +1 -0
  87. package/dist/src/agent/session-manager.d.ts +72 -0
  88. package/dist/src/agent/session-manager.js +214 -0
  89. package/dist/src/agent/session-manager.js.map +1 -0
  90. package/dist/src/agent/session-manager.test.d.ts +6 -0
  91. package/dist/src/agent/session-manager.test.js +145 -0
  92. package/dist/src/agent/session-manager.test.js.map +1 -0
  93. package/dist/src/agent/shell-executor-local.d.ts +16 -0
  94. package/dist/src/agent/shell-executor-local.js +51 -0
  95. package/dist/src/agent/shell-executor-local.js.map +1 -0
  96. package/dist/src/agent/shell-executor-local.test.d.ts +6 -0
  97. package/dist/src/agent/shell-executor-local.test.js +46 -0
  98. package/dist/src/agent/shell-executor-local.test.js.map +1 -0
  99. package/dist/src/agent/snapshot-server.d.ts +38 -0
  100. package/dist/src/agent/snapshot-server.js +114 -0
  101. package/dist/src/agent/snapshot-server.js.map +1 -0
  102. package/dist/src/agent/stores-e2e.test.d.ts +6 -0
  103. package/dist/src/agent/stores-e2e.test.js +433 -0
  104. package/dist/src/agent/stores-e2e.test.js.map +1 -0
  105. package/dist/src/agent/tool-context-builder.d.ts +11 -0
  106. package/dist/src/agent/tool-context-builder.js +84 -0
  107. package/dist/src/agent/tool-context-builder.js.map +1 -0
  108. package/dist/src/agent/tool-context-builder.test.d.ts +6 -0
  109. package/dist/src/agent/tool-context-builder.test.js +152 -0
  110. package/dist/src/agent/tool-context-builder.test.js.map +1 -0
  111. package/dist/src/agent/tool-executor-local.d.ts +15 -0
  112. package/dist/src/agent/tool-executor-local.js +74 -0
  113. package/dist/src/agent/tool-executor-local.js.map +1 -0
  114. package/dist/src/agent/tool-executor-local.test.d.ts +6 -0
  115. package/dist/src/agent/tool-executor-local.test.js +116 -0
  116. package/dist/src/agent/tool-executor-local.test.js.map +1 -0
  117. package/dist/src/agent/tool-harness-template.d.ts +23 -0
  118. package/dist/src/agent/tool-harness-template.js +94 -0
  119. package/dist/src/agent/tool-harness-template.js.map +1 -0
  120. package/dist/src/agent/user-context-fetcher.d.ts +25 -0
  121. package/dist/src/agent/user-context-fetcher.js +79 -0
  122. package/dist/src/agent/user-context-fetcher.js.map +1 -0
  123. package/dist/src/agent/user-context-fetcher.test.d.ts +6 -0
  124. package/dist/src/agent/user-context-fetcher.test.js +121 -0
  125. package/dist/src/agent/user-context-fetcher.test.js.map +1 -0
  126. package/dist/src/audit/audit-client.d.ts +46 -0
  127. package/dist/src/audit/audit-client.js +83 -0
  128. package/dist/src/audit/audit-client.js.map +1 -0
  129. package/dist/src/cron/heartbeat-runner.d.ts +24 -0
  130. package/dist/src/cron/heartbeat-runner.js +87 -0
  131. package/dist/src/cron/heartbeat-runner.js.map +1 -0
  132. package/dist/src/cron/heartbeat-runner.test.d.ts +6 -0
  133. package/dist/src/cron/heartbeat-runner.test.js +120 -0
  134. package/dist/src/cron/heartbeat-runner.test.js.map +1 -0
  135. package/dist/src/cron/heartbeat-scheduler.d.ts +26 -0
  136. package/dist/src/cron/heartbeat-scheduler.js +54 -0
  137. package/dist/src/cron/heartbeat-scheduler.js.map +1 -0
  138. package/dist/src/cron/heartbeat-scheduler.test.d.ts +6 -0
  139. package/dist/src/cron/heartbeat-scheduler.test.js +61 -0
  140. package/dist/src/cron/heartbeat-scheduler.test.js.map +1 -0
  141. package/dist/src/index.d.ts +24 -0
  142. package/dist/src/index.js +118 -0
  143. package/dist/src/index.js.map +1 -0
  144. package/dist/src/middleware/auth.d.ts +40 -0
  145. package/dist/src/middleware/auth.js +135 -0
  146. package/dist/src/middleware/auth.js.map +1 -0
  147. package/dist/src/middleware/auth.test.d.ts +6 -0
  148. package/dist/src/middleware/auth.test.js +268 -0
  149. package/dist/src/middleware/auth.test.js.map +1 -0
  150. package/dist/src/middleware/error-handler.d.ts +20 -0
  151. package/dist/src/middleware/error-handler.js +48 -0
  152. package/dist/src/middleware/error-handler.js.map +1 -0
  153. package/dist/src/middleware/error-handler.test.d.ts +6 -0
  154. package/dist/src/middleware/error-handler.test.js +68 -0
  155. package/dist/src/middleware/error-handler.test.js.map +1 -0
  156. package/dist/src/middleware/request-validation.d.ts +13 -0
  157. package/dist/src/middleware/request-validation.js +26 -0
  158. package/dist/src/middleware/request-validation.js.map +1 -0
  159. package/dist/src/middleware/request-validation.test.d.ts +6 -0
  160. package/dist/src/middleware/request-validation.test.js +57 -0
  161. package/dist/src/middleware/request-validation.test.js.map +1 -0
  162. package/dist/src/output/email-output.d.ts +10 -0
  163. package/dist/src/output/email-output.js +12 -0
  164. package/dist/src/output/email-output.js.map +1 -0
  165. package/dist/src/output/output-router.d.ts +12 -0
  166. package/dist/src/output/output-router.js +36 -0
  167. package/dist/src/output/output-router.js.map +1 -0
  168. package/dist/src/output/output-router.test.d.ts +6 -0
  169. package/dist/src/output/output-router.test.js +132 -0
  170. package/dist/src/output/output-router.test.js.map +1 -0
  171. package/dist/src/output/slack-output.d.ts +10 -0
  172. package/dist/src/output/slack-output.js +54 -0
  173. package/dist/src/output/slack-output.js.map +1 -0
  174. package/dist/src/output/webhook-output.d.ts +10 -0
  175. package/dist/src/output/webhook-output.js +25 -0
  176. package/dist/src/output/webhook-output.js.map +1 -0
  177. package/dist/src/routes/ai-stream.d.ts +159 -0
  178. package/dist/src/routes/ai-stream.js +309 -0
  179. package/dist/src/routes/ai-stream.js.map +1 -0
  180. package/dist/src/routes/ai-stream.test.d.ts +6 -0
  181. package/dist/src/routes/ai-stream.test.js +586 -0
  182. package/dist/src/routes/ai-stream.test.js.map +1 -0
  183. package/dist/src/routes/ask-user-response.d.ts +30 -0
  184. package/dist/src/routes/ask-user-response.js +61 -0
  185. package/dist/src/routes/ask-user-response.js.map +1 -0
  186. package/dist/src/routes/ask-user-response.test.d.ts +6 -0
  187. package/dist/src/routes/ask-user-response.test.js +88 -0
  188. package/dist/src/routes/ask-user-response.test.js.map +1 -0
  189. package/dist/src/routes/chat-stream.d.ts +14 -0
  190. package/dist/src/routes/chat-stream.js +84 -0
  191. package/dist/src/routes/chat-stream.js.map +1 -0
  192. package/dist/src/routes/chat-stream.test.d.ts +6 -0
  193. package/dist/src/routes/chat-stream.test.js +155 -0
  194. package/dist/src/routes/chat-stream.test.js.map +1 -0
  195. package/dist/src/routes/chat.d.ts +13 -0
  196. package/dist/src/routes/chat.js +55 -0
  197. package/dist/src/routes/chat.js.map +1 -0
  198. package/dist/src/routes/chat.test.d.ts +6 -0
  199. package/dist/src/routes/chat.test.js +99 -0
  200. package/dist/src/routes/chat.test.js.map +1 -0
  201. package/dist/src/routes/health.d.ts +13 -0
  202. package/dist/src/routes/health.js +23 -0
  203. package/dist/src/routes/health.js.map +1 -0
  204. package/dist/src/routes/health.test.d.ts +6 -0
  205. package/dist/src/routes/health.test.js +45 -0
  206. package/dist/src/routes/health.test.js.map +1 -0
  207. package/dist/src/routes/sessions.d.ts +14 -0
  208. package/dist/src/routes/sessions.js +82 -0
  209. package/dist/src/routes/sessions.js.map +1 -0
  210. package/dist/src/routes/webhooks.d.ts +13 -0
  211. package/dist/src/routes/webhooks.js +43 -0
  212. package/dist/src/routes/webhooks.js.map +1 -0
  213. package/dist/src/routes/webhooks.test.d.ts +6 -0
  214. package/dist/src/routes/webhooks.test.js +80 -0
  215. package/dist/src/routes/webhooks.test.js.map +1 -0
  216. package/dist/src/routes/widget-actions.d.ts +49 -0
  217. package/dist/src/routes/widget-actions.js +78 -0
  218. package/dist/src/routes/widget-actions.js.map +1 -0
  219. package/dist/src/server.d.ts +31 -0
  220. package/dist/src/server.js +129 -0
  221. package/dist/src/server.js.map +1 -0
  222. package/dist/src/server.test.d.ts +6 -0
  223. package/dist/src/server.test.js +153 -0
  224. package/dist/src/server.test.js.map +1 -0
  225. package/dist/src/session/history-converter.d.ts +21 -0
  226. package/dist/src/session/history-converter.js +59 -0
  227. package/dist/src/session/history-converter.js.map +1 -0
  228. package/dist/src/session/history-converter.test.d.ts +6 -0
  229. package/dist/src/session/history-converter.test.js +130 -0
  230. package/dist/src/session/history-converter.test.js.map +1 -0
  231. package/dist/src/session/session-manager.d.ts +117 -0
  232. package/dist/src/session/session-manager.js +480 -0
  233. package/dist/src/session/session-manager.js.map +1 -0
  234. package/dist/src/session/session-manager.test.d.ts +6 -0
  235. package/dist/src/session/session-manager.test.js +586 -0
  236. package/dist/src/session/session-manager.test.js.map +1 -0
  237. package/dist/src/session/session-runner.d.ts +30 -0
  238. package/dist/src/session/session-runner.js +771 -0
  239. package/dist/src/session/session-runner.js.map +1 -0
  240. package/dist/src/session/session-runner.test.d.ts +6 -0
  241. package/dist/src/session/session-runner.test.js +842 -0
  242. package/dist/src/session/session-runner.test.js.map +1 -0
  243. package/dist/src/stores/index.d.ts +8 -0
  244. package/dist/src/stores/index.js +9 -0
  245. package/dist/src/stores/index.js.map +1 -0
  246. package/dist/src/stores/key-resolver.d.ts +21 -0
  247. package/dist/src/stores/key-resolver.js +30 -0
  248. package/dist/src/stores/key-resolver.js.map +1 -0
  249. package/dist/src/stores/key-resolver.test.d.ts +6 -0
  250. package/dist/src/stores/key-resolver.test.js +31 -0
  251. package/dist/src/stores/key-resolver.test.js.map +1 -0
  252. package/dist/src/stores/pglite-store-backend.d.ts +36 -0
  253. package/dist/src/stores/pglite-store-backend.js +227 -0
  254. package/dist/src/stores/pglite-store-backend.js.map +1 -0
  255. package/dist/src/stores/pglite-store-backend.test.d.ts +6 -0
  256. package/dist/src/stores/pglite-store-backend.test.js +150 -0
  257. package/dist/src/stores/pglite-store-backend.test.js.map +1 -0
  258. package/dist/src/stores/ttl-resolver.d.ts +24 -0
  259. package/dist/src/stores/ttl-resolver.js +64 -0
  260. package/dist/src/stores/ttl-resolver.js.map +1 -0
  261. package/dist/src/stores/ttl-resolver.test.d.ts +6 -0
  262. package/dist/src/stores/ttl-resolver.test.js +68 -0
  263. package/dist/src/stores/ttl-resolver.test.js.map +1 -0
  264. package/dist/src/types.d.ts +227 -0
  265. package/dist/src/types.js +50 -0
  266. package/dist/src/types.js.map +1 -0
  267. package/dist/src/types.test.d.ts +6 -0
  268. package/dist/src/types.test.js +68 -0
  269. package/dist/src/types.test.js.map +1 -0
  270. package/dist/src/utils/jwt-verify.d.ts +20 -0
  271. package/dist/src/utils/jwt-verify.js +34 -0
  272. package/dist/src/utils/jwt-verify.js.map +1 -0
  273. package/dist/src/utils/jwt-verify.test.d.ts +6 -0
  274. package/dist/src/utils/jwt-verify.test.js +156 -0
  275. package/dist/src/utils/jwt-verify.test.js.map +1 -0
  276. package/dist/tsconfig.tsbuildinfo +1 -0
  277. package/package.json +51 -0
@@ -0,0 +1,137 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { Router } from 'express';
7
+ /**
8
+ * Creates routes for reading store data directly (without going through the LLM).
9
+ *
10
+ * GET /api/stores — list store definitions with doc counts
11
+ * GET /api/stores/:name — list documents (filter, sort, limit, offset)
12
+ * GET /api/stores/:name/:key — get single document + version history
13
+ */
14
+ export function createStoresRouter(options) {
15
+ const router = Router();
16
+ const { repo, storeBackend, tenantId } = options;
17
+ // List all store definitions with document counts
18
+ router.get('/api/stores', async (_req, res) => {
19
+ try {
20
+ const stores = await Promise.all(repo.stores.map(async (store) => {
21
+ const result = await storeBackend.list(tenantId, store.name, { limit: 0 });
22
+ return {
23
+ name: store.name,
24
+ entity: store.entity,
25
+ ttl: store.ttl,
26
+ trace: store.trace,
27
+ history: store.history,
28
+ documentCount: result.total,
29
+ };
30
+ }));
31
+ res.json({ stores });
32
+ }
33
+ catch (err) {
34
+ const message = err instanceof Error ? err.message : String(err);
35
+ res.status(500).json({ error: message });
36
+ }
37
+ });
38
+ // List documents from a store
39
+ router.get('/api/stores/:name', async (req, res) => {
40
+ const storeName = req.params['name'] ?? '';
41
+ // Verify store exists
42
+ const store = repo.stores.find((s) => s.name === storeName);
43
+ if (!store) {
44
+ res.status(404).json({ error: `Store "${storeName}" not found` });
45
+ return;
46
+ }
47
+ // Parse query params
48
+ let filter;
49
+ if (req.query['filter']) {
50
+ try {
51
+ filter = JSON.parse(String(req.query['filter']));
52
+ }
53
+ catch {
54
+ res.status(400).json({ error: 'Invalid filter JSON' });
55
+ return;
56
+ }
57
+ }
58
+ const sort = req.query['sort'] ? String(req.query['sort']) : undefined;
59
+ const limit = req.query['limit'] ? Number(req.query['limit']) : 20;
60
+ const offset = req.query['offset'] ? Number(req.query['offset']) : 0;
61
+ try {
62
+ const result = await storeBackend.list(tenantId, storeName, {
63
+ filter,
64
+ sort,
65
+ limit,
66
+ offset,
67
+ });
68
+ res.json(result);
69
+ }
70
+ catch (err) {
71
+ const message = err instanceof Error ? err.message : String(err);
72
+ res.status(500).json({ error: message });
73
+ }
74
+ });
75
+ // Get a single document + version history
76
+ router.get('/api/stores/:name/:key', async (req, res) => {
77
+ const storeName = req.params['name'] ?? '';
78
+ const key = req.params['key'] ?? '';
79
+ // Verify store exists
80
+ const store = repo.stores.find((s) => s.name === storeName);
81
+ if (!store) {
82
+ res.status(404).json({ error: `Store "${storeName}" not found` });
83
+ return;
84
+ }
85
+ try {
86
+ const document = await storeBackend.get(tenantId, storeName, key);
87
+ if (!document) {
88
+ res.status(404).json({ error: `Document "${key}" not found in store "${storeName}"` });
89
+ return;
90
+ }
91
+ // Include history if the store has versioning configured
92
+ let history = [];
93
+ if (store.history) {
94
+ history = await storeBackend.history(tenantId, storeName, key);
95
+ }
96
+ res.json({ document, history });
97
+ }
98
+ catch (err) {
99
+ const message = err instanceof Error ? err.message : String(err);
100
+ res.status(500).json({ error: message });
101
+ }
102
+ });
103
+ // Write a document to a store (for seeding/testing)
104
+ router.post('/api/stores/:name', async (req, res) => {
105
+ const storeName = req.params['name'] ?? '';
106
+ const store = repo.stores.find((s) => s.name === storeName);
107
+ if (!store) {
108
+ res.status(404).json({ error: `Store "${storeName}" not found` });
109
+ return;
110
+ }
111
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Express request body
112
+ const payload = req.body;
113
+ if (!payload || typeof payload !== 'object') {
114
+ res.status(400).json({ error: 'Request body must be a JSON object' });
115
+ return;
116
+ }
117
+ // Resolve key from template
118
+ const keyTemplate = store.entity.key;
119
+ const key = keyTemplate.replace(/\{(\w+)\}/g, (_, field) => {
120
+ const value = payload[field];
121
+ if (value === undefined || value === null) {
122
+ return field;
123
+ }
124
+ return String(value);
125
+ });
126
+ try {
127
+ const result = await storeBackend.put(tenantId, storeName, key, payload, {});
128
+ res.status(201).json(result);
129
+ }
130
+ catch (err) {
131
+ const message = err instanceof Error ? err.message : String(err);
132
+ res.status(500).json({ error: message });
133
+ }
134
+ });
135
+ return router;
136
+ }
137
+ //# sourceMappingURL=stores.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stores.js","sourceRoot":"","sources":["../../../../src/agent/routes/stores.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ export {};
@@ -0,0 +1,191 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { describe, it, expect, vi } from 'vitest';
7
+ import express from 'express';
8
+ import request from 'supertest';
9
+ import { createStoresRouter } from './stores.js';
10
+ function makeStore(name) {
11
+ return {
12
+ name,
13
+ entity: {
14
+ name: name.charAt(0).toUpperCase() + name.slice(1),
15
+ key: '{id}',
16
+ schema: {
17
+ id: { type: 'string' },
18
+ value: { type: 'string' },
19
+ },
20
+ },
21
+ location: `/test/stores/${name}.json`,
22
+ };
23
+ }
24
+ function makeRepo(stores) {
25
+ return {
26
+ source: 'local',
27
+ origin: '/test',
28
+ config: {
29
+ name: 'test',
30
+ version: '1.0',
31
+ models: { main: { provider: 'anthropic', model: 'claude-sonnet-4-20250514' } },
32
+ },
33
+ connections: new Map(),
34
+ skills: [],
35
+ agents: { subagents: [] },
36
+ automations: [],
37
+ knowledge: [],
38
+ evals: [],
39
+ tools: [],
40
+ stores,
41
+ };
42
+ }
43
+ function makeMockBackend() {
44
+ return {
45
+ initialize: vi.fn(),
46
+ get: vi.fn(),
47
+ put: vi.fn(),
48
+ list: vi.fn(),
49
+ delete: vi.fn(),
50
+ history: vi.fn(),
51
+ purgeExpired: vi.fn(),
52
+ close: vi.fn(),
53
+ };
54
+ }
55
+ function createApp(repo, backend) {
56
+ const app = express();
57
+ app.use(express.json());
58
+ app.use(createStoresRouter({ repo, storeBackend: backend, tenantId: 'test-tenant' }));
59
+ return app;
60
+ }
61
+ describe('stores router', () => {
62
+ describe('GET /api/stores', () => {
63
+ it('returns store definitions with document counts', async () => {
64
+ const stores = [makeStore('alerts'), makeStore('deals')];
65
+ const repo = makeRepo(stores);
66
+ const backend = makeMockBackend();
67
+ vi.mocked(backend.list)
68
+ .mockResolvedValueOnce({ documents: [], total: 47, hasMore: false })
69
+ .mockResolvedValueOnce({ documents: [], total: 12, hasMore: false });
70
+ const app = createApp(repo, backend);
71
+ const res = await request(app).get('/api/stores');
72
+ expect(res.status).toBe(200);
73
+ expect(res.body['stores']).toHaveLength(2);
74
+ expect(res.body['stores'][0]['name']).toBe('alerts');
75
+ expect(res.body['stores'][0]['documentCount']).toBe(47);
76
+ expect(res.body['stores'][1]['documentCount']).toBe(12);
77
+ });
78
+ it('returns empty when no stores defined', async () => {
79
+ const repo = makeRepo([]);
80
+ const backend = makeMockBackend();
81
+ const app = createApp(repo, backend);
82
+ const res = await request(app).get('/api/stores');
83
+ expect(res.status).toBe(200);
84
+ expect(res.body['stores']).toEqual([]);
85
+ });
86
+ });
87
+ describe('GET /api/stores/:name', () => {
88
+ it('lists documents from a store', async () => {
89
+ const stores = [makeStore('alerts')];
90
+ const repo = makeRepo(stores);
91
+ const backend = makeMockBackend();
92
+ vi.mocked(backend.list).mockResolvedValue({
93
+ documents: [{ key: 'a', tenantId: 'test', store: 'alerts', version: 1, payload: { id: 'a' }, meta: { computedAt: '2026-01-01', stale: false } }],
94
+ total: 1,
95
+ hasMore: false,
96
+ });
97
+ const app = createApp(repo, backend);
98
+ const res = await request(app).get('/api/stores/alerts');
99
+ expect(res.status).toBe(200);
100
+ expect(res.body['documents']).toHaveLength(1);
101
+ expect(res.body['total']).toBe(1);
102
+ });
103
+ it('returns 404 for unknown store', async () => {
104
+ const repo = makeRepo([]);
105
+ const backend = makeMockBackend();
106
+ const app = createApp(repo, backend);
107
+ const res = await request(app).get('/api/stores/nonexistent');
108
+ expect(res.status).toBe(404);
109
+ });
110
+ it('parses filter query param', async () => {
111
+ const stores = [makeStore('alerts')];
112
+ const repo = makeRepo(stores);
113
+ const backend = makeMockBackend();
114
+ vi.mocked(backend.list).mockResolvedValue({ documents: [], total: 0, hasMore: false });
115
+ const app = createApp(repo, backend);
116
+ await request(app)
117
+ .get('/api/stores/alerts')
118
+ .query({ filter: '{"severity":"P1"}', sort: '-severity', limit: '10' });
119
+ expect(backend.list).toHaveBeenCalledWith('test-tenant', 'alerts', expect.objectContaining({
120
+ filter: { severity: 'P1' },
121
+ sort: '-severity',
122
+ limit: 10,
123
+ }));
124
+ });
125
+ it('returns 400 for invalid filter JSON', async () => {
126
+ const stores = [makeStore('alerts')];
127
+ const repo = makeRepo(stores);
128
+ const backend = makeMockBackend();
129
+ const app = createApp(repo, backend);
130
+ const res = await request(app)
131
+ .get('/api/stores/alerts')
132
+ .query({ filter: 'not json' });
133
+ expect(res.status).toBe(400);
134
+ });
135
+ });
136
+ describe('GET /api/stores/:name/:key', () => {
137
+ it('returns a document by key', async () => {
138
+ const stores = [makeStore('alerts')];
139
+ const repo = makeRepo(stores);
140
+ const backend = makeMockBackend();
141
+ vi.mocked(backend.get).mockResolvedValue({
142
+ key: 'evt_123',
143
+ tenantId: 'test',
144
+ store: 'alerts',
145
+ version: 2,
146
+ payload: { id: 'evt_123', value: 'test' },
147
+ meta: { computedAt: '2026-01-01', stale: false },
148
+ });
149
+ vi.mocked(backend.history).mockResolvedValue([]);
150
+ const app = createApp(repo, backend);
151
+ const res = await request(app).get('/api/stores/alerts/evt_123');
152
+ expect(res.status).toBe(200);
153
+ expect(res.body['document']['key']).toBe('evt_123');
154
+ expect(res.body['history']).toEqual([]);
155
+ });
156
+ it('returns 404 for missing document', async () => {
157
+ const stores = [makeStore('alerts')];
158
+ const repo = makeRepo(stores);
159
+ const backend = makeMockBackend();
160
+ vi.mocked(backend.get).mockResolvedValue(null);
161
+ const app = createApp(repo, backend);
162
+ const res = await request(app).get('/api/stores/alerts/missing');
163
+ expect(res.status).toBe(404);
164
+ });
165
+ it('returns 404 for unknown store', async () => {
166
+ const repo = makeRepo([]);
167
+ const backend = makeMockBackend();
168
+ const app = createApp(repo, backend);
169
+ const res = await request(app).get('/api/stores/unknown/key');
170
+ expect(res.status).toBe(404);
171
+ });
172
+ it('includes version history when store has history config', async () => {
173
+ const stores = [makeStore('alerts')];
174
+ stores[0].history = { versions: 3 };
175
+ const repo = makeRepo(stores);
176
+ const backend = makeMockBackend();
177
+ vi.mocked(backend.get).mockResolvedValue({
178
+ key: 'k', tenantId: 'test', store: 'alerts', version: 3,
179
+ payload: { id: 'k' }, meta: { computedAt: '2026-01-01', stale: false },
180
+ });
181
+ vi.mocked(backend.history).mockResolvedValue([
182
+ { key: 'k', tenantId: 'test', store: 'alerts', version: 2, payload: { id: 'k' }, meta: { computedAt: '2026-01-01', stale: false } },
183
+ ]);
184
+ const app = createApp(repo, backend);
185
+ const res = await request(app).get('/api/stores/alerts/k');
186
+ expect(res.status).toBe(200);
187
+ expect(res.body['history']).toHaveLength(1);
188
+ });
189
+ });
190
+ });
191
+ //# sourceMappingURL=stores.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stores.test.js","sourceRoot":"","sources":["../../../../src/agent/routes/stores.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { Router } from 'express';
7
+ import type { AgentSessionManager } from '../session-manager.js';
8
+ export interface TaskRouterOptions {
9
+ sessionManager: AgentSessionManager;
10
+ }
11
+ export declare function createTaskRouter(options: TaskRouterOptions): Router;
@@ -0,0 +1,116 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { Router } from 'express';
7
+ import { randomUUID } from 'node:crypto';
8
+ import { z } from 'zod';
9
+ import { runAgentTurn } from '../agent-runner.js';
10
+ import { SSEEventType } from '../../types.js';
11
+ const TaskRequestSchema = z.object({
12
+ prompt: z.string().min(1),
13
+ tenant_id: z.string().min(1),
14
+ tenant_token: z.string().optional(),
15
+ });
16
+ const tasks = new Map();
17
+ export function createTaskRouter(options) {
18
+ const router = Router();
19
+ // POST /task — fire-and-forget task
20
+ router.post('/task', async (req, res) => {
21
+ const parsed = TaskRequestSchema.safeParse(req.body);
22
+ if (!parsed.success) {
23
+ res.status(400).json({ error: { code: 'VALIDATION_ERROR', message: parsed.error.message } });
24
+ return;
25
+ }
26
+ const { prompt, tenant_id, tenant_token } = parsed.data;
27
+ const taskId = randomUUID();
28
+ const record = {
29
+ id: taskId,
30
+ status: 'running',
31
+ events: [],
32
+ createdAt: Date.now(),
33
+ };
34
+ tasks.set(taskId, record);
35
+ // Return task ID immediately
36
+ res.status(202).json({ task_id: taskId });
37
+ // Run in background
38
+ void (async () => {
39
+ try {
40
+ const session = await options.sessionManager.create(tenant_id, tenant_token);
41
+ const controller = new AbortController();
42
+ for await (const event of runAgentTurn(session, prompt, controller.signal)) {
43
+ record.events.push(event);
44
+ }
45
+ record.status = 'completed';
46
+ }
47
+ catch (err) {
48
+ record.status = 'error';
49
+ const errMsg = err instanceof Error ? err.message : String(err);
50
+ record.events.push({ type: SSEEventType.Error, message: errMsg, timestamp: new Date().toISOString() });
51
+ }
52
+ })();
53
+ });
54
+ // GET /task/:id — poll task status
55
+ router.get('/task/:id', (req, res) => {
56
+ const taskId = req.params['id'];
57
+ if (!taskId) {
58
+ res.status(400).json({ error: { code: 'MISSING_ID', message: 'Task ID required' } });
59
+ return;
60
+ }
61
+ const record = tasks.get(taskId);
62
+ if (!record) {
63
+ res.status(404).json({ error: { code: 'NOT_FOUND', message: 'Task not found' } });
64
+ return;
65
+ }
66
+ res.json({
67
+ task_id: record.id,
68
+ status: record.status,
69
+ event_count: record.events.length,
70
+ created_at: record.createdAt,
71
+ });
72
+ });
73
+ // GET /task/:id/stream — stream task events
74
+ router.get('/task/:id/stream', (req, res) => {
75
+ const taskId = req.params['id'];
76
+ if (!taskId) {
77
+ res.status(400).json({ error: { code: 'MISSING_ID', message: 'Task ID required' } });
78
+ return;
79
+ }
80
+ const record = tasks.get(taskId);
81
+ if (!record) {
82
+ res.status(404).json({ error: { code: 'NOT_FOUND', message: 'Task not found' } });
83
+ return;
84
+ }
85
+ res.writeHead(200, {
86
+ 'Content-Type': 'text/event-stream',
87
+ 'Cache-Control': 'no-cache',
88
+ 'Connection': 'keep-alive',
89
+ });
90
+ // Send all existing events
91
+ for (const event of record.events) {
92
+ res.write(`data: ${JSON.stringify(event)}\n\n`);
93
+ }
94
+ if (record.status !== 'running') {
95
+ res.end();
96
+ return;
97
+ }
98
+ // Poll for new events
99
+ let lastSent = record.events.length;
100
+ const interval = setInterval(() => {
101
+ while (lastSent < record.events.length) {
102
+ res.write(`data: ${JSON.stringify(record.events[lastSent])}\n\n`);
103
+ lastSent++;
104
+ }
105
+ if (record.status !== 'running') {
106
+ clearInterval(interval);
107
+ res.end();
108
+ }
109
+ }, 100);
110
+ req.on('close', () => {
111
+ clearInterval(interval);
112
+ });
113
+ });
114
+ return router;
115
+ }
116
+ //# sourceMappingURL=task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.js","sourceRoot":"","sources":["../../../../src/agent/routes/task.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ export {};
@@ -0,0 +1,91 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
7
+ import express from 'express';
8
+ import request from 'supertest';
9
+ import { createTaskRouter } from './task.js';
10
+ // Mock agent-runner
11
+ vi.mock('../agent-runner.js', () => ({
12
+ runAgentTurn: vi.fn(async function* () {
13
+ yield { type: 'text_delta', content: 'Task output', timestamp: new Date().toISOString() };
14
+ yield { type: 'done', timestamp: new Date().toISOString() };
15
+ }),
16
+ }));
17
+ function makeSessionManager() {
18
+ return {
19
+ size: 0,
20
+ create: vi.fn(async () => ({
21
+ id: 'session-1',
22
+ tenantId: 'tenant-1',
23
+ runtime: { compiledContext: { systemPrompt: 'test' } },
24
+ conversationHistory: [],
25
+ createdAt: Date.now(),
26
+ lastAccessedAt: Date.now(),
27
+ planModeManager: {},
28
+ exploreConfig: {},
29
+ })),
30
+ get: vi.fn(),
31
+ destroy: vi.fn(),
32
+ cleanup: vi.fn(),
33
+ updateRepo: vi.fn(),
34
+ shutdown: vi.fn(),
35
+ };
36
+ }
37
+ function createTestApp(sessionManager) {
38
+ const app = express();
39
+ app.use(express.json());
40
+ app.use(createTaskRouter({ sessionManager }));
41
+ return app;
42
+ }
43
+ describe('repo-task route', () => {
44
+ let sessionManager;
45
+ beforeEach(() => {
46
+ sessionManager = makeSessionManager();
47
+ });
48
+ it('should reject invalid request', async () => {
49
+ const app = createTestApp(sessionManager);
50
+ const res = await request(app).post('/task').send({});
51
+ expect(res.status).toBe(400);
52
+ });
53
+ it('should accept and return task_id', async () => {
54
+ const app = createTestApp(sessionManager);
55
+ const res = await request(app)
56
+ .post('/task')
57
+ .send({ prompt: 'do something', tenant_id: 'tenant-1' });
58
+ expect(res.status).toBe(202);
59
+ expect(res.body).toHaveProperty('task_id');
60
+ });
61
+ it('should return 404 for unknown task', async () => {
62
+ const app = createTestApp(sessionManager);
63
+ const res = await request(app).get('/task/nonexistent');
64
+ expect(res.status).toBe(404);
65
+ });
66
+ it('should return task status after creation', async () => {
67
+ const app = createTestApp(sessionManager);
68
+ const createRes = await request(app)
69
+ .post('/task')
70
+ .send({ prompt: 'do something', tenant_id: 'tenant-1' });
71
+ const taskId = createRes.body['task_id'];
72
+ // Give the background task a moment to complete
73
+ await new Promise((resolve) => setTimeout(resolve, 100));
74
+ const statusRes = await request(app).get(`/task/${taskId}`);
75
+ expect(statusRes.status).toBe(200);
76
+ expect(statusRes.body).toHaveProperty('task_id', taskId);
77
+ expect(statusRes.body).toHaveProperty('status');
78
+ });
79
+ it('should stream task events', async () => {
80
+ const app = createTestApp(sessionManager);
81
+ const createRes = await request(app)
82
+ .post('/task')
83
+ .send({ prompt: 'do something', tenant_id: 'tenant-1' });
84
+ const taskId = createRes.body['task_id'];
85
+ // Give the background task a moment
86
+ await new Promise((resolve) => setTimeout(resolve, 100));
87
+ const streamRes = await request(app).get(`/task/${taskId}/stream`);
88
+ expect(streamRes.status).toBe(200);
89
+ });
90
+ });
91
+ //# sourceMappingURL=task.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.test.js","sourceRoot":"","sources":["../../../../src/agent/routes/task.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { Router } from 'express';
7
+ import type { ProactiveRunner } from '../proactive/proactive-runner.js';
8
+ export interface WebhookRouterOptions {
9
+ runner: ProactiveRunner;
10
+ webhookSecret?: string;
11
+ }
12
+ /**
13
+ * Creates routes for receiving webhook events from external systems.
14
+ *
15
+ * POST /webhooks/:name — trigger a webhook-based automation
16
+ */
17
+ export declare function createWebhookRouter(options: WebhookRouterOptions): Router;