@amodalai/runtime 0.1.26 → 0.2.1

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 (445) hide show
  1. package/dist/src/__fixtures__/README.md +88 -0
  2. package/dist/src/__fixtures__/e2e.test.js +211 -0
  3. package/dist/src/__fixtures__/e2e.test.js.map +1 -0
  4. package/dist/src/__fixtures__/smoke-agent/amodal.json +11 -0
  5. package/dist/src/__fixtures__/smoke-agent/automations/delivery-callback-test.json +9 -0
  6. package/dist/src/__fixtures__/smoke-agent/automations/test-auto.md +5 -0
  7. package/dist/src/__fixtures__/smoke-agent/connections/mock-api/access.json +11 -0
  8. package/dist/src/__fixtures__/smoke-agent/connections/mock-api/spec.json +4 -0
  9. package/dist/src/__fixtures__/smoke-agent/connections/mock-api/surface.md +9 -0
  10. package/dist/src/__fixtures__/smoke-agent/connections/mock-mcp/access.json +3 -0
  11. package/dist/src/__fixtures__/smoke-agent/connections/mock-mcp/spec.json +8 -0
  12. package/dist/src/__fixtures__/smoke-agent/evals/basic-eval.md +12 -0
  13. package/dist/src/__fixtures__/smoke-agent/knowledge/test-knowledge.md +3 -0
  14. package/dist/src/__fixtures__/smoke-agent/skills/test-skill/SKILL.md +11 -0
  15. package/dist/src/__fixtures__/smoke-agent/stores/test-items.json +11 -0
  16. package/dist/src/__fixtures__/smoke-agent/tools/echo_tool/handler.d.ts +18 -0
  17. package/dist/src/__fixtures__/smoke-agent/tools/echo_tool/handler.js +22 -0
  18. package/dist/src/__fixtures__/smoke-agent/tools/echo_tool/handler.js.map +1 -0
  19. package/dist/src/__fixtures__/smoke-agent/tools/echo_tool/tool.json +17 -0
  20. package/dist/src/__fixtures__/smoke.test.js +1404 -0
  21. package/dist/src/__fixtures__/smoke.test.js.map +1 -0
  22. package/dist/src/__fixtures__/test-env.d.ts +27 -0
  23. package/dist/src/__fixtures__/test-env.js +64 -0
  24. package/dist/src/__fixtures__/test-env.js.map +1 -0
  25. package/dist/src/__fixtures__/test-helpers.d.ts +30 -0
  26. package/dist/src/__fixtures__/test-helpers.js +120 -0
  27. package/dist/src/__fixtures__/test-helpers.js.map +1 -0
  28. package/dist/src/__tests__/test-providers.d.ts +40 -0
  29. package/dist/src/__tests__/test-providers.js +61 -0
  30. package/dist/src/__tests__/test-providers.js.map +1 -0
  31. package/dist/src/agent/agent-types.d.ts +22 -0
  32. package/dist/src/agent/agent-types.js.map +1 -1
  33. package/dist/src/agent/automation-bridge.d.ts +9 -0
  34. package/dist/src/agent/automation-bridge.js +26 -0
  35. package/dist/src/agent/automation-bridge.js.map +1 -1
  36. package/dist/src/agent/automation-bridge.test.js +63 -0
  37. package/dist/src/agent/automation-bridge.test.js.map +1 -1
  38. package/dist/src/agent/local-server.d.ts +1 -8
  39. package/dist/src/agent/local-server.js +398 -163
  40. package/dist/src/agent/local-server.js.map +1 -1
  41. package/dist/src/agent/local-server.test.js +14 -8
  42. package/dist/src/agent/local-server.test.js.map +1 -1
  43. package/dist/src/agent/loop-types.d.ts +254 -0
  44. package/dist/src/agent/loop-types.js +24 -0
  45. package/dist/src/agent/loop-types.js.map +1 -0
  46. package/dist/src/agent/loop.d.ts +31 -0
  47. package/dist/src/agent/loop.js +152 -0
  48. package/dist/src/agent/loop.js.map +1 -0
  49. package/dist/src/agent/loop.test.js +1594 -0
  50. package/dist/src/agent/loop.test.js.map +1 -0
  51. package/dist/src/agent/mcp-config.d.ts +28 -0
  52. package/dist/src/agent/mcp-config.js +57 -0
  53. package/dist/src/agent/mcp-config.js.map +1 -0
  54. package/dist/src/agent/page-builder.js +6 -1
  55. package/dist/src/agent/page-builder.js.map +1 -1
  56. package/dist/src/agent/proactive/delivery-router.d.ts +68 -0
  57. package/dist/src/agent/proactive/delivery-router.js +337 -0
  58. package/dist/src/agent/proactive/delivery-router.js.map +1 -0
  59. package/dist/src/agent/{stores-e2e.test.d.ts → proactive/delivery-router.test.d.ts} +1 -1
  60. package/dist/src/agent/proactive/delivery-router.test.js +455 -0
  61. package/dist/src/agent/proactive/delivery-router.test.js.map +1 -0
  62. package/dist/src/agent/proactive/proactive-runner.d.ts +46 -8
  63. package/dist/src/agent/proactive/proactive-runner.js +67 -37
  64. package/dist/src/agent/proactive/proactive-runner.js.map +1 -1
  65. package/dist/src/agent/proactive/proactive-runner.test.d.ts +1 -1
  66. package/dist/src/agent/proactive/proactive-runner.test.js +73 -87
  67. package/dist/src/agent/proactive/proactive-runner.test.js.map +1 -1
  68. package/dist/src/agent/routes/admin-chat-abort.test.d.ts +6 -0
  69. package/dist/src/agent/routes/admin-chat-abort.test.js +206 -0
  70. package/dist/src/agent/routes/admin-chat-abort.test.js.map +1 -0
  71. package/dist/src/agent/routes/admin-chat.d.ts +15 -3
  72. package/dist/src/agent/routes/admin-chat.js +61 -18
  73. package/dist/src/agent/routes/admin-chat.js.map +1 -1
  74. package/dist/src/agent/routes/automations.js +5 -6
  75. package/dist/src/agent/routes/automations.js.map +1 -1
  76. package/dist/src/agent/routes/evals.d.ts +3 -2
  77. package/dist/src/agent/routes/evals.js +25 -12
  78. package/dist/src/agent/routes/evals.js.map +1 -1
  79. package/dist/src/agent/routes/files.js +7 -9
  80. package/dist/src/agent/routes/files.js.map +1 -1
  81. package/dist/src/agent/routes/inspect.d.ts +6 -2
  82. package/dist/src/agent/routes/inspect.js +31 -17
  83. package/dist/src/agent/routes/inspect.js.map +1 -1
  84. package/dist/src/agent/routes/inspect.test.js +18 -42
  85. package/dist/src/agent/routes/inspect.test.js.map +1 -1
  86. package/dist/src/agent/routes/stores.js +9 -12
  87. package/dist/src/agent/routes/stores.js.map +1 -1
  88. package/dist/src/agent/routes/task.d.ts +15 -3
  89. package/dist/src/agent/routes/task.js +16 -7
  90. package/dist/src/agent/routes/task.js.map +1 -1
  91. package/dist/src/agent/routes/task.test.d.ts +1 -1
  92. package/dist/src/agent/routes/task.test.js +68 -53
  93. package/dist/src/agent/routes/task.test.js.map +1 -1
  94. package/dist/src/agent/routes/webhooks.js +12 -3
  95. package/dist/src/agent/routes/webhooks.js.map +1 -1
  96. package/dist/src/agent/snapshot-server.d.ts +2 -22
  97. package/dist/src/agent/snapshot-server.js +48 -27
  98. package/dist/src/agent/snapshot-server.js.map +1 -1
  99. package/dist/src/agent/states/compacting.d.ts +14 -0
  100. package/dist/src/agent/states/compacting.js +260 -0
  101. package/dist/src/agent/states/compacting.js.map +1 -0
  102. package/dist/src/agent/states/confirming.d.ts +10 -0
  103. package/dist/src/agent/states/confirming.js +79 -0
  104. package/dist/src/agent/states/confirming.js.map +1 -0
  105. package/dist/src/agent/states/dispatching.d.ts +18 -0
  106. package/dist/src/agent/states/dispatching.js +285 -0
  107. package/dist/src/agent/states/dispatching.js.map +1 -0
  108. package/dist/src/agent/states/executing.d.ts +21 -0
  109. package/dist/src/agent/states/executing.js +452 -0
  110. package/dist/src/agent/states/executing.js.map +1 -0
  111. package/dist/src/agent/states/streaming.d.ts +10 -0
  112. package/dist/src/agent/states/streaming.js +169 -0
  113. package/dist/src/agent/states/streaming.js.map +1 -0
  114. package/dist/src/agent/states/thinking.d.ts +13 -0
  115. package/dist/src/agent/states/thinking.js +450 -0
  116. package/dist/src/agent/states/thinking.js.map +1 -0
  117. package/dist/src/agent/token-estimate.d.ts +31 -0
  118. package/dist/src/agent/token-estimate.js +34 -0
  119. package/dist/src/agent/token-estimate.js.map +1 -0
  120. package/dist/src/agent/token-estimate.test.d.ts +6 -0
  121. package/dist/src/agent/token-estimate.test.js +44 -0
  122. package/dist/src/agent/token-estimate.test.js.map +1 -0
  123. package/dist/src/agent/tool-executor-local.js +9 -18
  124. package/dist/src/agent/tool-executor-local.js.map +1 -1
  125. package/dist/src/agent/tool-executor-local.test.js +3 -5
  126. package/dist/src/agent/tool-executor-local.test.js.map +1 -1
  127. package/dist/src/api/create-agent.d.ts +15 -0
  128. package/dist/src/api/create-agent.js +134 -0
  129. package/dist/src/api/create-agent.js.map +1 -0
  130. package/dist/src/api/types.d.ts +66 -0
  131. package/dist/src/api/types.js +7 -0
  132. package/dist/src/api/types.js.map +1 -0
  133. package/dist/src/context/compiler.d.ts +13 -0
  134. package/dist/src/context/compiler.js +358 -0
  135. package/dist/src/context/compiler.js.map +1 -0
  136. package/dist/src/context/compiler.test.d.ts +6 -0
  137. package/dist/src/context/compiler.test.js +532 -0
  138. package/dist/src/context/compiler.test.js.map +1 -0
  139. package/dist/src/context/types.d.ts +110 -0
  140. package/dist/src/context/types.js +7 -0
  141. package/dist/src/context/types.js.map +1 -0
  142. package/dist/src/env-ref.d.ts +13 -0
  143. package/dist/src/env-ref.js +31 -0
  144. package/dist/src/env-ref.js.map +1 -0
  145. package/dist/src/env-ref.test.d.ts +6 -0
  146. package/dist/src/env-ref.test.js +34 -0
  147. package/dist/src/env-ref.test.js.map +1 -0
  148. package/dist/src/errors.d.ts +15 -0
  149. package/dist/src/errors.js +22 -0
  150. package/dist/src/errors.js.map +1 -1
  151. package/dist/src/errors.test.js +2 -2
  152. package/dist/src/errors.test.js.map +1 -1
  153. package/dist/src/events/event-bus.d.ts +54 -0
  154. package/dist/src/events/event-bus.js +84 -0
  155. package/dist/src/events/event-bus.js.map +1 -0
  156. package/dist/src/events/event-bus.test.d.ts +6 -0
  157. package/dist/src/events/event-bus.test.js +112 -0
  158. package/dist/src/events/event-bus.test.js.map +1 -0
  159. package/dist/src/events/events-route.d.ts +36 -0
  160. package/dist/src/events/events-route.js +80 -0
  161. package/dist/src/events/events-route.js.map +1 -0
  162. package/dist/src/events/events-route.test.d.ts +6 -0
  163. package/dist/src/events/events-route.test.js +134 -0
  164. package/dist/src/events/events-route.test.js.map +1 -0
  165. package/dist/src/events/store-event-wrapper.d.ts +19 -0
  166. package/dist/src/events/store-event-wrapper.js +57 -0
  167. package/dist/src/events/store-event-wrapper.js.map +1 -0
  168. package/dist/src/events/store-event-wrapper.test.d.ts +6 -0
  169. package/dist/src/events/store-event-wrapper.test.js +91 -0
  170. package/dist/src/events/store-event-wrapper.test.js.map +1 -0
  171. package/dist/src/index.d.ts +33 -6
  172. package/dist/src/index.js +35 -21
  173. package/dist/src/index.js.map +1 -1
  174. package/dist/src/middleware/auth.d.ts +0 -2
  175. package/dist/src/middleware/auth.js.map +1 -1
  176. package/dist/src/providers/create-provider.d.ts +23 -0
  177. package/dist/src/providers/create-provider.js +185 -0
  178. package/dist/src/providers/create-provider.js.map +1 -0
  179. package/dist/src/providers/create-provider.test.d.ts +6 -0
  180. package/dist/src/providers/create-provider.test.js +95 -0
  181. package/dist/src/providers/create-provider.test.js.map +1 -0
  182. package/dist/src/providers/failover.d.ts +38 -0
  183. package/dist/src/providers/failover.js +147 -0
  184. package/dist/src/providers/failover.js.map +1 -0
  185. package/dist/src/providers/failover.test.d.ts +6 -0
  186. package/dist/src/providers/failover.test.js +169 -0
  187. package/dist/src/providers/failover.test.js.map +1 -0
  188. package/dist/src/providers/search-provider.d.ts +64 -0
  189. package/dist/src/providers/search-provider.js +174 -0
  190. package/dist/src/providers/search-provider.js.map +1 -0
  191. package/dist/src/providers/types.d.ts +118 -0
  192. package/dist/src/providers/types.js +7 -0
  193. package/dist/src/providers/types.js.map +1 -0
  194. package/dist/src/routes/ai-stream.d.ts +28 -10
  195. package/dist/src/routes/ai-stream.js +85 -41
  196. package/dist/src/routes/ai-stream.js.map +1 -1
  197. package/dist/src/routes/chat-new.test.d.ts +6 -0
  198. package/dist/src/routes/chat-new.test.js +107 -0
  199. package/dist/src/routes/chat-new.test.js.map +1 -0
  200. package/dist/src/routes/chat-stream-new.test.d.ts +6 -0
  201. package/dist/src/routes/chat-stream-new.test.js +135 -0
  202. package/dist/src/routes/chat-stream-new.test.js.map +1 -0
  203. package/dist/src/routes/chat-stream.d.ts +20 -4
  204. package/dist/src/routes/chat-stream.js +49 -29
  205. package/dist/src/routes/chat-stream.js.map +1 -1
  206. package/dist/src/routes/chat.d.ts +19 -4
  207. package/dist/src/routes/chat.js +62 -23
  208. package/dist/src/routes/chat.js.map +1 -1
  209. package/dist/src/routes/health.d.ts +3 -2
  210. package/dist/src/routes/health.js.map +1 -1
  211. package/dist/src/routes/route-helpers.d.ts +50 -0
  212. package/dist/src/routes/route-helpers.js +80 -0
  213. package/dist/src/routes/route-helpers.js.map +1 -0
  214. package/dist/src/routes/session-resolver.d.ts +77 -0
  215. package/dist/src/routes/session-resolver.js +109 -0
  216. package/dist/src/routes/session-resolver.js.map +1 -0
  217. package/dist/src/routes/session-resolver.test.d.ts +6 -0
  218. package/dist/src/routes/session-resolver.test.js +207 -0
  219. package/dist/src/routes/session-resolver.test.js.map +1 -0
  220. package/dist/src/routes/webhooks.d.ts +3 -1
  221. package/dist/src/routes/webhooks.js +12 -4
  222. package/dist/src/routes/webhooks.js.map +1 -1
  223. package/dist/src/security/permission-checker.d.ts +80 -0
  224. package/dist/src/security/permission-checker.js +75 -0
  225. package/dist/src/security/permission-checker.js.map +1 -0
  226. package/dist/src/security/permission-checker.test.d.ts +6 -0
  227. package/dist/src/security/permission-checker.test.js +208 -0
  228. package/dist/src/security/permission-checker.test.js.map +1 -0
  229. package/dist/src/server.d.ts +18 -11
  230. package/dist/src/server.js +46 -46
  231. package/dist/src/server.js.map +1 -1
  232. package/dist/src/server.test.d.ts +1 -1
  233. package/dist/src/server.test.js +6 -144
  234. package/dist/src/server.test.js.map +1 -1
  235. package/dist/src/session/drizzle-session-store.d.ts +56 -0
  236. package/dist/src/session/drizzle-session-store.js +203 -0
  237. package/dist/src/session/drizzle-session-store.js.map +1 -0
  238. package/dist/src/session/manager.d.ts +101 -0
  239. package/dist/src/session/manager.js +394 -0
  240. package/dist/src/session/manager.js.map +1 -0
  241. package/dist/src/session/manager.test.d.ts +6 -0
  242. package/dist/src/session/manager.test.js +309 -0
  243. package/dist/src/session/manager.test.js.map +1 -0
  244. package/dist/src/session/pglite-session-store.d.ts +23 -0
  245. package/dist/src/session/pglite-session-store.js +70 -0
  246. package/dist/src/session/pglite-session-store.js.map +1 -0
  247. package/dist/src/session/postgres-session-store.d.ts +44 -0
  248. package/dist/src/session/postgres-session-store.js +138 -0
  249. package/dist/src/session/postgres-session-store.js.map +1 -0
  250. package/dist/src/session/session-builder.d.ts +69 -0
  251. package/dist/src/session/session-builder.js +384 -0
  252. package/dist/src/session/session-builder.js.map +1 -0
  253. package/dist/src/session/session-builder.test.d.ts +6 -0
  254. package/dist/src/session/session-builder.test.js +350 -0
  255. package/dist/src/session/session-builder.test.js.map +1 -0
  256. package/dist/src/session/session-store-selector.d.ts +49 -0
  257. package/dist/src/session/session-store-selector.js +60 -0
  258. package/dist/src/session/session-store-selector.js.map +1 -0
  259. package/dist/src/session/session-store-selector.test.d.ts +6 -0
  260. package/dist/src/session/session-store-selector.test.js +79 -0
  261. package/dist/src/session/session-store-selector.test.js.map +1 -0
  262. package/dist/src/session/store.d.ts +171 -0
  263. package/dist/src/session/store.js +155 -0
  264. package/dist/src/session/store.js.map +1 -0
  265. package/dist/src/session/store.test.d.ts +6 -0
  266. package/dist/src/session/store.test.js +423 -0
  267. package/dist/src/session/store.test.js.map +1 -0
  268. package/dist/src/session/stream-hooks.d.ts +39 -0
  269. package/dist/src/session/stream-hooks.js +7 -0
  270. package/dist/src/session/stream-hooks.js.map +1 -0
  271. package/dist/src/session/tool-context-factory.d.ts +61 -0
  272. package/dist/src/session/tool-context-factory.js +189 -0
  273. package/dist/src/session/tool-context-factory.js.map +1 -0
  274. package/dist/src/session/tool-context-factory.test.d.ts +6 -0
  275. package/dist/src/session/tool-context-factory.test.js +284 -0
  276. package/dist/src/session/tool-context-factory.test.js.map +1 -0
  277. package/dist/src/session/types.d.ts +195 -0
  278. package/dist/src/session/types.js +7 -0
  279. package/dist/src/session/types.js.map +1 -0
  280. package/dist/src/stores/drizzle-store-backend.d.ts +49 -0
  281. package/dist/src/stores/drizzle-store-backend.js +306 -0
  282. package/dist/src/stores/drizzle-store-backend.js.map +1 -0
  283. package/dist/src/stores/drizzle-store-backend.test.d.ts +6 -0
  284. package/dist/src/stores/drizzle-store-backend.test.js +215 -0
  285. package/dist/src/stores/drizzle-store-backend.test.js.map +1 -0
  286. package/dist/src/stores/index.d.ts +4 -0
  287. package/dist/src/stores/index.js +2 -0
  288. package/dist/src/stores/index.js.map +1 -1
  289. package/dist/src/stores/pglite-store-backend.d.ts +16 -19
  290. package/dist/src/stores/pglite-store-backend.js +85 -239
  291. package/dist/src/stores/pglite-store-backend.js.map +1 -1
  292. package/dist/src/stores/postgres-store-backend.d.ts +30 -0
  293. package/dist/src/stores/postgres-store-backend.js +100 -0
  294. package/dist/src/stores/postgres-store-backend.js.map +1 -0
  295. package/dist/src/stores/schema.d.ts +457 -0
  296. package/dist/src/stores/schema.js +59 -0
  297. package/dist/src/stores/schema.js.map +1 -0
  298. package/dist/src/tools/admin-file-tools.d.ts +42 -0
  299. package/dist/src/tools/admin-file-tools.js +714 -0
  300. package/dist/src/tools/admin-file-tools.js.map +1 -0
  301. package/dist/src/tools/admin-file-tools.test.d.ts +6 -0
  302. package/dist/src/tools/admin-file-tools.test.js +521 -0
  303. package/dist/src/tools/admin-file-tools.test.js.map +1 -0
  304. package/dist/src/tools/custom-tool-adapter.d.ts +41 -0
  305. package/dist/src/tools/custom-tool-adapter.js +190 -0
  306. package/dist/src/tools/custom-tool-adapter.js.map +1 -0
  307. package/dist/src/tools/custom-tool-adapter.test.d.ts +6 -0
  308. package/dist/src/tools/custom-tool-adapter.test.js +243 -0
  309. package/dist/src/tools/custom-tool-adapter.test.js.map +1 -0
  310. package/dist/src/tools/dispatch-tool.d.ts +52 -0
  311. package/dist/src/tools/dispatch-tool.js +71 -0
  312. package/dist/src/tools/dispatch-tool.js.map +1 -0
  313. package/dist/src/tools/dispatch-tool.test.d.ts +6 -0
  314. package/dist/src/tools/dispatch-tool.test.js +75 -0
  315. package/dist/src/tools/dispatch-tool.test.js.map +1 -0
  316. package/dist/src/tools/fetch-url-tool.d.ts +23 -0
  317. package/dist/src/tools/fetch-url-tool.js +333 -0
  318. package/dist/src/tools/fetch-url-tool.js.map +1 -0
  319. package/dist/src/tools/fetch-url-tool.test.d.ts +6 -0
  320. package/dist/src/tools/fetch-url-tool.test.js +228 -0
  321. package/dist/src/tools/fetch-url-tool.test.js.map +1 -0
  322. package/dist/src/tools/mcp-tool-adapter.d.ts +18 -0
  323. package/dist/src/tools/mcp-tool-adapter.js +135 -0
  324. package/dist/src/tools/mcp-tool-adapter.js.map +1 -0
  325. package/dist/src/tools/mcp-tool-adapter.test.d.ts +6 -0
  326. package/dist/src/tools/mcp-tool-adapter.test.js +226 -0
  327. package/dist/src/tools/mcp-tool-adapter.test.js.map +1 -0
  328. package/dist/src/tools/registry.d.ts +25 -0
  329. package/dist/src/tools/registry.js +72 -0
  330. package/dist/src/tools/registry.js.map +1 -0
  331. package/dist/src/tools/registry.test.d.ts +6 -0
  332. package/dist/src/tools/registry.test.js +120 -0
  333. package/dist/src/tools/registry.test.js.map +1 -0
  334. package/dist/src/tools/request-tool.d.ts +42 -0
  335. package/dist/src/tools/request-tool.js +190 -0
  336. package/dist/src/tools/request-tool.js.map +1 -0
  337. package/dist/src/tools/request-tool.test.d.ts +6 -0
  338. package/dist/src/tools/request-tool.test.js +253 -0
  339. package/dist/src/tools/request-tool.test.js.map +1 -0
  340. package/dist/src/tools/store-tools.d.ts +29 -0
  341. package/dist/src/tools/store-tools.js +224 -0
  342. package/dist/src/tools/store-tools.js.map +1 -0
  343. package/dist/src/tools/store-tools.test.d.ts +6 -0
  344. package/dist/src/tools/store-tools.test.js +215 -0
  345. package/dist/src/tools/store-tools.test.js.map +1 -0
  346. package/dist/src/tools/types.d.ts +129 -0
  347. package/dist/src/tools/types.js +7 -0
  348. package/dist/src/tools/types.js.map +1 -0
  349. package/dist/src/tools/web-search-tool.d.ts +31 -0
  350. package/dist/src/tools/web-search-tool.js +170 -0
  351. package/dist/src/tools/web-search-tool.js.map +1 -0
  352. package/dist/src/tools/web-search-tool.test.d.ts +6 -0
  353. package/dist/src/tools/web-search-tool.test.js +153 -0
  354. package/dist/src/tools/web-search-tool.test.js.map +1 -0
  355. package/dist/src/tools/web-tools-shared.d.ts +21 -0
  356. package/dist/src/tools/web-tools-shared.js +32 -0
  357. package/dist/src/tools/web-tools-shared.js.map +1 -0
  358. package/dist/src/types.d.ts +40 -12
  359. package/dist/src/types.js +16 -2
  360. package/dist/src/types.js.map +1 -1
  361. package/dist/tsconfig.tsbuildinfo +1 -1
  362. package/package.json +27 -4
  363. package/dist/src/__tests__/sse-contract.test.js +0 -464
  364. package/dist/src/__tests__/sse-contract.test.js.map +0 -1
  365. package/dist/src/__tests__/tools.test.js +0 -583
  366. package/dist/src/__tests__/tools.test.js.map +0 -1
  367. package/dist/src/agent/agent-runner.d.ts +0 -33
  368. package/dist/src/agent/agent-runner.js +0 -1040
  369. package/dist/src/agent/agent-runner.js.map +0 -1
  370. package/dist/src/agent/custom-tools-e2e.test.d.ts +0 -6
  371. package/dist/src/agent/custom-tools-e2e.test.js +0 -566
  372. package/dist/src/agent/custom-tools-e2e.test.js.map +0 -1
  373. package/dist/src/agent/request-helper.d.ts +0 -16
  374. package/dist/src/agent/request-helper.js +0 -96
  375. package/dist/src/agent/request-helper.js.map +0 -1
  376. package/dist/src/agent/session-store.d.ts +0 -62
  377. package/dist/src/agent/session-store.js +0 -151
  378. package/dist/src/agent/session-store.js.map +0 -1
  379. package/dist/src/agent/stores-e2e.test.js +0 -433
  380. package/dist/src/agent/stores-e2e.test.js.map +0 -1
  381. package/dist/src/agent/tool-context-builder.d.ts +0 -11
  382. package/dist/src/agent/tool-context-builder.js +0 -102
  383. package/dist/src/agent/tool-context-builder.js.map +0 -1
  384. package/dist/src/agent/tool-context-builder.test.d.ts +0 -6
  385. package/dist/src/agent/tool-context-builder.test.js +0 -152
  386. package/dist/src/agent/tool-context-builder.test.js.map +0 -1
  387. package/dist/src/agent/write-repo-file.test.js +0 -270
  388. package/dist/src/agent/write-repo-file.test.js.map +0 -1
  389. package/dist/src/cron/heartbeat-runner.d.ts +0 -21
  390. package/dist/src/cron/heartbeat-runner.js +0 -79
  391. package/dist/src/cron/heartbeat-runner.js.map +0 -1
  392. package/dist/src/cron/heartbeat-runner.test.d.ts +0 -6
  393. package/dist/src/cron/heartbeat-runner.test.js +0 -120
  394. package/dist/src/cron/heartbeat-runner.test.js.map +0 -1
  395. package/dist/src/cron/heartbeat-scheduler.d.ts +0 -26
  396. package/dist/src/cron/heartbeat-scheduler.js +0 -55
  397. package/dist/src/cron/heartbeat-scheduler.js.map +0 -1
  398. package/dist/src/cron/heartbeat-scheduler.test.d.ts +0 -6
  399. package/dist/src/cron/heartbeat-scheduler.test.js +0 -61
  400. package/dist/src/cron/heartbeat-scheduler.test.js.map +0 -1
  401. package/dist/src/routes/ai-stream.test.d.ts +0 -6
  402. package/dist/src/routes/ai-stream.test.js +0 -586
  403. package/dist/src/routes/ai-stream.test.js.map +0 -1
  404. package/dist/src/routes/ask-user-response.d.ts +0 -30
  405. package/dist/src/routes/ask-user-response.js +0 -61
  406. package/dist/src/routes/ask-user-response.js.map +0 -1
  407. package/dist/src/routes/ask-user-response.test.d.ts +0 -6
  408. package/dist/src/routes/ask-user-response.test.js +0 -88
  409. package/dist/src/routes/ask-user-response.test.js.map +0 -1
  410. package/dist/src/routes/chat-stream.test.d.ts +0 -6
  411. package/dist/src/routes/chat-stream.test.js +0 -155
  412. package/dist/src/routes/chat-stream.test.js.map +0 -1
  413. package/dist/src/routes/chat.test.d.ts +0 -6
  414. package/dist/src/routes/chat.test.js +0 -99
  415. package/dist/src/routes/chat.test.js.map +0 -1
  416. package/dist/src/routes/widget-actions.d.ts +0 -49
  417. package/dist/src/routes/widget-actions.js +0 -78
  418. package/dist/src/routes/widget-actions.js.map +0 -1
  419. package/dist/src/session/admin-file-tools.d.ts +0 -136
  420. package/dist/src/session/admin-file-tools.js +0 -240
  421. package/dist/src/session/admin-file-tools.js.map +0 -1
  422. package/dist/src/session/custom-tool-adapter.d.ts +0 -74
  423. package/dist/src/session/custom-tool-adapter.js +0 -180
  424. package/dist/src/session/custom-tool-adapter.js.map +0 -1
  425. package/dist/src/session/history-converter.d.ts +0 -21
  426. package/dist/src/session/history-converter.js +0 -59
  427. package/dist/src/session/history-converter.js.map +0 -1
  428. package/dist/src/session/history-converter.test.d.ts +0 -6
  429. package/dist/src/session/history-converter.test.js +0 -130
  430. package/dist/src/session/history-converter.test.js.map +0 -1
  431. package/dist/src/session/session-manager.d.ts +0 -219
  432. package/dist/src/session/session-manager.js +0 -915
  433. package/dist/src/session/session-manager.js.map +0 -1
  434. package/dist/src/session/session-manager.test.d.ts +0 -6
  435. package/dist/src/session/session-manager.test.js +0 -455
  436. package/dist/src/session/session-manager.test.js.map +0 -1
  437. package/dist/src/session/session-runner.d.ts +0 -45
  438. package/dist/src/session/session-runner.js +0 -719
  439. package/dist/src/session/session-runner.js.map +0 -1
  440. package/dist/src/session/session-runner.test.d.ts +0 -6
  441. package/dist/src/session/session-runner.test.js +0 -834
  442. package/dist/src/session/session-runner.test.js.map +0 -1
  443. /package/dist/src/{__tests__/sse-contract.test.d.ts → __fixtures__/e2e.test.d.ts} +0 -0
  444. /package/dist/src/{__tests__/tools.test.d.ts → __fixtures__/smoke.test.d.ts} +0 -0
  445. /package/dist/src/agent/{write-repo-file.test.d.ts → loop.test.d.ts} +0 -0
