@cursor/bdk 0.2.3 → 0.2.4

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 (577) hide show
  1. package/dist/bin/agent-serve.js +9 -1
  2. package/dist/channels/slack/attachments.d.ts +2 -1
  3. package/dist/channels/slack/attachments.d.ts.map +1 -1
  4. package/dist/channels/slack/attachments.js +19 -9
  5. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  6. package/dist/channels/slack/dispatch.js +26 -24
  7. package/dist/channels/slack/thread-context.d.ts +21 -11
  8. package/dist/channels/slack/thread-context.d.ts.map +1 -1
  9. package/dist/channels/slack/thread-context.js +75 -27
  10. package/dist/docs/404.html +2 -2
  11. package/dist/docs/assets/{app.BOIHhrKi.js → app.4kQ8Db_q.js} +4 -4
  12. package/dist/docs/assets/chunks/@localSearchIndexroot.CvuAJ0My.js +1 -0
  13. package/dist/docs/assets/chunks/{VPLocalSearchBox.D49zVZqM.js → VPLocalSearchBox.DY1RwB8Q.js} +1 -1
  14. package/dist/docs/assets/chunks/{arc.hmjb-sc4.js → arc.CxE_fSPK.js} +1 -1
  15. package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.CxEI1KqM.js → architectureDiagram-Q4EWVU46.CPX426ui.js} +1 -1
  16. package/dist/docs/assets/chunks/{baseUniq.DHHvBWoV.js → baseUniq.CB52JrKG.js} +1 -1
  17. package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.DnXW-3bu.js → blockDiagram-DXYQGD6D.J0cNaQCL.js} +1 -1
  18. package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.e-47O2jM.js → c4Diagram-AHTNJAMY.DJn3vEGT.js} +1 -1
  19. package/dist/docs/assets/chunks/channel.BoNycAoN.js +1 -0
  20. package/dist/docs/assets/chunks/{chunk-4BX2VUAB.3ry4pYXB.js → chunk-4BX2VUAB.Dao618F6.js} +1 -1
  21. package/dist/docs/assets/chunks/{chunk-4TB4RGXK.DGIZFRx6.js → chunk-4TB4RGXK.QW8Rhjai.js} +1 -1
  22. package/dist/docs/assets/chunks/{chunk-55IACEB6.DKBnqg9U.js → chunk-55IACEB6.DfRLLKF_.js} +1 -1
  23. package/dist/docs/assets/chunks/{chunk-EDXVE4YY.BIU8Ue5k.js → chunk-EDXVE4YY.CIV2ApKQ.js} +1 -1
  24. package/dist/docs/assets/chunks/{chunk-FMBD7UC4.DP-TFhjI.js → chunk-FMBD7UC4.BEheSuxp.js} +1 -1
  25. package/dist/docs/assets/chunks/{chunk-OYMX7WX6.Ux0OYj5v.js → chunk-OYMX7WX6.CUN88ENB.js} +1 -1
  26. package/dist/docs/assets/chunks/{chunk-QZHKN3VN.BzHMwYox.js → chunk-QZHKN3VN.CgqCs8b_.js} +1 -1
  27. package/dist/docs/assets/chunks/{chunk-YZCP3GAM.D4OGAsSP.js → chunk-YZCP3GAM.iCH0nnTJ.js} +1 -1
  28. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.C4x07Gkj.js +1 -0
  29. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.C4x07Gkj.js +1 -0
  30. package/dist/docs/assets/chunks/clone.Db22cH_-.js +1 -0
  31. package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.Jq_7BUNx.js → cose-bilkent-S5V4N54A.BLcUxhWE.js} +1 -1
  32. package/dist/docs/assets/chunks/{dagre-KV5264BT.Di-skR2x.js → dagre-KV5264BT.Ep7LofOm.js} +1 -1
  33. package/dist/docs/assets/chunks/{diagram-5BDNPKRD.DeREHIdH.js → diagram-5BDNPKRD.Bzf4GSQ4.js} +1 -1
  34. package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.C7Kcqxro.js → diagram-G4DWMVQ6.DD6Jh-eM.js} +1 -1
  35. package/dist/docs/assets/chunks/{diagram-MMDJMWI5.BK3eohyo.js → diagram-MMDJMWI5.oOIl8bWd.js} +1 -1
  36. package/dist/docs/assets/chunks/{diagram-TYMM5635.C6TyymXT.js → diagram-TYMM5635.DHs85Ade.js} +1 -1
  37. package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.DYGG-gGx.js → erDiagram-SMLLAGMA.BIb5ghCk.js} +1 -1
  38. package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.C9nBcSV4.js → flowDiagram-DWJPFMVM.DV4paY9k.js} +1 -1
  39. package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.wAg_ymsp.js → ganttDiagram-T4ZO3ILL.AyEKA6_v.js} +1 -1
  40. package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.B87j9Oeg.js → gitGraphDiagram-UUTBAWPF.BltiCDFo.js} +1 -1
  41. package/dist/docs/assets/chunks/{graph.CuFMj31w.js → graph.DzuEYGdC.js} +1 -1
  42. package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.P_mLGumP.js → infoDiagram-42DDH7IO.BV2l981J.js} +1 -1
  43. package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.DyuL_MsT.js → ishikawaDiagram-UXIWVN3A.BA4Izf-m.js} +1 -1
  44. package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.CtP09IoJ.js → journeyDiagram-VCZTEJTY.DjaFbFS3.js} +1 -1
  45. package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.BoeSYPZo.js → kanban-definition-6JOO6SKY.CfTFieDs.js} +1 -1
  46. package/dist/docs/assets/chunks/{layout.B0lMMtNo.js → layout.DzfWqTBV.js} +1 -1
  47. package/dist/docs/assets/chunks/{linear.HxRBiAFX.js → linear.BO6mpulV.js} +1 -1
  48. package/dist/docs/assets/chunks/{min.BGlFFHwS.js → min.BGgTadgT.js} +1 -1
  49. package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.JyLBD9M8.js → mindmap-definition-QFDTVHPH.DPuIXVWY.js} +1 -1
  50. package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.DnSmNZF8.js → pieDiagram-DEJITSTG.BOnl3bBg.js} +1 -1
  51. package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.CUCnbfCa.js → quadrantDiagram-34T5L4WZ.DNB6Ckdc.js} +1 -1
  52. package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.py0IVUn5.js → requirementDiagram-MS252O5E.D5-Qo7vb.js} +1 -1
  53. package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.Bkc-HWYp.js → sankeyDiagram-XADWPNL6.8t65cesf.js} +1 -1
  54. package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.Dqn8Mlv2.js → sequenceDiagram-FGHM5R23.CaG07BdS.js} +1 -1
  55. package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.JikkoQUU.js → stateDiagram-FHFEXIEX.TKOweTB6.js} +1 -1
  56. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.CuqmyQc4.js +1 -0
  57. package/dist/docs/assets/chunks/{theme.b6HQ6zG_.js → theme.Dx-JhpTB.js} +2 -2
  58. package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.BvpSXiBj.js → timeline-definition-GMOUNBTQ.fE53zQ2s.js} +1 -1
  59. package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.CU7MVnZx.js → vennDiagram-DHZGUBPP.DJsZZaJg.js} +1 -1
  60. package/dist/docs/assets/chunks/{wardley-RL74JXVD.BKwC4ctG.js → wardley-RL74JXVD.844kyrjl.js} +1 -1
  61. package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.BfaF6Uhe.js → wardleyDiagram-NUSXRM2D.CMZ-Ru_t.js} +1 -1
  62. package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.Bg5dcpj4.js → xychartDiagram-5P7HB3ND.XXrhBc7a.js} +1 -1
  63. package/dist/docs/assets/{deployment.md.BJ8i7Q6p.js → deployment.md.UhnJIMr-.js} +2 -2
  64. package/dist/docs/assets/{deployment.md.BJ8i7Q6p.lean.js → deployment.md.UhnJIMr-.lean.js} +1 -1
  65. package/dist/docs/assets/{guides_jev.md.BNDm14Gy.js → guides_jev.md.CRcgmjDb.js} +2 -2
  66. package/dist/docs/assets/{guides_jev.md.BNDm14Gy.lean.js → guides_jev.md.CRcgmjDb.lean.js} +1 -1
  67. package/dist/docs/assets/{reference_agent-config.md.DzGI777n.js → reference_agent-config.md.Cj5uBKp4.js} +1 -1
  68. package/dist/docs/assets/{reference_extensions.md.CPPrkWlJ.js → reference_extensions.md.pa2tN-e4.js} +4 -3
  69. package/dist/docs/assets/{reference_extensions.md.CPPrkWlJ.lean.js → reference_extensions.md.pa2tN-e4.lean.js} +1 -1
  70. package/dist/docs/building-with-agents.html +35 -35
  71. package/dist/docs/deployment.html +37 -37
  72. package/dist/docs/deployment.md +4 -1
  73. package/dist/docs/evals.html +35 -35
  74. package/dist/docs/guides/agent-to-agent.html +35 -35
  75. package/dist/docs/guides/bitbucket.html +35 -35
  76. package/dist/docs/guides/cloud-agents.html +35 -35
  77. package/dist/docs/guides/convert-automation.html +35 -35
  78. package/dist/docs/guides/github.html +35 -35
  79. package/dist/docs/guides/gitlab.html +35 -35
  80. package/dist/docs/guides/grokbot-agents.html +35 -35
  81. package/dist/docs/guides/hooks.html +35 -35
  82. package/dist/docs/guides/improve.html +35 -35
  83. package/dist/docs/guides/jev.html +37 -37
  84. package/dist/docs/guides/jev.md +7 -0
  85. package/dist/docs/guides/mcp-oauth.html +35 -35
  86. package/dist/docs/guides/opentelemetry.html +35 -35
  87. package/dist/docs/guides/slack.html +35 -35
  88. package/dist/docs/guides/webhooks.html +35 -35
  89. package/dist/docs/hashmap.json +1 -1
  90. package/dist/docs/hillclimbing.html +35 -35
  91. package/dist/docs/index.html +35 -35
  92. package/dist/docs/llms-full.txt +25 -2
  93. package/dist/docs/quickstart.html +35 -35
  94. package/dist/docs/reference/agent-config.html +37 -37
  95. package/dist/docs/reference/agent-config.md +1 -1
  96. package/dist/docs/reference/artifacts.html +35 -35
  97. package/dist/docs/reference/channels.html +35 -35
  98. package/dist/docs/reference/cli.html +35 -35
  99. package/dist/docs/reference/connections.html +35 -35
  100. package/dist/docs/reference/evals.html +35 -35
  101. package/dist/docs/reference/extensions.html +39 -38
  102. package/dist/docs/reference/extensions.md +13 -0
  103. package/dist/docs/reference/hooks.html +35 -35
  104. package/dist/docs/reference/http-api.html +35 -35
  105. package/dist/docs/reference/instructions.html +35 -35
  106. package/dist/docs/reference/playground.html +35 -35
  107. package/dist/docs/reference/project-layout.html +35 -35
  108. package/dist/docs/reference/prompt.html +35 -35
  109. package/dist/docs/reference/schedules.html +35 -35
  110. package/dist/docs/reference/sessions.html +35 -35
  111. package/dist/docs/reference/skills.html +35 -35
  112. package/dist/docs/reference/subagents.html +35 -35
  113. package/dist/docs/reference/tools.html +35 -35
  114. package/dist/docs/templates/agentic-owners.html +35 -35
  115. package/dist/docs/templates/security-reviewer.html +35 -35
  116. package/dist/docs/templates/thermo-quality-review.html +35 -35
  117. package/dist/docs/templates/thermo-review.html +35 -35
  118. package/dist/docs/templates/triage.html +35 -35
  119. package/dist/docs/troubleshooting.html +35 -35
  120. package/dist/extensions/jev/extension.d.ts +3 -0
  121. package/dist/extensions/jev/extension.d.ts.map +1 -1
  122. package/dist/extensions/jev/extension.js +10 -1
  123. package/dist/extensions/jev/lib/evaluate.d.ts +4 -0
  124. package/dist/extensions/jev/lib/evaluate.d.ts.map +1 -1
  125. package/dist/extensions/jev/lib/evaluate.js +6 -2
  126. package/dist/extensions.d.ts +4 -2
  127. package/dist/extensions.d.ts.map +1 -1
  128. package/dist/extensions.js +5 -2
  129. package/dist/internal/cli-deploy.d.ts.map +1 -1
  130. package/dist/internal/cli-deploy.js +19 -5
  131. package/dist/internal/discovery/agent-config.d.ts +6 -5
  132. package/dist/internal/discovery/agent-config.d.ts.map +1 -1
  133. package/dist/internal/discovery/agent-config.js +29 -28
  134. package/dist/internal/discovery/agent.js +1 -1
  135. package/dist/internal/discovery/extensions.d.ts.map +1 -1
  136. package/dist/internal/discovery/extensions.js +12 -0
  137. package/dist/internal/hosting.d.ts +8 -0
  138. package/dist/internal/hosting.d.ts.map +1 -1
  139. package/dist/internal/hosting.js +24 -0
  140. package/dist/types.d.ts +18 -2
  141. package/dist/types.d.ts.map +1 -1
  142. package/docs/deployment.md +4 -1
  143. package/docs/guides/jev.md +7 -0
  144. package/docs/reference/agent-config.md +1 -1
  145. package/docs/reference/extensions.md +13 -0
  146. package/package.json +1 -9
  147. package/dist/docs/assets/chunks/@localSearchIndexroot.D5L-b34G.js +0 -1
  148. package/dist/docs/assets/chunks/channel.BbOGaJQP.js +0 -1
  149. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.Db58HCb1.js +0 -1
  150. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.Db58HCb1.js +0 -1
  151. package/dist/docs/assets/chunks/clone.Co4MBflG.js +0 -1
  152. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.CMsKhrW0.js +0 -1
  153. package/src/artifacts.ts +0 -68
  154. package/src/bin/agent-serve.ts +0 -1854
  155. package/src/channels/bitbucket/api.ts +0 -891
  156. package/src/channels/bitbucket/binding.ts +0 -417
  157. package/src/channels/bitbucket/bitbucket-channel.ts +0 -162
  158. package/src/channels/bitbucket/bitbucket-webhook.ts +0 -519
  159. package/src/channels/bitbucket/checks.ts +0 -146
  160. package/src/channels/bitbucket/cursor-account.ts +0 -106
  161. package/src/channels/bitbucket/defaults.ts +0 -100
  162. package/src/channels/bitbucket/events.ts +0 -74
  163. package/src/channels/bitbucket/index.ts +0 -51
  164. package/src/channels/bitbucket/replay.ts +0 -421
  165. package/src/channels/bitbucket/state.ts +0 -59
  166. package/src/channels/bitbucket/types.ts +0 -261
  167. package/src/channels/change-monitors/change-monitors-channel.ts +0 -63
  168. package/src/channels/change-monitors/index.ts +0 -8
  169. package/src/channels/change-monitors/types.ts +0 -42
  170. package/src/channels/checks.ts +0 -185
  171. package/src/channels/deployments/deployments-channel.ts +0 -224
  172. package/src/channels/deployments/index.ts +0 -25
  173. package/src/channels/deployments/types.ts +0 -92
  174. package/src/channels/github/api.ts +0 -526
  175. package/src/channels/github/auth.ts +0 -293
  176. package/src/channels/github/binding.ts +0 -233
  177. package/src/channels/github/checks.ts +0 -145
  178. package/src/channels/github/cursor-account.ts +0 -303
  179. package/src/channels/github/defaults.ts +0 -168
  180. package/src/channels/github/events.ts +0 -67
  181. package/src/channels/github/forward.ts +0 -359
  182. package/src/channels/github/github-channel.ts +0 -2334
  183. package/src/channels/github/index.ts +0 -54
  184. package/src/channels/github/progress.ts +0 -365
  185. package/src/channels/github/replay.ts +0 -372
  186. package/src/channels/github/state.ts +0 -124
  187. package/src/channels/github/types.ts +0 -590
  188. package/src/channels/gitlab/api.ts +0 -329
  189. package/src/channels/gitlab/binding.ts +0 -231
  190. package/src/channels/gitlab/checks.ts +0 -228
  191. package/src/channels/gitlab/cursor-account.ts +0 -105
  192. package/src/channels/gitlab/defaults.ts +0 -80
  193. package/src/channels/gitlab/events.ts +0 -37
  194. package/src/channels/gitlab/gitlab-channel.ts +0 -160
  195. package/src/channels/gitlab/gitlab-webhook.ts +0 -509
  196. package/src/channels/gitlab/index.ts +0 -44
  197. package/src/channels/gitlab/replay.ts +0 -328
  198. package/src/channels/gitlab/state.ts +0 -55
  199. package/src/channels/gitlab/types.ts +0 -247
  200. package/src/channels/issues/index.ts +0 -9
  201. package/src/channels/issues/issues-channel.ts +0 -45
  202. package/src/channels/issues/types.ts +0 -38
  203. package/src/channels/origin/api.ts +0 -507
  204. package/src/channels/origin/binding.ts +0 -114
  205. package/src/channels/origin/checks.ts +0 -250
  206. package/src/channels/origin/cursor-account.ts +0 -58
  207. package/src/channels/origin/defaults.ts +0 -140
  208. package/src/channels/origin/events.ts +0 -35
  209. package/src/channels/origin/index.ts +0 -35
  210. package/src/channels/origin/origin-channel.ts +0 -815
  211. package/src/channels/origin/origin-webhook.ts +0 -296
  212. package/src/channels/origin/reactions.ts +0 -72
  213. package/src/channels/origin/state.ts +0 -54
  214. package/src/channels/origin/types.ts +0 -295
  215. package/src/channels/slack/agentic-delivery.ts +0 -634
  216. package/src/channels/slack/agentic-posted.ts +0 -135
  217. package/src/channels/slack/agentic-signals.ts +0 -231
  218. package/src/channels/slack/api.ts +0 -761
  219. package/src/channels/slack/approvals.ts +0 -279
  220. package/src/channels/slack/assistant.ts +0 -76
  221. package/src/channels/slack/attachments.ts +0 -596
  222. package/src/channels/slack/auth.ts +0 -127
  223. package/src/channels/slack/blocks.ts +0 -131
  224. package/src/channels/slack/bot-mentions.ts +0 -318
  225. package/src/channels/slack/channel-watch.ts +0 -314
  226. package/src/channels/slack/cli-project.ts +0 -249
  227. package/src/channels/slack/code-fences.ts +0 -171
  228. package/src/channels/slack/constants.ts +0 -38
  229. package/src/channels/slack/credentials.ts +0 -88
  230. package/src/channels/slack/defaults.ts +0 -714
  231. package/src/channels/slack/dispatch.ts +0 -1060
  232. package/src/channels/slack/doctor.ts +0 -338
  233. package/src/channels/slack/eval-directive.ts +0 -306
  234. package/src/channels/slack/event-id-dedupe.ts +0 -30
  235. package/src/channels/slack/external-policy.ts +0 -75
  236. package/src/channels/slack/footer.ts +0 -106
  237. package/src/channels/slack/inbound.ts +0 -416
  238. package/src/channels/slack/index.ts +0 -53
  239. package/src/channels/slack/init.ts +0 -169
  240. package/src/channels/slack/interactive.ts +0 -406
  241. package/src/channels/slack/links.ts +0 -23
  242. package/src/channels/slack/live-delivery.ts +0 -489
  243. package/src/channels/slack/log.ts +0 -70
  244. package/src/channels/slack/manifest.ts +0 -240
  245. package/src/channels/slack/message-body.ts +0 -82
  246. package/src/channels/slack/nudge-carrier.ts +0 -224
  247. package/src/channels/slack/nudge-store.ts +0 -334
  248. package/src/channels/slack/paint-start.ts +0 -93
  249. package/src/channels/slack/placeholder.ts +0 -358
  250. package/src/channels/slack/pr-ref.ts +0 -74
  251. package/src/channels/slack/progress-delivery.ts +0 -138
  252. package/src/channels/slack/reasoning-card.ts +0 -125
  253. package/src/channels/slack/reasoning-chip.ts +0 -41
  254. package/src/channels/slack/recording-sink.ts +0 -167
  255. package/src/channels/slack/redact.ts +0 -6
  256. package/src/channels/slack/reply-options.ts +0 -279
  257. package/src/channels/slack/setup.ts +0 -125
  258. package/src/channels/slack/slack-channel.ts +0 -744
  259. package/src/channels/slack/socket-mode.ts +0 -140
  260. package/src/channels/slack/stop.ts +0 -25
  261. package/src/channels/slack/stream.ts +0 -66
  262. package/src/channels/slack/thread-context.ts +0 -485
  263. package/src/channels/slack/tool-approval-events.ts +0 -233
  264. package/src/channels/slack/tool-cards.ts +0 -198
  265. package/src/channels/slack/tool-chip.ts +0 -34
  266. package/src/channels/slack/types.ts +0 -787
  267. package/src/channels/slack/upload.ts +0 -137
  268. package/src/channels.ts +0 -543
  269. package/src/connections.ts +0 -153
  270. package/src/dashboard-session-url.ts +0 -30
  271. package/src/evals/assertions.ts +0 -688
  272. package/src/evals/expect.ts +0 -250
  273. package/src/evals/judge.ts +0 -329
  274. package/src/evals/loaders.ts +0 -111
  275. package/src/evals/matchers.ts +0 -223
  276. package/src/evals/reporters.ts +0 -257
  277. package/src/evals/results.ts +0 -130
  278. package/src/evals/run-facts.ts +0 -306
  279. package/src/evals.ts +0 -709
  280. package/src/extensions/cursor-cloud-agents/extension.ts +0 -131
  281. package/src/extensions/cursor-cloud-agents/lib/backend.ts +0 -386
  282. package/src/extensions/cursor-cloud-agents/lib/channels.ts +0 -11
  283. package/src/extensions/cursor-cloud-agents/lib/fleet.ts +0 -98
  284. package/src/extensions/cursor-cloud-agents/lib/inputs.ts +0 -5
  285. package/src/extensions/cursor-cloud-agents/lib/repos.ts +0 -80
  286. package/src/extensions/cursor-cloud-agents/lib/transcript.ts +0 -19
  287. package/src/extensions/cursor-cloud-agents/skills/handoff.md +0 -37
  288. package/src/extensions/cursor-cloud-agents/tools/cancel.ts +0 -21
  289. package/src/extensions/cursor-cloud-agents/tools/dump.ts +0 -47
  290. package/src/extensions/cursor-cloud-agents/tools/get.ts +0 -18
  291. package/src/extensions/cursor-cloud-agents/tools/launch.ts +0 -62
  292. package/src/extensions/cursor-cloud-agents/tools/list.ts +0 -31
  293. package/src/extensions/cursor-cloud-agents/tools/reply.ts +0 -36
  294. package/src/extensions/cursor-grokbot-agents/extension.ts +0 -132
  295. package/src/extensions/cursor-grokbot-agents/lib/agents.ts +0 -42
  296. package/src/extensions/cursor-grokbot-agents/lib/backend.ts +0 -208
  297. package/src/extensions/cursor-grokbot-agents/lib/contacts.ts +0 -74
  298. package/src/extensions/cursor-grokbot-agents/lib/conversation.ts +0 -260
  299. package/src/extensions/cursor-grokbot-agents/lib/inputs.ts +0 -21
  300. package/src/extensions/cursor-grokbot-agents/lib/lock.ts +0 -26
  301. package/src/extensions/cursor-grokbot-agents/skills/consult.md +0 -40
  302. package/src/extensions/cursor-grokbot-agents/tools/ask.ts +0 -32
  303. package/src/extensions/cursor-grokbot-agents/tools/check.ts +0 -25
  304. package/src/extensions/cursor-grokbot-agents/tools/interrupt.ts +0 -17
  305. package/src/extensions/cursor-grokbot-agents/tools/list.ts +0 -26
  306. package/src/extensions/improve/extension.ts +0 -69
  307. package/src/extensions/improve/skills/yourself.ts +0 -50
  308. package/src/extensions/jev/extension.ts +0 -95
  309. package/src/extensions/jev/lib/evaluate.ts +0 -266
  310. package/src/extensions/jev/skills/gated-write.md +0 -25
  311. package/src/extensions/jev/skills/questions.md +0 -33
  312. package/src/extensions/jev/tools/evaluate.ts +0 -82
  313. package/src/extensions/slack-communication/evals/harness.ts +0 -705
  314. package/src/extensions/slack-communication/evals/slack-communication.eval.ts +0 -830
  315. package/src/extensions/slack-communication/evals/slack-placeholder.eval.ts +0 -172
  316. package/src/extensions/slack-communication/extension.ts +0 -44
  317. package/src/extensions/slack-communication/skills/slack-voice.ts +0 -56
  318. package/src/extensions/slack-communication/tools/delete-message.ts +0 -33
  319. package/src/extensions/slack-communication/tools/edit-message.ts +0 -42
  320. package/src/extensions/slack-communication/tools/post-card.ts +0 -28
  321. package/src/extensions/slack-communication/tools/post-file.ts +0 -82
  322. package/src/extensions/slack-communication/tools/post-update.ts +0 -40
  323. package/src/extensions/slack-communication/tools/react.ts +0 -30
  324. package/src/extensions/slack-communication/tools/set-status.ts +0 -21
  325. package/src/extensions.ts +0 -179
  326. package/src/files-backends/agent-store-presigned-url.ts +0 -11
  327. package/src/files-backends/cursor-hosted.ts +0 -1212
  328. package/src/files-backends/local-fs.ts +0 -163
  329. package/src/files.ts +0 -293
  330. package/src/filesystem.ts +0 -2005
  331. package/src/hooks.ts +0 -30
  332. package/src/index.ts +0 -259
  333. package/src/internal/advertise-tools.ts +0 -370
  334. package/src/internal/approval-gate.ts +0 -103
  335. package/src/internal/artifacts-store.ts +0 -836
  336. package/src/internal/as-of.ts +0 -257
  337. package/src/internal/auth.ts +0 -46
  338. package/src/internal/authored-alias-hooks.ts +0 -138
  339. package/src/internal/authored-loaders.ts +0 -188
  340. package/src/internal/bounded-int.ts +0 -24
  341. package/src/internal/bounded.ts +0 -25
  342. package/src/internal/brand.ts +0 -28
  343. package/src/internal/browser-origin-guard.ts +0 -67
  344. package/src/internal/builtin-tools/artifacts.ts +0 -62
  345. package/src/internal/builtin-tools/index.ts +0 -53
  346. package/src/internal/builtin-tools/reminders.ts +0 -145
  347. package/src/internal/channel-dispatch.ts +0 -129
  348. package/src/internal/channel-route-dispatch.ts +0 -58
  349. package/src/internal/channel-state.ts +0 -83
  350. package/src/internal/chat-client.ts +0 -594
  351. package/src/internal/cli-ax.ts +0 -2318
  352. package/src/internal/cli-bitbucket.ts +0 -438
  353. package/src/internal/cli-convert-automation.ts +0 -335
  354. package/src/internal/cli-cursor.ts +0 -282
  355. package/src/internal/cli-deploy.ts +0 -2519
  356. package/src/internal/cli-docs.ts +0 -192
  357. package/src/internal/cli-github.ts +0 -806
  358. package/src/internal/cli-gitlab.ts +0 -452
  359. package/src/internal/cli-images.ts +0 -672
  360. package/src/internal/cli-manifest.ts +0 -56
  361. package/src/internal/cli-mcp-oauth.ts +0 -396
  362. package/src/internal/cli-mcp.ts +0 -808
  363. package/src/internal/cli-skills.ts +0 -98
  364. package/src/internal/cli-slack-manual.ts +0 -418
  365. package/src/internal/cli-slack.ts +0 -874
  366. package/src/internal/cloud-merge.ts +0 -51
  367. package/src/internal/cloud-turn-cost.ts +0 -159
  368. package/src/internal/connection-env.ts +0 -106
  369. package/src/internal/continuation-channel.ts +0 -233
  370. package/src/internal/continuation-identity.ts +0 -935
  371. package/src/internal/conversation-mirror.ts +0 -423
  372. package/src/internal/convert-automation/convert-workflow.ts +0 -1377
  373. package/src/internal/convert-automation/slug.ts +0 -29
  374. package/src/internal/convert-automation/types.ts +0 -212
  375. package/src/internal/cron.ts +0 -76
  376. package/src/internal/cursor/account-mcp.ts +0 -692
  377. package/src/internal/cursor/backend-client.ts +0 -984
  378. package/src/internal/cursor/bound-secret-file.ts +0 -101
  379. package/src/internal/cursor/credentials.ts +0 -560
  380. package/src/internal/cursor/cursor-api-transport.ts +0 -65
  381. package/src/internal/cursor/github-credentials.ts +0 -228
  382. package/src/internal/cursor/hosted-bound-secrets.ts +0 -71
  383. package/src/internal/cursor/hosted-deployment-secrets.ts +0 -100
  384. package/src/internal/cursor/hosted-store-secrets.ts +0 -152
  385. package/src/internal/cursor/session-token.ts +0 -111
  386. package/src/internal/cursor/store-api-client.ts +0 -323
  387. package/src/internal/cursor-account-mcp-auth.ts +0 -303
  388. package/src/internal/cursor-agent-template.ts +0 -50
  389. package/src/internal/cursor-deployment-relay.ts +0 -315
  390. package/src/internal/cursor-event-relay.ts +0 -675
  391. package/src/internal/cursor-relay-core.ts +0 -563
  392. package/src/internal/deferred-channel-session.ts +0 -61
  393. package/src/internal/deploy-client.ts +0 -1574
  394. package/src/internal/deploy-manifest.ts +0 -361
  395. package/src/internal/deploy-source.ts +0 -144
  396. package/src/internal/describe-error.ts +0 -32
  397. package/src/internal/dev-mode.ts +0 -20
  398. package/src/internal/discovery/agent-config.ts +0 -288
  399. package/src/internal/discovery/agent.ts +0 -381
  400. package/src/internal/discovery/channels.ts +0 -100
  401. package/src/internal/discovery/connections.ts +0 -516
  402. package/src/internal/discovery/context.ts +0 -38
  403. package/src/internal/discovery/cursor-plugin.ts +0 -628
  404. package/src/internal/discovery/extension-overlay.ts +0 -247
  405. package/src/internal/discovery/extensions.ts +0 -490
  406. package/src/internal/discovery/fs.ts +0 -103
  407. package/src/internal/discovery/hooks.ts +0 -63
  408. package/src/internal/discovery/info.ts +0 -174
  409. package/src/internal/discovery/instructions.ts +0 -98
  410. package/src/internal/discovery/modules.ts +0 -107
  411. package/src/internal/discovery/names.ts +0 -45
  412. package/src/internal/discovery/project.ts +0 -319
  413. package/src/internal/discovery/reminders.ts +0 -65
  414. package/src/internal/discovery/runtime.ts +0 -158
  415. package/src/internal/discovery/schedules.ts +0 -120
  416. package/src/internal/discovery/seed-files.ts +0 -34
  417. package/src/internal/discovery/services.ts +0 -151
  418. package/src/internal/discovery/skills.ts +0 -174
  419. package/src/internal/discovery/subagent.ts +0 -138
  420. package/src/internal/discovery/tools.ts +0 -170
  421. package/src/internal/discovery.ts +0 -27
  422. package/src/internal/distribution.ts +0 -126
  423. package/src/internal/docs-site.ts +0 -248
  424. package/src/internal/duration.ts +0 -37
  425. package/src/internal/env-file.ts +0 -83
  426. package/src/internal/eval-judge-model.ts +0 -142
  427. package/src/internal/eval-run-store.ts +0 -585
  428. package/src/internal/eval-runner.ts +0 -823
  429. package/src/internal/evals-client.ts +0 -475
  430. package/src/internal/event-log.ts +0 -342
  431. package/src/internal/event-mapper.ts +0 -811
  432. package/src/internal/expected-delivery-failure.ts +0 -34
  433. package/src/internal/factory-resource-channel.ts +0 -103
  434. package/src/internal/filesystem/errors.ts +0 -207
  435. package/src/internal/filesystem/format.ts +0 -253
  436. package/src/internal/filesystem/merge.ts +0 -192
  437. package/src/internal/filesystem/nearest.ts +0 -112
  438. package/src/internal/filesystem/scratch.ts +0 -239
  439. package/src/internal/filesystem/sdk-schemas.ts +0 -204
  440. package/src/internal/filesystem/tools.ts +0 -804
  441. package/src/internal/filesystem/walk.ts +0 -366
  442. package/src/internal/fixtures/units-server.ts +0 -52
  443. package/src/internal/framework-file-storage.ts +0 -357
  444. package/src/internal/framework-storage-selection.ts +0 -156
  445. package/src/internal/frontmatter.ts +0 -108
  446. package/src/internal/github-fanout.ts +0 -144
  447. package/src/internal/guest-network.ts +0 -391
  448. package/src/internal/handleAgentServeTrigger.ts +0 -286
  449. package/src/internal/host-files.ts +0 -341
  450. package/src/internal/host-kv.ts +0 -81
  451. package/src/internal/host-otel.ts +0 -231
  452. package/src/internal/host-platforms.ts +0 -170
  453. package/src/internal/hosted-admission-adapter.ts +0 -47
  454. package/src/internal/hosted-admission-context.ts +0 -37
  455. package/src/internal/hosted-catch-protocol.ts +0 -112
  456. package/src/internal/hosted-catch.ts +0 -179
  457. package/src/internal/hosted-delivery-protocol.ts +0 -824
  458. package/src/internal/hosted-delivery.ts +0 -1410
  459. package/src/internal/hosted-execution-diag.ts +0 -291
  460. package/src/internal/hosted-execution-flush.ts +0 -136
  461. package/src/internal/hosted-execution-latency.ts +0 -301
  462. package/src/internal/hosted-managed-automation.ts +0 -116
  463. package/src/internal/hosting.ts +0 -114
  464. package/src/internal/http-channel-define.ts +0 -25
  465. package/src/internal/http-channel.ts +0 -669
  466. package/src/internal/http-control-plane-session.ts +0 -110
  467. package/src/internal/ids.ts +0 -39
  468. package/src/internal/incoming-headers-to-fetch.ts +0 -45
  469. package/src/internal/init-interview.ts +0 -360
  470. package/src/internal/init-project.ts +0 -711
  471. package/src/internal/init-scaffold.ts +0 -182
  472. package/src/internal/inline-stdio-define-stub.ts +0 -4
  473. package/src/internal/inline-stdio-mcp.ts +0 -230
  474. package/src/internal/install-cursor-skills.ts +0 -604
  475. package/src/internal/is-record.ts +0 -3
  476. package/src/internal/json-schema.ts +0 -95
  477. package/src/internal/legacy-command-guard.ts +0 -66
  478. package/src/internal/listen-port.ts +0 -85
  479. package/src/internal/local-control-plane.ts +0 -442
  480. package/src/internal/local-env.ts +0 -59
  481. package/src/internal/local-ingress.ts +0 -90
  482. package/src/internal/log-ring.ts +0 -59
  483. package/src/internal/logs-client.ts +0 -477
  484. package/src/internal/map-pool.ts +0 -39
  485. package/src/internal/mcp-endpoint.ts +0 -747
  486. package/src/internal/mcp-host.ts +0 -509
  487. package/src/internal/mcp-oauth-on-demand.ts +0 -337
  488. package/src/internal/mcp-oauth-persist.ts +0 -118
  489. package/src/internal/mcp-oauth.ts +0 -549
  490. package/src/internal/net.ts +0 -29
  491. package/src/internal/open-browser.ts +0 -41
  492. package/src/internal/otel/attrs.ts +0 -16
  493. package/src/internal/otel/collector.ts +0 -937
  494. package/src/internal/otel/config.ts +0 -287
  495. package/src/internal/otel/http.ts +0 -122
  496. package/src/internal/otel/mcp.ts +0 -56
  497. package/src/internal/otel/propagation.ts +0 -17
  498. package/src/internal/otel/runtime.ts +0 -441
  499. package/src/internal/package-inline-stdio.ts +0 -114
  500. package/src/internal/peer-connections.ts +0 -96
  501. package/src/internal/platform-schedule-sync.ts +0 -75
  502. package/src/internal/platform-timers.ts +0 -365
  503. package/src/internal/playground/static.ts +0 -278
  504. package/src/internal/playground/toolchain.ts +0 -270
  505. package/src/internal/playground-proxy.ts +0 -564
  506. package/src/internal/process-memory-telemetry.ts +0 -334
  507. package/src/internal/project-layout.ts +0 -31
  508. package/src/internal/prompt-context.ts +0 -116
  509. package/src/internal/reminder-control-plane-protocol.ts +0 -482
  510. package/src/internal/reminder-runner.ts +0 -1559
  511. package/src/internal/reminder-schedule.ts +0 -104
  512. package/src/internal/reminder-store.ts +0 -176
  513. package/src/internal/request-error-status.ts +0 -95
  514. package/src/internal/request-headers.ts +0 -21
  515. package/src/internal/resolve-prod-target.ts +0 -334
  516. package/src/internal/resolved-connections.ts +0 -190
  517. package/src/internal/router.ts +0 -143
  518. package/src/internal/run-client.ts +0 -354
  519. package/src/internal/runtime-dispatch-runner.ts +0 -50
  520. package/src/internal/sanitize-mcp-tool-name.ts +0 -31
  521. package/src/internal/schedule-runner.ts +0 -154
  522. package/src/internal/scm/pr-url.ts +0 -245
  523. package/src/internal/sdk-runner.ts +0 -959
  524. package/src/internal/serve-restart.ts +0 -113
  525. package/src/internal/server.ts +0 -3147
  526. package/src/internal/session-cost.ts +0 -208
  527. package/src/internal/session-engine.ts +0 -5622
  528. package/src/internal/session-links.ts +0 -84
  529. package/src/internal/session-run-log.ts +0 -535
  530. package/src/internal/session-store.ts +0 -307
  531. package/src/internal/session-urls.ts +0 -32
  532. package/src/internal/sessions-client.ts +0 -239
  533. package/src/internal/skill-catalog.ts +0 -66
  534. package/src/internal/skills-sync.ts +0 -55
  535. package/src/internal/slack-provision-client.ts +0 -544
  536. package/src/internal/slack-thread-key.ts +0 -11
  537. package/src/internal/sleep.ts +0 -3
  538. package/src/internal/start-log-store.ts +0 -164
  539. package/src/internal/steering.ts +0 -17
  540. package/src/internal/storage-coordinator.ts +0 -800
  541. package/src/internal/storage-roles.ts +0 -86
  542. package/src/internal/storage.ts +0 -1
  543. package/src/internal/store-api-protocol.ts +0 -205
  544. package/src/internal/store-mirror.ts +0 -73
  545. package/src/internal/stream-progress.ts +0 -294
  546. package/src/internal/terminal-style.ts +0 -133
  547. package/src/internal/testing/factory-resource-fixtures.ts +0 -84
  548. package/src/internal/testing/scm-continuation-fixtures.ts +0 -285
  549. package/src/internal/tool-catalog.ts +0 -104
  550. package/src/internal/tool-policy.ts +0 -222
  551. package/src/internal/tool-result.ts +0 -50
  552. package/src/internal/trajectory.ts +0 -418
  553. package/src/internal/turn-cost.ts +0 -136
  554. package/src/internal/turn-governor.ts +0 -145
  555. package/src/internal/turn-lease-store.ts +0 -144
  556. package/src/internal/turn-outbox.ts +0 -77
  557. package/src/internal/update-check.ts +0 -517
  558. package/src/internal/v2-hosting.ts +0 -52
  559. package/src/internal/workspace-sync.ts +0 -114
  560. package/src/internal/workspace.ts +0 -505
  561. package/src/kv/memory-kv.ts +0 -94
  562. package/src/kv.ts +0 -18
  563. package/src/memory.ts +0 -487
  564. package/src/otel-public.ts +0 -24
  565. package/src/otel.ts +0 -320
  566. package/src/prompt.ts +0 -80
  567. package/src/reminders.ts +0 -65
  568. package/src/schedules.ts +0 -31
  569. package/src/skills.ts +0 -27
  570. package/src/storage-backends/cursor-hosted-v2.ts +0 -204
  571. package/src/storage-backends/cursor-hosted.ts +0 -388
  572. package/src/storage-backends/file-kv.ts +0 -276
  573. package/src/storage-protocol.ts +0 -261
  574. package/src/storage.ts +0 -408
  575. package/src/tools.ts +0 -166
  576. package/src/types.ts +0 -3776
  577. /package/dist/docs/assets/{reference_agent-config.md.DzGI777n.lean.js → reference_agent-config.md.Cj5uBKp4.lean.js} +0 -0
