@cursor/bdk 0.2.11 → 0.2.13

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 (457) hide show
  1. package/dist/bin/agent-serve.js +28 -26
  2. package/dist/channels/bitbucket/api.js +8 -8
  3. package/dist/channels/bitbucket/binding.js +4 -4
  4. package/dist/channels/bitbucket/bitbucket-channel.js +1 -1
  5. package/dist/channels/bitbucket/bitbucket-webhook.js +1 -1
  6. package/dist/channels/bitbucket/checks.js +1 -1
  7. package/dist/channels/bitbucket/cursor-account.js +1 -1
  8. package/dist/channels/bitbucket/events.js +1 -1
  9. package/dist/channels/change-monitors/change-monitors-channel.js +1 -1
  10. package/dist/channels/checks.js +2 -2
  11. package/dist/channels/deployments/deployments-channel.js +1 -1
  12. package/dist/channels/github/cursor-account.js +3 -3
  13. package/dist/channels/github/defaults.js +3 -3
  14. package/dist/channels/github/events.js +1 -1
  15. package/dist/channels/github/forward.js +8 -8
  16. package/dist/channels/github/github-channel.js +2 -2
  17. package/dist/channels/github/index.d.ts +22 -12
  18. package/dist/channels/github/index.d.ts.map +1 -1
  19. package/dist/channels/github/index.js +11 -12
  20. package/dist/channels/gitlab/binding.js +4 -4
  21. package/dist/channels/gitlab/checks.js +1 -1
  22. package/dist/channels/gitlab/cursor-account.js +1 -1
  23. package/dist/channels/gitlab/events.js +1 -1
  24. package/dist/channels/gitlab/gitlab-channel.js +1 -1
  25. package/dist/channels/gitlab/gitlab-webhook.js +1 -1
  26. package/dist/channels/gitlab/replay.js +2 -2
  27. package/dist/channels/origin/binding.js +3 -3
  28. package/dist/channels/origin/checks.js +1 -1
  29. package/dist/channels/origin/cursor-account.js +1 -1
  30. package/dist/channels/origin/events.js +1 -1
  31. package/dist/channels/origin/index.d.ts +21 -11
  32. package/dist/channels/origin/index.d.ts.map +1 -1
  33. package/dist/channels/origin/index.js +10 -11
  34. package/dist/channels/origin/origin-channel.js +1 -1
  35. package/dist/channels/origin/origin-webhook.js +2 -2
  36. package/dist/channels/slack/agentic-delivery.js +3 -3
  37. package/dist/channels/slack/agentic-signals.js +1 -1
  38. package/dist/channels/slack/api.js +5 -5
  39. package/dist/channels/slack/approvals.js +1 -1
  40. package/dist/channels/slack/attachments.js +3 -3
  41. package/dist/channels/slack/blocks.js +3 -3
  42. package/dist/channels/slack/bot-mentions.js +4 -4
  43. package/dist/channels/slack/channel-watch.js +4 -4
  44. package/dist/channels/slack/cli-project.js +3 -3
  45. package/dist/channels/slack/dispatch.js +1 -1
  46. package/dist/channels/slack/doctor.js +1 -1
  47. package/dist/channels/slack/eval-directive.js +1 -1
  48. package/dist/channels/slack/footer.js +1 -1
  49. package/dist/channels/slack/interactive.js +2 -2
  50. package/dist/channels/slack/log.d.ts.map +1 -1
  51. package/dist/channels/slack/log.js +1 -1
  52. package/dist/channels/slack/manifest.js +1 -1
  53. package/dist/channels/slack/nudge-carrier.js +1 -1
  54. package/dist/channels/slack/nudge-store.js +2 -2
  55. package/dist/channels/slack/recording-sink.js +6 -6
  56. package/dist/channels/slack/reply-options.js +6 -6
  57. package/dist/channels/slack/self-identity.d.ts +7 -4
  58. package/dist/channels/slack/self-identity.d.ts.map +1 -1
  59. package/dist/channels/slack/self-identity.js +17 -8
  60. package/dist/channels/slack/sender-name.d.ts.map +1 -1
  61. package/dist/channels/slack/sender-name.js +2 -6
  62. package/dist/channels/slack/setup.d.ts.map +1 -1
  63. package/dist/channels/slack/setup.js +1 -1
  64. package/dist/channels/slack/slack-channel.js +2 -2
  65. package/dist/channels/slack/socket-mode.js +2 -2
  66. package/dist/channels/slack/thread-context.js +8 -8
  67. package/dist/channels/slack/tool-cards.js +1 -1
  68. package/dist/channels/slack/user-info.d.ts +2 -1
  69. package/dist/channels/slack/user-info.d.ts.map +1 -1
  70. package/dist/channels/slack/user-info.js +16 -1
  71. package/dist/channels.js +1 -1
  72. package/dist/docs/404.html +3 -3
  73. package/dist/docs/assets/{app.DXI7bwox.js → app.CaLG1pPt.js} +4 -4
  74. package/dist/docs/assets/chunks/@localSearchIndexroot.DvlKuIO-.js +1 -0
  75. package/dist/docs/assets/chunks/{VPLocalSearchBox.BrbO5mEe.js → VPLocalSearchBox.YsP_2wqD.js} +2 -2
  76. package/dist/docs/assets/chunks/{arc.BOG1yms8.js → arc.C2j9hR7c.js} +1 -1
  77. package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.C0hsMZnZ.js → architectureDiagram-Q4EWVU46.C5qkGp7y.js} +1 -1
  78. package/dist/docs/assets/chunks/{baseUniq.H044KjKs.js → baseUniq.U6GgTHOD.js} +1 -1
  79. package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.BsRW6GoB.js → blockDiagram-DXYQGD6D.D51mJop2.js} +1 -1
  80. package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.B9HV5PFR.js → c4Diagram-AHTNJAMY.w1d6QxV7.js} +1 -1
  81. package/dist/docs/assets/chunks/channel.BRSFxCcD.js +1 -0
  82. package/dist/docs/assets/chunks/{chunk-4BX2VUAB.CPoT_ajl.js → chunk-4BX2VUAB.B_A815un.js} +1 -1
  83. package/dist/docs/assets/chunks/{chunk-4TB4RGXK.DZBwWuCL.js → chunk-4TB4RGXK.DMrm-ZCb.js} +1 -1
  84. package/dist/docs/assets/chunks/{chunk-55IACEB6.CZ3yTiyq.js → chunk-55IACEB6.8qw6Xdal.js} +1 -1
  85. package/dist/docs/assets/chunks/{chunk-EDXVE4YY.6DfvHSd8.js → chunk-EDXVE4YY.Cq_nHODn.js} +1 -1
  86. package/dist/docs/assets/chunks/{chunk-FMBD7UC4.CpBj8HfK.js → chunk-FMBD7UC4.B67ohCYn.js} +1 -1
  87. package/dist/docs/assets/chunks/{chunk-OYMX7WX6.BdKo8YqS.js → chunk-OYMX7WX6.Bo8rQI8F.js} +1 -1
  88. package/dist/docs/assets/chunks/{chunk-QZHKN3VN.BnXNyxJx.js → chunk-QZHKN3VN.BERUMfE9.js} +1 -1
  89. package/dist/docs/assets/chunks/{chunk-YZCP3GAM.Cg1OcF8G.js → chunk-YZCP3GAM.DWG2tXIX.js} +1 -1
  90. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.Cmtm6WkN.js +1 -0
  91. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.Cmtm6WkN.js +1 -0
  92. package/dist/docs/assets/chunks/clone.JMC96Eo6.js +1 -0
  93. package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.1SP8al9c.js → cose-bilkent-S5V4N54A.tezXBs9b.js} +1 -1
  94. package/dist/docs/assets/chunks/{dagre-KV5264BT.DS1L6hJt.js → dagre-KV5264BT.aSbEUwT7.js} +1 -1
  95. package/dist/docs/assets/chunks/{diagram-5BDNPKRD.ChsausbG.js → diagram-5BDNPKRD.vnT6aJ57.js} +1 -1
  96. package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.3XsptNWj.js → diagram-G4DWMVQ6.hGYdrDa2.js} +1 -1
  97. package/dist/docs/assets/chunks/{diagram-MMDJMWI5.DPA9Dk_P.js → diagram-MMDJMWI5.CmdSUP6L.js} +1 -1
  98. package/dist/docs/assets/chunks/{diagram-TYMM5635.BVswXWrB.js → diagram-TYMM5635.BbAnLEBB.js} +1 -1
  99. package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.BSak5OSP.js → erDiagram-SMLLAGMA.H40W4HWE.js} +1 -1
  100. package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.CQgN4TTz.js → flowDiagram-DWJPFMVM.BFMtUSv-.js} +1 -1
  101. package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.GrT0kA4a.js → ganttDiagram-T4ZO3ILL.CbYiu7Dt.js} +1 -1
  102. package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.CdS7Ucll.js → gitGraphDiagram-UUTBAWPF.Cyc5mzZD.js} +1 -1
  103. package/dist/docs/assets/chunks/{graph.BVqKRmRo.js → graph.BRptDG1H.js} +1 -1
  104. package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.C3C9FRto.js → infoDiagram-42DDH7IO.Bz6KCA3a.js} +1 -1
  105. package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.2FuAh_Zj.js → ishikawaDiagram-UXIWVN3A.DDJ_7_Fq.js} +1 -1
  106. package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.CaHMfK4b.js → journeyDiagram-VCZTEJTY.D0t_ltlb.js} +1 -1
  107. package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.CjhIUwcA.js → kanban-definition-6JOO6SKY.DyyNsMfi.js} +1 -1
  108. package/dist/docs/assets/chunks/{layout.CGU3gfSf.js → layout.Cbxq-Rhp.js} +1 -1
  109. package/dist/docs/assets/chunks/{linear.DaihpW_n.js → linear.DxGYL0MP.js} +1 -1
  110. package/dist/docs/assets/chunks/{min.BS-j8kHQ.js → min.DA5KL8wu.js} +1 -1
  111. package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.BVJ1Bbnk.js → mindmap-definition-QFDTVHPH.Bc72Utls.js} +1 -1
  112. package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.Cz1WIv9r.js → pieDiagram-DEJITSTG.BtpHnIB_.js} +1 -1
  113. package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.DKLFxcjy.js → quadrantDiagram-34T5L4WZ.Cx4oCSRR.js} +1 -1
  114. package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.BHegiK7x.js → requirementDiagram-MS252O5E.BC0hXWlW.js} +1 -1
  115. package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.DYkY6yPc.js → sankeyDiagram-XADWPNL6.Dg8T1SEp.js} +1 -1
  116. package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.DYQ1QUrI.js → sequenceDiagram-FGHM5R23.CWSdHYAF.js} +1 -1
  117. package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.Iru8BsFo.js → stateDiagram-FHFEXIEX.0MVPRI28.js} +1 -1
  118. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.N4Am6sXd.js +1 -0
  119. package/dist/docs/assets/chunks/{theme.DaplWQhQ.js → theme.DO1avLBn.js} +2 -2
  120. package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.BwFA8hiX.js → timeline-definition-GMOUNBTQ.BuRinAVi.js} +1 -1
  121. package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.CZ60W1C_.js → vennDiagram-DHZGUBPP.DXf0PCoJ.js} +1 -1
  122. package/dist/docs/assets/chunks/wardley-RL74JXVD._eATmGtu.js +162 -0
  123. package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.B69D2r8-.js → wardleyDiagram-NUSXRM2D.T4ThngYV.js} +1 -1
  124. package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.CLPZEIU9.js → xychartDiagram-5P7HB3ND.b4pZF3D5.js} +1 -1
  125. package/dist/docs/assets/{reference_connections.md.Bljpve-y.js → reference_connections.md.DLrgAd5f.js} +1 -1
  126. package/dist/docs/assets/{reference_hooks.md.C5LCJ1R3.js → reference_hooks.md.B-eGa2km.js} +3 -3
  127. package/dist/docs/assets/{reference_hooks.md.C5LCJ1R3.lean.js → reference_hooks.md.B-eGa2km.lean.js} +1 -1
  128. package/dist/docs/assets/{reference_sessions.md.CM5zo3w4.js → reference_sessions.md.CyM7ARz1.js} +1 -1
  129. package/dist/docs/assets/{reference_skills.md.ClkMoQsV.js → reference_skills.md.C0guGcH0.js} +3 -3
  130. package/dist/docs/assets/{reference_tools.md.v3SXVSs_.js → reference_tools.md.DzIY9JzY.js} +3 -3
  131. package/dist/docs/assets/{reference_tools.md.v3SXVSs_.lean.js → reference_tools.md.DzIY9JzY.lean.js} +1 -1
  132. package/dist/docs/assets/{style.C130MVnH.css → style.Dwls12uf.css} +1 -1
  133. package/dist/docs/building-with-agents.html +37 -37
  134. package/dist/docs/deployment.html +37 -37
  135. package/dist/docs/evals.html +37 -37
  136. package/dist/docs/guides/agent-to-agent.html +37 -37
  137. package/dist/docs/guides/bitbucket.html +37 -37
  138. package/dist/docs/guides/cloud-agents.html +37 -37
  139. package/dist/docs/guides/convert-automation.html +37 -37
  140. package/dist/docs/guides/github.html +37 -37
  141. package/dist/docs/guides/gitlab.html +37 -37
  142. package/dist/docs/guides/grokbot-agents.html +37 -37
  143. package/dist/docs/guides/hooks.html +37 -37
  144. package/dist/docs/guides/improve.html +37 -37
  145. package/dist/docs/guides/jev.html +37 -37
  146. package/dist/docs/guides/mcp-oauth.html +37 -37
  147. package/dist/docs/guides/migrate.html +37 -37
  148. package/dist/docs/guides/opentelemetry.html +37 -37
  149. package/dist/docs/guides/slack.html +37 -37
  150. package/dist/docs/guides/webhooks.html +37 -37
  151. package/dist/docs/hashmap.json +1 -1
  152. package/dist/docs/hillclimbing.html +37 -37
  153. package/dist/docs/index.html +37 -37
  154. package/dist/docs/llms-full.txt +15 -2
  155. package/dist/docs/quickstart.html +37 -37
  156. package/dist/docs/reference/agent-config.html +37 -37
  157. package/dist/docs/reference/artifacts.html +37 -37
  158. package/dist/docs/reference/channels.html +37 -37
  159. package/dist/docs/reference/cli.html +37 -37
  160. package/dist/docs/reference/connections.html +39 -39
  161. package/dist/docs/reference/connections.md +2 -1
  162. package/dist/docs/reference/evals.html +37 -37
  163. package/dist/docs/reference/extensions.html +37 -37
  164. package/dist/docs/reference/hooks.html +39 -39
  165. package/dist/docs/reference/hooks.md +1 -0
  166. package/dist/docs/reference/http-api.html +37 -37
  167. package/dist/docs/reference/instructions.html +37 -37
  168. package/dist/docs/reference/playground.html +36 -36
  169. package/dist/docs/reference/project-layout.html +37 -37
  170. package/dist/docs/reference/prompt.html +37 -37
  171. package/dist/docs/reference/schedules.html +37 -37
  172. package/dist/docs/reference/sessions.html +37 -37
  173. package/dist/docs/reference/sessions.md +1 -1
  174. package/dist/docs/reference/skills.html +40 -40
  175. package/dist/docs/reference/subagents.html +37 -37
  176. package/dist/docs/reference/tools.html +39 -39
  177. package/dist/docs/reference/tools.md +11 -0
  178. package/dist/docs/templates/agentic-owners.html +37 -37
  179. package/dist/docs/templates/grokbot-agents.html +37 -37
  180. package/dist/docs/templates/security-reviewer.html +37 -37
  181. package/dist/docs/templates/thermo-quality-review.html +37 -37
  182. package/dist/docs/templates/thermo-review.html +37 -37
  183. package/dist/docs/templates/triage.html +37 -37
  184. package/dist/docs/troubleshooting.html +36 -36
  185. package/dist/evals/assertions.d.ts.map +1 -1
  186. package/dist/evals/assertions.js +21 -19
  187. package/dist/evals/expect.js +1 -1
  188. package/dist/evals/judge.js +1 -1
  189. package/dist/evals/reporters.js +8 -8
  190. package/dist/evals/run-facts.js +2 -2
  191. package/dist/evals.js +6 -6
  192. package/dist/extensions/cursor-cloud-agents/extension.d.ts +2 -0
  193. package/dist/extensions/cursor-cloud-agents/extension.d.ts.map +1 -1
  194. package/dist/extensions/cursor-cloud-agents/extension.js +2 -1
  195. package/dist/extensions/cursor-cloud-agents/lib/backend.d.ts +16 -0
  196. package/dist/extensions/cursor-cloud-agents/lib/backend.d.ts.map +1 -1
  197. package/dist/extensions/cursor-cloud-agents/lib/backend.js +44 -3
  198. package/dist/extensions/cursor-cloud-agents/lib/fleet.js +1 -1
  199. package/dist/extensions/cursor-cloud-agents/lib/launch-agent.d.ts +23 -0
  200. package/dist/extensions/cursor-cloud-agents/lib/launch-agent.d.ts.map +1 -0
  201. package/dist/extensions/cursor-cloud-agents/lib/launch-agent.js +32 -0
  202. package/dist/extensions/cursor-cloud-agents/lib/repos.js +2 -2
  203. package/dist/extensions/cursor-cloud-agents/lib/transcript.js +2 -2
  204. package/dist/extensions/cursor-cloud-agents/lib/watch.d.ts.map +1 -1
  205. package/dist/extensions/cursor-cloud-agents/lib/watch.js +1 -1
  206. package/dist/extensions/cursor-cloud-agents/tools/launch.d.ts.map +1 -1
  207. package/dist/extensions/cursor-cloud-agents/tools/launch.js +3 -8
  208. package/dist/extensions/cursor-cloud-agents/tools/list.js +1 -1
  209. package/dist/extensions/cursor-grokbot-agents/extension.js +3 -3
  210. package/dist/extensions/cursor-grokbot-agents/lib/agents.js +3 -3
  211. package/dist/extensions/cursor-grokbot-agents/lib/contacts.js +3 -3
  212. package/dist/extensions/cursor-grokbot-agents/lib/conversation.js +4 -4
  213. package/dist/extensions/cursor-grokbot-agents/tools/list.js +1 -1
  214. package/dist/extensions/improve/skills/yourself.js +1 -1
  215. package/dist/extensions/jev/extension.js +2 -2
  216. package/dist/extensions/jev/tools/evaluate.js +1 -1
  217. package/dist/extensions/slack-communication/tools/react.js +1 -1
  218. package/dist/files-backends/cursor-hosted.js +8 -8
  219. package/dist/files-backends/local-fs.js +1 -1
  220. package/dist/filesystem.d.ts.map +1 -1
  221. package/dist/filesystem.js +15 -15
  222. package/dist/internal/advertise-tools.d.ts +3 -2
  223. package/dist/internal/advertise-tools.d.ts.map +1 -1
  224. package/dist/internal/advertise-tools.js +11 -9
  225. package/dist/internal/approval-gate.js +1 -1
  226. package/dist/internal/artifacts-store.js +13 -13
  227. package/dist/internal/as-of.js +2 -2
  228. package/dist/internal/authored-alias-hooks.d.ts +4 -3
  229. package/dist/internal/authored-alias-hooks.d.ts.map +1 -1
  230. package/dist/internal/authored-alias-hooks.js +16 -7
  231. package/dist/internal/authored-loaders.d.ts.map +1 -1
  232. package/dist/internal/authored-loaders.js +21 -5
  233. package/dist/internal/builtin-tools/reminders.js +2 -2
  234. package/dist/internal/chat-client.js +5 -5
  235. package/dist/internal/cli-ax.js +14 -14
  236. package/dist/internal/cli-bitbucket.js +10 -10
  237. package/dist/internal/cli-convert-automation.js +2 -2
  238. package/dist/internal/cli-cursor.js +2 -2
  239. package/dist/internal/cli-deploy.d.ts.map +1 -1
  240. package/dist/internal/cli-deploy.js +40 -40
  241. package/dist/internal/cli-docs.js +5 -5
  242. package/dist/internal/cli-github.js +15 -15
  243. package/dist/internal/cli-gitlab.js +10 -10
  244. package/dist/internal/cli-images.js +16 -16
  245. package/dist/internal/cli-manifest.js +1 -1
  246. package/dist/internal/cli-mcp-oauth.js +5 -5
  247. package/dist/internal/cli-mcp.js +3 -3
  248. package/dist/internal/cli-migrate.js +1 -1
  249. package/dist/internal/cli-skills.js +2 -2
  250. package/dist/internal/cli-slack.js +5 -5
  251. package/dist/internal/cloud-turn-cost.js +1 -1
  252. package/dist/internal/continuation-identity.js +6 -6
  253. package/dist/internal/conversation-mirror.js +5 -5
  254. package/dist/internal/convert-automation/convert-workflow.js +24 -24
  255. package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
  256. package/dist/internal/cursor/account-mcp.js +20 -20
  257. package/dist/internal/cursor/backend-client.js +6 -6
  258. package/dist/internal/cursor/credentials.js +1 -1
  259. package/dist/internal/cursor/store-api-client.js +1 -1
  260. package/dist/internal/cursor-account-mcp-auth.js +9 -9
  261. package/dist/internal/cursor-deployment-relay.d.ts.map +1 -1
  262. package/dist/internal/cursor-deployment-relay.js +9 -9
  263. package/dist/internal/cursor-event-relay.js +10 -10
  264. package/dist/internal/cursor-relay-core.js +2 -2
  265. package/dist/internal/deploy-manifest.d.ts +14 -0
  266. package/dist/internal/deploy-manifest.d.ts.map +1 -1
  267. package/dist/internal/deploy-manifest.js +33 -10
  268. package/dist/internal/discovery/agent-config.js +2 -2
  269. package/dist/internal/discovery/agent.js +6 -6
  270. package/dist/internal/discovery/connections.js +5 -5
  271. package/dist/internal/discovery/cursor-plugin.js +12 -12
  272. package/dist/internal/discovery/extension-overlay.js +3 -3
  273. package/dist/internal/discovery/extensions.js +6 -6
  274. package/dist/internal/discovery/info.js +9 -9
  275. package/dist/internal/discovery/instructions.js +1 -1
  276. package/dist/internal/discovery/project.js +3 -3
  277. package/dist/internal/discovery/services.js +1 -1
  278. package/dist/internal/discovery/tools.js +1 -1
  279. package/dist/internal/docs-site.js +2 -2
  280. package/dist/internal/env-file.js +1 -1
  281. package/dist/internal/eval-run-store.js +7 -7
  282. package/dist/internal/eval-runner.d.ts.map +1 -1
  283. package/dist/internal/eval-runner.js +14 -14
  284. package/dist/internal/eval-transport.js +1 -1
  285. package/dist/internal/evals-client.d.ts.map +1 -1
  286. package/dist/internal/evals-client.js +4 -4
  287. package/dist/internal/event-log.js +8 -8
  288. package/dist/internal/event-mapper.js +13 -13
  289. package/dist/internal/expected-delivery-failure.js +2 -2
  290. package/dist/internal/filesystem/format.js +2 -2
  291. package/dist/internal/filesystem/nearest.js +3 -3
  292. package/dist/internal/filesystem/scratch.js +3 -3
  293. package/dist/internal/filesystem/tools.js +6 -6
  294. package/dist/internal/filesystem/walk.d.ts.map +1 -1
  295. package/dist/internal/filesystem/walk.js +2 -2
  296. package/dist/internal/framework-file-storage.d.ts.map +1 -1
  297. package/dist/internal/framework-file-storage.js +6 -5
  298. package/dist/internal/framework-storage-selection.d.ts.map +1 -1
  299. package/dist/internal/framework-storage-selection.js +4 -2
  300. package/dist/internal/github-fanout.d.ts.map +1 -1
  301. package/dist/internal/github-fanout.js +3 -3
  302. package/dist/internal/guest-network.js +4 -4
  303. package/dist/internal/host-files.js +1 -1
  304. package/dist/internal/host-kv.js +2 -2
  305. package/dist/internal/hosted-catch-protocol.js +1 -1
  306. package/dist/internal/hosted-catch.js +1 -1
  307. package/dist/internal/hosted-delivery-protocol.d.ts +24 -0
  308. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
  309. package/dist/internal/hosted-delivery-protocol.js +58 -14
  310. package/dist/internal/hosted-delivery.d.ts +6 -0
  311. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  312. package/dist/internal/hosted-delivery.js +64 -13
  313. package/dist/internal/hosted-eval-cases.js +4 -4
  314. package/dist/internal/hosted-execution-diag.js +3 -3
  315. package/dist/internal/hosted-managed-automation.d.ts +3 -3
  316. package/dist/internal/hosted-managed-automation.js +3 -3
  317. package/dist/internal/hosting.js +1 -1
  318. package/dist/internal/http-channel.js +1 -1
  319. package/dist/internal/http-control-plane-session.js +2 -2
  320. package/dist/internal/init-interview.js +7 -7
  321. package/dist/internal/init-project.d.ts.map +1 -1
  322. package/dist/internal/init-project.js +12 -12
  323. package/dist/internal/inline-stdio-mcp.js +2 -2
  324. package/dist/internal/install-cursor-skills.js +11 -11
  325. package/dist/internal/json-schema.js +1 -1
  326. package/dist/internal/local-control-plane.js +3 -3
  327. package/dist/internal/local-env.js +3 -3
  328. package/dist/internal/log-ring.js +1 -1
  329. package/dist/internal/logs-client.js +1 -1
  330. package/dist/internal/mcp-endpoint.js +8 -8
  331. package/dist/internal/mcp-host.d.ts.map +1 -1
  332. package/dist/internal/mcp-host.js +5 -5
  333. package/dist/internal/mcp-oauth-on-demand.js +3 -3
  334. package/dist/internal/mcp-oauth.js +5 -5
  335. package/dist/internal/net.js +2 -2
  336. package/dist/internal/otel/config.js +3 -3
  337. package/dist/internal/otel/runtime.js +13 -13
  338. package/dist/internal/peer-connections.js +2 -2
  339. package/dist/internal/persistent-stage-log-mirror.d.ts +57 -0
  340. package/dist/internal/persistent-stage-log-mirror.d.ts.map +1 -0
  341. package/dist/internal/persistent-stage-log-mirror.js +231 -0
  342. package/dist/internal/platform-schedule-sync.js +1 -1
  343. package/dist/internal/platform-timers.js +1 -1
  344. package/dist/internal/playground/static.js +2 -2
  345. package/dist/internal/playground/toolchain.js +2 -2
  346. package/dist/internal/playground-proxy.js +3 -3
  347. package/dist/internal/process-memory-telemetry.js +1 -1
  348. package/dist/internal/reminder-runner.d.ts +1 -1
  349. package/dist/internal/reminder-runner.d.ts.map +1 -1
  350. package/dist/internal/reminder-runner.js +14 -16
  351. package/dist/internal/reminder-store.js +1 -1
  352. package/dist/internal/resolved-connections.js +8 -8
  353. package/dist/internal/router.js +4 -4
  354. package/dist/internal/run-client.js +2 -2
  355. package/dist/internal/schedule-runner.d.ts +13 -2
  356. package/dist/internal/schedule-runner.d.ts.map +1 -1
  357. package/dist/internal/schedule-runner.js +48 -9
  358. package/dist/internal/sdk-runner.d.ts +2 -1
  359. package/dist/internal/sdk-runner.d.ts.map +1 -1
  360. package/dist/internal/sdk-runner.js +13 -8
  361. package/dist/internal/serve-restart.js +1 -1
  362. package/dist/internal/server.d.ts.map +1 -1
  363. package/dist/internal/server.js +101 -76
  364. package/dist/internal/session-cost.js +3 -3
  365. package/dist/internal/session-engine.d.ts +8 -0
  366. package/dist/internal/session-engine.d.ts.map +1 -1
  367. package/dist/internal/session-engine.js +183 -118
  368. package/dist/internal/session-live-publisher.d.ts +48 -0
  369. package/dist/internal/session-live-publisher.d.ts.map +1 -0
  370. package/dist/internal/session-live-publisher.js +415 -0
  371. package/dist/internal/session-run-log.js +6 -6
  372. package/dist/internal/sessions-client.js +3 -3
  373. package/dist/internal/skill-catalog.js +2 -2
  374. package/dist/internal/sleep.js +1 -1
  375. package/dist/internal/start-log-store.d.ts +5 -1
  376. package/dist/internal/start-log-store.d.ts.map +1 -1
  377. package/dist/internal/start-log-store.js +5 -3
  378. package/dist/internal/storage-coordinator.js +12 -12
  379. package/dist/internal/store-api-protocol.d.ts +51 -0
  380. package/dist/internal/store-api-protocol.d.ts.map +1 -1
  381. package/dist/internal/store-api-protocol.js +39 -2
  382. package/dist/internal/store-mirror.js +4 -4
  383. package/dist/internal/stream-progress.d.ts.map +1 -1
  384. package/dist/internal/stream-progress.js +4 -0
  385. package/dist/internal/terminal-style.js +2 -2
  386. package/dist/internal/testing/conversation-identity-vectors.d.ts +48 -0
  387. package/dist/internal/testing/conversation-identity-vectors.d.ts.map +1 -0
  388. package/dist/internal/testing/conversation-identity-vectors.js +136 -0
  389. package/dist/internal/tool-call-retry.d.ts +87 -0
  390. package/dist/internal/tool-call-retry.d.ts.map +1 -0
  391. package/dist/internal/tool-call-retry.js +387 -0
  392. package/dist/internal/tool-result.js +3 -3
  393. package/dist/internal/trajectory.js +7 -7
  394. package/dist/internal/turn-governor.js +2 -2
  395. package/dist/internal/turn-outbox.js +1 -1
  396. package/dist/internal/update-check.d.ts.map +1 -1
  397. package/dist/internal/update-check.js +4 -2
  398. package/dist/internal/v2-hosting.d.ts +6 -0
  399. package/dist/internal/v2-hosting.d.ts.map +1 -1
  400. package/dist/internal/v2-hosting.js +7 -1
  401. package/dist/internal/workspace.js +4 -4
  402. package/dist/kv/memory-kv.js +3 -3
  403. package/dist/playground/assets/index-CzttDc-d.css +1 -0
  404. package/dist/playground/assets/{index-Be0-1hw2.js → index-DIiKbZ25.js} +42 -42
  405. package/dist/playground/index.html +2 -2
  406. package/dist/prompt.js +1 -1
  407. package/dist/storage-backends/cursor-hosted-v2.js +2 -2
  408. package/dist/storage-backends/file-kv.js +7 -7
  409. package/dist/storage-protocol.d.ts +7 -0
  410. package/dist/storage-protocol.d.ts.map +1 -1
  411. package/dist/storage-protocol.js +7 -0
  412. package/dist/storage.js +3 -3
  413. package/dist/types.d.ts +21 -4
  414. package/dist/types.d.ts.map +1 -1
  415. package/dist/types.js +4 -4
  416. package/docs/reference/connections.md +2 -1
  417. package/docs/reference/hooks.md +1 -0
  418. package/docs/reference/sessions.md +1 -1
  419. package/docs/reference/tools.md +11 -0
  420. package/package.json +6 -6
  421. package/templates/agentic-owners/bot/channels/github.ts +2 -2
  422. package/templates/agentic-owners/bot/lib/github.ts +7 -5
  423. package/templates/agentic-owners/bot/lib/owners/decision.ts +9 -9
  424. package/templates/agentic-owners/bot/lib/owners/handles.ts +2 -2
  425. package/templates/agentic-owners/bot/lib/owners/match.ts +5 -3
  426. package/templates/agentic-owners/bot/lib/owners/matching.ts +1 -1
  427. package/templates/agentic-owners/bot/lib/owners/parse.ts +4 -4
  428. package/templates/agentic-owners/bot/lib/owners/prompt.ts +1 -1
  429. package/templates/agentic-owners/bot/lib/review.ts +18 -17
  430. package/templates/agentic-owners/evals/owners.eval.ts +2 -2
  431. package/templates/agents-md/bot/lib/collect.ts +6 -6
  432. package/templates/agents-md/bot/lib/config.ts +1 -1
  433. package/templates/agents-md/bot/tools/apply_agents.ts +4 -4
  434. package/templates/code-wiki/bot/channels/github.ts +3 -3
  435. package/templates/code-wiki/bot/lib/repos.ts +1 -1
  436. package/templates/code-wiki/bot/tools/apply_wiki.ts +2 -2
  437. package/templates/demo/bot/lib/collect.ts +1 -1
  438. package/templates/demo/bot/lib/repos.ts +1 -1
  439. package/templates/demo/bot/tools/record_demo.ts +1 -1
  440. package/templates/pr-autofixer/bot/channels/github.ts +2 -2
  441. package/templates/pr-autofixer/bot/lib/merge-watch.ts +2 -2
  442. package/templates/pr-autofixer/bot/lib/repos.ts +2 -2
  443. package/templates/pr-autofixer/bot/lib/webhook-routing.ts +1 -1
  444. package/templates/security-help/bot/lib/repos.ts +1 -1
  445. package/templates/security-reviewer/bot/lib/repos.ts +1 -1
  446. package/templates/triage/bot/lib/actuate.ts +15 -15
  447. package/dist/docs/assets/chunks/@localSearchIndexroot.CtLtpWcx.js +0 -1
  448. package/dist/docs/assets/chunks/channel.CBwrU9rP.js +0 -1
  449. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.CbC_mrvB.js +0 -1
  450. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.CbC_mrvB.js +0 -1
  451. package/dist/docs/assets/chunks/clone.BTvFyY1a.js +0 -1
  452. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.BYXl4LW6.js +0 -1
  453. package/dist/docs/assets/chunks/wardley-RL74JXVD.iXazD3Z7.js +0 -162
  454. package/dist/playground/assets/index-Clz6uHj9.css +0 -1
  455. /package/dist/docs/assets/{reference_connections.md.Bljpve-y.lean.js → reference_connections.md.DLrgAd5f.lean.js} +0 -0
  456. /package/dist/docs/assets/{reference_sessions.md.CM5zo3w4.lean.js → reference_sessions.md.CyM7ARz1.lean.js} +0 -0
  457. /package/dist/docs/assets/{reference_skills.md.ClkMoQsV.lean.js → reference_skills.md.C0guGcH0.lean.js} +0 -0