@@ -0,0 +1,169 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * Provider Failover Tests
8
+ *
9
+ * Integration tests against real providers (skipped when API keys are
10
+ * not available). No mocks — calls the real AI SDK through the real
11
+ * createProvider → createFailoverProvider chain.
12
+ *
13
+ * Scenarios:
14
+ * 1. Primary with invalid key + fallback with valid key → response from fallback
15
+ * 2. Valid primary → uses primary, no fallback
16
+ * 3. All providers fail → throws ProviderError with context about all attempts
17
+ */
18
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
19
+ import { createFailoverProvider } from './failover.js';
20
+ import { ProviderError } from '../errors.js';
21
+ import { testProviders, hasAnyProvider } from '../__tests__/test-providers.js';
22
+ // ---------------------------------------------------------------------------
23
+ // Helpers
24
+ // ---------------------------------------------------------------------------
25
+ function makeMockLogger() {
26
+ return {
27
+ trace: vi.fn(),
28
+ debug: vi.fn(),
29
+ info: vi.fn(),
30
+ warn: vi.fn(),
31
+ error: vi.fn(),
32
+ fatal: vi.fn(),
33
+ child: vi.fn().mockReturnThis(),
34
+ };
35
+ }
36
+ // ---------------------------------------------------------------------------
37
+ // Unit tests (no API calls)
38
+ // ---------------------------------------------------------------------------
39
+ describe('createFailoverProvider (unit)', () => {
40
+ let logger;
41
+ beforeEach(() => {
42
+ logger = makeMockLogger();
43
+ });
44
+ it('exposes primary model and provider on the returned object', () => {
45
+ const provider = createFailoverProvider({
46
+ primary: { provider: 'anthropic', model: 'claude-sonnet-4-20250514', apiKey: 'fake' },
47
+ fallbacks: [{ provider: 'openai', model: 'gpt-4o', apiKey: 'fake' }],
48
+ logger,
49
+ });
50
+ expect(provider.model).toBe('claude-sonnet-4-20250514');
51
+ expect(provider.provider).toBe('anthropic');
52
+ expect(provider.languageModel).toBeDefined();
53
+ expect(typeof provider.streamText).toBe('function');
54
+ expect(typeof provider.generateText).toBe('function');
55
+ });
56
+ it('works with a single provider (no fallbacks)', () => {
57
+ const provider = createFailoverProvider({
58
+ primary: { provider: 'anthropic', model: 'claude-sonnet-4-20250514', apiKey: 'fake' },
59
+ logger,
60
+ });
61
+ expect(provider.model).toBe('claude-sonnet-4-20250514');
62
+ });
63
+ });
64
+ // ---------------------------------------------------------------------------
65
+ // Integration tests (real API calls — skipped without keys)
66
+ // ---------------------------------------------------------------------------
67
+ describe.skipIf(!hasAnyProvider)('createFailoverProvider (integration)', () => {
68
+ let logger;
69
+ beforeEach(() => {
70
+ logger = makeMockLogger();
71
+ });
72
+ // ── 1. Primary fails (invalid key) + fallback succeeds ────────────────
73
+ it('uses fallback when primary has invalid API key', async () => {
74
+ const fallback = testProviders.cheapest();
75
+ const invalid = testProviders.invalid(fallback.provider);
76
+ const provider = createFailoverProvider({
77
+ primary: invalid,
78
+ fallbacks: [fallback],
79
+ logger,
80
+ sessionId: 'test-failover',
81
+ });
82
+ const result = await provider.generateText({
83
+ messages: [{ role: 'user', content: [{ type: 'text', text: 'Reply with exactly: pong' }] }],
84
+ maxOutputTokens: 10,
85
+ });
86
+ expect(result.text.toLowerCase()).toContain('pong');
87
+ expect(result.usage.inputTokens).toBeGreaterThan(0);
88
+ expect(result.usage.outputTokens).toBeGreaterThan(0);
89
+ expect(logger.error).toHaveBeenCalledWith('provider_call_failed', expect.objectContaining({ session: 'test-failover', willRetry: true }));
90
+ expect(logger.warn).toHaveBeenCalledWith('provider_failover_used', expect.objectContaining({
91
+ succeeded: `${fallback.provider}/${fallback.model}`,
92
+ }));
93
+ }, 30000);
94
+ // ── 2. Valid primary → uses primary, no fallback ──────────────────────
95
+ it('uses primary when it succeeds — fallback not touched', async () => {
96
+ const primary = testProviders.cheapest();
97
+ const provider = createFailoverProvider({
98
+ primary,
99
+ // Fallback has invalid key — would fail if reached
100
+ fallbacks: [testProviders.invalid(primary.provider)],
101
+ logger,
102
+ });
103
+ const result = await provider.generateText({
104
+ messages: [{ role: 'user', content: [{ type: 'text', text: 'Reply with exactly: ping' }] }],
105
+ maxOutputTokens: 10,
106
+ });
107
+ expect(result.text.toLowerCase()).toContain('ping');
108
+ expect(logger.error).not.toHaveBeenCalled();
109
+ expect(logger.warn).not.toHaveBeenCalled();
110
+ }, 30000);
111
+ // ── 3. All providers fail → ProviderError with all attempts ───────────
112
+ it('throws ProviderError with context about all failed attempts', async () => {
113
+ const provider = createFailoverProvider({
114
+ primary: testProviders.invalid('anthropic'),
115
+ fallbacks: [testProviders.invalid('openai')],
116
+ logger,
117
+ sessionId: 'test-all-fail',
118
+ });
119
+ try {
120
+ await provider.generateText({
121
+ messages: [{ role: 'user', content: [{ type: 'text', text: 'hello' }] }],
122
+ maxOutputTokens: 10,
123
+ });
124
+ expect.unreachable('should have thrown');
125
+ }
126
+ catch (err) {
127
+ expect(err).toBeInstanceOf(ProviderError);
128
+ const pe = err;
129
+ expect(pe.message).toBe('All providers failed');
130
+ expect(pe.provider).toBe('failover');
131
+ const attempts = pe.context['attempts'];
132
+ expect(attempts).toHaveLength(2);
133
+ expect(attempts[0].provider).toBe('anthropic');
134
+ expect(attempts[1].provider).toBe('openai');
135
+ }
136
+ expect(logger.error).toHaveBeenCalledTimes(2);
137
+ expect(logger.error).toHaveBeenCalledWith('provider_call_failed', expect.objectContaining({ session: 'test-all-fail', willRetry: true }));
138
+ expect(logger.error).toHaveBeenCalledWith('provider_call_failed', expect.objectContaining({ willRetry: false }));
139
+ }, 30000);
140
+ // ── 4. Streaming failover ─────────────────────────────────────────────
141
+ it('streaming: uses fallback when primary stream fails', async () => {
142
+ const fallback = testProviders.cheapest();
143
+ const invalid = testProviders.invalid(fallback.provider);
144
+ const provider = createFailoverProvider({
145
+ primary: invalid,
146
+ fallbacks: [fallback],
147
+ logger,
148
+ });
149
+ const result = provider.streamText({
150
+ messages: [{ role: 'user', content: [{ type: 'text', text: 'Reply with exactly: stream-ok' }] }],
151
+ maxOutputTokens: 10,
152
+ });
153
+ const events = [];
154
+ for await (const event of result.fullStream) {
155
+ events.push(event);
156
+ }
157
+ const textDeltas = events.filter((e) => e.type === 'text-delta');
158
+ expect(textDeltas.length).toBeGreaterThan(0);
159
+ const text = await result.text;
160
+ expect(text.length).toBeGreaterThan(0);
161
+ const usage = await result.usage;
162
+ expect(usage.inputTokens).toBeGreaterThan(0);
163
+ expect(logger.error).toHaveBeenCalledWith('provider_call_failed', expect.objectContaining({ willRetry: true }));
164
+ expect(logger.warn).toHaveBeenCalledWith('provider_failover_used', expect.objectContaining({
165
+ succeeded: `${fallback.provider}/${fallback.model}`,
166
+ }));
167
+ }, 30000);
168
+ });
169
+ //# sourceMappingURL=failover.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failover.test.js","sourceRoot":"","sources":["../../../src/providers/failover.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import type { WebToolsConfig } from '@amodalai/types';
7
+ /** Default Gemini model for search + urlContext when none is configured. */
8
+ export declare const DEFAULT_SEARCH_MODEL = "gemini-3-flash-preview";
9
+ /** A single grounded source citation (from googleSearch or urlContext). */
10
+ export interface SearchSource {
11
+ /** Fully-qualified source URL. */
12
+ uri: string;
13
+ /** Human-readable title if the provider supplied one. */
14
+ title?: string;
15
+ }
16
+ /** Result of a grounded search query. */
17
+ export interface SearchResult {
18
+ /** Synthesized answer text from the model. */
19
+ text: string;
20
+ /** Source URLs the answer was grounded in (may be empty). */
21
+ sources: SearchSource[];
22
+ }
23
+ /** Result of a grounded URL fetch. */
24
+ export interface FetchResult {
25
+ /** Extracted page content as markdown (or summary if `prompt` was provided). */
26
+ text: string;
27
+ /** URLs that were actually retrieved by urlContext (usually 1, may be 0 on failure). */
28
+ retrievedUrls: string[];
29
+ }
30
+ /** Options for a single search call. */
31
+ export interface SearchOptions {
32
+ /** Abort signal for cancellation/timeout. */
33
+ signal?: AbortSignal;
34
+ }
35
+ /** Options for a single fetch call. */
36
+ export interface FetchOptions {
37
+ /** Extraction prompt — what to pull from the page. Defaults to "render as markdown". */
38
+ prompt?: string;
39
+ /** Abort signal for cancellation/timeout. */
40
+ signal?: AbortSignal;
41
+ }
42
+ /**
43
+ * Narrow, purpose-specific interface for grounded search + fetch.
44
+ *
45
+ * Not an `LLMProvider` — it returns grounding metadata that `LLMProvider`
46
+ * doesn't surface. Tool executors (`web_search`, `fetch_url`) depend on
47
+ * this interface, not on the concrete AI SDK types.
48
+ */
49
+ export interface SearchProvider {
50
+ /** Run a grounded search query. */
51
+ search(query: string, opts?: SearchOptions): Promise<SearchResult>;
52
+ /** Fetch + extract content from a URL using urlContext grounding. */
53
+ fetchUrl(url: string, opts?: FetchOptions): Promise<FetchResult>;
54
+ /** Model identifier used for introspection/logging. */
55
+ readonly model: string;
56
+ }
57
+ /**
58
+ * Create a SearchProvider from webTools config.
59
+ *
60
+ * Throws `ConfigError` when the provider string is unsupported. All
61
+ * current config values go through Zod validation at load time, so this
62
+ * is defensive rather than user-facing.
63
+ */
64
+ export declare function createSearchProvider(config: WebToolsConfig): SearchProvider;
@@ -0,0 +1,174 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * Search provider: dedicated Gemini Flash instance for web_search + fetch_url.
8
+ *
9
+ * This is SEPARATE from the main LLM provider. Regardless of what model the
10
+ * agent is using (Anthropic/OpenAI/Google), web search and URL fetch always
11
+ * route through a Gemini Flash call with Google Search + urlContext grounding
12
+ * enabled. That gives us synthesized answers with cited URLs without paying
13
+ * the main-model rate and without coupling search to the main provider.
14
+ *
15
+ * Deviation from the implementation plan: the plan said to return an
16
+ * `LLMProvider` wrapper, but `LLMProvider.generateText` doesn't expose
17
+ * `providerMetadata`, which is where grounding sources live. Rather than
18
+ * pollute `LLMProvider` with Google-specific fields, we return a narrow
19
+ * purpose-specific interface with `search()` and `fetchUrl()` methods that
20
+ * yield `{ text, sources }` shaped results.
21
+ */
22
+ import { generateText } from 'ai';
23
+ import { createGoogleGenerativeAI } from '@ai-sdk/google';
24
+ import { ConfigError, ProviderError } from '../errors.js';
25
+ // ---------------------------------------------------------------------------
26
+ // Constants
27
+ // ---------------------------------------------------------------------------
28
+ /** Default Gemini model for search + urlContext when none is configured. */
29
+ export const DEFAULT_SEARCH_MODEL = 'gemini-3-flash-preview';
30
+ /**
31
+ * Preamble prepended to every grounded search query. Biases Gemini toward
32
+ * authoritative sources and precise citation. ~30 tokens per call.
33
+ */
34
+ const SEARCH_SYSTEM_PREAMBLE = 'Prefer authoritative sources: official documentation, GitHub, package registries, release notes. ' +
35
+ 'When asked for a version number, date, or other exact value, cite it directly from the source. ' +
36
+ 'If sources disagree, say so.';
37
+ /** Tool names required by the Google provider — must match SDK expectations. */
38
+ const GOOGLE_SEARCH_TOOL_NAME = 'google_search';
39
+ const URL_CONTEXT_TOOL_NAME = 'url_context';
40
+ function extractGoogleMetadata(providerMetadata) {
41
+ if (!providerMetadata)
42
+ return undefined;
43
+ const google = providerMetadata['google'];
44
+ if (!google || typeof google !== 'object')
45
+ return undefined;
46
+ return google;
47
+ }
48
+ function extractSources(metadata) {
49
+ const chunks = metadata?.groundingMetadata?.groundingChunks;
50
+ if (!Array.isArray(chunks))
51
+ return [];
52
+ const sources = [];
53
+ for (const chunk of chunks) {
54
+ const uri = chunk.web?.uri;
55
+ if (typeof uri === 'string' && uri.length > 0) {
56
+ sources.push({
57
+ uri,
58
+ ...(chunk.web?.title ? { title: chunk.web.title } : {}),
59
+ });
60
+ }
61
+ }
62
+ return sources;
63
+ }
64
+ /**
65
+ * Extract an HTTP status code from an AI SDK error if present. The SDK wraps
66
+ * provider failures in `AI_APICallError` which carries `statusCode`. We use
67
+ * this to classify failures into auth/quota/transient for the tool executors.
68
+ */
69
+ function extractStatusCode(err) {
70
+ if (err && typeof err === 'object' && 'statusCode' in err) {
71
+ const code = err.statusCode;
72
+ if (typeof code === 'number')
73
+ return code;
74
+ }
75
+ // Error wrapper — check cause
76
+ if (err instanceof Error && err.cause)
77
+ return extractStatusCode(err.cause);
78
+ return undefined;
79
+ }
80
+ function extractRetrievedUrls(metadata) {
81
+ const entries = metadata?.urlContextMetadata?.urlMetadata;
82
+ if (!Array.isArray(entries))
83
+ return [];
84
+ const urls = [];
85
+ for (const entry of entries) {
86
+ if (typeof entry.retrievedUrl === 'string' && entry.retrievedUrl.length > 0) {
87
+ urls.push(entry.retrievedUrl);
88
+ }
89
+ }
90
+ return urls;
91
+ }
92
+ // ---------------------------------------------------------------------------
93
+ // Factory
94
+ // ---------------------------------------------------------------------------
95
+ /**
96
+ * Create a SearchProvider from webTools config.
97
+ *
98
+ * Throws `ConfigError` when the provider string is unsupported. All
99
+ * current config values go through Zod validation at load time, so this
100
+ * is defensive rather than user-facing.
101
+ */
102
+ export function createSearchProvider(config) {
103
+ if (config.provider !== 'google') {
104
+ throw new ConfigError(`Unsupported webTools provider: ${config.provider}`, {
105
+ key: 'webTools.provider',
106
+ suggestion: 'Only "google" is supported today.',
107
+ });
108
+ }
109
+ const google = createGoogleGenerativeAI({ apiKey: config.apiKey });
110
+ const modelId = config.model ?? DEFAULT_SEARCH_MODEL;
111
+ const model = google(modelId);
112
+ return {
113
+ model: modelId,
114
+ async search(query, opts) {
115
+ try {
116
+ const result = await generateText({
117
+ model,
118
+ system: SEARCH_SYSTEM_PREAMBLE,
119
+ prompt: query,
120
+ tools: {
121
+ [GOOGLE_SEARCH_TOOL_NAME]: google.tools.googleSearch({}),
122
+ },
123
+ ...(opts?.signal ? { abortSignal: opts.signal } : {}),
124
+ });
125
+ const metadata = extractGoogleMetadata(result.providerMetadata);
126
+ return {
127
+ text: result.text,
128
+ sources: extractSources(metadata),
129
+ };
130
+ }
131
+ catch (err) {
132
+ const statusCode = extractStatusCode(err);
133
+ throw new ProviderError('Grounded search failed', {
134
+ provider: 'google',
135
+ ...(statusCode !== undefined ? { statusCode } : {}),
136
+ retryable: statusCode !== undefined && statusCode >= 500,
137
+ context: { model: modelId, operation: 'search' },
138
+ cause: err,
139
+ });
140
+ }
141
+ },
142
+ async fetchUrl(url, opts) {
143
+ const prompt = opts?.prompt
144
+ ? `Fetch ${url} and ${opts.prompt}. Respond with the result.`
145
+ : `Fetch ${url} and render the page content as markdown. Preserve headings, links, and lists.`;
146
+ try {
147
+ const result = await generateText({
148
+ model,
149
+ prompt,
150
+ tools: {
151
+ [URL_CONTEXT_TOOL_NAME]: google.tools.urlContext({}),
152
+ },
153
+ ...(opts?.signal ? { abortSignal: opts.signal } : {}),
154
+ });
155
+ const metadata = extractGoogleMetadata(result.providerMetadata);
156
+ return {
157
+ text: result.text,
158
+ retrievedUrls: extractRetrievedUrls(metadata),
159
+ };
160
+ }
161
+ catch (err) {
162
+ const statusCode = extractStatusCode(err);
163
+ throw new ProviderError('Grounded URL fetch failed', {
164
+ provider: 'google',
165
+ ...(statusCode !== undefined ? { statusCode } : {}),
166
+ retryable: statusCode !== undefined && statusCode >= 500,
167
+ context: { model: modelId, operation: 'fetchUrl', url },
168
+ cause: err,
169
+ });
170
+ }
171
+ },
172
+ };
173
+ }
174
+ //# sourceMappingURL=search-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-provider.js","sourceRoot":"","sources":["../../../src/providers/search-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * Provider abstraction wrapping the Vercel AI SDK.
8
+ *
9
+ * This is the boundary between Amodal code and the AI SDK. The rest of
10
+ * the runtime talks to LLMProvider, never to the SDK directly. This lets
11
+ * us swap SDK versions, add new providers, or intercept calls (logging,
12
+ * retries, cost tracking) in one place.
13
+ */
14
+ import type { LanguageModel, ModelMessage, Tool, ToolChoice, ToolSet } from 'ai';
15
+ export interface StreamTextOptions {
16
+ messages: ModelMessage[];
17
+ system?: string;
18
+ tools?: Record<string, Tool>;
19
+ toolChoice?: ToolChoice<ToolSet>;
20
+ maxOutputTokens?: number;
21
+ temperature?: number;
22
+ abortSignal?: AbortSignal;
23
+ }
24
+ export interface GenerateTextOptions {
25
+ messages: ModelMessage[];
26
+ system?: string;
27
+ tools?: Record<string, Tool>;
28
+ toolChoice?: ToolChoice<ToolSet>;
29
+ maxOutputTokens?: number;
30
+ temperature?: number;
31
+ abortSignal?: AbortSignal;
32
+ }
33
+ export interface TokenUsage {
34
+ inputTokens: number;
35
+ outputTokens: number;
36
+ cachedInputTokens?: number;
37
+ cacheCreationInputTokens?: number;
38
+ totalTokens: number;
39
+ }
40
+ export interface StreamTextResult {
41
+ /** The full text stream — yields string chunks */
42
+ textStream: AsyncIterable<string>;
43
+ /** The full event stream — yields structured events including tool calls */
44
+ fullStream: AsyncIterable<StreamEvent>;
45
+ /** Resolves when the stream is complete with final usage */
46
+ usage: PromiseLike<TokenUsage>;
47
+ /** Resolves with the complete response text */
48
+ text: PromiseLike<string>;
49
+ }
50
+ export type StreamEvent = {
51
+ type: 'text-delta';
52
+ textDelta: string;
53
+ } | {
54
+ type: 'tool-call';
55
+ toolCallId: string;
56
+ toolName: string;
57
+ args: Record<string, unknown>;
58
+ } | {
59
+ type: 'tool-result';
60
+ toolCallId: string;
61
+ toolName: string;
62
+ result: unknown;
63
+ } | {
64
+ type: 'finish';
65
+ usage: TokenUsage;
66
+ } | {
67
+ type: 'error';
68
+ error: unknown;
69
+ };
70
+ export interface GenerateTextResult {
71
+ text: string;
72
+ toolCalls: Array<{
73
+ toolCallId: string;
74
+ toolName: string;
75
+ args: Record<string, unknown>;
76
+ }>;
77
+ usage: TokenUsage;
78
+ finishReason: 'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other';
79
+ }
80
+ /**
81
+ * Unified LLM provider interface.
82
+ *
83
+ * Wraps the Vercel AI SDK so the rest of the runtime never imports `ai`
84
+ * directly. Implementations exist for Anthropic, OpenAI, Google, and
85
+ * any OpenAI-compatible provider (DeepSeek, Groq, Mistral, etc.).
86
+ */
87
+ export interface LLMProvider {
88
+ /** Stream a text/tool response from the LLM */
89
+ streamText(opts: StreamTextOptions): StreamTextResult;
90
+ /** Generate a complete text response (non-streaming) */
91
+ generateText(opts: GenerateTextOptions): Promise<GenerateTextResult>;
92
+ /** The model identifier (e.g., 'claude-sonnet-4-20250514') */
93
+ readonly model: string;
94
+ /** The provider name (e.g., 'anthropic', 'openai', 'google') */
95
+ readonly provider: string;
96
+ /** The underlying AI SDK LanguageModel instance (for advanced use) */
97
+ readonly languageModel: LanguageModel;
98
+ /**
99
+ * Optional provider-native token counter. When implemented, the runtime
100
+ * uses this to decide when to compact context (more accurate than the
101
+ * default 4-chars-per-token heuristic). Implementations should be cheap
102
+ * and synchronous — return an estimate based on a local tokenizer, not
103
+ * an API call.
104
+ */
105
+ countTokens?(messages: ModelMessage[]): number;
106
+ }
107
+ export interface ProviderConfig {
108
+ /** Provider name: 'anthropic', 'openai', 'google', 'deepseek', etc. */
109
+ provider: string;
110
+ /** Model name: 'claude-sonnet-4-20250514', 'gpt-4o', etc. */
111
+ model: string;
112
+ /** API key (resolved from env or credentials) */
113
+ apiKey?: string;
114
+ /** Custom base URL (for self-hosted or proxy endpoints) */
115
+ baseUrl?: string;
116
+ /** AWS region (for Bedrock) */
117
+ region?: string;
118
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/providers/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -1,14 +1,14 @@
1
1
  /**
2
2
  * @license
3
- * Copyright 2025 Amodal Labs, Inc.
3
+ * Copyright 2026 Amodal Labs, Inc.
4
4
  * SPDX-License-Identifier: MIT
5
5
  */
6
6
  /**
7
7
  * Vercel AI SDK UI Message Stream Protocol adapter.
8
8
  *
9
9
  * Accepts requests in the Vercel AI SDK format, feeds the user message into
10
- * the existing `streamMessage()` async generator, and translates every
11
- * `SSEEvent` into the UI Message Stream Protocol that `@ai-sdk/react`'s
10
+ * the standalone session manager's `runMessage()` generator, and translates
11
+ * every `SSEEvent` into the UI Message Stream Protocol that `@ai-sdk/react`'s
12
12
  * `useChat` hook expects.
13
13
  *
14
14
  * Protocol spec: events are newline-delimited JSON objects prefixed with
@@ -18,9 +18,10 @@
18
18
  import { Router } from 'express';
19
19
  import { z } from 'zod';
20
20
  import type { AuthContext } from '../middleware/auth.js';
21
- import type { SessionManager } from '../session/session-manager.js';
22
- import { type StreamHooks } from '../session/session-runner.js';
21
+ import type { StandaloneSessionManager } from '../session/manager.js';
22
+ import type { StreamHooks } from '../session/stream-hooks.js';
23
23
  import { type SSEEvent } from '../types.js';
24
+ import type { BundleResolver, SharedResources } from './session-resolver.js';
24
25
  export declare const AIStreamRequestSchema: z.ZodObject<{
25
26
  messages: z.ZodArray<z.ZodObject<{
26
27
  role: z.ZodEnum<["user", "assistant", "system"]>;
@@ -36,14 +37,14 @@ export declare const AIStreamRequestSchema: z.ZodObject<{
36
37
  }>, "many">>;
37
38
  content: z.ZodOptional<z.ZodString>;
38
39
  }, "strip", z.ZodTypeAny, {
39
- role: "user" | "assistant" | "system";
40
+ role: "system" | "user" | "assistant";
40
41
  content?: string | undefined;
41
42
  parts?: {
42
43
  type: string;
43
44
  text?: string | undefined;
44
45
  }[] | undefined;
45
46
  }, {
46
- role: "user" | "assistant" | "system";
47
+ role: "system" | "user" | "assistant";
47
48
  content?: string | undefined;
48
49
  parts?: {
49
50
  type: string;
@@ -53,9 +54,16 @@ export declare const AIStreamRequestSchema: z.ZodObject<{
53
54
  session_id: z.ZodOptional<z.ZodString>;
54
55
  role: z.ZodOptional<z.ZodString>;
55
56
  deploy_id: z.ZodOptional<z.ZodString>;
57
+ /**
58
+ * Optional session-wide **token** budget cap (cumulative across all
59
+ * turns; soft ceiling — single turns can overshoot by maxOutputTokens
60
+ * + tool result sizes). Applied only when this request creates a new
61
+ * session. Distinct from the LLM-API per-call max_tokens.
62
+ */
63
+ max_session_tokens: z.ZodOptional<z.ZodNumber>;
56
64
  }, "strip", z.ZodTypeAny, {
57
65
  messages: {
58
- role: "user" | "assistant" | "system";
66
+ role: "system" | "user" | "assistant";
59
67
  content?: string | undefined;
60
68
  parts?: {
61
69
  type: string;
@@ -65,9 +73,10 @@ export declare const AIStreamRequestSchema: z.ZodObject<{
65
73
  session_id?: string | undefined;
66
74
  role?: string | undefined;
67
75
  deploy_id?: string | undefined;
76
+ max_session_tokens?: number | undefined;
68
77
  }, {
69
78
  messages: {
70
- role: "user" | "assistant" | "system";
79
+ role: "system" | "user" | "assistant";
71
80
  content?: string | undefined;
72
81
  parts?: {
73
82
  type: string;
@@ -77,6 +86,7 @@ export declare const AIStreamRequestSchema: z.ZodObject<{
77
86
  session_id?: string | undefined;
78
87
  role?: string | undefined;
79
88
  deploy_id?: string | undefined;
89
+ max_session_tokens?: number | undefined;
80
90
  }>;
81
91
  export type AIStreamRequest = z.infer<typeof AIStreamRequestSchema>;
82
92
  interface UIMessageStart {
@@ -152,9 +162,17 @@ interface AdapterState {
152
162
  export declare function translateEvent(event: SSEEvent, state: AdapterState): UIStreamEvent[];
153
163
  export declare function extractUserMessage(messages: AIStreamRequest['messages']): string;
154
164
  export interface AIStreamRouterOptions {
155
- sessionManager: SessionManager;
165
+ sessionManager: StandaloneSessionManager;
166
+ bundleResolver: BundleResolver;
167
+ shared: SharedResources;
156
168
  /** Factory that builds per-request stream hooks from the auth context */
157
169
  createStreamHooks?: (auth?: AuthContext) => StreamHooks;
170
+ /** Server-side summarizer hook passed into every runMessage call. */
171
+ summarizeToolResult?: (opts: {
172
+ toolName: string;
173
+ content: string;
174
+ signal: AbortSignal;
175
+ }) => Promise<string>;
158
176
  }
159
177
  export declare function createAIStreamRouter(options: AIStreamRouterOptions): Router;
160
178
  export {};