@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,53 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { Router } from 'express';
7
+ import { verifyHmacSignature } from '../proactive/delivery.js';
8
+ /**
9
+ * Creates routes for receiving webhook events from external systems.
10
+ *
11
+ * POST /webhooks/:name — trigger a webhook-based automation
12
+ */
13
+ export function createWebhookRouter(options) {
14
+ const router = Router();
15
+ router.post('/webhooks/:name', async (req, res) => {
16
+ const automationName = req.params['name'] ?? '';
17
+ // HMAC verification
18
+ if (options.webhookSecret) {
19
+ const signature = req.headers['x-amodal-signature'];
20
+ if (typeof signature !== 'string') {
21
+ res.status(401).json({ error: 'Missing X-Amodal-Signature header' });
22
+ return;
23
+ }
24
+ const rawBody = typeof req.body === 'string'
25
+ ? req.body
26
+ : JSON.stringify(req.body);
27
+ if (!verifyHmacSignature(rawBody, signature, options.webhookSecret)) {
28
+ res.status(401).json({ error: 'Invalid webhook signature' });
29
+ return;
30
+ }
31
+ }
32
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Express body parsing
33
+ const payload = (req.body ?? {});
34
+ try {
35
+ const result = await options.runner.handleWebhook(automationName, payload);
36
+ if (!result.matched) {
37
+ res.status(404).json({ error: result.error });
38
+ return;
39
+ }
40
+ if (result.error) {
41
+ res.status(500).json({ error: result.error, matched: true });
42
+ return;
43
+ }
44
+ res.json({ status: 'accepted', automation: automationName });
45
+ }
46
+ catch (err) {
47
+ const msg = err instanceof Error ? err.message : String(err);
48
+ res.status(500).json({ error: msg });
49
+ }
50
+ });
51
+ return router;
52
+ }
53
+ //# sourceMappingURL=webhooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../../../src/agent/routes/webhooks.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,MAAM,EAAC,MAAM,SAAS,CAAC;AAE/B,OAAO,EAAC,mBAAmB,EAAC,MAAM,0BAA0B,CAAC;AAQ7D;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAA6B;IAC/D,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;QACnE,MAAM,cAAc,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAEhD,oBAAoB;QACpB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;YAC1B,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;YACpD,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;gBAClC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,mCAAmC,EAAC,CAAC,CAAC;gBACnE,OAAO;YACT,CAAC;YAED,MAAM,OAAO,GAAG,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;gBAC1C,CAAC,CAAC,GAAG,CAAC,IAAI;gBACV,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAE7B,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;gBACpE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,2BAA2B,EAAC,CAAC,CAAC;gBAC3D,OAAO;YACT,CAAC;QACH,CAAC;QAED,+FAA+F;QAC/F,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAA4B,CAAC;QAE5D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;YAC3E,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,MAAM,CAAC,KAAK,EAAC,CAAC,CAAC;gBAC5C,OAAO;YACT,CAAC;YAED,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBACjB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAC,CAAC,CAAC;gBAC3D,OAAO;YACT,CAAC;YAED,GAAG,CAAC,IAAI,CAAC,EAAC,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAC,CAAC,CAAC;QAC7D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,GAAG,EAAC,CAAC,CAAC;QACrC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ export {};
@@ -0,0 +1,100 @@
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 { createHmac } from 'node:crypto';
10
+ import { createWebhookRouter } from './webhooks.js';
11
+ function makeMockRunner(overrides) {
12
+ return {
13
+ start: vi.fn(),
14
+ stop: vi.fn(),
15
+ listAutomations: vi.fn().mockReturnValue([]),
16
+ handleWebhook: vi.fn().mockResolvedValue({ matched: true }),
17
+ triggerAutomation: vi.fn().mockResolvedValue({ success: true }),
18
+ ...overrides,
19
+ };
20
+ }
21
+ function createApp(runner, webhookSecret) {
22
+ const app = express();
23
+ app.use(express.json());
24
+ app.use(createWebhookRouter({ runner, webhookSecret }));
25
+ return app;
26
+ }
27
+ describe('repo-webhooks routes', () => {
28
+ it('should accept valid webhook', async () => {
29
+ const runner = makeMockRunner();
30
+ const app = createApp(runner);
31
+ const res = await request(app)
32
+ .post('/webhooks/my-auto')
33
+ .send({ alert: 'cpu-high' });
34
+ expect(res.status).toBe(200);
35
+ expect(res.body.status).toBe('accepted');
36
+ expect(runner.handleWebhook).toHaveBeenCalledWith('my-auto', { alert: 'cpu-high' });
37
+ });
38
+ it('should return 404 for unmatched automation', async () => {
39
+ const runner = makeMockRunner({
40
+ handleWebhook: vi.fn().mockResolvedValue({ matched: false, error: 'Not found' }),
41
+ });
42
+ const app = createApp(runner);
43
+ const res = await request(app)
44
+ .post('/webhooks/unknown')
45
+ .send({});
46
+ expect(res.status).toBe(404);
47
+ });
48
+ it('should return 500 on automation error', async () => {
49
+ const runner = makeMockRunner({
50
+ handleWebhook: vi.fn().mockResolvedValue({ matched: true, error: 'Exec failed' }),
51
+ });
52
+ const app = createApp(runner);
53
+ const res = await request(app)
54
+ .post('/webhooks/my-auto')
55
+ .send({});
56
+ expect(res.status).toBe(500);
57
+ expect(res.body.error).toBe('Exec failed');
58
+ });
59
+ it('should verify HMAC signature when secret is set', async () => {
60
+ const runner = makeMockRunner();
61
+ const secret = 'my-secret';
62
+ const app = createApp(runner, secret);
63
+ const body = JSON.stringify({ alert: 'test' });
64
+ const sig = `sha256=${createHmac('sha256', secret).update(body).digest('hex')}`;
65
+ const res = await request(app)
66
+ .post('/webhooks/my-auto')
67
+ .set('Content-Type', 'application/json')
68
+ .set('X-Amodal-Signature', sig)
69
+ .send(body);
70
+ expect(res.status).toBe(200);
71
+ });
72
+ it('should reject missing signature when secret is set', async () => {
73
+ const runner = makeMockRunner();
74
+ const app = createApp(runner, 'my-secret');
75
+ const res = await request(app)
76
+ .post('/webhooks/my-auto')
77
+ .send({ alert: 'test' });
78
+ expect(res.status).toBe(401);
79
+ expect(res.body.error).toContain('Missing');
80
+ });
81
+ it('should reject invalid signature', async () => {
82
+ const runner = makeMockRunner();
83
+ const app = createApp(runner, 'my-secret');
84
+ const res = await request(app)
85
+ .post('/webhooks/my-auto')
86
+ .set('X-Amodal-Signature', 'sha256=invalid')
87
+ .send({ alert: 'test' });
88
+ expect(res.status).toBe(401);
89
+ expect(res.body.error).toContain('Invalid');
90
+ });
91
+ it('should not require signature when no secret configured', async () => {
92
+ const runner = makeMockRunner();
93
+ const app = createApp(runner);
94
+ const res = await request(app)
95
+ .post('/webhooks/my-auto')
96
+ .send({});
97
+ expect(res.status).toBe(200);
98
+ });
99
+ });
100
+ //# sourceMappingURL=webhooks.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.test.js","sourceRoot":"","sources":["../../../../src/agent/routes/webhooks.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import type { AmodalRepo } from '@amodalai/core';
7
+ import type { RuntimeTelemetryEvent, CustomToolExecutor, CustomShellExecutor, StoreBackend } from '@amodalai/core';
8
+ import type { AgentSession } from './agent-types.js';
9
+ export type TelemetrySink = (event: RuntimeTelemetryEvent) => void;
10
+ export interface AgentSessionManagerOptions {
11
+ ttlMs?: number;
12
+ telemetrySink?: TelemetrySink;
13
+ toolExecutor?: CustomToolExecutor;
14
+ shellExecutor?: CustomShellExecutor;
15
+ storeBackend?: StoreBackend;
16
+ }
17
+ /**
18
+ * Manages repo-based sessions with TTL eviction.
19
+ */
20
+ export declare class AgentSessionManager {
21
+ private repo;
22
+ private readonly sessions;
23
+ private readonly ttlMs;
24
+ private readonly telemetrySink?;
25
+ private readonly toolExecutor?;
26
+ private readonly shellExecutor?;
27
+ private readonly storeBackend?;
28
+ private platformTelemetry?;
29
+ private cleanupTimer;
30
+ constructor(repo: AmodalRepo, options?: AgentSessionManagerOptions);
31
+ get size(): number;
32
+ /**
33
+ * Create a new session, optionally fetching user context for role extraction.
34
+ */
35
+ create(tenantId: string, tenantToken?: string): Promise<AgentSession>;
36
+ /**
37
+ * Create a session from a specific repo (e.g., enriched with tenant credentials).
38
+ * Used by hosted runtime when tenant-specific config is fetched from the platform API.
39
+ */
40
+ createFromRepo(repo: AmodalRepo, tenantId: string): Promise<AgentSession>;
41
+ /**
42
+ * Re-register a session under a different ID (e.g., restoring original ID on hydration).
43
+ */
44
+ reregister(session: AgentSession, newId: string): void;
45
+ /**
46
+ * Get an existing session by ID.
47
+ */
48
+ get(sessionId: string): AgentSession | undefined;
49
+ /**
50
+ * Destroy a session.
51
+ */
52
+ destroy(sessionId: string): void;
53
+ /**
54
+ * Remove sessions that have been idle longer than TTL.
55
+ * Returns the number of sessions removed.
56
+ */
57
+ cleanup(): number;
58
+ /**
59
+ * Update the repo for all new sessions (hot reload).
60
+ * Existing sessions keep their old repo.
61
+ */
62
+ updateRepo(repo: AmodalRepo): void;
63
+ /**
64
+ * Shut down all sessions and stop the cleanup timer.
65
+ */
66
+ shutdown(): Promise<void>;
67
+ /**
68
+ * Initialize MCP servers for a session if the repo has MCP config.
69
+ */
70
+ private initMcp;
71
+ private getConnectionsMap;
72
+ }
@@ -0,0 +1,214 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { randomUUID } from 'node:crypto';
7
+ import { setupSession, PlanModeManager, prepareExploreConfig, extractRoles, buildConnectionsMap, PlatformTelemetrySink, McpManager, } from '@amodalai/core';
8
+ import { fetchUserContext } from './user-context-fetcher.js';
9
+ const DEFAULT_TTL_MS = 30 * 60 * 1000; // 30 minutes
10
+ const CLEANUP_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes
11
+ /**
12
+ * Manages repo-based sessions with TTL eviction.
13
+ */
14
+ export class AgentSessionManager {
15
+ repo;
16
+ sessions = new Map();
17
+ ttlMs;
18
+ telemetrySink;
19
+ toolExecutor;
20
+ shellExecutor;
21
+ storeBackend;
22
+ platformTelemetry;
23
+ cleanupTimer = null;
24
+ constructor(repo, options) {
25
+ this.repo = repo;
26
+ this.ttlMs = options?.ttlMs ?? DEFAULT_TTL_MS;
27
+ // If platform config is set and no explicit sink provided, create a platform sink
28
+ if (!options?.telemetrySink && repo.config.platform?.apiKey) {
29
+ const platformUrl = process.env['PLATFORM_API_URL'] ?? 'http://localhost:4000';
30
+ this.platformTelemetry = new PlatformTelemetrySink(platformUrl, repo.config.platform.apiKey);
31
+ this.telemetrySink = this.platformTelemetry.sink();
32
+ }
33
+ else {
34
+ this.telemetrySink = options?.telemetrySink;
35
+ }
36
+ this.toolExecutor = options?.toolExecutor;
37
+ this.shellExecutor = options?.shellExecutor;
38
+ this.storeBackend = options?.storeBackend;
39
+ this.cleanupTimer = setInterval(() => {
40
+ this.cleanup();
41
+ }, CLEANUP_INTERVAL_MS);
42
+ // Unref so the timer doesn't keep the process alive
43
+ if (this.cleanupTimer && typeof this.cleanupTimer === 'object' && 'unref' in this.cleanupTimer) {
44
+ this.cleanupTimer.unref();
45
+ }
46
+ }
47
+ get size() {
48
+ return this.sessions.size;
49
+ }
50
+ /**
51
+ * Create a new session, optionally fetching user context for role extraction.
52
+ */
53
+ async create(tenantId, tenantToken) {
54
+ let userRoles = [];
55
+ // Fetch user context if configured
56
+ if (this.repo.config.userContext && tenantToken) {
57
+ try {
58
+ const connectionsMap = this.getConnectionsMap();
59
+ const userData = await fetchUserContext(this.repo, tenantToken, connectionsMap);
60
+ userRoles = extractRoles(userData);
61
+ }
62
+ catch {
63
+ // Degraded but functional — empty roles
64
+ }
65
+ }
66
+ const runtime = setupSession({
67
+ repo: this.repo,
68
+ userId: tenantId,
69
+ userRoles,
70
+ isDelegated: false,
71
+ telemetrySink: this.telemetrySink,
72
+ });
73
+ const planModeManager = new PlanModeManager();
74
+ const exploreConfig = prepareExploreConfig(runtime);
75
+ const session = {
76
+ id: randomUUID(),
77
+ runtime,
78
+ tenantId,
79
+ conversationHistory: [],
80
+ createdAt: Date.now(),
81
+ lastAccessedAt: Date.now(),
82
+ planModeManager,
83
+ exploreConfig,
84
+ toolExecutor: this.toolExecutor,
85
+ shellExecutor: this.shellExecutor,
86
+ storeBackend: this.storeBackend,
87
+ };
88
+ // Start MCP servers if configured (non-blocking)
89
+ await this.initMcp(session, this.repo);
90
+ this.sessions.set(session.id, session);
91
+ return session;
92
+ }
93
+ /**
94
+ * Create a session from a specific repo (e.g., enriched with tenant credentials).
95
+ * Used by hosted runtime when tenant-specific config is fetched from the platform API.
96
+ */
97
+ async createFromRepo(repo, tenantId) {
98
+ const runtime = setupSession({
99
+ repo,
100
+ userId: tenantId,
101
+ userRoles: [],
102
+ isDelegated: false,
103
+ telemetrySink: this.telemetrySink,
104
+ });
105
+ const planModeManager = new PlanModeManager();
106
+ const exploreConfig = prepareExploreConfig(runtime);
107
+ const session = {
108
+ id: randomUUID(),
109
+ runtime,
110
+ tenantId,
111
+ conversationHistory: [],
112
+ createdAt: Date.now(),
113
+ lastAccessedAt: Date.now(),
114
+ planModeManager,
115
+ exploreConfig,
116
+ toolExecutor: this.toolExecutor,
117
+ shellExecutor: this.shellExecutor,
118
+ storeBackend: this.storeBackend,
119
+ };
120
+ // Start MCP servers if configured (non-blocking)
121
+ await this.initMcp(session, repo);
122
+ this.sessions.set(session.id, session);
123
+ return session;
124
+ }
125
+ /**
126
+ * Re-register a session under a different ID (e.g., restoring original ID on hydration).
127
+ */
128
+ reregister(session, newId) {
129
+ this.sessions.delete(session.id);
130
+ session.id = newId;
131
+ this.sessions.set(newId, session);
132
+ }
133
+ /**
134
+ * Get an existing session by ID.
135
+ */
136
+ get(sessionId) {
137
+ const session = this.sessions.get(sessionId);
138
+ if (session) {
139
+ session.lastAccessedAt = Date.now();
140
+ }
141
+ return session;
142
+ }
143
+ /**
144
+ * Destroy a session.
145
+ */
146
+ destroy(sessionId) {
147
+ this.sessions.delete(sessionId);
148
+ }
149
+ /**
150
+ * Remove sessions that have been idle longer than TTL.
151
+ * Returns the number of sessions removed.
152
+ */
153
+ cleanup() {
154
+ const now = Date.now();
155
+ let removed = 0;
156
+ for (const [id, session] of this.sessions) {
157
+ if (now - session.lastAccessedAt > this.ttlMs) {
158
+ this.sessions.delete(id);
159
+ removed++;
160
+ }
161
+ }
162
+ return removed;
163
+ }
164
+ /**
165
+ * Update the repo for all new sessions (hot reload).
166
+ * Existing sessions keep their old repo.
167
+ */
168
+ updateRepo(repo) {
169
+ this.repo = repo;
170
+ }
171
+ /**
172
+ * Shut down all sessions and stop the cleanup timer.
173
+ */
174
+ async shutdown() {
175
+ if (this.cleanupTimer) {
176
+ clearInterval(this.cleanupTimer);
177
+ this.cleanupTimer = null;
178
+ }
179
+ if (this.platformTelemetry) {
180
+ await this.platformTelemetry.destroy();
181
+ this.platformTelemetry = undefined;
182
+ }
183
+ // Shutdown MCP managers for all sessions
184
+ for (const session of this.sessions.values()) {
185
+ if (session.mcpManager) {
186
+ await session.mcpManager.shutdown().catch(() => { });
187
+ }
188
+ }
189
+ this.sessions.clear();
190
+ }
191
+ /**
192
+ * Initialize MCP servers for a session if the repo has MCP config.
193
+ */
194
+ async initMcp(session, repo) {
195
+ if (!repo.mcpServers || Object.keys(repo.mcpServers).length === 0) {
196
+ return;
197
+ }
198
+ const manager = new McpManager();
199
+ try {
200
+ await manager.startServers(repo.mcpServers);
201
+ if (manager.connectedCount > 0) {
202
+ session.mcpManager = manager;
203
+ }
204
+ }
205
+ catch (err) {
206
+ const msg = err instanceof Error ? err.message : String(err);
207
+ process.stderr.write(`[SESSION] MCP initialization failed: ${msg}\n`);
208
+ }
209
+ }
210
+ getConnectionsMap() {
211
+ return buildConnectionsMap(this.repo.connections);
212
+ }
213
+ }
214
+ //# sourceMappingURL=session-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../../../src/agent/session-manager.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,145 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
7
+ import { AgentSessionManager } from './session-manager.js';
8
+ // Mock setupSession and friends
9
+ vi.mock('@amodalai/core', async (importOriginal) => {
10
+ const actual = await importOriginal();
11
+ return {
12
+ ...actual,
13
+ setupSession: vi.fn(() => ({
14
+ repo: makeRepo(),
15
+ scrubTracker: {},
16
+ fieldScrubber: { scrub: vi.fn() },
17
+ outputGuard: { guard: vi.fn(() => ({ output: '', modified: false, blocked: false, findings: [] })) },
18
+ actionGate: { evaluate: vi.fn(() => ({ decision: 'allow', escalated: false, endpointPath: '' })) },
19
+ contextCompiler: {},
20
+ compiledContext: { systemPrompt: 'test', tokenUsage: { total: 100000, used: 500, remaining: 99500, sectionBreakdown: {} }, sections: [] },
21
+ exploreContext: { systemPrompt: 'explore', tokenUsage: { total: 100000, used: 300, remaining: 99700, sectionBreakdown: {} }, sections: [] },
22
+ outputPipeline: { process: vi.fn((t) => ({ output: t, modified: false, blocked: false, findings: [] })), createStreamProcessor: vi.fn() },
23
+ telemetry: { logScrub: vi.fn(), logGuard: vi.fn(), logGate: vi.fn(), logExplore: vi.fn() },
24
+ connectionsMap: {},
25
+ userRoles: [],
26
+ sessionId: 'test-session',
27
+ isDelegated: false,
28
+ })),
29
+ prepareExploreConfig: vi.fn(() => ({
30
+ systemPrompt: 'explore',
31
+ model: { provider: 'anthropic', model: 'test' },
32
+ connectionsMap: {},
33
+ readOnly: true,
34
+ maxTurns: 10,
35
+ maxDepth: 2,
36
+ })),
37
+ PlanModeManager: vi.fn(() => ({
38
+ isActive: vi.fn(() => false),
39
+ getApprovedPlan: vi.fn(() => null),
40
+ getReason: vi.fn(() => null),
41
+ enter: vi.fn(),
42
+ approve: vi.fn(),
43
+ exit: vi.fn(),
44
+ getPlanningReminder: vi.fn(() => null),
45
+ getApprovedPlanContext: vi.fn(() => null),
46
+ })),
47
+ extractRoles: vi.fn(() => []),
48
+ buildConnectionsMap: vi.fn(() => ({})),
49
+ };
50
+ });
51
+ function makeRepo() {
52
+ return {
53
+ source: 'local',
54
+ origin: '/test',
55
+ config: {
56
+ name: 'test',
57
+ version: '1.0.0',
58
+ models: {
59
+ main: { provider: 'anthropic', model: 'claude-sonnet-4-20250514' },
60
+ },
61
+ },
62
+ connections: new Map(),
63
+ skills: [],
64
+ agents: { subagents: [] },
65
+ automations: [],
66
+ knowledge: [],
67
+ evals: [],
68
+ tools: [],
69
+ stores: [],
70
+ };
71
+ }
72
+ describe('AgentSessionManager', () => {
73
+ let manager;
74
+ beforeEach(() => {
75
+ vi.useFakeTimers();
76
+ manager = new AgentSessionManager(makeRepo(), { ttlMs: 1000 });
77
+ });
78
+ afterEach(async () => {
79
+ await manager.shutdown();
80
+ vi.useRealTimers();
81
+ });
82
+ it('should create a session', async () => {
83
+ const session = await manager.create('tenant-1');
84
+ expect(session.id).toBeTruthy();
85
+ expect(session.tenantId).toBe('tenant-1');
86
+ expect(session.conversationHistory).toEqual([]);
87
+ expect(manager.size).toBe(1);
88
+ });
89
+ it('should get an existing session', async () => {
90
+ const session = await manager.create('tenant-1');
91
+ const found = manager.get(session.id);
92
+ expect(found).toBeDefined();
93
+ expect(found?.id).toBe(session.id);
94
+ });
95
+ it('should return undefined for unknown session', () => {
96
+ expect(manager.get('nonexistent')).toBeUndefined();
97
+ });
98
+ it('should destroy a session', async () => {
99
+ const session = await manager.create('tenant-1');
100
+ manager.destroy(session.id);
101
+ expect(manager.get(session.id)).toBeUndefined();
102
+ expect(manager.size).toBe(0);
103
+ });
104
+ it('should clean up expired sessions', async () => {
105
+ await manager.create('tenant-1');
106
+ expect(manager.size).toBe(1);
107
+ vi.advanceTimersByTime(1500);
108
+ const removed = manager.cleanup();
109
+ expect(removed).toBe(1);
110
+ expect(manager.size).toBe(0);
111
+ });
112
+ it('should not clean up active sessions', async () => {
113
+ const session = await manager.create('tenant-1');
114
+ vi.advanceTimersByTime(500);
115
+ // Access the session to update lastAccessedAt
116
+ manager.get(session.id);
117
+ vi.advanceTimersByTime(600);
118
+ const removed = manager.cleanup();
119
+ expect(removed).toBe(0);
120
+ expect(manager.size).toBe(1);
121
+ });
122
+ it('should update repo for new sessions', async () => {
123
+ const newRepo = makeRepo();
124
+ newRepo.config.name = 'updated';
125
+ manager.updateRepo(newRepo);
126
+ // The next created session should use the new repo
127
+ const session = await manager.create('tenant-1');
128
+ expect(session).toBeDefined();
129
+ });
130
+ it('should shutdown cleanly', async () => {
131
+ await manager.create('tenant-1');
132
+ await manager.create('tenant-2');
133
+ expect(manager.size).toBe(2);
134
+ await manager.shutdown();
135
+ expect(manager.size).toBe(0);
136
+ });
137
+ it('should update lastAccessedAt on get', async () => {
138
+ const session = await manager.create('tenant-1');
139
+ const initialAccess = session.lastAccessedAt;
140
+ vi.advanceTimersByTime(100);
141
+ manager.get(session.id);
142
+ expect(session.lastAccessedAt).toBeGreaterThan(initialAccess);
143
+ });
144
+ });
145
+ //# sourceMappingURL=session-manager.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.test.js","sourceRoot":"","sources":["../../../src/agent/session-manager.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import type { CustomShellExecutor } from '@amodalai/core';
7
+ /**
8
+ * Executes shell commands locally via child_process.
9
+ */
10
+ export declare class LocalShellExecutor implements CustomShellExecutor {
11
+ exec(command: string, timeout: number, signal: AbortSignal): Promise<{
12
+ stdout: string;
13
+ stderr: string;
14
+ exitCode: number;
15
+ }>;
16
+ }