@@ -53,14 +53,17 @@ import { sessionExternalLinks } from "./session-links.js";
53
53
  import { SessionStore } from "./session-store.js";
54
54
  import { syncSkillsToStore } from "./skills-sync.js";
55
55
  import { steeringEnabled } from "./steering.js";
56
+ import { resolveApiKeySync } from "./cursor/credentials.js";
57
+ import { createSessionLivePublisher } from "./session-live-publisher.js";
56
58
  import { StorageCoordinator, isTurnBoundaryEvent } from "./storage-coordinator.js";
57
59
  import { decideToolCall, directCallEffect } from "./tool-policy.js";
60
+ import { retryReadOnlyToolCall } from "./tool-call-retry.js";
58
61
  import { normalizeToolResult, toolCallErrorMessage } from "./tool-result.js";
59
62
  import { estimateTurnCostFromApi, roundCostUsd, } from "./turn-cost.js";
60
63
  import { TurnGovernor } from "./turn-governor.js";
61
64
  import { TurnLeaseStore } from "./turn-lease-store.js";
62
65
  import { TurnOutbox } from "./turn-outbox.js";
63
- import { resolveAgentV2Hosting } from "./v2-hosting.js";
66
+ import { isCursorManagedV2Hosting, resolveAgentV2Hosting } from "./v2-hosting.js";
64
67
  import { buildAgentsMdContent, buildCloudMemorySection, buildCloudSessionWorkspaceSection, buildCloudWorkspaceSection, ensureOwnGitRoot, isNestedInGitRepo, materializeWorkspace, SERVER_TOOLS_MCP_SERVER_NAME, } from "./workspace.js";
