@adonis-agora/agent 0.61.0 → 0.63.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 (664) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/README.md +12 -7
  3. package/dist/configure.d.ts +7 -5
  4. package/dist/configure.d.ts.map +1 -1
  5. package/dist/configure.js +7 -5
  6. package/dist/configure.js.map +1 -1
  7. package/dist/providers/a2a_provider.d.ts +14 -0
  8. package/dist/providers/a2a_provider.d.ts.map +1 -0
  9. package/dist/providers/a2a_provider.js +136 -0
  10. package/dist/providers/a2a_provider.js.map +1 -0
  11. package/dist/providers/agent_provider.d.ts.map +1 -1
  12. package/dist/providers/agent_provider.js +81 -25
  13. package/dist/providers/agent_provider.js.map +1 -1
  14. package/dist/providers/mcp_provider.d.ts +3 -0
  15. package/dist/providers/mcp_provider.d.ts.map +1 -1
  16. package/dist/providers/mcp_provider.js +147 -62
  17. package/dist/providers/mcp_provider.js.map +1 -1
  18. package/dist/src/a2a/auth.d.ts +67 -0
  19. package/dist/src/a2a/auth.d.ts.map +1 -0
  20. package/dist/src/a2a/auth.js +47 -0
  21. package/dist/src/a2a/auth.js.map +1 -0
  22. package/dist/src/a2a/define_config.d.ts +74 -0
  23. package/dist/src/a2a/define_config.d.ts.map +1 -0
  24. package/dist/src/a2a/define_config.js +5 -0
  25. package/dist/src/a2a/define_config.js.map +1 -0
  26. package/dist/src/a2a/gate.d.ts +23 -0
  27. package/dist/src/a2a/gate.d.ts.map +1 -0
  28. package/dist/src/a2a/gate.js +56 -0
  29. package/dist/src/a2a/gate.js.map +1 -0
  30. package/dist/src/a2a/handler.d.ts +65 -0
  31. package/dist/src/a2a/handler.d.ts.map +1 -0
  32. package/dist/src/a2a/handler.js +322 -0
  33. package/dist/src/a2a/handler.js.map +1 -0
  34. package/dist/src/a2a/index.d.ts +15 -0
  35. package/dist/src/a2a/index.d.ts.map +1 -0
  36. package/dist/src/a2a/index.js +9 -0
  37. package/dist/src/a2a/index.js.map +1 -0
  38. package/dist/src/a2a/permission-tool.d.ts +17 -0
  39. package/dist/src/a2a/permission-tool.d.ts.map +1 -0
  40. package/dist/src/a2a/permission-tool.js +70 -0
  41. package/dist/src/a2a/permission-tool.js.map +1 -0
  42. package/dist/src/a2a/protocol.d.ts +100 -0
  43. package/dist/src/a2a/protocol.d.ts.map +1 -0
  44. package/dist/src/a2a/protocol.js +106 -0
  45. package/dist/src/a2a/protocol.js.map +1 -0
  46. package/dist/src/a2a/runtime.d.ts +6 -0
  47. package/dist/src/a2a/runtime.d.ts.map +1 -0
  48. package/dist/src/a2a/runtime.js +13 -0
  49. package/dist/src/a2a/runtime.js.map +1 -0
  50. package/dist/src/a2a/server_middleware.d.ts +13 -0
  51. package/dist/src/a2a/server_middleware.d.ts.map +1 -0
  52. package/dist/src/a2a/server_middleware.js +18 -0
  53. package/dist/src/a2a/server_middleware.js.map +1 -0
  54. package/dist/src/a2a/store.d.ts +79 -0
  55. package/dist/src/a2a/store.d.ts.map +1 -0
  56. package/dist/src/a2a/store.js +151 -0
  57. package/dist/src/a2a/store.js.map +1 -0
  58. package/dist/src/a2a/turn.d.ts +80 -0
  59. package/dist/src/a2a/turn.d.ts.map +1 -0
  60. package/dist/src/a2a/turn.js +211 -0
  61. package/dist/src/a2a/turn.js.map +1 -0
  62. package/dist/src/action-proposal-executor.d.ts +3 -0
  63. package/dist/src/action-proposal-executor.d.ts.map +1 -1
  64. package/dist/src/action-proposal-executor.js +10 -0
  65. package/dist/src/action-proposal-executor.js.map +1 -1
  66. package/dist/src/action-proposal-service.d.ts +7 -2
  67. package/dist/src/action-proposal-service.d.ts.map +1 -1
  68. package/dist/src/action-proposal-service.js +21 -16
  69. package/dist/src/action-proposal-service.js.map +1 -1
  70. package/dist/src/action-proposal-text.d.ts +42 -3
  71. package/dist/src/action-proposal-text.d.ts.map +1 -1
  72. package/dist/src/action-proposal-text.js +80 -12
  73. package/dist/src/action-proposal-text.js.map +1 -1
  74. package/dist/src/action-proposal-worker.d.ts +2 -1
  75. package/dist/src/action-proposal-worker.d.ts.map +1 -1
  76. package/dist/src/action-proposal-worker.js +9 -2
  77. package/dist/src/action-proposal-worker.js.map +1 -1
  78. package/dist/src/actor-resolver.d.ts +12 -4
  79. package/dist/src/actor-resolver.d.ts.map +1 -1
  80. package/dist/src/actor-resolver.js +24 -7
  81. package/dist/src/actor-resolver.js.map +1 -1
  82. package/dist/src/ag-ui/adapter.d.ts.map +1 -1
  83. package/dist/src/ag-ui/adapter.js +115 -17
  84. package/dist/src/ag-ui/adapter.js.map +1 -1
  85. package/dist/src/ag-ui/core/encoder.d.ts +106 -0
  86. package/dist/src/ag-ui/core/encoder.d.ts.map +1 -0
  87. package/dist/src/ag-ui/core/encoder.js +534 -0
  88. package/dist/src/ag-ui/core/encoder.js.map +1 -0
  89. package/dist/src/ag-ui/core/index.d.ts +12 -0
  90. package/dist/src/ag-ui/core/index.d.ts.map +1 -0
  91. package/dist/src/ag-ui/core/index.js +12 -0
  92. package/dist/src/ag-ui/core/index.js.map +1 -0
  93. package/dist/src/ag-ui/core/input.d.ts +92 -0
  94. package/dist/src/ag-ui/core/input.d.ts.map +1 -0
  95. package/dist/src/ag-ui/core/input.js +246 -0
  96. package/dist/src/ag-ui/core/input.js.map +1 -0
  97. package/dist/src/ag-ui/core/interrupt-id.d.ts +31 -0
  98. package/dist/src/ag-ui/core/interrupt-id.d.ts.map +1 -0
  99. package/dist/src/ag-ui/core/interrupt-id.js +48 -0
  100. package/dist/src/ag-ui/core/interrupt-id.js.map +1 -0
  101. package/dist/src/ag-ui/{proposal-decision.d.ts → core/proposal-decision.d.ts} +1 -1
  102. package/dist/src/ag-ui/core/proposal-decision.d.ts.map +1 -0
  103. package/dist/src/ag-ui/{proposal-decision.js → core/proposal-decision.js} +3 -6
  104. package/dist/src/ag-ui/core/proposal-decision.js.map +1 -0
  105. package/dist/src/ag-ui/core/stream.d.ts +49 -0
  106. package/dist/src/ag-ui/core/stream.d.ts.map +1 -0
  107. package/dist/src/ag-ui/core/stream.js +90 -0
  108. package/dist/src/ag-ui/core/stream.js.map +1 -0
  109. package/dist/src/ag-ui/core/types.d.ts +249 -0
  110. package/dist/src/ag-ui/core/types.d.ts.map +1 -0
  111. package/dist/src/ag-ui/core/types.js +35 -0
  112. package/dist/src/ag-ui/core/types.js.map +1 -0
  113. package/dist/src/ag-ui/encoder.d.ts +3 -4
  114. package/dist/src/ag-ui/encoder.d.ts.map +1 -1
  115. package/dist/src/ag-ui/encoder.js +10 -11
  116. package/dist/src/ag-ui/encoder.js.map +1 -1
  117. package/dist/src/ag-ui/frames.d.ts +8 -5
  118. package/dist/src/ag-ui/frames.d.ts.map +1 -1
  119. package/dist/src/ag-ui/frames.js +21 -7
  120. package/dist/src/ag-ui/frames.js.map +1 -1
  121. package/dist/src/ag-ui/index.d.ts +3 -5
  122. package/dist/src/ag-ui/index.d.ts.map +1 -1
  123. package/dist/src/ag-ui/index.js +3 -5
  124. package/dist/src/ag-ui/index.js.map +1 -1
  125. package/dist/src/ag-ui/stream.d.ts +3 -4
  126. package/dist/src/ag-ui/stream.d.ts.map +1 -1
  127. package/dist/src/ag-ui/stream.js +4 -5
  128. package/dist/src/ag-ui/stream.js.map +1 -1
  129. package/dist/src/agent-deps-factory.d.ts +3 -0
  130. package/dist/src/agent-deps-factory.d.ts.map +1 -1
  131. package/dist/src/agent-deps-factory.js +3 -0
  132. package/dist/src/agent-deps-factory.js.map +1 -1
  133. package/dist/src/agent-deps.d.ts +3 -0
  134. package/dist/src/agent-deps.d.ts.map +1 -1
  135. package/dist/src/agent-deps.js.map +1 -1
  136. package/dist/src/agent-loop.d.ts +4 -3
  137. package/dist/src/agent-loop.d.ts.map +1 -1
  138. package/dist/src/agent-loop.js +50 -25
  139. package/dist/src/agent-loop.js.map +1 -1
  140. package/dist/src/agent-service.d.ts +46 -4
  141. package/dist/src/agent-service.d.ts.map +1 -1
  142. package/dist/src/agent-service.js +87 -11
  143. package/dist/src/agent-service.js.map +1 -1
  144. package/dist/src/ai-sdk/ai-sdk-model.js +4 -1
  145. package/dist/src/ai-sdk/ai-sdk-model.js.map +1 -1
  146. package/dist/src/ai-tool-ref.d.ts +4 -0
  147. package/dist/src/ai-tool-ref.d.ts.map +1 -1
  148. package/dist/src/ai-tool-ref.js +10 -14
  149. package/dist/src/ai-tool-ref.js.map +1 -1
  150. package/dist/src/attachment-limits.d.ts +10 -0
  151. package/dist/src/attachment-limits.d.ts.map +1 -0
  152. package/dist/src/attachment-limits.js +13 -0
  153. package/dist/src/attachment-limits.js.map +1 -0
  154. package/dist/src/channels/adapters/evolution_api.d.ts +49 -0
  155. package/dist/src/channels/adapters/evolution_api.d.ts.map +1 -0
  156. package/dist/src/channels/adapters/evolution_api.js +241 -0
  157. package/dist/src/channels/adapters/evolution_api.js.map +1 -0
  158. package/dist/src/channels/adapters/telegram.d.ts +34 -0
  159. package/dist/src/channels/adapters/telegram.d.ts.map +1 -0
  160. package/dist/src/channels/adapters/telegram.js +196 -0
  161. package/dist/src/channels/adapters/telegram.js.map +1 -0
  162. package/dist/src/channels/adapters/whatsapp_cloud.d.ts +31 -0
  163. package/dist/src/channels/adapters/whatsapp_cloud.d.ts.map +1 -0
  164. package/dist/src/channels/adapters/whatsapp_cloud.js +177 -0
  165. package/dist/src/channels/adapters/whatsapp_cloud.js.map +1 -0
  166. package/dist/src/channels/handler.d.ts +167 -0
  167. package/dist/src/channels/handler.d.ts.map +1 -0
  168. package/dist/src/channels/handler.js +569 -0
  169. package/dist/src/channels/handler.js.map +1 -0
  170. package/dist/src/channels/http.d.ts +45 -0
  171. package/dist/src/channels/http.d.ts.map +1 -0
  172. package/dist/src/channels/http.js +147 -0
  173. package/dist/src/channels/http.js.map +1 -0
  174. package/dist/src/channels/index.d.ts +16 -0
  175. package/dist/src/channels/index.d.ts.map +1 -0
  176. package/dist/src/channels/index.js +15 -0
  177. package/dist/src/channels/index.js.map +1 -0
  178. package/dist/src/channels/markdown.d.ts +12 -0
  179. package/dist/src/channels/markdown.d.ts.map +1 -0
  180. package/dist/src/channels/markdown.js +120 -0
  181. package/dist/src/channels/markdown.js.map +1 -0
  182. package/dist/src/channels/questions.d.ts +43 -0
  183. package/dist/src/channels/questions.d.ts.map +1 -0
  184. package/dist/src/channels/questions.js +90 -0
  185. package/dist/src/channels/questions.js.map +1 -0
  186. package/dist/src/channels/split.d.ts +8 -0
  187. package/dist/src/channels/split.d.ts.map +1 -0
  188. package/dist/src/channels/split.js +45 -0
  189. package/dist/src/channels/split.js.map +1 -0
  190. package/dist/src/channels/store.d.ts +78 -0
  191. package/dist/src/channels/store.d.ts.map +1 -0
  192. package/dist/src/channels/store.js +151 -0
  193. package/dist/src/channels/store.js.map +1 -0
  194. package/dist/src/channels/types.d.ts +138 -0
  195. package/dist/src/channels/types.d.ts.map +1 -0
  196. package/dist/src/channels/types.js +7 -0
  197. package/dist/src/channels/types.js.map +1 -0
  198. package/dist/src/chat-queue-service.d.ts.map +1 -1
  199. package/dist/src/chat-queue-service.js +2 -0
  200. package/dist/src/chat-queue-service.js.map +1 -1
  201. package/dist/src/define_config.d.ts +61 -12
  202. package/dist/src/define_config.d.ts.map +1 -1
  203. package/dist/src/define_config.js.map +1 -1
  204. package/dist/src/engine.d.ts +77 -0
  205. package/dist/src/engine.d.ts.map +1 -0
  206. package/dist/src/engine.js +27 -0
  207. package/dist/src/engine.js.map +1 -0
  208. package/dist/src/genui/builtins.d.ts +73 -3
  209. package/dist/src/genui/builtins.d.ts.map +1 -1
  210. package/dist/src/genui/builtins.js +357 -3
  211. package/dist/src/genui/builtins.js.map +1 -1
  212. package/dist/src/genui/capabilities.d.ts +24 -0
  213. package/dist/src/genui/capabilities.d.ts.map +1 -0
  214. package/dist/src/genui/capabilities.js +81 -0
  215. package/dist/src/genui/capabilities.js.map +1 -0
  216. package/dist/src/genui/catalog.d.ts +86 -0
  217. package/dist/src/genui/catalog.d.ts.map +1 -0
  218. package/dist/src/genui/catalog.js +96 -0
  219. package/dist/src/genui/catalog.js.map +1 -0
  220. package/dist/src/genui/factory.d.ts +7 -14
  221. package/dist/src/genui/factory.d.ts.map +1 -1
  222. package/dist/src/genui/factory.js.map +1 -1
  223. package/dist/src/genui/index.d.ts +4 -12
  224. package/dist/src/genui/index.d.ts.map +1 -1
  225. package/dist/src/genui/index.js +5 -18
  226. package/dist/src/genui/index.js.map +1 -1
  227. package/dist/src/genui/public.d.ts +9 -0
  228. package/dist/src/genui/public.d.ts.map +1 -0
  229. package/dist/src/genui/public.js +9 -0
  230. package/dist/src/genui/public.js.map +1 -0
  231. package/dist/src/genui/registry.d.ts +65 -0
  232. package/dist/src/genui/registry.d.ts.map +1 -0
  233. package/dist/src/genui/registry.js +151 -0
  234. package/dist/src/genui/registry.js.map +1 -0
  235. package/dist/src/genui/schema.d.ts +71 -0
  236. package/dist/src/genui/schema.d.ts.map +1 -0
  237. package/dist/src/genui/schema.js +304 -0
  238. package/dist/src/genui/schema.js.map +1 -0
  239. package/dist/src/genui/text.d.ts +36 -0
  240. package/dist/src/genui/text.d.ts.map +1 -0
  241. package/dist/src/genui/text.js +157 -0
  242. package/dist/src/genui/text.js.map +1 -0
  243. package/dist/src/genui/tools.d.ts +92 -0
  244. package/dist/src/genui/tools.d.ts.map +1 -0
  245. package/dist/src/genui/tools.js +291 -0
  246. package/dist/src/genui/tools.js.map +1 -0
  247. package/dist/src/genui/tree.d.ts +56 -0
  248. package/dist/src/genui/tree.d.ts.map +1 -0
  249. package/dist/src/genui/tree.js +188 -0
  250. package/dist/src/genui/tree.js.map +1 -0
  251. package/dist/src/index.d.ts +6 -3
  252. package/dist/src/index.d.ts.map +1 -1
  253. package/dist/src/index.js +4 -2
  254. package/dist/src/index.js.map +1 -1
  255. package/dist/src/mcp/auth.d.ts +17 -1
  256. package/dist/src/mcp/auth.d.ts.map +1 -1
  257. package/dist/src/mcp/auth.js +14 -3
  258. package/dist/src/mcp/auth.js.map +1 -1
  259. package/dist/src/mcp/define_config.d.ts +81 -2
  260. package/dist/src/mcp/define_config.d.ts.map +1 -1
  261. package/dist/src/mcp/define_config.js.map +1 -1
  262. package/dist/src/mcp/index.d.ts +1 -1
  263. package/dist/src/mcp/index.d.ts.map +1 -1
  264. package/dist/src/mcp/index.js.map +1 -1
  265. package/dist/src/mcp/oauth-resource.d.ts +9 -0
  266. package/dist/src/mcp/oauth-resource.d.ts.map +1 -0
  267. package/dist/src/mcp/oauth-resource.js +16 -0
  268. package/dist/src/mcp/oauth-resource.js.map +1 -0
  269. package/dist/src/mcp/server.d.ts +5 -0
  270. package/dist/src/mcp/server.d.ts.map +1 -1
  271. package/dist/src/mcp/server.js +48 -16
  272. package/dist/src/mcp/server.js.map +1 -1
  273. package/dist/src/negotiated-tool-ui.d.ts.map +1 -1
  274. package/dist/src/negotiated-tool-ui.js +12 -8
  275. package/dist/src/negotiated-tool-ui.js.map +1 -1
  276. package/dist/src/opencode/client.d.ts +202 -0
  277. package/dist/src/opencode/client.d.ts.map +1 -0
  278. package/dist/src/opencode/client.js +2 -0
  279. package/dist/src/opencode/client.js.map +1 -0
  280. package/dist/src/opencode/durable/index.d.ts +33 -0
  281. package/dist/src/opencode/durable/index.d.ts.map +1 -0
  282. package/dist/src/opencode/durable/index.js +38 -0
  283. package/dist/src/opencode/durable/index.js.map +1 -0
  284. package/dist/src/opencode/durable/runner.d.ts +36 -0
  285. package/dist/src/opencode/durable/runner.d.ts.map +1 -0
  286. package/dist/src/opencode/durable/runner.js +88 -0
  287. package/dist/src/opencode/durable/runner.js.map +1 -0
  288. package/dist/src/opencode/durable/workflow.d.ts +40 -0
  289. package/dist/src/opencode/durable/workflow.d.ts.map +1 -0
  290. package/dist/src/opencode/durable/workflow.js +106 -0
  291. package/dist/src/opencode/durable/workflow.js.map +1 -0
  292. package/dist/src/opencode/engine.d.ts +48 -0
  293. package/dist/src/opencode/engine.d.ts.map +1 -0
  294. package/dist/src/opencode/engine.js +98 -0
  295. package/dist/src/opencode/engine.js.map +1 -0
  296. package/dist/src/opencode/event-hub.d.ts +23 -0
  297. package/dist/src/opencode/event-hub.d.ts.map +1 -0
  298. package/dist/src/opencode/event-hub.js +99 -0
  299. package/dist/src/opencode/event-hub.js.map +1 -0
  300. package/dist/src/opencode/forms.d.ts +19 -0
  301. package/dist/src/opencode/forms.d.ts.map +1 -0
  302. package/dist/src/opencode/forms.js +82 -0
  303. package/dist/src/opencode/forms.js.map +1 -0
  304. package/dist/src/opencode/host.d.ts +179 -0
  305. package/dist/src/opencode/host.d.ts.map +1 -0
  306. package/dist/src/opencode/host.js +34 -0
  307. package/dist/src/opencode/host.js.map +1 -0
  308. package/dist/src/opencode/index.d.ts +15 -0
  309. package/dist/src/opencode/index.d.ts.map +1 -0
  310. package/dist/src/opencode/index.js +9 -0
  311. package/dist/src/opencode/index.js.map +1 -0
  312. package/dist/src/opencode/log.d.ts +9 -0
  313. package/dist/src/opencode/log.d.ts.map +1 -0
  314. package/dist/src/opencode/log.js +15 -0
  315. package/dist/src/opencode/log.js.map +1 -0
  316. package/dist/src/opencode/mcp.d.ts +60 -0
  317. package/dist/src/opencode/mcp.d.ts.map +1 -0
  318. package/dist/src/opencode/mcp.js +258 -0
  319. package/dist/src/opencode/mcp.js.map +1 -0
  320. package/dist/src/opencode/runner.d.ts +40 -0
  321. package/dist/src/opencode/runner.d.ts.map +1 -0
  322. package/dist/src/opencode/runner.js +125 -0
  323. package/dist/src/opencode/runner.js.map +1 -0
  324. package/dist/src/opencode/turn.d.ts +167 -0
  325. package/dist/src/opencode/turn.d.ts.map +1 -0
  326. package/dist/src/opencode/turn.js +761 -0
  327. package/dist/src/opencode/turn.js.map +1 -0
  328. package/dist/src/opencode/turns.d.ts +247 -0
  329. package/dist/src/opencode/turns.d.ts.map +1 -0
  330. package/dist/src/opencode/turns.js +867 -0
  331. package/dist/src/opencode/turns.js.map +1 -0
  332. package/dist/src/personas.d.ts.map +1 -1
  333. package/dist/src/personas.js +4 -1
  334. package/dist/src/personas.js.map +1 -1
  335. package/dist/src/react/ag-ui.d.ts +4 -2
  336. package/dist/src/react/ag-ui.d.ts.map +1 -1
  337. package/dist/src/react/ag-ui.js +2 -2
  338. package/dist/src/react/ag-ui.js.map +1 -1
  339. package/dist/src/react/client.d.ts +1 -1
  340. package/dist/src/react/client.d.ts.map +1 -1
  341. package/dist/src/react/client.js +1 -1
  342. package/dist/src/react/client.js.map +1 -1
  343. package/dist/src/react/core/ag-ui-backend.d.ts +109 -0
  344. package/dist/src/react/core/ag-ui-backend.d.ts.map +1 -0
  345. package/dist/src/react/core/ag-ui-backend.js +574 -0
  346. package/dist/src/react/core/ag-ui-backend.js.map +1 -0
  347. package/dist/src/react/core/agent-chat-transport.d.ts +187 -0
  348. package/dist/src/react/core/agent-chat-transport.d.ts.map +1 -0
  349. package/dist/src/react/core/agent-chat-transport.js +817 -0
  350. package/dist/src/react/core/agent-chat-transport.js.map +1 -0
  351. package/dist/src/react/core/approvals/countdown.d.ts +22 -0
  352. package/dist/src/react/core/approvals/countdown.d.ts.map +1 -0
  353. package/dist/src/react/core/approvals/countdown.js +39 -0
  354. package/dist/src/react/core/approvals/countdown.js.map +1 -0
  355. package/dist/src/react/core/approvals/proposals.d.ts +15 -0
  356. package/dist/src/react/core/approvals/proposals.d.ts.map +1 -0
  357. package/dist/src/react/core/approvals/proposals.js +82 -0
  358. package/dist/src/react/core/approvals/proposals.js.map +1 -0
  359. package/dist/src/react/core/approvals/use-action-proposals.d.ts +10 -0
  360. package/dist/src/react/core/approvals/use-action-proposals.d.ts.map +1 -0
  361. package/dist/src/react/core/approvals/use-action-proposals.js +86 -0
  362. package/dist/src/react/core/approvals/use-action-proposals.js.map +1 -0
  363. package/dist/src/react/core/attachments/files.d.ts +39 -0
  364. package/dist/src/react/core/attachments/files.d.ts.map +1 -0
  365. package/dist/src/react/core/attachments/files.js +89 -0
  366. package/dist/src/react/core/attachments/files.js.map +1 -0
  367. package/dist/src/react/core/attachments/use-attachments.d.ts +106 -0
  368. package/dist/src/react/core/attachments/use-attachments.d.ts.map +1 -0
  369. package/dist/src/react/core/attachments/use-attachments.js +217 -0
  370. package/dist/src/react/core/attachments/use-attachments.js.map +1 -0
  371. package/dist/src/react/core/backend.d.ts +245 -0
  372. package/dist/src/react/core/backend.d.ts.map +1 -0
  373. package/dist/src/react/core/backend.js +21 -0
  374. package/dist/src/react/core/backend.js.map +1 -0
  375. package/dist/src/react/core/background-runs.d.ts +32 -0
  376. package/dist/src/react/core/background-runs.d.ts.map +1 -0
  377. package/dist/src/react/core/background-runs.js +47 -0
  378. package/dist/src/react/core/background-runs.js.map +1 -0
  379. package/dist/src/react/core/catalog/use-agents.d.ts +31 -0
  380. package/dist/src/react/core/catalog/use-agents.d.ts.map +1 -0
  381. package/dist/src/react/core/catalog/use-agents.js +28 -0
  382. package/dist/src/react/core/catalog/use-agents.js.map +1 -0
  383. package/dist/src/react/core/catalog/use-models.d.ts +41 -0
  384. package/dist/src/react/core/catalog/use-models.d.ts.map +1 -0
  385. package/dist/src/react/core/catalog/use-models.js +35 -0
  386. package/dist/src/react/core/catalog/use-models.js.map +1 -0
  387. package/dist/src/react/core/catalog/use-resource.d.ts +12 -0
  388. package/dist/src/react/core/catalog/use-resource.d.ts.map +1 -0
  389. package/dist/src/react/core/catalog/use-resource.js +41 -0
  390. package/dist/src/react/core/catalog/use-resource.js.map +1 -0
  391. package/dist/src/react/core/client-wire.d.ts +14 -0
  392. package/dist/src/react/core/client-wire.d.ts.map +1 -0
  393. package/dist/src/react/core/client-wire.js +2 -0
  394. package/dist/src/react/core/client-wire.js.map +1 -0
  395. package/dist/src/react/core/client.d.ts +222 -0
  396. package/dist/src/react/core/client.d.ts.map +1 -0
  397. package/dist/src/react/core/client.js +435 -0
  398. package/dist/src/react/core/client.js.map +1 -0
  399. package/dist/src/react/core/components/ambient-ui.d.ts +22 -0
  400. package/dist/src/react/core/components/ambient-ui.d.ts.map +1 -0
  401. package/dist/src/react/core/components/ambient-ui.js +30 -0
  402. package/dist/src/react/core/components/ambient-ui.js.map +1 -0
  403. package/dist/src/react/core/components/chat-input.d.ts +44 -0
  404. package/dist/src/react/core/components/chat-input.d.ts.map +1 -0
  405. package/dist/src/react/core/components/chat-input.js +69 -0
  406. package/dist/src/react/core/components/chat-input.js.map +1 -0
  407. package/dist/src/react/core/components/index.d.ts +7 -0
  408. package/dist/src/react/core/components/index.d.ts.map +1 -0
  409. package/dist/src/react/core/components/index.js +7 -0
  410. package/dist/src/react/core/components/index.js.map +1 -0
  411. package/dist/src/react/core/components/message-item.d.ts +101 -0
  412. package/dist/src/react/core/components/message-item.d.ts.map +1 -0
  413. package/dist/src/react/core/components/message-item.js +118 -0
  414. package/dist/src/react/core/components/message-item.js.map +1 -0
  415. package/dist/src/react/core/components/message-list.d.ts +85 -0
  416. package/dist/src/react/core/components/message-list.d.ts.map +1 -0
  417. package/dist/src/react/core/components/message-list.js +45 -0
  418. package/dist/src/react/core/components/message-list.js.map +1 -0
  419. package/dist/src/react/core/components/speech-languages.d.ts +22 -0
  420. package/dist/src/react/core/components/speech-languages.d.ts.map +1 -0
  421. package/dist/src/react/core/components/speech-languages.js +38 -0
  422. package/dist/src/react/core/components/speech-languages.js.map +1 -0
  423. package/dist/src/react/core/components/use-speech-recognition.d.ts +19 -0
  424. package/dist/src/react/core/components/use-speech-recognition.d.ts.map +1 -0
  425. package/dist/src/react/core/components/use-speech-recognition.js +92 -0
  426. package/dist/src/react/core/components/use-speech-recognition.js.map +1 -0
  427. package/dist/src/react/core/composer/index.d.ts +4 -0
  428. package/dist/src/react/core/composer/index.d.ts.map +1 -0
  429. package/dist/src/react/core/composer/index.js +4 -0
  430. package/dist/src/react/core/composer/index.js.map +1 -0
  431. package/dist/src/react/core/composer/model.d.ts +83 -0
  432. package/dist/src/react/core/composer/model.d.ts.map +1 -0
  433. package/dist/src/react/core/composer/model.js +53 -0
  434. package/dist/src/react/core/composer/model.js.map +1 -0
  435. package/dist/src/react/core/composer/skills-source.d.ts +29 -0
  436. package/dist/src/react/core/composer/skills-source.d.ts.map +1 -0
  437. package/dist/src/react/core/composer/skills-source.js +61 -0
  438. package/dist/src/react/core/composer/skills-source.js.map +1 -0
  439. package/dist/src/react/core/composer/use-composer-autocomplete.d.ts +78 -0
  440. package/dist/src/react/core/composer/use-composer-autocomplete.d.ts.map +1 -0
  441. package/dist/src/react/core/composer/use-composer-autocomplete.js +244 -0
  442. package/dist/src/react/core/composer/use-composer-autocomplete.js.map +1 -0
  443. package/dist/src/react/core/config/use-agent-config.d.ts +21 -0
  444. package/dist/src/react/core/config/use-agent-config.d.ts.map +1 -0
  445. package/dist/src/react/core/config/use-agent-config.js +57 -0
  446. package/dist/src/react/core/config/use-agent-config.js.map +1 -0
  447. package/dist/src/react/core/elicitation/answers.d.ts +22 -0
  448. package/dist/src/react/core/elicitation/answers.d.ts.map +1 -0
  449. package/dist/src/react/core/elicitation/answers.js +65 -0
  450. package/dist/src/react/core/elicitation/answers.js.map +1 -0
  451. package/dist/src/react/core/feedback/use-message-feedback.d.ts +32 -0
  452. package/dist/src/react/core/feedback/use-message-feedback.d.ts.map +1 -0
  453. package/dist/src/react/core/feedback/use-message-feedback.js +106 -0
  454. package/dist/src/react/core/feedback/use-message-feedback.js.map +1 -0
  455. package/dist/src/react/core/genui/generative-ui.d.ts +76 -0
  456. package/dist/src/react/core/genui/generative-ui.d.ts.map +1 -0
  457. package/dist/src/react/core/genui/generative-ui.js +210 -0
  458. package/dist/src/react/core/genui/generative-ui.js.map +1 -0
  459. package/dist/src/react/core/genui/index.d.ts +5 -0
  460. package/dist/src/react/core/genui/index.d.ts.map +1 -0
  461. package/dist/src/react/core/genui/index.js +5 -0
  462. package/dist/src/react/core/genui/index.js.map +1 -0
  463. package/dist/src/react/core/genui/json-render.d.ts +54 -0
  464. package/dist/src/react/core/genui/json-render.d.ts.map +1 -0
  465. package/dist/src/react/core/genui/json-render.js +64 -0
  466. package/dist/src/react/core/genui/json-render.js.map +1 -0
  467. package/dist/src/react/core/genui/playwright.d.ts +12 -0
  468. package/dist/src/react/core/genui/playwright.d.ts.map +1 -0
  469. package/dist/src/react/core/genui/playwright.js +141 -0
  470. package/dist/src/react/core/genui/playwright.js.map +1 -0
  471. package/dist/src/react/core/genui/react-registry.d.ts +22 -0
  472. package/dist/src/react/core/genui/react-registry.d.ts.map +1 -0
  473. package/dist/src/react/core/genui/react-registry.js +72 -0
  474. package/dist/src/react/core/genui/react-registry.js.map +1 -0
  475. package/dist/src/react/core/genui/server.d.ts +32 -0
  476. package/dist/src/react/core/genui/server.d.ts.map +1 -0
  477. package/dist/src/react/core/genui/server.js +66 -0
  478. package/dist/src/react/core/genui/server.js.map +1 -0
  479. package/dist/src/react/core/genui/types.d.ts +98 -0
  480. package/dist/src/react/core/genui/types.d.ts.map +1 -0
  481. package/dist/src/react/core/genui/types.js +3 -0
  482. package/dist/src/react/core/genui/types.js.map +1 -0
  483. package/dist/src/react/core/genui/use-generative-ui.d.ts +42 -0
  484. package/dist/src/react/core/genui/use-generative-ui.d.ts.map +1 -0
  485. package/dist/src/react/core/genui/use-generative-ui.js +186 -0
  486. package/dist/src/react/core/genui/use-generative-ui.js.map +1 -0
  487. package/dist/src/react/core/http-error.d.ts +33 -0
  488. package/dist/src/react/core/http-error.d.ts.map +1 -0
  489. package/dist/src/react/core/http-error.js +47 -0
  490. package/dist/src/react/core/http-error.js.map +1 -0
  491. package/dist/src/react/core/index.d.ts +35 -0
  492. package/dist/src/react/core/index.d.ts.map +1 -0
  493. package/dist/src/react/core/index.js +34 -0
  494. package/dist/src/react/core/index.js.map +1 -0
  495. package/dist/src/react/core/markdown/agent-markdown.d.ts +39 -0
  496. package/dist/src/react/core/markdown/agent-markdown.d.ts.map +1 -0
  497. package/dist/src/react/core/markdown/agent-markdown.js +22 -0
  498. package/dist/src/react/core/markdown/agent-markdown.js.map +1 -0
  499. package/dist/src/react/core/markdown/index.d.ts +2 -0
  500. package/dist/src/react/core/markdown/index.d.ts.map +1 -0
  501. package/dist/src/react/core/markdown/index.js +2 -0
  502. package/dist/src/react/core/markdown/index.js.map +1 -0
  503. package/dist/src/react/core/media/index.d.ts +64 -0
  504. package/dist/src/react/core/media/index.d.ts.map +1 -0
  505. package/dist/src/react/core/media/index.js +135 -0
  506. package/dist/src/react/core/media/index.js.map +1 -0
  507. package/dist/src/react/core/media/tus.d.ts +13 -0
  508. package/dist/src/react/core/media/tus.d.ts.map +1 -0
  509. package/dist/src/react/core/media/tus.js +59 -0
  510. package/dist/src/react/core/media/tus.js.map +1 -0
  511. package/dist/src/react/core/presentation/phrasing.d.ts +25 -0
  512. package/dist/src/react/core/presentation/phrasing.d.ts.map +1 -0
  513. package/dist/src/react/core/presentation/phrasing.js +58 -0
  514. package/dist/src/react/core/presentation/phrasing.js.map +1 -0
  515. package/dist/src/react/core/presentation/result-view.d.ts +43 -0
  516. package/dist/src/react/core/presentation/result-view.d.ts.map +1 -0
  517. package/dist/src/react/core/presentation/result-view.js +90 -0
  518. package/dist/src/react/core/presentation/result-view.js.map +1 -0
  519. package/dist/src/react/core/presentation/tool-activity.d.ts +106 -0
  520. package/dist/src/react/core/presentation/tool-activity.d.ts.map +1 -0
  521. package/dist/src/react/core/presentation/tool-activity.js +165 -0
  522. package/dist/src/react/core/presentation/tool-activity.js.map +1 -0
  523. package/dist/src/react/core/presentation/use-tool-catalog.d.ts +39 -0
  524. package/dist/src/react/core/presentation/use-tool-catalog.d.ts.map +1 -0
  525. package/dist/src/react/core/presentation/use-tool-catalog.js +77 -0
  526. package/dist/src/react/core/presentation/use-tool-catalog.js.map +1 -0
  527. package/dist/src/react/core/provider.d.ts +68 -0
  528. package/dist/src/react/core/provider.d.ts.map +1 -0
  529. package/dist/src/react/core/provider.js +61 -0
  530. package/dist/src/react/core/provider.js.map +1 -0
  531. package/dist/src/react/core/queue/model.d.ts +73 -0
  532. package/dist/src/react/core/queue/model.d.ts.map +1 -0
  533. package/dist/src/react/core/queue/model.js +2 -0
  534. package/dist/src/react/core/queue/model.js.map +1 -0
  535. package/dist/src/react/core/quota/use-quota.d.ts +35 -0
  536. package/dist/src/react/core/quota/use-quota.d.ts.map +1 -0
  537. package/dist/src/react/core/quota/use-quota.js +47 -0
  538. package/dist/src/react/core/quota/use-quota.js.map +1 -0
  539. package/dist/src/react/core/reasoning/timing.d.ts +38 -0
  540. package/dist/src/react/core/reasoning/timing.d.ts.map +1 -0
  541. package/dist/src/react/core/reasoning/timing.js +73 -0
  542. package/dist/src/react/core/reasoning/timing.js.map +1 -0
  543. package/dist/src/react/core/run-errors.d.ts +37 -0
  544. package/dist/src/react/core/run-errors.d.ts.map +1 -0
  545. package/dist/src/react/core/run-errors.js +37 -0
  546. package/dist/src/react/core/run-errors.js.map +1 -0
  547. package/dist/src/react/core/stored-message-to-ui-message.d.ts +4 -0
  548. package/dist/src/react/core/stored-message-to-ui-message.d.ts.map +1 -0
  549. package/dist/src/react/core/stored-message-to-ui-message.js +216 -0
  550. package/dist/src/react/core/stored-message-to-ui-message.js.map +1 -0
  551. package/dist/src/react/core/stored-thread-to-ui-messages.d.ts +82 -0
  552. package/dist/src/react/core/stored-thread-to-ui-messages.d.ts.map +1 -0
  553. package/dist/src/react/core/stored-thread-to-ui-messages.js +116 -0
  554. package/dist/src/react/core/stored-thread-to-ui-messages.js.map +1 -0
  555. package/dist/src/react/core/threads/threads-events.d.ts +22 -0
  556. package/dist/src/react/core/threads/threads-events.d.ts.map +1 -0
  557. package/dist/src/react/core/threads/threads-events.js +21 -0
  558. package/dist/src/react/core/threads/threads-events.js.map +1 -0
  559. package/dist/src/react/core/threads/use-threads.d.ts +31 -0
  560. package/dist/src/react/core/threads/use-threads.d.ts.map +1 -0
  561. package/dist/src/react/core/threads/use-threads.js +81 -0
  562. package/dist/src/react/core/threads/use-threads.js.map +1 -0
  563. package/dist/src/react/core/transcript/index.d.ts +4 -0
  564. package/dist/src/react/core/transcript/index.d.ts.map +1 -0
  565. package/dist/src/react/core/transcript/index.js +4 -0
  566. package/dist/src/react/core/transcript/index.js.map +1 -0
  567. package/dist/src/react/core/transcript/model.d.ts +399 -0
  568. package/dist/src/react/core/transcript/model.d.ts.map +1 -0
  569. package/dist/src/react/core/transcript/model.js +725 -0
  570. package/dist/src/react/core/transcript/model.js.map +1 -0
  571. package/dist/src/react/core/transcript/use-chat-transcript.d.ts +254 -0
  572. package/dist/src/react/core/transcript/use-chat-transcript.d.ts.map +1 -0
  573. package/dist/src/react/core/transcript/use-chat-transcript.js +572 -0
  574. package/dist/src/react/core/transcript/use-chat-transcript.js.map +1 -0
  575. package/dist/src/react/core/transcript/use-stick-to-bottom.d.ts +33 -0
  576. package/dist/src/react/core/transcript/use-stick-to-bottom.d.ts.map +1 -0
  577. package/dist/src/react/core/transcript/use-stick-to-bottom.js +48 -0
  578. package/dist/src/react/core/transcript/use-stick-to-bottom.js.map +1 -0
  579. package/dist/src/react/core/use-agent-chat.d.ts +341 -0
  580. package/dist/src/react/core/use-agent-chat.d.ts.map +1 -0
  581. package/dist/src/react/core/use-agent-chat.js +1118 -0
  582. package/dist/src/react/core/use-agent-chat.js.map +1 -0
  583. package/dist/src/react/genui/index.d.ts +1 -7
  584. package/dist/src/react/genui/index.d.ts.map +1 -1
  585. package/dist/src/react/genui/index.js +1 -7
  586. package/dist/src/react/genui/index.js.map +1 -1
  587. package/dist/src/react/genui/json-render.d.ts +1 -5
  588. package/dist/src/react/genui/json-render.d.ts.map +1 -1
  589. package/dist/src/react/genui/json-render.js +1 -5
  590. package/dist/src/react/genui/json-render.js.map +1 -1
  591. package/dist/src/react/genui/server.d.ts +2 -0
  592. package/dist/src/react/genui/server.d.ts.map +1 -0
  593. package/dist/src/react/genui/server.js +2 -0
  594. package/dist/src/react/genui/server.js.map +1 -0
  595. package/dist/src/react/genui/server_playwright.d.ts +2 -0
  596. package/dist/src/react/genui/server_playwright.d.ts.map +1 -0
  597. package/dist/src/react/genui/server_playwright.js +2 -0
  598. package/dist/src/react/genui/server_playwright.js.map +1 -0
  599. package/dist/src/react/index.d.ts +5 -7
  600. package/dist/src/react/index.d.ts.map +1 -1
  601. package/dist/src/react/index.js +5 -7
  602. package/dist/src/react/index.js.map +1 -1
  603. package/dist/src/react/markdown.d.ts +1 -6
  604. package/dist/src/react/markdown.d.ts.map +1 -1
  605. package/dist/src/react/markdown.js +1 -6
  606. package/dist/src/react/markdown.js.map +1 -1
  607. package/dist/src/react/media.d.ts +1 -17
  608. package/dist/src/react/media.d.ts.map +1 -1
  609. package/dist/src/react/media.js +1 -17
  610. package/dist/src/react/media.js.map +1 -1
  611. package/dist/src/refusal.d.ts +3 -0
  612. package/dist/src/refusal.d.ts.map +1 -0
  613. package/dist/src/refusal.js +3 -0
  614. package/dist/src/refusal.js.map +1 -0
  615. package/dist/src/spi/agent-runner.d.ts +6 -0
  616. package/dist/src/spi/agent-runner.d.ts.map +1 -1
  617. package/dist/src/spi/chat-queue.d.ts +4 -1
  618. package/dist/src/spi/chat-queue.d.ts.map +1 -1
  619. package/dist/src/spi/chat-queue.js.map +1 -1
  620. package/dist/src/spi/protocol-adapter.d.ts +3 -3
  621. package/dist/src/spi/roles-policy.d.ts +7 -0
  622. package/dist/src/spi/roles-policy.d.ts.map +1 -1
  623. package/dist/src/spi/tool.d.ts +18 -3
  624. package/dist/src/spi/tool.d.ts.map +1 -1
  625. package/dist/src/stores/lucid-schema.d.ts +24 -6
  626. package/dist/src/stores/lucid-schema.d.ts.map +1 -1
  627. package/dist/src/stores/lucid-schema.js +49 -6
  628. package/dist/src/stores/lucid-schema.js.map +1 -1
  629. package/dist/src/stores/lucid.d.ts +2 -0
  630. package/dist/src/stores/lucid.d.ts.map +1 -1
  631. package/dist/src/stores/lucid.js +7 -0
  632. package/dist/src/stores/lucid.js.map +1 -1
  633. package/dist/src/testing/chat-queue-store-contract.d.ts.map +1 -1
  634. package/dist/src/testing/chat-queue-store-contract.js +4 -0
  635. package/dist/src/testing/chat-queue-store-contract.js.map +1 -1
  636. package/dist/src/testing/in-memory-store.d.ts.map +1 -1
  637. package/dist/src/testing/in-memory-store.js +1 -0
  638. package/dist/src/testing/in-memory-store.js.map +1 -1
  639. package/dist/src/tool-discovery.d.ts +1 -1
  640. package/dist/src/tool-discovery.d.ts.map +1 -1
  641. package/dist/src/tool-discovery.js +5 -1
  642. package/dist/src/tool-discovery.js.map +1 -1
  643. package/dist/src/tool-registry.d.ts +3 -0
  644. package/dist/src/tool-registry.d.ts.map +1 -1
  645. package/dist/src/tool-registry.js +15 -3
  646. package/dist/src/tool-registry.js.map +1 -1
  647. package/dist/src/tool-result-presentation.d.ts +12 -0
  648. package/dist/src/tool-result-presentation.d.ts.map +1 -0
  649. package/dist/src/tool-result-presentation.js +44 -0
  650. package/dist/src/tool-result-presentation.js.map +1 -0
  651. package/dist/src/types.d.ts +20 -0
  652. package/dist/src/types.d.ts.map +1 -1
  653. package/dist/src/ui-capabilities.d.ts +1 -8
  654. package/dist/src/ui-capabilities.d.ts.map +1 -1
  655. package/dist/src/ui-capabilities.js +3 -24
  656. package/dist/src/ui-capabilities.js.map +1 -1
  657. package/package.json +128 -22
  658. package/skills/agent-governance/SKILL.md +12 -4
  659. package/skills/agent-personas-agents/SKILL.md +2 -1
  660. package/skills/agent-setup/SKILL.md +73 -14
  661. package/skills/agent-testing/SKILL.md +22 -0
  662. package/skills/agent-tools/SKILL.md +57 -9
  663. package/dist/src/ag-ui/proposal-decision.d.ts.map +0 -1
  664. package/dist/src/ag-ui/proposal-decision.js.map +0 -1
