@cursor/bdk 0.2.2 → 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 (284) hide show
  1. package/AGENTS.md +1 -1
  2. package/dist/bin/agent-serve.js +23 -7
  3. package/dist/channels/github/auth.d.ts.map +1 -1
  4. package/dist/channels/github/auth.js +36 -5
  5. package/dist/connections.d.ts +1 -1
  6. package/dist/connections.js +1 -1
  7. package/dist/docs/404.html +2 -2
  8. package/dist/docs/assets/{app.DtYVVVyK.js → app.BOIHhrKi.js} +4 -4
  9. package/dist/docs/assets/chunks/@localSearchIndexroot.D5L-b34G.js +1 -0
  10. package/dist/docs/assets/chunks/{VPLocalSearchBox.D47xT7J4.js → VPLocalSearchBox.D49zVZqM.js} +1 -1
  11. package/dist/docs/assets/chunks/{arc.CDJ6xzxR.js → arc.hmjb-sc4.js} +1 -1
  12. package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.l1Xnjd3N.js → architectureDiagram-Q4EWVU46.CxEI1KqM.js} +1 -1
  13. package/dist/docs/assets/chunks/{baseUniq.x-finShZ.js → baseUniq.DHHvBWoV.js} +1 -1
  14. package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.COC3qynH.js → blockDiagram-DXYQGD6D.DnXW-3bu.js} +1 -1
  15. package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.DdQO850E.js → c4Diagram-AHTNJAMY.e-47O2jM.js} +1 -1
  16. package/dist/docs/assets/chunks/channel.BbOGaJQP.js +1 -0
  17. package/dist/docs/assets/chunks/{chunk-4BX2VUAB.Dpn8omLk.js → chunk-4BX2VUAB.3ry4pYXB.js} +1 -1
  18. package/dist/docs/assets/chunks/{chunk-4TB4RGXK.C0XWStUN.js → chunk-4TB4RGXK.DGIZFRx6.js} +1 -1
  19. package/dist/docs/assets/chunks/{chunk-55IACEB6.DsKSZfIM.js → chunk-55IACEB6.DKBnqg9U.js} +1 -1
  20. package/dist/docs/assets/chunks/{chunk-EDXVE4YY.dNU6JDu6.js → chunk-EDXVE4YY.BIU8Ue5k.js} +1 -1
  21. package/dist/docs/assets/chunks/{chunk-FMBD7UC4.DN41fxKE.js → chunk-FMBD7UC4.DP-TFhjI.js} +1 -1
  22. package/dist/docs/assets/chunks/{chunk-OYMX7WX6.COpKCZus.js → chunk-OYMX7WX6.Ux0OYj5v.js} +1 -1
  23. package/dist/docs/assets/chunks/{chunk-QZHKN3VN.HDB-azx2.js → chunk-QZHKN3VN.BzHMwYox.js} +1 -1
  24. package/dist/docs/assets/chunks/{chunk-YZCP3GAM.DEeX_a2j.js → chunk-YZCP3GAM.D4OGAsSP.js} +1 -1
  25. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.Db58HCb1.js +1 -0
  26. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.Db58HCb1.js +1 -0
  27. package/dist/docs/assets/chunks/clone.Co4MBflG.js +1 -0
  28. package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.C3yGL2A8.js → cose-bilkent-S5V4N54A.Jq_7BUNx.js} +1 -1
  29. package/dist/docs/assets/chunks/{dagre-KV5264BT.Bpl24en4.js → dagre-KV5264BT.Di-skR2x.js} +1 -1
  30. package/dist/docs/assets/chunks/{diagram-5BDNPKRD.nFco6seU.js → diagram-5BDNPKRD.DeREHIdH.js} +1 -1
  31. package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.DXhA6DWR.js → diagram-G4DWMVQ6.C7Kcqxro.js} +1 -1
  32. package/dist/docs/assets/chunks/{diagram-MMDJMWI5.8GoOYcwk.js → diagram-MMDJMWI5.BK3eohyo.js} +1 -1
  33. package/dist/docs/assets/chunks/{diagram-TYMM5635.DDBlqvlJ.js → diagram-TYMM5635.C6TyymXT.js} +1 -1
  34. package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.vl_N81P4.js → erDiagram-SMLLAGMA.DYGG-gGx.js} +1 -1
  35. package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.Cteg8g7I.js → flowDiagram-DWJPFMVM.C9nBcSV4.js} +1 -1
  36. package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.D4aMhlMM.js → ganttDiagram-T4ZO3ILL.wAg_ymsp.js} +1 -1
  37. package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.DF_J0D4q.js → gitGraphDiagram-UUTBAWPF.B87j9Oeg.js} +1 -1
  38. package/dist/docs/assets/chunks/{graph.DJs0LDCf.js → graph.CuFMj31w.js} +1 -1
  39. package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.Bb-4RQwg.js → infoDiagram-42DDH7IO.P_mLGumP.js} +1 -1
  40. package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.DEtQRSbc.js → ishikawaDiagram-UXIWVN3A.DyuL_MsT.js} +1 -1
  41. package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.DhQQ75FA.js → journeyDiagram-VCZTEJTY.CtP09IoJ.js} +1 -1
  42. package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.C4gEw3Rk.js → kanban-definition-6JOO6SKY.BoeSYPZo.js} +1 -1
  43. package/dist/docs/assets/chunks/{layout.DT-PGlXa.js → layout.B0lMMtNo.js} +1 -1
  44. package/dist/docs/assets/chunks/{linear.BMMe__JW.js → linear.HxRBiAFX.js} +1 -1
  45. package/dist/docs/assets/chunks/{min.XyaU9K9Q.js → min.BGlFFHwS.js} +1 -1
  46. package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.CbBM6xZ-.js → mindmap-definition-QFDTVHPH.JyLBD9M8.js} +1 -1
  47. package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.DFJoIVou.js → pieDiagram-DEJITSTG.DnSmNZF8.js} +1 -1
  48. package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.CQjkDYqb.js → quadrantDiagram-34T5L4WZ.CUCnbfCa.js} +1 -1
  49. package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.D-mK-JQu.js → requirementDiagram-MS252O5E.py0IVUn5.js} +1 -1
  50. package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.BStQInpd.js → sankeyDiagram-XADWPNL6.Bkc-HWYp.js} +1 -1
  51. package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.CA_eooPJ.js → sequenceDiagram-FGHM5R23.Dqn8Mlv2.js} +1 -1
  52. package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.BXl-b7ad.js → stateDiagram-FHFEXIEX.JikkoQUU.js} +1 -1
  53. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.CMsKhrW0.js +1 -0
  54. package/dist/docs/assets/chunks/{theme.q37tOs4x.js → theme.b6HQ6zG_.js} +2 -2
  55. package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.vjuaGOSe.js → timeline-definition-GMOUNBTQ.BvpSXiBj.js} +1 -1
  56. package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.BxduJl-F.js → vennDiagram-DHZGUBPP.CU7MVnZx.js} +1 -1
  57. package/dist/docs/assets/chunks/wardley-RL74JXVD.BKwC4ctG.js +162 -0
  58. package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.D1z3ds0D.js → wardleyDiagram-NUSXRM2D.BfaF6Uhe.js} +1 -1
  59. package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.CRU5Ti9b.js → xychartDiagram-5P7HB3ND.Bg5dcpj4.js} +1 -1
  60. package/dist/docs/assets/{deployment.md.nGo1yIsa.js → deployment.md.BJ8i7Q6p.js} +5 -8
  61. package/dist/docs/assets/{deployment.md.nGo1yIsa.lean.js → deployment.md.BJ8i7Q6p.lean.js} +1 -1
  62. package/dist/docs/assets/{guides_github.md.C2_DSWlE.js → guides_github.md.Bq9kQU9B.js} +9 -3
  63. package/dist/docs/assets/{guides_github.md.C2_DSWlE.lean.js → guides_github.md.Bq9kQU9B.lean.js} +1 -1
  64. package/dist/docs/assets/{guides_slack.md.ZbHQETOT.js → guides_slack.md.diqqXTTm.js} +2 -2
  65. package/dist/docs/assets/{guides_slack.md.ZbHQETOT.lean.js → guides_slack.md.diqqXTTm.lean.js} +1 -1
  66. package/dist/docs/assets/{quickstart.md.wG4shE1f.js → quickstart.md.CHpHPBUN.js} +5 -3
  67. package/dist/docs/assets/{quickstart.md.wG4shE1f.lean.js → quickstart.md.CHpHPBUN.lean.js} +1 -1
  68. package/dist/docs/assets/{reference_artifacts.md.CFMNPreZ.js → reference_artifacts.md.CQfKq8F2.js} +1 -1
  69. package/dist/docs/assets/reference_cli.md.DgeLTO18.js +91 -0
  70. package/dist/docs/assets/reference_cli.md.DgeLTO18.lean.js +1 -0
  71. package/dist/docs/assets/{reference_connections.md._XpKiOaF.js → reference_connections.md.COq--gAm.js} +7 -3
  72. package/dist/docs/assets/{reference_connections.md._XpKiOaF.lean.js → reference_connections.md.COq--gAm.lean.js} +1 -1
  73. package/dist/docs/assets/{reference_evals.md.DqNyHMA6.js → reference_evals.md.CJm3uCUm.js} +4 -4
  74. package/dist/docs/assets/{reference_evals.md.DqNyHMA6.lean.js → reference_evals.md.CJm3uCUm.lean.js} +1 -1
  75. package/dist/docs/assets/{reference_skills.md.CRFTxt9M.js → reference_skills.md.Cy00QMKS.js} +3 -3
  76. package/dist/docs/assets/{reference_skills.md.CRFTxt9M.lean.js → reference_skills.md.Cy00QMKS.lean.js} +1 -1
  77. package/dist/docs/assets/troubleshooting.md.Cw5PKa3t.js +1 -0
  78. package/dist/docs/assets/{troubleshooting.md.BzZSu1Gz.lean.js → troubleshooting.md.Cw5PKa3t.lean.js} +1 -1
  79. package/dist/docs/building-with-agents.html +35 -35
  80. package/dist/docs/deployment.html +40 -43
  81. package/dist/docs/deployment.md +45 -15
  82. package/dist/docs/evals.html +35 -35
  83. package/dist/docs/guides/agent-to-agent.html +35 -35
  84. package/dist/docs/guides/bitbucket.html +35 -35
  85. package/dist/docs/guides/cloud-agents.html +35 -35
  86. package/dist/docs/guides/convert-automation.html +35 -35
  87. package/dist/docs/guides/github.html +43 -37
  88. package/dist/docs/guides/github.md +34 -0
  89. package/dist/docs/guides/gitlab.html +35 -35
  90. package/dist/docs/guides/grokbot-agents.html +35 -35
  91. package/dist/docs/guides/hooks.html +35 -35
  92. package/dist/docs/guides/improve.html +35 -35
  93. package/dist/docs/guides/jev.html +35 -35
  94. package/dist/docs/guides/mcp-oauth.html +35 -35
  95. package/dist/docs/guides/opentelemetry.html +35 -35
  96. package/dist/docs/guides/slack.html +37 -37
  97. package/dist/docs/guides/slack.md +5 -0
  98. package/dist/docs/guides/webhooks.html +35 -35
  99. package/dist/docs/hashmap.json +1 -1
  100. package/dist/docs/hillclimbing.html +35 -35
  101. package/dist/docs/index.html +35 -35
  102. package/dist/docs/llms-full.txt +198 -92
  103. package/dist/docs/quickstart.html +40 -38
  104. package/dist/docs/quickstart.md +7 -1
  105. package/dist/docs/reference/agent-config.html +35 -35
  106. package/dist/docs/reference/artifacts.html +37 -37
  107. package/dist/docs/reference/artifacts.md +1 -1
  108. package/dist/docs/reference/channels.html +35 -35
  109. package/dist/docs/reference/cli.html +55 -61
  110. package/dist/docs/reference/cli.md +65 -63
  111. package/dist/docs/reference/connections.html +42 -38
  112. package/dist/docs/reference/connections.md +28 -2
  113. package/dist/docs/reference/evals.html +39 -39
  114. package/dist/docs/reference/evals.md +6 -7
  115. package/dist/docs/reference/extensions.html +35 -35
  116. package/dist/docs/reference/hooks.html +35 -35
  117. package/dist/docs/reference/http-api.html +35 -35
  118. package/dist/docs/reference/instructions.html +35 -35
  119. package/dist/docs/reference/playground.html +35 -35
  120. package/dist/docs/reference/project-layout.html +35 -35
  121. package/dist/docs/reference/prompt.html +35 -35
  122. package/dist/docs/reference/schedules.html +35 -35
  123. package/dist/docs/reference/sessions.html +35 -35
  124. package/dist/docs/reference/skills.html +38 -38
  125. package/dist/docs/reference/subagents.html +35 -35
  126. package/dist/docs/reference/tools.html +35 -35
  127. package/dist/docs/templates/agentic-owners.html +35 -35
  128. package/dist/docs/templates/security-reviewer.html +35 -35
  129. package/dist/docs/templates/thermo-quality-review.html +35 -35
  130. package/dist/docs/templates/thermo-review.html +35 -35
  131. package/dist/docs/templates/triage.html +35 -35
  132. package/dist/docs/troubleshooting.html +36 -36
  133. package/dist/docs/troubleshooting.md +7 -3
  134. package/dist/extensions/cursor-grokbot-agents/extension.d.ts +77 -0
  135. package/dist/extensions/cursor-grokbot-agents/extension.d.ts.map +1 -0
  136. package/dist/extensions/cursor-grokbot-agents/extension.js +63 -0
  137. package/dist/extensions/cursor-grokbot-agents/lib/agents.d.ts +11 -0
  138. package/dist/extensions/cursor-grokbot-agents/lib/agents.d.ts.map +1 -0
  139. package/dist/extensions/cursor-grokbot-agents/lib/agents.js +31 -0
  140. package/dist/extensions/cursor-grokbot-agents/lib/backend.d.ts +56 -0
  141. package/dist/extensions/cursor-grokbot-agents/lib/backend.d.ts.map +1 -0
  142. package/dist/extensions/cursor-grokbot-agents/lib/backend.js +158 -0
  143. package/dist/extensions/cursor-grokbot-agents/lib/contacts.d.ts +28 -0
  144. package/dist/extensions/cursor-grokbot-agents/lib/contacts.d.ts.map +1 -0
  145. package/dist/extensions/cursor-grokbot-agents/lib/contacts.js +59 -0
  146. package/dist/extensions/cursor-grokbot-agents/lib/conversation.d.ts +53 -0
  147. package/dist/extensions/cursor-grokbot-agents/lib/conversation.d.ts.map +1 -0
  148. package/dist/extensions/cursor-grokbot-agents/lib/conversation.js +206 -0
  149. package/dist/extensions/cursor-grokbot-agents/lib/inputs.d.ts +4 -0
  150. package/dist/extensions/cursor-grokbot-agents/lib/inputs.d.ts.map +1 -0
  151. package/dist/extensions/cursor-grokbot-agents/lib/inputs.js +15 -0
  152. package/dist/extensions/cursor-grokbot-agents/lib/lock.d.ts +12 -0
  153. package/dist/extensions/cursor-grokbot-agents/lib/lock.d.ts.map +1 -0
  154. package/dist/extensions/cursor-grokbot-agents/lib/lock.js +25 -0
  155. package/dist/extensions/cursor-grokbot-agents/skills/consult.md +40 -0
  156. package/dist/extensions/cursor-grokbot-agents/tools/ask.d.ts +4 -0
  157. package/dist/extensions/cursor-grokbot-agents/tools/ask.d.ts.map +1 -0
  158. package/dist/extensions/cursor-grokbot-agents/tools/ask.js +37 -0
  159. package/dist/extensions/cursor-grokbot-agents/tools/check.d.ts +4 -0
  160. package/dist/extensions/cursor-grokbot-agents/tools/check.d.ts.map +1 -0
  161. package/dist/extensions/cursor-grokbot-agents/tools/check.js +32 -0
  162. package/dist/extensions/cursor-grokbot-agents/tools/interrupt.d.ts +4 -0
  163. package/dist/extensions/cursor-grokbot-agents/tools/interrupt.d.ts.map +1 -0
  164. package/dist/extensions/cursor-grokbot-agents/tools/interrupt.js +24 -0
  165. package/dist/extensions/cursor-grokbot-agents/tools/list.d.ts +4 -0
  166. package/dist/extensions/cursor-grokbot-agents/tools/list.d.ts.map +1 -0
  167. package/dist/extensions/cursor-grokbot-agents/tools/list.js +34 -0
  168. package/dist/internal/cli-ax.d.ts +1 -0
  169. package/dist/internal/cli-ax.d.ts.map +1 -1
  170. package/dist/internal/cli-ax.js +43 -10
  171. package/dist/internal/cli-deploy.d.ts +5 -1
  172. package/dist/internal/cli-deploy.d.ts.map +1 -1
  173. package/dist/internal/cli-deploy.js +22 -4
  174. package/dist/internal/cli-mcp-oauth.d.ts.map +1 -1
  175. package/dist/internal/cli-mcp-oauth.js +2 -1
  176. package/dist/internal/cli-skills.d.ts +1 -1
  177. package/dist/internal/cli-skills.d.ts.map +1 -1
  178. package/dist/internal/cli-skills.js +5 -5
  179. package/dist/internal/connection-env.d.ts +31 -0
  180. package/dist/internal/connection-env.d.ts.map +1 -0
  181. package/dist/internal/connection-env.js +84 -0
  182. package/dist/internal/cursor/backend-client.js +5 -0
  183. package/dist/internal/deploy-client.d.ts +30 -6
  184. package/dist/internal/deploy-client.d.ts.map +1 -1
  185. package/dist/internal/deploy-client.js +45 -9
  186. package/dist/internal/discovery/connections.d.ts.map +1 -1
  187. package/dist/internal/discovery/connections.js +11 -0
  188. package/dist/internal/hosted-delivery-protocol.d.ts +36 -11
  189. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
  190. package/dist/internal/hosted-delivery-protocol.js +31 -8
  191. package/dist/internal/hosted-delivery.d.ts +2 -2
  192. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  193. package/dist/internal/hosted-delivery.js +228 -48
  194. package/dist/internal/hosting.d.ts +2 -2
  195. package/dist/internal/hosting.d.ts.map +1 -1
  196. package/dist/internal/hosting.js +9 -3
  197. package/dist/internal/install-cursor-skills.d.ts +20 -24
  198. package/dist/internal/install-cursor-skills.d.ts.map +1 -1
  199. package/dist/internal/install-cursor-skills.js +50 -48
  200. package/dist/internal/legacy-command-guard.d.ts +2 -0
  201. package/dist/internal/legacy-command-guard.d.ts.map +1 -1
  202. package/dist/internal/legacy-command-guard.js +10 -1
  203. package/dist/internal/mcp-host.d.ts +6 -0
  204. package/dist/internal/mcp-host.d.ts.map +1 -1
  205. package/dist/internal/mcp-host.js +35 -16
  206. package/dist/internal/sdk-runner.d.ts +2 -0
  207. package/dist/internal/sdk-runner.d.ts.map +1 -1
  208. package/dist/internal/sdk-runner.js +10 -0
  209. package/dist/internal/server.d.ts.map +1 -1
  210. package/dist/internal/server.js +11 -1
  211. package/dist/internal/session-engine.d.ts.map +1 -1
  212. package/dist/internal/session-engine.js +9 -5
  213. package/dist/types.d.ts +11 -1
  214. package/dist/types.d.ts.map +1 -1
  215. package/docs/deployment.md +45 -15
  216. package/docs/guides/github.md +34 -0
  217. package/docs/guides/slack.md +5 -0
  218. package/docs/quickstart.md +7 -1
  219. package/docs/reference/artifacts.md +1 -1
  220. package/docs/reference/cli.md +65 -63
  221. package/docs/reference/connections.md +28 -2
  222. package/docs/reference/evals.md +6 -7
  223. package/docs/troubleshooting.md +7 -3
  224. package/package.json +1 -3
  225. package/scripts/install-cursor-skills.mjs +1 -1
  226. package/skills/create-agent/SKILL.md +1 -1
  227. package/skills/debug/SKILL.md +1 -1
  228. package/skills/deploy/SKILL.md +1 -1
  229. package/skills/evals/SKILL.md +1 -1
  230. package/skills/framework-map/SKILL.md +1 -1
  231. package/skills/github/SKILL.md +1 -1
  232. package/skills/hillclimb/SKILL.md +1 -1
  233. package/skills/mcp-auth/SKILL.md +1 -1
  234. package/skills/otel/SKILL.md +1 -1
  235. package/skills/setup-slack/SKILL.md +1 -1
  236. package/src/bin/agent-serve.ts +27 -6
  237. package/src/channels/github/auth.ts +44 -5
  238. package/src/connections.ts +1 -1
  239. package/src/extensions/cursor-grokbot-agents/extension.ts +132 -0
  240. package/src/extensions/cursor-grokbot-agents/lib/agents.ts +42 -0
  241. package/src/extensions/cursor-grokbot-agents/lib/backend.ts +208 -0
  242. package/src/extensions/cursor-grokbot-agents/lib/contacts.ts +74 -0
  243. package/src/extensions/cursor-grokbot-agents/lib/conversation.ts +260 -0
  244. package/src/extensions/cursor-grokbot-agents/lib/inputs.ts +21 -0
  245. package/src/extensions/cursor-grokbot-agents/lib/lock.ts +26 -0
  246. package/src/extensions/cursor-grokbot-agents/skills/consult.md +40 -0
  247. package/src/extensions/cursor-grokbot-agents/tools/ask.ts +32 -0
  248. package/src/extensions/cursor-grokbot-agents/tools/check.ts +25 -0
  249. package/src/extensions/cursor-grokbot-agents/tools/interrupt.ts +17 -0
  250. package/src/extensions/cursor-grokbot-agents/tools/list.ts +26 -0
  251. package/src/internal/cli-ax.ts +52 -7
  252. package/src/internal/cli-deploy.ts +39 -6
  253. package/src/internal/cli-mcp-oauth.ts +2 -1
  254. package/src/internal/cli-skills.ts +4 -5
  255. package/src/internal/connection-env.ts +106 -0
  256. package/src/internal/cursor/backend-client.ts +6 -0
  257. package/src/internal/deploy-client.ts +79 -9
  258. package/src/internal/discovery/connections.ts +11 -0
  259. package/src/internal/hosted-delivery-protocol.ts +57 -20
  260. package/src/internal/hosted-delivery.ts +486 -228
  261. package/src/internal/hosting.ts +10 -3
  262. package/src/internal/install-cursor-skills.ts +56 -53
  263. package/src/internal/legacy-command-guard.ts +13 -1
  264. package/src/internal/mcp-host.ts +45 -17
  265. package/src/internal/sdk-runner.ts +11 -0
  266. package/src/internal/server.ts +13 -1
  267. package/src/internal/session-engine.ts +9 -5
  268. package/src/types.ts +11 -1
  269. package/templates/agents-md/bot/lib/collect.ts +1 -4
  270. package/templates/code-wiki/bot/channels/github.ts +2 -2
  271. package/templates/demo/bot/channels/github.ts +5 -1
  272. package/templates/pr-autofixer/bot/lib/start-drive.ts +4 -4
  273. package/templates/triage/bot/lib/types.ts +6 -6
  274. package/dist/docs/assets/chunks/@localSearchIndexroot.BgTA2tV1.js +0 -1
  275. package/dist/docs/assets/chunks/channel.B2nMEx82.js +0 -1
  276. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.D8iCH2ve.js +0 -1
  277. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.D8iCH2ve.js +0 -1
  278. package/dist/docs/assets/chunks/clone.5XNLjby0.js +0 -1
  279. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.yGM2uLZQ.js +0 -1
  280. package/dist/docs/assets/chunks/wardley-RL74JXVD.DKfyIejL.js +0 -162
  281. package/dist/docs/assets/reference_cli.md.BK2QUH67.js +0 -97
  282. package/dist/docs/assets/reference_cli.md.BK2QUH67.lean.js +0 -1
  283. package/dist/docs/assets/troubleshooting.md.BzZSu1Gz.js +0 -1
  284. /package/dist/docs/assets/{reference_artifacts.md.CFMNPreZ.lean.js → reference_artifacts.md.CQfKq8F2.lean.js} +0 -0