65
68
  import { syncSessionWorkspaceFiles, syncWorkspaceToStore, WorkspaceFileRefusal, wipeSessionWorkspace, } from "./workspace-sync.js";
66
69
  export const HTTP_CHANNEL_ID = "http";
@@ -274,7 +277,7 @@ export class SessionEngine {
274
277
  this.askDedupe = new SlackAskDedupeStore(join(options.stateRoot, "slack-asks"));
275
278
  this.turnLeases = new TurnLeaseStore(join(options.stateRoot, "turn-leases"));
276
279
  this.outbox = new TurnOutbox(join(options.stateRoot, "outbox"));
277
- this.logs = new EventLogStore(sessionId => this.sessions.eventFilePath(sessionId), (sessionId, error) => this.logger(`[bdk] failed to persist events for ${sessionId}: ${describeError(error)}`));
280
+ this.logs = new EventLogStore((sessionId) => this.sessions.eventFilePath(sessionId), (sessionId, error) => this.logger(`[bdk] failed to persist events for ${sessionId}: ${describeError(error)}`));
278
281
  // Framework session state (records, event chunks, continuations) is
279
282
  // mirrored to whatever this selects; see framework-storage-selection.ts
280
283
  // for why the choice does not belong to the agent author.
@@ -292,14 +295,24 @@ export class SessionEngine {
292
295
  logger: this.logger,
293
296
  keys: storageKeysForArchitecture(options.project.agent.architecture),
294
297
  });
