@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
@@ -7,8 +7,8 @@
7
7
  * locally with the same grammar the server enforces.
8
8
  */
9
9
 
10
- /** `hosting.egressDomains` cap (backend caps the deploy body at 20). */
11
- export const MAX_EGRESS_DOMAINS = 20;
10
+ /** `hosting.egressDomains` cap (the manifest schema and deploy body agree). */
11
+ export const MAX_EGRESS_DOMAINS = 64;
12
12
  /** Max secrets per deployment. */
13
13
  export const MAX_SECRETS = 32;
14
14
  /** Max secret value size in bytes. */
@@ -46,12 +46,19 @@ const SECRET_NAME_PATTERN = /^[A-Z][A-Z0-9_]*$/;
46
46
  // leading `*.` wildcard. Labels: alphanumeric with interior hyphens.
47
47
  const EGRESS_DOMAIN_PATTERN = /^(\*\.)?([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z]+$/;
48
48
 
49
+ /** `host:port` asks for raw TCP egress; a wildcard host has no address to open. */
50
+ const EGRESS_TCP_PATTERN = /^([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z]+:([1-9]\d{0,4})$/;
51
+
49
52
  /** Returns a human error message, or undefined when the domain is valid. */
50
53
  export function validateEgressDomain(domain: string): string | undefined {
51
54
  if (EGRESS_DOMAIN_PATTERN.test(domain)) {
52
55
  return undefined;
53
56
  }
54
- return `Invalid egress domain ${JSON.stringify(domain)}: use a lowercase hostname with at least two labels and an alphabetic TLD (e.g. "api.example.com"), optionally with a single leading "*." wildcard.`;
57
+ const tcp = EGRESS_TCP_PATTERN.exec(domain);
58
+ if (tcp !== null && Number(tcp[3]) <= 65535) {
59
+ return undefined;
60
+ }
61
+ return `Invalid egress domain ${JSON.stringify(domain)}: use a lowercase hostname with at least two labels and an alphabetic TLD (e.g. "api.example.com"), optionally with a single leading "*." wildcard or a trailing ":port" for raw TCP.`;
55
62
  }
56
63
 
57
64
  /**
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Offer to install the package's coding-agent skills into the user's
3
- * personal Cursor skills dir under `~/.cursor/skills/agentsdk/<skill>/`.
3
+ * personal Cursor skills dir under `~/.cursor/skills/bdk/<skill>/`.
4
4
  *
5
- * Cursor walks `~/.cursor/skills` recursively, so the `agentsdk/` folder is
5
+ * Cursor walks `~/.cursor/skills` recursively, so the `bdk/` folder is
6
6
  * only organizational — identity comes from the leaf folder that holds
7
7
  * SKILL.md. Installed copies get `alwaysApply: true` so Cursor injects the
8
8
  * skill body as a global rule instead of leaving it as an on-demand catalog
@@ -22,10 +22,13 @@ import { parseFrontmatter } from "./frontmatter.js";
22
22
  import { stdoutPalette } from "./terminal-style.js";
23
23
 
24
24
  /** Category folder under ~/.cursor/skills (Cursor discovers nested skills). */
25
- export const CURSOR_SKILLS_NAMESPACE = "agentsdk";
25
+ export const CURSOR_SKILLS_NAMESPACE = "bdk";
26
26
 
27
- /** Pre-rename install folder. Install deletes this so `/agentkit-*` rows disappear. */
28
- export const LEGACY_CURSOR_SKILLS_NAMESPACE = "agentkit";
27
+ /**
28
+ * Earlier install folders. Deleted on install so stale skill ids stop
29
+ * being discovered next to the current copies.
30
+ */
31
+ const LEGACY_CURSOR_SKILLS_NAMESPACES = ["agentsdk", "agentkit"] as const;
29
32
 
30
33
  /** How long the `init` offer waits for an answer before skipping the install. */
31
34
  export const SKILL_PROMPT_TIMEOUT_MS = 45_000;
@@ -40,9 +43,9 @@ export const CURSOR_JULY_SKILLS_HOME_ENV = "CURSOR_JULY_SKILLS_HOME";
40
43
  export const CURSOR_JULY_SKIP_SKILL_INSTALL_ENV = "CURSOR_JULY_SKIP_SKILL_INSTALL";
41
44
 
42
45
  export interface PackageSkill {
43
- /** Frontmatter `name` (e.g. agentsdk-create-agent). */
46
+ /** Frontmatter `name` (e.g. bdk-create-agent). */
44
47
  name: string;
45
- /** Leaf install directory under agentsdk/ (e.g. create-agent). */
48
+ /** Leaf install directory under bdk/ (e.g. create-agent). */
46
49
  leafDir: string;
47
50
  /** Absolute path to the source skill directory in the package. */
48
51
  sourceDir: string;
@@ -71,27 +74,26 @@ export function isConsumerPackageInstall(packageRoot: string): boolean {
71
74
  return packageRoot.split(/[\\/]/).includes("node_modules");
72
75
  }
73
76
 
74
- /** `~/.cursor/skills/agentsdk` — where package skills are installed. */
75
- export function agentsdkCursorSkillsDir(skillsHome: string = cursorSkillsHome()): string {
77
+ /** `~/.cursor/skills/bdk` — where package skills are installed. */
78
+ export function bdkCursorSkillsDir(skillsHome: string = cursorSkillsHome()): string {
76
79
  return join(skillsHome, CURSOR_SKILLS_NAMESPACE);
77
80
  }
78
81
 
79
- /** Pre-rename `~/.cursor/skills/agentkit`. */
80
- export function legacyAgentkitCursorSkillsDir(skillsHome: string = cursorSkillsHome()): string {
81
- return join(skillsHome, LEGACY_CURSOR_SKILLS_NAMESPACE);
82
+ function legacyCursorSkillsDirs(skillsHome: string): string[] {
83
+ return LEGACY_CURSOR_SKILLS_NAMESPACES.map(name => join(skillsHome, name));
82
84
  }
83
85
 
84
- /** Absolute install path for one skill: `…/agentsdk/<leafDir>`. */
86
+ /** Absolute install path for one skill: `…/bdk/<leafDir>`. */
85
87
  export function skillInstallPath(
86
88
  skill: Pick<PackageSkill, "leafDir">,
87
89
  skillsHome: string = cursorSkillsHome(),
88
90
  ): string {
89
- return join(agentsdkCursorSkillsDir(skillsHome), skill.leafDir);
91
+ return join(bdkCursorSkillsDir(skillsHome), skill.leafDir);
90
92
  }
91
93
 
92
94
  /**
93
95
  * Skills shipped next to the running package. Uses the frontmatter `name`
94
- * when present, otherwise `agentsdk-<dir>`.
96
+ * when present, otherwise `bdk-<dir>`.
95
97
  */
96
98
  export async function listShippedPackageSkills(
97
99
  packageRoot: string = packageRootDir(),
@@ -137,7 +139,7 @@ async function readPackageVersion(packageRoot: string): Promise<string> {
137
139
  }
138
140
 
139
141
  /**
140
- * Skills that do not yet have a SKILL.md under ~/.cursor/skills/agentsdk/.
142
+ * Skills that do not yet have a SKILL.md under ~/.cursor/skills/bdk/.
141
143
  * Install still overwrites every shipped skill when the user confirms — this
142
144
  * helper is for messaging (fresh install vs update).
143
145
  */
@@ -163,22 +165,22 @@ export interface SkillInstallResult {
163
165
  installed: string[];
164
166
  /** Leaf dirs deleted because the package no longer ships them. */
165
167
  removed: string[];
166
- /** True when leftover `~/.cursor/skills/agentkit` was deleted. */
167
- removedLegacyNamespace: boolean;
168
+ /** Leftover namespace dirs deleted (`…/agentsdk`, `…/agentkit`). */
169
+ removedLegacyDirs: string[];
168
170
  }
169
171
 
170
172
  /**
171
- * Copy each skill directory into `skillsHome/agentsdk/<leafDir>/`.
173
+ * Copy each skill directory into `skillsHome/bdk/<leafDir>/`.
172
174
  * Always overwrites so a package upgrade refreshes local Cursor skills.
173
175
  * Strips monorepo-only frontmatter, sets `alwaysApply: true` so Cursor
174
176
  * loads the body into context, and removes leaf dirs no longer shipped.
175
- * Also deletes leftover `skillsHome/agentkit/` from the previous namespace.
177
+ * Also deletes leftover `skillsHome/agentsdk/` and `skillsHome/agentkit/`.
176
178
  */
177
179
  export async function installCursorSkills(
178
180
  skills: readonly PackageSkill[],
179
181
  skillsHome: string = cursorSkillsHome(),
180
182
  ): Promise<SkillInstallResult> {
181
- const namespaceDir = agentsdkCursorSkillsDir(skillsHome);
183
+ const namespaceDir = bdkCursorSkillsDir(skillsHome);
182
184
  await mkdir(namespaceDir, { recursive: true });
183
185
 
184
186
  const removed = await orphanLeaves(namespaceDir, skills);
@@ -203,8 +205,8 @@ export async function installCursorSkills(
203
205
  }
204
206
  installed.push(skill.leafDir);
205
207
  }
206
- const removedLegacyNamespace = await removeLegacyCursorSkillsNamespace(skillsHome);
207
- return { installed, removed, removedLegacyNamespace };
208
+ const removedLegacyDirs = await removeLegacyCursorSkillsNamespaces(skillsHome);
209
+ return { installed, removed, removedLegacyDirs };
208
210
  }
209
211
 
210
212
  async function makeTreeWritable(root: string): Promise<void> {
@@ -245,25 +247,26 @@ async function orphanLeaves(
245
247
  .map(entry => entry.name);
246
248
  }
247
249
 
248
- /** Drop leftover `skillsHome/agentkit` from the previous install namespace. */
249
- async function removeLegacyCursorSkillsNamespace(skillsHome: string): Promise<boolean> {
250
- const legacyDir = legacyAgentkitCursorSkillsDir(skillsHome);
251
- try {
252
- await stat(legacyDir);
253
- } catch {
254
- return false;
250
+ /** Drop leftover earlier install folders so stale skill ids are not discovered. */
251
+ async function removeLegacyCursorSkillsNamespaces(skillsHome: string): Promise<string[]> {
252
+ const present = await existingLegacyCursorSkillsDirs(skillsHome);
253
+ for (const dir of present) {
254
+ await rm(dir, { recursive: true, force: true });
255
255
  }
256
- await rm(legacyDir, { recursive: true, force: true });
257
- return true;
256
+ return present;
258
257
  }
259
258
 
260
- async function hasLegacyCursorSkillsNamespace(skillsHome: string): Promise<boolean> {
261
- try {
262
- await stat(legacyAgentkitCursorSkillsDir(skillsHome));
263
- return true;
264
- } catch {
265
- return false;
259
+ async function existingLegacyCursorSkillsDirs(skillsHome: string): Promise<string[]> {
260
+ const present: string[] = [];
261
+ for (const dir of legacyCursorSkillsDirs(skillsHome)) {
262
+ try {
263
+ await stat(dir);
264
+ present.push(dir);
265
+ } catch {
266
+ continue;
267
+ }
266
268
  }
269
+ return present;
267
270
  }
268
271
 
269
272
  /**
@@ -289,7 +292,7 @@ export function prepareSkillMarkdownForCursorInstall(
289
292
  adjustedBody.includes(PACKAGE_VERSION_PLACEHOLDER) &&
290
293
  (packageVersion === undefined || packageVersion.trim() === "")
291
294
  ) {
292
- throw new Error("Cannot install an Agent SDK skill without a package version.");
295
+ throw new Error("Cannot install a BDK skill without a package version.");
293
296
  }
294
297
  const versionBoundBody =
295
298
  packageVersion === undefined
@@ -333,7 +336,7 @@ export interface SkillInstallPlan {
333
336
  shipped: PackageSkill[];
334
337
  /** Resolved `~/.cursor/skills`, to install into. */
335
338
  skillsHome: string;
336
- /** Install target: `<skillsHome>/agentsdk`. */
339
+ /** Install target: `<skillsHome>/bdk`. */
337
340
  directory: string;
338
341
  /** Leaf dirs the package ships. */
339
342
  leaves: string[];
@@ -341,8 +344,8 @@ export interface SkillInstallPlan {
341
344
  firstInstall: boolean;
342
345
  /** Installed leaf dirs the package dropped; installing deletes them. */
343
346
  orphans: string[];
344
- /** True when leftover `skillsHome/agentkit` still exists. */
345
- hasLegacyNamespace: boolean;
347
+ /** Leftover namespace dirs that still exist. Installing deletes them. */
348
+ legacyDirs: string[];
346
349
  }
347
350
 
348
351
  /** What an install would do, for the offer and for `install-skills`. */
@@ -351,7 +354,7 @@ export async function planSkillInstall(options?: {
351
354
  skillsHome?: string;
352
355
  }): Promise<SkillInstallPlan> {
353
356
  const skillsHome = options?.skillsHome ?? cursorSkillsHome();
354
- const directory = agentsdkCursorSkillsDir(skillsHome);
357
+ const directory = bdkCursorSkillsDir(skillsHome);
355
358
  const shipped = await listShippedPackageSkills(options?.packageRoot);
356
359
  const present = await Promise.all(
357
360
  shipped.map(async skill => {
@@ -370,20 +373,20 @@ export async function planSkillInstall(options?: {
370
373
  leaves: shipped.map(skill => skill.leafDir),
371
374
  firstInstall: present.every(isPresent => !isPresent),
372
375
  orphans: await orphanLeaves(directory, shipped),
373
- hasLegacyNamespace: await hasLegacyCursorSkillsNamespace(skillsHome),
376
+ legacyDirs: await existingLegacyCursorSkillsDirs(skillsHome),
374
377
  };
375
378
  }
376
379
 
377
- /** `Installed 9 Agent SDK skills`, what it dropped, and where it went. */
380
+ /** `Installed 9 BDK skills`, what it dropped, and where it went. */
378
381
  export function formatSkillInstall(plan: SkillInstallPlan, result: SkillInstallResult): string {
379
382
  const noun = result.installed.length === 1 ? "skill" : "skills";
380
383
  const verb = plan.firstInstall ? "Installed" : "Updated";
381
- const lines = [`${verb} ${result.installed.length} Agent SDK ${noun}`];
384
+ const lines = [`${verb} ${result.installed.length} BDK ${noun}`];
382
385
  if (result.removed.length > 0) {
383
386
  lines.push(` removed: ${result.removed.join(", ")}`);
384
387
  }
385
- if (result.removedLegacyNamespace) {
386
- lines.push(` removed: ${legacyAgentkitCursorSkillsDir(plan.skillsHome)} (legacy namespace)`);
388
+ for (const dir of result.removedLegacyDirs) {
389
+ lines.push(` removed: ${dir}`);
387
390
  }
388
391
  lines.push(` location: ${plan.directory}`);
389
392
  return `${lines.join("\n")}\n`;
@@ -406,7 +409,7 @@ export interface SyncCursorSkillsOnPackageInstallOptions {
406
409
  }
407
410
 
408
411
  /**
409
- * Copy shipped coding-agent skills into ~/.cursor/skills/agentsdk during a
412
+ * Copy shipped coding-agent skills into ~/.cursor/skills/bdk during a
410
413
  * consumer `npm install` / `npx`. Never throws: a failed copy must not fail
411
414
  * the package install. No-op in the monorepo source tree and when
412
415
  * `CURSOR_JULY_SKIP_SKILL_INSTALL=1`.
@@ -459,7 +462,7 @@ export interface OfferInstallCursorSkillsOptions {
459
462
 
460
463
  /**
461
464
  * On a TTY, offer to install/update every shipped package skill into
462
- * ~/.cursor/skills/agentsdk (always overwriting). No-op when non-interactive
465
+ * ~/.cursor/skills/bdk (always overwriting). No-op when non-interactive
463
466
  * or the package ships no skills. An unanswered prompt skips the install
464
467
  * rather than blocking the caller — see `SKILL_PROMPT_TIMEOUT_MS`.
465
468
  */
@@ -484,7 +487,7 @@ export async function offerInstallCursorSkills(
484
487
  const noun = plan.shipped.length === 1 ? "skill" : "skills";
485
488
  const verb = plan.firstInstall ? "Install" : "Update";
486
489
  const c = stdoutPalette();
487
- out(`${verb} ${plan.shipped.length} Agent SDK ${noun} in ${plan.directory}?\n`);
490
+ out(`${verb} ${plan.shipped.length} BDK ${noun} in ${plan.directory}?\n`);
488
491
  out(c.dim(` ${plan.leaves.join(", ")}\n`));
489
492
  if (!plan.firstInstall) {
490
493
  out(c.dim(" (overwrites existing copies with the package version)\n"));
@@ -492,8 +495,8 @@ export async function offerInstallCursorSkills(
492
495
  if (plan.orphans.length > 0) {
493
496
  out(c.dim(` (deletes ${plan.orphans.join(", ")})\n`));
494
497
  }
495
- if (plan.hasLegacyNamespace) {
496
- out(c.dim(` (deletes leftover ${legacyAgentkitCursorSkillsDir(plan.skillsHome)})\n`));
498
+ for (const dir of plan.legacyDirs) {
499
+ out(c.dim(` (deletes leftover ${dir})\n`));
497
500
  }
498
501
 
499
502
  const confirm =
@@ -1,4 +1,5 @@
1
1
  import { type AgentServeDeployClient, DeployApiError } from "./deploy-client.js";
2
+ import { CLI_COMMAND_NAME } from "./distribution.js";
2
3
 
3
4
  /**
4
5
  * Classify a hosted slug by probing the v2 control plane.
@@ -27,9 +28,20 @@ export async function deploymentArchitecture(args: {
27
28
  }
28
29
  }
29
30
 
31
+ /** `run --prod` returns a delivery; read the session after it is allocated. */
32
+ export function v2HostedVerifyHint(slug = "<slug>"): string {
33
+ return (
34
+ `\`${CLI_COMMAND_NAME} run --prod\` returns a delivery. ` +
35
+ `An accept without sessionId is expected. ` +
36
+ `Poll the delivery until the session is allocated, then ` +
37
+ `\`${CLI_COMMAND_NAME} session <ses_> --prod --slug ${slug}\`.`
38
+ );
39
+ }
40
+
30
41
  export function unsupportedV2LegacyCommandError(slug: string): DeployApiError {
31
42
  return new DeployApiError(
32
- `This command is not supported for architecture v2 deployment "${slug}". The command stopped before calling the legacy v1 deployment API.`,
43
+ `This command is not supported for architecture v2 deployment "${slug}". ` +
44
+ `call and sessions stay on the v1 API. ${v2HostedVerifyHint(slug)}`,
33
45
  409,
34
46
  );
35
47
  }
@@ -24,6 +24,10 @@ import {
24
24
  type JsonObject,
25
25
  type McpToolAnnotations,
26
26
  } from "../types.js";
27
+ import {
28
+ connectionCredentialsFingerprint,
29
+ resolveConnectionEnvTemplates,
30
+ } from "./connection-env.js";
27
31
  import { CLI_COMMAND_NAME as CLI } from "./distribution.js";
28
32
  import { createHostMcpOAuthProvider } from "./mcp-oauth.js";
29
33
  import { instrumentedMcpFetch, mcpTraceMeta, runMcpClientSpan } from "./otel/mcp.js";
@@ -67,6 +71,12 @@ interface OpenedConnection {
67
71
  close: () => Promise<void>;
68
72
  }
69
73
 
74
+ interface CachedClient {
75
+ /** Fingerprint of the credentials this client opened with. */
76
+ credentials: string;
77
+ opened: Promise<OpenedConnection>;
78
+ }
79
+
70
80
  /**
71
81
  * A non-caching view of one connection: every operation opens a fresh
72
82
  * client and closes it afterwards. See {@link McpHost.oneOff}.
@@ -78,7 +88,7 @@ export interface HostMcpOneOff {
78
88
 
79
89
  export class McpHost implements HostMcpRegistry {
80
90
  private readonly byName = new Map<string, DiscoveredConnection>();
81
- private readonly clients = new Map<string, Promise<OpenedConnection>>();
91
+ private readonly clients = new Map<string, CachedClient>();
82
92
  private oauthRedirectUrl: string | undefined;
83
93
 
84
94
  constructor(connections: DiscoveredConnection[]) {
@@ -187,20 +197,20 @@ export class McpHost implements HostMcpRegistry {
187
197
  }
188
198
 
189
199
  async dropClient(name: string): Promise<void> {
190
- const pending = this.clients.get(name);
200
+ const cached = this.clients.get(name);
191
201
  this.clients.delete(name);
192
- if (pending === undefined) {
202
+ if (cached === undefined) {
193
203
  return;
194
204
  }
195
205
  try {
196
- await (await pending).close();
206
+ await (await cached.opened).close();
197
207
  } catch {
198
208
  // Best-effort teardown.
199
209
  }
200
210
  }
201
211
 
202
212
  async close(): Promise<void> {
203
- const opened = await Promise.allSettled([...this.clients.values()]);
213
+ const opened = await Promise.allSettled([...this.clients.values()].map(entry => entry.opened));
204
214
  this.clients.clear();
205
215
  await Promise.allSettled(
206
216
  opened.map(async settled => {
@@ -234,23 +244,41 @@ export class McpHost implements HostMcpRegistry {
234
244
  }
235
245
  }
236
246
 
247
+ /**
248
+ * Cached per connection, but only for as long as the credentials it opened
249
+ * with still apply: a hosted deployment binds its secrets per request, so a
250
+ * rotated (or first-ever) value would otherwise never reach a client opened
251
+ * on an earlier turn.
252
+ */
237
253
  private getClient(name: string): Promise<OpenedConnection> {
238
- let pending = this.clients.get(name);
239
- if (pending === undefined) {
240
- pending = this.connect(name).catch(error => {
241
- this.clients.delete(name);
242
- throw error;
243
- });
244
- this.clients.set(name, pending);
254
+ const credentials = connectionCredentialsFingerprint(this.requireConnection(name).transport);
255
+ const cached = this.clients.get(name);
256
+ if (cached !== undefined) {
257
+ if (cached.credentials === credentials) {
258
+ return cached.opened;
259
+ }
260
+ void this.dropClient(name);
245
261
  }
246
- return pending;
262
+ // Only evict this entry: a connect that fails after its credentials were
263
+ // replaced would otherwise orphan the client that replaced it.
264
+ const entry: CachedClient = {
265
+ credentials,
266
+ opened: this.connect(name).catch(error => {
267
+ if (this.clients.get(name) === entry) {
268
+ this.clients.delete(name);
269
+ }
270
+ throw error;
271
+ }),
272
+ };
273
+ this.clients.set(name, entry);
274
+ return entry.opened;
247
275
  }
248
276
 
249
277
  private async invalidateClient(name: string, opened: OpenedConnection): Promise<void> {
250
- const pending = this.clients.get(name);
251
- if (pending !== undefined) {
278
+ const cached = this.clients.get(name);
279
+ if (cached !== undefined) {
252
280
  try {
253
- if ((await pending) === opened) {
281
+ if ((await cached.opened) === opened) {
254
282
  this.clients.delete(name);
255
283
  }
256
284
  } catch {
@@ -385,7 +413,7 @@ async function openConnection(
385
413
  }
386
414
 
387
415
  async function createTransport(connection: DiscoveredConnection, oauthRedirectUrl?: string) {
388
- const transport = connection.transport;
416
+ const transport = resolveConnectionEnvTemplates(connection.transport);
389
417
  if ("agent" in transport) {
390
418
  // Peers are resolved to concrete URLs by the serve host before any call
391
419
  // (SessionEngine.setResolvedConnections); reaching here means the
@@ -210,12 +210,23 @@ export function isModelCapacityError(
210
210
  message: string | undefined,
211
211
  code?: string | undefined,
212
212
  ): boolean {
213
+ if (isGithubApiRateLimitMessage(message)) {
214
+ return false;
215
+ }
213
216
  if (code !== undefined && /^(resource_exhausted|unavailable)$/i.test(code)) {
214
217
  return true;
215
218
  }
216
219
  return message !== undefined && /resource_exhausted|\[unavailable\]/i.test(message);
217
220
  }
218
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
+
219
230
  export function isModelCapacityErrorMessage(message: string | undefined): boolean {
220
231
  return isModelCapacityError(message);
221
232
  }
@@ -377,8 +377,14 @@ export async function startServer(
377
377
  // The SCM relay reads the event stream as the signed-in user, so
378
378
  // `cursorEvents` cannot work signed out. Require the credential before any
379
379
  // slow or stateful startup work (playground build, channel onStart, cron).
380
+ // Not on a hosted v2 guest: under `--no-control-plane` with no v1 mount
381
+ // this process never polls `/v0/scm-events` (the hosted control plane
382
+ // owns ingest), and a persistent slot starts before its first credential
383
+ // is bound, so demanding one here would refuse a guest that never needed it.
384
+ const hostedControlPlaneOwnsIngest =
385
+ noControlPlane && mounts.every(mount => isV2Project(mount.project));
380
386
  const cursorEventsAuth =
381
- effectiveCursorEvents === undefined
387
+ effectiveCursorEvents === undefined || hostedControlPlaneOwnsIngest
382
388
  ? undefined
383
389
  : requireCursorEventsAuth(effectiveCursorEvents, accountKey);
384
390
 
@@ -1136,6 +1142,12 @@ export async function startServer(
1136
1142
  "[agent-sdk] cursor-events: skipping v2 scm-events poll (--no-control-plane); hosted CP owns ingest",
1137
1143
  );
1138
1144
  }
1145
+ } else if (hostedControlPlaneOwnsIngest && effectiveCursorEvents !== undefined) {
1146
+ // No credential was required above, so no relay object was built; the
1147
+ // outcome is the same skip.
1148
+ logger(
1149
+ "[agent-sdk] cursor-events: skipping v2 scm-events poll (--no-control-plane); hosted CP owns ingest",
1150
+ );
1139
1151
  }
1140
1152
 
1141
1153
  // Cursor deployment-events relay: automatic when a mounted agent authored
@@ -104,6 +104,7 @@ import {
104
104
  isUnpricedCompletedTurn,
105
105
  mapSdkTokenUsage,
106
106
  } from "./cloud-turn-cost.js";
107
+ import { resolveConnectionEnvTemplates } from "./connection-env.js";
107
108
  import {
108
109
  applyAgentContinuationDefaults,
109
110
  channelContinuationIdentity,
@@ -3002,7 +3003,7 @@ export class SessionEngine {
3002
3003
  if (evaluated === undefined) {
3003
3004
  continue;
3004
3005
  }
3005
- const transport = connection.transport;
3006
+ const transport = resolveConnectionEnvTemplates(connection.transport);
3006
3007
  if ("url" in transport) {
3007
3008
  servers[connection.name] = {
3008
3009
  ...transport,
@@ -3011,7 +3012,9 @@ export class SessionEngine {
3011
3012
  }
3012
3013
  continue;
3013
3014
  }
3014
- servers[connection.name] = connection.transport;
3015
+ // Templated credentials resolve here, once per turn: the module that
3016
+ // declared them was imported before the platform bound any secret.
3017
+ servers[connection.name] = resolveConnectionEnvTemplates(connection.transport);
3015
3018
  }
3016
3019
  for (const resolved of this.resolvedConnections) {
3017
3020
  if (advertisedNames.has(resolved.name) || hostConnectionNames.has(resolved.name)) {
@@ -3660,11 +3663,12 @@ export class SessionEngine {
3660
3663
  if (!isHostOauthConnectionTransport(authored.transport)) {
3661
3664
  return undefined;
3662
3665
  }
3666
+ const transport = resolveConnectionEnvTemplates(authored.transport);
3663
3667
  return await this.oauthHub.mint({
3664
3668
  connection,
3665
- url: authored.transport.url,
3666
- type: authored.transport.type === "sse" ? "sse" : "http",
3667
- headers: authored.transport.headers,
3669
+ url: transport.url,
3670
+ type: transport.type === "sse" ? "sse" : "http",
3671
+ headers: transport.headers,
3668
3672
  sessionId,
3669
3673
  });
3670
3674
  }
package/src/types.ts CHANGED
@@ -342,7 +342,10 @@ export interface AgentHostingOptions {
342
342
  * Domains the deployed engine pod may reach (egress allowlist), e.g.
343
343
  * `"api.example.com"` or `"*.example.com"` (single leading wildcard).
344
344
  * Lowercase hostnames with at least two labels and an alphabetic TLD;
345
- * max 20. `agent-sdk deploy` sends these as `egressAllowedDomains`
345
+ * max 64. A `"host:port"` entry (e.g. `"clickhouse.example.com:9440"`)
346
+ * opens raw TCP to that host's addresses, for wire protocols the proxy
347
+ * cannot read a TLS hostname from.
348
+ * `agent-sdk deploy` sends these as `egressAllowedDomains`
346
349
  * (unioned with any `--allow-domain` flags). Only valid on repo-backed
347
350
  * deployments. Deployment-scoped like {@link secretNames}: not capped by
348
351
  * the team's Cloud Agent egress allowlist. The platform still merges a
@@ -1219,6 +1222,13 @@ export interface DiscoveredExtension {
1219
1222
  * resolves to a bridge on this host that executes every tool **on the
1220
1223
  * Cursor backend** with the account's stored OAuth credentials — tokens
1221
1224
  * never reach this host.
1225
+ *
1226
+ * Credentials belong in `headers` (http/sse) and `env` (stdio) as `${NAME}`
1227
+ * templates, which the transport keeps verbatim and expands from the
1228
+ * environment each time a client opens. Reading `process.env` in the
1229
+ * connection module instead pins whatever the variable held when discovery
1230
+ * imported it, which on Cursor hosting is nothing: the platform binds a
1231
+ * deployment's secrets per request, long after that import.
1222
1232
  */
1223
1233
  export type ConnectionTransport =
1224
1234
  | {
@@ -335,10 +335,7 @@ async function readFile(
335
335
  ): Promise<string | undefined> {
336
336
  try {
337
337
  const { data } = await octokit.rest.repos.getContent(args);
338
- if (Array.isArray(data) || data.encoding !== "base64") {
339
- return undefined;
340
- }
341
- if (typeof data.content !== "string") {
338
+ if (Array.isArray(data) || data.type !== "file" || data.encoding !== "base64") {
342
339
  return undefined;
343
340
  }
344
341
  return Buffer.from(data.content, "base64").toString("utf8");
@@ -90,8 +90,8 @@ async function loadWiki(
90
90
  if (
91
91
  body === undefined ||
92
92
  Array.isArray(body) ||
93
- body.encoding !== "base64" ||
94
- typeof body.content !== "string"
93
+ body.type !== "file" ||
94
+ body.encoding !== "base64"
95
95
  ) {
96
96
  return;
97
97
  }
@@ -12,7 +12,11 @@ function wake(url: string, github: GitHubHandle) {
12
12
  if (start === undefined || ref === undefined) {
13
13
  return null;
14
14
  }
15
- return { task: () => startDemo(start, github, ref) };
15
+ return {
16
+ task: async () => {
17
+ await startDemo(start, github, ref);
18
+ },
19
+ };
16
20
  }
17
21
 
18
22
  export default githubChannel({
@@ -7,13 +7,13 @@ import { fetchPrState, isTerminalPrState } from "./pr-state.js";
7
7
 
8
8
  export type StartDriveErrorCode = "missing_pr" | "unrecognized_pr";
9
9
 
10
- export interface StartDriveError {
10
+ export type StartDriveError = {
11
11
  ok: false;
12
12
  code: StartDriveErrorCode;
13
13
  error: string;
14
- }
14
+ };
15
15
 
16
- export interface StartDriveSuccess {
16
+ export type StartDriveSuccess = {
17
17
  ok: true;
18
18
  pr: string;
19
19
  sessionId: string | null;
@@ -23,7 +23,7 @@ export interface StartDriveSuccess {
23
23
  status: string;
24
24
  result: string | null;
25
25
  mergeConflictReminderId: string | null;
26
- }
26
+ };
27
27
 
28
28
  export type StartDriveResult = StartDriveError | StartDriveSuccess;
29
29