@@ -1,959 +0,0 @@
1
- /**
2
- * Executes turns on the Cursor harness through `@cursor/sdk`.
3
- * Each framework session maps 1:1 to an SDK agent. Local agents use the
4
- * session id as the SDK agent id and materialize a workspace for project
5
- * settings; cloud agents use Cursor cloud (`bc-…` ids) with optional
6
- * `cloud` options from `defineAgent`.
7
- */
8
-
9
- import { mkdir } from "node:fs/promises";
10
- import {
11
- Agent,
12
- type AgentDefinition,
13
- type AgentOptions,
14
- type CloudAgentOptions,
15
- Cursor,
16
- createAgentPlatform,
17
- type LocalAgentStore,
18
- type ModelSelection,
19
- type Run,
20
- type RunResult,
21
- type SDKAgent,
22
- } from "@cursor/sdk";
23
- import { SqliteLocalAgentStore } from "@cursor/sdk/sqlite";
24
- import {
25
- DEFAULT_MODEL,
26
- type ModelSetting,
27
- type RunnerSubagent,
28
- type RunnerTurnRequest,
29
- type TurnOutcome,
30
- type TurnUsage,
31
- } from "../types.js";
32
- import { mapSdkTokenUsage, usageTokenSum } from "./cloud-turn-cost.js";
33
- import type { ConversationMirror } from "./conversation-mirror.js";
34
- import { resolveApiKeySync } from "./cursor/credentials.js";
35
- import { describeError } from "./describe-error.js";
36
- import { CLI_COMMAND_NAME as CLI } from "./distribution.js";
37
- import { sleep } from "./sleep.js";
38
-
39
- /** Mirrors @cursor/sdk's SteerAckOutcome; the published dist may predate it. */
40
- export type SteerAckOutcome = "complete_delivered" | "revert_to_followup";
41
-
42
- /** Internal seam between the session engine and the Cursor SDK harness. */
43
- export interface AgentRunner {
44
- runTurn(request: RunnerTurnRequest): Promise<TurnOutcome>;
45
- steer?(request: { sessionId: string; text: string }): Promise<SteerAckOutcome>;
46
- /**
47
- * Resolve a local workspace before any session needs it, so the first turn
48
- * is not the one that pays for it. Best effort, hence the reported outcome:
49
- * a runner that cannot warm must say so rather than let a caller log
50
- * success over a workspace that was never touched.
51
- */
52
- prewarm?(request: RunnerPrewarmRequest): Promise<PrewarmOutcome>;
53
- dispose?(): Promise<void>;
54
- }
55
-
56
- /**
57
- * The parts of a turn that decide which local executor it runs on. Must stay
58
- * a subset of {@link RunnerTurnRequest} — anything that disagrees warms an
59
- * executor no turn will ask for.
60
- */
61
- export type RunnerPrewarmRequest = Pick<
62
- RunnerTurnRequest,
63
- | "workspaceDir"
64
- | "runnerStateDir"
65
- | "sandbox"
66
- | "tools"
67
- | "disallowedTools"
68
- | "mcpServers"
69
- | "perSendMcpServers"
70
- | "subagents"
71
- | "model"
72
- >;
73
-
74
- /** Whether a workspace was actually resolved, and why not when it wasn't. */
75
- export type PrewarmOutcome =
76
- | { readonly warmed: true }
77
- | { readonly warmed: false; readonly reason: string };
78
-
79
- /**
80
- * How long a non-`--dev` serve holds workspace scans (rules, skills,
81
- * `AGENTS.md`, ignore files). The SDK default is 20s for an editor whose
82
- * files move under it; agent-serve checkouts only change on deploy, so a
83
- * missed mid-process edit is the right trade. `CURSOR_RIPWALK_CACHE_TTL_MS`
84
- * still wins when set. `--dev` leaves the 20s default so skill edits show up.
85
- */
86
- export const SERVE_WORKSPACE_SCAN_CACHE_TTL_MS: number = 24 * 60 * 60 * 1000;
87
-
88
- /**
89
- * Resolve the SDK workspace-scan TTL for this serve. `undefined` means "do
90
- * not call `Cursor.configure`" and leave the SDK at its 20s editor default.
91
- */
92
- export function resolveServeWorkspaceScanCacheTtlMs(args: {
93
- dev: boolean;
94
- env?: NodeJS.ProcessEnv;
95
- }): number | undefined {
96
- const raw = (args.env ?? process.env).CURSOR_RIPWALK_CACHE_TTL_MS?.trim();
97
- if (raw !== undefined && raw !== "") {
98
- const parsed = Number(raw);
99
- if (Number.isFinite(parsed) && parsed > 0) {
100
- return parsed;
101
- }
102
- }
103
- if (args.dev) {
104
- return undefined;
105
- }
106
- return SERVE_WORKSPACE_SCAN_CACHE_TTL_MS;
107
- }
108
-
109
- export interface CursorSdkRunnerOptions {
110
- /** Cursor API key. Defaults to the `CURSOR_API_KEY` environment variable. */
111
- apiKey?: string;
112
- /**
113
- * Conversation store override. Defaults to a JSONL store under the
114
- * engine's state root; install `sqlite3` and pass an SQLite-backed
115
- * `LocalAgentStore` for heavy multi-session concurrency.
116
- */
117
- store?: LocalAgentStore;
118
- /**
119
- * Durable mirror for local conversations (v2 hosted engines). Hydrated
120
- * before `Agent.resume` so a follow-up landing on a fresh pod finds the
121
- * conversation, and persisted — awaited — after each local turn settles,
122
- * because a hosted pod can be parked right after the execution reply.
123
- */
124
- conversationMirror?: ConversationMirror;
125
- /** Diagnostics for degraded paths (resume-miss fallback). */
126
- logger?: (line: string) => void;
127
- /**
128
- * Hold workspace scans this long (ms). Applied via `Cursor.configure` so
129
- * each new local executor reuses the walk. Omit to keep the SDK 20s default.
130
- */
131
- workspaceScanCacheTtlMs?: number;
132
- }
133
-
134
- /**
135
- * How long one SDK agent handle (and the Connect transport inside it) may be
136
- * reused before the runner retires it.
137
- *
138
- * The transport exchanges the account API key for a short-lived access token
139
- * (`SessionType.API_KEY_TOKEN`, 60 minutes) once per handle, and has no
140
- * reliable refresh: an Unauthenticated rejection on the agent's streaming RPC
141
- * surfaces while the stream is being read — outside the transport's
142
- * request-time 401 retry — so an expired token gets replayed on every
143
- * subsequent turn until the handle is rebuilt. Long-lived sessions (watch
144
- * wakes, crons) hit this at the ~60 minute mark and then fail forever.
145
- * Retiring the handle comfortably before the token can expire keeps them
146
- * healthy: `Agent.resume` rehydrates the same conversation from the runner
147
- * store on a fresh transport, so recycling costs only transport warmth.
148
- */
149
- const MAX_AGENT_HANDLE_AGE_MS = 45 * 60 * 1000;
150
-
151
- interface CachedAgentHandle {
152
- agent: Promise<SDKAgent>;
153
- openedAtMs: number;
154
- }
155
-
156
- /**
157
- * The backend's `NotLoggedIn` copy ("Authentication error" title, "try
158
- * logging out and back in." detail) as it surfaces through SDK RunResults.
159
- * Deliberately narrow: this gates a one-shot in-place retry, and matching
160
- * broader error text would retry turns that a fresh transport cannot fix.
161
- */
162
- export function isAuthErrorMessage(message: string | undefined): boolean {
163
- if (message === undefined) {
164
- return false;
165
- }
166
- return /authentication error|try logging out and back in/i.test(message);
167
- }
168
-
169
- /** Cloud `wait()` copy for `stream_expired` / a missing start-state blob. */
170
- function isStreamExpiredErrorMessage(message: string | undefined): boolean {
171
- if (message === undefined) {
172
- return false;
173
- }
174
- return /run stream is no longer available|\[stream_expired\]/i.test(message);
175
- }
176
-
177
- function retryReason(message: string | undefined, isFirstTurn: boolean): string | undefined {
178
- if (isStreamExpiredErrorMessage(message)) {
179
- return "cloud run stream expired";
180
- }
181
- // First-turn auth is the credential; a fresh handle cannot fix it.
182
- if (!isFirstTurn && isAuthErrorMessage(message)) {
183
- return "authentication failure";
184
- }
185
- return undefined;
186
- }
187
-
188
- /**
189
- * The SDK rejects a selection the credential's catalog does not list with
190
- * this copy, thrown from `Agent.create` / `Agent.resume` before the turn
191
- * streams anything. Matched on the message because the SDK uses its generic
192
- * configuration error here.
193
- */
194
- export function isUnavailableModelSelectionMessage(message: string | undefined): boolean {
195
- return message !== undefined && /cannot use this model/i.test(message);
196
- }
197
-
198
- export function isUnavailableModelSelectionError(error: unknown): boolean {
199
- const message = error instanceof Error ? error.message : undefined;
200
- return isUnavailableModelSelectionMessage(message);
201
- }
202
-
203
- /**
204
- * Inference / provider capacity on the selected model. `wait()` stores the
205
- * connect status on `error.code` and strips `[code]` from the message, so
206
- * both must be checked. `[unavailable]` in text is the connect status, not
207
- * a loose "temporarily unavailable" substring.
208
- */
209
- export function isModelCapacityError(
210
- message: string | undefined,
211
- code?: string | undefined,
212
- ): boolean {
213
- if (isGithubApiRateLimitMessage(message)) {
214
- return false;
215
- }
216
- if (code !== undefined && /^(resource_exhausted|unavailable)$/i.test(code)) {
217
- return true;
218
- }
219
- return message !== undefined && /resource_exhausted|\[unavailable\]/i.test(message);
220
- }
221
-
222
- /** GitHub token 429s share `resource_exhausted` with model capacity. */
223
- export function isGithubApiRateLimitMessage(message: string | undefined): boolean {
224
- if (message === undefined) {
225
- return false;
226
- }
227
- return /github/i.test(message) && /(rate limit|\b429\b)/i.test(message);
228
- }
229
-
230
- export function isModelCapacityErrorMessage(message: string | undefined): boolean {
231
- return isModelCapacityError(message);
232
- }
233
-
234
- /** Catalog refusal or capacity: the authored fallback list can still save the turn. */
235
- export function shouldFallbackToNextModel(
236
- message: string | undefined,
237
- code?: string | undefined,
238
- ): boolean {
239
- return isUnavailableModelSelectionMessage(message) || isModelCapacityError(message, code);
240
- }
241
-
242
- export function shouldFallbackToNextModelOnError(error: unknown): boolean {
243
- const message = error instanceof Error ? error.message : undefined;
244
- return shouldFallbackToNextModel(message, errorCodeOf(error));
245
- }
246
-
247
- function errorCodeOf(error: unknown): string | undefined {
248
- if (typeof error !== "object" || error === null || !("code" in error)) {
249
- return undefined;
250
- }
251
- const code = (error as { code?: unknown }).code;
252
- return typeof code === "string" ? code : undefined;
253
- }
254
-
255
- function modelSettingLabel(model: ModelSetting | undefined): string {
256
- if (model === undefined) {
257
- return "default";
258
- }
259
- return typeof model === "string" ? model : model.id;
260
- }
261
-
262
- /** Primary model, then authored fallbacks. No fallbacks keeps today's single attempt. */
263
- function modelAttemptChain(request: RunnerTurnRequest): Array<ModelSetting | undefined> {
264
- const fallbacks = request.modelFallbacks ?? [];
265
- if (fallbacks.length === 0) {
266
- return [request.model];
267
- }
268
- return [request.model ?? DEFAULT_MODEL, ...fallbacks];
269
- }
270
-
271
- /**
272
- * A rejected create may already have stored the agent id. Later attempts
273
- * resume that id so the next model does not die on "already exists". A
274
- * create that threw before persisting falls through the runner's not-found
275
- * path and creates again. Cloud turns that never received a server id stay
276
- * on create: resuming the framework session id is not a cloud agent.
277
- */
278
- function modelAttemptRequest(
279
- request: RunnerTurnRequest,
280
- model: ModelSetting | undefined,
281
- attempt: number,
282
- ): RunnerTurnRequest {
283
- if (attempt === 0) {
284
- return model === request.model ? request : { ...request, model };
285
- }
286
- const persistedId = request.sdkAgentId ?? request.sessionId;
287
- if (
288
- request.runtime === "cloud" &&
289
- request.isFirstTurn &&
290
- !isServerMintedCloudAgentId(persistedId)
291
- ) {
292
- return { ...request, model };
293
- }
294
- return {
295
- ...request,
296
- model,
297
- isFirstTurn: false,
298
- sdkAgentId: persistedId,
299
- };
300
- }
301
-
302
- export class CursorSdkRunner implements AgentRunner {
303
- private readonly agents = new Map<string, CachedAgentHandle>();
304
- private readonly activeRuns = new Map<string, Run>();
305
- private readonly stores = new Map<string, Promise<LocalAgentStore>>();
306
- private readonly prewarmReleases: Array<() => Promise<void>> = [];
307
-
308
- constructor(private readonly options: CursorSdkRunnerOptions = {}) {
309
- if (options.workspaceScanCacheTtlMs !== undefined) {
310
- Cursor.configure({
311
- local: { workspaceScanCacheTtlMs: options.workspaceScanCacheTtlMs },
312
- });
313
- this.log(`[agent-sdk] workspace scan cache ttl=${options.workspaceScanCacheTtlMs}ms`);
314
- }
315
- }
316
-
317
- async runTurn(request: RunnerTurnRequest): Promise<TurnOutcome> {
318
- // Fail closed: this runner only knows the Cursor SDK's local and cloud
319
- // harnesses. A grokbot turn reaching it means the serve wiring skipped
320
- // the Grok Bot runner — running it on the local harness would silently
321
- // swap the box (and the SendToUser contract) out from under the agent.
322
- if (request.runtime === "grokbot") {
323
- throw new Error(
324
- `Session ${request.sessionId} is a grokbot turn, which the Cursor SDK runner cannot execute. Serve must route grokbot turns to the Grok Bot runner.`,
325
- );
326
- }
327
- const models = modelAttemptChain(request);
328
- let lastError: unknown;
329
- for (let attempt = 0; attempt < models.length; attempt++) {
330
- const model = models[attempt];
331
- let streamed = false;
332
- const attemptRequest = modelAttemptRequest(request, model, attempt);
333
- try {
334
- const outcome = await this.runTurnWithTransportRetry(attemptRequest, () => {
335
- streamed = true;
336
- });
337
- if (
338
- outcome.status !== "error" ||
339
- streamed ||
340
- request.signal?.aborted === true ||
341
- !shouldFallbackToNextModel(outcome.errorMessage, outcome.errorCode) ||
342
- attempt === models.length - 1
343
- ) {
344
- return outcome;
345
- }
346
- this.logModelFallback(request.sessionId, model, models[attempt + 1], outcome.errorMessage);
347
- } catch (error) {
348
- lastError = error;
349
- if (
350
- streamed ||
351
- request.signal?.aborted === true ||
352
- !shouldFallbackToNextModelOnError(error) ||
353
- attempt === models.length - 1
354
- ) {
355
- throw error;
356
- }
357
- const message = error instanceof Error ? error.message : undefined;
358
- this.logModelFallback(request.sessionId, model, models[attempt + 1], message);
359
- }
360
- }
361
- throw lastError;
362
- }
363
-
364
- /**
365
- * One model attempt, plus the existing in-place transport retry (expired
366
- * cloud stream, or a follow-up auth failure) on that same model. Model
367
- * fallback is the caller's job: this returns the error outcome when a
368
- * fresh handle cannot fix it.
369
- */
370
- private async runTurnWithTransportRetry(
371
- request: RunnerTurnRequest,
372
- onStreamed: () => void,
373
- ): Promise<TurnOutcome> {
374
- let sawUpdate = false;
375
- const tracked: RunnerTurnRequest = {
376
- ...request,
377
- onUpdate: update => {
378
- sawUpdate = true;
379
- onStreamed();
380
- return request.onUpdate(update);
381
- },
382
- };
383
- const outcome = await this.runTurnAttempt(tracked);
384
- if (outcome.status !== "error" || sawUpdate || request.signal?.aborted === true) {
385
- return outcome;
386
- }
387
- const reason = retryReason(outcome.errorMessage, request.isFirstTurn);
388
- if (reason === undefined) {
389
- return outcome;
390
- }
391
- // Log the original error even when the retry succeeds so the expiry
392
- // still shows up in Datadog.
393
- this.log(
394
- `[agent-sdk] session ${request.sessionId}: ${reason}: ${outcome.errorMessage}; retrying the turn`,
395
- );
396
- try {
397
- return await this.runTurnAttempt(tracked);
398
- } catch {
399
- return outcome;
400
- }
401
- }
402
-
403
- private logModelFallback(
404
- sessionId: string,
405
- from: ModelSetting | undefined,
406
- to: ModelSetting | undefined,
407
- message: string | undefined,
408
- ): void {
409
- this.log(
410
- `[agent-sdk] session ${sessionId}: cannot use model ${modelSettingLabel(from)}; retrying on ${modelSettingLabel(to)}: ${message ?? "model unavailable"}`,
411
- );
412
- }
413
-
414
- private async runTurnAttempt(request: RunnerTurnRequest): Promise<TurnOutcome> {
415
- const agentPromise = this.getAgent(request);
416
- try {
417
- const agent = await agentPromise;
418
- const sendMessage =
419
- request.images !== undefined && request.images.length > 0
420
- ? {
421
- text: request.prompt,
422
- images: request.images.map(image => ({
423
- data: image.data,
424
- mimeType: image.mimeType,
425
- })),
426
- }
427
- : request.prompt;
428
- const run = await agent.send(sendMessage, {
429
- onDelta: async ({ update }) => {
430
- try {
431
- await request.onUpdate(update);
432
- } catch {
433
- // Stream mapping must never reject into the SDK transport.
434
- }
435
- },
436
- // The SDK builds this send's MCP session from exactly this set, so
437
- // a turn always runs on the headers the engine evaluated for it —
438
- // never on the ones a previous turn opened the cached handle with.
439
- ...(request.runtime === "local" && request.perSendMcpServers === true
440
- ? { mcpServers: request.mcpServers as AgentOptions["mcpServers"] }
441
- : {}),
442
- ...(request.runtime === "local"
443
- ? {
444
- local: {
445
- customTools: request.customTools,
446
- // Follow-up turns expire any run still marked active on the
447
- // agent (a preempted or crash-wedged run) so this send is not
448
- // rejected with "already has active run".
449
- ...(request.forceExpireActiveRun === true ? { force: true } : {}),
450
- },
451
- }
452
- : {}),
453
- });
454
- // A follow-up can preempt this turn: cancelling tears down execution and
455
- // marks the SDK run terminal so the next send is admitted cleanly. The
456
- // signal may already be aborted if the preempt landed while send() was
457
- // still creating the run.
458
- const signal = request.signal;
459
- const onAbort = (): void => {
460
- void run.cancel().catch(() => {});
461
- };
462
- if (signal !== undefined) {
463
- if (signal.aborted) {
464
- onAbort();
465
- } else {
466
- signal.addEventListener("abort", onAbort, { once: true });
467
- }
468
- }
469
- // Cloud + envVars: server mints the real `bc-…` id during createAgent
470
- // inside the first send. Bind only after that so we never persist/print
471
- // the provisional client-seeded id.
472
- if (request.onSdkAgentId !== undefined) {
473
- await request.onSdkAgentId(agent.agentId);
474
- }
475
- // Readable on the handle as soon as send resolves, long before wait().
476
- if (
477
- request.onRequestId !== undefined &&
478
- run.requestId !== undefined &&
479
- run.requestId !== ""
480
- ) {
481
- await request.onRequestId(run.requestId);
482
- }
483
- this.activeRuns.set(request.sessionId, run);
484
- try {
485
- const result = await run.wait();
486
- let outcome = toTurnOutcome(result);
487
- if (outcome.status === "error") {
488
- // An error result usually means the handle's transport is poisoned
489
- // — most often a cached access token that aged past its 60-minute
490
- // lifetime and gets replayed on every request (stream failures
491
- // bypass the transport's 401 retry). Retire the handle so the next
492
- // attempt resumes the conversation from the store on a fresh
493
- // transport instead of failing every turn until a restart.
494
- this.evictAgent(request.sessionId, agentPromise);
495
- } else if (
496
- request.runtime === "cloud" &&
497
- outcome.status === "finished" &&
498
- usageTokenSum(outcome.usage) <= 0 &&
499
- result.id !== ""
500
- ) {
501
- // Cloud `wait()` drops usage after stream reconnect / getRun replay,
502
- // or returns an all-zero stub. `getUsage` still has the run's tokens
503
- // (eventually); without them traces never record an estimated cost.
504
- outcome = await fillMissingCloudUsage(agent, result.id, outcome);
505
- }
506
- return outcome;
507
- } finally {
508
- if (this.activeRuns.get(request.sessionId) === run) {
509
- this.activeRuns.delete(request.sessionId);
510
- }
511
- signal?.removeEventListener("abort", onAbort);
512
- // Mirror the conversation before replying: on hosted v2 the pod can
513
- // be parked as soon as the execution reply lands, so a
514
- // fire-and-forget write would race VM teardown. In the `finally` so
515
- // a `wait()` that THROWS (transport death mid-turn, an abort with
516
- // no follow-up) still persists the checkpoints the turn already
517
- // wrote — the store is local SQLite, safe to read on the throw
518
- // path, and persistConversation swallows its own errors. Guarded
519
- // here (not just inside the helper) so unmirrored turns keep their
520
- // exact post-wait sequencing.
521
- if (request.runtime === "local" && this.options.conversationMirror !== undefined) {
522
- await this.persistConversation(request, agent.agentId);
523
- }
524
- }
525
- } catch (error) {
526
- // Drop the cached agent so a dead Connect/HTTP2 session cannot poison
527
- // the next turn (terminal/shell overflow often kills the transport).
528
- this.evictAgent(request.sessionId, agentPromise);
529
- throw error;
530
- }
531
- }
532
-
533
- async steer(request: { sessionId: string; text: string }): Promise<SteerAckOutcome> {
534
- const run = this.activeRuns.get(request.sessionId) as
535
- | (Run & {
536
- steer?: (text: string) => Promise<SteerAckOutcome>;
537
- })
538
- | undefined;
539
- if (run?.steer === undefined) {
540
- return "revert_to_followup";
541
- }
542
- try {
543
- return await run.steer(request.text);
544
- } catch (error) {
545
- this.log(`[agent-sdk] session ${request.sessionId}: steer failed: ${describeError(error)}`);
546
- return "revert_to_followup";
547
- }
548
- }
549
-
550
- /**
551
- * Build the local executor for a workspace before any session asks for it.
552
- * The warmed executor is reference counted, so the lease is held until
553
- * {@link dispose}; dropping it early would tear the workspace back down.
554
- */
555
- async prewarm(request: RunnerPrewarmRequest): Promise<PrewarmOutcome> {
556
- const platform = await createAgentPlatform();
557
- const release = await platform.prewarmLocalWorkspace(await this.buildLocalOptions(request));
558
- this.prewarmReleases.push(release);
559
- return { warmed: true };
560
- }
561
-
562
- /**
563
- * Drop the cached SDK agent for this session, if one is open.
564
- *
565
- * Hosted v2 parks and hibernates this process as soon as the execution
566
- * reply lands on non-interactive channels. A leftover handle still holds
567
- * the pre-freeze Connect/HTTP2 session; the next wake then reuses it and
568
- * `AgentService/Run` never starts. Call after `waitForCompletion` so the
569
- * hibernate snapshot has an empty cache. Slack's interactive hot-window
570
- * still reuses handles because that path does not go through hosted
571
- * delivery.
572
- */
573
- evictSession(sessionId: string): void {
574
- const cached = this.agents.get(sessionId);
575
- if (cached === undefined) {
576
- return;
577
- }
578
- this.evictAgent(sessionId, cached.agent);
579
- }
580
-
581
- async dispose(): Promise<void> {
582
- const releases = this.prewarmReleases.splice(0);
583
- await Promise.allSettled(releases.map(release => release()));
584
- const agents = await Promise.allSettled([...this.agents.values()].map(handle => handle.agent));
585
- this.agents.clear();
586
- for (const settled of agents) {
587
- if (settled.status === "fulfilled") {
588
- settled.value.close();
589
- }
590
- }
591
- }
592
-
593
- private getAgent(request: RunnerTurnRequest): Promise<SDKAgent> {
594
- const cached = this.agents.get(request.sessionId);
595
- if (cached !== undefined) {
596
- const ageMs = Date.now() - cached.openedAtMs;
597
- if (ageMs < MAX_AGENT_HANDLE_AGE_MS) {
598
- return cached.agent;
599
- }
600
- // Past this age the handle's exchanged access token could expire
601
- // mid-turn. Retire it and reopen below on a fresh transport.
602
- this.log(
603
- `[agent-sdk] session ${request.sessionId}: recycling the SDK agent handle after ${Math.round(ageMs / 60_000)} min so the turn runs on a fresh access token`,
604
- );
605
- this.evictAgent(request.sessionId, cached.agent);
606
- }
607
- const agentPromise = this.openAgent(request).catch(error => {
608
- // Nothing opened, so there is no handle to close — just free the slot.
609
- this.agents.delete(request.sessionId);
610
- throw error;
611
- });
612
- this.agents.set(request.sessionId, {
613
- agent: agentPromise,
614
- openedAtMs: Date.now(),
615
- });
616
- return agentPromise;
617
- }
618
-
619
- /**
620
- * Drop a cached handle and close it best-effort to release its transport
621
- * and executor lease. Identity-checked so a turn that lost a race with a
622
- * newer open cannot evict the replacement handle.
623
- */
624
- private evictAgent(sessionId: string, agent: Promise<SDKAgent>): void {
625
- const cached = this.agents.get(sessionId);
626
- if (cached === undefined || cached.agent !== agent) {
627
- return;
628
- }
629
- this.agents.delete(sessionId);
630
- void cached.agent.then(sdkAgent => sdkAgent.close()).catch(() => {});
631
- }
632
-
633
- private log(line: string): void {
634
- (this.options.logger ?? (() => {}))(line);
635
- }
636
-
637
- /**
638
- * Re-resolve on every turn. Hosted freeze snapshots listen unsigned; the
639
- * binder drops `CURSOR_API_KEY` / `CURSOR_API_KEY_FILE` at task time into
640
- * the already-running process, which must not have closed over `undefined`.
641
- */
642
- private requireApiKey(): string {
643
- const resolved = resolveApiKeySync({ apiKey: this.options.apiKey });
644
- if (resolved === undefined) {
645
- throw new Error(
646
- `The Cursor SDK runner requires a Cursor credential: run \`${CLI} login\`, set CURSOR_API_KEY, CURSOR_SERVICE_ACCOUNT_KEY, or CURSOR_API_KEY_FILE, or pass serve({ apiKey }).`,
647
- );
648
- }
649
- return resolved.apiKey;
650
- }
651
-
652
- private buildSharedOptions(
653
- request: RunnerPrewarmRequest,
654
- ): Pick<AgentOptions, "model" | "apiKey" | "mcpServers" | "agents"> {
655
- const subagents = toAgentDefinitions(request.subagents);
656
- return {
657
- model: toModelSelection(request.model ?? DEFAULT_MODEL),
658
- apiKey: this.requireApiKey(),
659
- // Per-send servers ride each agent.send instead (fresh per-session
660
- // auth headers every turn). Keeping them out of the create/resume
661
- // options also keeps the local executor cache key — which hashes
662
- // these options — stable while credentials rotate.
663
- ...(Object.keys(request.mcpServers).length > 0 && request.perSendMcpServers !== true
664
- ? { mcpServers: request.mcpServers as AgentOptions["mcpServers"] }
665
- : {}),
666
- ...(subagents === undefined ? {} : { agents: subagents }),
667
- };
668
- }
669
-
670
- /**
671
- * The options that decide which local executor a turn runs on. Prewarming
672
- * goes through here too, so a warmed workspace is the one turns land on.
673
- */
674
- private async buildLocalOptions(
675
- request: RunnerPrewarmRequest & Pick<RunnerTurnRequest, "instructions">,
676
- ): Promise<AgentOptions> {
677
- // Not resolveStore: an injected store is used synchronously (no
678
- // microtask, no thenable assimilation), exactly as before the mirror
679
- // existed.
680
- const store = this.options.store ?? (await this.getStore(request.runnerStateDir));
681
- return {
682
- ...this.buildSharedOptions(request),
683
- // The built-in tool allowlist rides AgentOptions, not `local`, and is
684
- // deliberately absent from openCloudAgent's options: the SDK rejects
685
- // tool restrictions on cloud agents. Passed on create *and* resume
686
- // (both flow through here) — the SDK does not persist it across runs.
687
- ...(request.tools === undefined ? {} : { tools: request.tools }),
688
- ...(request.disallowedTools === undefined
689
- ? {}
690
- : { disallowedTools: request.disallowedTools }),
691
- // Same shape: local-only (the SDK rejects it with `cloud`), not
692
- // persisted, so it rides every create/resume. Replaces Cursor's
693
- // built-in system prompt with the agent's composed instructions.
694
- // Prewarm requests carry none, and the SDK's workspace cache key
695
- // ignores it, so a warmed executor is still the one turns land on.
696
- systemPrompt: request.instructions,
697
- local: {
698
- cwd: request.workspaceDir,
699
- settingSources: ["project"],
700
- store,
701
- ...(request.sandbox === true ? { sandboxOptions: { enabled: true } } : {}),
702
- },
703
- };
704
- }
705
-
706
- private async openAgent(request: RunnerTurnRequest): Promise<SDKAgent> {
707
- if (request.runtime === "cloud") {
708
- return this.openCloudAgent(request, this.buildSharedOptions(request));
709
- }
710
- return this.openLocalAgent(request);
711
- }
712
-
713
- private async openLocalAgent(request: RunnerTurnRequest): Promise<SDKAgent> {
714
- const options = await this.buildLocalOptions(request);
715
-
716
- if (request.isFirstTurn || request.sdkAgentId === undefined) {
717
- return Agent.create({
718
- ...options,
719
- agentId: request.sdkAgentId ?? request.sessionId,
720
- });
721
- }
722
-
723
- const agentId = request.sdkAgentId ?? request.sessionId;
724
- const mirror = this.options.conversationMirror;
725
- if (mirror !== undefined) {
726
- // Host replacement: restore the conversation from the durable mirror
727
- // before resuming, so the thread continues instead of starting fresh.
728
- // A sink failure propagates and fails the turn (retryable) — reading
729
- // an outage as "nothing mirrored" would silently fork the thread.
730
- const store = await this.resolveStore(request);
731
- await mirror.hydrate(store, agentId);
732
- }
733
- try {
734
- return await Agent.resume(agentId, options);
735
- } catch (error) {
736
- if (!isLocalAgentNotFoundError(error, agentId)) {
737
- throw error;
738
- }
739
- // Host replacement: the session record survived in durable storage,
740
- // but the conversation store died with the old pod. A fresh
741
- // conversation under the same id beats failing this thread's turns
742
- // forever ("Agent … not found" on every follow-up). The channel's
743
- // warm-turn prompt context re-hydrates the thread history.
744
- this.log(
745
- `[agent-sdk] no stored conversation for ${agentId} on this host; starting a fresh one`,
746
- );
747
- return Agent.create({ ...options, agentId });
748
- }
749
- }
750
-
751
- private async openCloudAgent(
752
- request: RunnerTurnRequest,
753
- shared: Pick<AgentOptions, "model" | "apiKey" | "mcpServers" | "agents">,
754
- ): Promise<SDKAgent> {
755
- const cloud = toCloudAgentOptions(request.cloud, request.agentServeAgent);
756
- const hasEnvVars = cloud.envVars !== undefined && Object.keys(cloud.envVars).length > 0;
757
- const options: AgentOptions = {
758
- ...shared,
759
- cloud,
760
- };
761
-
762
- const sdkAgentId = request.sdkAgentId?.trim();
763
- if (sdkAgentId !== undefined && sdkAgentId !== "") {
764
- // A server-minted `bc-…` id always resumes — including on the first
765
- // framework turn of a session seeded via SendMessageOptions.sdkAgentId
766
- // (PR→bcId affinity across session-store resets). Any persisted id
767
- // resumes on later turns.
768
- if (isServerMintedCloudAgentId(sdkAgentId) || !request.isFirstTurn) {
769
- return Agent.resume(sdkAgentId, options);
770
- }
771
- if (!hasEnvVars) {
772
- // Client-seeded (non bc-…) id on a brand new session: forward it to
773
- // create so the server adopts it. With envVars the server must mint
774
- // the id, so the seed cannot be honored and create() runs below.
775
- return Agent.create({ ...options, agentId: sdkAgentId });
776
- }
777
- }
778
-
779
- if (request.isFirstTurn) {
780
- return Agent.create(options);
781
- }
782
- // A cloud session past its first turn should carry the bound agent id
783
- // (the engine persists it via onSdkAgentId as soon as create() reports
784
- // one). Reaching here means the binding turn failed before the server
785
- // ever minted an agent — e.g. create() rejected its PR attach — so the
786
- // session would otherwise fail every future turn. Mirror the local
787
- // host-replacement path above: a fresh conversation beats failing this
788
- // thread forever, and the new id binds to the session for later resumes.
789
- this.log(
790
- `[agent-sdk] cloud session ${request.sessionId} has no bound cloud agent; creating a fresh one`,
791
- );
792
- return Agent.create(options);
793
- }
794
-
795
- private resolveStore(
796
- request: Pick<RunnerPrewarmRequest, "runnerStateDir">,
797
- ): Promise<LocalAgentStore> {
798
- return this.options.store !== undefined
799
- ? Promise.resolve(this.options.store)
800
- : this.getStore(request.runnerStateDir);
801
- }
802
-
803
- /**
804
- * Mirror the settled turn's conversation. Persist failures are logged and
805
- * dropped — a durable-mirror outage must not fail a turn that already ran.
806
- */
807
- private async persistConversation(request: RunnerTurnRequest, sdkAgentId: string): Promise<void> {
808
- const mirror = this.options.conversationMirror;
809
- if (mirror === undefined) {
810
- return;
811
- }
812
- try {
813
- const store = await this.resolveStore(request);
814
- await mirror.persist(store, sdkAgentId);
815
- } catch (error) {
816
- this.log(
817
- `[agent-sdk] conversation mirror: persist for ${sdkAgentId} failed: ${
818
- error instanceof Error ? error.message : String(error)
819
- }`,
820
- );
821
- }
822
- }
823
-
824
- private getStore(stateDir: string): Promise<LocalAgentStore> {
825
- let storePromise = this.stores.get(stateDir);
826
- if (storePromise === undefined) {
827
- storePromise = mkdir(stateDir, { recursive: true }).then(() =>
828
- SqliteLocalAgentStore.open({
829
- stateRoot: stateDir,
830
- workspaceRef: stateDir,
831
- }),
832
- );
833
- this.stores.set(stateDir, storePromise);
834
- }
835
- return storePromise;
836
- }
837
- }
838
-
839
- /** Cloud agent ids minted by the server are `bc-…`; those always resume. */
840
- export function isServerMintedCloudAgentId(id: string): boolean {
841
- return id.startsWith("bc-");
842
- }
843
-
844
- /**
845
- * `Agent.resume` on a store with no row for the agent ("Agent <id> not
846
- * found", surfaced by every built-in {@link LocalAgentStore} backend).
847
- * Deliberately narrow: transient store/transport failures must propagate
848
- * rather than silently fork the thread onto a fresh conversation.
849
- */
850
- export function isLocalAgentNotFoundError(error: unknown, agentId: string): boolean {
851
- return (
852
- error instanceof Error &&
853
- error.message.includes(agentId) &&
854
- /\bnot found\b/i.test(error.message)
855
- );
856
- }
857
-
858
- export function toModelSelection(model: ModelSetting): ModelSelection {
859
- if (typeof model === "string") {
860
- return { id: model };
861
- }
862
- return {
863
- id: model.id,
864
- ...(model.params === undefined ? {} : { params: model.params }),
865
- };
866
- }
867
-
868
- function toCloudAgentOptions(
869
- cloud: RunnerTurnRequest["cloud"],
870
- agentServeAgent?: string,
871
- ): CloudAgentOptions {
872
- return {
873
- ...(cloud?.env === undefined ? {} : { env: cloud.env }),
874
- ...(cloud?.repos === undefined ? {} : { repos: cloud.repos }),
875
- ...(cloud?.workOnCurrentBranch === undefined
876
- ? {}
877
- : { workOnCurrentBranch: cloud.workOnCurrentBranch }),
878
- ...(cloud?.autoCreatePR === undefined ? {} : { autoCreatePR: cloud.autoCreatePR }),
879
- ...(cloud?.skipReviewerRequest === undefined
880
- ? {}
881
- : { skipReviewerRequest: cloud.skipReviewerRequest }),
882
- ...(cloud?.envVars === undefined ? {} : { envVars: cloud.envVars }),
883
- ...(agentServeAgent === undefined ? {} : { agentServeAgent }),
884
- };
885
- }
886
-
887
- function toAgentDefinitions(
888
- subagents: RunnerSubagent[],
889
- ): Record<string, AgentDefinition> | undefined {
890
- if (subagents.length === 0) {
891
- return undefined;
892
- }
893
- const definitions: Record<string, AgentDefinition> = {};
894
- for (const subagent of subagents) {
895
- definitions[subagent.name] = {
896
- description: subagent.description,
897
- prompt: subagent.prompt,
898
- model: subagent.model === undefined ? "inherit" : toModelSelection(subagent.model),
899
- };
900
- }
901
- return definitions;
902
- }
903
-
904
- function toTurnOutcome(result: RunResult): TurnOutcome {
905
- const usage: TurnUsage | undefined =
906
- result.usage === undefined
907
- ? undefined
908
- : {
909
- inputTokens: result.usage.inputTokens,
910
- outputTokens: result.usage.outputTokens,
911
- cacheReadTokens: result.usage.cacheReadTokens,
912
- cacheWriteTokens: result.usage.cacheWriteTokens,
913
- ...(result.usage.reasoningTokens === undefined
914
- ? {}
915
- : { reasoningTokens: result.usage.reasoningTokens }),
916
- };
917
- return {
918
- status: result.status,
919
- ...(result.result === undefined ? {} : { result: result.result }),
920
- ...(result.status === "error" ? { errorMessage: runErrorMessage(result) } : {}),
921
- errorCode: result.status === "error" ? result.error?.code : undefined,
922
- ...(usage === undefined ? {} : { usage }),
923
- };
924
- }
925
-
926
- /** Billing can lag briefly after `wait()`; retry before giving up on cost. */
927
- const CLOUD_USAGE_RETRY_DELAYS_MS = [0, 400, 1200] as const;
928
-
929
- /**
930
- * Cloud `wait()` often omits usage after a stream drop. Pull the run's
931
- * tokens from the usage API so the engine can still price the turn.
932
- * Failures are ignored: a missing estimate is better than failing the turn.
933
- */
934
- async function fillMissingCloudUsage(
935
- agent: SDKAgent,
936
- runId: string,
937
- outcome: TurnOutcome,
938
- ): Promise<TurnOutcome> {
939
- for (const delayMs of CLOUD_USAGE_RETRY_DELAYS_MS) {
940
- if (delayMs > 0) {
941
- await sleep(delayMs);
942
- }
943
- try {
944
- const billed = await agent.getUsage({ runId });
945
- const mapped = mapSdkTokenUsage(billed.usage);
946
- if (usageTokenSum(mapped) <= 0) {
947
- continue;
948
- }
949
- return { ...outcome, usage: mapped };
950
- } catch {
951
- // Transient usage-API failures should still burn the retry budget.
952
- }
953
- }
954
- return outcome;
955
- }
956
-
957
- export function runErrorMessage(result: Pick<RunResult, "error">): string {
958
- return result.error?.message?.trim() || "The Cursor agent run failed";
959
- }