298
+ const v2Hosting = resolveAgentV2Hosting({
299
+ architecture: options.project.agent.architecture,
300
+ });
301
+ // Author KV stays on disk for a persistent slot: `/state/kv` is durable
302
+ // and already holds entries a switch to the store would hide.
303
+ const authorKvStorage = v2Hosting.kind === "cursor-managed-persistent" ? undefined : this.storage;
295
304
  this.kvApi = createHostKvApi({
296
305
  agentName: options.project.name,
297
306
  stateRoot: options.stateRoot,
298
- ...(this.storage === undefined ? {} : { storage: this.storage }),
299
- });
300
- const v2Hosting = resolveAgentV2Hosting({
301
- architecture: options.project.agent.architecture,
307
+ ...(authorKvStorage === undefined ? {} : { storage: authorKvStorage }),
302
308
  });
309
+ this.livePublisher = isCursorManagedV2Hosting(v2Hosting)
310
+ ? createSessionLivePublisher({
311
+ readEvents: (sessionId, fromIndex) => this.listEvents(sessionId, fromIndex),
312
+ resolveApiKey: () => resolveApiKeySync()?.apiKey,
313
+ logger: this.logger,
314
+ })
315
+ : undefined;
303
316
  const managedV2Files = v2Hosting.kind === "cursor-managed"
304
317
  ? () => cursorHostedFiles({
305
318
  resolveStoreSourceId: () => v2Hosting.resolveStoreIds().deploymentStoreSourceId,
@@ -332,7 +345,7 @@ export class SessionEngine {
332
345
  this.mcpHost = new McpHost([
333
346
  ...options.project.agent.connections,
334
347
  ...(options.project.agent.hostConnections ?? []),
335
- ].filter(connection => !isSymbolicConnectionTransport(connection.transport)));
348
+ ].filter((connection) => !isSymbolicConnectionTransport(connection.transport)));
336
349
  const basePlatforms = options.platforms ?? createHostPlatforms();
337
350
  const slackBinding = resolveDedicatedSlackHostBinding(options.project.channels);
338
351
  this.platforms =
@@ -378,8 +391,8 @@ export class SessionEngine {
378
391
  }
379
392
  }
380
393
  authoredConnection(name) {
381
- return (this.project.agent.connections.find(item => item.name === name) ??
382
- this.project.agent.hostConnections?.find(item => item.name === name));
394
+ return (this.project.agent.connections.find((item) => item.name === name) ??
395
+ this.project.agent.hostConnections?.find((item) => item.name === name));
383
396
  }
384
397
  setCloudServerToolsConnection(connection, resolveHeaders) {
385
398
  this.cloudServerToolsConnection = connection;
@@ -464,8 +477,8 @@ export class SessionEngine {
464
477
  turnId: input.turnId ?? binding.turnId,
465
478
  });
466
479
  },
467
- list: filter => this.artifactsStore.list(filter),
468
- page: options => this.artifactsStore.page(options),
480
+ list: (filter) => this.artifactsStore.list(filter),
481
+ page: (options) => this.artifactsStore.page(options),
469
482
  };
470
483
  }
