@cursor/bdk 0.2.3 → 0.2.5

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 (760) hide show
  1. package/README.md +76 -1154
  2. package/dist/bin/agent-serve.js +9 -1
  3. package/dist/channels/slack/attachments.d.ts +2 -1
  4. package/dist/channels/slack/attachments.d.ts.map +1 -1
  5. package/dist/channels/slack/attachments.js +19 -9
  6. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  7. package/dist/channels/slack/dispatch.js +26 -24
  8. package/dist/channels/slack/thread-context.d.ts +21 -11
  9. package/dist/channels/slack/thread-context.d.ts.map +1 -1
  10. package/dist/channels/slack/thread-context.js +75 -27
  11. package/dist/docs/404.html +2 -2
  12. package/dist/docs/assets/{app.BOIHhrKi.js → app.94Iu5dyD.js} +4 -4
  13. package/dist/docs/assets/{building-with-agents.md.-fcjCmJU.js → building-with-agents.md.BPjPFxFg.js} +2 -2
  14. package/dist/docs/assets/{building-with-agents.md.-fcjCmJU.lean.js → building-with-agents.md.BPjPFxFg.lean.js} +1 -1
  15. package/dist/docs/assets/chunks/@localSearchIndexroot.BITLoOQa.js +1 -0
  16. package/dist/docs/assets/chunks/{VPLocalSearchBox.D49zVZqM.js → VPLocalSearchBox.DTKFDlBr.js} +1 -1
  17. package/dist/docs/assets/chunks/{arc.hmjb-sc4.js → arc.DuzwHEeg.js} +1 -1
  18. package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.CxEI1KqM.js → architectureDiagram-Q4EWVU46.C6lyhLs0.js} +1 -1
  19. package/dist/docs/assets/chunks/{baseUniq.DHHvBWoV.js → baseUniq.DUNEWlY8.js} +1 -1
  20. package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.DnXW-3bu.js → blockDiagram-DXYQGD6D.CXOQGI0O.js} +1 -1
  21. package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.e-47O2jM.js → c4Diagram-AHTNJAMY.BYdPE-Oe.js} +1 -1
  22. package/dist/docs/assets/chunks/channel.B46uXH41.js +1 -0
  23. package/dist/docs/assets/chunks/{chunk-4BX2VUAB.3ry4pYXB.js → chunk-4BX2VUAB.YIV9HeX0.js} +1 -1
  24. package/dist/docs/assets/chunks/{chunk-4TB4RGXK.DGIZFRx6.js → chunk-4TB4RGXK.BG80DEOc.js} +1 -1
  25. package/dist/docs/assets/chunks/{chunk-55IACEB6.DKBnqg9U.js → chunk-55IACEB6.BDKJSZQc.js} +1 -1
  26. package/dist/docs/assets/chunks/{chunk-EDXVE4YY.BIU8Ue5k.js → chunk-EDXVE4YY.CtYnQqts.js} +1 -1
  27. package/dist/docs/assets/chunks/{chunk-FMBD7UC4.DP-TFhjI.js → chunk-FMBD7UC4.CityOth-.js} +1 -1
  28. package/dist/docs/assets/chunks/{chunk-OYMX7WX6.Ux0OYj5v.js → chunk-OYMX7WX6.CMD22CQX.js} +1 -1
  29. package/dist/docs/assets/chunks/{chunk-QZHKN3VN.BzHMwYox.js → chunk-QZHKN3VN.WWpc3ND0.js} +1 -1
  30. package/dist/docs/assets/chunks/{chunk-YZCP3GAM.D4OGAsSP.js → chunk-YZCP3GAM.BMg-yhj3.js} +1 -1
  31. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.0cmCFsSf.js +1 -0
  32. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.0cmCFsSf.js +1 -0
  33. package/dist/docs/assets/chunks/clone.1vTOFZT1.js +1 -0
  34. package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.Jq_7BUNx.js → cose-bilkent-S5V4N54A.Buu_LC5q.js} +1 -1
  35. package/dist/docs/assets/chunks/{dagre-KV5264BT.Di-skR2x.js → dagre-KV5264BT.DW7onj6E.js} +1 -1
  36. package/dist/docs/assets/chunks/{diagram-5BDNPKRD.DeREHIdH.js → diagram-5BDNPKRD.B3NxIbEV.js} +1 -1
  37. package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.C7Kcqxro.js → diagram-G4DWMVQ6.BJvN6Vkv.js} +1 -1
  38. package/dist/docs/assets/chunks/{diagram-MMDJMWI5.BK3eohyo.js → diagram-MMDJMWI5.wfRWrexs.js} +1 -1
  39. package/dist/docs/assets/chunks/{diagram-TYMM5635.C6TyymXT.js → diagram-TYMM5635.7QtjSYio.js} +1 -1
  40. package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.DYGG-gGx.js → erDiagram-SMLLAGMA.jxPgDH1t.js} +1 -1
  41. package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.C9nBcSV4.js → flowDiagram-DWJPFMVM.BhDWA-TO.js} +1 -1
  42. package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.wAg_ymsp.js → ganttDiagram-T4ZO3ILL.Ijq8iYKv.js} +1 -1
  43. package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.B87j9Oeg.js → gitGraphDiagram-UUTBAWPF.DXpfW4YG.js} +1 -1
  44. package/dist/docs/assets/chunks/{graph.CuFMj31w.js → graph.CoPlssRl.js} +1 -1
  45. package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.P_mLGumP.js → infoDiagram-42DDH7IO.eJuv_EOz.js} +1 -1
  46. package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.DyuL_MsT.js → ishikawaDiagram-UXIWVN3A._OEzenCR.js} +1 -1
  47. package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.CtP09IoJ.js → journeyDiagram-VCZTEJTY.CwlTjirB.js} +1 -1
  48. package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.BoeSYPZo.js → kanban-definition-6JOO6SKY.DSp_C8cZ.js} +1 -1
  49. package/dist/docs/assets/chunks/{layout.B0lMMtNo.js → layout.Bms9s7uB.js} +1 -1
  50. package/dist/docs/assets/chunks/{linear.HxRBiAFX.js → linear.BjnmB4je.js} +1 -1
  51. package/dist/docs/assets/chunks/{min.BGlFFHwS.js → min.CKkYlMsn.js} +1 -1
  52. package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.JyLBD9M8.js → mindmap-definition-QFDTVHPH.T2d0vJ7X.js} +1 -1
  53. package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.DnSmNZF8.js → pieDiagram-DEJITSTG.DU0RoCvx.js} +1 -1
  54. package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.CUCnbfCa.js → quadrantDiagram-34T5L4WZ.9QZjM-x0.js} +1 -1
  55. package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.py0IVUn5.js → requirementDiagram-MS252O5E.CZpylJMd.js} +1 -1
  56. package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.Bkc-HWYp.js → sankeyDiagram-XADWPNL6.CnFdfW95.js} +1 -1
  57. package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.Dqn8Mlv2.js → sequenceDiagram-FGHM5R23.-jC0PP1t.js} +1 -1
  58. package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.JikkoQUU.js → stateDiagram-FHFEXIEX.DG7yBRUU.js} +1 -1
  59. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.CbsZcOOu.js +1 -0
  60. package/dist/docs/assets/chunks/{theme.b6HQ6zG_.js → theme.B3O9koXV.js} +2 -2
  61. package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.BvpSXiBj.js → timeline-definition-GMOUNBTQ.Bf9u4Ebb.js} +1 -1
  62. package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.CU7MVnZx.js → vennDiagram-DHZGUBPP.BjhbbYE6.js} +1 -1
  63. package/dist/docs/assets/chunks/{wardley-RL74JXVD.BKwC4ctG.js → wardley-RL74JXVD.DEA21akR.js} +1 -1
  64. package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.BfaF6Uhe.js → wardleyDiagram-NUSXRM2D.8fRb4Nb5.js} +1 -1
  65. package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.Bg5dcpj4.js → xychartDiagram-5P7HB3ND.DoOP3zZM.js} +1 -1
  66. package/dist/docs/assets/{deployment.md.BJ8i7Q6p.js → deployment.md.BdqTiGdc.js} +5 -5
  67. package/dist/docs/assets/{deployment.md.BJ8i7Q6p.lean.js → deployment.md.BdqTiGdc.lean.js} +1 -1
  68. package/dist/docs/assets/{evals.md.CCAtNcuL.js → evals.md.LRCSn6Ik.js} +2 -2
  69. package/dist/docs/assets/{evals.md.CCAtNcuL.lean.js → evals.md.LRCSn6Ik.lean.js} +1 -1
  70. package/dist/docs/assets/{guides_agent-to-agent.md.CGkicXeB.js → guides_agent-to-agent.md.Cps5NiCV.js} +2 -2
  71. package/dist/docs/assets/{guides_agent-to-agent.md.CGkicXeB.lean.js → guides_agent-to-agent.md.Cps5NiCV.lean.js} +1 -1
  72. package/dist/docs/assets/{guides_bitbucket.md.Cb3LPKt3.js → guides_bitbucket.md.BB6fqD-M.js} +2 -2
  73. package/dist/docs/assets/{guides_bitbucket.md.Cb3LPKt3.lean.js → guides_bitbucket.md.BB6fqD-M.lean.js} +1 -1
  74. package/dist/docs/assets/{guides_cloud-agents.md.BuEkDCwo.js → guides_cloud-agents.md.CWJjS9No.js} +2 -2
  75. package/dist/docs/assets/{guides_cloud-agents.md.BuEkDCwo.lean.js → guides_cloud-agents.md.CWJjS9No.lean.js} +1 -1
  76. package/dist/docs/assets/{guides_convert-automation.md.Ci-Y2iD5.js → guides_convert-automation.md.DMEX9nF-.js} +3 -3
  77. package/dist/docs/assets/{guides_convert-automation.md.Ci-Y2iD5.lean.js → guides_convert-automation.md.DMEX9nF-.lean.js} +1 -1
  78. package/dist/docs/assets/{guides_github.md.Bq9kQU9B.js → guides_github.md.Cr1Xlf-m.js} +3 -3
  79. package/dist/docs/assets/{guides_github.md.Bq9kQU9B.lean.js → guides_github.md.Cr1Xlf-m.lean.js} +1 -1
  80. package/dist/docs/assets/{guides_gitlab.md.BM27P43u.js → guides_gitlab.md.CMpmFi4M.js} +2 -2
  81. package/dist/docs/assets/{guides_gitlab.md.BM27P43u.lean.js → guides_gitlab.md.CMpmFi4M.lean.js} +1 -1
  82. package/dist/docs/assets/{guides_grokbot-agents.md.yxVbSlKA.js → guides_grokbot-agents.md.tD1smFhU.js} +2 -2
  83. package/dist/docs/assets/{guides_grokbot-agents.md.yxVbSlKA.lean.js → guides_grokbot-agents.md.tD1smFhU.lean.js} +1 -1
  84. package/dist/docs/assets/{guides_hooks.md.BWoiNaMq.js → guides_hooks.md.5Ce3NXxZ.js} +2 -2
  85. package/dist/docs/assets/{guides_hooks.md.BWoiNaMq.lean.js → guides_hooks.md.5Ce3NXxZ.lean.js} +1 -1
  86. package/dist/docs/assets/{guides_improve.md.COtL-6ft.js → guides_improve.md.CRrYq22s.js} +2 -2
  87. package/dist/docs/assets/{guides_improve.md.COtL-6ft.lean.js → guides_improve.md.CRrYq22s.lean.js} +1 -1
  88. package/dist/docs/assets/{guides_jev.md.BNDm14Gy.js → guides_jev.md.D7XH4JH3.js} +2 -2
  89. package/dist/docs/assets/{guides_mcp-oauth.md.Cu6mhZ_3.js → guides_mcp-oauth.md.DR3zhC9r.js} +2 -2
  90. package/dist/docs/assets/{guides_mcp-oauth.md.Cu6mhZ_3.lean.js → guides_mcp-oauth.md.DR3zhC9r.lean.js} +1 -1
  91. package/dist/docs/assets/{guides_opentelemetry.md.DLlIB5rv.js → guides_opentelemetry.md.jcPNrQbH.js} +8 -6
  92. package/dist/docs/assets/{guides_opentelemetry.md.DLlIB5rv.lean.js → guides_opentelemetry.md.jcPNrQbH.lean.js} +1 -1
  93. package/dist/docs/assets/{guides_slack.md.diqqXTTm.js → guides_slack.md.Bn-WupSE.js} +8 -8
  94. package/dist/docs/assets/{guides_slack.md.diqqXTTm.lean.js → guides_slack.md.Bn-WupSE.lean.js} +1 -1
  95. package/dist/docs/assets/{guides_webhooks.md.D0furjw0.js → guides_webhooks.md.BBvAm_VF.js} +2 -2
  96. package/dist/docs/assets/{guides_webhooks.md.D0furjw0.lean.js → guides_webhooks.md.BBvAm_VF.lean.js} +1 -1
  97. package/dist/docs/assets/{hillclimbing.md.Biy0m-Qb.js → hillclimbing.md.Dxvd-0gT.js} +2 -2
  98. package/dist/docs/assets/{hillclimbing.md.Biy0m-Qb.lean.js → hillclimbing.md.Dxvd-0gT.lean.js} +1 -1
  99. package/dist/docs/assets/index.md.Dxxr7pFa.js +27 -0
  100. package/dist/docs/assets/{index.md.CVc_oOA3.lean.js → index.md.Dxxr7pFa.lean.js} +1 -1
  101. package/dist/docs/assets/{quickstart.md.CHpHPBUN.js → quickstart.md.BK5gjHM2.js} +2 -2
  102. package/dist/docs/assets/{quickstart.md.CHpHPBUN.lean.js → quickstart.md.BK5gjHM2.lean.js} +1 -1
  103. package/dist/docs/assets/{reference_agent-config.md.DzGI777n.js → reference_agent-config.md.DrtLxWgR.js} +4 -4
  104. package/dist/docs/assets/{reference_agent-config.md.DzGI777n.lean.js → reference_agent-config.md.DrtLxWgR.lean.js} +1 -1
  105. package/dist/docs/assets/{reference_artifacts.md.CQfKq8F2.js → reference_artifacts.md.DLV9MZES.js} +2 -2
  106. package/dist/docs/assets/{reference_artifacts.md.CQfKq8F2.lean.js → reference_artifacts.md.DLV9MZES.lean.js} +1 -1
  107. package/dist/docs/assets/{reference_channels.md.mbNtKCiR.js → reference_channels.md.LbNIJBwd.js} +2 -2
  108. package/dist/docs/assets/{reference_channels.md.mbNtKCiR.lean.js → reference_channels.md.LbNIJBwd.lean.js} +1 -1
  109. package/dist/docs/assets/{reference_cli.md.DgeLTO18.js → reference_cli.md.BsgDqYPh.js} +4 -4
  110. package/dist/docs/assets/{reference_cli.md.DgeLTO18.lean.js → reference_cli.md.BsgDqYPh.lean.js} +1 -1
  111. package/dist/docs/assets/{reference_connections.md.COq--gAm.js → reference_connections.md.Bljpve-y.js} +4 -4
  112. package/dist/docs/assets/{reference_connections.md.COq--gAm.lean.js → reference_connections.md.Bljpve-y.lean.js} +1 -1
  113. package/dist/docs/assets/{reference_evals.md.CJm3uCUm.js → reference_evals.md.D5i8PuXJ.js} +2 -2
  114. package/dist/docs/assets/{reference_evals.md.CJm3uCUm.lean.js → reference_evals.md.D5i8PuXJ.lean.js} +1 -1
  115. package/dist/docs/assets/{reference_extensions.md.CPPrkWlJ.js → reference_extensions.md.OUacPetl.js} +5 -4
  116. package/dist/docs/assets/{reference_extensions.md.CPPrkWlJ.lean.js → reference_extensions.md.OUacPetl.lean.js} +1 -1
  117. package/dist/docs/assets/{reference_hooks.md.DbthhtIR.js → reference_hooks.md.C5LCJ1R3.js} +2 -2
  118. package/dist/docs/assets/{reference_hooks.md.DbthhtIR.lean.js → reference_hooks.md.C5LCJ1R3.lean.js} +1 -1
  119. package/dist/docs/assets/{reference_http-api.md.BZOvhCqY.js → reference_http-api.md.DbFNOubV.js} +1 -1
  120. package/dist/docs/assets/{reference_instructions.md.Bdwscs4G.js → reference_instructions.md.DrcHZXig.js} +2 -2
  121. package/dist/docs/assets/{reference_instructions.md.Bdwscs4G.lean.js → reference_instructions.md.DrcHZXig.lean.js} +1 -1
  122. package/dist/docs/assets/reference_playground.md.1hx0gcIu.js +1 -0
  123. package/dist/docs/assets/{reference_playground.md.BdQzRJc2.lean.js → reference_playground.md.1hx0gcIu.lean.js} +1 -1
  124. package/dist/docs/assets/{reference_project-layout.md.CpLQ9j4K.js → reference_project-layout.md.C2JMRh7p.js} +2 -2
  125. package/dist/docs/assets/{reference_prompt.md.BQZB4eaV.js → reference_prompt.md.DqPh71XN.js} +3 -3
  126. package/dist/docs/assets/{reference_prompt.md.BQZB4eaV.lean.js → reference_prompt.md.DqPh71XN.lean.js} +1 -1
  127. package/dist/docs/assets/{reference_schedules.md.BVU5EFbz.js → reference_schedules.md.BuJ8fgMa.js} +2 -2
  128. package/dist/docs/assets/{reference_schedules.md.BVU5EFbz.lean.js → reference_schedules.md.BuJ8fgMa.lean.js} +1 -1
  129. package/dist/docs/assets/reference_sessions.md.CM5zo3w4.js +1 -0
  130. package/dist/docs/assets/{reference_sessions.md.DeRUItHD.lean.js → reference_sessions.md.CM5zo3w4.lean.js} +1 -1
  131. package/dist/docs/assets/{reference_skills.md.Cy00QMKS.js → reference_skills.md.C0guGcH0.js} +4 -4
  132. package/dist/docs/assets/{reference_skills.md.Cy00QMKS.lean.js → reference_skills.md.C0guGcH0.lean.js} +1 -1
  133. package/dist/docs/assets/{reference_subagents.md.B8oyeXOI.js → reference_subagents.md.gmPt5J-M.js} +2 -2
  134. package/dist/docs/assets/{reference_subagents.md.B8oyeXOI.lean.js → reference_subagents.md.gmPt5J-M.lean.js} +1 -1
  135. package/dist/docs/assets/{reference_tools.md.hg2Wi5Bq.js → reference_tools.md.v3SXVSs_.js} +2 -2
  136. package/dist/docs/assets/{reference_tools.md.hg2Wi5Bq.lean.js → reference_tools.md.v3SXVSs_.lean.js} +1 -1
  137. package/dist/docs/assets/{templates_agentic-owners.md.BykUiZ8j.js → templates_agentic-owners.md.vtjfwxbf.js} +2 -2
  138. package/dist/docs/assets/{templates_agentic-owners.md.BykUiZ8j.lean.js → templates_agentic-owners.md.vtjfwxbf.lean.js} +1 -1
  139. package/dist/docs/assets/templates_grokbot-agents.md.2sydjFiO.js +5 -0
  140. package/dist/docs/assets/templates_grokbot-agents.md.2sydjFiO.lean.js +1 -0
  141. package/dist/docs/assets/{templates_security-reviewer.md.DXMmKl_o.js → templates_security-reviewer.md.CX9l9bcg.js} +2 -2
  142. package/dist/docs/assets/{templates_security-reviewer.md.DXMmKl_o.lean.js → templates_security-reviewer.md.CX9l9bcg.lean.js} +1 -1
  143. package/dist/docs/assets/{templates_thermo-quality-review.md.Dg1p1MsG.js → templates_thermo-quality-review.md.95qmTmr1.js} +2 -2
  144. package/dist/docs/assets/{templates_thermo-quality-review.md.Dg1p1MsG.lean.js → templates_thermo-quality-review.md.95qmTmr1.lean.js} +1 -1
  145. package/dist/docs/assets/{templates_thermo-review.md.Dlylkowj.js → templates_thermo-review.md.DQh6Q0C-.js} +2 -2
  146. package/dist/docs/assets/{templates_thermo-review.md.Dlylkowj.lean.js → templates_thermo-review.md.DQh6Q0C-.lean.js} +1 -1
  147. package/dist/docs/assets/{templates_triage.md.CvJyx81N.js → templates_triage.md.BFlQhWXf.js} +3 -3
  148. package/dist/docs/assets/{templates_triage.md.CvJyx81N.lean.js → templates_triage.md.BFlQhWXf.lean.js} +1 -1
  149. package/dist/docs/assets/troubleshooting.md.Bscj6ODe.js +1 -0
  150. package/dist/docs/assets/{troubleshooting.md.Cw5PKa3t.lean.js → troubleshooting.md.Bscj6ODe.lean.js} +1 -1
  151. package/dist/docs/building-with-agents.html +36 -36
  152. package/dist/docs/building-with-agents.md +0 -3
  153. package/dist/docs/deployment.html +39 -39
  154. package/dist/docs/deployment.md +6 -10
  155. package/dist/docs/evals.html +36 -36
  156. package/dist/docs/evals.md +0 -3
  157. package/dist/docs/guides/agent-to-agent.html +36 -36
  158. package/dist/docs/guides/agent-to-agent.md +0 -3
  159. package/dist/docs/guides/bitbucket.html +36 -36
  160. package/dist/docs/guides/bitbucket.md +0 -3
  161. package/dist/docs/guides/cloud-agents.html +36 -36
  162. package/dist/docs/guides/cloud-agents.md +0 -4
  163. package/dist/docs/guides/convert-automation.html +37 -37
  164. package/dist/docs/guides/convert-automation.md +2 -5
  165. package/dist/docs/guides/github.html +37 -37
  166. package/dist/docs/guides/github.md +1 -4
  167. package/dist/docs/guides/gitlab.html +36 -36
  168. package/dist/docs/guides/gitlab.md +0 -3
  169. package/dist/docs/guides/grokbot-agents.html +37 -37
  170. package/dist/docs/guides/grokbot-agents.md +1 -4
  171. package/dist/docs/guides/hooks.html +36 -36
  172. package/dist/docs/guides/hooks.md +0 -3
  173. package/dist/docs/guides/improve.html +36 -36
  174. package/dist/docs/guides/improve.md +0 -3
  175. package/dist/docs/guides/jev.html +37 -37
  176. package/dist/docs/guides/jev.md +7 -3
  177. package/dist/docs/guides/mcp-oauth.html +37 -37
  178. package/dist/docs/guides/mcp-oauth.md +1 -4
  179. package/dist/docs/guides/opentelemetry.html +42 -40
  180. package/dist/docs/guides/opentelemetry.md +4 -5
  181. package/dist/docs/guides/slack.html +43 -43
  182. package/dist/docs/guides/slack.md +14 -24
  183. package/dist/docs/guides/webhooks.html +36 -36
  184. package/dist/docs/guides/webhooks.md +0 -3
  185. package/dist/docs/hashmap.json +1 -1
  186. package/dist/docs/hillclimbing.html +36 -36
  187. package/dist/docs/hillclimbing.md +0 -3
  188. package/dist/docs/index.html +38 -38
  189. package/dist/docs/index.md +9 -16
  190. package/dist/docs/llms-full.txt +156 -220
  191. package/dist/docs/llms.txt +1 -0
  192. package/dist/docs/quickstart.html +36 -36
  193. package/dist/docs/quickstart.md +2 -7
  194. package/dist/docs/reference/agent-config.html +38 -38
  195. package/dist/docs/reference/agent-config.md +4 -7
  196. package/dist/docs/reference/artifacts.html +36 -36
  197. package/dist/docs/reference/artifacts.md +0 -3
  198. package/dist/docs/reference/channels.html +37 -37
  199. package/dist/docs/reference/channels.md +1 -6
  200. package/dist/docs/reference/cli.html +38 -38
  201. package/dist/docs/reference/cli.md +7 -14
  202. package/dist/docs/reference/connections.html +38 -38
  203. package/dist/docs/reference/connections.md +7 -10
  204. package/dist/docs/reference/evals.html +36 -36
  205. package/dist/docs/reference/evals.md +0 -3
  206. package/dist/docs/reference/extensions.html +40 -39
  207. package/dist/docs/reference/extensions.md +15 -5
  208. package/dist/docs/reference/hooks.html +36 -36
  209. package/dist/docs/reference/hooks.md +0 -3
  210. package/dist/docs/reference/http-api.html +37 -37
  211. package/dist/docs/reference/http-api.md +1 -1
  212. package/dist/docs/reference/instructions.html +36 -36
  213. package/dist/docs/reference/instructions.md +0 -3
  214. package/dist/docs/reference/playground.html +36 -36
  215. package/dist/docs/reference/playground.md +0 -3
  216. package/dist/docs/reference/project-layout.html +37 -37
  217. package/dist/docs/reference/project-layout.md +2 -2
  218. package/dist/docs/reference/prompt.html +37 -37
  219. package/dist/docs/reference/prompt.md +0 -3
  220. package/dist/docs/reference/schedules.html +36 -36
  221. package/dist/docs/reference/schedules.md +0 -3
  222. package/dist/docs/reference/sessions.html +36 -36
  223. package/dist/docs/reference/sessions.md +0 -3
  224. package/dist/docs/reference/skills.html +38 -38
  225. package/dist/docs/reference/skills.md +0 -3
  226. package/dist/docs/reference/subagents.html +36 -36
  227. package/dist/docs/reference/subagents.md +0 -3
  228. package/dist/docs/reference/tools.html +36 -36
  229. package/dist/docs/reference/tools.md +1 -5
  230. package/dist/docs/templates/agentic-owners.html +36 -36
  231. package/dist/docs/templates/agentic-owners.md +0 -3
  232. package/dist/docs/templates/grokbot-agents.html +64 -0
  233. package/dist/docs/templates/grokbot-agents.md +55 -0
  234. package/dist/docs/templates/security-reviewer.html +37 -37
  235. package/dist/docs/templates/security-reviewer.md +0 -3
  236. package/dist/docs/templates/thermo-quality-review.html +36 -36
  237. package/dist/docs/templates/thermo-quality-review.md +3 -6
  238. package/dist/docs/templates/thermo-review.html +36 -36
  239. package/dist/docs/templates/thermo-review.md +3 -5
  240. package/dist/docs/templates/triage.html +37 -37
  241. package/dist/docs/templates/triage.md +2 -3
  242. package/dist/docs/troubleshooting.html +36 -36
  243. package/dist/docs/troubleshooting.md +3 -7
  244. package/dist/extensions/jev/extension.d.ts +3 -0
  245. package/dist/extensions/jev/extension.d.ts.map +1 -1
  246. package/dist/extensions/jev/extension.js +10 -1
  247. package/dist/extensions/jev/lib/evaluate.d.ts +4 -0
  248. package/dist/extensions/jev/lib/evaluate.d.ts.map +1 -1
  249. package/dist/extensions/jev/lib/evaluate.js +6 -2
  250. package/dist/extensions.d.ts +4 -2
  251. package/dist/extensions.d.ts.map +1 -1
  252. package/dist/extensions.js +5 -2
  253. package/dist/internal/cli-deploy.d.ts.map +1 -1
  254. package/dist/internal/cli-deploy.js +19 -5
  255. package/dist/internal/discovery/agent-config.d.ts +6 -5
  256. package/dist/internal/discovery/agent-config.d.ts.map +1 -1
  257. package/dist/internal/discovery/agent-config.js +29 -28
  258. package/dist/internal/discovery/agent.js +1 -1
  259. package/dist/internal/discovery/extensions.d.ts.map +1 -1
  260. package/dist/internal/discovery/extensions.js +12 -0
  261. package/dist/internal/hosting.d.ts +8 -0
  262. package/dist/internal/hosting.d.ts.map +1 -1
  263. package/dist/internal/hosting.js +24 -0
  264. package/dist/types.d.ts +18 -2
  265. package/dist/types.d.ts.map +1 -1
  266. package/docs/README.md +9 -16
  267. package/docs/building-with-agents.md +0 -3
  268. package/docs/deployment.md +6 -10
  269. package/docs/evals.md +0 -3
  270. package/docs/guides/agent-to-agent.md +0 -3
  271. package/docs/guides/bitbucket.md +0 -3
  272. package/docs/guides/cloud-agents.md +0 -4
  273. package/docs/guides/convert-automation.md +2 -5
  274. package/docs/guides/github.md +1 -4
  275. package/docs/guides/gitlab.md +0 -3
  276. package/docs/guides/grokbot-agents.md +1 -4
  277. package/docs/guides/hooks.md +0 -3
  278. package/docs/guides/improve.md +0 -3
  279. package/docs/guides/jev.md +7 -3
  280. package/docs/guides/mcp-oauth.md +1 -4
  281. package/docs/guides/opentelemetry.md +4 -5
  282. package/docs/guides/slack.md +14 -24
  283. package/docs/guides/webhooks.md +0 -3
  284. package/docs/hillclimbing.md +0 -3
  285. package/docs/quickstart.md +2 -7
  286. package/docs/reference/agent-config.md +4 -7
  287. package/docs/reference/artifacts.md +0 -3
  288. package/docs/reference/channels.md +1 -6
  289. package/docs/reference/cli.md +7 -14
  290. package/docs/reference/connections.md +7 -10
  291. package/docs/reference/evals.md +0 -3
  292. package/docs/reference/extensions.md +15 -5
  293. package/docs/reference/hooks.md +0 -3
  294. package/docs/reference/http-api.md +1 -1
  295. package/docs/reference/instructions.md +0 -3
  296. package/docs/reference/playground.md +0 -3
  297. package/docs/reference/project-layout.md +2 -2
  298. package/docs/reference/prompt.md +0 -3
  299. package/docs/reference/schedules.md +0 -3
  300. package/docs/reference/sessions.md +0 -3
  301. package/docs/reference/skills.md +0 -3
  302. package/docs/reference/subagents.md +0 -3
  303. package/docs/reference/tools.md +1 -5
  304. package/docs/templates/agentic-owners.md +0 -3
  305. package/docs/templates/grokbot-agents.md +60 -0
  306. package/docs/templates/security-reviewer.md +0 -3
  307. package/docs/templates/thermo-quality-review.md +3 -6
  308. package/docs/templates/thermo-review.md +3 -5
  309. package/docs/templates/triage.md +2 -3
  310. package/docs/troubleshooting.md +3 -7
  311. package/package.json +2 -10
  312. package/templates/agentic-owners/README.md +0 -3
  313. package/templates/agents-md/README.md +4 -3
  314. package/templates/code-wiki/README.md +0 -3
  315. package/templates/demo/README.md +0 -3
  316. package/templates/grokbot-agents/README.md +4 -6
  317. package/templates/security-help/README.md +12 -6
  318. package/templates/security-reviewer/README.md +0 -3
  319. package/templates/thermo-quality-review/README.md +0 -3
  320. package/templates/thermo-review/README.md +0 -3
  321. package/templates/triage/README.md +0 -3
  322. package/templates/triage/overlays/jira/README.md +0 -3
  323. package/templates/triage/overlays/linear/README.md +0 -3
  324. package/dist/docs/assets/chunks/@localSearchIndexroot.D5L-b34G.js +0 -1
  325. package/dist/docs/assets/chunks/channel.BbOGaJQP.js +0 -1
  326. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.Db58HCb1.js +0 -1
  327. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.Db58HCb1.js +0 -1
  328. package/dist/docs/assets/chunks/clone.Co4MBflG.js +0 -1
  329. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.CMsKhrW0.js +0 -1
  330. package/dist/docs/assets/index.md.CVc_oOA3.js +0 -27
  331. package/dist/docs/assets/reference_playground.md.BdQzRJc2.js +0 -1
  332. package/dist/docs/assets/reference_sessions.md.DeRUItHD.js +0 -1
  333. package/dist/docs/assets/troubleshooting.md.Cw5PKa3t.js +0 -1
  334. package/src/artifacts.ts +0 -68
  335. package/src/bin/agent-serve.ts +0 -1854
  336. package/src/channels/bitbucket/api.ts +0 -891
  337. package/src/channels/bitbucket/binding.ts +0 -417
  338. package/src/channels/bitbucket/bitbucket-channel.ts +0 -162
  339. package/src/channels/bitbucket/bitbucket-webhook.ts +0 -519
  340. package/src/channels/bitbucket/checks.ts +0 -146
  341. package/src/channels/bitbucket/cursor-account.ts +0 -106
  342. package/src/channels/bitbucket/defaults.ts +0 -100
  343. package/src/channels/bitbucket/events.ts +0 -74
  344. package/src/channels/bitbucket/index.ts +0 -51
  345. package/src/channels/bitbucket/replay.ts +0 -421
  346. package/src/channels/bitbucket/state.ts +0 -59
  347. package/src/channels/bitbucket/types.ts +0 -261
  348. package/src/channels/change-monitors/change-monitors-channel.ts +0 -63
  349. package/src/channels/change-monitors/index.ts +0 -8
  350. package/src/channels/change-monitors/types.ts +0 -42
  351. package/src/channels/checks.ts +0 -185
  352. package/src/channels/deployments/deployments-channel.ts +0 -224
  353. package/src/channels/deployments/index.ts +0 -25
  354. package/src/channels/deployments/types.ts +0 -92
  355. package/src/channels/github/api.ts +0 -526
  356. package/src/channels/github/auth.ts +0 -293
  357. package/src/channels/github/binding.ts +0 -233
  358. package/src/channels/github/checks.ts +0 -145
  359. package/src/channels/github/cursor-account.ts +0 -303
  360. package/src/channels/github/defaults.ts +0 -168
  361. package/src/channels/github/events.ts +0 -67
  362. package/src/channels/github/forward.ts +0 -359
  363. package/src/channels/github/github-channel.ts +0 -2334
  364. package/src/channels/github/index.ts +0 -54
  365. package/src/channels/github/progress.ts +0 -365
  366. package/src/channels/github/replay.ts +0 -372
  367. package/src/channels/github/state.ts +0 -124
  368. package/src/channels/github/types.ts +0 -590
  369. package/src/channels/gitlab/api.ts +0 -329
  370. package/src/channels/gitlab/binding.ts +0 -231
  371. package/src/channels/gitlab/checks.ts +0 -228
  372. package/src/channels/gitlab/cursor-account.ts +0 -105
  373. package/src/channels/gitlab/defaults.ts +0 -80
  374. package/src/channels/gitlab/events.ts +0 -37
  375. package/src/channels/gitlab/gitlab-channel.ts +0 -160
  376. package/src/channels/gitlab/gitlab-webhook.ts +0 -509
  377. package/src/channels/gitlab/index.ts +0 -44
  378. package/src/channels/gitlab/replay.ts +0 -328
  379. package/src/channels/gitlab/state.ts +0 -55
  380. package/src/channels/gitlab/types.ts +0 -247
  381. package/src/channels/issues/index.ts +0 -9
  382. package/src/channels/issues/issues-channel.ts +0 -45
  383. package/src/channels/issues/types.ts +0 -38
  384. package/src/channels/origin/api.ts +0 -507
  385. package/src/channels/origin/binding.ts +0 -114
  386. package/src/channels/origin/checks.ts +0 -250
  387. package/src/channels/origin/cursor-account.ts +0 -58
  388. package/src/channels/origin/defaults.ts +0 -140
  389. package/src/channels/origin/events.ts +0 -35
  390. package/src/channels/origin/index.ts +0 -35
  391. package/src/channels/origin/origin-channel.ts +0 -815
  392. package/src/channels/origin/origin-webhook.ts +0 -296
  393. package/src/channels/origin/reactions.ts +0 -72
  394. package/src/channels/origin/state.ts +0 -54
  395. package/src/channels/origin/types.ts +0 -295
  396. package/src/channels/slack/agentic-delivery.ts +0 -634
  397. package/src/channels/slack/agentic-posted.ts +0 -135
  398. package/src/channels/slack/agentic-signals.ts +0 -231
  399. package/src/channels/slack/api.ts +0 -761
  400. package/src/channels/slack/approvals.ts +0 -279
  401. package/src/channels/slack/assistant.ts +0 -76
  402. package/src/channels/slack/attachments.ts +0 -596
  403. package/src/channels/slack/auth.ts +0 -127
  404. package/src/channels/slack/blocks.ts +0 -131
  405. package/src/channels/slack/bot-mentions.ts +0 -318
  406. package/src/channels/slack/channel-watch.ts +0 -314
  407. package/src/channels/slack/cli-project.ts +0 -249
  408. package/src/channels/slack/code-fences.ts +0 -171
  409. package/src/channels/slack/constants.ts +0 -38
  410. package/src/channels/slack/credentials.ts +0 -88
  411. package/src/channels/slack/defaults.ts +0 -714
  412. package/src/channels/slack/dispatch.ts +0 -1060
  413. package/src/channels/slack/doctor.ts +0 -338
  414. package/src/channels/slack/eval-directive.ts +0 -306
  415. package/src/channels/slack/event-id-dedupe.ts +0 -30
  416. package/src/channels/slack/external-policy.ts +0 -75
  417. package/src/channels/slack/footer.ts +0 -106
  418. package/src/channels/slack/inbound.ts +0 -416
  419. package/src/channels/slack/index.ts +0 -53
  420. package/src/channels/slack/init.ts +0 -169
  421. package/src/channels/slack/interactive.ts +0 -406
  422. package/src/channels/slack/links.ts +0 -23
  423. package/src/channels/slack/live-delivery.ts +0 -489
  424. package/src/channels/slack/log.ts +0 -70
  425. package/src/channels/slack/manifest.ts +0 -240
  426. package/src/channels/slack/message-body.ts +0 -82
  427. package/src/channels/slack/nudge-carrier.ts +0 -224
  428. package/src/channels/slack/nudge-store.ts +0 -334
  429. package/src/channels/slack/paint-start.ts +0 -93
  430. package/src/channels/slack/placeholder.ts +0 -358
  431. package/src/channels/slack/pr-ref.ts +0 -74
  432. package/src/channels/slack/progress-delivery.ts +0 -138
  433. package/src/channels/slack/reasoning-card.ts +0 -125
  434. package/src/channels/slack/reasoning-chip.ts +0 -41
  435. package/src/channels/slack/recording-sink.ts +0 -167
  436. package/src/channels/slack/redact.ts +0 -6
  437. package/src/channels/slack/reply-options.ts +0 -279
  438. package/src/channels/slack/setup.ts +0 -125
  439. package/src/channels/slack/slack-channel.ts +0 -744
  440. package/src/channels/slack/socket-mode.ts +0 -140
  441. package/src/channels/slack/stop.ts +0 -25
  442. package/src/channels/slack/stream.ts +0 -66
  443. package/src/channels/slack/thread-context.ts +0 -485
  444. package/src/channels/slack/tool-approval-events.ts +0 -233
  445. package/src/channels/slack/tool-cards.ts +0 -198
  446. package/src/channels/slack/tool-chip.ts +0 -34
  447. package/src/channels/slack/types.ts +0 -787
  448. package/src/channels/slack/upload.ts +0 -137
  449. package/src/channels.ts +0 -543
  450. package/src/connections.ts +0 -153
  451. package/src/dashboard-session-url.ts +0 -30
  452. package/src/evals/assertions.ts +0 -688
  453. package/src/evals/expect.ts +0 -250
  454. package/src/evals/judge.ts +0 -329
  455. package/src/evals/loaders.ts +0 -111
  456. package/src/evals/matchers.ts +0 -223
  457. package/src/evals/reporters.ts +0 -257
  458. package/src/evals/results.ts +0 -130
  459. package/src/evals/run-facts.ts +0 -306
  460. package/src/evals.ts +0 -709
  461. package/src/extensions/cursor-cloud-agents/extension.ts +0 -131
  462. package/src/extensions/cursor-cloud-agents/lib/backend.ts +0 -386
  463. package/src/extensions/cursor-cloud-agents/lib/channels.ts +0 -11
  464. package/src/extensions/cursor-cloud-agents/lib/fleet.ts +0 -98
  465. package/src/extensions/cursor-cloud-agents/lib/inputs.ts +0 -5
  466. package/src/extensions/cursor-cloud-agents/lib/repos.ts +0 -80
  467. package/src/extensions/cursor-cloud-agents/lib/transcript.ts +0 -19
  468. package/src/extensions/cursor-cloud-agents/skills/handoff.md +0 -37
  469. package/src/extensions/cursor-cloud-agents/tools/cancel.ts +0 -21
  470. package/src/extensions/cursor-cloud-agents/tools/dump.ts +0 -47
  471. package/src/extensions/cursor-cloud-agents/tools/get.ts +0 -18
  472. package/src/extensions/cursor-cloud-agents/tools/launch.ts +0 -62
  473. package/src/extensions/cursor-cloud-agents/tools/list.ts +0 -31
  474. package/src/extensions/cursor-cloud-agents/tools/reply.ts +0 -36
  475. package/src/extensions/cursor-grokbot-agents/extension.ts +0 -132
  476. package/src/extensions/cursor-grokbot-agents/lib/agents.ts +0 -42
  477. package/src/extensions/cursor-grokbot-agents/lib/backend.ts +0 -208
  478. package/src/extensions/cursor-grokbot-agents/lib/contacts.ts +0 -74
  479. package/src/extensions/cursor-grokbot-agents/lib/conversation.ts +0 -260
  480. package/src/extensions/cursor-grokbot-agents/lib/inputs.ts +0 -21
  481. package/src/extensions/cursor-grokbot-agents/lib/lock.ts +0 -26
  482. package/src/extensions/cursor-grokbot-agents/skills/consult.md +0 -40
  483. package/src/extensions/cursor-grokbot-agents/tools/ask.ts +0 -32
  484. package/src/extensions/cursor-grokbot-agents/tools/check.ts +0 -25
  485. package/src/extensions/cursor-grokbot-agents/tools/interrupt.ts +0 -17
  486. package/src/extensions/cursor-grokbot-agents/tools/list.ts +0 -26
  487. package/src/extensions/improve/extension.ts +0 -69
  488. package/src/extensions/improve/skills/yourself.ts +0 -50
  489. package/src/extensions/jev/extension.ts +0 -95
  490. package/src/extensions/jev/lib/evaluate.ts +0 -266
  491. package/src/extensions/jev/skills/gated-write.md +0 -25
  492. package/src/extensions/jev/skills/questions.md +0 -33
  493. package/src/extensions/jev/tools/evaluate.ts +0 -82
  494. package/src/extensions/slack-communication/evals/harness.ts +0 -705
  495. package/src/extensions/slack-communication/evals/slack-communication.eval.ts +0 -830
  496. package/src/extensions/slack-communication/evals/slack-placeholder.eval.ts +0 -172
  497. package/src/extensions/slack-communication/extension.ts +0 -44
  498. package/src/extensions/slack-communication/skills/slack-voice.ts +0 -56
  499. package/src/extensions/slack-communication/tools/delete-message.ts +0 -33
  500. package/src/extensions/slack-communication/tools/edit-message.ts +0 -42
  501. package/src/extensions/slack-communication/tools/post-card.ts +0 -28
  502. package/src/extensions/slack-communication/tools/post-file.ts +0 -82
  503. package/src/extensions/slack-communication/tools/post-update.ts +0 -40
  504. package/src/extensions/slack-communication/tools/react.ts +0 -30
  505. package/src/extensions/slack-communication/tools/set-status.ts +0 -21
  506. package/src/extensions.ts +0 -179
  507. package/src/files-backends/agent-store-presigned-url.ts +0 -11
  508. package/src/files-backends/cursor-hosted.ts +0 -1212
  509. package/src/files-backends/local-fs.ts +0 -163
  510. package/src/files.ts +0 -293
  511. package/src/filesystem.ts +0 -2005
  512. package/src/hooks.ts +0 -30
  513. package/src/index.ts +0 -259
  514. package/src/internal/advertise-tools.ts +0 -370
  515. package/src/internal/approval-gate.ts +0 -103
  516. package/src/internal/artifacts-store.ts +0 -836
  517. package/src/internal/as-of.ts +0 -257
  518. package/src/internal/auth.ts +0 -46
  519. package/src/internal/authored-alias-hooks.ts +0 -138
  520. package/src/internal/authored-loaders.ts +0 -188
  521. package/src/internal/bounded-int.ts +0 -24
  522. package/src/internal/bounded.ts +0 -25
  523. package/src/internal/brand.ts +0 -28
  524. package/src/internal/browser-origin-guard.ts +0 -67
  525. package/src/internal/builtin-tools/artifacts.ts +0 -62
  526. package/src/internal/builtin-tools/index.ts +0 -53
  527. package/src/internal/builtin-tools/reminders.ts +0 -145
  528. package/src/internal/channel-dispatch.ts +0 -129
  529. package/src/internal/channel-route-dispatch.ts +0 -58
  530. package/src/internal/channel-state.ts +0 -83
  531. package/src/internal/chat-client.ts +0 -594
  532. package/src/internal/cli-ax.ts +0 -2318
  533. package/src/internal/cli-bitbucket.ts +0 -438
  534. package/src/internal/cli-convert-automation.ts +0 -335
  535. package/src/internal/cli-cursor.ts +0 -282
  536. package/src/internal/cli-deploy.ts +0 -2519
  537. package/src/internal/cli-docs.ts +0 -192
  538. package/src/internal/cli-github.ts +0 -806
  539. package/src/internal/cli-gitlab.ts +0 -452
  540. package/src/internal/cli-images.ts +0 -672
  541. package/src/internal/cli-manifest.ts +0 -56
  542. package/src/internal/cli-mcp-oauth.ts +0 -396
  543. package/src/internal/cli-mcp.ts +0 -808
  544. package/src/internal/cli-skills.ts +0 -98
  545. package/src/internal/cli-slack-manual.ts +0 -418
  546. package/src/internal/cli-slack.ts +0 -874
  547. package/src/internal/cloud-merge.ts +0 -51
  548. package/src/internal/cloud-turn-cost.ts +0 -159
  549. package/src/internal/connection-env.ts +0 -106
  550. package/src/internal/continuation-channel.ts +0 -233
  551. package/src/internal/continuation-identity.ts +0 -935
  552. package/src/internal/conversation-mirror.ts +0 -423
  553. package/src/internal/convert-automation/convert-workflow.ts +0 -1377
  554. package/src/internal/convert-automation/slug.ts +0 -29
  555. package/src/internal/convert-automation/types.ts +0 -212
  556. package/src/internal/cron.ts +0 -76
  557. package/src/internal/cursor/account-mcp.ts +0 -692
  558. package/src/internal/cursor/backend-client.ts +0 -984
  559. package/src/internal/cursor/bound-secret-file.ts +0 -101
  560. package/src/internal/cursor/credentials.ts +0 -560
  561. package/src/internal/cursor/cursor-api-transport.ts +0 -65
  562. package/src/internal/cursor/github-credentials.ts +0 -228
  563. package/src/internal/cursor/hosted-bound-secrets.ts +0 -71
  564. package/src/internal/cursor/hosted-deployment-secrets.ts +0 -100
  565. package/src/internal/cursor/hosted-store-secrets.ts +0 -152
  566. package/src/internal/cursor/session-token.ts +0 -111
  567. package/src/internal/cursor/store-api-client.ts +0 -323
  568. package/src/internal/cursor-account-mcp-auth.ts +0 -303
  569. package/src/internal/cursor-agent-template.ts +0 -50
  570. package/src/internal/cursor-deployment-relay.ts +0 -315
  571. package/src/internal/cursor-event-relay.ts +0 -675
  572. package/src/internal/cursor-relay-core.ts +0 -563
  573. package/src/internal/deferred-channel-session.ts +0 -61
  574. package/src/internal/deploy-client.ts +0 -1574
  575. package/src/internal/deploy-manifest.ts +0 -361
  576. package/src/internal/deploy-source.ts +0 -144
  577. package/src/internal/describe-error.ts +0 -32
  578. package/src/internal/dev-mode.ts +0 -20
  579. package/src/internal/discovery/agent-config.ts +0 -288
  580. package/src/internal/discovery/agent.ts +0 -381
  581. package/src/internal/discovery/channels.ts +0 -100
  582. package/src/internal/discovery/connections.ts +0 -516
  583. package/src/internal/discovery/context.ts +0 -38
  584. package/src/internal/discovery/cursor-plugin.ts +0 -628
  585. package/src/internal/discovery/extension-overlay.ts +0 -247
  586. package/src/internal/discovery/extensions.ts +0 -490
  587. package/src/internal/discovery/fs.ts +0 -103
  588. package/src/internal/discovery/hooks.ts +0 -63
  589. package/src/internal/discovery/info.ts +0 -174
  590. package/src/internal/discovery/instructions.ts +0 -98
  591. package/src/internal/discovery/modules.ts +0 -107
  592. package/src/internal/discovery/names.ts +0 -45
  593. package/src/internal/discovery/project.ts +0 -319
  594. package/src/internal/discovery/reminders.ts +0 -65
  595. package/src/internal/discovery/runtime.ts +0 -158
  596. package/src/internal/discovery/schedules.ts +0 -120
  597. package/src/internal/discovery/seed-files.ts +0 -34
  598. package/src/internal/discovery/services.ts +0 -151
  599. package/src/internal/discovery/skills.ts +0 -174
  600. package/src/internal/discovery/subagent.ts +0 -138
  601. package/src/internal/discovery/tools.ts +0 -170
  602. package/src/internal/discovery.ts +0 -27
  603. package/src/internal/distribution.ts +0 -126
  604. package/src/internal/docs-site.ts +0 -248
  605. package/src/internal/duration.ts +0 -37
  606. package/src/internal/env-file.ts +0 -83
  607. package/src/internal/eval-judge-model.ts +0 -142
  608. package/src/internal/eval-run-store.ts +0 -585
  609. package/src/internal/eval-runner.ts +0 -823
  610. package/src/internal/evals-client.ts +0 -475
  611. package/src/internal/event-log.ts +0 -342
  612. package/src/internal/event-mapper.ts +0 -811
  613. package/src/internal/expected-delivery-failure.ts +0 -34
  614. package/src/internal/factory-resource-channel.ts +0 -103
  615. package/src/internal/filesystem/errors.ts +0 -207
  616. package/src/internal/filesystem/format.ts +0 -253
  617. package/src/internal/filesystem/merge.ts +0 -192
  618. package/src/internal/filesystem/nearest.ts +0 -112
  619. package/src/internal/filesystem/scratch.ts +0 -239
  620. package/src/internal/filesystem/sdk-schemas.ts +0 -204
  621. package/src/internal/filesystem/tools.ts +0 -804
  622. package/src/internal/filesystem/walk.ts +0 -366
  623. package/src/internal/fixtures/units-server.ts +0 -52
  624. package/src/internal/framework-file-storage.ts +0 -357
  625. package/src/internal/framework-storage-selection.ts +0 -156
  626. package/src/internal/frontmatter.ts +0 -108
  627. package/src/internal/github-fanout.ts +0 -144
  628. package/src/internal/guest-network.ts +0 -391
  629. package/src/internal/handleAgentServeTrigger.ts +0 -286
  630. package/src/internal/host-files.ts +0 -341
  631. package/src/internal/host-kv.ts +0 -81
  632. package/src/internal/host-otel.ts +0 -231
  633. package/src/internal/host-platforms.ts +0 -170
  634. package/src/internal/hosted-admission-adapter.ts +0 -47
  635. package/src/internal/hosted-admission-context.ts +0 -37
  636. package/src/internal/hosted-catch-protocol.ts +0 -112
  637. package/src/internal/hosted-catch.ts +0 -179
  638. package/src/internal/hosted-delivery-protocol.ts +0 -824
  639. package/src/internal/hosted-delivery.ts +0 -1410
  640. package/src/internal/hosted-execution-diag.ts +0 -291
  641. package/src/internal/hosted-execution-flush.ts +0 -136
  642. package/src/internal/hosted-execution-latency.ts +0 -301
  643. package/src/internal/hosted-managed-automation.ts +0 -116
  644. package/src/internal/hosting.ts +0 -114
  645. package/src/internal/http-channel-define.ts +0 -25
  646. package/src/internal/http-channel.ts +0 -669
  647. package/src/internal/http-control-plane-session.ts +0 -110
  648. package/src/internal/ids.ts +0 -39
  649. package/src/internal/incoming-headers-to-fetch.ts +0 -45
  650. package/src/internal/init-interview.ts +0 -360
  651. package/src/internal/init-project.ts +0 -711
  652. package/src/internal/init-scaffold.ts +0 -182
  653. package/src/internal/inline-stdio-define-stub.ts +0 -4
  654. package/src/internal/inline-stdio-mcp.ts +0 -230
  655. package/src/internal/install-cursor-skills.ts +0 -604
  656. package/src/internal/is-record.ts +0 -3
  657. package/src/internal/json-schema.ts +0 -95
  658. package/src/internal/legacy-command-guard.ts +0 -66
  659. package/src/internal/listen-port.ts +0 -85
  660. package/src/internal/local-control-plane.ts +0 -442
  661. package/src/internal/local-env.ts +0 -59
  662. package/src/internal/local-ingress.ts +0 -90
  663. package/src/internal/log-ring.ts +0 -59
  664. package/src/internal/logs-client.ts +0 -477
  665. package/src/internal/map-pool.ts +0 -39
  666. package/src/internal/mcp-endpoint.ts +0 -747
  667. package/src/internal/mcp-host.ts +0 -509
  668. package/src/internal/mcp-oauth-on-demand.ts +0 -337
  669. package/src/internal/mcp-oauth-persist.ts +0 -118
  670. package/src/internal/mcp-oauth.ts +0 -549
  671. package/src/internal/net.ts +0 -29
  672. package/src/internal/open-browser.ts +0 -41
  673. package/src/internal/otel/attrs.ts +0 -16
  674. package/src/internal/otel/collector.ts +0 -937
  675. package/src/internal/otel/config.ts +0 -287
  676. package/src/internal/otel/http.ts +0 -122
  677. package/src/internal/otel/mcp.ts +0 -56
  678. package/src/internal/otel/propagation.ts +0 -17
  679. package/src/internal/otel/runtime.ts +0 -441
  680. package/src/internal/package-inline-stdio.ts +0 -114
  681. package/src/internal/peer-connections.ts +0 -96
  682. package/src/internal/platform-schedule-sync.ts +0 -75
  683. package/src/internal/platform-timers.ts +0 -365
  684. package/src/internal/playground/static.ts +0 -278
  685. package/src/internal/playground/toolchain.ts +0 -270
  686. package/src/internal/playground-proxy.ts +0 -564
  687. package/src/internal/process-memory-telemetry.ts +0 -334
  688. package/src/internal/project-layout.ts +0 -31
  689. package/src/internal/prompt-context.ts +0 -116
  690. package/src/internal/reminder-control-plane-protocol.ts +0 -482
  691. package/src/internal/reminder-runner.ts +0 -1559
  692. package/src/internal/reminder-schedule.ts +0 -104
  693. package/src/internal/reminder-store.ts +0 -176
  694. package/src/internal/request-error-status.ts +0 -95
  695. package/src/internal/request-headers.ts +0 -21
  696. package/src/internal/resolve-prod-target.ts +0 -334
  697. package/src/internal/resolved-connections.ts +0 -190
  698. package/src/internal/router.ts +0 -143
  699. package/src/internal/run-client.ts +0 -354
  700. package/src/internal/runtime-dispatch-runner.ts +0 -50
  701. package/src/internal/sanitize-mcp-tool-name.ts +0 -31
  702. package/src/internal/schedule-runner.ts +0 -154
  703. package/src/internal/scm/pr-url.ts +0 -245
  704. package/src/internal/sdk-runner.ts +0 -959
  705. package/src/internal/serve-restart.ts +0 -113
  706. package/src/internal/server.ts +0 -3147
  707. package/src/internal/session-cost.ts +0 -208
  708. package/src/internal/session-engine.ts +0 -5622
  709. package/src/internal/session-links.ts +0 -84
  710. package/src/internal/session-run-log.ts +0 -535
  711. package/src/internal/session-store.ts +0 -307
  712. package/src/internal/session-urls.ts +0 -32
  713. package/src/internal/sessions-client.ts +0 -239
  714. package/src/internal/skill-catalog.ts +0 -66
  715. package/src/internal/skills-sync.ts +0 -55
  716. package/src/internal/slack-provision-client.ts +0 -544
  717. package/src/internal/slack-thread-key.ts +0 -11
  718. package/src/internal/sleep.ts +0 -3
  719. package/src/internal/start-log-store.ts +0 -164
  720. package/src/internal/steering.ts +0 -17
  721. package/src/internal/storage-coordinator.ts +0 -800
  722. package/src/internal/storage-roles.ts +0 -86
  723. package/src/internal/storage.ts +0 -1
  724. package/src/internal/store-api-protocol.ts +0 -205
  725. package/src/internal/store-mirror.ts +0 -73
  726. package/src/internal/stream-progress.ts +0 -294
  727. package/src/internal/terminal-style.ts +0 -133
  728. package/src/internal/testing/factory-resource-fixtures.ts +0 -84
  729. package/src/internal/testing/scm-continuation-fixtures.ts +0 -285
  730. package/src/internal/tool-catalog.ts +0 -104
  731. package/src/internal/tool-policy.ts +0 -222
  732. package/src/internal/tool-result.ts +0 -50
  733. package/src/internal/trajectory.ts +0 -418
  734. package/src/internal/turn-cost.ts +0 -136
  735. package/src/internal/turn-governor.ts +0 -145
  736. package/src/internal/turn-lease-store.ts +0 -144
  737. package/src/internal/turn-outbox.ts +0 -77
  738. package/src/internal/update-check.ts +0 -517
  739. package/src/internal/v2-hosting.ts +0 -52
  740. package/src/internal/workspace-sync.ts +0 -114
  741. package/src/internal/workspace.ts +0 -505
  742. package/src/kv/memory-kv.ts +0 -94
  743. package/src/kv.ts +0 -18
  744. package/src/memory.ts +0 -487
  745. package/src/otel-public.ts +0 -24
  746. package/src/otel.ts +0 -320
  747. package/src/prompt.ts +0 -80
  748. package/src/reminders.ts +0 -65
  749. package/src/schedules.ts +0 -31
  750. package/src/skills.ts +0 -27
  751. package/src/storage-backends/cursor-hosted-v2.ts +0 -204
  752. package/src/storage-backends/cursor-hosted.ts +0 -388
  753. package/src/storage-backends/file-kv.ts +0 -276
  754. package/src/storage-protocol.ts +0 -261
  755. package/src/storage.ts +0 -408
  756. package/src/tools.ts +0 -166
  757. package/src/types.ts +0 -3776
  758. /package/dist/docs/assets/{guides_jev.md.BNDm14Gy.lean.js → guides_jev.md.D7XH4JH3.lean.js} +0 -0
  759. /package/dist/docs/assets/{reference_http-api.md.BZOvhCqY.lean.js → reference_http-api.md.DbFNOubV.lean.js} +0 -0
  760. /package/dist/docs/assets/{reference_project-layout.md.CpLQ9j4K.lean.js → reference_project-layout.md.C2JMRh7p.lean.js} +0 -0