@@ -0,0 +1,867 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { streamErrorFrame } from '../agent-loop.js';
3
+ import { isThreadTurn } from '../chat-queue-service.js';
4
+ import { RUN_ENDED_BEFORE_TOOL_CALL } from '../dangling-tool-calls.js';
5
+ import { buildMemoryBlock, offerMemories } from '../memory.js';
6
+ import { offerSkills } from '../skills.js';
7
+ import { DefaultApprovalPolicy } from '../spi/approval-policy.js';
8
+ import { isChatQueueStore, releaseThreadRun } from '../spi/chat-queue.js';
9
+ import { OpenCodeEventHub } from './event-hub.js';
10
+ import { errorText, openCodeLog } from './log.js';
11
+ import { OpenCodeTurn } from './turn.js';
12
+ const DEFAULT_TURN_TIMEOUT_MS = 30 * 60_000;
13
+ const DEFAULT_TOOLS_TTL_MS = 7 * 24 * 60 * 60_000;
14
+ /** Tool kinds the LOOP serves (delegation, `ask`, `skill`, `remember`): never served over MCP. */
15
+ const LOOP_SERVED_KINDS = new Set(['agent', 'ask', 'skill', 'memory']);
16
+ /**
17
+ * The steps of an OpenCode turn — `begin` (thread, session, instructions), `prompt`, `observe`
18
+ * (until a person is asked something or the execution ends), `reply`, `settle` — so an in-memory
19
+ * runner can run them in a row and a durable one can checkpoint each. A step may run in a process
20
+ * that did not run the one before (a durable run resumed elsewhere): the live turn is rebuilt from
21
+ * the session, catching up on what OpenCode asked while nobody listened.
22
+ */
23
+ export class OpenCodeTurns {
24
+ events = new OpenCodeEventHub();
25
+ live = new Map();
26
+ /** Actions approved per run, and the approvals the MCP endpoint already spent. */
27
+ grants = new Map();
28
+ spent = new Set();
29
+ /** When the tools endpoint was last registered for a location (`server|boot|directory`). */
30
+ toolsIssued = new Map();
31
+ host;
32
+ sessions;
33
+ settings;
34
+ factory;
35
+ store;
36
+ sink;
37
+ registry;
38
+ queue;
39
+ mintToolsToken;
40
+ /** Starts the next queued message of the thread; set by the runner (it owns `start`). */
41
+ startNext;
42
+ constructor(deps) {
43
+ this.host = deps.host;
44
+ this.sessions = deps.sessions;
45
+ this.settings = deps.settings;
46
+ this.factory = deps.factory;
47
+ this.store = deps.store;
48
+ this.sink = deps.sink;
49
+ this.registry = deps.registry;
50
+ this.queue = deps.queue;
51
+ this.mintToolsToken = deps.mintToolsToken;
52
+ }
53
+ /** The tools server's name in OpenCode. */
54
+ get toolsServer() {
55
+ return this.settings.tools?.server ?? 'agora';
56
+ }
57
+ /** The agent's deps (prompt, approval policy, allow-list, skills, memory) for a turn. */
58
+ depsFor(input) {
59
+ return this.factory.forAgent(input.agentName);
60
+ }
61
+ /** The tools a turn may reach: the agent's allow-list, narrowed by its persona's. */
62
+ allowedTools(input) {
63
+ const deps = this.depsFor(input);
64
+ const persona = personaOf(deps, input.persona);
65
+ const agent = deps.toolAllowList;
66
+ const own = persona?.allowedTools;
67
+ if (agent === undefined)
68
+ return own;
69
+ if (own === undefined)
70
+ return agent;
71
+ return agent.filter((name) => own.includes(name));
72
+ }
73
+ /** Whether the memory provider writes, so the endpoint serves `remember`. */
74
+ memoryWritable(input) {
75
+ return (this.settings.tools !== undefined && this.depsFor(input).memory?.provider.write !== undefined);
76
+ }
77
+ /** The runs this process is following now (an updater drains on it). */
78
+ liveRuns() {
79
+ return [...this.live.keys()];
80
+ }
81
+ /** Stop following every run, and close the event streams. */
82
+ close() {
83
+ for (const live of this.live.values())
84
+ live.stop();
85
+ this.live.clear();
86
+ this.events.close();
87
+ }
88
+ // ---- tools over MCP --------------------------------------------------------------------------
89
+ /**
90
+ * The turn a tool call over the engine's MCP endpoint belongs to, or `undefined` when it belongs
91
+ * to none — which the endpoint refuses: it exists only to serve turns. OpenCode names its session in
92
+ * every call's `_meta` (`ai.opencode/sessionID`); the call is that session's running turn's, and
93
+ * only when the endpoint's caller is the person that turn runs for, on the server the token was
94
+ * issued for. A session this process is not following is found through OpenCode (`session.get` →
95
+ * the thread it was created for → the thread's running turn); its components still reach the
96
+ * stream, as a message of their own.
97
+ */
98
+ async callContext(call) {
99
+ const sessionId = sessionOfMeta(call.meta);
100
+ if (sessionId === undefined)
101
+ return undefined;
102
+ const scope = (runId) => `${runId}:${call.requestId || randomUUID()}`;
103
+ for (const [runId, live] of this.live) {
104
+ if (live.handle.sessionId !== sessionId)
105
+ continue;
106
+ if (live.input.actor.id !== call.actor.id || live.handle.serverKey !== call.serverKey) {
107
+ return undefined;
108
+ }
109
+ return {
110
+ input: live.input,
111
+ runId,
112
+ ctx: {
113
+ threadId: live.input.threadId,
114
+ runId,
115
+ ...(live.input.agentName !== undefined ? { agentName: live.input.agentName } : {}),
116
+ emitUi: uiEmitter(scope(runId), async (component) => {
117
+ await live.turn.pushUi(component);
118
+ await this.uiPushed(live.input, runId, component);
119
+ }),
120
+ },
121
+ };
122
+ }
123
+ const threadId = await this.threadOfSession(call.actor, sessionId);
124
+ if (threadId === undefined)
125
+ return undefined;
126
+ if ((await this.store.getThreadActorRef(threadId)) !== call.actor.id)
127
+ return undefined;
128
+ const known = await this.sessions.get(threadId);
129
+ if (known === null || known.sessionId !== sessionId || known.serverKey !== call.serverKey) {
130
+ return undefined;
131
+ }
132
+ const runId = await this.activeRun(threadId);
133
+ if (runId === null)
134
+ return undefined;
135
+ // Followed elsewhere: what this call knows of the run.
136
+ const input = {
137
+ threadId,
138
+ actor: call.actor,
139
+ userText: '',
140
+ ...(known.agentName !== undefined ? { agentName: known.agentName } : {}),
141
+ ...(known.persona !== undefined ? { persona: known.persona } : {}),
142
+ };
143
+ return {
144
+ input,
145
+ runId,
146
+ ctx: {
147
+ threadId,
148
+ runId,
149
+ ...(known.agentName !== undefined ? { agentName: known.agentName } : {}),
150
+ emitUi: uiEmitter(scope(runId), async (component) => {
151
+ const writer = await this.sink.open(runId);
152
+ await writer.write({ t: 'event', event: { kind: 'ui', ...component } });
153
+ await this.store.appendMessage({
154
+ threadId,
155
+ role: 'assistant',
156
+ content: '',
157
+ runId,
158
+ ui: [component],
159
+ });
160
+ await this.uiPushed(input, runId, component);
161
+ }),
162
+ },
163
+ };
164
+ }
165
+ /**
166
+ * Spend one approval of `tool` in `runId` — what the MCP endpoint asks before it runs an `action`.
167
+ * OpenCode asks the person (or the policy answers) before it calls an action tool; the endpoint
168
+ * runs it only against an approval this engine saw granted, so a caller that skipped OpenCode's
169
+ * permission rules (anything that got hold of the token) cannot run an action unapproved. The
170
+ * approval is the run's own: live in this process, else read off the run's persisted calls.
171
+ */
172
+ async spendApproval(runId, threadId, tool) {
173
+ const names = new Set([tool, `${this.toolsServer}.${tool}`, `${this.toolsServer}_${tool}`]);
174
+ const local = (this.grants.get(runId) ?? []).find((grant) => names.has(grant.action) && !this.spent.has(grant.id));
175
+ if (local !== undefined) {
176
+ this.spent.add(local.id);
177
+ return true;
178
+ }
179
+ const thread = await this.store.getThread(threadId);
180
+ for (const message of thread?.messages ?? []) {
181
+ if (message.runId !== runId)
182
+ continue;
183
+ for (const call of message.toolCalls ?? []) {
184
+ if (!names.has(call.name) || this.spent.has(call.id))
185
+ continue;
186
+ const result = message.toolResults?.find((r) => r.id === call.id);
187
+ const approved = result?.output?.approved === true;
188
+ if (approved) {
189
+ this.spent.add(call.id);
190
+ return true;
191
+ }
192
+ }
193
+ }
194
+ return false;
195
+ }
196
+ /**
197
+ * Push a component into the run an OpenCode session is serving, for the host's own trusted
198
+ * callers (no caller check — the MCP endpoint checks its own). `false` when no run is live on
199
+ * that session in this process.
200
+ */
201
+ async pushToSession(sessionId, component) {
202
+ for (const [runId, live] of this.live) {
203
+ if (live.handle.sessionId !== sessionId)
204
+ continue;
205
+ await live.turn.pushUi(component);
206
+ await this.uiPushed(live.input, runId, component);
207
+ return true;
208
+ }
209
+ return false;
210
+ }
211
+ async uiPushed(input, runId, component) {
212
+ if (this.host.onUi === undefined)
213
+ return;
214
+ try {
215
+ await this.host.onUi({ input, runId, component });
216
+ }
217
+ catch (error) {
218
+ openCodeLog.warn(`onUi failed: ${errorText(error, 'error')}`);
219
+ }
220
+ }
221
+ async threadOfSession(actor, sessionId) {
222
+ try {
223
+ const server = await this.host.server(actor);
224
+ const info = await server.client.session.get?.({ sessionID: sessionId });
225
+ const threadId = info?.metadata?.threadId;
226
+ return typeof threadId === 'string' ? threadId : undefined;
227
+ }
228
+ catch {
229
+ return undefined;
230
+ }
231
+ }
232
+ async activeRun(threadId) {
233
+ if (isChatQueueStore(this.store))
234
+ return this.store.activeRunForThread(threadId);
235
+ return (await this.store.getThread(threadId))?.activeRunId ?? null;
236
+ }
237
+ // ---- begin -----------------------------------------------------------------------------------
238
+ /**
239
+ * Open the run's row, persist the user message (or rewind the thread for a regenerate), find or
240
+ * create the thread's session, and refresh what the session is told this turn.
241
+ */
242
+ async begin(runId, input, durable = false) {
243
+ // A durable `begin` re-run after a crash finds its row already there.
244
+ if ((await this.store.getRunActorRef(runId)) === null) {
245
+ await this.store.recordRunStart({
246
+ runId,
247
+ threadId: input.threadId,
248
+ actor: input.actor,
249
+ durable,
250
+ ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),
251
+ });
252
+ }
253
+ const earlier = await this.prepareThread(runId, input);
254
+ const server = await this.host.server(input.actor);
255
+ const known = await this.sessions.get(input.threadId);
256
+ const reusable = known !== null &&
257
+ known.serverKey === server.key &&
258
+ known.bootId === server.bootId &&
259
+ ((await this.host.reuse?.({ input, runId, session: known })) ?? true);
260
+ let handle;
261
+ let created = false;
262
+ if (known !== null && reusable) {
263
+ handle = {
264
+ sessionId: known.sessionId,
265
+ serverKey: known.serverKey,
266
+ ...(known.bootId !== undefined ? { bootId: known.bootId } : {}),
267
+ ...(known.directory !== undefined ? { directory: known.directory } : {}),
268
+ };
269
+ if (input.regenerate === true)
270
+ await this.revertLastExchange(server.client, handle.sessionId);
271
+ await this.addTools(input, server, handle.directory, false);
272
+ }
273
+ else {
274
+ handle = await this.createSession(runId, input, server, earlier);
275
+ created = true;
276
+ }
277
+ const persona = typeof input.persona === 'string' ? input.persona : input.persona?.id;
278
+ if (created || known?.agentName !== input.agentName || known?.persona !== persona) {
279
+ await this.sessions.set(input.threadId, {
280
+ ...handle,
281
+ ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),
282
+ ...(persona !== undefined ? { persona } : {}),
283
+ });
284
+ }
285
+ await this.host.beforePrompt?.({
286
+ input,
287
+ runId,
288
+ sessionId: handle.sessionId,
289
+ client: server.client,
290
+ created,
291
+ });
292
+ await this.refreshInstructions(runId, input, server.client, handle.sessionId);
293
+ return handle;
294
+ }
295
+ async createSession(runId, input, server, earlier, note) {
296
+ const { client } = server;
297
+ const context = { input, runId };
298
+ const spec = await this.host.session(context);
299
+ const directory = spec.location?.directory;
300
+ const skills = await this.writeSkills(input, client, directory);
301
+ const sessionId = (await client.session.create({
302
+ ...spec,
303
+ permissions: [
304
+ ...(spec.permissions ?? []),
305
+ ...this.toolRules(input),
306
+ ...skills.map((name) => ({
307
+ action: 'skill',
308
+ resource: name,
309
+ effect: 'allow',
310
+ })),
311
+ ],
312
+ metadata: { ...(spec.metadata ?? {}), threadId: input.threadId },
313
+ })).id;
314
+ const handle = {
315
+ sessionId,
316
+ serverKey: server.key,
317
+ ...(server.bootId !== undefined ? { bootId: server.bootId } : {}),
318
+ ...(directory !== undefined ? { directory } : {}),
319
+ };
320
+ await this.sessions.set(input.threadId, handle);
321
+ await this.addTools(input, server, directory, true);
322
+ await this.host.prepare?.({ ...context, sessionId, client });
323
+ const transcript = transcriptOf(earlier, this.settings.historyMessages ?? 20);
324
+ if (transcript || note) {
325
+ await client.session.instructions.entry.put({
326
+ sessionID: sessionId,
327
+ key: 'agora.history',
328
+ value: [
329
+ transcript
330
+ ? `The conversation so far (continue it; do not repeat it):\n${transcript}`
331
+ : '',
332
+ note ?? '',
333
+ ]
334
+ .filter(Boolean)
335
+ .join('\n\n'),
336
+ });
337
+ }
338
+ return handle;
339
+ }
340
+ /** The user message, as the loop persists it (or, on a regenerate, the thread rewound to it). */
341
+ async prepareThread(runId, input) {
342
+ const thread = await this.store.getThread(input.threadId);
343
+ const messages = thread?.messages ?? [];
344
+ if (input.regenerate === true) {
345
+ let lastUser = -1;
346
+ for (let i = messages.length - 1; i >= 0; i -= 1) {
347
+ if (messages[i]?.role === 'user') {
348
+ lastUser = i;
349
+ break;
350
+ }
351
+ }
352
+ const firstDropped = messages[lastUser + 1];
353
+ if (firstDropped !== undefined) {
354
+ await this.store.truncateFrom(input.threadId, firstDropped.id);
355
+ }
356
+ return messages.slice(0, Math.max(lastUser, 0));
357
+ }
358
+ await this.store.appendMessage({
359
+ threadId: input.threadId,
360
+ role: 'user',
361
+ content: input.userText,
362
+ runId,
363
+ ...(typeof input.persona === 'string' ? { persona: input.persona } : {}),
364
+ ...(input.attachments !== undefined ? { attachments: input.attachments } : {}),
365
+ });
366
+ if (thread !== null && (thread.title === '' || thread.title === 'New chat')) {
367
+ await this.store.setTitle(input.threadId, titleOf(input.userText));
368
+ }
369
+ return messages;
370
+ }
371
+ /** Rewind the session to before its last user message, so the regenerated answer replaces it. */
372
+ async revertLastExchange(client, sessionId) {
373
+ if (client.message === undefined || client.session.revert === undefined)
374
+ return;
375
+ const page = await client.message.list({ sessionID: sessionId, order: 'desc', limit: 50 });
376
+ const last = page.data.find((m) => m.type === 'user');
377
+ if (last === undefined)
378
+ return;
379
+ await client.session.revert.stage({ sessionID: sessionId, messageID: last.id, files: false });
380
+ await client.session.revert.commit({ sessionID: sessionId });
381
+ }
382
+ /** The agent's prompt, the memory block and the host's entries — refreshed every turn. */
383
+ async refreshInstructions(runId, input, client, sessionId) {
384
+ const memory = await this.memoryBlock(input);
385
+ const entries = {
386
+ [this.settings.systemKey ?? 'agora.system']: await this.systemPrompt(input),
387
+ ...(memory !== undefined ? { 'agora.memory': memory } : {}),
388
+ ...((await this.host.instructions?.({ input, runId, sessionId })) ?? {}),
389
+ };
390
+ for (const [key, value] of Object.entries(entries)) {
391
+ await client.session.instructions.entry.put({ sessionID: sessionId, key, value });
392
+ }
393
+ }
394
+ /**
395
+ * The agent's prompt as the loop resolves it: a persona's prompt stands in for the base (a
396
+ * builder is handed the base as `basePrompt`), else the agent's `systemPrompt`.
397
+ */
398
+ async systemPrompt(input) {
399
+ const deps = this.depsFor(input);
400
+ const persona = personaOf(deps, input.persona);
401
+ const ctx = {
402
+ actor: input.actor,
403
+ ...(persona !== undefined ? { persona } : {}),
404
+ ...(input.pageContext !== undefined ? { pageContext: input.pageContext } : {}),
405
+ ...(input.uiCapabilities !== undefined ? { uiCapabilities: input.uiCapabilities } : {}),
406
+ };
407
+ const resolve = async (prompt, basePrompt) => typeof prompt === 'function' ? prompt({ ...ctx, basePrompt }) : prompt;
408
+ const own = persona?.systemPrompt;
409
+ if (own === undefined)
410
+ return resolve(deps.systemPrompt, '');
411
+ const base = typeof own === 'function' ? await resolve(deps.systemPrompt, '') : '';
412
+ return resolve(own, base);
413
+ }
414
+ scopeContext(input) {
415
+ return {
416
+ actor: input.actor,
417
+ threadId: input.threadId,
418
+ ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),
419
+ ...(input.pageContext !== undefined ? { pageContext: input.pageContext } : {}),
420
+ };
421
+ }
422
+ /** What is on file about the actor (`memory` in the config); writable when `remember` is served. */
423
+ async memoryBlock(input) {
424
+ const memory = this.depsFor(input).memory;
425
+ if (memory === undefined)
426
+ return undefined;
427
+ const digest = await offerMemories({
428
+ config: memory,
429
+ ctx: this.scopeContext(input),
430
+ query: input.userText,
431
+ });
432
+ if (digest.entries.length === 0)
433
+ return undefined;
434
+ return buildMemoryBlock({
435
+ entries: digest.entries,
436
+ writable: this.memoryWritable(input),
437
+ partial: digest.omitted > 0 || digest.recalled === true,
438
+ });
439
+ }
440
+ /**
441
+ * The agent's skills (`skills` in the config) as `SKILL.md` files under the session's directory,
442
+ * where OpenCode's own `skill` tool finds them. Returns the names written.
443
+ */
444
+ async writeSkills(input, client, directory) {
445
+ const skills = this.depsFor(input).skills;
446
+ if (skills === undefined || client.file === undefined || directory === undefined)
447
+ return [];
448
+ const ctx = this.scopeContext(input);
449
+ const offer = await offerSkills(skills, ctx);
450
+ const dir = this.settings.skillsDir ?? '.opencode/skills';
451
+ const written = [];
452
+ for (const entry of offer.entries) {
453
+ const body = await skills.provider.load({ name: entry.name, scope: entry.scope, ctx });
454
+ if (body === null)
455
+ continue;
456
+ const file = `---\nname: ${entry.name}\ndescription: ${JSON.stringify(entry.description)}\n---\n\n${body}\n`;
457
+ await client.file.write({
458
+ location: { directory },
459
+ path: `${dir}/${entry.name}/SKILL.md`,
460
+ payload: new TextEncoder().encode(file),
461
+ });
462
+ written.push(entry.name);
463
+ }
464
+ return written;
465
+ }
466
+ /**
467
+ * Permission rules for the app's tools: the MCP server allowed as a whole (OpenCode offers a
468
+ * server's tools only when the server itself is allowed), then each `action` tool asked — the last
469
+ * matching rule wins, so an action still lands on an approval card. Tools outside the agent's
470
+ * allow-list, and the kinds only the loop serves, are denied.
471
+ */
472
+ toolRules(input) {
473
+ if (this.settings.tools === undefined)
474
+ return [];
475
+ const server = this.toolsServer;
476
+ const allow = this.allowedTools(input);
477
+ const both = (name) => [`${server}.${name}`, `${server}_${name}`];
478
+ const rules = [
479
+ { action: `${server}*`, resource: '*', effect: 'allow' },
480
+ ];
481
+ for (const spec of this.registry.allSpecs()) {
482
+ const offered = (allow === undefined || allow.includes(spec.name)) && !LOOP_SERVED_KINDS.has(spec.kind);
483
+ if (offered && spec.kind === 'read')
484
+ continue;
485
+ const effect = offered && spec.kind === 'action' ? 'ask' : 'deny';
486
+ for (const action of both(spec.name))
487
+ rules.push({ action, resource: '*', effect });
488
+ }
489
+ return rules;
490
+ }
491
+ /**
492
+ * Register the tools endpoint at the session's location, with a bearer token for the turn's
493
+ * actor. On a new session always; on a kept one when this process has not registered it yet or
494
+ * its token is half-way through its life.
495
+ */
496
+ async addTools(input, server, directory, fresh) {
497
+ const tools = this.settings.tools;
498
+ if (tools === undefined || this.mintToolsToken === undefined)
499
+ return;
500
+ const { client } = server;
501
+ if (client.mcp === undefined) {
502
+ openCodeLog.warn('`tools` is set but the OpenCode client cannot add MCP servers (`mcp.add`)');
503
+ return;
504
+ }
505
+ const key = `${server.key}|${server.bootId ?? ''}|${directory ?? ''}|${input.actor.id}`;
506
+ const issued = this.toolsIssued.get(key);
507
+ const ttl = tools.ttlMs ?? DEFAULT_TOOLS_TTL_MS;
508
+ if (!fresh && issued !== undefined && Date.now() - issued < ttl / 2)
509
+ return;
510
+ await client.mcp.add({
511
+ server: this.toolsServer,
512
+ ...(directory !== undefined ? { location: { directory } } : {}),
513
+ config: {
514
+ type: 'remote',
515
+ url: tools.url,
516
+ headers: { Authorization: `Bearer ${this.mintToolsToken(input.actor, server.key)}` },
517
+ oauth: false,
518
+ },
519
+ });
520
+ this.toolsIssued.set(key, Date.now());
521
+ }
522
+ // ---- prompt / observe / reply ----------------------------------------------------------------
523
+ /** Start listening to the session (so nothing it says is missed), then send the user message. */
524
+ async prompt(runId, input, handle) {
525
+ const live = await this.ensureLive(runId, input, handle, false);
526
+ try {
527
+ const prompt = (await this.host.promptFor?.({
528
+ input,
529
+ runId,
530
+ sessionId: handle.sessionId,
531
+ })) ?? {
532
+ text: input.userText,
533
+ ...(input.attachments?.length && this.host.files
534
+ ? { files: await this.host.files({ input, runId }) }
535
+ : {}),
536
+ };
537
+ await live.client.session.prompt({
538
+ sessionID: handle.sessionId,
539
+ text: prompt.text,
540
+ ...(prompt.files?.length ? { files: prompt.files } : {}),
541
+ });
542
+ }
543
+ catch (error) {
544
+ live.turn.fail(`OpenCode refused the message: ${errorText(error, 'unknown error')}`);
545
+ }
546
+ }
547
+ /**
548
+ * Wait for the turn's next milestone. In a process that was not following the turn (a resumed
549
+ * durable run), the turn is rebuilt and first catches up on requests OpenCode raised meanwhile;
550
+ * `session.wait` is the safety net for a terminal event that was missed.
551
+ */
552
+ async observe(runId, input, handle) {
553
+ const live = await this.ensureLive(runId, input, handle, true);
554
+ const { turn, client } = live;
555
+ if (turn.hasMilestone())
556
+ return this.reached(runId, input, handle, await turn.next());
557
+ // Set once this observation has its milestone: the safety nets below only act while it waits.
558
+ let done = false;
559
+ const next = turn.next().then((milestone) => {
560
+ done = true;
561
+ return milestone;
562
+ });
563
+ const timeoutMs = this.settings.turnTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS;
564
+ const timer = setTimeout(() => {
565
+ if (!done)
566
+ turn.fail('Timed out waiting for OpenCode.');
567
+ }, timeoutMs);
568
+ timer.unref?.();
569
+ if (client.session.wait !== undefined) {
570
+ void client.session
571
+ .wait({ sessionID: handle.sessionId })
572
+ .then(() => new Promise((resolve) => setTimeout(resolve, 2_000)))
573
+ .then(async () => {
574
+ if (done || turn.finished)
575
+ return;
576
+ await turn.catchUp().catch(() => undefined);
577
+ // Let a milestone the catch-up reached settle this observation first.
578
+ await new Promise((resolve) => setImmediate(resolve));
579
+ // Idle with nothing open: the execution ended while its last events were lost.
580
+ if (!done && !turn.finished) {
581
+ turn.handle({
582
+ type: 'session.execution.succeeded',
583
+ data: { sessionID: handle.sessionId },
584
+ });
585
+ }
586
+ })
587
+ .catch(() => undefined);
588
+ }
589
+ try {
590
+ return await this.reached(runId, input, handle, await next);
591
+ }
592
+ finally {
593
+ clearTimeout(timer);
594
+ }
595
+ }
596
+ /**
597
+ * Hand a person's answer back to OpenCode. When the server restarted while the turn waited, the
598
+ * request is gone with it: a new session is opened, told what the person decided, and prompted
599
+ * to go on.
600
+ */
601
+ async reply(runId, input, handle, ask, reply) {
602
+ const server = await this.host.server(input.actor);
603
+ if (server.key !== handle.serverKey || server.bootId !== handle.bootId) {
604
+ return this.continueAfterRestart(runId, input, server, ask, reply);
605
+ }
606
+ const live = await this.ensureLive(runId, input, handle, false);
607
+ await live.turn.decide(ask, reply);
608
+ return handle;
609
+ }
610
+ async continueAfterRestart(runId, input, server, ask, reply) {
611
+ const approved = 'approved' in reply && reply.approved === true;
612
+ const note = ask.kind === 'approval'
613
+ ? approved
614
+ ? `The user approved the action ${ask.action} you asked permission for. Continue the task.`
615
+ : `The user did not approve the action ${ask.action}. Continue without it and explain.`
616
+ : `The user answered your question: ${JSON.stringify('answers' in reply ? reply.answers : {})}. Continue.`;
617
+ const thread = await this.store.getThread(input.threadId);
618
+ const handle = await this.createSession(runId, input, server, thread?.messages ?? [], note);
619
+ await this.refreshInstructions(runId, input, server.client, handle.sessionId);
620
+ this.drop(runId);
621
+ const live = await this.ensureLive(runId, input, handle, false);
622
+ // The old request's card settles as decided; OpenCode is told in the note.
623
+ await live.turn.decide(ask, reply, { tellOpenCode: false });
624
+ await live.client.session.prompt({ sessionID: handle.sessionId, text: note });
625
+ return handle;
626
+ }
627
+ /** Interrupt the thread's session (cancel). */
628
+ async interrupt(input) {
629
+ const known = await this.sessions.get(input.threadId);
630
+ if (known === null)
631
+ return;
632
+ const server = await this.host.server(input.actor);
633
+ if (server.key !== known.serverKey || server.bootId !== known.bootId)
634
+ return;
635
+ await server.client.session.interrupt({ sessionID: known.sessionId });
636
+ }
637
+ async ensureLive(runId, input, handle, catchUp) {
638
+ const current = this.live.get(runId);
639
+ if (current !== undefined && current.handle.sessionId === handle.sessionId)
640
+ return current;
641
+ current?.stop();
642
+ const server = await this.host.server(input.actor);
643
+ const deps = this.depsFor(input);
644
+ const policy = deps.approvalPolicy ?? new DefaultApprovalPolicy();
645
+ const writer = await this.sink.open(runId);
646
+ const turn = new OpenCodeTurn({
647
+ runId,
648
+ input,
649
+ client: server.client,
650
+ sessionId: handle.sessionId,
651
+ writer,
652
+ store: this.store,
653
+ approvalFor: async (action) => policy.requirementFor({ name: action, kind: 'action' }, input.actor, {
654
+ threadId: input.threadId,
655
+ runId,
656
+ ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),
657
+ }),
658
+ modelLabel: input.model ?? 'opencode',
659
+ onGranted: (action, id) => {
660
+ const grants = this.grants.get(runId) ?? [];
661
+ grants.push({ action, id });
662
+ this.grants.set(runId, grants);
663
+ },
664
+ });
665
+ const stop = await this.events.listen(server.key, server.client, handle.sessionId, (event) => turn.handle(event));
666
+ const live = { turn, input, handle, client: server.client, stop };
667
+ this.live.set(runId, live);
668
+ if (catchUp && current === undefined)
669
+ await turn.catchUp().catch(() => undefined);
670
+ return live;
671
+ }
672
+ /** Stop following a run in this process. */
673
+ drop(runId) {
674
+ this.live.get(runId)?.stop();
675
+ this.live.delete(runId);
676
+ }
677
+ // ---- settle ----------------------------------------------------------------------------------
678
+ /** A person was asked something: tell the host (cards in other channels, wake-ups). */
679
+ async reached(runId, input, handle, milestone) {
680
+ if (milestone.kind === 'ask' && this.host.onAsk !== undefined) {
681
+ try {
682
+ await this.host.onAsk({ input, runId, sessionId: handle.sessionId, ask: milestone.ask });
683
+ }
684
+ catch (error) {
685
+ openCodeLog.warn(`onAsk failed: ${errorText(error, 'error')}`);
686
+ }
687
+ }
688
+ return milestone;
689
+ }
690
+ /** What the run produced, as the host's settle hooks see it. */
691
+ async runResult(runId, input, outcome, durationMs) {
692
+ const thread = await this.store.getThread(input.threadId);
693
+ const messages = (thread?.messages ?? []).filter((m) => m.role === 'assistant' && m.runId === runId);
694
+ const usage = { inputTokens: 0, outputTokens: 0, costUsd: 0 };
695
+ for (const m of messages) {
696
+ usage.inputTokens += m.usage?.inputTokens ?? 0;
697
+ usage.outputTokens += m.usage?.outputTokens ?? 0;
698
+ usage.costUsd += m.usage?.costUsd ?? 0;
699
+ }
700
+ return {
701
+ runId,
702
+ input,
703
+ outcome,
704
+ text: messages
705
+ .map((m) => m.content)
706
+ .filter(Boolean)
707
+ .join('\n\n'),
708
+ messages,
709
+ usage,
710
+ durationMs,
711
+ };
712
+ }
713
+ /**
714
+ * The host's last word on the answer before the stream ends: components to append (a guardrail
715
+ * notice), or, for a failed run, the error the person reads instead of OpenCode's.
716
+ */
717
+ async amend(writer, result) {
718
+ if (this.host.beforeSettle === undefined)
719
+ return {};
720
+ let amendment = {};
721
+ try {
722
+ amendment = (await this.host.beforeSettle(result)) ?? {};
723
+ }
724
+ catch (error) {
725
+ openCodeLog.warn(`beforeSettle failed: ${errorText(error, 'error')}`);
726
+ }
727
+ const ui = amendment.ui ?? [];
728
+ const last = result.messages.at(-1);
729
+ if (ui.length > 0) {
730
+ for (const component of ui) {
731
+ await writer.write({ t: 'event', event: { kind: 'ui', ...component } });
732
+ }
733
+ if (last !== undefined)
734
+ await this.store.setMessageUi?.(last.id, [...(last.ui ?? []), ...ui]);
735
+ }
736
+ return amendment;
737
+ }
738
+ /** Delivery, telemetry, spend: after the run settled. Errors are the host's, never the run's. */
739
+ async settled(result) {
740
+ try {
741
+ await this.host.onSettled?.(result);
742
+ }
743
+ catch (error) {
744
+ openCodeLog.warn(`onSettled failed: ${errorText(error, 'error')}`);
745
+ }
746
+ }
747
+ forget(runId) {
748
+ this.drop(runId);
749
+ for (const grant of this.grants.get(runId) ?? [])
750
+ this.spent.delete(grant.id);
751
+ this.grants.delete(runId);
752
+ }
753
+ /** End the run's stream and bookkeeping for how its execution ended. */
754
+ async settle(runId, input, outcome, durationMs) {
755
+ if (outcome.status === 'failed') {
756
+ await this.settleFailed(runId, input, outcome.error, durationMs);
757
+ return;
758
+ }
759
+ const totals = this.live.get(runId)?.turn.totals();
760
+ this.forget(runId);
761
+ const writer = await this.sink.open(runId);
762
+ const result = await this.runResult(runId, input, outcome, durationMs);
763
+ await this.amend(writer, result);
764
+ if (outcome.status === 'interrupted') {
765
+ await this.store.recordRunEnd({ runId, status: 'cancelled' });
766
+ await Promise.resolve(this.store.failUnsettledToolCalls?.(runId, RUN_ENDED_BEFORE_TOOL_CALL)).catch(() => 0);
767
+ await this.handoff(writer, input, runId, 'cancelled');
768
+ await releaseThreadRun(this.store, input.threadId, runId);
769
+ await writer.write({ t: 'event', event: { kind: 'cancelled' } });
770
+ await writer.end();
771
+ }
772
+ else {
773
+ await this.store.recordRunEnd({
774
+ runId,
775
+ status: 'completed',
776
+ finishedAt: Date.now(),
777
+ stepCount: totals?.steps ?? 0,
778
+ inputTokens: totals?.inputTokens ?? result.usage.inputTokens,
779
+ outputTokens: totals?.outputTokens ?? result.usage.outputTokens,
780
+ ...(totals?.costUsd !== undefined ? { costUsd: totals.costUsd } : {}),
781
+ });
782
+ await this.handoff(writer, input, runId, 'completed');
783
+ await releaseThreadRun(this.store, input.threadId, runId);
784
+ await writer.end();
785
+ }
786
+ await this.settled(result);
787
+ }
788
+ async settleFailed(runId, input, error, durationMs = 0) {
789
+ this.forget(runId);
790
+ const writer = await this.sink.open(runId);
791
+ const result = await this.runResult(runId, input, { status: 'failed', error }, durationMs);
792
+ const worded = (await this.amend(writer, result)).error;
793
+ await this.store.recordRunEnd({ runId, status: 'failed', error });
794
+ await Promise.resolve(this.store.failUnsettledToolCalls?.(runId, RUN_ENDED_BEFORE_TOOL_CALL)).catch(() => 0);
795
+ await this.handoff(writer, input, runId, 'failed', error);
796
+ await releaseThreadRun(this.store, input.threadId, runId);
797
+ // The host's wording is for the person and shown as is; OpenCode's own error follows the
798
+ // library's rule (shown outside production, logged everywhere).
799
+ await writer.write(worded !== undefined
800
+ ? { t: 'error', code: 'run_failed', message: worded }
801
+ : streamErrorFrame(new Error(error), runId));
802
+ await writer.end();
803
+ await this.settled({ ...result, outcome: { status: 'failed', error: worded ?? error } });
804
+ }
805
+ /** As `InlineAgentRunner`: hand the thread to its next queued message, and say so on the stream. */
806
+ async handoff(writer, input, runId, outcome, error) {
807
+ const queue = this.queue;
808
+ const startNext = this.startNext;
809
+ if (queue === undefined || !queue.supported || startNext === undefined)
810
+ return;
811
+ if (!isThreadTurn(input))
812
+ return;
813
+ try {
814
+ const frame = await queue.handoff({ threadId: input.threadId, runId, outcome, ...(error !== undefined ? { error } : {}) }, (next, nextRunId) => startNext(next, nextRunId));
815
+ if (frame !== undefined)
816
+ await writer.write({ t: 'event', event: frame });
817
+ }
818
+ catch (failure) {
819
+ openCodeLog.error(`could not advance the queue of thread ${input.threadId} after run ${runId}: ${errorText(failure, 'error')}`);
820
+ }
821
+ }
822
+ }
823
+ /** The persona a turn names (an id, or the whole definition a direct caller handed over). */
824
+ function personaOf(deps, persona) {
825
+ if (persona === undefined)
826
+ return undefined;
827
+ return typeof persona === 'string' ? deps.personas.get(persona) : persona;
828
+ }
829
+ function titleOf(text) {
830
+ const trimmed = text.trim().replace(/\s+/g, ' ');
831
+ return trimmed.length > 60 ? `${trimmed.slice(0, 57)}...` : trimmed || 'New chat';
832
+ }
833
+ function transcriptOf(messages, limit) {
834
+ return messages
835
+ .filter((m) => (m.role === 'user' || m.role === 'assistant') && m.content.trim())
836
+ .slice(-limit)
837
+ .map((m) => `${m.role === 'user' ? 'User' : 'Assistant'}: ${m.content.slice(0, 2000)}`)
838
+ .join('\n');
839
+ }
840
+ /** The `_meta` key OpenCode names its session with on every MCP call. */
841
+ export const SESSION_META_KEY = 'ai.opencode/sessionID';
842
+ function sessionOfMeta(meta) {
843
+ const value = meta?.[SESSION_META_KEY];
844
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
845
+ }
846
+ /** `ctx.emitUi` over `push`, with the library's id and snapshot rules. */
847
+ function uiEmitter(scope, push) {
848
+ let next = 0;
849
+ return async (component, props, options = {}) => {
850
+ if (typeof component !== 'string' || component.length === 0) {
851
+ throw new Error('emitUi: component must be a non-empty string');
852
+ }
853
+ if (typeof props !== 'object' || props === null || Array.isArray(props)) {
854
+ throw new Error('emitUi: props must be a JSON object');
855
+ }
856
+ const id = options.id ?? `${scope}:ui:${next++}`;
857
+ await push({
858
+ id,
859
+ component,
860
+ props: JSON.parse(JSON.stringify(props)),
861
+ ...(options.version !== undefined ? { version: options.version } : {}),
862
+ ...(options.fallbackText !== undefined ? { fallbackText: options.fallbackText } : {}),
863
+ });
864
+ return { id };
865
+ };
866
+ }
867
+ //# sourceMappingURL=turns.js.map