471
484
  /**
@@ -592,10 +605,10 @@ export class SessionEngine {
592
605
  }
593
606
  slackNudgeHostApi() {
594
607
  return {
595
- append: input => this.nudgeStore.append(input),
596
- drainFormatted: continuationKey => this.nudgeStore.drainFormatted(continuationKey),
597
- clear: continuationKey => this.nudgeStore.clear(continuationKey),
598
- hasUndelivered: continuationKey => this.nudgeStore.hasUndelivered(continuationKey),
608
+ append: (input) => this.nudgeStore.append(input),
609
+ drainFormatted: (continuationKey) => this.nudgeStore.drainFormatted(continuationKey),
610
+ clear: (continuationKey) => this.nudgeStore.clear(continuationKey),
611
+ hasUndelivered: (continuationKey) => this.nudgeStore.hasUndelivered(continuationKey),
599
612
  isDelivered: (continuationKey, sourceTs) => this.nudgeStore.isDelivered(continuationKey, sourceTs),
600
613
  tryClaimAsk: (channelId, messageTs) => this.askDedupe.tryClaim(channelId, messageTs),
601
614
  releaseAsk: (channelId, messageTs) => this.askDedupe.release(channelId, messageTs),
@@ -686,7 +699,7 @@ export class SessionEngine {
686
699
  if (refreshWorkspace ||
687
700
  sendOptions.workspaceFiles !== undefined ||
688
701
  sendOptions.images !== undefined) {
689
- record = await this.updateRecord(existing.sessionId, current => ({
702
+ record = await this.updateRecord(existing.sessionId, (current) => ({
690
703
  ...current,
691
704
  workspaceOverride: refreshWorkspace
692
705
  ? sendOptions.workspaceDir
@@ -699,14 +712,14 @@ export class SessionEngine {
699
712
  // configured runtime. Omission remains sticky for compatibility:
700
713
  // follow-ups that do not know the original attach keep it.
701
714
  if (sendOptions.clearCloudOverride === true && record.cloudOverride !== undefined) {
702
- record = await this.updateRecord(record.sessionId, current => ({
715
+ record = await this.updateRecord(record.sessionId, (current) => ({
703
716
  ...current,
704
717
  cloudOverride: undefined,
705
718
  }));
706
719
  }
707
720
  else if (sendOptions.cloud !== undefined &&
708
721
  JSON.stringify(sendOptions.cloud) !== JSON.stringify(record.cloudOverride)) {
709
- record = await this.updateRecord(record.sessionId, current => ({
722
+ record = await this.updateRecord(record.sessionId, (current) => ({
710
723
  ...current,
711
724
  cloudOverride: sendOptions.cloud,
712
725
  }));
@@ -714,7 +727,7 @@ export class SessionEngine {
714
727
  // Refresh wake-derived channel state (GitHub headSha / refs) without
715
728
  // wiping sticky fields. Null patch values are skipped.
716
729
  if (sendOptions.refreshState !== undefined) {
717
- record = await this.updateRecord(record.sessionId, current => ({
730
+ record = await this.updateRecord(record.sessionId, (current) => ({
718
731
  ...current,
719
732
  channelState: mergeChannelStateSkipNull(current.channelState, sendOptions.refreshState),
720
733
  }));
@@ -791,7 +804,7 @@ export class SessionEngine {
791
804
  const stale = new Error("stale HTTP continuation");
792
805
  let previous;
793
806
  try {
794
- await this.updateRecord(sessionId, record => {
807
+ await this.updateRecord(sessionId, (record) => {
795
808
  const expectedChannel = record.httpContinuationKey === undefined ? record.channelId : HTTP_CHANNEL_ID;
796
809
  const expectedKey = record.httpContinuationKey ?? record.continuationKey;
797
810
  if (token.channelId !== expectedChannel || token.key !== expectedKey) {
@@ -812,7 +825,7 @@ export class SessionEngine {
812
825
  return next;
813
826
  }
814
827
  catch (error) {
815
- await this.updateRecord(sessionId, record => record.httpContinuationKey === next ? { ...record, httpContinuationKey: previous } : record);
828
+ await this.updateRecord(sessionId, (record) => record.httpContinuationKey === next ? { ...record, httpContinuationKey: previous } : record);
816
829
  throw error;
817
830
  }
818
831
  }
@@ -939,7 +952,7 @@ export class SessionEngine {
939
952
  drainOutbox(sessionId) {
940
953
  void this.outbox
941
954
  .takeAll(sessionId)
942
- .then(items => {
955
+ .then((items) => {
943
956
  for (const item of items) {
944
957
  void this.startTurn(sessionId, item.message, item.options).catch(() => { });
945
958
  }
@@ -948,7 +961,7 @@ export class SessionEngine {
948
961
  }
949
962
  enqueueCoalesced(sessionId, item) {
950
963
  const queue = this.coalesceQueues.get(sessionId) ?? [];
951
- if (item.sourceTs !== undefined && queue.some(entry => entry.sourceTs === item.sourceTs)) {
964
+ if (item.sourceTs !== undefined && queue.some((entry) => entry.sourceTs === item.sourceTs)) {
952
965
  return;
953
966
  }
954
967
  queue.push(item);
@@ -1124,7 +1137,7 @@ export class SessionEngine {
1124
1137
  this.pendingTurns.add(sessionId);
1125
1138
  let lifecycleInstalled = false;
1126
1139
  try {
1127
- const record = await this.updateRecord(sessionId, current => ({
1140
+ const record = await this.updateRecord(sessionId, (current) => ({
1128
1141
  ...current,
1129
1142
  turnCount: current.turnCount + 1,
1130
1143
  }));
@@ -1175,7 +1188,7 @@ export class SessionEngine {
1175
1188
  // Failed or cancelled owners must not start a coalesced successor;
1176
1189
  // managed delivery retries the same follow-ups.
1177
1190
  if (wasCurrent && !abort.signal.aborted && outcome.status === "finished") {
1178
- const drain = this.drainCoalescedFollowups(sessionId).catch(error => {
1191
+ const drain = this.drainCoalescedFollowups(sessionId).catch((error) => {
1179
1192
  this.logger(`[session] coalesce drain failed for ${sessionId}: ${describeError(error)}`);
1180
1193
  });
1181
1194
  this.coalesceDrains.set(sessionId, drain);
@@ -1391,7 +1404,7 @@ export class SessionEngine {
1391
1404
  if (turn === undefined) {
1392
1405
  return tools;
1393
1406
  }
1394
- return tools.map(tool => {
1407
+ return tools.map((tool) => {
1395
1408
  const execute = tool.definition.execute;
1396
1409
  if (typeof execute !== "function") {
1397
1410
  return tool;
@@ -1586,7 +1599,7 @@ export class SessionEngine {
1586
1599
  // the turns' requests or the warmed executor is one no turn asks for.
1587
1600
  mcpServers: this.buildMcpServers("local"),
1588
1601
  ...(this.hasAttachedAuthedConnections() ||
1589
- this.project.agent.connections.some(connection => isCursorAccountTransport(connection.transport))
1602
+ this.project.agent.connections.some((connection) => isCursorAccountTransport(connection.transport))
1590
1603
  ? { perSendMcpServers: true }
1591
1604
  : {}),
1592
1605
  subagents: buildRunnerSubagents(agent),
@@ -1637,7 +1650,7 @@ export class SessionEngine {
1637
1650
  // Read by closure, so the mapper still sees it while draining after the
1638
1651
  // registry entry below is gone.
1639
1652
  const stubbed = new Set();
1640
- const mapper = new TurnEventMapper(emit, callId => stubbed.has(callId));
1653
+ const mapper = new TurnEventMapper(emit, (callId) => stubbed.has(callId));
1641
1654
  // Take a turn slot before any work happens. When every slot is busy the
1642
1655
  // turn waits FIFO — durable `turn.queued` marks the wait — and a
1643
1656
  // preempting follow-up (or interrupt) resolves the wait as cancelled
@@ -1645,7 +1658,7 @@ export class SessionEngine {
1645
1658
  const permit = await this.turnGovernor.acquire({
1646
1659
  sessionId,
1647
1660
  signal,
1648
- onQueued: position => {
1661
+ onQueued: (position) => {
1649
1662
  const maxRunningTurns = this.turnGovernor.maxRunningTurns ?? 0;
1650
1663
  emit({ type: "turn.queued", data: { position, maxRunningTurns } });
1651
1664
  this.logger(`[session] ${sessionId} ${turnId} queued at position ${position} (${maxRunningTurns} turn slot(s) busy)`);
@@ -1704,7 +1717,7 @@ export class SessionEngine {
1704
1717
  }
1705
1718
  if ((hasPendingFiles && runtime !== "cloud") ||
1706
1719
  (pendingImages !== undefined && pendingImages.length > 0)) {
1707
- await this.updateRecord(sessionId, current => ({
1720
+ await this.updateRecord(sessionId, (current) => ({
1708
1721
  ...current,
1709
1722
  pendingWorkspaceFiles: hasPendingFiles &&
1710
1723
  runtime !== "cloud" &&
@@ -1772,7 +1785,7 @@ export class SessionEngine {
1772
1785
  mapper.finish();
1773
1786
  if (mapper.title !== undefined) {
1774
1787
  const title = mapper.title;
1775
- await this.updateRecord(sessionId, current => ({ ...current, title }));
1788
+ await this.updateRecord(sessionId, (current) => ({ ...current, title }));
1776
1789
  eventContext.session = { ...eventContext.session, title };
1777
1790
  }
1778
1791
  const finalResult = outcome.result ?? mapper.finalText;
@@ -1832,7 +1845,7 @@ export class SessionEngine {
1832
1845
  // dispatch, and awaiting that chain deadlocks when an earlier handler
1833
1846
  // is waiting on the next turn (defineResult refresh). Coalesce drain
1834
1847
  // snapshots disk as soon as this returns.
1835
- await this.updateRecord(sessionId, current => ({
1848
+ await this.updateRecord(sessionId, (current) => ({
1836
1849
  ...current,
1837
1850
  channelState: mergeChannelStateMutation({
1838
1851
  current: current.channelState,
@@ -1912,7 +1925,7 @@ export class SessionEngine {
1912
1925
  }
1913
1926
  }
1914
1927
  async clearPendingWorkspaceFiles(sessionId, pending) {
1915
- await this.updateRecord(sessionId, current => ({
1928
+ await this.updateRecord(sessionId, (current) => ({
1916
1929
  ...current,
1917
1930
  pendingWorkspaceFiles: current.pendingWorkspaceFiles === pending ? undefined : current.pendingWorkspaceFiles,
1918
1931
  }));
@@ -1929,7 +1942,7 @@ export class SessionEngine {
1929
1942
  if (inFlight !== undefined) {
1930
1943
  return inFlight;
1931
1944
  }
1932
- let sync = run().then(() => true, error => {
1945
+ let sync = run().then(() => true, (error) => {
1933
1946
  this.logger(`[${surface}] ${store.label} sync failed: ${error instanceof Error ? error.message : String(error)}`);
1934
1947
  return false;
1935
1948
  });
@@ -2016,7 +2029,7 @@ export class SessionEngine {
2016
2029
  // per-session tools or identity is worse than a refused one. Non-local
2017
2030
  // agents already fail discovery; this guards hybrid agents' per-send
2018
2031
  // cloud sessions.
2019
- const perSessionConnection = agent.connections.find(connection => connection.advertiseTools === true || connection.auth !== undefined);
2032
+ const perSessionConnection = agent.connections.find((connection) => connection.advertiseTools === true || connection.auth !== undefined);
2020
2033
  if (runtime !== "local" && perSessionConnection !== undefined) {
2021
2034
  throw new Error(`Agent "${agent.name}" connection "${perSessionConnection.name}" uses advertiseTools/auth, which only run on local turns. Refusing the session rather than running it without the connection's tools or identity.`);
2022
2035
  }
@@ -2055,7 +2068,7 @@ export class SessionEngine {
2055
2068
  // replace a working index with an empty custom tool.
2056
2069
  const synthesized = root === undefined
2057
2070
  ? []
2058
- : this.withTurnScratchTools(authoredRoot ? fileTools : fileTools.filter(tool => tool.name !== "SemanticSearch"), record.sessionId);
2071
+ : this.withTurnScratchTools(authoredRoot ? fileTools : fileTools.filter((tool) => tool.name !== "SemanticSearch"), record.sessionId);
2059
2072
  let turnPrompt = prompt;
2060
2073
  if (isFirstTurn) {
2061
2074
  const contextBlock = buildSessionContextBlock({
@@ -2120,7 +2133,7 @@ export class SessionEngine {
2120
2133
  sections.push(buildCloudMemorySection(this.project.name));
2121
2134
  }
2122
2135
  if (preamble !== "" || sections.length > 0) {
2123
- turnPrompt = [preamble, ...sections, turnPrompt].filter(part => part !== "").join("\n\n");
2136
+ turnPrompt = [preamble, ...sections, turnPrompt].filter((part) => part !== "").join("\n\n");
2124
2137
  }
2125
2138
  }
2126
2139
  else if (isFirstTurn && runtime === "local" && authoredRoot) {
@@ -2172,11 +2185,13 @@ export class SessionEngine {
2172
2185
  ...(runtime === "cloud" && !isCursorHostedFilesAvailable()
2173
2186
  ? { agentServeAgent: this.project.name }
2174
2187
  : {}),
2175
- customTools: runtime === "local" ? await this.buildCustomTools(record, turnId, emit, synthesized) : {},
2188
+ customTools: runtime === "local"
2189
+ ? await this.buildCustomTools(record, turnId, emit, synthesized, signal)
2190
+ : {},
2176
2191
  mcpServers: this.buildMcpServers(runtime, record.sessionId, await this.evaluateConnectionAuth(record)),
2177
2192
  ...(runtime === "local" &&
2178
2193
  (this.hasAttachedAuthedConnections() ||
2179
- this.project.agent.connections.some(connection => isCursorAccountTransport(connection.transport)))
2194
+ this.project.agent.connections.some((connection) => isCursorAccountTransport(connection.transport)))
2180
2195
  ? { perSendMcpServers: true }
2181
2196
  : {}),
2182
2197
  subagents: buildRunnerSubagents(agent),
@@ -2185,14 +2200,14 @@ export class SessionEngine {
2185
2200
  // Local follow-ups expire any lingering active run so a preempted turn
2186
2201
  // (or one orphaned by a crashed process) never blocks this send.
2187
2202
  forceExpireActiveRun: runtime === "local" && !isFirstTurn,
2188
- onRequestId: requestId => {
2203
+ onRequestId: (requestId) => {
2189
2204
  emit({ type: "turn.bound", data: { requestId } });
2190
2205
  },
2191
2206
  onSdkAgentId: async (sdkAgentId) => {
2192
2207
  if (record.sdkAgentId === sdkAgentId) {
2193
2208
  return;
2194
2209
  }
2195
- await this.updateRecord(record.sessionId, current => ({
2210
+ await this.updateRecord(record.sessionId, (current) => ({
2196
2211
  ...current,
2197
2212
  sdkAgentId,
2198
2213
  }));
@@ -2275,9 +2290,9 @@ export class SessionEngine {
2275
2290
  // Advertised connections surface as named server tools instead of an
2276
2291
  // attached MCP server (each tool appears exactly once).
2277
2292
  const advertisedNames = new Set(this.project.agent.connections
2278
- .filter(connection => connection.advertiseTools === true)
2279
- .map(connection => connection.name));
2280
- const hostConnectionNames = new Set((this.project.agent.hostConnections ?? []).map(connection => connection.name));
2293
+ .filter((connection) => connection.advertiseTools === true)
2294
+ .map((connection) => connection.name));
2295
+ const hostConnectionNames = new Set((this.project.agent.hostConnections ?? []).map((connection) => connection.name));
2281
2296
  const bridgedNames = new Set(runtime === "cloud" &&
2282
2297
  sessionId !== undefined &&
2283
2298
  this.cloudServerToolsConnection !== undefined &&
@@ -2286,7 +2301,7 @@ export class SessionEngine {
2286
2301
  : []);
2287
2302
  assertCloudCanHonorAccountServersFilters({
2288
2303
  runtime,
2289
- resolvedConnections: this.resolvedConnections.filter(resolved => !advertisedNames.has(resolved.name) && !hostConnectionNames.has(resolved.name)),
2304
+ resolvedConnections: this.resolvedConnections.filter((resolved) => !advertisedNames.has(resolved.name) && !hostConnectionNames.has(resolved.name)),
2290
2305
  bridgedNames,
2291
2306
  });
2292
2307
  const bridgeTransport = (name) => sessionId === undefined || !bridgedNames.has(name)
@@ -2368,7 +2383,7 @@ export class SessionEngine {
2368
2383
  if (runtime === "cloud" &&
2369
2384
  sessionId !== undefined &&
2370
2385
  this.cloudServerToolsConnection !== undefined &&
2371
- this.project.agent.tools.some(tool => tool.execution === "server")) {
2386
+ this.project.agent.tools.some((tool) => tool.execution === "server")) {
2372
2387
  if (servers[SERVER_TOOLS_MCP_SERVER_NAME] !== undefined) {
2373
2388
  throw new Error(`MCP connection name "${SERVER_TOOLS_MCP_SERVER_NAME}" is reserved for authored server tools on cloud turns.`);
2374
2389
  }
@@ -2391,7 +2406,7 @@ export class SessionEngine {
2391
2406
  * ride every send instead of being pinned on the cached agent handle.
2392
2407
  */
