@amodalai/runtime 0.1.26 → 0.2.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 (347) hide show
  1. package/dist/src/__fixtures__/README.md +84 -0
  2. package/dist/src/__fixtures__/smoke-agent/amodal.json +11 -0
  3. package/dist/src/__fixtures__/smoke-agent/automations/test-auto.md +5 -0
  4. package/dist/src/__fixtures__/smoke-agent/connections/mock-api/access.json +11 -0
  5. package/dist/src/__fixtures__/smoke-agent/connections/mock-api/spec.json +4 -0
  6. package/dist/src/__fixtures__/smoke-agent/connections/mock-api/surface.md +9 -0
  7. package/dist/src/__fixtures__/smoke-agent/connections/mock-mcp/access.json +3 -0
  8. package/dist/src/__fixtures__/smoke-agent/connections/mock-mcp/spec.json +8 -0
  9. package/dist/src/__fixtures__/smoke-agent/evals/basic-eval.md +12 -0
  10. package/dist/src/__fixtures__/smoke-agent/knowledge/test-knowledge.md +3 -0
  11. package/dist/src/__fixtures__/smoke-agent/skills/test-skill/SKILL.md +11 -0
  12. package/dist/src/__fixtures__/smoke-agent/stores/test-items.json +11 -0
  13. package/dist/src/__fixtures__/smoke-agent/tools/echo_tool/handler.d.ts +18 -0
  14. package/dist/src/__fixtures__/smoke-agent/tools/echo_tool/handler.js +22 -0
  15. package/dist/src/__fixtures__/smoke-agent/tools/echo_tool/handler.js.map +1 -0
  16. package/dist/src/__fixtures__/smoke-agent/tools/echo_tool/tool.json +17 -0
  17. package/dist/src/__fixtures__/smoke.test.js +718 -0
  18. package/dist/src/__fixtures__/smoke.test.js.map +1 -0
  19. package/dist/src/__tests__/test-providers.d.ts +40 -0
  20. package/dist/src/__tests__/test-providers.js +61 -0
  21. package/dist/src/__tests__/test-providers.js.map +1 -0
  22. package/dist/src/agent/local-server.d.ts +3 -3
  23. package/dist/src/agent/local-server.js +213 -122
  24. package/dist/src/agent/local-server.js.map +1 -1
  25. package/dist/src/agent/loop-types.d.ts +175 -0
  26. package/dist/src/agent/loop-types.js +20 -0
  27. package/dist/src/agent/loop-types.js.map +1 -0
  28. package/dist/src/agent/loop.d.ts +31 -0
  29. package/dist/src/agent/loop.js +139 -0
  30. package/dist/src/agent/loop.js.map +1 -0
  31. package/dist/src/agent/loop.test.js +1030 -0
  32. package/dist/src/agent/loop.test.js.map +1 -0
  33. package/dist/src/agent/mcp-config.d.ts +28 -0
  34. package/dist/src/agent/mcp-config.js +57 -0
  35. package/dist/src/agent/mcp-config.js.map +1 -0
  36. package/dist/src/agent/page-builder.js +6 -1
  37. package/dist/src/agent/page-builder.js.map +1 -1
  38. package/dist/src/agent/proactive/proactive-runner.d.ts +24 -8
  39. package/dist/src/agent/proactive/proactive-runner.js +30 -32
  40. package/dist/src/agent/proactive/proactive-runner.js.map +1 -1
  41. package/dist/src/agent/proactive/proactive-runner.test.d.ts +1 -1
  42. package/dist/src/agent/proactive/proactive-runner.test.js +75 -87
  43. package/dist/src/agent/proactive/proactive-runner.test.js.map +1 -1
  44. package/dist/src/agent/routes/admin-chat.d.ts +15 -3
  45. package/dist/src/agent/routes/admin-chat.js +63 -18
  46. package/dist/src/agent/routes/admin-chat.js.map +1 -1
  47. package/dist/src/agent/routes/automations.js +5 -6
  48. package/dist/src/agent/routes/automations.js.map +1 -1
  49. package/dist/src/agent/routes/evals.d.ts +3 -2
  50. package/dist/src/agent/routes/evals.js +25 -12
  51. package/dist/src/agent/routes/evals.js.map +1 -1
  52. package/dist/src/agent/routes/files.js +7 -9
  53. package/dist/src/agent/routes/files.js.map +1 -1
  54. package/dist/src/agent/routes/inspect.d.ts +6 -2
  55. package/dist/src/agent/routes/inspect.js +31 -17
  56. package/dist/src/agent/routes/inspect.js.map +1 -1
  57. package/dist/src/agent/routes/inspect.test.js +18 -42
  58. package/dist/src/agent/routes/inspect.test.js.map +1 -1
  59. package/dist/src/agent/routes/stores.js +9 -12
  60. package/dist/src/agent/routes/stores.js.map +1 -1
  61. package/dist/src/agent/routes/task.d.ts +15 -3
  62. package/dist/src/agent/routes/task.js +16 -7
  63. package/dist/src/agent/routes/task.js.map +1 -1
  64. package/dist/src/agent/routes/task.test.d.ts +1 -1
  65. package/dist/src/agent/routes/task.test.js +70 -53
  66. package/dist/src/agent/routes/task.test.js.map +1 -1
  67. package/dist/src/agent/routes/webhooks.js +12 -3
  68. package/dist/src/agent/routes/webhooks.js.map +1 -1
  69. package/dist/src/agent/session-store.d.ts +11 -2
  70. package/dist/src/agent/session-store.js +1 -1
  71. package/dist/src/agent/session-store.js.map +1 -1
  72. package/dist/src/agent/snapshot-server.d.ts +2 -22
  73. package/dist/src/agent/snapshot-server.js +50 -27
  74. package/dist/src/agent/snapshot-server.js.map +1 -1
  75. package/dist/src/agent/states/compacting.d.ts +14 -0
  76. package/dist/src/agent/states/compacting.js +258 -0
  77. package/dist/src/agent/states/compacting.js.map +1 -0
  78. package/dist/src/agent/states/confirming.d.ts +10 -0
  79. package/dist/src/agent/states/confirming.js +76 -0
  80. package/dist/src/agent/states/confirming.js.map +1 -0
  81. package/dist/src/agent/states/dispatching.d.ts +18 -0
  82. package/dist/src/agent/states/dispatching.js +241 -0
  83. package/dist/src/agent/states/dispatching.js.map +1 -0
  84. package/dist/src/agent/states/executing.d.ts +21 -0
  85. package/dist/src/agent/states/executing.js +308 -0
  86. package/dist/src/agent/states/executing.js.map +1 -0
  87. package/dist/src/agent/states/streaming.d.ts +10 -0
  88. package/dist/src/agent/states/streaming.js +155 -0
  89. package/dist/src/agent/states/streaming.js.map +1 -0
  90. package/dist/src/agent/states/thinking.d.ts +13 -0
  91. package/dist/src/agent/states/thinking.js +233 -0
  92. package/dist/src/agent/states/thinking.js.map +1 -0
  93. package/dist/src/agent/token-estimate.d.ts +17 -0
  94. package/dist/src/agent/token-estimate.js +13 -0
  95. package/dist/src/agent/token-estimate.js.map +1 -0
  96. package/dist/src/agent/tool-executor-local.js +9 -18
  97. package/dist/src/agent/tool-executor-local.js.map +1 -1
  98. package/dist/src/agent/tool-executor-local.test.js +3 -5
  99. package/dist/src/agent/tool-executor-local.test.js.map +1 -1
  100. package/dist/src/api/create-agent.d.ts +15 -0
  101. package/dist/src/api/create-agent.js +137 -0
  102. package/dist/src/api/create-agent.js.map +1 -0
  103. package/dist/src/api/types.d.ts +68 -0
  104. package/dist/src/api/types.js +7 -0
  105. package/dist/src/api/types.js.map +1 -0
  106. package/dist/src/context/compiler.d.ts +13 -0
  107. package/dist/src/context/compiler.js +358 -0
  108. package/dist/src/context/compiler.js.map +1 -0
  109. package/dist/src/context/compiler.test.js +532 -0
  110. package/dist/src/context/compiler.test.js.map +1 -0
  111. package/dist/src/context/types.d.ts +110 -0
  112. package/dist/src/context/types.js +7 -0
  113. package/dist/src/context/types.js.map +1 -0
  114. package/dist/src/index.d.ts +33 -6
  115. package/dist/src/index.js +35 -21
  116. package/dist/src/index.js.map +1 -1
  117. package/dist/src/providers/create-provider.d.ts +23 -0
  118. package/dist/src/providers/create-provider.js +185 -0
  119. package/dist/src/providers/create-provider.js.map +1 -0
  120. package/dist/src/{agent/stores-e2e.test.d.ts → providers/create-provider.test.d.ts} +1 -1
  121. package/dist/src/providers/create-provider.test.js +95 -0
  122. package/dist/src/providers/create-provider.test.js.map +1 -0
  123. package/dist/src/providers/failover.d.ts +38 -0
  124. package/dist/src/providers/failover.js +147 -0
  125. package/dist/src/providers/failover.js.map +1 -0
  126. package/dist/src/providers/failover.test.d.ts +6 -0
  127. package/dist/src/providers/failover.test.js +169 -0
  128. package/dist/src/providers/failover.test.js.map +1 -0
  129. package/dist/src/providers/types.d.ts +110 -0
  130. package/dist/src/providers/types.js +7 -0
  131. package/dist/src/providers/types.js.map +1 -0
  132. package/dist/src/routes/ai-stream.d.ts +13 -10
  133. package/dist/src/routes/ai-stream.js +76 -41
  134. package/dist/src/routes/ai-stream.js.map +1 -1
  135. package/dist/src/routes/chat-new.test.d.ts +6 -0
  136. package/dist/src/routes/chat-new.test.js +107 -0
  137. package/dist/src/routes/chat-new.test.js.map +1 -0
  138. package/dist/src/routes/chat-stream-new.test.d.ts +6 -0
  139. package/dist/src/routes/chat-stream-new.test.js +135 -0
  140. package/dist/src/routes/chat-stream-new.test.js.map +1 -0
  141. package/dist/src/routes/chat-stream.d.ts +14 -4
  142. package/dist/src/routes/chat-stream.js +47 -29
  143. package/dist/src/routes/chat-stream.js.map +1 -1
  144. package/dist/src/routes/chat.d.ts +13 -4
  145. package/dist/src/routes/chat.js +60 -23
  146. package/dist/src/routes/chat.js.map +1 -1
  147. package/dist/src/routes/health.d.ts +3 -2
  148. package/dist/src/routes/health.js.map +1 -1
  149. package/dist/src/routes/route-helpers.d.ts +50 -0
  150. package/dist/src/routes/route-helpers.js +80 -0
  151. package/dist/src/routes/route-helpers.js.map +1 -0
  152. package/dist/src/routes/session-resolver.d.ts +72 -0
  153. package/dist/src/routes/session-resolver.js +123 -0
  154. package/dist/src/routes/session-resolver.js.map +1 -0
  155. package/dist/src/routes/session-resolver.test.d.ts +6 -0
  156. package/dist/src/routes/session-resolver.test.js +206 -0
  157. package/dist/src/routes/session-resolver.test.js.map +1 -0
  158. package/dist/src/routes/webhooks.d.ts +3 -1
  159. package/dist/src/routes/webhooks.js +12 -4
  160. package/dist/src/routes/webhooks.js.map +1 -1
  161. package/dist/src/security/permission-checker.d.ts +80 -0
  162. package/dist/src/security/permission-checker.js +75 -0
  163. package/dist/src/security/permission-checker.js.map +1 -0
  164. package/dist/src/security/permission-checker.test.d.ts +6 -0
  165. package/dist/src/security/permission-checker.test.js +208 -0
  166. package/dist/src/security/permission-checker.test.js.map +1 -0
  167. package/dist/src/server.d.ts +12 -11
  168. package/dist/src/server.js +44 -46
  169. package/dist/src/server.js.map +1 -1
  170. package/dist/src/server.test.d.ts +1 -1
  171. package/dist/src/server.test.js +6 -144
  172. package/dist/src/server.test.js.map +1 -1
  173. package/dist/src/session/manager.d.ts +98 -0
  174. package/dist/src/session/manager.js +364 -0
  175. package/dist/src/session/manager.js.map +1 -0
  176. package/dist/src/session/manager.test.d.ts +6 -0
  177. package/dist/src/session/manager.test.js +315 -0
  178. package/dist/src/session/manager.test.js.map +1 -0
  179. package/dist/src/session/session-builder.d.ts +71 -0
  180. package/dist/src/session/session-builder.js +364 -0
  181. package/dist/src/session/session-builder.js.map +1 -0
  182. package/dist/src/session/session-builder.test.d.ts +6 -0
  183. package/dist/src/session/session-builder.test.js +352 -0
  184. package/dist/src/session/session-builder.test.js.map +1 -0
  185. package/dist/src/session/store.d.ts +57 -0
  186. package/dist/src/session/store.js +167 -0
  187. package/dist/src/session/store.js.map +1 -0
  188. package/dist/src/session/store.test.d.ts +6 -0
  189. package/dist/src/session/store.test.js +145 -0
  190. package/dist/src/session/store.test.js.map +1 -0
  191. package/dist/src/session/stream-hooks.d.ts +39 -0
  192. package/dist/src/session/stream-hooks.js +7 -0
  193. package/dist/src/session/stream-hooks.js.map +1 -0
  194. package/dist/src/session/tool-context-factory.d.ts +60 -0
  195. package/dist/src/session/tool-context-factory.js +190 -0
  196. package/dist/src/session/tool-context-factory.js.map +1 -0
  197. package/dist/src/session/tool-context-factory.test.d.ts +6 -0
  198. package/dist/src/session/tool-context-factory.test.js +287 -0
  199. package/dist/src/session/tool-context-factory.test.js.map +1 -0
  200. package/dist/src/session/types.d.ts +188 -0
  201. package/dist/src/session/types.js +7 -0
  202. package/dist/src/session/types.js.map +1 -0
  203. package/dist/src/stores/drizzle-store-backend.d.ts +49 -0
  204. package/dist/src/stores/drizzle-store-backend.js +306 -0
  205. package/dist/src/stores/drizzle-store-backend.js.map +1 -0
  206. package/dist/src/stores/drizzle-store-backend.test.d.ts +6 -0
  207. package/dist/src/stores/drizzle-store-backend.test.js +215 -0
  208. package/dist/src/stores/drizzle-store-backend.test.js.map +1 -0
  209. package/dist/src/stores/index.d.ts +4 -0
  210. package/dist/src/stores/index.js +2 -0
  211. package/dist/src/stores/index.js.map +1 -1
  212. package/dist/src/stores/pglite-store-backend.d.ts +16 -19
  213. package/dist/src/stores/pglite-store-backend.js +85 -239
  214. package/dist/src/stores/pglite-store-backend.js.map +1 -1
  215. package/dist/src/stores/postgres-store-backend.d.ts +30 -0
  216. package/dist/src/stores/postgres-store-backend.js +100 -0
  217. package/dist/src/stores/postgres-store-backend.js.map +1 -0
  218. package/dist/src/stores/schema.d.ts +491 -0
  219. package/dist/src/stores/schema.js +57 -0
  220. package/dist/src/stores/schema.js.map +1 -0
  221. package/dist/src/tools/admin-file-tools.d.ts +13 -0
  222. package/dist/src/tools/admin-file-tools.js +200 -0
  223. package/dist/src/tools/admin-file-tools.js.map +1 -0
  224. package/dist/src/tools/admin-file-tools.test.d.ts +6 -0
  225. package/dist/src/tools/admin-file-tools.test.js +152 -0
  226. package/dist/src/tools/admin-file-tools.test.js.map +1 -0
  227. package/dist/src/tools/custom-tool-adapter.d.ts +41 -0
  228. package/dist/src/tools/custom-tool-adapter.js +190 -0
  229. package/dist/src/tools/custom-tool-adapter.js.map +1 -0
  230. package/dist/src/tools/custom-tool-adapter.test.d.ts +6 -0
  231. package/dist/src/tools/custom-tool-adapter.test.js +244 -0
  232. package/dist/src/tools/custom-tool-adapter.test.js.map +1 -0
  233. package/dist/src/tools/dispatch-tool.d.ts +52 -0
  234. package/dist/src/tools/dispatch-tool.js +71 -0
  235. package/dist/src/tools/dispatch-tool.js.map +1 -0
  236. package/dist/src/tools/dispatch-tool.test.d.ts +6 -0
  237. package/dist/src/tools/dispatch-tool.test.js +75 -0
  238. package/dist/src/tools/dispatch-tool.test.js.map +1 -0
  239. package/dist/src/tools/mcp-tool-adapter.d.ts +18 -0
  240. package/dist/src/tools/mcp-tool-adapter.js +135 -0
  241. package/dist/src/tools/mcp-tool-adapter.js.map +1 -0
  242. package/dist/src/tools/mcp-tool-adapter.test.d.ts +6 -0
  243. package/dist/src/tools/mcp-tool-adapter.test.js +227 -0
  244. package/dist/src/tools/mcp-tool-adapter.test.js.map +1 -0
  245. package/dist/src/tools/registry.d.ts +25 -0
  246. package/dist/src/tools/registry.js +72 -0
  247. package/dist/src/tools/registry.js.map +1 -0
  248. package/dist/src/tools/registry.test.d.ts +6 -0
  249. package/dist/src/tools/registry.test.js +121 -0
  250. package/dist/src/tools/registry.test.js.map +1 -0
  251. package/dist/src/tools/request-tool.d.ts +42 -0
  252. package/dist/src/tools/request-tool.js +190 -0
  253. package/dist/src/tools/request-tool.js.map +1 -0
  254. package/dist/src/tools/request-tool.test.d.ts +6 -0
  255. package/dist/src/tools/request-tool.test.js +254 -0
  256. package/dist/src/tools/request-tool.test.js.map +1 -0
  257. package/dist/src/tools/store-tools.d.ts +29 -0
  258. package/dist/src/tools/store-tools.js +224 -0
  259. package/dist/src/tools/store-tools.js.map +1 -0
  260. package/dist/src/tools/store-tools.test.d.ts +6 -0
  261. package/dist/src/tools/store-tools.test.js +216 -0
  262. package/dist/src/tools/store-tools.test.js.map +1 -0
  263. package/dist/src/tools/types.d.ts +111 -0
  264. package/dist/src/tools/types.js +7 -0
  265. package/dist/src/tools/types.js.map +1 -0
  266. package/dist/src/types.d.ts +20 -12
  267. package/dist/src/types.js +3 -2
  268. package/dist/src/types.js.map +1 -1
  269. package/dist/tsconfig.tsbuildinfo +1 -1
  270. package/package.json +13 -4
  271. package/dist/src/__tests__/sse-contract.test.js +0 -464
  272. package/dist/src/__tests__/sse-contract.test.js.map +0 -1
  273. package/dist/src/__tests__/tools.test.js +0 -583
  274. package/dist/src/__tests__/tools.test.js.map +0 -1
  275. package/dist/src/agent/agent-runner.d.ts +0 -33
  276. package/dist/src/agent/agent-runner.js +0 -1040
  277. package/dist/src/agent/agent-runner.js.map +0 -1
  278. package/dist/src/agent/custom-tools-e2e.test.d.ts +0 -6
  279. package/dist/src/agent/custom-tools-e2e.test.js +0 -566
  280. package/dist/src/agent/custom-tools-e2e.test.js.map +0 -1
  281. package/dist/src/agent/request-helper.d.ts +0 -16
  282. package/dist/src/agent/request-helper.js +0 -96
  283. package/dist/src/agent/request-helper.js.map +0 -1
  284. package/dist/src/agent/stores-e2e.test.js +0 -433
  285. package/dist/src/agent/stores-e2e.test.js.map +0 -1
  286. package/dist/src/agent/tool-context-builder.d.ts +0 -11
  287. package/dist/src/agent/tool-context-builder.js +0 -102
  288. package/dist/src/agent/tool-context-builder.js.map +0 -1
  289. package/dist/src/agent/tool-context-builder.test.d.ts +0 -6
  290. package/dist/src/agent/tool-context-builder.test.js +0 -152
  291. package/dist/src/agent/tool-context-builder.test.js.map +0 -1
  292. package/dist/src/agent/write-repo-file.test.js +0 -270
  293. package/dist/src/agent/write-repo-file.test.js.map +0 -1
  294. package/dist/src/cron/heartbeat-runner.d.ts +0 -21
  295. package/dist/src/cron/heartbeat-runner.js +0 -79
  296. package/dist/src/cron/heartbeat-runner.js.map +0 -1
  297. package/dist/src/cron/heartbeat-runner.test.d.ts +0 -6
  298. package/dist/src/cron/heartbeat-runner.test.js +0 -120
  299. package/dist/src/cron/heartbeat-runner.test.js.map +0 -1
  300. package/dist/src/cron/heartbeat-scheduler.d.ts +0 -26
  301. package/dist/src/cron/heartbeat-scheduler.js +0 -55
  302. package/dist/src/cron/heartbeat-scheduler.js.map +0 -1
  303. package/dist/src/cron/heartbeat-scheduler.test.d.ts +0 -6
  304. package/dist/src/cron/heartbeat-scheduler.test.js +0 -61
  305. package/dist/src/cron/heartbeat-scheduler.test.js.map +0 -1
  306. package/dist/src/routes/ai-stream.test.d.ts +0 -6
  307. package/dist/src/routes/ai-stream.test.js +0 -586
  308. package/dist/src/routes/ai-stream.test.js.map +0 -1
  309. package/dist/src/routes/ask-user-response.d.ts +0 -30
  310. package/dist/src/routes/ask-user-response.js +0 -61
  311. package/dist/src/routes/ask-user-response.js.map +0 -1
  312. package/dist/src/routes/ask-user-response.test.d.ts +0 -6
  313. package/dist/src/routes/ask-user-response.test.js +0 -88
  314. package/dist/src/routes/ask-user-response.test.js.map +0 -1
  315. package/dist/src/routes/chat-stream.test.d.ts +0 -6
  316. package/dist/src/routes/chat-stream.test.js +0 -155
  317. package/dist/src/routes/chat-stream.test.js.map +0 -1
  318. package/dist/src/routes/chat.test.d.ts +0 -6
  319. package/dist/src/routes/chat.test.js +0 -99
  320. package/dist/src/routes/chat.test.js.map +0 -1
  321. package/dist/src/routes/widget-actions.d.ts +0 -49
  322. package/dist/src/routes/widget-actions.js +0 -78
  323. package/dist/src/routes/widget-actions.js.map +0 -1
  324. package/dist/src/session/custom-tool-adapter.d.ts +0 -74
  325. package/dist/src/session/custom-tool-adapter.js +0 -180
  326. package/dist/src/session/custom-tool-adapter.js.map +0 -1
  327. package/dist/src/session/history-converter.d.ts +0 -21
  328. package/dist/src/session/history-converter.js +0 -59
  329. package/dist/src/session/history-converter.js.map +0 -1
  330. package/dist/src/session/history-converter.test.d.ts +0 -6
  331. package/dist/src/session/history-converter.test.js +0 -130
  332. package/dist/src/session/history-converter.test.js.map +0 -1
  333. package/dist/src/session/session-manager.d.ts +0 -219
  334. package/dist/src/session/session-manager.js +0 -915
  335. package/dist/src/session/session-manager.js.map +0 -1
  336. package/dist/src/session/session-manager.test.d.ts +0 -6
  337. package/dist/src/session/session-manager.test.js +0 -455
  338. package/dist/src/session/session-manager.test.js.map +0 -1
  339. package/dist/src/session/session-runner.d.ts +0 -45
  340. package/dist/src/session/session-runner.js +0 -719
  341. package/dist/src/session/session-runner.js.map +0 -1
  342. package/dist/src/session/session-runner.test.d.ts +0 -6
  343. package/dist/src/session/session-runner.test.js +0 -834
  344. package/dist/src/session/session-runner.test.js.map +0 -1
  345. /package/dist/src/{__tests__/sse-contract.test.d.ts → __fixtures__/smoke.test.d.ts} +0 -0
  346. /package/dist/src/{__tests__/tools.test.d.ts → agent/loop.test.d.ts} +0 -0
  347. /package/dist/src/{agent/write-repo-file.test.d.ts → context/compiler.test.d.ts} +0 -0
