@cursor/bdk 0.2.1 → 0.2.3

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 (336) hide show
  1. package/AGENTS.md +1 -1
  2. package/README.md +1 -6
  3. package/dist/artifacts.d.ts +5 -2
  4. package/dist/artifacts.d.ts.map +1 -1
  5. package/dist/artifacts.js +5 -2
  6. package/dist/bin/agent-serve.js +23 -7
  7. package/dist/channels/github/auth.d.ts.map +1 -1
  8. package/dist/channels/github/auth.js +36 -5
  9. package/dist/channels/slack/manifest.d.ts.map +1 -1
  10. package/dist/channels/slack/manifest.js +3 -2
  11. package/dist/channels/slack/types.d.ts +6 -1
  12. package/dist/channels/slack/types.d.ts.map +1 -1
  13. package/dist/connections.d.ts +1 -1
  14. package/dist/connections.js +1 -1
  15. package/dist/docs/404.html +2 -2
  16. package/dist/docs/assets/{app.JVQvbRO-.js → app.BOIHhrKi.js} +4 -4
  17. package/dist/docs/assets/chunks/@localSearchIndexroot.D5L-b34G.js +1 -0
  18. package/dist/docs/assets/chunks/{VPLocalSearchBox.BkhY63uW.js → VPLocalSearchBox.D49zVZqM.js} +1 -1
  19. package/dist/docs/assets/chunks/{arc.Cc1unYd3.js → arc.hmjb-sc4.js} +1 -1
  20. package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.CAY_TPVz.js → architectureDiagram-Q4EWVU46.CxEI1KqM.js} +1 -1
  21. package/dist/docs/assets/chunks/{baseUniq.my2VD3Xm.js → baseUniq.DHHvBWoV.js} +1 -1
  22. package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.CQXAOmqd.js → blockDiagram-DXYQGD6D.DnXW-3bu.js} +1 -1
  23. package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.D0AsQFSX.js → c4Diagram-AHTNJAMY.e-47O2jM.js} +1 -1
  24. package/dist/docs/assets/chunks/channel.BbOGaJQP.js +1 -0
  25. package/dist/docs/assets/chunks/{chunk-4BX2VUAB.DZjhgNls.js → chunk-4BX2VUAB.3ry4pYXB.js} +1 -1
  26. package/dist/docs/assets/chunks/{chunk-4TB4RGXK.qdcp_qbo.js → chunk-4TB4RGXK.DGIZFRx6.js} +1 -1
  27. package/dist/docs/assets/chunks/{chunk-55IACEB6.BHXoZhJ-.js → chunk-55IACEB6.DKBnqg9U.js} +1 -1
  28. package/dist/docs/assets/chunks/{chunk-EDXVE4YY.Cds_Vwj3.js → chunk-EDXVE4YY.BIU8Ue5k.js} +1 -1
  29. package/dist/docs/assets/chunks/{chunk-FMBD7UC4.CSl0HknT.js → chunk-FMBD7UC4.DP-TFhjI.js} +1 -1
  30. package/dist/docs/assets/chunks/{chunk-OYMX7WX6.DJMvAt5N.js → chunk-OYMX7WX6.Ux0OYj5v.js} +1 -1
  31. package/dist/docs/assets/chunks/{chunk-QZHKN3VN.BYQzBK9D.js → chunk-QZHKN3VN.BzHMwYox.js} +1 -1
  32. package/dist/docs/assets/chunks/{chunk-YZCP3GAM.BAvw7N4o.js → chunk-YZCP3GAM.D4OGAsSP.js} +1 -1
  33. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.Db58HCb1.js +1 -0
  34. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.Db58HCb1.js +1 -0
  35. package/dist/docs/assets/chunks/clone.Co4MBflG.js +1 -0
  36. package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.Buf3seya.js → cose-bilkent-S5V4N54A.Jq_7BUNx.js} +1 -1
  37. package/dist/docs/assets/chunks/{dagre-KV5264BT.DMGGa3uA.js → dagre-KV5264BT.Di-skR2x.js} +1 -1
  38. package/dist/docs/assets/chunks/{diagram-5BDNPKRD.DDjnwRmY.js → diagram-5BDNPKRD.DeREHIdH.js} +1 -1
  39. package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.RwyrIr8Q.js → diagram-G4DWMVQ6.C7Kcqxro.js} +1 -1
  40. package/dist/docs/assets/chunks/{diagram-MMDJMWI5.DRvQV16Z.js → diagram-MMDJMWI5.BK3eohyo.js} +1 -1
  41. package/dist/docs/assets/chunks/{diagram-TYMM5635.Dw8W9BTk.js → diagram-TYMM5635.C6TyymXT.js} +1 -1
  42. package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.DQT1Hnwf.js → erDiagram-SMLLAGMA.DYGG-gGx.js} +1 -1
  43. package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.6_Aky-ut.js → flowDiagram-DWJPFMVM.C9nBcSV4.js} +1 -1
  44. package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.DHIwqnqN.js → ganttDiagram-T4ZO3ILL.wAg_ymsp.js} +1 -1
  45. package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.CGd_eJbn.js → gitGraphDiagram-UUTBAWPF.B87j9Oeg.js} +1 -1
  46. package/dist/docs/assets/chunks/{graph.ChMEylkh.js → graph.CuFMj31w.js} +1 -1
  47. package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.Cd4gMyAz.js → infoDiagram-42DDH7IO.P_mLGumP.js} +1 -1
  48. package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.D1uw7MXq.js → ishikawaDiagram-UXIWVN3A.DyuL_MsT.js} +1 -1
  49. package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.AWLXtelc.js → journeyDiagram-VCZTEJTY.CtP09IoJ.js} +1 -1
  50. package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.CagPhAn5.js → kanban-definition-6JOO6SKY.BoeSYPZo.js} +1 -1
  51. package/dist/docs/assets/chunks/{layout.ClTBBkE_.js → layout.B0lMMtNo.js} +1 -1
  52. package/dist/docs/assets/chunks/{linear.SwS2rOLA.js → linear.HxRBiAFX.js} +1 -1
  53. package/dist/docs/assets/chunks/{min.By_x-Btb.js → min.BGlFFHwS.js} +1 -1
  54. package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.By_RAMaP.js → mindmap-definition-QFDTVHPH.JyLBD9M8.js} +1 -1
  55. package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.DfAl9sy4.js → pieDiagram-DEJITSTG.DnSmNZF8.js} +1 -1
  56. package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.CNuqFRBj.js → quadrantDiagram-34T5L4WZ.CUCnbfCa.js} +1 -1
  57. package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.DJ5CmTCl.js → requirementDiagram-MS252O5E.py0IVUn5.js} +1 -1
  58. package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.D-T_AKJj.js → sankeyDiagram-XADWPNL6.Bkc-HWYp.js} +1 -1
  59. package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.BRn9WcrR.js → sequenceDiagram-FGHM5R23.Dqn8Mlv2.js} +1 -1
  60. package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.F12urmm7.js → stateDiagram-FHFEXIEX.JikkoQUU.js} +1 -1
  61. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.CMsKhrW0.js +1 -0
  62. package/dist/docs/assets/chunks/{theme.zK3OJa_C.js → theme.b6HQ6zG_.js} +2 -2
  63. package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.B7GiQBeC.js → timeline-definition-GMOUNBTQ.BvpSXiBj.js} +1 -1
  64. package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.D0niwuY_.js → vennDiagram-DHZGUBPP.CU7MVnZx.js} +1 -1
  65. package/dist/docs/assets/chunks/{wardley-RL74JXVD.1zhHNRsx.js → wardley-RL74JXVD.BKwC4ctG.js} +1 -1
  66. package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.DKaqpT7K.js → wardleyDiagram-NUSXRM2D.BfaF6Uhe.js} +1 -1
  67. package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.e8BPicch.js → xychartDiagram-5P7HB3ND.Bg5dcpj4.js} +1 -1
  68. package/dist/docs/assets/{deployment.md.nGo1yIsa.js → deployment.md.BJ8i7Q6p.js} +5 -8
  69. package/dist/docs/assets/{deployment.md.nGo1yIsa.lean.js → deployment.md.BJ8i7Q6p.lean.js} +1 -1
  70. package/dist/docs/assets/{guides_github.md.C2_DSWlE.js → guides_github.md.Bq9kQU9B.js} +9 -3
  71. package/dist/docs/assets/{guides_github.md.C2_DSWlE.lean.js → guides_github.md.Bq9kQU9B.lean.js} +1 -1
  72. package/dist/docs/assets/{guides_slack.md.ZbHQETOT.js → guides_slack.md.diqqXTTm.js} +2 -2
  73. package/dist/docs/assets/{guides_slack.md.ZbHQETOT.lean.js → guides_slack.md.diqqXTTm.lean.js} +1 -1
  74. package/dist/docs/assets/{quickstart.md.wG4shE1f.js → quickstart.md.CHpHPBUN.js} +5 -3
  75. package/dist/docs/assets/{quickstart.md.wG4shE1f.lean.js → quickstart.md.CHpHPBUN.lean.js} +1 -1
  76. package/dist/docs/assets/{reference_artifacts.md.IFFC5Zln.js → reference_artifacts.md.CQfKq8F2.js} +1 -1
  77. package/dist/docs/assets/reference_cli.md.DgeLTO18.js +91 -0
  78. package/dist/docs/assets/reference_cli.md.DgeLTO18.lean.js +1 -0
  79. package/dist/docs/assets/{reference_connections.md._XpKiOaF.js → reference_connections.md.COq--gAm.js} +7 -3
  80. package/dist/docs/assets/{reference_connections.md._XpKiOaF.lean.js → reference_connections.md.COq--gAm.lean.js} +1 -1
  81. package/dist/docs/assets/{reference_evals.md.DqNyHMA6.js → reference_evals.md.CJm3uCUm.js} +4 -4
  82. package/dist/docs/assets/{reference_evals.md.DqNyHMA6.lean.js → reference_evals.md.CJm3uCUm.lean.js} +1 -1
  83. package/dist/docs/assets/{reference_hooks.md.Dg3dEugd.js → reference_hooks.md.DbthhtIR.js} +1 -1
  84. package/dist/docs/assets/{reference_sessions.md.BtpTjZmh.js → reference_sessions.md.DeRUItHD.js} +1 -1
  85. package/dist/docs/assets/troubleshooting.md.Cw5PKa3t.js +1 -0
  86. package/dist/docs/assets/{troubleshooting.md.BzZSu1Gz.lean.js → troubleshooting.md.Cw5PKa3t.lean.js} +1 -1
  87. package/dist/docs/building-with-agents.html +35 -35
  88. package/dist/docs/deployment.html +40 -43
  89. package/dist/docs/deployment.md +45 -15
  90. package/dist/docs/evals.html +35 -35
  91. package/dist/docs/guides/agent-to-agent.html +35 -35
  92. package/dist/docs/guides/bitbucket.html +35 -35
  93. package/dist/docs/guides/cloud-agents.html +35 -35
  94. package/dist/docs/guides/convert-automation.html +35 -35
  95. package/dist/docs/guides/github.html +43 -37
  96. package/dist/docs/guides/github.md +34 -0
  97. package/dist/docs/guides/gitlab.html +35 -35
  98. package/dist/docs/guides/grokbot-agents.html +35 -35
  99. package/dist/docs/guides/hooks.html +35 -35
  100. package/dist/docs/guides/improve.html +35 -35
  101. package/dist/docs/guides/jev.html +35 -35
  102. package/dist/docs/guides/mcp-oauth.html +35 -35
  103. package/dist/docs/guides/opentelemetry.html +35 -35
  104. package/dist/docs/guides/slack.html +37 -37
  105. package/dist/docs/guides/slack.md +5 -0
  106. package/dist/docs/guides/webhooks.html +35 -35
  107. package/dist/docs/hashmap.json +1 -1
  108. package/dist/docs/hillclimbing.html +35 -35
  109. package/dist/docs/index.html +35 -35
  110. package/dist/docs/llms-full.txt +205 -97
  111. package/dist/docs/quickstart.html +40 -38
  112. package/dist/docs/quickstart.md +7 -1
  113. package/dist/docs/reference/agent-config.html +35 -35
  114. package/dist/docs/reference/artifacts.html +37 -37
  115. package/dist/docs/reference/artifacts.md +1 -1
  116. package/dist/docs/reference/channels.html +35 -35
  117. package/dist/docs/reference/cli.html +55 -61
  118. package/dist/docs/reference/cli.md +65 -63
  119. package/dist/docs/reference/connections.html +42 -38
  120. package/dist/docs/reference/connections.md +28 -2
  121. package/dist/docs/reference/evals.html +39 -39
  122. package/dist/docs/reference/evals.md +6 -7
  123. package/dist/docs/reference/extensions.html +35 -35
  124. package/dist/docs/reference/hooks.html +37 -37
  125. package/dist/docs/reference/hooks.md +3 -2
  126. package/dist/docs/reference/http-api.html +35 -35
  127. package/dist/docs/reference/instructions.html +35 -35
  128. package/dist/docs/reference/playground.html +35 -35
  129. package/dist/docs/reference/project-layout.html +35 -35
  130. package/dist/docs/reference/prompt.html +35 -35
  131. package/dist/docs/reference/schedules.html +35 -35
  132. package/dist/docs/reference/sessions.html +36 -36
  133. package/dist/docs/reference/sessions.md +4 -3
  134. package/dist/docs/reference/skills.html +35 -35
  135. package/dist/docs/reference/subagents.html +35 -35
  136. package/dist/docs/reference/tools.html +35 -35
  137. package/dist/docs/templates/agentic-owners.html +35 -35
  138. package/dist/docs/templates/security-reviewer.html +35 -35
  139. package/dist/docs/templates/thermo-quality-review.html +35 -35
  140. package/dist/docs/templates/thermo-review.html +35 -35
  141. package/dist/docs/templates/triage.html +35 -35
  142. package/dist/docs/troubleshooting.html +36 -36
  143. package/dist/docs/troubleshooting.md +7 -3
  144. package/dist/extensions/cursor-cloud-agents/extension.d.ts +16 -4
  145. package/dist/extensions/cursor-cloud-agents/extension.d.ts.map +1 -1
  146. package/dist/extensions/cursor-cloud-agents/extension.js +7 -3
  147. package/dist/extensions/cursor-cloud-agents/lib/channels.d.ts +3 -0
  148. package/dist/extensions/cursor-cloud-agents/lib/channels.d.ts.map +1 -0
  149. package/dist/extensions/cursor-cloud-agents/lib/channels.js +7 -0
  150. package/dist/extensions/cursor-cloud-agents/lib/repos.d.ts +4 -2
  151. package/dist/extensions/cursor-cloud-agents/lib/repos.d.ts.map +1 -1
  152. package/dist/extensions/cursor-cloud-agents/lib/repos.js +21 -12
  153. package/dist/extensions/cursor-cloud-agents/tools/cancel.d.ts.map +1 -1
  154. package/dist/extensions/cursor-cloud-agents/tools/cancel.js +2 -0
  155. package/dist/extensions/cursor-cloud-agents/tools/launch.d.ts.map +1 -1
  156. package/dist/extensions/cursor-cloud-agents/tools/launch.js +3 -1
  157. package/dist/extensions/cursor-cloud-agents/tools/reply.d.ts.map +1 -1
  158. package/dist/extensions/cursor-cloud-agents/tools/reply.js +2 -0
  159. package/dist/extensions/cursor-grokbot-agents/extension.d.ts +77 -0
  160. package/dist/extensions/cursor-grokbot-agents/extension.d.ts.map +1 -0
  161. package/dist/extensions/cursor-grokbot-agents/extension.js +63 -0
  162. package/dist/extensions/cursor-grokbot-agents/lib/agents.d.ts +11 -0
  163. package/dist/extensions/cursor-grokbot-agents/lib/agents.d.ts.map +1 -0
  164. package/dist/extensions/cursor-grokbot-agents/lib/agents.js +31 -0
  165. package/dist/extensions/cursor-grokbot-agents/lib/backend.d.ts +56 -0
  166. package/dist/extensions/cursor-grokbot-agents/lib/backend.d.ts.map +1 -0
  167. package/dist/extensions/cursor-grokbot-agents/lib/backend.js +158 -0
  168. package/dist/extensions/cursor-grokbot-agents/lib/contacts.d.ts +28 -0
  169. package/dist/extensions/cursor-grokbot-agents/lib/contacts.d.ts.map +1 -0
  170. package/dist/extensions/cursor-grokbot-agents/lib/contacts.js +59 -0
  171. package/dist/extensions/cursor-grokbot-agents/lib/conversation.d.ts +53 -0
  172. package/dist/extensions/cursor-grokbot-agents/lib/conversation.d.ts.map +1 -0
  173. package/dist/extensions/cursor-grokbot-agents/lib/conversation.js +206 -0
  174. package/dist/extensions/cursor-grokbot-agents/lib/inputs.d.ts +4 -0
  175. package/dist/extensions/cursor-grokbot-agents/lib/inputs.d.ts.map +1 -0
  176. package/dist/extensions/cursor-grokbot-agents/lib/inputs.js +15 -0
  177. package/dist/extensions/cursor-grokbot-agents/lib/lock.d.ts +12 -0
  178. package/dist/extensions/cursor-grokbot-agents/lib/lock.d.ts.map +1 -0
  179. package/dist/extensions/cursor-grokbot-agents/lib/lock.js +25 -0
  180. package/dist/extensions/cursor-grokbot-agents/skills/consult.md +40 -0
  181. package/dist/extensions/cursor-grokbot-agents/tools/ask.d.ts +4 -0
  182. package/dist/extensions/cursor-grokbot-agents/tools/ask.d.ts.map +1 -0
  183. package/dist/extensions/cursor-grokbot-agents/tools/ask.js +37 -0
  184. package/dist/extensions/cursor-grokbot-agents/tools/check.d.ts +4 -0
  185. package/dist/extensions/cursor-grokbot-agents/tools/check.d.ts.map +1 -0
  186. package/dist/extensions/cursor-grokbot-agents/tools/check.js +32 -0
  187. package/dist/extensions/cursor-grokbot-agents/tools/interrupt.d.ts +4 -0
  188. package/dist/extensions/cursor-grokbot-agents/tools/interrupt.d.ts.map +1 -0
  189. package/dist/extensions/cursor-grokbot-agents/tools/interrupt.js +24 -0
  190. package/dist/extensions/cursor-grokbot-agents/tools/list.d.ts +4 -0
  191. package/dist/extensions/cursor-grokbot-agents/tools/list.d.ts.map +1 -0
  192. package/dist/extensions/cursor-grokbot-agents/tools/list.js +34 -0
  193. package/dist/files-backends/cursor-hosted.js +4 -4
  194. package/dist/internal/artifacts-store.d.ts +12 -2
  195. package/dist/internal/artifacts-store.d.ts.map +1 -1
  196. package/dist/internal/artifacts-store.js +8 -4
  197. package/dist/internal/cli-ax.d.ts +1 -0
  198. package/dist/internal/cli-ax.d.ts.map +1 -1
  199. package/dist/internal/cli-ax.js +43 -10
  200. package/dist/internal/cli-deploy.d.ts +5 -1
  201. package/dist/internal/cli-deploy.d.ts.map +1 -1
  202. package/dist/internal/cli-deploy.js +22 -4
  203. package/dist/internal/cli-mcp-oauth.d.ts.map +1 -1
  204. package/dist/internal/cli-mcp-oauth.js +2 -1
  205. package/dist/internal/cli-skills.d.ts +1 -1
  206. package/dist/internal/cli-skills.d.ts.map +1 -1
  207. package/dist/internal/cli-skills.js +5 -5
  208. package/dist/internal/connection-env.d.ts +31 -0
  209. package/dist/internal/connection-env.d.ts.map +1 -0
  210. package/dist/internal/connection-env.js +84 -0
  211. package/dist/internal/cursor/backend-client.js +5 -0
  212. package/dist/internal/deploy-client.d.ts +30 -6
  213. package/dist/internal/deploy-client.d.ts.map +1 -1
  214. package/dist/internal/deploy-client.js +45 -9
  215. package/dist/internal/discovery/connections.d.ts.map +1 -1
  216. package/dist/internal/discovery/connections.js +11 -0
  217. package/dist/internal/event-mapper.d.ts +46 -4
  218. package/dist/internal/event-mapper.d.ts.map +1 -1
  219. package/dist/internal/event-mapper.js +316 -25
  220. package/dist/internal/hosted-delivery-protocol.d.ts +36 -11
  221. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
  222. package/dist/internal/hosted-delivery-protocol.js +31 -8
  223. package/dist/internal/hosted-delivery.d.ts +2 -2
  224. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  225. package/dist/internal/hosted-delivery.js +229 -49
  226. package/dist/internal/hosting.d.ts +2 -2
  227. package/dist/internal/hosting.d.ts.map +1 -1
  228. package/dist/internal/hosting.js +9 -3
  229. package/dist/internal/install-cursor-skills.d.ts +20 -24
  230. package/dist/internal/install-cursor-skills.d.ts.map +1 -1
  231. package/dist/internal/install-cursor-skills.js +50 -48
  232. package/dist/internal/legacy-command-guard.d.ts +2 -0
  233. package/dist/internal/legacy-command-guard.d.ts.map +1 -1
  234. package/dist/internal/legacy-command-guard.js +10 -1
  235. package/dist/internal/mcp-host.d.ts +6 -0
  236. package/dist/internal/mcp-host.d.ts.map +1 -1
  237. package/dist/internal/mcp-host.js +35 -16
  238. package/dist/internal/sdk-runner.d.ts +2 -0
  239. package/dist/internal/sdk-runner.d.ts.map +1 -1
  240. package/dist/internal/sdk-runner.js +10 -0
  241. package/dist/internal/server.d.ts.map +1 -1
  242. package/dist/internal/server.js +11 -1
  243. package/dist/internal/session-engine.d.ts +1 -1
  244. package/dist/internal/session-engine.d.ts.map +1 -1
  245. package/dist/internal/session-engine.js +33 -8
  246. package/dist/playground/assets/index-6BbTPnaT.css +1 -0
  247. package/dist/playground/assets/{index-FFdUqTt_.js → index-CI7FAmOP.js} +43 -43
  248. package/dist/playground/index.html +2 -2
  249. package/dist/types.d.ts +50 -4
  250. package/dist/types.d.ts.map +1 -1
  251. package/docs/deployment.md +45 -15
  252. package/docs/guides/github.md +34 -0
  253. package/docs/guides/slack.md +5 -0
  254. package/docs/quickstart.md +7 -1
  255. package/docs/reference/artifacts.md +1 -1
  256. package/docs/reference/cli.md +65 -63
  257. package/docs/reference/connections.md +28 -2
  258. package/docs/reference/evals.md +6 -7
  259. package/docs/reference/hooks.md +3 -2
  260. package/docs/reference/sessions.md +4 -3
  261. package/docs/troubleshooting.md +7 -3
  262. package/package.json +2 -4
  263. package/scripts/install-cursor-skills.mjs +1 -1
  264. package/skills/create-agent/SKILL.md +1 -1
  265. package/skills/debug/SKILL.md +1 -1
  266. package/skills/deploy/SKILL.md +1 -1
  267. package/skills/evals/SKILL.md +1 -1
  268. package/skills/framework-map/SKILL.md +1 -1
  269. package/skills/github/SKILL.md +1 -1
  270. package/skills/hillclimb/SKILL.md +1 -1
  271. package/skills/mcp-auth/SKILL.md +1 -1
  272. package/skills/otel/SKILL.md +1 -1
  273. package/skills/setup-slack/SKILL.md +1 -1
  274. package/src/artifacts.ts +5 -2
  275. package/src/bin/agent-serve.ts +27 -6
  276. package/src/channels/github/auth.ts +44 -5
  277. package/src/channels/slack/manifest.ts +2 -1
  278. package/src/channels/slack/types.ts +6 -1
  279. package/src/connections.ts +1 -1
  280. package/src/extensions/cursor-cloud-agents/extension.ts +23 -6
  281. package/src/extensions/cursor-cloud-agents/lib/channels.ts +11 -0
  282. package/src/extensions/cursor-cloud-agents/lib/repos.ts +19 -7
  283. package/src/extensions/cursor-cloud-agents/tools/cancel.ts +2 -0
  284. package/src/extensions/cursor-cloud-agents/tools/launch.ts +3 -1
  285. package/src/extensions/cursor-cloud-agents/tools/reply.ts +2 -0
  286. package/src/extensions/cursor-grokbot-agents/extension.ts +132 -0
  287. package/src/extensions/cursor-grokbot-agents/lib/agents.ts +42 -0
  288. package/src/extensions/cursor-grokbot-agents/lib/backend.ts +208 -0
  289. package/src/extensions/cursor-grokbot-agents/lib/contacts.ts +74 -0
  290. package/src/extensions/cursor-grokbot-agents/lib/conversation.ts +260 -0
  291. package/src/extensions/cursor-grokbot-agents/lib/inputs.ts +21 -0
  292. package/src/extensions/cursor-grokbot-agents/lib/lock.ts +26 -0
  293. package/src/extensions/cursor-grokbot-agents/skills/consult.md +40 -0
  294. package/src/extensions/cursor-grokbot-agents/tools/ask.ts +32 -0
  295. package/src/extensions/cursor-grokbot-agents/tools/check.ts +25 -0
  296. package/src/extensions/cursor-grokbot-agents/tools/interrupt.ts +17 -0
  297. package/src/extensions/cursor-grokbot-agents/tools/list.ts +26 -0
  298. package/src/files-backends/cursor-hosted.ts +4 -4
  299. package/src/internal/artifacts-store.ts +14 -3
  300. package/src/internal/cli-ax.ts +52 -7
  301. package/src/internal/cli-deploy.ts +39 -6
  302. package/src/internal/cli-mcp-oauth.ts +2 -1
  303. package/src/internal/cli-skills.ts +4 -5
  304. package/src/internal/connection-env.ts +106 -0
  305. package/src/internal/cursor/backend-client.ts +6 -0
  306. package/src/internal/deploy-client.ts +79 -9
  307. package/src/internal/discovery/connections.ts +11 -0
  308. package/src/internal/event-mapper.ts +367 -36
  309. package/src/internal/hosted-delivery-protocol.ts +57 -20
  310. package/src/internal/hosted-delivery.ts +487 -229
  311. package/src/internal/hosting.ts +10 -3
  312. package/src/internal/install-cursor-skills.ts +56 -53
  313. package/src/internal/legacy-command-guard.ts +13 -1
  314. package/src/internal/mcp-host.ts +45 -17
  315. package/src/internal/sdk-runner.ts +11 -0
  316. package/src/internal/server.ts +13 -1
  317. package/src/internal/session-engine.ts +33 -13
  318. package/src/types.ts +56 -5
  319. package/templates/agents-md/bot/lib/collect.ts +1 -4
  320. package/templates/code-wiki/bot/channels/github.ts +2 -2
  321. package/templates/demo/bot/channels/github.ts +5 -1
  322. package/templates/pr-autofixer/bot/lib/start-drive.ts +4 -4
  323. package/templates/triage/bot/lib/types.ts +6 -6
  324. package/dist/docs/assets/chunks/@localSearchIndexroot.Caw9W1pM.js +0 -1
  325. package/dist/docs/assets/chunks/channel.Sapo9HJZ.js +0 -1
  326. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.NPiy3Hz7.js +0 -1
  327. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.NPiy3Hz7.js +0 -1
  328. package/dist/docs/assets/chunks/clone.zl2qolPE.js +0 -1
  329. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2._auCa3fR.js +0 -1
  330. package/dist/docs/assets/reference_cli.md.BK2QUH67.js +0 -97
  331. package/dist/docs/assets/reference_cli.md.BK2QUH67.lean.js +0 -1
  332. package/dist/docs/assets/troubleshooting.md.BzZSu1Gz.js +0 -1
  333. package/dist/playground/assets/index-BMV_IcEE.css +0 -1
  334. /package/dist/docs/assets/{reference_artifacts.md.IFFC5Zln.lean.js → reference_artifacts.md.CQfKq8F2.lean.js} +0 -0
  335. /package/dist/docs/assets/{reference_hooks.md.Dg3dEugd.lean.js → reference_hooks.md.DbthhtIR.lean.js} +0 -0
  336. /package/dist/docs/assets/{reference_sessions.md.BtpTjZmh.lean.js → reference_sessions.md.DeRUItHD.lean.js} +0 -0