@@ -1,2519 +0,0 @@
1
- /**
2
- * `agent-sdk deploy | deployments | deployment | stop | rollback | delete | rotate-token |
3
- * secrets set|list|unset` — Heroku-style deploys
4
- * onto Cursor's managed agent-serve hosting.
5
- *
6
- * All intelligence is server-side (backend/server/src/agentServe/); these
7
- * handlers resolve parameters (credentials, team, slug, the project's
8
- * `hosting` / `architecture` manifest block), call the v1 agent-serve or
9
- * v2 agentsdk management API through `deploy-client.ts`, poll status, and
10
- * render.
11
- */
12
-
13
- import { basename, resolve } from "node:path";
14
- import { catchAuthDeclaration, isPublicEndpointPolicy } from "../channels.js";
15
- import {
16
- type AgentArchitecture,
17
- type AgentHostingOptions,
18
- isCursorAccountTransport,
19
- } from "../types.js";
20
- import { CursorBackendClient } from "./cursor/backend-client.js";
21
- import { cursorExternalApiUrl, resolveApiKey, SIGN_IN_HINT } from "./cursor/credentials.js";
22
- import { authorizeCursorAccountConnectors } from "./cursor-account-mcp-auth.js";
23
- import { readDeployTemplate } from "./cursor-agent-template.js";
24
- import {
25
- type AgentkitCancelRunsResult,
26
- type AgentkitDeployAccepted,
27
- type AgentkitDeployComponent,
28
- type AgentkitDeploymentListItem,
29
- type AgentkitDeployStatus,
30
- type AgentkitStopAccepted,
31
- AgentServeDeployClient,
32
- type DeleteAccepted,
33
- type DeployAccepted,
34
- DeployApiError,
35
- type Deployment,
36
- type DeploymentDetail,
37
- type DeploymentProgress,
38
- type DeploySource,
39
- deploymentServiceAccountId,
40
- type SecretInfo,
41
- type StopAccepted,
42
- slugFromDirectoryName,
43
- TERMINAL_AGENTKIT_DEPLOY_STATUSES,
44
- TERMINAL_DEPLOY_STATUSES,
45
- validateDeploymentSlug,
46
- } from "./deploy-client.js";
47
- import { type GitRunner, inferDeployGitSource } from "./deploy-source.js";
48
- import { describeError } from "./describe-error.js";
49
- import {
50
- type ChildAgentDir,
51
- formatDiagnostics,
52
- hasErrorDiagnostics,
53
- isAgentProjectDir,
54
- listChildAgentDirs,
55
- loadAgentProject,
56
- } from "./discovery.js";
57
- import { CLI_COMMAND_NAME as CLI } from "./distribution.js";
58
- import {
59
- isReservedSecretName,
60
- isValidCursorEventRepo,
61
- validateSettableSecretName,
62
- } from "./hosting.js";
63
- import { deploymentArchitecture, rejectV2ForLegacyCommand } from "./legacy-command-guard.js";
64
- import { deployProgressLabel, sanitizeCustomerError } from "./logs-client.js";
65
- import { sleep } from "./sleep.js";
66
- import { stderrPalette } from "./terminal-style.js";
67
-
68
- const DEFAULT_POLL_INTERVAL_MS = 3_000;
69
- const DEFAULT_DEPLOY_TIMEOUT_MS = 10 * 60 * 1000;
70
- /** `--multi-tenant` HTTP deploy is Anysphere-only (team id 1). */
71
- const MULTI_TENANT_HTTP_DEPLOY_TEAM_ID = 1;
72
-
73
- /** One agent directory selected for deploy (single or multi-agent parent). */
74
- export type DeployTarget = ChildAgentDir;
75
-
76
- /**
77
- * Interactive / test seam: pick which agents under a multi-agent parent to
78
- * deploy. Return `null` to cancel.
79
- */
80
- export type ChooseDeployTargets = (
81
- agents: readonly DeployTarget[],
82
- ) => Promise<DeployTarget[] | null>;
83
-
84
- export interface DeployCliOptions {
85
- dir?: string;
86
- slug?: string;
87
- /**
88
- * deploy `--all`: when `--dir` is a multi-agent parent, deploy every
89
- * child agent (skips the interactive picker).
90
- */
91
- all?: boolean;
92
- /** `--team <id>`; resolved from the account when omitted. */
93
- team?: string;
94
- json?: boolean;
95
- noWait?: boolean;
96
- /** v2 stop: also request cancellation for every active session run. */
97
- cancelRuns?: boolean;
98
- apiKey?: string;
99
- /**
100
- * deploy `--repo <url>`: https git repo the control plane builds from.
101
- * Optional — inferred from `git remote origin` when omitted inside an
102
- * agent project checkout.
103
- */
104
- repo?: string;
105
- /**
106
- * deploy `--ref <ref>`: git ref to build. Optional — inferred from the
107
- * current branch (or HEAD SHA if detached) when omitted; otherwise the
108
- * server uses the repo's default branch.
109
- */
110
- ref?: string;
111
- /**
112
- * deploy `--path <agentPath>`: agent directory relative to the repo root.
113
- * Optional — inferred from `--dir` vs the git toplevel when omitted.
114
- */
115
- path?: string;
116
- /** deploy `--cursor-events-repo <owner/name>` (repeatable). */
117
- cursorEventsRepos?: string[];
118
- /** deploy `--allow-domain <domain>` (repeatable; unioned with the manifest). */
119
- allowDomains?: string[];
120
- /**
121
- * deploy `--multi-tenant`: add a release to an existing Cursor-managed
122
- * (multi-tenant) product. Hidden Anysphere-only flag. Cannot create a
123
- * new multi-tenant application.
124
- */
125
- multiTenant?: boolean;
126
- /** Test seams. */
127
- fetchImpl?: typeof fetch;
128
- /** Inject the connector-auth browser opener (tests; also forces interactive). */
129
- openBrowserImpl?: (url: string) => void;
130
- sleepImpl?: (ms: number) => Promise<void>;
131
- connectorPollIntervalMs?: number;
132
- connectorPollTimeoutMs?: number;
133
- /** Inject git probing for deploy source inference (tests). */
134
- git?: GitRunner;
135
- /** Inject the multi-agent picker (tests / non-interactive hosts). */
136
- chooseTargets?: ChooseDeployTargets;
137
- pollIntervalMs?: number;
138
- timeoutMs?: number;
139
- out?: (text: string) => void;
140
- err?: (text: string) => void;
141
- /** `secrets set` value input (hidden prompt on a TTY, lines otherwise). */
142
- stdin?: SecretInputStream;
143
- /**
144
- * Opt in to `NAME=VALUE` argv secrets. Default is names only (hidden
145
- * prompt / stdin) so values never land in shell history or agent-captured
146
- * terminals.
147
- */
148
- fromArgv?: boolean;
149
- }
150
-
151
- /** Minimal stdin surface `secrets set` reads values from (test-injectable). */
152
- export type SecretInputStream = NodeJS.ReadableStream & {
153
- isTTY?: boolean;
154
- setRawMode?: (mode: boolean) => void;
155
- };
156
-
157
- export interface DeployCliContext {
158
- client: AgentServeDeployClient;
159
- teamId: number;
160
- apiKey: string;
161
- backendUrl: string;
162
- json: boolean;
163
- noWait: boolean;
164
- pollIntervalMs: number;
165
- timeoutMs: number;
166
- out: (text: string) => void;
167
- err: (text: string) => void;
168
- }
169
-
170
- export interface ResolveDeployAuthOptions {
171
- team?: string;
172
- apiKey?: string;
173
- fetchImpl?: typeof fetch;
174
- /** Quiet team-resolution chatter (default: write to stderr). */
175
- err?: (text: string) => void;
176
- }
177
-
178
- export interface ResolvedDeployAuth {
179
- client: AgentServeDeployClient;
180
- teamId: number;
181
- /** The resolved account credential, for dashboard RPCs beside the deploy API. */
182
- apiKey: string;
183
- backendUrl: string;
184
- }
185
-
186
- /**
187
- * Credentials → deploy client → team id. Shared by deploy commands and
188
- * `--prod` AX routing. Returns an exit code (error already rendered) on
189
- * failure.
190
- */
191
- export async function resolveDeployAuth(
192
- options: ResolveDeployAuthOptions,
193
- ): Promise<ResolvedDeployAuth | number> {
194
- const err = options.err ?? ((text: string) => void process.stderr.write(text));
195
-
196
- const resolved = await resolveApiKey(
197
- options.apiKey === undefined ? undefined : { apiKey: options.apiKey },
198
- );
199
- if (resolved === undefined) {
200
- err(`Not signed in to Cursor. ${SIGN_IN_HINT}\n`);
201
- return 1;
202
- }
203
- // The deployment management routes live on the external API host
204
- // (api.cursor.com), not the default backend (api2.cursor.sh) — see
205
- // cursorExternalApiUrl. GetMe below stays on the resolved backend.
206
- const client = new AgentServeDeployClient({
207
- backendUrl: cursorExternalApiUrl(),
208
- apiKey: resolved.apiKey,
209
- fetchImpl: options.fetchImpl,
210
- });
211
-
212
- let teamId: number;
213
- if (options.team !== undefined) {
214
- teamId = Number.parseInt(options.team, 10);
215
- if (Number.isNaN(teamId) || teamId <= 0) {
216
- err(`Invalid --team: ${options.team} (expected a positive team id)\n`);
217
- return 1;
218
- }
219
- } else {
220
- const account = new CursorBackendClient({
221
- backendUrl: resolved.backendUrl,
222
- apiKey: resolved.apiKey,
223
- fetchImpl: options.fetchImpl,
224
- });
225
- let identity: Awaited<ReturnType<CursorBackendClient["getMe"]>>;
226
- try {
227
- identity = await account.getMe();
228
- } catch (error) {
229
- err(
230
- `Could not resolve your team from the Cursor account: ${describeError(error)}\nPass --team <id> explicitly.\n`,
231
- );
232
- return 1;
233
- }
234
- if (identity.teamId === undefined || identity.teamId <= 0) {
235
- err(
236
- "This Cursor account has no default team; pass --team <id> (find it in the Cursor dashboard URL).\n",
237
- );
238
- return 1;
239
- }
240
- teamId = identity.teamId;
241
- const dim = stderrPalette().dim;
242
- err(
243
- `${dim(
244
- `Using team ${teamId}${identity.teamName === undefined ? "" : ` (${identity.teamName})`}`,
245
- )}\n${dim(" the account's team — pass --team to override.")}\n`,
246
- );
247
- }
248
-
249
- return {
250
- client,
251
- teamId,
252
- apiKey: resolved.apiKey,
253
- backendUrl: resolved.backendUrl,
254
- };
255
- }
256
-
257
- /**
258
- * Shared preamble: credentials → client → team id. Returns an exit code
259
- * (with the error already rendered) when resolution fails.
260
- */
261
- export async function prepare(options: DeployCliOptions): Promise<DeployCliContext | number> {
262
- const out = options.out ?? ((text: string) => void process.stdout.write(text));
263
- const err = options.err ?? ((text: string) => void process.stderr.write(text));
264
-
265
- const auth = await resolveDeployAuth({
266
- team: options.team,
267
- apiKey: options.apiKey,
268
- fetchImpl: options.fetchImpl,
269
- err,
270
- });
271
- if (typeof auth === "number") {
272
- return auth;
273
- }
274
-
275
- return {
276
- client: auth.client,
277
- teamId: auth.teamId,
278
- apiKey: auth.apiKey,
279
- backendUrl: auth.backendUrl,
280
- json: options.json === true,
281
- noWait: options.noWait === true,
282
- pollIntervalMs: options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS,
283
- timeoutMs: options.timeoutMs ?? DEFAULT_DEPLOY_TIMEOUT_MS,
284
- out,
285
- err,
286
- };
287
- }
288
-
289
- // ============================================================================
290
- // deploy
291
- // ============================================================================
292
-
293
- export async function cmdDeploy(options: DeployCliOptions): Promise<number> {
294
- const ctx = await prepare(options);
295
- if (typeof ctx === "number") {
296
- return ctx;
297
- }
298
-
299
- if (options.multiTenant === true && ctx.teamId !== MULTI_TENANT_HTTP_DEPLOY_TEAM_ID) {
300
- ctx.err("--multi-tenant is not available for this team.\n");
301
- return 1;
302
- }
303
-
304
- const targets = await resolveDeployTargets(options, ctx);
305
- if (typeof targets === "number") {
306
- return targets;
307
- }
308
-
309
- if (targets.length === 1) {
310
- return deployOne(ctx, options, targets[0]!);
311
- }
312
-
313
- // Multi-agent parent: when every child declares `architecture: "v2"`,
314
- // the v2 control plane models sibling agents as release components of
315
- // ONE application, so deploy them together (one app, one component per
316
- // child) instead of minting a separate application per child. Mixed and
317
- // v1 parents keep the per-child sequential deploys.
318
- const manifests: DeployManifest[] = [];
319
- for (const target of targets) {
320
- manifests.push(await readDeployManifest(target.dir));
321
- }
322
- if (manifests.every(manifest => manifest.architecture === "v2")) {
323
- return deployAgentsdkApplication(ctx, options, targets, {
324
- // `persistent` is per child agent, like `agentPath`: each release
325
- // component carries its own.
326
- componentPersistent: Object.fromEntries(
327
- targets.map((target, index) => [target.slug, manifests[index]?.persistent === true]),
328
- ),
329
- componentImage: Object.fromEntries(
330
- targets.flatMap((target, index) =>
331
- manifests[index]?.image === undefined ? [] : [[target.slug, manifests[index].image]],
332
- ),
333
- ),
334
- hasScmChannels: manifests.some(manifest => manifest.hasScmChannels),
335
- declaredSecretNames: [
336
- ...new Set(manifests.flatMap(manifest => manifest.hosting?.secretNames ?? [])),
337
- ],
338
- hasDeploymentsChannels: manifests.some(manifest => manifest.hasDeploymentsChannels),
339
- });
340
- }
341
- if (!ctx.json && manifests.some(manifest => manifest.architecture === "v2")) {
342
- ctx.err(
343
- `warning: agents under this parent mix architectures; deploying each separately (v2 children become standalone single-component applications).\n`,
344
- );
345
- }
346
-
347
- // --path is per-agent (relative to the repo root). When deploying several
348
- // agents, ignore a shared --path so each target can infer its own path.
349
- let deployOptions = options;
350
- if (options.path !== undefined) {
351
- if (!ctx.json) {
352
- ctx.err(
353
- `warning: ignoring --path ${JSON.stringify(options.path)} for a multi-agent deploy; each agent infers its own path from git.\n`,
354
- );
355
- }
356
- deployOptions = { ...options, path: undefined };
357
- }
358
-
359
- // Multi-agent batch: deploy sequentially; --json emits an array.
360
- const jsonResults: unknown[] = [];
361
- let failures = 0;
362
- for (const [index, target] of targets.entries()) {
363
- if (!ctx.json) {
364
- ctx.err(`\n=== [${index + 1}/${targets.length}] Deploying ${target.slug} ===\n`);
365
- }
366
- const before = jsonResults.length;
367
- const code = await deployOne(ctx, deployOptions, target, {
368
- jsonCollect: ctx.json ? jsonResults : undefined,
369
- });
370
- if (code !== 0) {
371
- failures += 1;
372
- if (ctx.json && jsonResults.length === before) {
373
- jsonResults.push({ slug: target.slug, error: "deploy failed" });
374
- }
375
- }
376
- }
377
- if (ctx.json) {
378
- ctx.out(`${JSON.stringify(jsonResults, null, 2)}\n`);
379
- } else if (failures > 0) {
380
- ctx.err(`\n${failures} of ${targets.length} deploy(s) failed.\n`);
381
- } else {
382
- ctx.err(`\nDeployed ${targets.length} agents.\n`);
383
- }
384
- return failures === 0 ? 0 : 1;
385
- }
386
-
387
- /**
388
- * Resolve which agent directory(ies) to deploy from `--dir` / `--slug` /
389
- * `--all`, with an interactive picker when a multi-agent parent is on a TTY.
390
- */
391
- async function resolveDeployTargets(
392
- options: DeployCliOptions,
393
- ctx: DeployCliContext,
394
- ): Promise<DeployTarget[] | number> {
395
- const dir = resolve(options.dir ?? ".");
396
-
397
- if (options.slug !== undefined) {
398
- const slugError = validateDeploymentSlug(options.slug);
399
- if (slugError !== undefined) {
400
- ctx.err(`${slugError}\n`);
401
- return 1;
402
- }
403
- }
404
- if (options.all === true && options.slug !== undefined) {
405
- ctx.err("Pass either --slug or --all, not both.\n");
406
- return 1;
407
- }
408
-
409
- if (await isAgentProjectDir(dir)) {
410
- if (options.all === true) {
411
- ctx.err(
412
- `--all requires a multi-agent parent directory (several child agents under --dir); ${dir} is a single agent project.\n`,
413
- );
414
- return 1;
415
- }
416
- let slug: string;
417
- if (options.slug !== undefined) {
418
- slug = options.slug;
419
- } else {
420
- const derived = slugFromDirectoryName(basename(dir));
421
- if (derived === undefined) {
422
- ctx.err(
423
- `Could not derive a deployment slug from the directory name ${JSON.stringify(basename(dir))}; pass --slug.\n`,
424
- );
425
- return 1;
426
- }
427
- slug = derived;
428
- if (!ctx.json) {
429
- ctx.err(`Deploying as "${slug}" (from the directory name).\n`);
430
- }
431
- }
432
- return [{ slug, dir }];
433
- }
434
-
435
- let children: ChildAgentDir[];
436
- try {
437
- children = await listChildAgentDirs(dir);
438
- } catch (error) {
439
- ctx.err(`${describeError(error)}\n`);
440
- return 1;
441
- }
442
- // Deploy slugs are lowercase-only; normalize directory names the same way
443
- // single-agent deploy does so MixedCase child dirs still deploy.
444
- children = children.flatMap(child => {
445
- const slug = slugFromDirectoryName(basename(child.dir));
446
- if (slug === undefined) {
447
- return [];
448
- }
449
- return [{ slug, dir: child.dir }];
450
- });
451
-
452
- if (children.length === 0) {
453
- if (options.all === true) {
454
- ctx.err(`--all requires child agent projects under --dir; none found in ${dir}.\n`);
455
- return 1;
456
- }
457
- // Bare-slug deploy against a non-agent directory (still requires --repo).
458
- let slug: string;
459
- if (options.slug !== undefined) {
460
- slug = options.slug;
461
- } else {
462
- const derived = slugFromDirectoryName(basename(dir));
463
- if (derived === undefined) {
464
- ctx.err(
465
- `No agent projects under ${dir}, and could not derive a slug from ${JSON.stringify(basename(dir))}; pass --slug or --dir <agent>.\n`,
466
- );
467
- return 1;
468
- }
469
- slug = derived;
470
- if (!ctx.json) {
471
- ctx.err(`Deploying as "${slug}" (no agent project at ${dir}).\n`);
472
- }
473
- }
474
- return [{ slug, dir }];
475
- }
476
-
477
- if (children.length === 1) {
478
- const only = children[0]!;
479
- if (options.all === true) {
480
- // One child is fine for --all (degenerate multi-agent parent).
481
- } else if (options.slug !== undefined && options.slug.toLowerCase() !== only.slug) {
482
- ctx.err(`No agent "${options.slug}" under ${dir}; found "${only.slug}".\n`);
483
- return 1;
484
- }
485
- if (!ctx.json) {
486
- ctx.err(`Deploying "${only.slug}" (only agent under ${basename(dir)}).\n`);
487
- }
488
- return [only];
489
- }
490
-
491
- // Multiple children.
492
- if (options.all === true) {
493
- if (!ctx.json) {
494
- ctx.err(
495
- `Deploying all ${children.length} agents under ${basename(dir)}: ${children.map(c => c.slug).join(", ")}.\n`,
496
- );
497
- }
498
- return [...children];
499
- }
500
-
501
- if (options.slug !== undefined) {
502
- const wanted = options.slug.toLowerCase();
503
- const match = children.find(child => child.slug === wanted);
504
- if (match === undefined) {
505
- ctx.err(
506
- `No agent "${options.slug}" under ${dir}.\n` +
507
- formatAgentList(children) +
508
- `Pass --slug <name> or --all.\n`,
509
- );
510
- return 1;
511
- }
512
- return [match];
513
- }
514
-
515
- // An all-v2 parent deploys as ONE application (siblings are components
516
- // of a single app on the v2 control plane), so "deploy the parent" is
517
- // unambiguous and needs no picker or --all. A child that is v1 — or
518
- // fails to load — keeps the interactive picker below.
519
- if (await allChildrenAreV2(children)) {
520
- if (!ctx.json) {
521
- ctx.err(
522
- `Deploying all ${children.length} v2 agents under ${basename(dir)} as one application (pass --slug <name> to deploy a single agent standalone).\n`,
523
- );
524
- }
525
- return [...children];
526
- }
527
-
528
- const chooser =
529
- options.chooseTargets ??
530
- (agents =>
531
- promptChooseDeployTargets(agents, {
532
- err: ctx.err,
533
- stdin: options.stdin ?? process.stdin,
534
- interactive:
535
- ctx.json !== true &&
536
- (options.stdin ?? process.stdin).isTTY === true &&
537
- process.stderr.isTTY === true,
538
- }));
539
- const chosen = await chooser(children);
540
- if (chosen === null) {
541
- ctx.err("Deploy cancelled.\n");
542
- return 1;
543
- }
544
- if (chosen.length === 0) {
545
- ctx.err(
546
- `Multiple agents under ${dir}:\n` +
547
- formatAgentList(children) +
548
- `Pass --slug <name> or --all (or re-run on a TTY to pick interactively).\n`,
549
- );
550
- return 1;
551
- }
552
- return chosen;
553
- }
554
-
555
- function formatAgentList(agents: readonly DeployTarget[]): string {
556
- return agents.map((agent, i) => ` ${i + 1}) ${agent.slug}\n`).join("");
557
- }
558
-
559
- /**
560
- * True when every child agent project loads and declares
561
- * `architecture: "v2"`. Broken projects count as not-v2 so target
562
- * resolution falls back to the picker instead of failing the whole deploy
563
- * on a child the user might not even select.
564
- */
565
- async function allChildrenAreV2(children: readonly DeployTarget[]): Promise<boolean> {
566
- for (const child of children) {
567
- try {
568
- if ((await readDeployManifest(child.dir)).architecture !== "v2") {
569
- return false;
570
- }
571
- } catch {
572
- return false;
573
- }
574
- }
575
- return true;
576
- }
577
-
578
- /**
579
- * TTY picker for multi-agent parents. Non-interactive callers get `[]`
580
- * so {@link resolveDeployTargets} can print the --slug/--all hint.
581
- */
582
- export async function promptChooseDeployTargets(
583
- agents: readonly DeployTarget[],
584
- options: {
585
- err: (text: string) => void;
586
- stdin: SecretInputStream;
587
- interactive: boolean;
588
- },
589
- ): Promise<DeployTarget[] | null> {
590
- options.err(`Multiple agents (${agents.length}):\n` + formatAgentList(agents) + ` a) all\n`);
591
- if (!options.interactive) {
592
- return [];
593
- }
594
- options.err('Deploy which? Enter a number, slug, "all", or "q" to cancel: ');
595
- const readLine = createLineReader(options.stdin);
596
- // createLineReader pauses until data; ensure stdin is flowing on a TTY.
597
- options.stdin.resume?.();
598
- const answer = (await readLine())?.trim().toLowerCase();
599
- if (answer === undefined || answer === "q" || answer === "quit") {
600
- return null;
601
- }
602
- if (answer === "a" || answer === "all" || answer === "*") {
603
- return [...agents];
604
- }
605
- const asIndex = Number.parseInt(answer, 10);
606
- if (
607
- !Number.isNaN(asIndex) &&
608
- String(asIndex) === answer &&
609
- asIndex >= 1 &&
610
- asIndex <= agents.length
611
- ) {
612
- return [agents[asIndex - 1]!];
613
- }
614
- const bySlug = agents.find(agent => agent.slug.toLowerCase() === answer);
615
- if (bySlug !== undefined) {
616
- return [bySlug];
617
- }
618
- options.err(
619
- `Unrecognized choice ${JSON.stringify(answer)} — expected 1–${agents.length}, a slug, "all", or "q". Aborting.\n`,
620
- );
621
- return null;
622
- }
623
-
624
- async function deployOne(
625
- ctx: DeployCliContext,
626
- options: DeployCliOptions,
627
- target: DeployTarget,
628
- extras?: { jsonCollect?: unknown[] },
629
- ): Promise<number> {
630
- const { dir, slug } = target;
631
-
632
- // Fill --repo/--ref/--path from the local git checkout when omitted so
633
- // `agent-sdk deploy` inside an agent directory is enough. Only probe git
634
- // for real agent projects (avoids ambient monorepo remotes when someone
635
- // deploys a bare --slug). Explicit flags always win.
636
- const isAgent = await isAgentProjectDir(dir);
637
- const needsGitInference =
638
- isAgent &&
639
- (options.repo === undefined || options.ref === undefined || options.path === undefined);
640
- const inferred = needsGitInference
641
- ? await inferDeployGitSource(dir, {
642
- ...(options.git === undefined ? {} : { git: options.git }),
643
- })
644
- : {};
645
- const gitRepoUrl = options.repo ?? inferred.gitRepoUrl;
646
- const gitRef = options.ref ?? inferred.gitRef;
647
- const agentPath = options.path ?? inferred.agentPath;
648
-
649
- if (gitRepoUrl !== undefined && !gitRepoUrl.startsWith("https://")) {
650
- ctx.err(`Invalid --repo: ${gitRepoUrl} (expected an https:// git repository URL)\n`);
651
- return 1;
652
- }
653
- if (gitRepoUrl === undefined) {
654
- ctx.err(
655
- `Could not resolve an https:// git repository URL for this deploy.\n` +
656
- ` Pass --repo https://github.com/<owner>/<repo> (inferred from origin when possible).\n`,
657
- );
658
- return 1;
659
- }
660
- for (const repo of options.cursorEventsRepos ?? []) {
661
- if (!isValidCursorEventRepo(repo)) {
662
- ctx.err(`Invalid --cursor-events-repo: ${repo} (expected owner/name)\n`);
663
- return 1;
664
- }
665
- }
666
-
667
- if (!ctx.json && gitRepoUrl !== undefined) {
668
- const inferredBits: string[] = [];
669
- if (options.repo === undefined && inferred.gitRepoUrl !== undefined) {
670
- inferredBits.push("repo");
671
- }
672
- if (options.ref === undefined && inferred.gitRef !== undefined) {
673
- inferredBits.push("ref");
674
- }
675
- if (options.path === undefined && inferred.agentPath !== undefined) {
676
- inferredBits.push("path");
677
- }
678
- ctx.err(
679
- ` source: ${gitRepoUrl}${gitRef === undefined ? "" : ` @ ${gitRef}`}\n` +
680
- (agentPath === undefined ? "" : ` path: ${agentPath}\n`) +
681
- (inferredBits.length === 0
682
- ? ""
683
- : ` (inferred ${inferredBits.join(", ")} from git; pass --repo/--ref/--path to override)\n`),
684
- );
685
- }
686
-
687
- // The package manifest (`defineAgent({ hosting })`) is the source of
688
- // truth for egress domains and expected secret names; flags override or
689
- // augment it. Directories without an agent project have no manifest. The same load supplies the
690
- // cursorAccount connection refs for the post-deploy connector auth and
691
- // the channels declared public via `publicEndpoint()`.
692
- const manifest = isAgent ? await readDeployManifest(dir) : undefined;
693
- const hosting = manifest?.hosting;
694
- const egressAllowedDomains = [
695
- ...new Set([...(hosting?.egressDomains ?? []), ...(options.allowDomains ?? [])]),
696
- ];
697
- const publicRoutePaths = (manifest?.publicChannelIds ?? []).map(
698
- channelId => `/v1/channels/${channelId}`,
699
- );
700
- if (!ctx.json && manifest?.httpChannelPublicEndpoint === true) {
701
- ctx.err(
702
- `warning: publicEndpoint() on the built-in HTTP channel has no effect on hosting — only custom channels (/v1/channels/…) can be public; the session API always requires the alias token.\n`,
703
- );
704
- }
705
- if (!ctx.json && publicRoutePaths.length > 0) {
706
- // Security-relevant surface change: say exactly what will be reachable
707
- // without the alias token before the deploy is accepted.
708
- ctx.err(
709
- ` public: ${publicRoutePaths.join(", ")} (served WITHOUT the alias token — these channels authenticate requests themselves)\n`,
710
- );
711
- }
712
- const deadSecretChannels = manifest?.publicChannelIdsWithDeadSecretPolicies ?? [];
713
- if (!ctx.json && deadSecretChannels.length > 0) {
714
- ctx.err(
715
- `warning: ${deadSecretChannels
716
- .map(channelId => `/v1/channels/${channelId}`)
717
- .join(
718
- ", ",
719
- )}: publicEndpoint() sits beside sharedSecretAuth()/hmacSignatureAuth() — auth chains are any-of, so every request is admitted and those secret policies never run. Drop publicEndpoint() to enforce them, or drop them to make the intent explicit.\n`,
720
- );
721
- }
722
-
723
- if (manifest?.architecture === "v2") {
724
- if (!ctx.json) {
725
- ctx.err(
726
- ` architecture: v2${manifest.persistent ? " (persistent)" : ""}${manifest.image === undefined ? "" : `\n image: ${manifest.image}`}\n`,
727
- );
728
- }
729
- return deployOneAgentsdk(ctx, extras, {
730
- persistent: manifest.persistent,
731
- image: manifest.image,
732
- slug,
733
- gitRepoUrl,
734
- gitRef,
735
- agentPath,
736
- repositories: options.cursorEventsRepos,
737
- hasScmChannels: manifest.hasScmChannels,
738
- declaredSecretNames: hosting?.secretNames,
739
- hasDeploymentsChannels: manifest.hasDeploymentsChannels,
740
- multiTenant: options.multiTenant === true,
741
- });
742
- }
743
-
744
- if (options.multiTenant === true) {
745
- ctx.err(
746
- "--multi-tenant is only valid for architecture: v2 deploys (Cursor-managed products).\n",
747
- );
748
- return 1;
749
- }
750
-
751
- // Today's only source shape: the control plane builds from a git ref.
752
- // See DeploySource for the artifact seam.
753
- const source: DeploySource = {
754
- kind: "git-ref",
755
- gitRepoUrl,
756
- ...(gitRef === undefined ? {} : { gitRef }),
757
- ...(agentPath === undefined ? {} : { agentPath }),
758
- ...(options.cursorEventsRepos === undefined || options.cursorEventsRepos.length === 0
759
- ? {}
760
- : { cursorEventRepos: options.cursorEventsRepos }),
761
- ...(egressAllowedDomains.length === 0 ? {} : { egressAllowedDomains }),
762
- publicRoutePaths: publicRoutePaths.length === 0 ? undefined : publicRoutePaths,
763
- // Deliberately NO manifest here: the control plane captures it from the
764
- // provisioned engine (`GET /v1/manifest` after the health probe), which
765
- // is the single write path for deploy manifests. `july manifest` remains
766
- // available for local visibility only.
767
- };
768
-
769
- let accepted: DeployAccepted;
770
- try {
771
- accepted = await ctx.client.deploy({
772
- teamId: ctx.teamId,
773
- slug,
774
- source,
775
- template: readDeployTemplate(dir),
776
- });
777
- } catch (error) {
778
- return renderApiError(error, ctx.err);
779
- }
780
-
781
- const aliasUrl = ctx.client.aliasUrl(accepted.engineAlias);
782
- if (!ctx.json && accepted.aliasToken !== undefined) {
783
- ctx.out(aliasTokenBlock(accepted.aliasToken));
784
- }
785
-
786
- if (ctx.noWait) {
787
- if (extras?.jsonCollect !== undefined) {
788
- extras.jsonCollect.push(accepted);
789
- } else if (ctx.json) {
790
- ctx.out(`${JSON.stringify(accepted, null, 2)}\n`);
791
- } else {
792
- ctx.out(
793
- `Deploy accepted: ${slug} (team ${ctx.teamId}, generation ${accepted.generation}, ${accepted.deploymentKind})\n` +
794
- ` alias: ${aliasUrl}\n` +
795
- `Check progress with \`${CLI} deployment ${slug} --team ${ctx.teamId}\`.\n`,
796
- );
797
- }
798
- return 0;
799
- }
800
-
801
- let detail: DeploymentDetail;
802
- try {
803
- detail = await pollUntil(ctx, slug, TERMINAL_DEPLOY_STATUSES, () =>
804
- ctx.client.getDeployment({ teamId: ctx.teamId, slug }),
805
- );
806
- } catch (error) {
807
- return renderApiError(error, ctx.err);
808
- }
809
-
810
- warnMissingSecrets(ctx, slug, hosting?.secretNames, detail.secretNames);
811
-
812
- const payload =
813
- accepted.aliasToken === undefined ? detail : { ...detail, aliasToken: accepted.aliasToken };
814
-
815
- if (extras?.jsonCollect !== undefined) {
816
- extras.jsonCollect.push(payload);
817
- return detail.status === "running" ? 0 : 1;
818
- }
819
-
820
- if (ctx.json) {
821
- ctx.out(`${JSON.stringify(payload, null, 2)}\n`);
822
- return detail.status === "running" ? 0 : 1;
823
- }
824
-
825
- if (detail.status !== "running") {
826
- ctx.err(`Deployment ${slug} ended ${detail.status}${deployFailureDetail(detail.lastError)}\n`);
827
- return 1;
828
- }
829
- const deployedPublicRoutes = detail.publicRoutePaths ?? [];
830
- ctx.out(
831
- `Deployed ${slug} (team ${ctx.teamId})\n` +
832
- ` status: running\n` +
833
- ` generation: ${detail.generation}\n` +
834
- ` kind: ${detail.deploymentKind}\n` +
835
- ` alias: ${aliasUrl}\n` +
836
- ` playground: ${aliasUrl}/playground (sign in with the alias token)\n` +
837
- ` open: ${CLI} playground --prod --slug ${slug} --team ${ctx.teamId}\n` +
838
- // Paste-ready webhook URLs: these subtrees skip the alias token, so
839
- // the channel handler must verify deliveries (webhook signatures).
840
- deployedPublicRoutes
841
- .map(path => ` public: ${aliasUrl}${path} (no alias token)\n`)
842
- .join(""),
843
- );
844
-
845
- await runPostDeployConnectorAuth(ctx, options, {
846
- slug,
847
- connections: manifest?.cursorAccountConnections ?? [],
848
- serviceAccountId: deploymentServiceAccountId(detail),
849
- });
850
- return 0;
851
- }
852
-
853
- /**
854
- * Multi-agent parent whose children all declare `architecture: "v2"`:
855
- * deploy ONE application whose release carries a component per child. The
856
- * application slug derives from the parent directory name; each component
857
- * key is the child's slug and its path is the child directory relative to
858
- * the repo root (a shared --path names the parent's directory in the repo).
859
- */
860
- async function deployAgentsdkApplication(
861
- ctx: DeployCliContext,
862
- options: DeployCliOptions,
863
- targets: readonly DeployTarget[],
864
- declarations: {
865
- /** Per child slug: `persistent: true` on that agent's manifest. */
866
- componentPersistent: Record<string, boolean>;
867
- /** Per child slug: `hosting.image` on that agent's manifest. */
868
- componentImage: Record<string, string>;
869
- hasScmChannels: boolean;
870
- declaredSecretNames: string[];
871
- hasDeploymentsChannels: boolean;
872
- },
873
- ): Promise<number> {
874
- const parentDir = resolve(options.dir ?? ".");
875
- const slug = slugFromDirectoryName(basename(parentDir));
876
- if (slug === undefined) {
877
- ctx.err(
878
- `Could not derive an application slug from the parent directory name ${JSON.stringify(basename(parentDir))} — rename it (deploy slugs use lowercase letters, digits, '-' or '_').\n`,
879
- );
880
- return 1;
881
- }
882
-
883
- const needsGitInference =
884
- options.repo === undefined || options.ref === undefined || options.path === undefined;
885
- const inferred = needsGitInference
886
- ? await inferDeployGitSource(parentDir, {
887
- ...(options.git === undefined ? {} : { git: options.git }),
888
- })
889
- : {};
890
- const gitRepoUrl = options.repo ?? inferred.gitRepoUrl;
891
- const gitRef = options.ref ?? inferred.gitRef;
892
- const parentPath = options.path ?? inferred.agentPath;
893
-
894
- if (gitRepoUrl !== undefined && !gitRepoUrl.startsWith("https://")) {
895
- ctx.err(`Invalid --repo: ${gitRepoUrl} (expected an https:// git repository URL)\n`);
896
- return 1;
897
- }
898
- if (gitRepoUrl === undefined) {
899
- ctx.err(
900
- `Could not resolve an https:// git repository URL for this deploy.\n` +
901
- ` Pass --repo https://github.com/<owner>/<repo> (inferred from origin when possible).\n`,
902
- );
903
- return 1;
904
- }
905
- for (const repo of options.cursorEventsRepos ?? []) {
906
- if (!isValidCursorEventRepo(repo)) {
907
- ctx.err(`Invalid --cursor-events-repo: ${repo} (expected owner/name)\n`);
908
- return 1;
909
- }
910
- }
911
-
912
- const components: AgentkitDeployComponent[] = targets.map(target => ({
913
- componentKey: target.slug,
914
- agentPath: [parentPath, basename(target.dir)]
915
- .filter((part): part is string => part !== undefined && part !== "")
916
- .join("/"),
917
- persistent: declarations.componentPersistent[target.slug] === true,
918
- image: declarations.componentImage[target.slug],
919
- }));
920
-
921
- if (!ctx.json) {
922
- ctx.err(
923
- `Deploying "${slug}" as one v2 application with ${targets.length} components (slug from the parent directory name).\n` +
924
- ` architecture: v2\n` +
925
- ` source: ${gitRepoUrl}${gitRef === undefined ? "" : ` @ ${gitRef}`}\n` +
926
- components
927
- .map(
928
- component =>
929
- ` component: ${component.componentKey} (${component.agentPath ?? "."})${component.persistent ? " persistent" : ""}${component.image === undefined ? "" : ` image ${component.image}`}\n`,
930
- )
931
- .join(""),
932
- );
933
- }
934
-
935
- return deployOneAgentsdk(ctx, undefined, {
936
- // Multi-component: the flag travels on each component instead.
937
- persistent: false,
938
- slug,
939
- gitRepoUrl,
940
- gitRef,
941
- agentPath: undefined,
942
- components,
943
- repositories: options.cursorEventsRepos,
944
- hasScmChannels: declarations.hasScmChannels,
945
- declaredSecretNames: declarations.declaredSecretNames,
946
- hasDeploymentsChannels: declarations.hasDeploymentsChannels,
947
- multiTenant: options.multiTenant === true,
948
- });
949
- }
950
-
951
- /**
952
- * `architecture: "v2"` deploy: POST `/internal/agentsdk/deployments` and
953
- * poll the matching GET. The v2 accept path starts freeze bake; it does
954
- * not mint an engine alias or alias token.
955
- */
956
- async function deployOneAgentsdk(
957
- ctx: DeployCliContext,
958
- extras: { jsonCollect?: unknown[] } | undefined,
959
- args: {
960
- slug: string;
961
- gitRepoUrl: string;
962
- gitRef: string | undefined;
963
- agentPath: string | undefined;
964
- components?: AgentkitDeployComponent[];
965
- repositories: string[] | undefined;
966
- /** Any component declares a GitHub/Origin channel. */
967
- hasScmChannels: boolean;
968
- /** Union of application component secret declarations. */
969
- declaredSecretNames?: string[];
970
- /** Any component declares a deployments channel (same repo scope). */
971
- hasDeploymentsChannels?: boolean;
972
- /** Redeploy an existing Cursor-managed product. */
973
- multiTenant: boolean;
974
- /**
975
- * `persistent: true` in a single agent's manifest. Multi-component
976
- * deploys pass `false` here and flag each component instead.
977
- */
978
- persistent: boolean;
979
- /** `hosting.image` of a single agent; components carry their own. */
980
- image?: string;
981
- },
982
- ): Promise<number> {
983
- const { slug } = args;
984
- const componentsLine =
985
- args.components === undefined
986
- ? ""
987
- : ` components: ${args.components.map(component => component.componentKey).join(", ")}\n`;
988
- if (args.multiTenant && !ctx.json) {
989
- ctx.err(" multi-tenant: existing product\n");
990
- }
991
- let accepted: AgentkitDeployAccepted;
992
- try {
993
- accepted = await ctx.client.deployAgentkit({
994
- teamId: ctx.teamId,
995
- slug,
996
- gitRepoUrl: args.gitRepoUrl,
997
- gitRef: args.gitRef,
998
- agentPath: args.agentPath,
999
- components: args.components,
1000
- repositories: args.repositories,
1001
- ...(args.multiTenant ? { multiTenant: true } : {}),
1002
- persistent: args.persistent,
1003
- image: args.image,
1004
- });
1005
- } catch (error) {
1006
- return renderApiError(error, ctx.err, {
1007
- multiTenant: args.multiTenant,
1008
- teamId: ctx.teamId,
1009
- });
1010
- }
1011
-
1012
- if (ctx.noWait) {
1013
- if (extras?.jsonCollect !== undefined) {
1014
- extras.jsonCollect.push(accepted);
1015
- } else if (ctx.json) {
1016
- ctx.out(`${JSON.stringify(accepted, null, 2)}\n`);
1017
- } else {
1018
- ctx.out(
1019
- `Deploy accepted: ${slug} (team ${ctx.teamId}, v2)\n` +
1020
- ` application: ${accepted.applicationId}\n` +
1021
- ` release: ${accepted.releaseId}\n` +
1022
- componentsLine,
1023
- );
1024
- }
1025
- return 0;
1026
- }
1027
-
1028
- let detail: AgentkitDeployStatus;
1029
- try {
1030
- detail = await pollUntil(ctx, slug, TERMINAL_AGENTKIT_DEPLOY_STATUSES, () =>
1031
- ctx.client.getAgentkitDeploy({ teamId: ctx.teamId, slug }),
1032
- );
1033
- } catch (error) {
1034
- return renderApiError(error, ctx.err);
1035
- }
1036
-
1037
- if (extras?.jsonCollect !== undefined) {
1038
- extras.jsonCollect.push(detail);
1039
- return detail.status === "running" ? 0 : 1;
1040
- }
1041
-
1042
- if (ctx.json) {
1043
- ctx.out(`${JSON.stringify(detail, null, 2)}\n`);
1044
- return detail.status === "running" ? 0 : 1;
1045
- }
1046
-
1047
- if (detail.status !== "running") {
1048
- ctx.err(`Deployment ${slug} ended ${detail.status}${deployFailureDetail(detail.lastError)}\n`);
1049
- return 1;
1050
- }
1051
- warnMissingSecrets(ctx, slug, args.declaredSecretNames, detail.secretNames);
1052
- const watchesRepositories = args.hasScmChannels || args.hasDeploymentsChannels === true;
1053
- ctx.out(
1054
- `Deployed ${slug} (team ${ctx.teamId})\n` +
1055
- ` status: running\n` +
1056
- ` architecture: v2\n` +
1057
- ` application: ${detail.applicationId}\n` +
1058
- ` release: ${detail.releaseId}\n` +
1059
- (args.components === undefined
1060
- ? ""
1061
- : ` components: ${args.components
1062
- .map(component => component.componentKey)
1063
- .join(", ")}\n`) +
1064
- (detail.repositories === undefined || !watchesRepositories
1065
- ? ""
1066
- : ` watching: ${detail.repositories.length === 0 ? "(nothing)" : detail.repositories.join(", ")}\n`),
1067
- );
1068
- // An agent with GitHub/Origin/deployments channels bound to no repository
1069
- // scope gets no deliveries at all (deployments channels receive the
1070
- // watched repos' deployment events), which is otherwise invisible here.
1071
- if (watchesRepositories && detail.repositories?.length === 0) {
1072
- ctx.err(
1073
- `warning: ${slug} watches no repositories, so its GitHub/Origin/deployments channels receive no events.\n` +
1074
- ` Redeploy with --cursor-events-repo <owner>/<name> to set the scope.\n`,
1075
- );
1076
- }
1077
- return 0;
1078
- }
1079
-
1080
- /**
1081
- * Post-deploy connector authorization for `cursorAccount` connections: the
1082
- * agent's connectors execute with tokens owned by the deployment's service
1083
- * account, which start out unauthorized. On a TTY this runs the dashboard's
1084
- * Authenticate flow inline (browser OAuth per connector, already-authorized
1085
- * ones skipped); otherwise it reports status only. Never affects the deploy
1086
- * outcome — anything left unauthorized just gets a playground-page pointer.
1087
- */
1088
- async function runPostDeployConnectorAuth(
1089
- ctx: DeployCliContext,
1090
- options: DeployCliOptions,
1091
- args: {
1092
- slug: string;
1093
- connections: DeployManifest["cursorAccountConnections"];
1094
- serviceAccountId: string | undefined;
1095
- },
1096
- ): Promise<void> {
1097
- if (args.connections.length === 0) {
1098
- return;
1099
- }
1100
-
1101
- const { serviceAccountId } = args;
1102
- if (serviceAccountId === undefined) {
1103
- ctx.err(
1104
- `warning: this agent uses Cursor account connectors, but the deployment has no service account; redeploy to mint one.\n`,
1105
- );
1106
- return;
1107
- }
1108
-
1109
- const backendClient = new CursorBackendClient({
1110
- backendUrl: ctx.backendUrl,
1111
- apiKey: ctx.apiKey,
1112
- fetchImpl: options.fetchImpl,
1113
- });
1114
-
1115
- const interactive =
1116
- options.openBrowserImpl !== undefined ||
1117
- (process.stdout.isTTY === true && process.stdin.isTTY === true);
1118
-
1119
- let anyUnauthorized = false;
1120
- for (const ref of args.connections) {
1121
- ctx.out(
1122
- `\nThis agent uses Cursor account connectors (connection "${ref.name}"${
1123
- ref.servers === undefined || ref.servers.length === 0 ? "" : `: ${ref.servers.join(", ")}`
1124
- }).\n`,
1125
- );
1126
- try {
1127
- const result = await authorizeCursorAccountConnectors({
1128
- backendClient,
1129
- teamId: ctx.teamId,
1130
- slug: args.slug,
1131
- serviceAccountId,
1132
- connectionName: ref.name,
1133
- servers: ref.servers,
1134
- interactive,
1135
- out: ctx.out,
1136
- err: ctx.err,
1137
- openBrowserImpl: options.openBrowserImpl,
1138
- sleep: options.sleepImpl,
1139
- pollIntervalMs: options.connectorPollIntervalMs,
1140
- pollTimeoutMs: options.connectorPollTimeoutMs,
1141
- });
1142
- if (result.pending.length > 0 || result.errored.length > 0) {
1143
- anyUnauthorized = true;
1144
- if (result.pending.length > 0) {
1145
- ctx.out(`Connectors not authorized yet: ${result.pending.join(", ")}.\n`);
1146
- }
1147
- }
1148
- } catch (error) {
1149
- anyUnauthorized = true;
1150
- ctx.err(
1151
- `warning: could not check connector authorization for "${ref.name}": ${describeError(error)}\n`,
1152
- );
1153
- }
1154
- }
1155
-
1156
- if (anyUnauthorized) {
1157
- ctx.out(
1158
- `You can authorize connectors at the playground page (cursor.com dashboard → Deployed Agents → ${args.slug}) or with \`${CLI} mcp oauth <connection>\`.\n`,
1159
- );
1160
- }
1161
- }
1162
-
1163
- interface DeployManifest {
1164
- hosting: AgentHostingOptions | undefined;
1165
- architecture: AgentArchitecture | undefined;
1166
- persistent: boolean;
1167
- /** `hosting.image`, the team container image this agent runs in. */
1168
- image: string | undefined;
1169
- /** `cursorAccount` connections declared by the agent. */
1170
- cursorAccountConnections: Array<{
1171
- name: string;
1172
- servers: string[] | undefined;
1173
- }>;
1174
- /**
1175
- * Channels whose authored auth chain contains `publicEndpoint()`: their
1176
- * `/v1/channels/<id>` subtree is served through the stable alias WITHOUT
1177
- * `X-Agent-Alias-Token` (the channel authenticates deliveries itself).
1178
- */
1179
- publicChannelIds: string[];
1180
- /**
1181
- * Public channels whose auth chain also carries `sharedSecretAuth` /
1182
- * `hmacSignatureAuth`. Chains are any-of, so `publicEndpoint()` admits
1183
- * every request and those secret policies never gate anything — locally
1184
- * or on the control plane; surfaced as a warning.
1185
- */
1186
- publicChannelIdsWithDeadSecretPolicies: string[];
1187
- /**
1188
- * `publicEndpoint()` on the built-in HTTP channel — a no-op on hosting
1189
- * (only `/v1/channels/…` subtrees can be public); surfaced as a warning.
1190
- */
1191
- httpChannelPublicEndpoint: boolean;
1192
- /**
1193
- * The agent has GitHub/Origin channels, so it only receives deliveries
1194
- * while the deployment is bound to at least one `owner/name` scope.
1195
- */
1196
- hasScmChannels: boolean;
1197
- /**
1198
- * The agent has deployments channels; deploy-source edges derive from
1199
- * the same watched-repo set as GitHub/Origin, so it too receives
1200
- * nothing while the deployment watches no repositories.
1201
- */
1202
- hasDeploymentsChannels: boolean;
1203
- }
1204
-
1205
- /**
1206
- * Read the deploy-relevant bits of the project manifest at `dir` in one
1207
- * load: the `hosting` block, the agent's cursorAccount connections, and the
1208
- * channels declared public via `publicEndpoint()`.
1209
- */
1210
- async function readDeployManifest(dir: string): Promise<DeployManifest> {
1211
- const project = await loadAgentProject(dir);
1212
- // Fail here, before anything is dispatched: a project with error
1213
- // diagnostics (e.g. agent/storage.ts on architecture v2) would only be
1214
- // refused later by `serve` inside the hosted build, wasting a bake.
1215
- if (hasErrorDiagnostics(project)) {
1216
- throw new Error(
1217
- `Refusing to deploy ${project.name} — it has errors:\n${formatDiagnostics(
1218
- project.diagnostics.filter(d => d.severity === "error"),
1219
- )}`,
1220
- );
1221
- }
1222
- return {
1223
- hosting: project.agent.hosting,
1224
- architecture: project.agent.architecture,
1225
- persistent: project.agent.persistent === true,
1226
- image: project.agent.hosting?.image,
1227
- cursorAccountConnections: project.agent.connections.flatMap(connection =>
1228
- isCursorAccountTransport(connection.transport)
1229
- ? [{ name: connection.name, servers: connection.transport.servers }]
1230
- : [],
1231
- ),
1232
- publicChannelIds: project.channels
1233
- .filter(channel => (channel.definition.auth ?? []).some(isPublicEndpointPolicy))
1234
- .map(channel => channel.id),
1235
- publicChannelIdsWithDeadSecretPolicies: project.channels
1236
- .filter(channel => {
1237
- const auth = channel.definition.auth ?? [];
1238
- return (
1239
- auth.some(isPublicEndpointPolicy) &&
1240
- auth.some(policy => {
1241
- const kind = catchAuthDeclaration(policy)?.kind;
1242
- return kind !== undefined && kind !== "public";
1243
- })
1244
- );
1245
- })
1246
- .map(channel => channel.id),
1247
- httpChannelPublicEndpoint: (project.httpChannel.auth ?? []).some(isPublicEndpointPolicy),
1248
- hasScmChannels: project.channels.some(channel => {
1249
- const kind = channel.definition.meta?.kind;
1250
- return kind === "github" || kind === "origin";
1251
- }),
1252
- hasDeploymentsChannels: project.channels.some(
1253
- channel => channel.definition.meta?.kind === "deployments",
1254
- ),
1255
- };
1256
- }
1257
-
1258
- /**
1259
- * Friendly post-deploy nudge: the manifest declares secrets the agent
1260
- * expects, but the deployment does not have them all set yet.
1261
- */
1262
- function warnMissingSecrets(
1263
- ctx: DeployCliContext,
1264
- slug: string,
1265
- declared: string[] | undefined,
1266
- set: string[] | undefined,
1267
- ): void {
1268
- if (declared === undefined || declared.length === 0) {
1269
- return;
1270
- }
1271
- const setNames = new Set(set ?? []);
1272
- // Platform-managed names (CURSOR_*, hosted storage) are injected by the
1273
- // control plane and never appear in secrets list — do not warn on them.
1274
- const missing = declared.filter(name => !setNames.has(name) && !isReservedSecretName(name));
1275
- if (missing.length === 0) {
1276
- return;
1277
- }
1278
- ctx.err(
1279
- `warning: secrets declared in the agent manifest but not set on ${slug}: ${missing.join(", ")}\n` +
1280
- ` set them with \`${CLI} secrets set ${slug} ${missing.join(" ")}\`\n`,
1281
- );
1282
- }
1283
-
1284
- // ============================================================================
1285
- // deployments (list)
1286
- // ============================================================================
1287
-
1288
- export async function cmdDeployments(options: DeployCliOptions): Promise<number> {
1289
- const ctx = await prepare(options);
1290
- if (typeof ctx === "number") {
1291
- return ctx;
1292
- }
1293
- let deployments: Deployment[];
1294
- try {
1295
- deployments = await ctx.client.listDeployments({ teamId: ctx.teamId });
1296
- } catch (error) {
1297
- return renderApiError(error, ctx.err);
1298
- }
1299
- let applications: AgentkitDeploymentListItem[] = [];
1300
- try {
1301
- applications = await ctx.client.listAgentkitDeployments({
1302
- teamId: ctx.teamId,
1303
- });
1304
- } catch (error) {
1305
- // Older control planes 404 this route; keep listing v1.
1306
- if (!(error instanceof DeployApiError && error.status === 404)) {
1307
- return renderApiError(error, ctx.err);
1308
- }
1309
- }
1310
- if (ctx.json) {
1311
- // Empty v2 list keeps `{ deployments }` for v1-only parsers.
1312
- ctx.out(
1313
- `${JSON.stringify(
1314
- applications.length === 0 ? { deployments } : { deployments, applications },
1315
- null,
1316
- 2,
1317
- )}\n`,
1318
- );
1319
- return 0;
1320
- }
1321
- if (deployments.length === 0 && applications.length === 0) {
1322
- ctx.out(`No deployments on team ${ctx.teamId}. Create one with \`${CLI} deploy\`.\n`);
1323
- return 0;
1324
- }
1325
- ctx.out(
1326
- `${renderTable(
1327
- ["SLUG", "ARCH", "STATUS", "GEN", "KIND", "UPDATED"],
1328
- [
1329
- ...deployments.map(d => [
1330
- d.slug,
1331
- "v1",
1332
- d.status,
1333
- String(d.generation),
1334
- d.deploymentKind,
1335
- d.desiredUpdatedAt ?? "",
1336
- ]),
1337
- ...applications.map(application => [
1338
- application.slug,
1339
- "v2",
1340
- application.status,
1341
- "-",
1342
- "application",
1343
- application.deployments
1344
- .map(row => row.desiredUpdatedAt)
1345
- .sort()
1346
- .at(-1) ?? "",
1347
- ]),
1348
- ],
1349
- )}\n`,
1350
- );
1351
- return 0;
1352
- }
1353
-
1354
- // ============================================================================
1355
- // deployment <slug> (detail)
1356
- // ============================================================================
1357
-
1358
- export async function cmdDeploymentStatus(
1359
- slug: string | undefined,
1360
- options: DeployCliOptions,
1361
- ): Promise<number> {
1362
- if (slug === undefined || slug === "") {
1363
- (options.err ?? ((t: string) => void process.stderr.write(t)))(
1364
- `Usage: ${CLI} deployment <slug> [--team <id>] [--json]\n`,
1365
- );
1366
- return 1;
1367
- }
1368
- const ctx = await prepare(options);
1369
- if (typeof ctx === "number") {
1370
- return ctx;
1371
- }
1372
- // Same dispatch as `stop`: v1 409s architecture-v2 slugs, so the v2
1373
- // GET goes first. A v2 404 (missing slug, or an older backend) falls
1374
- // through to the v1 agent-serve detail.
1375
- try {
1376
- const detail = await ctx.client.getAgentkitDeploy({
1377
- teamId: ctx.teamId,
1378
- slug,
1379
- });
1380
- renderAgentkitDeploymentStatus(ctx, detail);
1381
- return 0;
1382
- } catch (error) {
1383
- if (!(error instanceof DeployApiError) || error.status !== 404) {
1384
- return renderApiError(error, ctx.err);
1385
- }
1386
- }
1387
- let detail: DeploymentDetail;
1388
- try {
1389
- detail = await ctx.client.getDeployment({ teamId: ctx.teamId, slug });
1390
- } catch (error) {
1391
- return renderApiError(error, ctx.err);
1392
- }
1393
- if (ctx.json) {
1394
- ctx.out(`${JSON.stringify(detail, null, 2)}\n`);
1395
- return 0;
1396
- }
1397
- const aliasUrl = ctx.client.aliasUrl(detail.engineAlias);
1398
- const lines = [`${detail.slug} (team ${detail.teamId})`, ` status: ${detail.status}`];
1399
- if (detail.progress !== undefined) {
1400
- lines.push(` progress: ${detail.progress}`);
1401
- }
1402
- if (
1403
- detail.statusMessage !== null &&
1404
- detail.statusMessage !== undefined &&
1405
- detail.statusMessage.trim() !== ""
1406
- ) {
1407
- lines.push(` step: ${detail.statusMessage}`);
1408
- }
1409
- lines.push(
1410
- ` generation: ${detail.generation}`,
1411
- ` kind: ${detail.deploymentKind}`,
1412
- ` alias: ${aliasUrl}`,
1413
- ` playground: ${aliasUrl}/playground`,
1414
- );
1415
- if (detail.gitRepoUrl !== null && detail.gitRepoUrl !== undefined) {
1416
- lines.push(` repo: ${detail.gitRepoUrl} @ ${detail.gitRef ?? ""}`);
1417
- }
1418
- if (detail.serviceAccountId !== undefined && detail.serviceAccountId !== null) {
1419
- lines.push(` service account: ${detail.serviceAccountId}`);
1420
- }
1421
- if (detail.agentStoreSourceId !== undefined) {
1422
- // The durable file store's address: GET /v0/agent-serve-files/<id> lists
1423
- // it, and the pod sees it as AGENT_SERVE_STORE_SOURCE_ID.
1424
- lines.push(` file store: ${detail.agentStoreSourceId}`);
1425
- }
1426
- if (detail.egressAllowedDomains !== undefined && detail.egressAllowedDomains.length > 0) {
1427
- lines.push(` egress: ${detail.egressAllowedDomains.join(", ")}`);
1428
- }
1429
- if (detail.publicRoutePaths !== undefined && detail.publicRoutePaths.length > 0) {
1430
- // Served through the alias WITHOUT X-Agent-Alias-Token (the channel
1431
- // authenticates deliveries itself).
1432
- for (const path of detail.publicRoutePaths) {
1433
- lines.push(` public: ${aliasUrl}${path} (no alias token)`);
1434
- }
1435
- }
1436
- if (detail.secretNames !== undefined && detail.secretNames.length > 0) {
1437
- lines.push(` secrets: ${detail.secretNames.join(", ")}`);
1438
- }
1439
- if (detail.podCredentialMaskedKey !== undefined && detail.podCredentialMaskedKey !== null) {
1440
- lines.push(` pod credential: ${detail.podCredentialMaskedKey}`);
1441
- }
1442
- if (detail.engineUrl !== null && detail.engineUrl !== undefined) {
1443
- lines.push(` engine: ${detail.engineUrl}`);
1444
- }
1445
- if (
1446
- detail.engineAccess !== null &&
1447
- detail.engineAccess !== undefined &&
1448
- typeof detail.engineAccess === "object"
1449
- ) {
1450
- lines.push(
1451
- ` engine access: ${detail.engineAccess.url} (expires ${detail.engineAccess.expiresAt})`,
1452
- );
1453
- }
1454
- if (detail.lastError !== null && detail.lastError !== undefined) {
1455
- lines.push(` last error: ${sanitizeCustomerError(detail.lastError)}`);
1456
- }
1457
- if (detail.desiredUpdatedAt !== undefined) {
1458
- lines.push(` updated: ${detail.desiredUpdatedAt}`);
1459
- }
1460
- ctx.out(`${lines.join("\n")}\n`);
1461
- return 0;
1462
- }
1463
-
1464
- function renderAgentkitDeploymentStatus(ctx: DeployCliContext, detail: AgentkitDeployStatus): void {
1465
- if (ctx.json) {
1466
- ctx.out(`${JSON.stringify(detail, null, 2)}\n`);
1467
- return;
1468
- }
1469
- const lines = [
1470
- `${detail.slug} (team ${detail.teamId})`,
1471
- ` status: ${detail.status}`,
1472
- ` architecture: v2`,
1473
- ` application: ${detail.applicationId}`,
1474
- ` release: ${detail.releaseId}`,
1475
- ` progress: ${detail.progress}`,
1476
- ];
1477
- if (detail.statusMessage !== null && detail.statusMessage.trim() !== "") {
1478
- lines.push(` step: ${detail.statusMessage}`);
1479
- }
1480
- if (detail.repositories !== undefined) {
1481
- lines.push(
1482
- ` watching: ${
1483
- detail.repositories.length === 0 ? "(nothing)" : detail.repositories.join(", ")
1484
- }`,
1485
- );
1486
- }
1487
- if (detail.secretNames !== undefined && detail.secretNames.length > 0) {
1488
- lines.push(` secrets: ${detail.secretNames.join(", ")}`);
1489
- }
1490
- if (detail.lastError !== null && detail.lastError !== undefined) {
1491
- lines.push(` last error: ${sanitizeCustomerError(detail.lastError)}`);
1492
- }
1493
- ctx.out(`${lines.join("\n")}\n`);
1494
- }
1495
-
1496
- // ============================================================================
1497
- // stop <slug>
1498
- // ============================================================================
1499
-
1500
- export async function cmdStop(
1501
- slug: string | undefined,
1502
- options: DeployCliOptions,
1503
- ): Promise<number> {
1504
- if (slug === undefined || slug === "") {
1505
- (options.err ?? ((t: string) => void process.stderr.write(t)))(
1506
- `Usage: ${CLI} stop <slug> [--team <id>] [--json] [--no-wait]\n`,
1507
- );
1508
- return 1;
1509
- }
1510
- const ctx = await prepare(options);
1511
- if (typeof ctx === "number") {
1512
- return ctx;
1513
- }
1514
- // Stop takes only a slug, so there is no manifest to dispatch on (unlike
1515
- // deploy). The v2 agentsdk control plane goes first: v1 endpoints refuse
1516
- // `architecture: "v2"` slugs with a 409 rather than a 404, so v1-first
1517
- // could not fall through. A v2 404 (including an older backend without
1518
- // the `/internal/agentsdk` mount) falls back to the v1 stop.
1519
- let architecture: "v1" | "v2" = "v2";
1520
- let accepted: StopAccepted | AgentkitStopAccepted;
1521
- try {
1522
- accepted = await ctx.client.stopAgentkit({
1523
- teamId: ctx.teamId,
1524
- slug,
1525
- cancelRuns: options.cancelRuns,
1526
- });
1527
- } catch (error) {
1528
- if (!(error instanceof DeployApiError) || error.status !== 404) {
1529
- return renderApiError(error, ctx.err);
1530
- }
1531
- if (options.cancelRuns === true) {
1532
- ctx.err(
1533
- `Canceling active runs while stopping is supported only for Agent SDK v2 deployments.\n`,
1534
- );
1535
- return 1;
1536
- }
1537
- try {
1538
- accepted = await ctx.client.stopDeployment({ teamId: ctx.teamId, slug });
1539
- architecture = "v1";
1540
- } catch (v1Error) {
1541
- return renderApiError(v1Error, ctx.err);
1542
- }
1543
- }
1544
- const cancellation = "cancellation" in accepted ? accepted.cancellation : undefined;
1545
- const stoppedGlobally = "scope" in accepted && accepted.scope === "global";
1546
- if (ctx.noWait) {
1547
- if (ctx.json) {
1548
- ctx.out(`${JSON.stringify(accepted, null, 2)}\n`);
1549
- } else {
1550
- ctx.out(
1551
- stoppedGlobally
1552
- ? `Stop accepted for ${slug} across all tenants (status: ${accepted.status}).\n`
1553
- : `Stop accepted for ${slug} (status: ${accepted.status}).\n`,
1554
- );
1555
- }
1556
- return cancellation?.failed === 0 || cancellation === undefined ? 0 : 1;
1557
- }
1558
- let detail: DeploymentDetail | AgentkitDeployStatus;
1559
- try {
1560
- detail =
1561
- architecture === "v2"
1562
- ? await pollUntil(ctx, slug, new Set(["stopped"]), () =>
1563
- ctx.client.getAgentkitDeploy({ teamId: ctx.teamId, slug }),
1564
- )
1565
- : await pollUntil(ctx, slug, new Set(["stopped"]), () =>
1566
- ctx.client.getDeployment({ teamId: ctx.teamId, slug }),
1567
- );
1568
- } catch (error) {
1569
- return renderApiError(error, ctx.err);
1570
- }
1571
- if (ctx.json) {
1572
- ctx.out(`${JSON.stringify(detail, null, 2)}\n`);
1573
- } else if (stoppedGlobally) {
1574
- ctx.out(
1575
- `Stopped ${slug} across all tenants (team ${ctx.teamId}); resume with \`${CLI} start ${slug}\`.\n`,
1576
- );
1577
- } else {
1578
- ctx.out(`Stopped ${slug} (team ${ctx.teamId}).\n`);
1579
- }
1580
- if (cancellation !== undefined) {
1581
- return writeCancellationStarted(ctx, cancellation, slug);
1582
- }
1583
- return 0;
1584
- }
1585
-
1586
- function writeCancellationStarted(
1587
- ctx: { out: (text: string) => void; err: (text: string) => void },
1588
- cancellation: AgentkitCancelRunsResult,
1589
- slug: string,
1590
- ): number {
1591
- ctx.out(`Started cancellation across ${cancellation.batchesStarted} deployment batch(es).\n`);
1592
- if (cancellation.sessionsMarkedFailed !== undefined) {
1593
- ctx.out(`Marked ${cancellation.sessionsMarkedFailed} factory session(s) failed.\n`);
1594
- }
1595
- if (cancellation.failed > 0) {
1596
- ctx.err(
1597
- `Failed to start ${cancellation.failed} cancellation batch(es); retry with \`${CLI} cancel-runs ${slug}\`.\n`,
1598
- );
1599
- return 1;
1600
- }
1601
- return 0;
1602
- }
1603
-
1604
- export async function cmdStart(
1605
- slug: string | undefined,
1606
- options: DeployCliOptions,
1607
- ): Promise<number> {
1608
- if (slug === undefined || slug === "") {
1609
- (options.err ?? ((t: string) => void process.stderr.write(t)))(
1610
- `Usage: ${CLI} start <slug> [--team <id>] [--json]\n`,
1611
- );
1612
- return 1;
1613
- }
1614
- const ctx = await prepare(options);
1615
- if (typeof ctx === "number") {
1616
- return ctx;
1617
- }
1618
- try {
1619
- const accepted = await ctx.client.startAgentkit({
1620
- teamId: ctx.teamId,
1621
- slug,
1622
- });
1623
- if (ctx.json) {
1624
- ctx.out(`${JSON.stringify(accepted, null, 2)}\n`);
1625
- } else {
1626
- ctx.out(`Started ${slug} (team ${ctx.teamId}).\n`);
1627
- }
1628
- return 0;
1629
- } catch (error) {
1630
- return renderApiError(error, ctx.err);
1631
- }
1632
- }
1633
-
1634
- export async function cmdKill(
1635
- slug: string | undefined,
1636
- options: DeployCliOptions,
1637
- ): Promise<number> {
1638
- if (slug === undefined || slug === "") {
1639
- (options.err ?? ((t: string) => void process.stderr.write(t)))(
1640
- `Usage: ${CLI} kill <slug> [--team <id>] [--json]\n`,
1641
- );
1642
- return 1;
1643
- }
1644
- const ctx = await prepare(options);
1645
- if (typeof ctx === "number") {
1646
- return ctx;
1647
- }
1648
- let accepted: AgentkitStopAccepted;
1649
- try {
1650
- accepted = await ctx.client.killAgentkit({ teamId: ctx.teamId, slug });
1651
- } catch (error) {
1652
- return renderApiError(error, ctx.err);
1653
- }
1654
- if (ctx.json) {
1655
- ctx.out(`${JSON.stringify(accepted, null, 2)}\n`);
1656
- } else {
1657
- ctx.out(
1658
- accepted.scope === "global"
1659
- ? `Killed ${slug} across all tenants (team ${ctx.teamId}): deploys locked, admission stopped.\n`
1660
- : `Killed ${slug} (team ${ctx.teamId}): deploys locked, admission stopped.\n`,
1661
- );
1662
- ctx.out(
1663
- `Resume traffic with \`${CLI} unlock-deploys ${slug}\` then \`${CLI} start ${slug}\`.\n`,
1664
- );
1665
- ctx.out(`Unlock deploys with \`${CLI} unlock-deploys ${slug}\`.\n`);
1666
- }
1667
- if (accepted.cancellation !== undefined) {
1668
- return writeCancellationStarted(ctx, accepted.cancellation, slug);
1669
- }
1670
- return 0;
1671
- }
1672
-
1673
- export async function cmdUnlockDeploys(
1674
- slug: string | undefined,
1675
- options: DeployCliOptions,
1676
- ): Promise<number> {
1677
- if (slug === undefined || slug === "") {
1678
- (options.err ?? ((t: string) => void process.stderr.write(t)))(
1679
- `Usage: ${CLI} unlock-deploys <slug> [--team <id>] [--json]\n`,
1680
- );
1681
- return 1;
1682
- }
1683
- const ctx = await prepare(options);
1684
- if (typeof ctx === "number") {
1685
- return ctx;
1686
- }
1687
- try {
1688
- const accepted = await ctx.client.unlockAgentkitDeploys({
1689
- teamId: ctx.teamId,
1690
- slug,
1691
- });
1692
- if (ctx.json) {
1693
- ctx.out(`${JSON.stringify(accepted, null, 2)}\n`);
1694
- } else {
1695
- ctx.out(`Unlocked deploys for ${slug} (team ${ctx.teamId}).\n`);
1696
- }
1697
- return 0;
1698
- } catch (error) {
1699
- return renderApiError(error, ctx.err);
1700
- }
1701
- }
1702
-
1703
- export async function cmdCancelRuns(
1704
- slug: string | undefined,
1705
- options: DeployCliOptions,
1706
- ): Promise<number> {
1707
- if (slug === undefined || slug === "") {
1708
- (options.err ?? ((text: string) => void process.stderr.write(text)))(
1709
- `Usage: ${CLI} cancel-runs <slug> [--team <id>] [--json]\n`,
1710
- );
1711
- return 1;
1712
- }
1713
- const ctx = await prepare(options);
1714
- if (typeof ctx === "number") {
1715
- return ctx;
1716
- }
1717
- let result: AgentkitCancelRunsResult;
1718
- try {
1719
- result = await ctx.client.cancelAgentkitRuns({
1720
- teamId: ctx.teamId,
1721
- slug,
1722
- });
1723
- } catch (error) {
1724
- return renderApiError(error, ctx.err);
1725
- }
1726
- if (ctx.json) {
1727
- ctx.out(`${JSON.stringify(result, null, 2)}\n`);
1728
- } else {
1729
- ctx.out(`Started cancellation across ${result.batchesStarted} deployment batch(es).\n`);
1730
- if (result.sessionsMarkedFailed !== undefined) {
1731
- ctx.out(`Marked ${result.sessionsMarkedFailed} factory session(s) failed.\n`);
1732
- }
1733
- }
1734
- if (result.failed > 0) {
1735
- ctx.err(`Failed to start ${result.failed} cancellation batch(es).\n`);
1736
- return 1;
1737
- }
1738
- return 0;
1739
- }
1740
-
1741
- // ============================================================================
1742
- // event-repos <slug> --repo <owner/name>...
1743
- // ============================================================================
1744
-
1745
- export async function cmdEventRepos(
1746
- slug: string | undefined,
1747
- repositories: string[],
1748
- options: DeployCliOptions,
1749
- ): Promise<number> {
1750
- if (slug === undefined || slug === "") {
1751
- (options.err ?? ((text: string) => void process.stderr.write(text)))(
1752
- `Usage: ${CLI} event-repos <slug> --repo <owner/name>... [--team <id>] [--json]\n`,
1753
- );
1754
- return 1;
1755
- }
1756
- const ctx = await prepare(options);
1757
- if (typeof ctx === "number") {
1758
- return ctx;
1759
- }
1760
- let configured: string[];
1761
- try {
1762
- configured = await ctx.client.setAgentkitEventRepositories({
1763
- teamId: ctx.teamId,
1764
- slug,
1765
- repositories,
1766
- });
1767
- } catch (error) {
1768
- return renderApiError(error, ctx.err);
1769
- }
1770
- if (ctx.json) {
1771
- ctx.out(`${JSON.stringify({ repositories: configured }, null, 2)}\n`);
1772
- } else if (configured.length === 0) {
1773
- ctx.out(`${slug} now watches no repositories.\n`);
1774
- } else {
1775
- ctx.out(`${slug} now watches ${configured.join(", ")}.\n`);
1776
- }
1777
- return 0;
1778
- }
1779
-
1780
- // ============================================================================
1781
- // upgrade <slug>
1782
- // ============================================================================
1783
-
1784
- /** Release ids are uuids; anything else the user typed is a version. */
1785
- const RELEASE_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1786
-
1787
- export async function cmdUpgrade(
1788
- args: { slug: string | undefined; release: string | undefined },
1789
- options: DeployCliOptions,
1790
- ): Promise<number> {
1791
- return cmdPinRelease(args, options, {
1792
- usage: `Usage: ${CLI} upgrade <slug> [--release <id|version>] [--team <id>] [--json]\n`,
1793
- pin: (client, request) => client.upgradeAgentkitInstall(request),
1794
- success: (slug, releaseId) => `${slug} now runs release ${releaseId}.\n`,
1795
- });
1796
- }
1797
-
1798
- export async function cmdRollback(
1799
- args: { slug: string | undefined; release: string | undefined },
1800
- options: DeployCliOptions,
1801
- ): Promise<number> {
1802
- return cmdPinRelease(args, options, {
1803
- usage: `Usage: ${CLI} rollback <slug> [--release <id|version>] [--team <id>] [--json]\n`,
1804
- pin: (client, request) => client.rollbackAgentkitInstall(request),
1805
- success: (slug, releaseId) => `${slug} rolled back to release ${releaseId}.\n`,
1806
- });
1807
- }
1808
-
1809
- async function cmdPinRelease(
1810
- args: { slug: string | undefined; release: string | undefined },
1811
- options: DeployCliOptions,
1812
- pin: {
1813
- usage: string;
1814
- pin: (
1815
- client: AgentServeDeployClient,
1816
- request: {
1817
- teamId: number;
1818
- slug: string;
1819
- releaseId?: string;
1820
- version?: string;
1821
- },
1822
- ) => Promise<string>;
1823
- success: (slug: string, releaseId: string) => string;
1824
- },
1825
- ): Promise<number> {
1826
- const { slug, release } = args;
1827
- if (slug === undefined || slug === "") {
1828
- (options.err ?? ((text: string) => void process.stderr.write(text)))(pin.usage);
1829
- return 1;
1830
- }
1831
- const ctx = await prepare(options);
1832
- if (typeof ctx === "number") {
1833
- return ctx;
1834
- }
1835
- const selector = release?.trim() ?? "";
1836
- let releaseId: string;
1837
- try {
1838
- releaseId = await pin.pin(ctx.client, {
1839
- teamId: ctx.teamId,
1840
- slug,
1841
- ...(selector === ""
1842
- ? {}
1843
- : RELEASE_ID_RE.test(selector)
1844
- ? { releaseId: selector }
1845
- : { version: selector }),
1846
- });
1847
- } catch (error) {
1848
- return renderApiError(error, ctx.err);
1849
- }
1850
- if (ctx.json) {
1851
- ctx.out(`${JSON.stringify({ releaseId }, null, 2)}\n`);
1852
- } else {
1853
- ctx.out(pin.success(slug, releaseId));
1854
- }
1855
- return 0;
1856
- }
1857
-
1858
- // ============================================================================
1859
- // delete <slug>
1860
- // ============================================================================
1861
-
1862
- export async function cmdDelete(
1863
- slug: string | undefined,
1864
- options: DeployCliOptions,
1865
- ): Promise<number> {
1866
- if (slug === undefined || slug === "") {
1867
- (options.err ?? ((t: string) => void process.stderr.write(t)))(
1868
- `Usage: ${CLI} delete <slug> [--team <id>] [--json] [--no-wait]\n`,
1869
- );
1870
- return 1;
1871
- }
1872
- const ctx = await prepare(options);
1873
- if (typeof ctx === "number") {
1874
- return ctx;
1875
- }
1876
- // Same dispatch as `stop`: v1 409s architecture-v2 slugs, so the v2
1877
- // DELETE goes first. A v2 404 (missing slug, or an older backend)
1878
- // falls through to the v1 agent-serve delete.
1879
- let architecture: "v1" | "v2" = "v2";
1880
- let accepted: DeleteAccepted | AgentkitStopAccepted;
1881
- try {
1882
- accepted = await ctx.client.deleteAgentkit({ teamId: ctx.teamId, slug });
1883
- } catch (error) {
1884
- if (!(error instanceof DeployApiError) || error.status !== 404) {
1885
- return renderApiError(error, ctx.err);
1886
- }
1887
- try {
1888
- accepted = await ctx.client.deleteDeployment({
1889
- teamId: ctx.teamId,
1890
- slug,
1891
- });
1892
- architecture = "v1";
1893
- } catch (v1Error) {
1894
- return renderApiError(v1Error, ctx.err);
1895
- }
1896
- }
1897
- if (ctx.noWait) {
1898
- if (ctx.json) {
1899
- ctx.out(`${JSON.stringify(accepted, null, 2)}\n`);
1900
- } else {
1901
- ctx.out(`Delete accepted for ${slug} (status: ${accepted.status}).\n`);
1902
- }
1903
- return 0;
1904
- }
1905
- try {
1906
- await pollUntilGone(ctx, slug, () =>
1907
- architecture === "v2"
1908
- ? ctx.client.getAgentkitDeploy({ teamId: ctx.teamId, slug })
1909
- : ctx.client.getDeployment({ teamId: ctx.teamId, slug }),
1910
- );
1911
- } catch (error) {
1912
- return renderApiError(error, ctx.err);
1913
- }
1914
- if (ctx.json) {
1915
- ctx.out(`${JSON.stringify({ slug, status: "deleted" }, null, 2)}\n`);
1916
- } else {
1917
- ctx.out(`Deleted ${slug} (team ${ctx.teamId}).\n`);
1918
- }
1919
- return 0;
1920
- }
1921
-
1922
- // ============================================================================
1923
- // rotate-token <slug>
1924
- // ============================================================================
1925
-
1926
- export async function cmdRotateToken(
1927
- slug: string | undefined,
1928
- options: DeployCliOptions,
1929
- ): Promise<number> {
1930
- if (slug === undefined || slug === "") {
1931
- (options.err ?? ((t: string) => void process.stderr.write(t)))(
1932
- `Usage: ${CLI} rotate-token <slug> [--team <id>]\n`,
1933
- );
1934
- return 1;
1935
- }
1936
- const ctx = await prepare(options);
1937
- if (typeof ctx === "number") {
1938
- return ctx;
1939
- }
1940
- let aliasToken: string;
1941
- try {
1942
- const architecture = await deploymentArchitecture({
1943
- client: ctx.client,
1944
- teamId: ctx.teamId,
1945
- slug,
1946
- });
1947
- aliasToken =
1948
- architecture === "v2"
1949
- ? await ctx.client.rotateAgentsdkAliasToken({
1950
- teamId: ctx.teamId,
1951
- slug,
1952
- })
1953
- : await ctx.client.rotateAliasToken({
1954
- teamId: ctx.teamId,
1955
- slug,
1956
- });
1957
- } catch (error) {
1958
- return renderApiError(error, ctx.err);
1959
- }
1960
- if (ctx.json) {
1961
- ctx.out(`${JSON.stringify({ aliasToken }, null, 2)}\n`);
1962
- return 0;
1963
- }
1964
- ctx.out(
1965
- `Rotated the alias token for ${slug}. The old token stopped working immediately.\n${aliasTokenBlock(aliasToken)}`,
1966
- );
1967
- return 0;
1968
- }
1969
-
1970
- // ============================================================================
1971
- // secrets set|list|unset
1972
- // ============================================================================
1973
-
1974
- async function secretDeploymentArchitecture(
1975
- ctx: DeployCliContext,
1976
- slug: string,
1977
- ): Promise<"v1" | "v2"> {
1978
- return deploymentArchitecture({
1979
- client: ctx.client,
1980
- teamId: ctx.teamId,
1981
- slug,
1982
- });
1983
- }
1984
-
1985
- export async function cmdSecretsSet(
1986
- slug: string | undefined,
1987
- specs: string[],
1988
- options: DeployCliOptions,
1989
- ): Promise<number> {
1990
- const usageErr = options.err ?? ((t: string) => void process.stderr.write(t));
1991
- if (slug === undefined || slug === "" || specs.length === 0) {
1992
- usageErr(
1993
- `Usage: ${CLI} secrets set <slug> NAME [NAME2 ...] [--team <id>] [--json]\n` +
1994
- ` Enter values at the hidden prompt, or pipe one line per NAME.\n` +
1995
- ` Opt-in (leaks into argv / agent terminals): NAME=VALUE … --from-argv\n`,
1996
- );
1997
- return 1;
1998
- }
1999
-
2000
- // Parse and validate every name before prompting for any value, so a
2001
- // typo in the last name cannot waste typed-in secrets.
2002
- const parsed: Array<{ name: string; value?: string }> = [];
2003
- for (const spec of specs) {
2004
- const eq = spec.indexOf("=");
2005
- const name = eq === -1 ? spec : spec.slice(0, eq);
2006
- const nameError = validateSettableSecretName(name);
2007
- if (nameError !== undefined) {
2008
- usageErr(`${nameError}\n`);
2009
- return 1;
2010
- }
2011
- parsed.push(eq === -1 ? { name } : { name, value: spec.slice(eq + 1) });
2012
- }
2013
- const hasArgvValues = parsed.some(entry => entry.value !== undefined);
2014
- if (hasArgvValues && options.fromArgv !== true) {
2015
- usageErr(
2016
- `Refusing NAME=VALUE on argv (shows up in shell history and agent-captured terminals).\n` +
2017
- `Pass names only:\n` +
2018
- ` ${CLI} secrets set ${slug} NAME\n` +
2019
- `Hidden prompt on a TTY; one stdin line per NAME when piped.\n` +
2020
- `Or redirect a file: ${CLI} secrets set ${slug} NAME < ./secret.txt\n`,
2021
- );
2022
- return 1;
2023
- }
2024
- if (hasArgvValues) {
2025
- usageErr(
2026
- `warning: --from-argv puts secret values in argv (shell history and agent-captured terminals).\n`,
2027
- );
2028
- }
2029
-
2030
- const ctx = await prepare(options);
2031
- if (typeof ctx === "number") {
2032
- return ctx;
2033
- }
2034
-
2035
- const stdin = options.stdin ?? process.stdin;
2036
- const readValue = createSecretValueReader(stdin, ctx.err);
2037
- const secrets: Array<{ name: string; value: string }> = [];
2038
- for (const entry of parsed) {
2039
- secrets.push({
2040
- name: entry.name,
2041
- value: entry.value ?? (await readValue(entry.name)),
2042
- });
2043
- }
2044
-
2045
- let secretNames: string[];
2046
- let architecture: "v1" | "v2";
2047
- try {
2048
- architecture = await secretDeploymentArchitecture(ctx, slug);
2049
- secretNames =
2050
- architecture === "v2"
2051
- ? await ctx.client.setAgentkitSecrets({
2052
- teamId: ctx.teamId,
2053
- slug,
2054
- secrets,
2055
- })
2056
- : await ctx.client.setSecrets({
2057
- teamId: ctx.teamId,
2058
- slug,
2059
- secrets,
2060
- });
2061
- } catch (error) {
2062
- return renderApiError(error, ctx.err);
2063
- }
2064
- if (ctx.json) {
2065
- ctx.out(`${JSON.stringify({ secretNames }, null, 2)}\n`);
2066
- return 0;
2067
- }
2068
- ctx.out(
2069
- `Set ${secrets.length} secret${secrets.length === 1 ? "" : "s"} on ${slug}.\n` +
2070
- `Secrets now set: ${secretNames.join(", ")}\n` +
2071
- (architecture === "v2"
2072
- ? `The next task picks them up; no redeploy is required.\n`
2073
- : `The engine picks them up on its next deploy.\n`),
2074
- );
2075
- return 0;
2076
- }
2077
-
2078
- export async function cmdSecretsList(
2079
- slug: string | undefined,
2080
- options: DeployCliOptions,
2081
- ): Promise<number> {
2082
- if (slug === undefined || slug === "") {
2083
- (options.err ?? ((t: string) => void process.stderr.write(t)))(
2084
- `Usage: ${CLI} secrets list <slug> [--team <id>] [--json]\n`,
2085
- );
2086
- return 1;
2087
- }
2088
- const ctx = await prepare(options);
2089
- if (typeof ctx === "number") {
2090
- return ctx;
2091
- }
2092
- let secrets: SecretInfo[];
2093
- try {
2094
- const architecture = await secretDeploymentArchitecture(ctx, slug);
2095
- secrets =
2096
- architecture === "v2"
2097
- ? await ctx.client.listAgentkitSecrets({ teamId: ctx.teamId, slug })
2098
- : await ctx.client.listSecrets({ teamId: ctx.teamId, slug });
2099
- } catch (error) {
2100
- return renderApiError(error, ctx.err);
2101
- }
2102
- if (ctx.json) {
2103
- ctx.out(`${JSON.stringify({ secrets }, null, 2)}\n`);
2104
- return 0;
2105
- }
2106
- if (secrets.length === 0) {
2107
- ctx.out(`No secrets set on ${slug}. Add one with \`${CLI} secrets set ${slug} NAME\`.\n`);
2108
- return 0;
2109
- }
2110
- ctx.out(
2111
- `${renderTable(
2112
- ["NAME", "CREATED"],
2113
- secrets.map(secret => [secret.name, secret.createdAt]),
2114
- )}\n`,
2115
- );
2116
- return 0;
2117
- }
2118
-
2119
- export async function cmdSecretsUnset(
2120
- slug: string | undefined,
2121
- name: string | undefined,
2122
- options: DeployCliOptions,
2123
- ): Promise<number> {
2124
- if (slug === undefined || slug === "" || name === undefined || name === "") {
2125
- (options.err ?? ((t: string) => void process.stderr.write(t)))(
2126
- `Usage: ${CLI} secrets unset <slug> NAME [--team <id>]\n`,
2127
- );
2128
- return 1;
2129
- }
2130
- const ctx = await prepare(options);
2131
- if (typeof ctx === "number") {
2132
- return ctx;
2133
- }
2134
- try {
2135
- const architecture = await secretDeploymentArchitecture(ctx, slug);
2136
- if (architecture === "v2") {
2137
- await ctx.client.deleteAgentkitSecret({
2138
- teamId: ctx.teamId,
2139
- slug,
2140
- name,
2141
- });
2142
- } else {
2143
- await ctx.client.deleteSecret({ teamId: ctx.teamId, slug, name });
2144
- }
2145
- } catch (error) {
2146
- if (error instanceof DeployApiError && error.status === 404) {
2147
- ctx.err(
2148
- `No secret named ${name} on deployment ${slug} — check \`${CLI} secrets list ${slug}\` (and the slug / --team).\n`,
2149
- );
2150
- return 1;
2151
- }
2152
- return renderApiError(error, ctx.err);
2153
- }
2154
- if (ctx.json) {
2155
- ctx.out(`${JSON.stringify({ removed: name }, null, 2)}\n`);
2156
- } else {
2157
- ctx.out(`Removed secret ${name} from ${slug}.\n`);
2158
- }
2159
- return 0;
2160
- }
2161
-
2162
- /**
2163
- * Returns a reader for interactive secret values: hidden (no-echo) prompt
2164
- * when `stdin` is a TTY, otherwise one line per secret from the piped
2165
- * stream. One reader per command so piped lines are consumed in order.
2166
- */
2167
- function createSecretValueReader(
2168
- stdin: SecretInputStream,
2169
- err: (text: string) => void,
2170
- ): (name: string) => Promise<string> {
2171
- if (stdin.isTTY === true) {
2172
- return name => promptHidden(stdin, err, `Value for ${name}: `);
2173
- }
2174
- const readLine = createLineReader(stdin);
2175
- return async name => {
2176
- const line = await readLine();
2177
- if (line === undefined) {
2178
- throw new DeployApiError(
2179
- `stdin ended before a value for ${name} was provided (pipe one line per secret).`,
2180
- 0,
2181
- );
2182
- }
2183
- return line;
2184
- };
2185
- }
2186
-
2187
- /** Longest mask run drawn while typing a secret; the count carries the rest. */
2188
- const SECRET_MASK_MAX_WIDTH = 24;
2189
-
2190
- /**
2191
- * One line of typing feedback for the hidden prompt. Echoing the value would
2192
- * leak it, so the line carries a bounded mask plus the exact character count —
2193
- * enough to see that keystrokes, backspaces, and pasted values landed. The
2194
- * mask is clamped to the terminal width so the redraw stays on one line.
2195
- */
2196
- function renderSecretPromptLine(
2197
- prompt: string,
2198
- length: number,
2199
- dim: (text: string) => string,
2200
- ): string {
2201
- const count = `${length} char${length === 1 ? "" : "s"}`;
2202
- const room = (process.stderr.columns ?? 80) - prompt.length - count.length - 2;
2203
- const maskWidth = Math.max(0, Math.min(length, SECRET_MASK_MAX_WIDTH, room));
2204
- // `·` over `•`: the rest of the CLI's progress output already uses it, and
2205
- // fonts that ship no bullet glyph draw a tofu box in its place.
2206
- const mask = "·".repeat(maskWidth);
2207
- const body = mask === "" ? count : `${mask} ${count}`;
2208
- return `\r\u001b[2K${prompt}${dim(body)}`;
2209
- }
2210
-
2211
- /**
2212
- * Raw-mode hidden prompt: never echoes the value, redraws a mask + character
2213
- * count as it is typed, supports backspace and Ctrl-C.
2214
- */
2215
- function promptHidden(
2216
- stdin: SecretInputStream,
2217
- err: (text: string) => void,
2218
- prompt: string,
2219
- ): Promise<string> {
2220
- return new Promise((resolvePromise, reject) => {
2221
- const { dim } = stderrPalette();
2222
- let value = "";
2223
- const draw = (): void => {
2224
- err(renderSecretPromptLine(prompt, value.length, dim));
2225
- };
2226
- draw();
2227
- stdin.setRawMode?.(true);
2228
- stdin.resume();
2229
- const cleanup = (): void => {
2230
- stdin.off("data", onData);
2231
- stdin.setRawMode?.(false);
2232
- stdin.pause();
2233
- draw();
2234
- err("\n");
2235
- };
2236
- const onData = (chunk: Buffer | string): void => {
2237
- const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
2238
- for (const ch of text) {
2239
- if (ch === "\r" || ch === "\n") {
2240
- cleanup();
2241
- resolvePromise(value);
2242
- return;
2243
- }
2244
- if (ch === "\u0003") {
2245
- cleanup();
2246
- reject(new DeployApiError("Aborted.", 0));
2247
- return;
2248
- }
2249
- if (ch === "\u007f" || ch === "\b") {
2250
- value = value.slice(0, -1);
2251
- continue;
2252
- }
2253
- value += ch;
2254
- }
2255
- // One redraw per chunk keeps a pasted value from flooding the terminal.
2256
- draw();
2257
- };
2258
- stdin.on("data", onData);
2259
- });
2260
- }
2261
-
2262
- /** Buffered line reader over a piped stream; undefined once it ends. */
2263
- export function createLineReader(stream: NodeJS.ReadableStream): () => Promise<string | undefined> {
2264
- let buffer = "";
2265
- let ended = false;
2266
- const waiters: Array<(line: string | undefined) => void> = [];
2267
-
2268
- const drain = (): void => {
2269
- while (waiters.length > 0) {
2270
- const newline = buffer.indexOf("\n");
2271
- if (newline !== -1) {
2272
- const line = buffer.slice(0, newline).replace(/\r$/, "");
2273
- buffer = buffer.slice(newline + 1);
2274
- waiters.shift()?.(line);
2275
- continue;
2276
- }
2277
- if (!ended) {
2278
- return;
2279
- }
2280
- // Stream ended: a trailing unterminated line still counts once.
2281
- const rest = buffer;
2282
- buffer = "";
2283
- waiters.shift()?.(rest === "" ? undefined : rest.replace(/\r$/, ""));
2284
- }
2285
- };
2286
-
2287
- stream.on("data", (chunk: Buffer | string) => {
2288
- buffer += typeof chunk === "string" ? chunk : chunk.toString("utf8");
2289
- drain();
2290
- });
2291
- stream.on("end", () => {
2292
- ended = true;
2293
- drain();
2294
- });
2295
- stream.resume();
2296
-
2297
- return () =>
2298
- new Promise(resolvePromise => {
2299
- waiters.push(resolvePromise);
2300
- drain();
2301
- });
2302
- }
2303
-
2304
- // ============================================================================
2305
- // Polling + rendering helpers
2306
- // ============================================================================
2307
-
2308
- /**
2309
- * Poll deployment status every `pollIntervalMs` until it lands in
2310
- * `terminal` (single-line progress on a TTY, one line per transition
2311
- * otherwise). Prefers customer `statusMessage` / `progress` over raw
2312
- * status so create → checkout → start is visible. Throws DeployApiError
2313
- * on request failures or timeout.
2314
- */
2315
- async function pollUntil<
2316
- T extends {
2317
- status: string;
2318
- progress?: DeploymentProgress;
2319
- statusMessage?: string | null;
2320
- },
2321
- >(
2322
- ctx: DeployCliContext,
2323
- slug: string,
2324
- terminal: ReadonlySet<T["status"]>,
2325
- fetchDetail: () => Promise<T>,
2326
- ): Promise<T> {
2327
- const startedAt = Date.now();
2328
- const tty = process.stderr.isTTY === true;
2329
- let lastLabel: string | undefined;
2330
- let sawProgress = false;
2331
-
2332
- const report = (detail: T): void => {
2333
- if (ctx.json) {
2334
- return;
2335
- }
2336
- const label = deployProgressLabel(detail);
2337
- const elapsed = Math.round((Date.now() - startedAt) / 1000);
2338
- if (tty) {
2339
- ctx.err(`\r\x1b[2K${slug}: ${label} (${elapsed}s)`);
2340
- sawProgress = true;
2341
- } else if (label !== lastLabel) {
2342
- ctx.err(`${slug}: ${label}\n`);
2343
- }
2344
- lastLabel = label;
2345
- };
2346
- const finishProgressLine = (): void => {
2347
- if (tty && sawProgress) {
2348
- ctx.err("\n");
2349
- }
2350
- };
2351
-
2352
- for (;;) {
2353
- let detail: T;
2354
- try {
2355
- detail = await fetchDetail();
2356
- } catch (error: unknown) {
2357
- // Capacity / rate-limit on GET is not a bake failure. The v2 accept
2358
- // already started freeze; keep polling until the wait budget expires.
2359
- if (isTransientDeployStatusError(error) && Date.now() - startedAt < ctx.timeoutMs) {
2360
- if (!ctx.json) {
2361
- const elapsed = Math.round((Date.now() - startedAt) / 1000);
2362
- const label = "Waiting for status (server busy)";
2363
- if (tty) {
2364
- ctx.err(`\r\x1b[2K${slug}: ${label} (${elapsed}s)`);
2365
- sawProgress = true;
2366
- } else if (label !== lastLabel) {
2367
- ctx.err(`${slug}: ${label}\n`);
2368
- }
2369
- lastLabel = label;
2370
- }
2371
- const waitMs = transientDeployStatusWaitMs(error, ctx.pollIntervalMs);
2372
- const remaining = ctx.timeoutMs - (Date.now() - startedAt);
2373
- await sleep(Math.max(0, Math.min(waitMs, remaining)));
2374
- continue;
2375
- }
2376
- finishProgressLine();
2377
- throw error;
2378
- }
2379
- report(detail);
2380
- if (terminal.has(detail.status)) {
2381
- finishProgressLine();
2382
- return detail;
2383
- }
2384
- if (Date.now() - startedAt >= ctx.timeoutMs) {
2385
- finishProgressLine();
2386
- const last = deployProgressLabel(detail);
2387
- throw new DeployApiError(
2388
- `Timed out after ${Math.round(ctx.timeoutMs / 1000)}s waiting for ${slug} (last: ${last}). It may still converge — check \`${CLI} deployment ${slug} --team ${ctx.teamId}\`.`,
2389
- 0,
2390
- );
2391
- }
2392
- await sleep(ctx.pollIntervalMs);
2393
- }
2394
- }
2395
-
2396
- /** Load-shed / rate-limit on status GET — the deploy itself may still be baking. */
2397
- function isTransientDeployStatusError(error: unknown): error is DeployApiError {
2398
- return error instanceof DeployApiError && (error.status === 503 || error.status === 429);
2399
- }
2400
-
2401
- function transientDeployStatusWaitMs(error: DeployApiError, pollIntervalMs: number): number {
2402
- if (
2403
- error.status === 429 &&
2404
- error.retryAfterSeconds !== undefined &&
2405
- error.retryAfterSeconds > 0
2406
- ) {
2407
- return Math.max(pollIntervalMs, error.retryAfterSeconds * 1000);
2408
- }
2409
- return pollIntervalMs;
2410
- }
2411
-
2412
- /**
2413
- * Wait until GET 404s (the delete reconciler purged the record). Treats
2414
- * other errors as failures. Throws DeployApiError on timeout.
2415
- */
2416
- async function pollUntilGone(
2417
- ctx: DeployCliContext,
2418
- slug: string,
2419
- getDetail: () => Promise<{
2420
- status: string;
2421
- progress?: DeploymentProgress;
2422
- statusMessage?: string | null;
2423
- }>,
2424
- ): Promise<void> {
2425
- const startedAt = Date.now();
2426
- const tty = process.stderr.isTTY === true;
2427
- let sawProgress = false;
2428
- const report = (label: string): void => {
2429
- if (ctx.json) {
2430
- return;
2431
- }
2432
- const elapsed = Math.round((Date.now() - startedAt) / 1000);
2433
- if (tty) {
2434
- ctx.err(`\r\x1b[2K${slug}: ${label} (${elapsed}s)`);
2435
- sawProgress = true;
2436
- }
2437
- };
2438
- const finishProgressLine = (): void => {
2439
- if (tty && sawProgress) {
2440
- ctx.err("\n");
2441
- }
2442
- };
2443
-
2444
- for (;;) {
2445
- try {
2446
- const detail = await getDetail();
2447
- report(deployProgressLabel(detail));
2448
- } catch (error: unknown) {
2449
- if (error instanceof DeployApiError && error.status === 404) {
2450
- finishProgressLine();
2451
- return;
2452
- }
2453
- finishProgressLine();
2454
- throw error;
2455
- }
2456
- if (Date.now() - startedAt >= ctx.timeoutMs) {
2457
- finishProgressLine();
2458
- throw new DeployApiError(
2459
- `Timed out after ${Math.round(ctx.timeoutMs / 1000)}s waiting for ${slug} to disappear. It may still be deleting — check \`${CLI} deployment ${slug} --team ${ctx.teamId}\`.`,
2460
- 0,
2461
- );
2462
- }
2463
- await sleep(ctx.pollIntervalMs);
2464
- }
2465
- }
2466
-
2467
- function aliasTokenBlock(aliasToken: string): string {
2468
- return (
2469
- `\n Alias token (shown ONCE — save it now, it cannot be retrieved again):\n\n` +
2470
- ` ${aliasToken}\n\n` +
2471
- ` Send it as the X-Agent-Alias-Token header on requests to the alias URL,\n` +
2472
- ` or paste it into the hosted playground (<alias>/playground) sign-in gate.\n` +
2473
- ` Lost tokens: \`${CLI} rotate-token <slug>\` mints a replacement.\n\n`
2474
- );
2475
- }
2476
-
2477
- /**
2478
- * `: <reason>` suffix for a deploy that ended in a non-running state, or
2479
- * empty when the control plane recorded no reason.
2480
- */
2481
- function deployFailureDetail(lastError: string | null | undefined): string {
2482
- if (lastError === null || lastError === undefined || lastError.trim() === "") {
2483
- return "";
2484
- }
2485
- return `: ${sanitizeCustomerError(lastError.trim())}`;
2486
- }
2487
-
2488
- export function renderApiError(
2489
- error: unknown,
2490
- err: (text: string) => void,
2491
- context?: { multiTenant?: boolean; teamId?: number },
2492
- ): number {
2493
- if (error instanceof DeployApiError) {
2494
- err(`${error.message}\n`);
2495
- if (error.status === 409 && error.message.includes("application multiTenant does not match")) {
2496
- if (context?.multiTenant === true) {
2497
- err("This slug is a single-tenant application. Redeploy it without --multi-tenant.\n");
2498
- } else if (context?.teamId === MULTI_TENANT_HTTP_DEPLOY_TEAM_ID) {
2499
- err(
2500
- "This slug is a Cursor-managed (multi-tenant) product. Redeploy it with --multi-tenant.\n",
2501
- );
2502
- }
2503
- }
2504
- return 1;
2505
- }
2506
- throw error;
2507
- }
2508
-
2509
- export function renderTable(header: string[], rows: string[][]): string {
2510
- const widths = header.map((h, i) =>
2511
- Math.max(h.length, ...rows.map(row => (row[i] ?? "").length)),
2512
- );
2513
- const renderRow = (row: string[]): string =>
2514
- row
2515
- .map((cell, i) => cell.padEnd(widths[i] ?? 0))
2516
- .join(" ")
2517
- .trimEnd();
2518
- return [renderRow(header), ...rows.map(renderRow)].join("\n");
2519
- }