2393
2408
  hasAttachedAuthedConnections() {
2394
- return this.project.agent.connections.some(connection => connection.auth !== undefined && connection.advertiseTools !== true);
2409
+ return this.project.agent.connections.some((connection) => connection.auth !== undefined && connection.advertiseTools !== true);
2395
2410
  }
2396
2411
  /**
2397
2412
  * Evaluate per-session connection auth (`defineConnection({ auth })`)
@@ -2401,7 +2416,7 @@ export class SessionEngine {
2401
2416
  * without the connection's identity.
2402
2417
  */
2403
2418
  async evaluateConnectionAuth(record) {
2404
- const authed = this.project.agent.connections.filter(connection => connection.auth !== undefined && connection.advertiseTools !== true);
2419
+ const authed = this.project.agent.connections.filter((connection) => connection.auth !== undefined && connection.advertiseTools !== true);
2405
2420
  if (authed.length === 0) {
2406
2421
  return undefined;
2407
2422
  }
@@ -2423,7 +2438,7 @@ export class SessionEngine {
2423
2438
  }
2424
2439
  return evaluated;
2425
2440
  }
2426
- async buildCustomTools(record, turnId, emit, extraTools = []) {
2441
+ async buildCustomTools(record, turnId, emit, extraTools = [], signal) {
2427
2442
  const agent = this.project.agent;
2428
2443
  const tools = {};
2429
2444
  const register = (tool) => {
@@ -2447,6 +2462,7 @@ export class SessionEngine {
2447
2462
  record,
2448
2463
  turnId,
2449
2464
  emit,
2465
+ signal,
2450
2466
  });
2451
2467
  },
2452
2468
  };
@@ -2494,7 +2510,7 @@ export class SessionEngine {
2494
2510
  if (active === undefined) {
2495
2511
  return toolErrorResult(`Session ${sessionId} has no active turn for tool "${toolName}".`);
2496
2512
  }
2497
- const tool = this.project.agent.tools.find(candidate => candidate.name === toolName && candidate.execution === "server");
2513
+ const tool = this.project.agent.tools.find((candidate) => candidate.name === toolName && candidate.execution === "server");
2498
2514
  if (tool === undefined) {
2499
2515
  return toolErrorResult(`Unknown server tool "${toolName}".`);
2500
2516
  }
@@ -2507,6 +2523,7 @@ export class SessionEngine {
2507
2523
  record: active.record,
2508
2524
  turnId: active.turnId,
2509
2525
  emit: active.emit,
2526
+ signal: this.turnAborts.get(sessionId)?.signal,
2510
2527
  });
2511
2528
  this.logger(`[session] cloud HTTP MCP tool ${toolName} complete (${sessionId}, ${toolCallId}, isError=${isErrorEnvelope(result)})`);
2512
2529
  return result;
@@ -2607,7 +2624,14 @@ export class SessionEngine {
2607
2624
  callId: toolCallId,
2608
2625
  toolName: args.tool.name,
2609
2626
  emit: args.emit,
2610
- }, () => execute(validation.value, toolCtx)));
2627
+ }, () => this.runExecutedTool({
2628
+ tool: args.tool,
2629
+ input: validation.value,
2630
+ callId: toolCallId,
2631
+ signal: args.signal,
2632
+ emit: args.emit,
2633
+ execute: () => execute(validation.value, toolCtx),
2634
+ })));
2611
2635
  this.logger(`[session] tool ${args.tool.name} done (${Date.now() - started}ms)`);
2612
2636
  return normalizeToolResult(result);
2613
2637
  }
@@ -2651,6 +2675,34 @@ export class SessionEngine {
2651
2675
  toolName: args.toolName,
2652
2676
  }, run);
2653
2677
  }