@@ -36,7 +36,8 @@ import {
36
36
  HOSTED_GUEST_RETRY_TERMINAL,
37
37
  HOSTED_GUEST_RETRY_TRANSIENT,
38
38
  HOSTED_MAX_CONSUMED_DELIVERY_IDS,
39
- type HostedAdmission,
39
+ type HostedAdmissionInput,
40
+ type HostedAdmissionStart,
40
41
  type HostedGuestRetryDisposition,
41
42
  type HostedReminderFireDescriptorPayload,
42
43
  hostedFailureClassification,
@@ -74,7 +75,7 @@ import { type EngineSendOptions, HostedEnqueueNotActiveError } from "./session-e
74
75
  import type { SessionRunExecutionWrite } from "./session-run-log.js";
75
76
 
76
77
  type DispatchInput = {
77
- delivery: HostedAdmission;
78
+ delivery: HostedAdmissionInput;
78
79
  definition: object;
79
80
  args: ChannelHandlerArgs;
80
81
  };
@@ -94,6 +95,13 @@ type AdmissionDispatch = {
94
95
  type ExecutionReply = {
95
96
  status: number;
96
97
  body: Record<string, unknown>;
98
+ serverTiming?: string;
99
+ };
100
+
101
+ type AdmissionOperation = {
102
+ execution: Promise<ExecutionReply>;
103
+ settledReply?: ExecutionReply;
104
+ expiresAt: number;
97
105
  };
98
106
 
99
107
  type HostedEnqueueOutcome = {
@@ -109,6 +117,29 @@ type ActiveOwnerContext = {
109
117
  enqueueResults: Map<string, Promise<HostedEnqueueOutcome>>;
110
118
  };
111
119
 
120
+ async function responseToReply(response: Response): Promise<ExecutionReply> {
121
+ const value = (await response.json()) as unknown;
122
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
123
+ throw new Error("Hosted delivery produced a non-object JSON response.");
124
+ }
125
+ return {
126
+ status: response.status,
127
+ body: value as Record<string, unknown>,
128
+ serverTiming: response.headers.get("server-timing") ?? undefined,
129
+ };
130
+ }
131
+
132
+ function responseFromReply(reply: ExecutionReply): Response {
133
+ return Response.json(reply.body, {
134
+ status: reply.status,
135
+ headers: reply.serverTiming === undefined ? undefined : { "server-timing": reply.serverTiming },
136
+ });
137
+ }
138
+
139
+ function isTransientRetryReply(reply: ExecutionReply): boolean {
140
+ return reply.body.retry === HOSTED_GUEST_RETRY_TRANSIENT;
141
+ }
142
+
112
143
  /**
113
144
  * A second `send()` in one delivery is a deterministic authored bug — the
114
145
  * wire protocol carries exactly one pending send per delivery — so it must
@@ -137,6 +168,21 @@ function boundedMessage(text: string): string {
137
168
  : text;
138
169
  }
139
170
 
171
+ /**
172
+ * A channel's non-OK dispatch response body is the only record of why the
173
+ * delivery was refused (e.g. an authored 400 with a validation message).
174
+ * Carry it, bounded, into the terminal channel_dispatch_failed so the
175
+ * control plane's failure log is diagnosable.
176
+ */
177
+ async function channelDispatchDetail(response: Response): Promise<string | undefined> {
178
+ try {
179
+ const text = (await response.text()).trim();
180
+ return text === "" ? undefined : boundedMessage(text);
181
+ } catch {
182
+ return undefined;
183
+ }
184
+ }
185
+
140
186
  function terminalHostedError(status: number, error: string, message?: string): Response {
141
187
  return hostedGuestErrorResponse({
142
188
  status,
@@ -250,7 +296,7 @@ async function dispatchHostedReminderAdmission(
250
296
  reason?: string;
251
297
  }>;
252
298
  },
253
- delivery: HostedAdmission,
299
+ delivery: HostedAdmissionInput,
254
300
  ): Promise<Response> {
255
301
  const descriptor = parseHostedReminderFireDescriptorPayload(delivery.payload);
256
302
  if (descriptor !== undefined) {
@@ -364,6 +410,7 @@ async function runAdmission(
364
410
  response: terminalHostedError(
365
411
  dispatched.status >= 400 ? dispatched.status : 502,
366
412
  "channel_dispatch_failed",
413
+ await channelDispatchDetail(dispatched),
367
414
  ),
368
415
  };
369
416
  }
@@ -564,10 +611,14 @@ export function registerHostedDeliveryRoute(input: {
564
611
  deliveryId: string;
565
612
  sessionPublicId?: string;
566
613
  execution?: Promise<ExecutionReply>;
614
+ settledReply?: ExecutionReply;
567
615
  }
568
616
  >();
617
+ const admissions = new Map<string, AdmissionOperation>();
569
618
  const activeOwners = new Map<string, ActiveOwnerContext>();
570
619
  const pendingTtlMs = 10 * 60_000;
620
+ /** Keep an in-flight owner turn addressable for status polls. */
621
+ const ownerTurnPendingTtlMs = 12 * 60 * 60_000;
571
622
  const waitForNetwork = input.waitForGuestNetwork ?? (() => waitForGuestNetworkReady());
572
623
  const consumeBoundSecrets = input.consumeBoundSecrets ?? (() => consumeHostedBoundSecrets());
573
624
  /**
@@ -613,9 +664,83 @@ export function registerHostedDeliveryRoute(input: {
613
664
  pending.delete(token);
614
665
  }
615
666
  }
667
+ for (const [deliveryId, operation] of admissions) {
668
+ if (operation.expiresAt <= now) {
669
+ admissions.delete(deliveryId);
670
+ }
671
+ }
616
672
  };
673
+ const runAdmissionOperation = async (
674
+ delivery: HostedAdmissionStart,
675
+ definition: object | undefined,
676
+ ): Promise<ExecutionReply> =>
677
+ afterHostedWork(input.flushOtel, async () => {
678
+ const startedAt = performance.now();
679
+ let guestNetwork: GuestNetworkWaitStats | undefined;
680
+ const finish = (response: Response) =>
681
+ withServerTiming(response, performance.now() - startedAt, guestNetwork);
682
+ try {
683
+ const network = await finishNetworkWait("admission");
684
+ guestNetwork = network.timing;
685
+ if (network.response !== undefined) {
686
+ return await responseToReply(finish(network.response));
687
+ }
688
+ if (isHostedReminderAdmission(delivery)) {
689
+ return await responseToReply(
690
+ finish(await dispatchHostedReminderAdmission(input, delivery)),
691
+ );
692
+ }
693
+ if (definition === undefined) {
694
+ return await responseToReply(
695
+ finish(
696
+ terminalHostedError(
697
+ 404,
698
+ "channel_not_found",
699
+ `No channel named "${delivery.channelId}" is mounted.`,
700
+ ),
701
+ ),
702
+ );
703
+ }
704
+ const admitted = await dispatchHostedAdmission({
705
+ delivery,
706
+ definition,
707
+ args: input.buildHandlerArgs(delivery.channelId),
708
+ });
709
+ if (admitted.pendingSend === undefined) {
710
+ return await responseToReply(finish(admitted.response));
711
+ }
712
+ pruneExpired();
713
+ const admissionToken = randomBytes(24).toString("hex");
714
+ pending.set(admissionToken, {
715
+ send: admitted.pendingSend,
716
+ channelKind: delivery.channelKind,
717
+ expiresAt: Date.now() + pendingTtlMs,
718
+ deliveryId: delivery.deliveryId,
719
+ });
720
+ return await responseToReply(
721
+ finish(
722
+ Response.json({
723
+ ok: true,
724
+ v: HOSTED_DELIVERY_PROTOCOL_VERSION,
725
+ outcome: "send",
726
+ admissionToken,
727
+ }),
728
+ ),
729
+ );
730
+ } catch (error) {
731
+ return await responseToReply(
732
+ finish(
733
+ terminalHostedError(
734
+ 503,
735
+ "internal_error",
736
+ boundedMessage(error instanceof Error ? error.message : String(error)),
737
+ ),
738
+ ),
739
+ );
740
+ }
741
+ });
617
742
 
618
- // Hosted callers reach this only through AnyRun's signed pod-port URL.
743
+ // Hosted callers reach this only through Anyrun's signed pod-port URL.
619
744
  // The marker is a second, route-specific fence distinct from channel auth.
620
745
  const auth: AuthPolicy = request => {
621
746
  if (request.headers.get(HOSTED_DELIVERY_HEADER) !== "1") {
@@ -634,9 +759,8 @@ export function registerHostedDeliveryRoute(input: {
634
759
  handler: async request =>
635
760
  afterHostedWork(input.flushOtel, async () => {
636
761
  const startedAt = performance.now();
637
- let guestNetwork: GuestNetworkWaitStats | undefined;
638
762
  const finish = (response: Response) =>
639
- withServerTiming(response, performance.now() - startedAt, guestNetwork);
763
+ withServerTiming(response, performance.now() - startedAt);
640
764
  const unconsumed = finishBoundSecrets();
641
765
  if (unconsumed !== undefined) {
642
766
  return finish(unconsumed);
@@ -661,20 +785,53 @@ export function registerHostedDeliveryRoute(input: {
661
785
  ),
662
786
  );
663
787
  }
788
+ pruneExpired();
789
+ const existing = admissions.get(delivery.deliveryId);
790
+ if (delivery.mode === "status") {
791
+ if (existing === undefined) {
792
+ return finish(
793
+ transientHostedError(
794
+ 409,
795
+ "hosted_admission_unavailable",
796
+ "No hosted admission is in flight for this delivery.",
797
+ ),
798
+ );
799
+ }
800
+ return existing.settledReply === undefined
801
+ ? finish(
802
+ Response.json({
803
+ ok: true,
804
+ v: HOSTED_DELIVERY_PROTOCOL_VERSION,
805
+ outcome: "running",
806
+ }),
807
+ )
808
+ : responseFromReply(existing.settledReply);
809
+ }
810
+ if (existing !== undefined) {
811
+ if (existing.settledReply !== undefined && isTransientRetryReply(existing.settledReply)) {
812
+ admissions.delete(delivery.deliveryId);
813
+ } else {
814
+ return existing.settledReply === undefined
815
+ ? finish(
816
+ Response.json({
817
+ ok: true,
818
+ v: HOSTED_DELIVERY_PROTOCOL_VERSION,
819
+ outcome: "started",
820
+ }),
821
+ )
822
+ : responseFromReply(existing.settledReply);
823
+ }
824
+ }
825
+
664
826
  console.info(
665
827
  `[agent-sdk] hosted admission received deliveryId=${delivery.deliveryId} channelId=${delivery.channelId} channelKind=${delivery.channelKind} eventType=${delivery.eventType} sessionMode=${delivery.sessionMode} managedAutomation=${delivery.managedAutomation === undefined ? "<absent>" : `automationUuid=${delivery.managedAutomation.automationUuid} mcpServerNames=${String(delivery.managedAutomation.mcpServerNames.length)} slackChannels=${delivery.managedAutomation.slackChannels === undefined ? "<absent>" : JSON.stringify(delivery.managedAutomation.slackChannels)}`}`,
666
828
  );
667
829
  recordHostedManagedAutomation(delivery);
668
- if (isHostedReminderAdmission(delivery)) {
669
- const network = await finishNetworkWait("admission");
670
- guestNetwork = network.timing;
671
- if (network.response !== undefined) {
672
- return finish(network.response);
673
- }
674
- return finish(await dispatchHostedReminderAdmission(input, delivery));
675
- }
676
- const channel = input.channels.find(candidate => candidate.id === delivery.channelId);
677
- if (channel === undefined) {
830
+ const reminder = isHostedReminderAdmission(delivery);
831
+ const definition = reminder
832
+ ? undefined
833
+ : input.channels.find(candidate => candidate.id === delivery.channelId)?.definition;
834
+ if (!reminder && definition === undefined) {
678
835
  return finish(
679
836
  terminalHostedError(
680
837
  404,
@@ -683,33 +840,29 @@ export function registerHostedDeliveryRoute(input: {
683
840
  ),
684
841
  );
685
842
  }
686
- const network = await finishNetworkWait("admission");
687
- guestNetwork = network.timing;
688
- if (network.response !== undefined) {
689
- return finish(network.response);
690
- }
691
- const admitted = await dispatchHostedAdmission({
692
- delivery,
693
- definition: channel.definition,
694
- args: input.buildHandlerArgs(delivery.channelId),
843
+ let operation: AdmissionOperation;
844
+ const execution = runAdmissionOperation(delivery, definition).then(reply => {
845
+ operation.settledReply = reply;
846
+ operation.expiresAt = Date.now() + pendingTtlMs;
847
+ return reply;
695
848
  });
696
- if (admitted.pendingSend === undefined) {
697
- return finish(admitted.response);
849
+ operation = {
850
+ execution,
851
+ expiresAt: Date.now() + ownerTurnPendingTtlMs,
852
+ };
853
+ admissions.set(delivery.deliveryId, operation);
854
+ const quickReply = await Promise.race([
855
+ execution,
856
+ new Promise<undefined>(resolve => setImmediate(() => resolve(undefined))),
857
+ ]);
858
+ if (quickReply !== undefined) {
859
+ return responseFromReply(quickReply);
698
860
  }
699
- pruneExpired();
700
- const admissionToken = randomBytes(24).toString("hex");
701
- pending.set(admissionToken, {
702
- send: admitted.pendingSend,
703
- channelKind: delivery.channelKind,
704
- expiresAt: Date.now() + pendingTtlMs,
705
- deliveryId: delivery.deliveryId,
706
- });
707
861
  return finish(
708
862
  Response.json({
709
863
  ok: true,
710
864
  v: HOSTED_DELIVERY_PROTOCOL_VERSION,
711
- outcome: "send",
712
- admissionToken,
865
+ outcome: "started",
713
866
  }),
714
867
  );
715
868
  }),
@@ -762,14 +915,58 @@ export function registerHostedDeliveryRoute(input: {
762
915
  ),
763
916
  );
764
917
  }
765
- const network = await finishNetworkWait("execution");
766
- guestNetwork = network.timing;
767
- if (network.response !== undefined) {
768
- return finish(network.response);
918
+
919
+ if (
920
+ execution.mode === "start" &&
921
+ admitted.settledReply !== undefined &&
922
+ isTransientRetryReply(admitted.settledReply)
923
+ ) {
924
+ delete admitted.settledReply;
925
+ delete admitted.execution;
769
926
  }
927
+
928
+ if (
929
+ execution.mode === "status" ||
930
+ (execution.mode === "start" && admitted.execution !== undefined)
931
+ ) {
932
+ if (admitted.settledReply !== undefined) {
933
+ return responseFromReply(admitted.settledReply);
934
+ }
935
+ if (admitted.execution === undefined) {
936
+ return finish(
937
+ transientHostedError(
938
+ 409,
939
+ "hosted_admission_unavailable",
940
+ "The hosted admission token has no owner turn in flight.",
941
+ ),
942
+ );
943
+ }
944
+ if (execution.mode === "start") {
945
+ return finish(
946
+ Response.json({
947
+ ok: true,
948
+ v: HOSTED_DELIVERY_PROTOCOL_VERSION,
949
+ outcome: "started",
950
+ }),
951
+ );
952
+ }
953
+ return finish(
954
+ Response.json({
955
+ ok: true,
956
+ v: HOSTED_DELIVERY_PROTOCOL_VERSION,
957
+ outcome: "running",
958
+ }),
959
+ );
960
+ }
961
+
770
962
  admitted.sessionPublicId = execution.sessionPublicId;
771
963
 
772
964
  if (execution.mode === "enqueue") {
965
+ const network = await finishNetworkWait("execution");
966
+ guestNetwork = network.timing;
967
+ if (network.response !== undefined) {
968
+ return finish(network.response);
969
+ }
773
970
  const enqueueOutcome = await enqueueIntoActiveOwner({
774
971
  activeOwners,
775
972
  sessionPublicId: execution.sessionPublicId,
@@ -786,198 +983,259 @@ export function registerHostedDeliveryRoute(input: {
786
983
  );
787
984
  }
788
985
 
789
- admitted.execution ??= (async (): Promise<ExecutionReply> => {
790
- const startedAt = performance.now();
791
- const executionId = hostedExecutionDiagId(execution.admissionToken);
792
- const sinks: HostedExecutionFlushSinks = {
793
- ...(input.stateRoot === undefined ? {} : { stateRoot: input.stateRoot }),
794
- ...(input.persistSessionRun === undefined
795
- ? {}
796
- : { persistSessionRun: input.persistSessionRun }),
797
- ...(input.flushStartLog === undefined ? {} : { flushStartLog: input.flushStartLog }),
798
- ...(input.snapshotLogs === undefined ? {} : { snapshotLogs: input.snapshotLogs }),
799
- };
800
- const writeDiag = async (fields: {
801
- sessionId: string;
802
- turnStatus: string;
803
- message?: string;
804
- abortReason?: ReturnType<typeof abortReasonFromTurnStatus> | "execute_throw";
805
- failureCode?: string;
806
- errorCode?: string;
807
- error?: unknown;
808
- }): Promise<void> => {
809
- const classification =
810
- fields.failureCode === undefined
811
- ? undefined
812
- : hostedFailureClassification(fields.failureCode);
813
- await flushHostedExecutionRecord(sinks, {
814
- executionId,
815
- sessionPublicId: execution.sessionPublicId,
816
- sessionId: fields.sessionId,
817
- turnStatus: fields.turnStatus,
818
- durationMs: Math.max(0, Math.round(performance.now() - startedAt)),
819
- ...(fields.message === undefined ? {} : { message: fields.message }),
820
- ...(fields.abortReason === undefined ? {} : { abortReason: fields.abortReason }),
821
- failureCode: fields.failureCode,
822
- ...(fields.errorCode === undefined ? {} : { errorCode: fields.errorCode }),
823
- classification,
824
- ...(fields.error === undefined ? {} : { error: fields.error }),
986
+ if (admitted.execution === undefined) {
987
+ admitted.expiresAt = Date.now() + ownerTurnPendingTtlMs;
988
+ }
989
+ admitted.execution ??= afterHostedWork(
990
+ input.flushOtel,
991
+ async (): Promise<ExecutionReply> => {
992
+ const network = await finishNetworkWait("execution");
993
+ guestNetwork = network.timing;
994
+ if (network.response !== undefined) {
995
+ return await responseToReply(finish(network.response));
996
+ }
997
+ const startedAt = performance.now();
998
+ const executionId = hostedExecutionDiagId(execution.admissionToken);
999
+ const sinks: HostedExecutionFlushSinks = {
1000
+ ...(input.stateRoot === undefined ? {} : { stateRoot: input.stateRoot }),
1001
+ ...(input.persistSessionRun === undefined
1002
+ ? {}
1003
+ : { persistSessionRun: input.persistSessionRun }),
1004
+ ...(input.flushStartLog === undefined ? {} : { flushStartLog: input.flushStartLog }),
1005
+ ...(input.snapshotLogs === undefined ? {} : { snapshotLogs: input.snapshotLogs }),
1006
+ };
1007
+ const writeDiag = async (fields: {
1008
+ sessionId: string;
1009
+ turnStatus: string;
1010
+ message?: string;
1011
+ abortReason?: ReturnType<typeof abortReasonFromTurnStatus> | "execute_throw";
1012
+ failureCode?: string;
1013
+ errorCode?: string;
1014
+ error?: unknown;
1015
+ }): Promise<void> => {
1016
+ const classification =
1017
+ fields.failureCode === undefined
1018
+ ? undefined
1019
+ : hostedFailureClassification(fields.failureCode);
1020
+ await flushHostedExecutionRecord(sinks, {
1021
+ executionId,
1022
+ sessionPublicId: execution.sessionPublicId,
1023
+ sessionId: fields.sessionId,
1024
+ turnStatus: fields.turnStatus,
1025
+ durationMs: Math.max(0, Math.round(performance.now() - startedAt)),
1026
+ ...(fields.message === undefined ? {} : { message: fields.message }),
1027
+ ...(fields.abortReason === undefined ? {} : { abortReason: fields.abortReason }),
1028
+ failureCode: fields.failureCode,
1029
+ ...(fields.errorCode === undefined ? {} : { errorCode: fields.errorCode }),
1030
+ classification,
1031
+ ...(fields.error === undefined ? {} : { error: fields.error }),
1032
+ });
1033
+ };
1034
+ // Claim the file before the turn runs. If a later status request
1035
+ // fails, the host reads this record while the turn may still be
1036
+ // running; the marker prevents it from surfacing the previous
1037
+ // delivery's terminal record.
1038
+ await writeDiag({
1039
+ sessionId: "",
1040
+ turnStatus: HOSTED_EXECUTION_DIAG_RUNNING_STATUS,
825
1041
  });
826
- };
827
- // Claim the file before the turn runs. The host reads it after its
828
- // own POST returns, which for a 9-minute timeout is while this turn
829
- // is still going; without this marker that read would surface the
830
- // PREVIOUS delivery's terminal record as if it were this one's.
831
- await writeDiag({
832
- sessionId: "",
833
- turnStatus: HOSTED_EXECUTION_DIAG_RUNNING_STATUS,
834
- });
835
- let sessionId = "";
836
- const owner: ActiveOwnerContext = {
837
- primaryDeliveryId: admitted.deliveryId,
838
- acceptedDeliveryIds: [],
839
- accepting: true,
840
- inflightInjects: new Set(),
841
- enqueueResults: new Map(),
842
- };
843
- activeOwners.set(execution.sessionPublicId, owner);
844
- return await runWithHostedExecutionLatency(
845
- { channelKind: admitted.channelKind },
846
- async () => {
847
- let completionAt: number | undefined;
848
- let drainAt: number | undefined;
849
- try {
850
- const args = input.buildHandlerArgs(
851
- admitted.send.channelId,
852
- execution.sessionPublicId,
853
- );
854
- const session = await args.send(admitted.send.message, {
855
- ...admitted.send.options,
856
- mailboxContinuation: {
857
- key: admitted.send.mailboxContinuationKey,
858
- },
859
- });
860
- sessionId = session.id;
861
- // The pre-turn claim used an empty sessionId. Stamp the
862
- // engine id now so a dashboard / session-view poll that
863
- // only has the factory `ses_…` can follow `session-events/`.
864
- await writeDiag({
865
- sessionId,
866
- turnStatus: HOSTED_EXECUTION_DIAG_RUNNING_STATUS,
867
- });
868
- const outcome = await session.waitForCompletion();
869
- completionAt = hostedExecutionNow();
870
- // Status is the owner turn. waitForCompletion still waited
871
- // for any drained successor so this process is not parked
872
- // mid-follow-up; a successor failure must not 503-retry the
873
- // owner after satellites already ran.
874
- // Close acceptance at the turn boundary, before durability
875
- // work creates an idle-but-still-addressable window.
876
- owner.accepting = false;
877
- if (owner.inflightInjects.size > 0) {
878
- await Promise.allSettled([...owner.inflightInjects]);
879
- }
880
- // Failed turns drain too: their record/continuation updates must
881
- // survive the park just like a finished turn's.
882
- await input.drainSessionDurability?.(session.id);
883
- drainAt = hostedExecutionNow();
884
- const consumedDeliveryIds = [owner.primaryDeliveryId, ...owner.acceptedDeliveryIds];
885
- if (consumedDeliveryIds.length > HOSTED_MAX_CONSUMED_DELIVERY_IDS) {
886
- throw new Error(
887
- `hosted execute consumedDeliveryIds length ${String(consumedDeliveryIds.length)} exceeds cap ${String(HOSTED_MAX_CONSUMED_DELIVERY_IDS)}`,
1042
+ let sessionId = "";
1043
+ const owner: ActiveOwnerContext = {
1044
+ primaryDeliveryId: admitted.deliveryId,
1045
+ acceptedDeliveryIds: [],
1046
+ accepting: true,
1047
+ inflightInjects: new Set(),
1048
+ enqueueResults: new Map(),
1049
+ };
1050
+ activeOwners.set(execution.sessionPublicId, owner);
1051
+ return await runWithHostedExecutionLatency(
1052
+ { channelKind: admitted.channelKind },
1053
+ async () => {
1054
+ let completionAt: number | undefined;
1055
+ let drainAt: number | undefined;
1056
+ try {
1057
+ const args = input.buildHandlerArgs(
1058
+ admitted.send.channelId,
1059
+ execution.sessionPublicId,
888
1060
  );
1061
+ const session = await args.send(admitted.send.message, {
1062
+ ...admitted.send.options,
1063
+ mailboxContinuation: {
1064
+ key: admitted.send.mailboxContinuationKey,
1065
+ },
1066
+ });
1067
+ sessionId = session.id;
1068
+ // The pre-turn claim used an empty sessionId. Stamp the
1069
+ // engine id now so a dashboard / session-view poll that
1070
+ // only has the factory `ses_…` can follow `session-events/`.
1071
+ await writeDiag({
1072
+ sessionId,
1073
+ turnStatus: HOSTED_EXECUTION_DIAG_RUNNING_STATUS,
1074
+ });
1075
+ const outcome = await session.waitForCompletion();
1076
+ completionAt = hostedExecutionNow();
1077
+ // Status is the owner turn. waitForCompletion still waited
1078
+ // for any drained successor so this process is not parked
1079
+ // mid-follow-up; a successor failure must not 503-retry the
1080
+ // owner after satellites already ran.
1081
+ // Close acceptance at the turn boundary, before durability
1082
+ // work creates an idle-but-still-addressable window.
1083
+ owner.accepting = false;
1084
+ if (owner.inflightInjects.size > 0) {
1085
+ await Promise.allSettled([...owner.inflightInjects]);
1086
+ }
1087
+ // Failed turns drain too: their record/continuation updates must
1088
+ // survive the park just like a finished turn's.
1089
+ await input.drainSessionDurability?.(session.id);
1090
+ drainAt = hostedExecutionNow();
1091
+ const consumedDeliveryIds = [
1092
+ owner.primaryDeliveryId,
1093
+ ...owner.acceptedDeliveryIds,
1094
+ ];
1095
+ if (consumedDeliveryIds.length > HOSTED_MAX_CONSUMED_DELIVERY_IDS) {
1096
+ throw new Error(
1097
+ `hosted execute consumedDeliveryIds length ${String(consumedDeliveryIds.length)} exceeds cap ${String(HOSTED_MAX_CONSUMED_DELIVERY_IDS)}`,
1098
+ );
1099
+ }
1100
+ // Evict before the reply: TAS parks and hibernates this process
1101
+ // as soon as the POST returns. A leftover SDK handle freezes a
1102
+ // dead Connect/HTTP2 session that the next wake then reuses.
1103
+ evictHostedSdkSessions(
1104
+ input.evictSdkSession,
1105
+ session.id,
1106
+ execution.sessionPublicId,
1107
+ );
1108
+ const hostedFailure =
1109
+ outcome.status === "finished"
1110
+ ? undefined
1111
+ : hostedFailureForUnfinishedTurn(outcome);
1112
+ await writeDiag({
1113
+ sessionId: session.id,
1114
+ turnStatus: outcome.status,
1115
+ message: outcome.errorMessage,
1116
+ abortReason: abortReasonFromTurnStatus(
1117
+ outcome.status,
1118
+ outcome.cancellationReason,
1119
+ ),
1120
+ failureCode: hostedFailure?.error,
1121
+ ...(outcome.errorCode === undefined ? {} : { errorCode: outcome.errorCode }),
1122
+ });
1123
+ const reply =
1124
+ hostedFailure !== undefined
1125
+ ? {
1126
+ status: 503,
1127
+ body: {
1128
+ ok: false,
1129
+ error: hostedFailure.error,
1130
+ retry: hostedFailure.retry,
1131
+ classification: hostedFailureClassification(hostedFailure.error),
1132
+ turnStatus: outcome.status,
1133
+ message: outcome.errorMessage,
1134
+ ...(outcome.errorCode === undefined
1135
+ ? {}
1136
+ : { errorCode: outcome.errorCode }),
1137
+ },
1138
+ }
1139
+ : {
1140
+ status: 200,
1141
+ body: {
1142
+ ok: true,
1143
+ v: HOSTED_DELIVERY_PROTOCOL_VERSION,
1144
+ outcome: "send",
1145
+ consumedDeliveryIds,
1146
+ },
1147
+ };
1148
+ // Finalize as late as possible so `post_drain` and `total`
1149
+ // include eviction + diag write after durability drain.
1150
+ latencySnapshot = finalizeHostedExecutionLatency({
1151
+ completionAt,
1152
+ drainAt,
1153
+ endedAt: hostedExecutionNow(),
1154
+ });
1155
+ return await responseToReply(
1156
+ finish(Response.json(reply.body, { status: reply.status })),
1157
+ );
1158
+ } catch (error) {
1159
+ owner.accepting = false;
1160
+ if (owner.inflightInjects.size > 0) {
1161
+ await Promise.allSettled([...owner.inflightInjects]);
1162
+ }
1163
+ evictHostedSdkSessions(
1164
+ input.evictSdkSession,
1165
+ sessionId,
1166
+ execution.sessionPublicId,
1167
+ );
1168
+ const thrownErrorCode = describeErrorCode(error);
1169
+ await writeDiag({
1170
+ sessionId: "",
1171
+ turnStatus: "error",
1172
+ message: error instanceof Error ? error.message : String(error),
1173
+ abortReason: "execute_throw",
1174
+ failureCode: "internal_error",
1175
+ error,
1176
+ ...(thrownErrorCode === undefined ? {} : { errorCode: thrownErrorCode }),
1177
+ });
1178
+ const endedAt = hostedExecutionNow();
1179
+ // Preserve completion/drain marks when the failure happened
1180
+ // during post-drain work; otherwise collapse to endedAt.
1181
+ latencySnapshot = finalizeHostedExecutionLatency({
1182
+ completionAt: completionAt ?? endedAt,
1183
+ drainAt: drainAt ?? endedAt,
1184
+ endedAt,
1185
+ });
1186
+ throw error;
1187
+ } finally {
1188
+ if (activeOwners.get(execution.sessionPublicId) === owner) {
1189
+ activeOwners.delete(execution.sessionPublicId);
1190
+ }
889
1191
  }
890
- // Evict before the reply: TAS parks and hibernates this process
891
- // as soon as the POST returns. A leftover SDK handle freezes a
892
- // dead Connect/HTTP2 session that the next wake then reuses.
893
- evictHostedSdkSessions(
894
- input.evictSdkSession,
895
- session.id,
896
- execution.sessionPublicId,
897
- );
898
- const hostedFailure =
899
- outcome.status === "finished"
900
- ? undefined
901
- : hostedFailureForUnfinishedTurn(outcome);
902
- await writeDiag({
903
- sessionId: session.id,
904
- turnStatus: outcome.status,
905
- message: outcome.errorMessage,
906
- abortReason: abortReasonFromTurnStatus(
907
- outcome.status,
908
- outcome.cancellationReason,
909
- ),
910
- failureCode: hostedFailure?.error,
911
- ...(outcome.errorCode === undefined ? {} : { errorCode: outcome.errorCode }),
912
- });
913
- const reply =
914
- hostedFailure !== undefined
915
- ? {
916
- status: 503,
917
- body: {
918
- ok: false,
919
- error: hostedFailure.error,
920
- retry: hostedFailure.retry,
921
- classification: hostedFailureClassification(hostedFailure.error),
922
- turnStatus: outcome.status,
923
- message: outcome.errorMessage,
924
- ...(outcome.errorCode === undefined
925
- ? {}
926
- : { errorCode: outcome.errorCode }),
927
- },
928
- }
929
- : {
930
- status: 200,
931
- body: {
932
- ok: true,
933
- v: HOSTED_DELIVERY_PROTOCOL_VERSION,
934
- outcome: "send",
935
- consumedDeliveryIds,
936
- },
937
- };
938
- // Finalize as late as possible so `post_drain` and `total`
939
- // include eviction + diag write after durability drain.
940
- latencySnapshot = finalizeHostedExecutionLatency({
941
- completionAt,
942
- drainAt,
943
- endedAt: hostedExecutionNow(),
944
- });
945
- return reply;
946
- } catch (error) {
947
- owner.accepting = false;
948
- if (owner.inflightInjects.size > 0) {
949
- await Promise.allSettled([...owner.inflightInjects]);
950
- }
951
- evictHostedSdkSessions(input.evictSdkSession, sessionId, execution.sessionPublicId);
952
- const thrownErrorCode = describeErrorCode(error);
953
- await writeDiag({
954
- sessionId: "",
955
- turnStatus: "error",
956
- message: error instanceof Error ? error.message : String(error),
957
- abortReason: "execute_throw",
958
- failureCode: "internal_error",
959
- error,
960
- ...(thrownErrorCode === undefined ? {} : { errorCode: thrownErrorCode }),
961
- });
962
- const endedAt = hostedExecutionNow();
963
- // Preserve completion/drain marks when the failure happened
964
- // during post-drain work; otherwise collapse to endedAt.
965
- latencySnapshot = finalizeHostedExecutionLatency({
966
- completionAt: completionAt ?? endedAt,
967
- drainAt: drainAt ?? endedAt,
968
- endedAt,
969
- });
970
- throw error;
971
- } finally {
972
- if (activeOwners.get(execution.sessionPublicId) === owner) {
973
- activeOwners.delete(execution.sessionPublicId);
974
- }
975
- }
976
- },
1192
+ },
1193
+ );
1194
+ },
1195
+ ).then(
1196
+ reply => {
1197
+ admitted.settledReply = reply;
1198
+ admitted.expiresAt = Date.now() + pendingTtlMs;
1199
+ return reply;
1200
+ },
1201
+ error => {
1202
+ admitted.settledReply = {
1203
+ status: 503,
1204
+ body: {
1205
+ ok: false,
1206
+ error: "internal_error",
1207
+ retry: HOSTED_GUEST_RETRY_TERMINAL,
1208
+ classification: hostedFailureClassification("internal_error"),
1209
+ message: error instanceof Error ? error.message : String(error),
1210
+ },
1211
+ };
1212
+ admitted.expiresAt = Date.now() + pendingTtlMs;
1213
+ return admitted.settledReply;
1214
+ },
1215
+ );
1216
+ if (execution.mode === "start") {
1217
+ const quickReply = await Promise.race([
1218
+ admitted.execution,
1219
+ new Promise<undefined>(resolve => setImmediate(() => resolve(undefined))),
1220
+ ]);
1221
+ if (quickReply !== undefined) {
1222
+ return responseFromReply(quickReply);
1223
+ }
1224
+ return finish(
1225
+ Response.json({
1226
+ ok: true,
1227
+ v: HOSTED_DELIVERY_PROTOCOL_VERSION,
1228
+ outcome: "started",
1229
+ }),
977
1230
  );
978
- })();
979
- const reply = await admitted.execution;
980
- return finish(Response.json(reply.body, { status: reply.status }));
1231
+ }
1232
+ return finish(
1233
+ terminalHostedError(
1234
+ 400,
1235
+ "invalid_hosted_execution",
1236
+ "Owner execution requires start or status mode.",
1237
+ ),
1238
+ );
981
1239
  }),
982
1240
  });
983
1241
  }