@@ -1,719 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2025 Amodal Labs, Inc.
4
- * SPDX-License-Identifier: MIT
5
- */
6
- import { GeminiEventType, ToolErrorType, PRESENT_TOOL_NAME, ACTIVATE_SKILL_TOOL_NAME, ASK_USER_TOOL_NAME, } from '@amodalai/core';
7
- /**
8
- * Custom message bus event key for subagent activity.
9
- * Upstream MessageBusType doesn't include this — our dispatch tool emits on
10
- * this string key, which works because MessageBus extends EventEmitter.
11
- */
12
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- custom event key for our dispatch tool
13
- const SUBAGENT_ACTIVITY_EVENT = 'subagent-activity';
14
- import { SSEEventType, } from '../types.js';
15
- const MAX_TURNS = 50;
16
- /**
17
- * Extract text from tool response parts, truncated for audit logging.
18
- * Handles both plain text parts and functionResponse parts (from task agents).
19
- */
20
- function extractResultText(parts) {
21
- if (!parts || parts.length === 0)
22
- return undefined;
23
- const segments = [];
24
- for (const p of parts) {
25
- if (p.text) {
26
- segments.push(p.text);
27
- }
28
- else if (p.functionResponse?.response) {
29
- try {
30
- segments.push(JSON.stringify(p.functionResponse.response));
31
- }
32
- catch {
33
- segments.push('[unserializable response]');
34
- }
35
- }
36
- }
37
- const text = segments.join('');
38
- if (!text)
39
- return undefined;
40
- return text;
41
- }
42
- const MAX_SUBAGENT_RESULT_LENGTH = 300;
43
- /**
44
- * Map SubagentActivityEvent type strings to SSE event_type values.
45
- */
46
- function mapSubagentEventType(type) {
47
- switch (type) {
48
- case 'TOOL_CALL_START': return 'tool_call_start';
49
- case 'TOOL_CALL_END': return 'tool_call_end';
50
- case 'THOUGHT_CHUNK': return 'thought';
51
- case 'COMPLETE': return 'complete';
52
- case 'ERROR': return 'error';
53
- default: return 'error';
54
- }
55
- }
56
- /**
57
- * Truncate a string to the given max length, appending '...' if truncated.
58
- */
59
- function truncateSubagentResult(text, maxLen) {
60
- if (!text)
61
- return undefined;
62
- return text.length > maxLen ? text.slice(0, maxLen) + '...' : text;
63
- }
64
- /**
65
- * Convert a real-time SubagentActivityMessage to an SSESubagentEvent.
66
- */
67
- function subagentMessageToSSE(msg, parentToolId) {
68
- return {
69
- type: SSEEventType.SubagentEvent,
70
- parent_tool_id: parentToolId,
71
- agent_name: msg.agentName,
72
- event_type: mapSubagentEventType(msg.eventType),
73
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- name from subagent activity data
74
- tool_name: msg.data['name'],
75
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- args from subagent activity data
76
- tool_args: msg.data['args'],
77
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- output from subagent activity data
78
- result: truncateSubagentResult(msg.data['output'], MAX_SUBAGENT_RESULT_LENGTH),
79
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- text from subagent COMPLETE event
80
- text: msg.data['text'],
81
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- error from subagent activity data
82
- error: msg.data['error'],
83
- timestamp: new Date().toISOString(),
84
- };
85
- }
86
- /**
87
- * Run a synchronous (non-streaming) message through the agentic loop.
88
- * Collects all text and tool calls, returns a ChatResponse.
89
- */
90
- export async function runMessage(session, message, signal, hooks) {
91
- const { geminiClient, scheduler, config } = session;
92
- const promptId = `msg-${Date.now()}`;
93
- const sessionStartMs = Date.now();
94
- let currentMessages = [
95
- { role: 'user', parts: [{ text: message }] },
96
- ];
97
- let responseText = '';
98
- const toolCalls = [];
99
- const skillsActivated = [];
100
- let turnCount = 0;
101
- let status = 'completed';
102
- let errorMessage;
103
- const tokens = { inputTokens: 0, outputTokens: 0, cachedTokens: 0 };
104
- try {
105
- while (true) {
106
- turnCount++;
107
- if (turnCount > MAX_TURNS) {
108
- status = 'max_turns';
109
- break;
110
- }
111
- if (signal.aborted)
112
- break;
113
- const toolCallRequests = [];
114
- const responseStream = geminiClient.sendMessageStream(currentMessages[0]?.parts ?? [], signal, promptId, undefined, false, turnCount === 1 ? message : undefined);
115
- for await (const event of responseStream) {
116
- if (signal.aborted)
117
- break;
118
- if (event.type === GeminiEventType.Content) {
119
- responseText += event.value;
120
- }
121
- else if (event.type === GeminiEventType.ToolCallRequest) {
122
- toolCallRequests.push(event.value);
123
- }
124
- else if (event.type === GeminiEventType.Finished) {
125
- const meta = event.value.usageMetadata;
126
- if (meta) {
127
- tokens.inputTokens += meta.promptTokenCount ?? 0;
128
- tokens.outputTokens += meta.candidatesTokenCount ?? 0;
129
- tokens.cachedTokens += meta.cachedContentTokenCount ?? 0;
130
- }
131
- }
132
- else if (event.type === GeminiEventType.Error) {
133
- status = 'error';
134
- const errObj = event.value.error;
135
- const errMsg = errObj instanceof Error ? errObj.message : (typeof errObj === 'object' && errObj !== null && 'message' in errObj) ? String(errObj['message']) : String(errObj);
136
- errorMessage = errMsg;
137
- throw new Error(errMsg);
138
- }
139
- else if (event.type === GeminiEventType.AgentExecutionStopped) {
140
- return { session_id: session.id, response: responseText, tool_calls: toolCalls };
141
- }
142
- }
143
- if (toolCallRequests.length > 0) {
144
- const completedToolCalls = await scheduler.schedule(toolCallRequests, signal);
145
- const toolResponseParts = [];
146
- for (const completed of completedToolCalls) {
147
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- accessing optional field on CompletedToolCall union
148
- const duration = 'durationMs' in completed ? completed['durationMs'] : undefined;
149
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- inner_tool_calls from subagent data
150
- const innerCalls = completed.response.data?.['inner_tool_calls'];
151
- toolCalls.push({
152
- tool_name: completed.request.name,
153
- tool_id: completed.request.callId,
154
- args: completed.request.args,
155
- status: completed.response.error ? 'error' : 'success',
156
- duration_ms: duration,
157
- error: completed.response.error?.message,
158
- result: extractResultText(completed.response.responseParts),
159
- inner_tool_calls: innerCalls,
160
- });
161
- // Track skill activations
162
- if (completed.request.name === ACTIVATE_SKILL_TOOL_NAME &&
163
- !completed.response.error) {
164
- const skillName = String(completed.request.args['name'] ?? '');
165
- if (skillName) {
166
- skillsActivated.push(skillName);
167
- }
168
- }
169
- if (completed.response.responseParts) {
170
- toolResponseParts.push(...completed.response.responseParts);
171
- }
172
- // Record tool calls
173
- try {
174
- const currentModel = geminiClient.getCurrentSequenceModel() ?? config.getModel();
175
- geminiClient
176
- .getChat()
177
- .recordCompletedToolCalls(currentModel, completedToolCalls);
178
- }
179
- catch {
180
- // Non-critical — continue
181
- }
182
- }
183
- // Check for stop execution
184
- const stopTool = completedToolCalls.find((tc) => tc.response.errorType === ToolErrorType.STOP_EXECUTION);
185
- if (stopTool) {
186
- return { session_id: session.id, response: responseText, tool_calls: toolCalls };
187
- }
188
- currentMessages = [{ role: 'user', parts: toolResponseParts }];
189
- }
190
- else {
191
- break;
192
- }
193
- }
194
- return { session_id: session.id, response: responseText, tool_calls: toolCalls };
195
- }
196
- catch (err) {
197
- status = 'error';
198
- errorMessage = err instanceof Error ? err.message : String(err);
199
- throw err;
200
- }
201
- finally {
202
- if (hooks) {
203
- const model = geminiClient.getCurrentSequenceModel() ?? config.getModel();
204
- logSessionCompleted(hooks, session.id, message, responseText, turnCount, toolCalls, skillsActivated, status, errorMessage, sessionStartMs, model, tokens);
205
- }
206
- }
207
- }
208
- /**
209
- * Stream a message through the agentic loop, yielding SSE events.
210
- */
211
- export async function* streamMessage(session, message, signal, hooks, sessionManager) {
212
- const { geminiClient, scheduler, config } = session;
213
- const promptId = `msg-${Date.now()}`;
214
- const sessionStartMs = Date.now();
215
- let currentMessages = [
216
- { role: 'user', parts: [{ text: message }] },
217
- ];
218
- // Accumulators for the consolidated audit event
219
- const auditToolCalls = [];
220
- const skillsActivated = [];
221
- const widgetEvents = [];
222
- let responseText = '';
223
- let auditStatus = 'completed';
224
- const tokens = { inputTokens: 0, outputTokens: 0, cachedTokens: 0 };
225
- // Track content block ordering so history can reconstruct the correct interleave
226
- const contentBlockOrder = [];
227
- function trackText(text) {
228
- const last = contentBlockOrder[contentBlockOrder.length - 1];
229
- if (last && last['type'] === 'text') {
230
- last['text'] = String(last['text'] ?? '') + text;
231
- }
232
- else {
233
- contentBlockOrder.push({ type: 'text', text });
234
- }
235
- }
236
- function trackToolCall(callId) {
237
- const last = contentBlockOrder[contentBlockOrder.length - 1];
238
- if (last && last['type'] === 'tool_calls') {
239
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- extending callIds array
240
- last['callIds'].push(callId);
241
- }
242
- else {
243
- contentBlockOrder.push({ type: 'tool_calls', callIds: [callId] });
244
- }
245
- }
246
- let auditError;
247
- // Accumulate user message for session history
248
- const userMsg = {
249
- type: 'user',
250
- id: `msg-${Date.now()}`,
251
- text: message,
252
- timestamp: new Date().toISOString(),
253
- };
254
- session.accumulatedMessages.push(userMsg);
255
- yield {
256
- type: SSEEventType.Init,
257
- session_id: session.id,
258
- timestamp: new Date().toISOString(),
259
- };
260
- let turnCount = 0;
261
- while (true) {
262
- turnCount++;
263
- if (turnCount > MAX_TURNS) {
264
- auditStatus = 'max_turns';
265
- auditError = 'Maximum turns exceeded';
266
- yield {
267
- type: SSEEventType.Error,
268
- message: 'Maximum turns exceeded',
269
- timestamp: new Date().toISOString(),
270
- };
271
- break;
272
- }
273
- if (signal.aborted)
274
- break;
275
- const toolCallRequests = [];
276
- const responseStream = geminiClient.sendMessageStream(currentMessages[0]?.parts ?? [], signal, promptId, undefined, false, turnCount === 1 ? message : undefined);
277
- for await (const event of responseStream) {
278
- if (signal.aborted)
279
- break;
280
- if (event.type === GeminiEventType.Content) {
281
- responseText += event.value;
282
- trackText(event.value);
283
- yield {
284
- type: SSEEventType.TextDelta,
285
- content: event.value,
286
- timestamp: new Date().toISOString(),
287
- };
288
- }
289
- else if (event.type === GeminiEventType.ToolCallRequest) {
290
- // Suppress tool_call_start for present (widget events replace it) and ask_user (intercepted below)
291
- if (event.value.name !== PRESENT_TOOL_NAME && event.value.name !== ASK_USER_TOOL_NAME) {
292
- yield {
293
- type: SSEEventType.ToolCallStart,
294
- tool_name: event.value.name,
295
- tool_id: event.value.callId,
296
- parameters: event.value.args,
297
- timestamp: new Date().toISOString(),
298
- };
299
- }
300
- toolCallRequests.push(event.value);
301
- }
302
- else if (event.type === GeminiEventType.Finished) {
303
- const meta = event.value.usageMetadata;
304
- if (meta) {
305
- tokens.inputTokens += meta.promptTokenCount ?? 0;
306
- tokens.outputTokens += meta.candidatesTokenCount ?? 0;
307
- tokens.cachedTokens += meta.cachedContentTokenCount ?? 0;
308
- }
309
- }
310
- else if (event.type === GeminiEventType.Error) {
311
- auditStatus = 'error';
312
- const errObj = event.value.error;
313
- const errMsg = errObj instanceof Error ? errObj.message : (typeof errObj === 'object' && errObj !== null && 'message' in errObj) ? String(errObj['message']) : String(errObj);
314
- auditError = errMsg;
315
- yield {
316
- type: SSEEventType.Error,
317
- message: errMsg,
318
- timestamp: new Date().toISOString(),
319
- };
320
- logSessionCompleted(hooks, session.id, message, responseText, turnCount, auditToolCalls, skillsActivated, auditStatus, auditError, sessionStartMs, geminiClient.getCurrentSequenceModel() ?? config.getModel(), tokens);
321
- accumulateAssistantAndSave(session, hooks, responseText, auditToolCalls, skillsActivated, widgetEvents, contentBlockOrder, 'error');
322
- yield {
323
- type: SSEEventType.Done,
324
- timestamp: new Date().toISOString(),
325
- usage: {
326
- input_tokens: tokens.inputTokens,
327
- output_tokens: tokens.outputTokens,
328
- cached_tokens: tokens.cachedTokens,
329
- total_tokens: tokens.inputTokens + tokens.outputTokens,
330
- },
331
- };
332
- return;
333
- }
334
- else if (event.type === GeminiEventType.AgentExecutionStopped) {
335
- logSessionCompleted(hooks, session.id, message, responseText, turnCount, auditToolCalls, skillsActivated, auditStatus, auditError, sessionStartMs, geminiClient.getCurrentSequenceModel() ?? config.getModel(), tokens);
336
- accumulateAssistantAndSave(session, hooks, responseText, auditToolCalls, skillsActivated, widgetEvents, contentBlockOrder, 'completed');
337
- yield {
338
- type: SSEEventType.Done,
339
- timestamp: new Date().toISOString(),
340
- usage: {
341
- input_tokens: tokens.inputTokens,
342
- output_tokens: tokens.outputTokens,
343
- cached_tokens: tokens.cachedTokens,
344
- total_tokens: tokens.inputTokens + tokens.outputTokens,
345
- },
346
- };
347
- return;
348
- }
349
- }
350
- if (toolCallRequests.length > 0) {
351
- // Partition: separate ask_user requests from regular tool calls
352
- const askUserRequests = toolCallRequests.filter((req) => req.name === ASK_USER_TOOL_NAME);
353
- const otherRequests = toolCallRequests.filter((req) => req.name !== ASK_USER_TOOL_NAME);
354
- const toolResponseParts = [];
355
- // Handle ask_user requests: yield SSE event, wait for user response
356
- if (askUserRequests.length > 0 && sessionManager) {
357
- for (const askReq of askUserRequests) {
358
- const askId = askReq.callId;
359
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- LLM-provided questions array
360
- const questions = askReq.args['questions'] ?? [];
361
- const askStartMs = Date.now();
362
- // Emit tool_call_start for the ask_user tool
363
- yield {
364
- type: SSEEventType.ToolCallStart,
365
- tool_name: askReq.name,
366
- tool_id: askId,
367
- parameters: askReq.args,
368
- timestamp: new Date().toISOString(),
369
- };
370
- // Track ask_user in content block ordering
371
- contentBlockOrder.push({ type: 'ask_user', askId });
372
- // Emit ask_user SSE event
373
- yield {
374
- type: SSEEventType.AskUser,
375
- ask_id: askId,
376
- questions,
377
- timestamp: new Date().toISOString(),
378
- };
379
- try {
380
- const answers = await sessionManager.waitForAskUserResponse(session, askId, signal);
381
- const askDuration = Date.now() - askStartMs;
382
- const resultOutput = JSON.stringify({ answers });
383
- // Audit
384
- auditToolCalls.push({
385
- tool_name: askReq.name,
386
- tool_id: askId,
387
- args: askReq.args,
388
- status: 'success',
389
- duration_ms: askDuration,
390
- });
391
- // Emit tool_call_result
392
- yield {
393
- type: SSEEventType.ToolCallResult,
394
- tool_id: askId,
395
- status: 'success',
396
- result: resultOutput,
397
- duration_ms: askDuration,
398
- timestamp: new Date().toISOString(),
399
- };
400
- // Build function response part
401
- toolResponseParts.push({
402
- functionResponse: {
403
- id: askId,
404
- name: ASK_USER_TOOL_NAME,
405
- response: { output: resultOutput },
406
- },
407
- });
408
- }
409
- catch (err) {
410
- const askDuration = Date.now() - askStartMs;
411
- const errorMsg = err instanceof Error ? err.message : 'ask_user failed';
412
- auditToolCalls.push({
413
- tool_name: askReq.name,
414
- tool_id: askId,
415
- args: askReq.args,
416
- status: 'error',
417
- duration_ms: askDuration,
418
- error: errorMsg,
419
- });
420
- yield {
421
- type: SSEEventType.ToolCallResult,
422
- tool_id: askId,
423
- status: 'error',
424
- error: errorMsg,
425
- duration_ms: askDuration,
426
- timestamp: new Date().toISOString(),
427
- };
428
- toolResponseParts.push({
429
- functionResponse: {
430
- id: askId,
431
- name: ASK_USER_TOOL_NAME,
432
- response: { output: JSON.stringify({ error: errorMsg }) },
433
- },
434
- });
435
- }
436
- }
437
- }
438
- else if (askUserRequests.length > 0) {
439
- // No sessionManager — return fallback response
440
- for (const askReq of askUserRequests) {
441
- auditToolCalls.push({
442
- tool_name: askReq.name,
443
- tool_id: askReq.callId,
444
- args: askReq.args,
445
- status: 'error',
446
- error: 'ask_user not supported in this session mode',
447
- });
448
- toolResponseParts.push({
449
- functionResponse: {
450
- id: askReq.callId,
451
- name: ASK_USER_TOOL_NAME,
452
- response: { output: JSON.stringify({ error: 'ask_user not supported in this session mode' }) },
453
- },
454
- });
455
- }
456
- }
457
- // Handle other tool calls through the scheduler normally
458
- if (otherRequests.length > 0) {
459
- // --- Real-time subagent event streaming ---
460
- // Subscribe to SUBAGENT_ACTIVITY on the message bus so we can yield
461
- // subagent events as they happen (instead of waiting for dispatch to finish).
462
- const messageBus = config.getMessageBus();
463
- const subagentEventQueue = [];
464
- let notifyNewEvent = null;
465
- // Track dispatch tool call IDs for correlation
466
- const unmatchedDispatchCallIds = new Set();
467
- const dispatchIdToCallId = new Map();
468
- for (const req of otherRequests) {
469
- if (req.name === 'dispatch') {
470
- unmatchedDispatchCallIds.add(req.callId);
471
- }
472
- }
473
- const hasDispatchCalls = unmatchedDispatchCallIds.size > 0;
474
- const subagentListener = (msg) => {
475
- // Map dispatchId to the parent tool callId
476
- let parentToolId = dispatchIdToCallId.get(msg.dispatchId);
477
- if (!parentToolId && unmatchedDispatchCallIds.size > 0) {
478
- // Assign to the first unmatched dispatch call
479
- const firstUnmatched = unmatchedDispatchCallIds.values().next().value;
480
- if (firstUnmatched) {
481
- unmatchedDispatchCallIds.delete(firstUnmatched);
482
- dispatchIdToCallId.set(msg.dispatchId, firstUnmatched);
483
- parentToolId = firstUnmatched;
484
- }
485
- }
486
- if (!parentToolId)
487
- return;
488
- subagentEventQueue.push(subagentMessageToSSE(msg, parentToolId));
489
- // Wake up the yield loop
490
- notifyNewEvent?.();
491
- notifyNewEvent = null;
492
- };
493
- if (hasDispatchCalls) {
494
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion, @typescript-eslint/no-explicit-any -- custom event not in upstream Message union; EventEmitter accepts any string
495
- messageBus.subscribe(SUBAGENT_ACTIVITY_EVENT, subagentListener);
496
- }
497
- // Start the scheduler (don't await yet — we'll yield events concurrently)
498
- let completedToolCalls;
499
- const schedulerPromise = scheduler.schedule(otherRequests, signal).then((result) => {
500
- completedToolCalls = result;
501
- // Wake up the yield loop so it can exit
502
- notifyNewEvent?.();
503
- notifyNewEvent = null;
504
- });
505
- // Yield subagent events in real-time while the scheduler is running
506
- if (hasDispatchCalls) {
507
- while (completedToolCalls === undefined || subagentEventQueue.length > 0) {
508
- // Drain any pending events
509
- while (subagentEventQueue.length > 0) {
510
- yield subagentEventQueue.shift();
511
- }
512
- // If scheduler isn't done, wait for a new event or completion
513
- if (completedToolCalls === undefined) {
514
- await new Promise((resolve) => {
515
- notifyNewEvent = resolve;
516
- // Also resolve if the scheduler finishes while we're waiting
517
- schedulerPromise.then(() => {
518
- resolve();
519
- return;
520
- }, () => {
521
- resolve();
522
- return;
523
- });
524
- });
525
- }
526
- }
527
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion, @typescript-eslint/no-explicit-any -- custom event not in upstream Message union; EventEmitter accepts any string
528
- messageBus.unsubscribe(SUBAGENT_ACTIVITY_EVENT, subagentListener);
529
- }
530
- // Ensure scheduler has completed (no-op if already resolved)
531
- await schedulerPromise;
532
- // Process completed tool calls
533
- for (const completed of completedToolCalls) {
534
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- accessing optional field on CompletedToolCall union
535
- const duration = 'durationMs' in completed ? completed['durationMs'] : undefined;
536
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- inner_tool_calls from subagent data
537
- const innerCalls = completed.response.data?.['inner_tool_calls'];
538
- // Accumulate tool call summary for audit
539
- auditToolCalls.push({
540
- tool_name: completed.request.name,
541
- tool_id: completed.request.callId,
542
- args: completed.request.args,
543
- status: completed.response.error ? 'error' : 'success',
544
- duration_ms: duration,
545
- error: completed.response.error?.message,
546
- result: extractResultText(completed.response.responseParts),
547
- inner_tool_calls: innerCalls,
548
- });
549
- // Most subagent events were streamed in real-time above.
550
- // The COMPLETE event (agent's final summary) may be missed due to race
551
- // conditions, so emit it from the batch data as a fallback.
552
- if (completed.request.name === 'dispatch' && completed.response.data) {
553
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- subagent_events from dispatch tool data
554
- const batchEvents = completed.response.data['subagent_events'];
555
- if (batchEvents) {
556
- for (const evt of batchEvents) {
557
- if (evt.type === 'COMPLETE' && typeof evt.data['text'] === 'string') {
558
- yield {
559
- type: SSEEventType.SubagentEvent,
560
- parent_tool_id: completed.request.callId,
561
- agent_name: evt.agentName,
562
- event_type: 'complete',
563
- text: evt.data['text'],
564
- timestamp: new Date().toISOString(),
565
- };
566
- }
567
- }
568
- }
569
- }
570
- if (completed.request.name === PRESENT_TOOL_NAME && !completed.response.error) {
571
- // Emit a widget event instead of tool_call_result for the present tool
572
- const args = completed.request.args;
573
- const widgetType = String(args['widget'] ?? 'unknown');
574
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- LLM-provided data object
575
- const widgetData = args['data'] ?? {};
576
- widgetEvents.push({ widgetType, data: widgetData });
577
- contentBlockOrder.push({ type: 'widget', widgetType, data: widgetData });
578
- yield {
579
- type: SSEEventType.Widget,
580
- widget_type: widgetType,
581
- data: widgetData,
582
- timestamp: new Date().toISOString(),
583
- };
584
- }
585
- else {
586
- trackToolCall(completed.request.callId);
587
- yield {
588
- type: SSEEventType.ToolCallResult,
589
- tool_id: completed.request.callId,
590
- status: completed.response.error ? 'error' : 'success',
591
- result: extractResultText(completed.response.responseParts),
592
- duration_ms: duration,
593
- error: completed.response.error?.message,
594
- timestamp: new Date().toISOString(),
595
- };
596
- }
597
- // Track skill activations
598
- if (completed.request.name === ACTIVATE_SKILL_TOOL_NAME &&
599
- !completed.response.error) {
600
- const skillName = String(completed.request.args['name'] ?? '');
601
- if (skillName) {
602
- skillsActivated.push(skillName);
603
- yield {
604
- type: SSEEventType.SkillActivated,
605
- skill_name: skillName,
606
- timestamp: new Date().toISOString(),
607
- };
608
- }
609
- }
610
- if (completed.response.responseParts) {
611
- toolResponseParts.push(...completed.response.responseParts);
612
- }
613
- }
614
- // Record tool calls
615
- try {
616
- const currentModel = geminiClient.getCurrentSequenceModel() ?? config.getModel();
617
- geminiClient
618
- .getChat()
619
- .recordCompletedToolCalls(currentModel, completedToolCalls);
620
- }
621
- catch {
622
- // Non-critical
623
- }
624
- const stopTool = completedToolCalls.find((tc) => tc.response.errorType === ToolErrorType.STOP_EXECUTION);
625
- if (stopTool) {
626
- logSessionCompleted(hooks, session.id, message, responseText, turnCount, auditToolCalls, skillsActivated, auditStatus, auditError, sessionStartMs, geminiClient.getCurrentSequenceModel() ?? config.getModel(), tokens);
627
- accumulateAssistantAndSave(session, hooks, responseText, auditToolCalls, skillsActivated, widgetEvents, contentBlockOrder, 'completed');
628
- yield {
629
- type: SSEEventType.Done,
630
- timestamp: new Date().toISOString(),
631
- usage: {
632
- input_tokens: tokens.inputTokens,
633
- output_tokens: tokens.outputTokens,
634
- cached_tokens: tokens.cachedTokens,
635
- total_tokens: tokens.inputTokens + tokens.outputTokens,
636
- },
637
- };
638
- return;
639
- }
640
- }
641
- currentMessages = [{ role: 'user', parts: toolResponseParts }];
642
- }
643
- else {
644
- break;
645
- }
646
- }
647
- logSessionCompleted(hooks, session.id, message, responseText, turnCount, auditToolCalls, skillsActivated, auditStatus, auditError, sessionStartMs, geminiClient.getCurrentSequenceModel() ?? config.getModel(), tokens);
648
- accumulateAssistantAndSave(session, hooks, responseText, auditToolCalls, skillsActivated, widgetEvents, contentBlockOrder, auditStatus === 'completed' ? 'completed' : 'error');
649
- yield {
650
- type: SSEEventType.Done,
651
- timestamp: new Date().toISOString(),
652
- usage: {
653
- input_tokens: tokens.inputTokens,
654
- output_tokens: tokens.outputTokens,
655
- cached_tokens: tokens.cachedTokens,
656
- total_tokens: tokens.inputTokens + tokens.outputTokens,
657
- },
658
- };
659
- }
660
- /**
661
- * Accumulate the assistant response message and fire-and-forget save to platform-api.
662
- */
663
- function accumulateAssistantAndSave(session, hooks, responseText, toolCalls, skillsActivated, widgetEvents, contentBlocks, status) {
664
- const assistantMsg = {
665
- type: 'assistant_text',
666
- id: `msg-${Date.now()}`,
667
- text: responseText,
668
- timestamp: new Date().toISOString(),
669
- toolCalls: toolCalls.map((tc) => ({
670
- toolName: tc.tool_name,
671
- toolId: tc.tool_id,
672
- args: tc.args,
673
- status: tc.status,
674
- duration_ms: tc.duration_ms,
675
- error: tc.error,
676
- result: tc.result,
677
- inner_tool_calls: tc.inner_tool_calls,
678
- })),
679
- skillActivations: skillsActivated,
680
- widgets: widgetEvents.map((w) => ({
681
- widgetType: w.widgetType,
682
- data: w.data,
683
- })),
684
- contentBlocks,
685
- };
686
- session.accumulatedMessages.push(assistantMsg);
687
- hooks?.onSessionPersist?.(session.id, session.accumulatedMessages, status, {
688
- model: session.model,
689
- provider: session.provider,
690
- });
691
- }
692
- function logSessionCompleted(hooks, sessionId, message, response, turns, toolCalls, skillsActivated, status, error, startMs, model, tokens) {
693
- if (!hooks)
694
- return;
695
- const details = {
696
- message,
697
- response,
698
- turns,
699
- duration_ms: Date.now() - startMs,
700
- status,
701
- tool_calls: toolCalls,
702
- skills_activated: skillsActivated,
703
- };
704
- if (error) {
705
- details['error'] = error;
706
- }
707
- hooks.onAuditLog?.({
708
- event: 'session_completed',
709
- resource_name: sessionId,
710
- details,
711
- });
712
- const taskAgentRuns = toolCalls.filter((tc) => tc.tool_name === 'dispatch').length;
713
- hooks.onUsageReport?.({
714
- model: model ?? 'unknown',
715
- taskAgentRuns,
716
- tokens: tokens ?? { inputTokens: 0, outputTokens: 0, cachedTokens: 0 },
717
- });
718
- }
719
- //# sourceMappingURL=session-runner.js.map