2678
+ /**
2679
+ * Retry a read-effect call that already passed validation, dry-run, and
2680
+ * approval. Anything else runs once; a transient failure there is counted
2681
+ * and rethrown unchanged.
2682
+ */
2683
+ runExecutedTool(args) {
2684
+ const connection = args.tool.connection;
2685
+ return retryReadOnlyToolCall({
2686
+ toolName: args.tool.name,
2687
+ ...(connection === undefined ? {} : { connection }),
2688
+ effect: directCallEffect(args.tool, args.input),
2689
+ signal: args.signal,
2690
+ onRetry: (notice) => {
2691
+ this.logger(`[session] tool ${args.tool.name} retry connection=${notice.connection ?? "-"} attempt=${notice.attempt} class=${notice.reason} backoffMs=${notice.backoffMs}`);
2692
+ args.emit?.({
2693
+ type: "action.tool_retry",
2694
+ data: {
2695
+ callId: args.callId,
2696
+ toolName: args.tool.name,
2697
+ attempt: notice.attempt,
2698
+ reason: notice.reason,
2699
+ ...(notice.connection === undefined ? {} : { connection: notice.connection }),
2700
+ },
2701
+ });
2702
+ },
2703
+ execute: args.execute,
2704
+ });
2705
+ }
2654
2706
  /**
2655
2707
  * Park a server-tool call until a human approves or denies. Emits
2656
2708
  * `action.approval_requested` / `action.approval_resolved` on the
@@ -2666,10 +2718,10 @@ export class SessionEngine {
2666
2718
  requestedAt,
2667
2719
  };
2668
2720
  const resolutionPromise = this.approvals.wait(args.sessionId, pendingRecord);
2669
- await this.updateRecord(args.sessionId, current => ({
2721
+ await this.updateRecord(args.sessionId, (current) => ({
2670
2722
  ...current,
2671
2723
  pendingApprovals: [
2672
- ...(current.pendingApprovals ?? []).filter(item => item.callId !== args.callId),
2724
+ ...(current.pendingApprovals ?? []).filter((item) => item.callId !== args.callId),
2673
2725
  pendingRecord,
2674
2726
  ],
2675
2727
  }));
@@ -2683,9 +2735,9 @@ export class SessionEngine {
2683
2735
  });
2684
2736
  this.logger(`[session] tool ${args.toolName} awaiting approval (${args.callId})`);
2685
2737
  const { decision, by } = await resolutionPromise;
2686
- await this.updateRecord(args.sessionId, current => ({
2738
+ await this.updateRecord(args.sessionId, (current) => ({
2687
2739
  ...current,
2688
- pendingApprovals: (current.pendingApprovals ?? []).filter(item => item.callId !== args.callId),
2740
+ pendingApprovals: (current.pendingApprovals ?? []).filter((item) => item.callId !== args.callId),
2689
2741
  }));
2690
2742
  args.emit({
2691
2743
  type: "action.approval_resolved",
@@ -2706,7 +2758,7 @@ export class SessionEngine {
2706
2758
  current.pendingApprovals.length === 0) {
2707
2759
  return;
2708
2760
  }
2709
- await this.updateRecord(sessionId, record => ({
2761
+ await this.updateRecord(sessionId, (record) => ({
2710
2762
  ...record,
2711
2763
  pendingApprovals: [],
2712
2764
  }));
@@ -2740,8 +2792,8 @@ export class SessionEngine {
2740
2792
  if (!samePrincipal(record.auth, ownershipAuth)) {
2741
2793
  throw new SessionAuthError(sessionId);
2742
2794
  }
2743
- const pending = (record.pendingApprovals ?? []).find(item => item.callId === callId) ??
2744
- this.approvals.list(sessionId).find(item => item.callId === callId);
2795
+ const pending = (record.pendingApprovals ?? []).find((item) => item.callId === callId) ??
2796
+ this.approvals.list(sessionId).find((item) => item.callId === callId);
2745
2797
  if (pending === undefined) {
2746
2798
  throw new ApprovalNotFoundError(sessionId, callId);
2747
2799
  }
@@ -2753,23 +2805,23 @@ export class SessionEngine {
2753
2805
  return pending;
2754
2806
  }
2755
2807
  async removePendingApproval(sessionId, callId) {
2756
- await this.updateRecord(sessionId, current => ({
2808
+ await this.updateRecord(sessionId, (current) => ({
2757
2809
  ...current,
2758
- pendingApprovals: (current.pendingApprovals ?? []).filter(item => item.callId !== callId),
2810
+ pendingApprovals: (current.pendingApprovals ?? []).filter((item) => item.callId !== callId),
2759
2811
  }));
2760
2812
  }
2761
2813
  wrapMcp(inner) {
2762
2814
  return {
2763
2815
  names: () => inner.names(),
2764
- listTools: name => this.withMcpAuth(name, () => inner.listTools(name)),
2816
+ listTools: (name) => this.withMcpAuth(name, () => inner.listTools(name)),
2765
2817
  callTool: (name, tool, args) => this.withMcpAuth(name, () => inner.callTool(name, tool, args)),
2766
2818
  };
2767
2819
  }
2768
2820
  advertiseMcp() {
2769
2821
  return {
2770
- listTools: name => this.withMcpListAuth(name, () => this.mcpHost.listTools(name)),
2822
+ listTools: (name) => this.withMcpListAuth(name, () => this.mcpHost.listTools(name)),
2771
2823
  callTool: (name, tool, args) => this.withMcpAuth(name, () => this.mcpHost.callTool(name, tool, args)),
2772
- oneOff: connection => {
2824
+ oneOff: (connection) => {
2773
2825
  const inner = this.mcpHost.oneOff(connection);
2774
2826
  return {
2775
2827
  listTools: () => this.withMcpListAuth(connection.name, () => inner.listTools()),
@@ -2885,10 +2937,10 @@ export class SessionEngine {
2885
2937
  requestedAt,
2886
2938
  };
2887
2939
  const resolutionPromise = this.auths.wait(args.sessionId, pendingRecord);
2888
- await this.updateRecord(args.sessionId, current => ({
2940
+ await this.updateRecord(args.sessionId, (current) => ({
2889
2941
  ...current,
2890
2942
  pendingAuths: [
2891
- ...(current.pendingAuths ?? []).filter(item => item.callId !== args.callId),
2943
+ ...(current.pendingAuths ?? []).filter((item) => item.callId !== args.callId),
2892
2944
  pendingRecord,
2893
2945
  ],
2894
2946
  }));
@@ -2903,9 +2955,9 @@ export class SessionEngine {
2903
2955
  });
2904
2956
  this.logger(`[session] tool ${args.toolName} awaiting MCP auth ${args.connection} (${args.callId})`);
2905
2957
  const { decision, by } = await resolutionPromise;
2906
- await this.updateRecord(args.sessionId, current => ({
2958
+ await this.updateRecord(args.sessionId, (current) => ({
2907
2959
  ...current,
2908
- pendingAuths: (current.pendingAuths ?? []).filter(item => item.callId !== args.callId),
2960
+ pendingAuths: (current.pendingAuths ?? []).filter((item) => item.callId !== args.callId),
2909
2961
  }));
2910
2962
  args.emit({
2911
2963
  type: "action.auth_resolved",
@@ -2928,7 +2980,7 @@ export class SessionEngine {
2928
2980
  current.pendingAuths.length === 0) {
2929
2981
  return;
2930
2982
  }
2931
- await this.updateRecord(sessionId, record => ({
2983
+ await this.updateRecord(sessionId, (record) => ({
2932
2984
  ...record,
2933
2985
  pendingAuths: [],
2934
2986
  }));
@@ -2953,8 +3005,8 @@ export class SessionEngine {
2953
3005
  if (!samePrincipal(record.auth, ownershipAuth)) {
2954
3006
  throw new SessionAuthError(sessionId);
2955
3007
  }
2956
- const pending = (record.pendingAuths ?? []).find(item => item.callId === callId) ??
2957
- this.auths.list(sessionId).find(item => item.callId === callId);
3008
+ const pending = (record.pendingAuths ?? []).find((item) => item.callId === callId) ??
3009
+ this.auths.list(sessionId).find((item) => item.callId === callId);
2958
3010
  if (pending === undefined) {
2959
3011
  throw new AuthNotFoundError(sessionId, callId);
2960
3012
  }
@@ -2969,9 +3021,9 @@ export class SessionEngine {
2969
3021
  return pending;
2970
3022
  }
2971
3023
  async removePendingAuth(sessionId, callId) {
2972
- await this.updateRecord(sessionId, current => ({
3024
+ await this.updateRecord(sessionId, (current) => ({
2973
3025
  ...current,
2974
- pendingAuths: (current.pendingAuths ?? []).filter(item => item.callId !== callId),
3026
+ pendingAuths: (current.pendingAuths ?? []).filter((item) => item.callId !== callId),
2975
3027
  }));
2976
3028
  }
2977
3029
  async runWithMcpPark(sessionId, toolName, fn) {
@@ -3113,16 +3165,16 @@ export class SessionEngine {
3113
3165
  * fetch for `ls` must not wait on every advertised MCP server.
3114
3166
  */