@@ -48,6 +48,7 @@ import {
48
48
  cmdDeployments,
49
49
  cmdEventRepos,
50
50
  cmdKill,
51
+ cmdRollback,
51
52
  cmdRotateToken,
52
53
  cmdSecretsList,
53
54
  cmdSecretsSet,
@@ -66,6 +67,7 @@ import {
66
67
  PACKAGE_NAME,
67
68
  packageVersion,
68
69
  } from "../internal/distribution.js";
70
+ import { v2HostedVerifyHint } from "../internal/legacy-command-guard.js";
69
71
  import { loadAgentLocalEnv } from "../internal/local-env.js";
70
72
  import {
71
73
  ENTER_RESTART_EXIT_CODE,
@@ -97,6 +99,7 @@ Usage:
97
99
  [--slug <slug>] [--team <id>] [--dir <path>]
98
100
  ${CLI} sessions [--url <baseUrl> | --prod] [--json]
99
101
  [--slug <slug>] [--team <id>] [--dir <path>]
102
+ v2: unsupported. ${v2HostedVerifyHint()}
100
103
  ${CLI} session <sessionId> [--url <baseUrl> | --prod]
101
104
  [--json | --text | --events] [--out <file.ndjson>]
102
105
  [--slug <slug>] [--team <id>] [--dir <path>]
@@ -114,6 +117,7 @@ Usage:
114
117
  ${CLI} trajectory --events <file.ndjson> [--text]
115
118
  ${CLI} call <tool> [--input <json>] [--dir <path> | --url <baseUrl> | --prod]
116
119
  [--session <id>] [--slug <slug>] [--team <id>]
120
+ v2: unsupported. ${v2HostedVerifyHint()}
117
121
  ${CLI} skill <name> [--dir <path> | --url <baseUrl> | --prod]
118
122
  [--slug <slug>] [--team <id>] [--text]
119
123
  ${CLI} init [dir] [--template <name>] [--var id=value]... [--json]
@@ -157,6 +161,7 @@ Usage:
157
161
  ${CLI} cancel-runs <slug> [--team <id>] [--json]
158
162
  ${CLI} event-repos <slug> [--repo <owner/name>]... [--team <id>] [--json]
159
163
  ${CLI} upgrade <slug> [--release <id|version>] [--team <id>] [--json]
164
+ ${CLI} rollback <slug> [--release <id|version>] [--team <id>] [--json]
160
165
  ${CLI} delete <slug> [--team <id>] [--json] [--no-wait]
161
166
  ${CLI} rotate-token <slug> [--team <id>]
162
167
  ${CLI} secrets set <slug> NAME... | list <slug> | unset <slug> NAME
@@ -189,8 +194,10 @@ Commands:
189
194
  the current buffer. --prod shows deploy progress until the
190
195
  hosted deployment is running, then tails runtime logs. Without
191
196
  --prod, tails the local server (or --url).
192
- sessions List sessions on a running agent (or --prod hosted deployment).
193
- session Show one session. Default: text trajectory. --json for trajectory
197
+ sessions List sessions on a running agent or a v1 --prod deployment.
198
+ Unsupported on architecture v2. ${v2HostedVerifyHint()}
199
+ session Show one session. On v2: \`${CLI} session <ses_> --prod --slug <slug>\`.
200
+ Default: text trajectory. --json for trajectory
194
201
  JSON; --events for the raw event list. To continue interactively,
195
202
  use \`${CLI} resume [id]\`.
196
203
  cost Pull cost metrics. With a session id: per-turn token usage and
@@ -208,13 +215,14 @@ Commands:
208
215
  Streams tool calls and reply text to stderr when stderr is a TTY.
209
216
  Pass --prod to hit the hosted deployment instead of a local server.
210
217
  On an AgentSDK v2 slug, --prod starts a hosted session through
211
- the control plane (Temporal, no resident engine); --session
212
- ses_… resumes that exact session. A 404 falls back to the v1
218
+ the control plane (Temporal, no resident engine). ${v2HostedVerifyHint()}
219
+ --session ses_… resumes that exact session. A 404 falls back to the v1
213
220
  engine alias.
214
221
  trajectory Summarize an events.ndjson file into a trajectory.
215
222
  call Call an authored server tool deterministically (no model turn)
216
223
  via POST /v1/tools/:toolName. --session runs it inside an
217
224
  existing session and records it on that session's event stream.
225
+ Unsupported on architecture v2. ${v2HostedVerifyHint()}
218
226
  skill Read an authored skill deterministically (no model turn)
219
227
  via GET /v1/skills/:skillName. --text prints SKILL.md.
220
228
  init Scaffold a project (skipping existing files), npm install,
@@ -234,8 +242,8 @@ Commands:
234
242
  -> MCP). Review the project, then run \`validate\` / \`dev\`.
235
243
  Warnings never fail the command.
236
244
  install-skills
237
- Refresh the Agent SDK skills for coding agents in
238
- ~/.cursor/skills/agentsdk and print where they landed.
245
+ Refresh the BDK skills for coding agents in
246
+ ~/.cursor/skills/bdk and print where they landed.
239
247
  Installed copies set alwaysApply so Cursor injects them
240
248
  into context. \`npm install\` / \`npx\` already copies them
241
249
  (postinstall); this command overwrites with the package
@@ -306,6 +314,9 @@ Commands:
306
314
  upgrade Move this team's install onto a release, the newest ready one
307
315
  by default. Deploying a multi-tenant application publishes a
308
316
  release without moving any tenant onto it.
317
+ rollback Move this team's install onto an earlier ready release, the
318
+ nearest one by default. Does not publish a release. Pass
319
+ --release to choose an older id or version.
309
320
  delete Delete a deployment (teardown + purge the record) and wait
310
321
  until GET 404s. The slug is then free to redeploy.
311
322
  rotate-token Mint a new alias token for a deployment (shown once); the old
@@ -392,7 +403,10 @@ Options:
392
403
  --dir basename. Mutually exclusive with --url. Requires
393
404
  \`${CLI} login\`. For eval, this is how you opt into the
394
405
  persisted server-side batch (default is local).
406
+ v2: ${v2HostedVerifyHint()} call --prod and
407
+ sessions --prod stay on v1.
395
408
  --dry-run run/session --prod: mark the hosted v2 turn non-mutating.
409
+ ${v2HostedVerifyHint()}
396
410
  --component run/session --prod: wake this v2 component key,
397
411
  not the application default.
398
412
  --as-of run/session --prod: freeze the session clock at this
@@ -893,6 +907,13 @@ async function main(argv: string[]): Promise<number> {
893
907
  );
894
908
  }
895
909
 
910
+ case "rollback": {
911
+ return cmdRollback(
912
+ { slug: positionals[0], release: values.release },
913
+ deployOptionsFromValues(values),
914
+ );
915
+ }
916
+
896
917
  case "delete": {
897
918
  return cmdDelete(positionals[0], deployOptionsFromValues(values));
898
919
  }
@@ -215,11 +215,50 @@ export async function createGitHubInstallationToken(input: {
215
215
  privateKey,
216
216
  ...(input.api?.apiBaseUrl === undefined ? {} : { baseUrl: input.api.apiBaseUrl }),
217
217
  });
218
- const result = await auth({
219
- type: "installation",
220
- installationId: input.installationId,
221
- });
222
- return result.token;
218
+ try {
219
+ const result = await auth({
220
+ type: "installation",
221
+ installationId: input.installationId,
222
+ });
223
+ return result.token;
224
+ } catch (error) {
225
+ throw installationTokenMintError(error, {
226
+ appId,
227
+ installationId: input.installationId,
228
+ });
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Octokit's bare mint failure ("Not Found - <docs url>") names neither the
234
+ * app nor the installation, which makes a revoked installation or an
235
+ * app/installation credential mismatch undiagnosable from production logs.
236
+ * Rewrap with both ids and, for 404, the two causes that produce it.
237
+ */
238
+ function installationTokenMintError(
239
+ error: unknown,
240
+ context: { appId: string; installationId: number },
241
+ ): Error {
242
+ const status =
243
+ typeof error === "object" &&
244
+ error !== null &&
245
+ "status" in error &&
246
+ typeof (error as { status: unknown }).status === "number"
247
+ ? (error as { status: number }).status
248
+ : undefined;
249
+ const detail = error instanceof Error ? error.message : String(error);
250
+ const hint =
251
+ status === 404
252
+ ? " — the installation does not exist for this app: it was uninstalled or suspended, or the configured app credentials belong to a different GitHub App than the one this installation id refers to"
253
+ : "";
254
+ const wrapped = new Error(
255
+ `githubChannel: failed to mint an installation access token (app ${context.appId}, installation ${context.installationId}): ${detail}${hint}`,
256
+ error instanceof Error ? { cause: error } : undefined,
257
+ );
258
+ if (status !== undefined) {
259
+ (wrapped as Error & { status?: number }).status = status;
260
+ }
261
+ return wrapped;
223
262
  }
224
263
 
225
264
  /**
@@ -18,7 +18,7 @@
18
18
  *
19
19
  * export default defineConnection({
20
20
  * url: "https://mcp.linear.app/mcp",
21
- * headers: { authorization: `Bearer ${process.env.LINEAR_TOKEN}` },
21
+ * headers: { authorization: "Bearer ${LINEAR_TOKEN}" },
22
22
  * });
23
23
  *
24
24
  * // TypeScript tools, packaged as stdio MCP for the agent environment:
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Your Grok Bot agents as an extension. Mount it and the agent can talk to
3
+ * the Grok Bot agents of the host's account: send a message, read the
4
+ * reply, keep waiting on a long turn, interrupt one.
5
+ *
6
+ * ```ts
7
+ * // agent/extensions/grokbot.ts
8
+ * import cursorGrokBotAgents from "@cursor/bdk/extensions/cursor-grokbot-agents";
9
+ *
10
+ * export default cursorGrokBotAgents({
11
+ * agents: [
12
+ * { name: "Plan Keeper", description: "Keeps or moves outdoor plans." },
13
+ * ],
14
+ * });
15
+ * ```
16
+ *
17
+ * Contributes `grokbot__ask`, `grokbot__check`, `grokbot__interrupt`,
18
+ * `grokbot__list` and the `grokbot__consult` skill (the namespace is the
19
+ * mount filename), over the same public `/v0/grokbot` session API the
20
+ * grokbot runtime uses, under the serve host's Cursor API key
21
+ * (`CURSOR_API_KEY`, key file, or `login`). Agents are addressed by name and
22
+ * resolved on the account the key belongs to; a message lands in that
23
+ * account's own conversation with the agent, and the reply is what the agent
24
+ * sends back during that turn. The tools run on the serve host, so they
25
+ * need the local runtime.
26
+ *
27
+ * This is the other direction from `defineAgent({ runtime: "grokbot" })`:
28
+ * the runtime runs *this* agent's turns on the hosted Grok Bot harness; the
29
+ * extension keeps the agent where it is and lets it talk to *other* Grok
30
+ * Bot agents.
31
+ */
32
+
33
+ import { z } from "zod";
34
+ import { defineExtension } from "../../extensions.js";
35
+ import type { Extension } from "../../types.js";
36
+
37
+ /**
38
+ * A Grok Bot agent the model may address, by the name shown in the app.
39
+ * Type alias, not an interface: `list` returns these.
40
+ */
41
+ export type ConfiguredGrokBotAgent = {
42
+ name: string;
43
+ /** What the agent is for; shown to the model by `list`. */
44
+ description?: string;
45
+ };
46
+
47
+ /** Mount options; every field is optional. */
48
+ export interface CursorGrokBotAgentsOptions {
49
+ /**
50
+ * The Grok Bot agents the model may talk to, by name. This is the
51
+ * allowlist for a call's own `agent`: names outside it are refused, and a
52
+ * lone configured agent is the default when a call names none. Without
53
+ * it, any name goes through and `needsApproval` defaults to true, since
54
+ * an unknown name creates an agent of that name on the account.
55
+ */
56
+ agents?: Array<string | ConfiguredGrokBotAgent>;
57
+ /**
58
+ * Park messages for a human approval. Defaults to `true` when no `agents`
59
+ * are configured; `false` once they are. Pass an explicit boolean to
60
+ * override. Configured names still bound the model's choice regardless.
61
+ */
62
+ needsApproval?: boolean;
63
+ /** Cursor API key. Defaults to the serve host's own key. */
64
+ apiKey?: string;
65
+ /**
66
+ * How often to read the agent's transcript while waiting for a reply, in
67
+ * milliseconds. Defaults to 750.
68
+ */
69
+ pollIntervalMs?: number;
70
+ }
71
+
72
+ /** {@link CursorGrokBotAgentsOptions} with defaults applied. */
73
+ export interface CursorGrokBotAgentsConfig {
74
+ agents?: ConfiguredGrokBotAgent[];
75
+ needsApproval: boolean;
76
+ apiKey?: string;
77
+ pollIntervalMs: number;
78
+ }
79
+
80
+ /** The backend's session name limit. */
81
+ export const AGENT_NAME_MAX_LENGTH = 255;
82
+ const DEFAULT_POLL_INTERVAL_MS = 750;
83
+
84
+ const agentName = z
85
+ .string()
86
+ .trim()
87
+ .min(1, "Grok Bot agent names must not be empty.")
88
+ .max(AGENT_NAME_MAX_LENGTH);
89
+
90
+ const configuredAgent: z.ZodType<
91
+ ConfiguredGrokBotAgent,
92
+ z.ZodTypeDef,
93
+ string | ConfiguredGrokBotAgent
94
+ > = z
95
+ .union([agentName, z.object({ name: agentName, description: z.string().optional() })])
96
+ .transform(agent => (typeof agent === "string" ? { name: agent } : agent));
97
+
98
+ const agents = z
99
+ .array(configuredAgent)
100
+ .min(1, "agents must name at least one Grok Bot agent; omit it to allow any.")
101
+ .refine(
102
+ list => new Set(list.map(agent => agent.name.toLowerCase())).size === list.length,
103
+ "agents must not repeat a name (names match case-insensitively).",
104
+ );
105
+
106
+ const config: z.ZodType<
107
+ CursorGrokBotAgentsConfig,
108
+ z.ZodTypeDef,
109
+ CursorGrokBotAgentsOptions | undefined
110
+ > = z
111
+ .object({
112
+ agents: agents.optional(),
113
+ needsApproval: z.boolean().optional(),
114
+ apiKey: z.string().optional(),
115
+ pollIntervalMs: z.number().int().min(1).default(DEFAULT_POLL_INTERVAL_MS),
116
+ })
117
+ .default({})
118
+ .transform(options => ({
119
+ ...options,
120
+ needsApproval: options.needsApproval ?? options.agents === undefined,
121
+ }));
122
+
123
+ const cursorGrokBotAgents: Extension<
124
+ CursorGrokBotAgentsConfig,
125
+ CursorGrokBotAgentsOptions | undefined
126
+ > = defineExtension({
127
+ root: import.meta.dirname,
128
+ description: "Talk to your Grok Bot agents and read their replies.",
129
+ config,
130
+ });
131
+
132
+ export default cursorGrokBotAgents;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Which Grok Bot agent a call addresses. The model names one per call, but
3
+ * the author's `agents` are the allowlist: with them configured, a name
4
+ * outside the list is refused (the backend would create an agent of that
5
+ * name), and a lone configured agent stands in when the call names none.
6
+ * Matching is case-insensitive and resolves to the configured spelling,
7
+ * since the backend looks names up exactly.
8
+ */
9
+
10
+ import type { ConfiguredGrokBotAgent } from "../extension.js";
11
+
12
+ export function resolveAgentName(
13
+ requested: string | undefined,
14
+ configured: ConfiguredGrokBotAgent[] | undefined,
15
+ ): string {
16
+ const name = requested?.trim();
17
+ if (configured === undefined) {
18
+ if (name === undefined || name === "") {
19
+ throw new Error("`agent` is required: this extension has no configured Grok Bot agents.");
20
+ }
21
+ return name;
22
+ }
23
+ const names = configured.map(agent => `"${agent.name}"`).join(", ");
24
+ if (name === undefined || name === "") {
25
+ const only = configured.length === 1 ? configured[0] : undefined;
26
+ if (only === undefined) {
27
+ throw new Error(
28
+ `\`agent\` is required: this extension configures several Grok Bot agents (${names}).`,
29
+ );
30
+ }
31
+ return only.name;
32
+ }
33
+ const match =
34
+ configured.find(agent => agent.name === name) ??
35
+ configured.find(agent => agent.name.toLowerCase() === name.toLowerCase());
36
+ if (match === undefined) {
37
+ throw new Error(
38
+ `"${name}" is not one of this extension's configured Grok Bot agents (${names}).`,
39
+ );
40
+ }
41
+ return match.name;
42
+ }
@@ -0,0 +1,208 @@
1
+ /**
2
+ * The `/v0/grokbot` session API as the tools use it: the same four routes
3
+ * the grokbot runtime drives, on the external API host (`api.cursor.com`;
4
+ * they 404 on api2), under the host's Cursor API key. A session is a hosted
5
+ * Grok Bot agent of the key's account, get-or-created by name; messages go
6
+ * into its one conversation, and the transcript is read back as entries
7
+ * after a cursor, with the turn's status alongside.
8
+ */
9
+
10
+ import { randomUUID } from "node:crypto";
11
+ import { z } from "zod";
12
+ import {
13
+ cursorExternalApiUrl,
14
+ resolveApiKeySync,
15
+ SIGN_IN_HINT,
16
+ } from "../../../internal/cursor/credentials.js";
17
+ import extension from "../extension.js";
18
+
19
+ const REQUEST_TIMEOUT_MS = 60_000;
20
+
21
+ export class GrokBotApiError extends Error {
22
+ constructor(
23
+ message: string,
24
+ readonly status?: number,
25
+ ) {
26
+ super(message);
27
+ this.name = "GrokBotApiError";
28
+ }
29
+ }
30
+
31
+ // Type aliases, not interfaces: these flow into tool results.
32
+ export type GrokBotSession = {
33
+ /** The hosted agent's durable id; every other route addresses it. */
34
+ sessionId: string;
35
+ /** The name as the backend stores it (trimmed). */
36
+ name: string;
37
+ createdAtMs: number;
38
+ /** Transcript tail: reading after it skips the conversation's history. */
39
+ latestUpdatedSeq: string;
40
+ };
41
+
42
+ export type GrokBotEntry = {
43
+ seq: string;
44
+ updatedSeq: string;
45
+ kind: string;
46
+ role?: string;
47
+ text?: string;
48
+ createdAtMs: number;
49
+ };
50
+
51
+ export type GrokBotTurnStatus = {
52
+ idle: boolean;
53
+ inFlight: boolean;
54
+ queued: number;
55
+ };
56
+
57
+ export type GrokBotEntriesPage = {
58
+ entries: GrokBotEntry[];
59
+ latestUpdatedSeq: string;
60
+ turn: GrokBotTurnStatus;
61
+ };
62
+
63
+ const sessionSchema = z.object({
64
+ id: z.string(),
65
+ name: z.string(),
66
+ createdAtMs: z.number(),
67
+ latestUpdatedSeq: z.string(),
68
+ });
69
+
70
+ const sendSchema = z.object({
71
+ messageId: z.string(),
72
+ delivery: z.string(),
73
+ });
74
+
75
+ const entriesSchema: z.ZodType<GrokBotEntriesPage> = z.object({
76
+ entries: z.array(
77
+ z.object({
78
+ seq: z.string(),
79
+ updatedSeq: z.string(),
80
+ kind: z.string(),
81
+ role: z.string().optional(),
82
+ text: z.string().optional(),
83
+ createdAtMs: z.number(),
84
+ }),
85
+ ),
86
+ latestUpdatedSeq: z.string(),
87
+ turn: z.object({
88
+ idle: z.boolean(),
89
+ inFlight: z.boolean(),
90
+ queued: z.number(),
91
+ }),
92
+ });
93
+
94
+ export class GrokBotAgentsBackend {
95
+ constructor(
96
+ private readonly apiKey: () => string,
97
+ private readonly fetchImpl: typeof fetch = fetch,
98
+ ) {}
99
+
100
+ /** `POST /v0/grokbot/sessions`: the account's agent of that name, created when missing. */
101
+ async session(name: string): Promise<GrokBotSession> {
102
+ // No `instructions`: the agent is somebody's, configured in the app, and
103
+ // an omitted field never touches its stored profile.
104
+ const parsed = sessionSchema.parse(
105
+ await this.request("POST", "/v0/grokbot/sessions", { name }),
106
+ );
107
+ return {
108
+ sessionId: parsed.id,
109
+ name: parsed.name,
110
+ createdAtMs: parsed.createdAtMs,
111
+ latestUpdatedSeq: parsed.latestUpdatedSeq,
112
+ };
113
+ }
114
+
115
+ /** Deliver one user message to the agent's conversation. */
116
+ async send(sessionId: string, text: string): Promise<void> {
117
+ const { delivery } = sendSchema.parse(
118
+ await this.request("POST", `/v0/grokbot/sessions/${sessionId}/messages`, {
119
+ text,
120
+ messageId: randomUUID(),
121
+ }),
122
+ );
123
+ if (delivery !== "accepted_temporal" && delivery !== "duplicate") {
124
+ throw new GrokBotApiError(
125
+ `The Grok Bot agent's harness did not accept the message (delivery: ${delivery}).`,
126
+ );
127
+ }
128
+ }
129
+
130
+ /** Transcript entries after `afterUpdatedSeq`, oldest first, with the turn's status. */
131
+ async entries(sessionId: string, afterUpdatedSeq: string): Promise<GrokBotEntriesPage> {
132
+ return entriesSchema.parse(
133
+ await this.request(
134
+ "GET",
135
+ `/v0/grokbot/sessions/${sessionId}/entries?afterUpdatedSeq=${encodeURIComponent(afterUpdatedSeq)}`,
136
+ ),
137
+ );
138
+ }
139
+
140
+ async interrupt(sessionId: string, reason: string): Promise<void> {
141
+ await this.request("POST", `/v0/grokbot/sessions/${sessionId}/interrupt`, {
142
+ reason,
143
+ });
144
+ }
145
+
146
+ private async request(method: "GET" | "POST", path: string, body?: unknown): Promise<unknown> {
147
+ const headers: Record<string, string> = {
148
+ authorization: `Bearer ${this.apiKey()}`,
149
+ "x-cursor-client-type": "agent-serve",
150
+ "x-request-id": randomUUID(),
151
+ };
152
+ if (body !== undefined) {
153
+ headers["content-type"] = "application/json";
154
+ }
155
+ let response: Response;
156
+ try {
157
+ response = await this.fetchImpl(`${cursorExternalApiUrl()}${path}`, {
158
+ method,
159
+ headers,
160
+ body: body === undefined ? undefined : JSON.stringify(body),
161
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
162
+ });
163
+ } catch (error) {
164
+ throw new GrokBotApiError(
165
+ `Grok Bot API ${method} ${path} failed: ${error instanceof Error ? error.message : String(error)}`,
166
+ );
167
+ }
168
+ const text = await response.text();
169
+ if (!response.ok) {
170
+ throw new GrokBotApiError(
171
+ `Grok Bot API ${method} ${path} failed (${response.status}): ${apiErrorMessage(text)}`,
172
+ response.status,
173
+ );
174
+ }
175
+ return JSON.parse(text) as unknown;
176
+ }
177
+ }
178
+
179
+ let backend: GrokBotAgentsBackend | undefined;
180
+
181
+ /** The process-wide backend for this mount, built on first use. */
182
+ export function grokBotAgentsBackend(): GrokBotAgentsBackend {
183
+ backend ??= new GrokBotAgentsBackend(apiKey);
184
+ return backend;
185
+ }
186
+
187
+ export function apiKey(): string {
188
+ // Read per call: the host can sign in after the mount.
189
+ const key = resolveApiKeySync({ apiKey: extension.config.apiKey });
190
+ if (key === undefined) {
191
+ throw new Error(`Grok Bot agents need a Cursor API key. ${SIGN_IN_HINT}`);
192
+ }
193
+ return key.apiKey;
194
+ }
195
+
196
+ /** The route's `{ error }` envelope when it is one, the raw body otherwise. */
197
+ function apiErrorMessage(text: string): string {
198
+ try {
199
+ const parsed = JSON.parse(text) as { error?: unknown; message?: unknown };
200
+ const message = parsed.error ?? parsed.message;
201
+ if (typeof message === "string" && message !== "") {
202
+ return message;
203
+ }
204
+ } catch {
205
+ // Not JSON; fall through to the raw body.
206
+ }
207
+ return text.slice(0, 300);
208
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Who has talked to which Grok Bot agent, and how far into its transcript
3
+ * they have read. The tools authenticate with the serve host's one Cursor
4
+ * API key, so every agent is that account's; what the host keeps per
5
+ * principal is the read cursor, so `check` returns what the agent said
6
+ * since that caller last read, and a lookup by name for `check` and
7
+ * `interrupt`, which never create an agent the caller has not spoken to.
8
+ */
9
+
10
+ import { z } from "zod";
11
+ import type { ToolContext } from "../../../types.js";
12
+ import { KeyedLock } from "./lock.js";
13
+
14
+ const PREFIX = "grokbot-agents";
15
+
16
+ // Type alias, not an interface: contacts flow into tool results.
17
+ export type Contact = {
18
+ /** The agent's name as the backend stores it. */
19
+ name: string;
20
+ /** The hosted agent's `/v0/grokbot` session id. */
21
+ sessionId: string;
22
+ /** Newest transcript `updatedSeq` this principal has read. */
23
+ cursor: string;
24
+ firstContactAt: string;
25
+ lastContactAt: string;
26
+ };
27
+
28
+ const contactsSchema: z.ZodType<Contact[]> = z.array(
29
+ z.object({
30
+ name: z.string(),
31
+ sessionId: z.string(),
32
+ cursor: z.string(),
33
+ firstContactAt: z.string(),
34
+ lastContactAt: z.string(),
35
+ }),
36
+ );
37
+
38
+ const locks = new KeyedLock();
39
+
40
+ /** Unauthenticated sessions (local dev, direct calls) share one principal. */
41
+ export function principalOf(ctx: ToolContext): string {
42
+ const auth = ctx.session.auth;
43
+ return auth === null ? "anonymous" : `${auth.principalType}:${auth.principalId}`;
44
+ }
45
+
46
+ /** The caller's contacts, most recently spoken to first. */
47
+ export async function listContacts(ctx: ToolContext): Promise<Contact[]> {
48
+ const contacts = contactsSchema.safeParse(await ctx.host.kv.get(contactsKey(principalOf(ctx))));
49
+ return contacts.success ? contacts.data : [];
50
+ }
51
+
52
+ /** The contact of that name, exact spelling first, then case-insensitively. */
53
+ export function findContact(contacts: Contact[], name: string): Contact | undefined {
54
+ const wanted = name.trim();
55
+ return (
56
+ contacts.find(contact => contact.name === wanted) ??
57
+ contacts.find(contact => contact.name.toLowerCase() === wanted.toLowerCase())
58
+ );
59
+ }
60
+
61
+ /** Insert or replace the caller's record of one agent, newest first. */
62
+ export async function saveContact(ctx: ToolContext, contact: Contact): Promise<void> {
63
+ const key = contactsKey(principalOf(ctx));
64
+ await locks.run(key, async () => {
65
+ const others = (await listContacts(ctx)).filter(
66
+ existing => existing.sessionId !== contact.sessionId,
67
+ );
68
+ await ctx.host.kv.put(key, [contact, ...others]);
69
+ });
70
+ }
71
+
72
+ function contactsKey(principal: string): string {
73
+ return `${PREFIX}/principals/${encodeURIComponent(principal)}`;
74
+ }