3115
3167
  async describeCatalogTool(toolName, options = {}) {
3116
- const authored = this.project.agent.tools.find(tool => tool.name === toolName);
3168
+ const authored = this.project.agent.tools.find((tool) => tool.name === toolName);
3117
3169
  if (authored !== undefined) {
3118
3170
  return { tool: authored };
3119
3171
  }
3120
3172
  const catalog = await this.listCatalogTools(options);
3121
- const tool = catalog.tools.find(entry => entry.name === toolName);
3173
+ const tool = catalog.tools.find((entry) => entry.name === toolName);
3122
3174
  if (tool === undefined) {
3123
3175
  return {
3124
3176
  tool: undefined,
3125
- availableTools: catalog.tools.map(entry => entry.name),
3177
+ availableTools: catalog.tools.map((entry) => entry.name),
3126
3178
  connectionErrors: catalog.connectionErrors,
3127
3179
  };
3128
3180
  }
@@ -3156,8 +3208,9 @@ export class SessionEngine {
3156
3208
  if (native !== undefined) {
3157
3209
  return native;
3158
3210
  }
3159
- let tool = this.project.agent.tools.find(t => t.name === toolName);
3160
- if (tool === undefined && this.project.agent.connections.some(c => c.advertiseTools === true)) {
3211
+ let tool = this.project.agent.tools.find((t) => t.name === toolName);
3212
+ if (tool === undefined &&
3213
+ this.project.agent.connections.some((c) => c.advertiseTools === true)) {
3161
3214
  // Advertised passthroughs are ordinary server tools in the session's
3162
3215
  // namespace; resolve the live listing so direct calls address them by
3163
3216
  // the same model-facing name a turn would. A listing failure fails
@@ -3167,10 +3220,10 @@ export class SessionEngine {
3167
3220
  session,
3168
3221
  hostMcp: this.advertiseMcp(),
3169
3222
  });
3170
- tool = advertised.find(t => t.name === toolName);
3223
+ tool = advertised.find((t) => t.name === toolName);
3171
3224
  }
3172
3225
  if (tool === undefined) {
3173
- throw new UnknownToolError(toolName, this.project.agent.tools.filter(t => t.execution === "server").map(t => t.name));
3226
+ throw new UnknownToolError(toolName, this.project.agent.tools.filter((t) => t.execution === "server").map((t) => t.name));
3174
3227
  }
3175
3228
  const execute = tool.definition.execute;
3176
3229
  if (tool.execution !== "server" || typeof execute !== "function") {
@@ -3310,27 +3363,34 @@ export class SessionEngine {
3310
3363
  isError = false;
3311
3364
  }
3312
3365
  else {
3313
- const run = () => execute(validation.value, {
3314
- toolCallId: callId,
3315
- session,
3316
- workspaceDir,
3317
- stateRoot: this.stateRoot,
3318
- host: this.hostForSession(record?.sessionId),
3319
- // Scratch calls have no real session; their facade stays unbound.
3320
- artifacts: record === undefined
3321
- ? this.artifactsApi()
3322
- : this.artifactsApi({
3323
- sessionId: record.sessionId,
3324
- turnId: callId,
3366
+ const run = () => this.runExecutedTool({
3367
+ tool,
3368
+ input: validation.value,
3369
+ callId,
3370
+ signal: record === undefined ? undefined : this.turnAborts.get(record.sessionId)?.signal,
3371
+ emit,
3372
+ execute: () => execute(validation.value, {
3373
+ toolCallId: callId,
3374
+ session,
3375
+ workspaceDir,
3376
+ stateRoot: this.stateRoot,
3377
+ host: this.hostForSession(record?.sessionId),
3378
+ // Scratch calls have no real session; their facade stays unbound.
3379
+ artifacts: record === undefined
3380
+ ? this.artifactsApi()
3381
+ : this.artifactsApi({
3382
+ sessionId: record.sessionId,
3383
+ turnId: callId,
3384
+ }),
3385
+ send: (channelId, message, sendOptions = {}) => this.send(channelId, message, {
3386
+ ...sendOptions,
3387
+ auth: sendOptions.auth !== undefined ? sendOptions.auth : session.auth,
3325
3388
  }),
3326
- send: (channelId, message, sendOptions = {}) => this.send(channelId, message, {
3327
- ...sendOptions,
3328
- auth: sendOptions.auth !== undefined ? sendOptions.auth : session.auth,
3389
+ getSession: (channelId, sessionId) => this.getChannelSession(channelId, sessionId),
3390
+ emit,
3391
+ now: sessionClock(record?.asOf),
3392
+ ...(record?.asOf === undefined ? {} : { asOf: record.asOf }),
3329
3393
  }),
3330
- getSession: (channelId, sessionId) => this.getChannelSession(channelId, sessionId),
3331
- emit,
3332
- now: sessionClock(record?.asOf),
3333
- ...(record?.asOf === undefined ? {} : { asOf: record.asOf }),
3334
3394
  });
3335
3395
  const executeBody = record !== undefined && emit !== undefined
3336
3396
  ? () => mcpAuthAls.run({
@@ -3480,7 +3540,7 @@ export class SessionEngine {
3480
3540
  async bridgedToolInfo(connectionName, toolName) {
3481
3541
  try {
3482
3542
  const listed = await this.host.mcp.listTools(connectionName);
3483
- return listed.find(tool => tool.name === toolName);
3543
+ return listed.find((tool) => tool.name === toolName);
3484
3544
  }
3485
3545
  catch {
3486
3546
  return undefined;
@@ -3499,10 +3559,11 @@ export class SessionEngine {
3499
3559
  // Single funnel for both append paths (appendEvent + the held-log emit),
3500
3560
  // so the storage sink sees every durable event exactly once.
3501
3561
  this.storage?.event(event);
3562
+ this.livePublisher?.event(event);
3502
3563
  const chain = this.dispatchChains.get(sessionId) ?? Promise.resolve();
3503
3564
  const next = chain
3504
3565
  .then(() => this.dispatchEvent(sessionId, event, context))
3505
- .catch(error => {
3566
+ .catch((error) => {
3506
3567
  this.logger(`[bdk] event dispatch failed for ${sessionId}: ${describeError(error)}`);
3507
3568
  })
3508
3569
  .then(() => {
@@ -3559,10 +3620,10 @@ export class SessionEngine {
3559
3620
  // context; merge turn-start → live so a last-event before/after cannot
3560
3621
  // drop earlier handler writes.
3561
3622
  if (context === undefined) {
3562
- await this.updateRecord(sessionId, current => ({ ...current }));
3623
+ await this.updateRecord(sessionId, (current) => ({ ...current }));
3563
3624
  }
3564
3625
  else if (isTurnBoundaryEvent(event.type)) {
3565
- await this.updateRecord(sessionId, current => ({
3626
+ await this.updateRecord(sessionId, (current) => ({
3566
3627
  ...current,
3567
3628
  channelState: mergeChannelStateMutation({
3568
3629
  current: current.channelState,
@@ -3689,7 +3750,7 @@ export class SessionEngine {
3689
3750
  let matches;
3690
3751
  if (options?.includeAll !== true) {
3691
3752
  const owned = await this.ownedSessionIds(caller);
3692
- matches = record => record.sessionId !== undefined && owned.has(record.sessionId);
3753
+ matches = (record) => record.sessionId !== undefined && owned.has(record.sessionId);
3693
3754
  }
3694
3755
  return this.artifactsStore.page({
3695
3756
  kind: options?.filter?.kind,
@@ -3723,7 +3784,9 @@ export class SessionEngine {
3723
3784
  }
3724
3785
  async ownedSessionIds(caller) {
3725
3786
  const sessions = await this.sessions.list();
3726
- return new Set(sessions.filter(record => samePrincipal(record.auth, caller)).map(record => record.sessionId));
3787
+ return new Set(sessions
3788
+ .filter((record) => samePrincipal(record.auth, caller))
3789
+ .map((record) => record.sessionId));
3727
3790
  }
3728
3791
  /**
3729
3792
  * Same as {@link listSessions}, plus which store answered
@@ -3830,8 +3893,8 @@ export class SessionEngine {
3830
3893
  }
3831
3894
  summarizeSessionRecords(records, caller, includeAll) {
3832
3895
  return records
3833
- .filter(record => includeAll || samePrincipal(record.auth, caller))
3834
- .map(record => {
3896
+ .filter((record) => includeAll || samePrincipal(record.auth, caller))
3897
+ .map((record) => {
3835
3898
  const links = sessionExternalLinks(record);
3836
3899
  return {
3837
3900
  sessionId: record.sessionId,
@@ -3876,7 +3939,7 @@ export class SessionEngine {
3876
3939
  if (existing === undefined) {
3877
3940
  throw new Error(`Unknown session: ${sessionId}`);
3878
3941
  }
3879
- const record = await this.updateRecord(sessionId, current => ({
3942
+ const record = await this.updateRecord(sessionId, (current) => ({
3880
3943
  ...current,
3881
3944
  turnCount: current.turnCount + 1,
3882
3945
  }));
@@ -3928,7 +3991,7 @@ export class SessionEngine {
3928
3991
  data: { ...completed.data, cost },
3929
3992
  });
3930
3993
  })
3931
- .catch(error => {
3994
+ .catch((error) => {
3932
3995
  this.logger(`[bdk] turn cost stamp failed for ${sessionId}: ${describeError(error)}`);
3933
3996
  });
3934
3997
  }
@@ -4022,7 +4085,7 @@ export class SessionEngine {
4022
4085
  return pending;
4023
4086
  }
4024
4087
  const work = this.runCloudTurnCostBackfill(sessionId)
4025
- .catch(error => {
4088
+ .catch((error) => {
4026
4089
  this.logger(`[bdk] cloud cost backfill failed for ${sessionId}: ${describeError(error)}`);
4027
4090
  })
4028
4091
  .finally(() => {
@@ -4034,8 +4097,9 @@ export class SessionEngine {
4034
4097
  async runCloudTurnCostBackfill(sessionId) {
4035
4098
  const log = await this.logs.get(sessionId);
4036
4099
  const events = await log.snapshot(0);
4037
- if (!events.some(event => isUnpricedCompletedTurn(event))) {
4038
- if (!this.isTurnRunning(sessionId) && events.some(event => event.type === "turn.completed")) {
4100
+ if (!events.some((event) => isUnpricedCompletedTurn(event))) {
4101
+ if (!this.isTurnRunning(sessionId) &&
4102
+ events.some((event) => event.type === "turn.completed")) {
4039
4103
  this.cloudCostBackfillDone.add(sessionId);
4040
4104
  }
4041
4105
  return;
@@ -4063,13 +4127,13 @@ export class SessionEngine {
4063
4127
  }
4064
4128
  log.replace(i, next);
4065
4129
  }
4066
- if (!(await log.snapshot(0)).some(event => isUnpricedCompletedTurn(event))) {
4130
+ if (!(await log.snapshot(0)).some((event) => isUnpricedCompletedTurn(event))) {
4067
4131
  this.cloudCostBackfillDone.add(sessionId);
4068
4132
  }
4069
4133
  }
4070
4134
  async setContinuationToken(sessionId, token) {
4071
4135
  const previous = await this.sessions.get(sessionId);
4072
- await this.updateRecord(sessionId, current => ({
4136
+ await this.updateRecord(sessionId, (current) => ({
4073
4137
  ...current,
4074
4138
  continuationKey: token,
4075
4139
  }));
@@ -4200,7 +4264,7 @@ export class SessionEngine {
4200
4264
  // the lazy continuation-lookup path.
4201
4265
  const cutoff = Date.now() - policy.maxAgeMs;
4202
4266
  const candidates = loaded
4203
- .map(record => ({
4267
+ .map((record) => ({
4204
4268
  record,
4205
4269
  // Numeric timestamp for both the age filter and the sort; a
4206
4270
  // non-string updatedAt (e.g. a raw DB Date from an untyped sink)
@@ -4387,6 +4451,7 @@ export class SessionEngine {
4387
4451
  // After the drain, so a successor need not wait out the heartbeat TTL.
4388
4452
  await this.turnLeases.releaseAll().catch(() => { });
4389
4453
  await this.logs.flushAll();
4454
+ this.livePublisher?.close();
4390
4455
  await this.storage?.close();
4391
4456
  await this.mcpHost.close();
4392
4457
  await this.runner.dispose?.();
@@ -4424,7 +4489,7 @@ function eventsNdjson(events) {
4424
4489
  if (events.length === 0) {
4425
4490
  return undefined;
4426
4491
  }
4427
- return `${events.map(event => JSON.stringify(event)).join("\n")}\n`;
4492
+ return `${events.map((event) => JSON.stringify(event)).join("\n")}\n`;
4428
4493
  }
4429
4494
  /**
4430
4495
  * Restore-time turn-id fence: the durable record's `turnCount` may lag the
@@ -4460,7 +4525,7 @@ function subagentPrompt(subagent) {
4460
4525
  * executor that turn will run on.
4461
4526
  */
4462
4527
  function buildRunnerSubagents(agent) {
4463
- return agent.subagents.map(subagent => ({
4528
+ return agent.subagents.map((subagent) => ({
4464
4529
  name: subagent.name,
4465
4530
  description: subagent.description ?? subagent.name,
4466
4531
  prompt: subagentPrompt(subagent),
@@ -4480,7 +4545,7 @@ async function defaultGetCloudUsage(sdkAgentId) {
4480
4545
  return {
4481
4546
  usage: mapSdkTokenUsage(billed.usage),
4482
4547
  cost: billed.cost,
4483
- runs: billed.runs.map(run => ({
4548
+ runs: billed.runs.map((run) => ({
4484
4549
  runId: run.runId,
4485
4550
  usage: mapSdkTokenUsage(run.usage),
4486
4551
  cost: run.cost,
@@ -4520,7 +4585,7 @@ function approvalResolverLabel(auth) {
4520
4585
  }
4521
4586
  /** Let the HTTP NDJSON writer flush before the next SDK update. */
4522
4587
  function yieldEventLoop() {
4523
- return new Promise(resolve => {
4588
+ return new Promise((resolve) => {
4524
4589
  setImmediate(resolve);
4525
4590
  });
4526
4591
  }