@cursor/july 0.1.97 → 0.1.100

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 (337) hide show
  1. package/AGENTS.md +5 -3
  2. package/dist/bin/agent-serve.js +6 -7
  3. package/dist/channels/github/defaults.d.ts.map +1 -1
  4. package/dist/channels/github/defaults.js +28 -3
  5. package/dist/channels/github/github-channel.d.ts.map +1 -1
  6. package/dist/channels/github/github-channel.js +16 -0
  7. package/dist/channels/github/progress.d.ts +7 -0
  8. package/dist/channels/github/progress.d.ts.map +1 -1
  9. package/dist/channels/origin/origin-channel.d.ts +2 -0
  10. package/dist/channels/origin/origin-channel.d.ts.map +1 -1
  11. package/dist/channels/origin/origin-channel.js +37 -4
  12. package/dist/channels/slack/api.d.ts +16 -7
  13. package/dist/channels/slack/api.d.ts.map +1 -1
  14. package/dist/channels/slack/api.js +29 -13
  15. package/dist/channels/slack/constants.d.ts +6 -0
  16. package/dist/channels/slack/constants.d.ts.map +1 -1
  17. package/dist/channels/slack/constants.js +6 -0
  18. package/dist/channels/slack/defaults.d.ts +9 -4
  19. package/dist/channels/slack/defaults.d.ts.map +1 -1
  20. package/dist/channels/slack/defaults.js +221 -122
  21. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  22. package/dist/channels/slack/dispatch.js +3 -3
  23. package/dist/channels/slack/inbound.d.ts +9 -0
  24. package/dist/channels/slack/inbound.d.ts.map +1 -1
  25. package/dist/channels/slack/inbound.js +14 -0
  26. package/dist/channels/slack/index.d.ts +1 -0
  27. package/dist/channels/slack/index.d.ts.map +1 -1
  28. package/dist/channels/slack/index.js +1 -0
  29. package/dist/channels/slack/live-delivery.d.ts +6 -1
  30. package/dist/channels/slack/live-delivery.d.ts.map +1 -1
  31. package/dist/channels/slack/live-delivery.js +110 -20
  32. package/dist/channels/slack/progress-delivery.d.ts +28 -0
  33. package/dist/channels/slack/progress-delivery.d.ts.map +1 -0
  34. package/dist/channels/slack/progress-delivery.js +115 -0
  35. package/dist/channels/slack/reasoning-card.d.ts +38 -0
  36. package/dist/channels/slack/reasoning-card.d.ts.map +1 -0
  37. package/dist/channels/slack/reasoning-card.js +104 -0
  38. package/dist/channels/slack/redact.d.ts +2 -0
  39. package/dist/channels/slack/redact.d.ts.map +1 -0
  40. package/dist/channels/slack/redact.js +5 -0
  41. package/dist/channels/slack/reply-options.d.ts +40 -0
  42. package/dist/channels/slack/reply-options.d.ts.map +1 -0
  43. package/dist/channels/slack/reply-options.js +150 -0
  44. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  45. package/dist/channels/slack/slack-channel.js +8 -4
  46. package/dist/channels/slack/stream.d.ts +22 -10
  47. package/dist/channels/slack/stream.d.ts.map +1 -1
  48. package/dist/channels/slack/stream.js +9 -16
  49. package/dist/channels/slack/tool-cards.d.ts +22 -0
  50. package/dist/channels/slack/tool-cards.d.ts.map +1 -0
  51. package/dist/channels/slack/tool-cards.js +178 -0
  52. package/dist/channels/slack/types.d.ts +154 -7
  53. package/dist/channels/slack/types.d.ts.map +1 -1
  54. package/dist/docs/404.html +2 -2
  55. package/dist/docs/ab.html +6 -6
  56. package/dist/docs/ab.md +1 -1
  57. package/dist/docs/assets/{ab.md.DJo5r4R-.js → ab.md.mlVgqvSk.js} +1 -1
  58. package/dist/docs/assets/{app.B3rWNYE1.js → app.DZ1e0Ycq.js} +1 -1
  59. package/dist/docs/assets/{building-with-agents.md.DI4mEzlt.js → building-with-agents.md.CUSWxlP_.js} +2 -2
  60. package/dist/docs/assets/chunks/@localSearchIndexroot.j70vvPL4.js +1 -0
  61. package/dist/docs/assets/chunks/{VPLocalSearchBox.C1lhqJJR.js → VPLocalSearchBox.l8omwc6D.js} +1 -1
  62. package/dist/docs/assets/chunks/{theme.B40_SXuv.js → theme.JVcD6gel.js} +2 -2
  63. package/dist/docs/assets/{evals.md.lfJoEVc8.js → evals.md.CPzDAwoH.js} +1 -1
  64. package/dist/docs/assets/{guides_github.md.Cnh2mL4a.js → guides_github.md.BtPr9GaP.js} +1 -1
  65. package/dist/docs/assets/{guides_mcp-oauth.md.CN-6YmTJ.js → guides_mcp-oauth.md.Dp6cDP7f.js} +1 -1
  66. package/dist/docs/assets/{guides_opentelemetry.md.bmPmkvJu.js → guides_opentelemetry.md.BVTXDCRg.js} +2 -2
  67. package/dist/docs/assets/{guides_slack.md.VDXQV3ja.js → guides_slack.md.9oHPye9o.js} +19 -3
  68. package/dist/docs/assets/{guides_slack.md.VDXQV3ja.lean.js → guides_slack.md.9oHPye9o.lean.js} +1 -1
  69. package/dist/docs/assets/hillclimbing.md.CpTGTCle.js +4 -0
  70. package/dist/docs/assets/{index.md.CVeRUOeZ.js → index.md.Bb4k8kUm.js} +1 -1
  71. package/dist/docs/assets/{quickstart.md.Nj_LjW_a.js → quickstart.md.DdQOF7Y8.js} +1 -1
  72. package/dist/docs/assets/{reference_cli.md.RyZf5OTE.js → reference_cli.md.DfoeyvL0.js} +4 -4
  73. package/dist/docs/assets/{reference_cli.md.RyZf5OTE.lean.js → reference_cli.md.DfoeyvL0.lean.js} +1 -1
  74. package/dist/docs/assets/{reference_connections.md.DxldvyIB.js → reference_connections.md.BiGoBAk2.js} +1 -1
  75. package/dist/docs/assets/{reference_http-api.md.5zOAbV86.js → reference_http-api.md.BEJx9XVj.js} +1 -1
  76. package/dist/docs/assets/{reference_tools.md.B84gw9Ii.js → reference_tools.md.CvAHsdSp.js} +10 -2
  77. package/dist/docs/assets/{reference_tools.md.B84gw9Ii.lean.js → reference_tools.md.CvAHsdSp.lean.js} +1 -1
  78. package/dist/docs/assets/scaffolding-agents.md.em43xlY1.js +1 -0
  79. package/dist/docs/assets/skills_ab.md.CsFNatVx.js +26 -0
  80. package/dist/docs/assets/skills_ab.md.CsFNatVx.lean.js +1 -0
  81. package/dist/docs/assets/skills_create-agent.md.BVoWPcan.js +8 -0
  82. package/dist/docs/assets/skills_create-agent.md.BVoWPcan.lean.js +1 -0
  83. package/dist/docs/assets/skills_debug.md.CDbPhHfg.js +1 -0
  84. package/dist/docs/assets/skills_debug.md.CDbPhHfg.lean.js +1 -0
  85. package/dist/docs/assets/skills_evals.md.723kpUmA.js +25 -0
  86. package/dist/docs/assets/skills_evals.md.723kpUmA.lean.js +1 -0
  87. package/dist/docs/assets/skills_framework-map.md.BTi817yv.js +1 -0
  88. package/dist/docs/assets/skills_framework-map.md.BTi817yv.lean.js +1 -0
  89. package/dist/docs/assets/skills_github.md.D0JahM8c.js +16 -0
  90. package/dist/docs/assets/skills_github.md.D0JahM8c.lean.js +1 -0
  91. package/dist/docs/assets/skills_hillclimb.md.B_zJerxA.js +7 -0
  92. package/dist/docs/assets/skills_hillclimb.md.B_zJerxA.lean.js +1 -0
  93. package/dist/docs/assets/skills_index.md.DKwIxzGg.js +1 -0
  94. package/dist/docs/assets/skills_index.md.DKwIxzGg.lean.js +1 -0
  95. package/dist/docs/assets/skills_mcp-auth.md.DGvFP3HE.js +18 -0
  96. package/dist/docs/assets/skills_mcp-auth.md.DGvFP3HE.lean.js +1 -0
  97. package/dist/docs/assets/skills_otel.md.CgiZryR3.js +8 -0
  98. package/dist/docs/assets/skills_otel.md.CgiZryR3.lean.js +1 -0
  99. package/dist/docs/assets/skills_setup-slack.md.BBgx8lUz.js +20 -0
  100. package/dist/docs/assets/skills_setup-slack.md.BBgx8lUz.lean.js +1 -0
  101. package/dist/docs/assets/{troubleshooting.md.DCiPBhYs.js → troubleshooting.md.Cus_YZga.js} +1 -1
  102. package/dist/docs/building-with-agents.html +6 -6
  103. package/dist/docs/building-with-agents.md +14 -11
  104. package/dist/docs/concepts.html +4 -4
  105. package/dist/docs/deployment.html +4 -4
  106. package/dist/docs/design/runtime-abstraction.md +1757 -0
  107. package/dist/docs/evals.html +6 -6
  108. package/dist/docs/evals.md +1 -1
  109. package/dist/docs/guides/agent-to-agent.html +4 -4
  110. package/dist/docs/guides/cloud-runtime.html +4 -4
  111. package/dist/docs/guides/convert-automation.html +4 -4
  112. package/dist/docs/guides/github.html +5 -5
  113. package/dist/docs/guides/github.md +1 -1
  114. package/dist/docs/guides/human-in-the-loop.html +4 -4
  115. package/dist/docs/guides/mcp-oauth.html +5 -5
  116. package/dist/docs/guides/mcp-oauth.md +1 -1
  117. package/dist/docs/guides/opentelemetry.html +7 -7
  118. package/dist/docs/guides/opentelemetry.md +2 -2
  119. package/dist/docs/guides/slack.html +22 -6
  120. package/dist/docs/guides/slack.md +80 -1
  121. package/dist/docs/guides/webhooks.html +5 -5
  122. package/dist/docs/hashmap.json +1 -1
  123. package/dist/docs/hillclimbing.html +6 -6
  124. package/dist/docs/hillclimbing.md +5 -5
  125. package/dist/docs/index.html +6 -6
  126. package/dist/docs/index.md +1 -1
  127. package/dist/docs/llms-full.txt +2830 -37
  128. package/dist/docs/llms.txt +15 -0
  129. package/dist/docs/quickstart.html +5 -5
  130. package/dist/docs/quickstart.md +1 -1
  131. package/dist/docs/reference/agent-config.html +4 -4
  132. package/dist/docs/reference/artifacts.html +4 -4
  133. package/dist/docs/reference/channels.html +4 -4
  134. package/dist/docs/reference/cli.html +7 -7
  135. package/dist/docs/reference/cli.md +1 -7
  136. package/dist/docs/reference/connections.html +6 -6
  137. package/dist/docs/reference/connections.md +1 -1
  138. package/dist/docs/reference/hooks.html +4 -4
  139. package/dist/docs/reference/http-api.html +6 -6
  140. package/dist/docs/reference/http-api.md +1 -0
  141. package/dist/docs/reference/instructions.html +4 -4
  142. package/dist/docs/reference/playground.html +4 -4
  143. package/dist/docs/reference/project-layout.html +4 -4
  144. package/dist/docs/reference/prompt.html +4 -4
  145. package/dist/docs/reference/schedules.html +4 -4
  146. package/dist/docs/reference/sessions.html +4 -4
  147. package/dist/docs/reference/skills.html +4 -4
  148. package/dist/docs/reference/subagents.html +4 -4
  149. package/dist/docs/reference/tools.html +14 -6
  150. package/dist/docs/reference/tools.md +25 -0
  151. package/dist/docs/scaffolding-agents.html +5 -5
  152. package/dist/docs/scaffolding-agents.md +3 -3
  153. package/dist/docs/skills/ab.html +52 -0
  154. package/dist/docs/skills/ab.md +50 -0
  155. package/dist/docs/skills/create-agent.html +34 -0
  156. package/dist/docs/skills/create-agent.md +160 -0
  157. package/dist/docs/skills/debug.html +27 -0
  158. package/dist/docs/skills/debug.md +36 -0
  159. package/dist/docs/skills/evals.html +51 -0
  160. package/dist/docs/skills/evals.md +99 -0
  161. package/dist/docs/skills/framework-map.html +27 -0
  162. package/dist/docs/skills/framework-map.md +95 -0
  163. package/dist/docs/skills/github.html +42 -0
  164. package/dist/docs/skills/github.md +93 -0
  165. package/dist/docs/skills/hillclimb.html +33 -0
  166. package/dist/docs/skills/hillclimb.md +55 -0
  167. package/dist/docs/skills/index.html +27 -0
  168. package/dist/docs/skills/index.md +21 -0
  169. package/dist/docs/skills/mcp-auth.html +44 -0
  170. package/dist/docs/skills/mcp-auth.md +76 -0
  171. package/dist/docs/skills/otel.html +34 -0
  172. package/dist/docs/skills/otel.md +48 -0
  173. package/dist/docs/skills/setup-slack.html +46 -0
  174. package/dist/docs/skills/setup-slack.md +141 -0
  175. package/dist/docs/storage.html +4 -4
  176. package/dist/docs/templates/agentic-owners.html +4 -4
  177. package/dist/docs/templates/agents-md.html +4 -4
  178. package/dist/docs/templates/code-wiki.html +4 -4
  179. package/dist/docs/templates/demo.html +4 -4
  180. package/dist/docs/templates/pr-autofixer.html +4 -4
  181. package/dist/docs/templates/security-help.html +4 -4
  182. package/dist/docs/templates/security-reviewer.html +4 -4
  183. package/dist/docs/templates/triage.html +4 -4
  184. package/dist/docs/troubleshooting.html +5 -5
  185. package/dist/docs/troubleshooting.md +1 -1
  186. package/dist/files-backends/cursor-hosted.d.ts +9 -2
  187. package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
  188. package/dist/files-backends/cursor-hosted.js +9 -11
  189. package/dist/index.d.ts +1 -0
  190. package/dist/index.d.ts.map +1 -1
  191. package/dist/index.js +1 -0
  192. package/dist/internal/as-of.d.ts +19 -0
  193. package/dist/internal/as-of.d.ts.map +1 -0
  194. package/dist/internal/as-of.js +82 -0
  195. package/dist/internal/cli-deploy.d.ts +2 -1
  196. package/dist/internal/cli-deploy.d.ts.map +1 -1
  197. package/dist/internal/cli-deploy.js +102 -7
  198. package/dist/internal/conversation-mirror.d.ts.map +1 -1
  199. package/dist/internal/conversation-mirror.js +3 -4
  200. package/dist/internal/cursor/hosted-store-secrets.d.ts +15 -0
  201. package/dist/internal/cursor/hosted-store-secrets.d.ts.map +1 -0
  202. package/dist/internal/cursor/hosted-store-secrets.js +48 -0
  203. package/dist/internal/cursor-event-relay.d.ts.map +1 -1
  204. package/dist/internal/cursor-event-relay.js +5 -6
  205. package/dist/internal/deploy-client.d.ts +6 -6
  206. package/dist/internal/deploy-client.js +7 -7
  207. package/dist/internal/discovery.d.ts.map +1 -1
  208. package/dist/internal/discovery.js +11 -1
  209. package/dist/internal/framework-file-storage.d.ts +5 -4
  210. package/dist/internal/framework-file-storage.d.ts.map +1 -1
  211. package/dist/internal/framework-file-storage.js +6 -4
  212. package/dist/internal/framework-storage-selection.d.ts +13 -11
  213. package/dist/internal/framework-storage-selection.d.ts.map +1 -1
  214. package/dist/internal/framework-storage-selection.js +28 -23
  215. package/dist/internal/hosted-admission-adapter.d.ts +28 -0
  216. package/dist/internal/hosted-admission-adapter.d.ts.map +1 -0
  217. package/dist/internal/hosted-admission-adapter.js +7 -0
  218. package/dist/internal/hosted-delivery-protocol.d.ts +6 -1
  219. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
  220. package/dist/internal/hosted-delivery-protocol.js +1 -1
  221. package/dist/internal/hosted-delivery.d.ts +15 -1
  222. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  223. package/dist/internal/hosted-delivery.js +47 -21
  224. package/dist/internal/hosted-execution-diag.d.ts +11 -0
  225. package/dist/internal/hosted-execution-diag.d.ts.map +1 -1
  226. package/dist/internal/hosted-execution-diag.js +39 -2
  227. package/dist/internal/http-channel.d.ts.map +1 -1
  228. package/dist/internal/http-channel.js +4 -1
  229. package/dist/internal/server.d.ts +3 -0
  230. package/dist/internal/server.d.ts.map +1 -1
  231. package/dist/internal/server.js +82 -19
  232. package/dist/internal/session-engine.d.ts.map +1 -1
  233. package/dist/internal/session-engine.js +24 -4
  234. package/dist/internal/session-run-log.d.ts +120 -0
  235. package/dist/internal/session-run-log.d.ts.map +1 -0
  236. package/dist/internal/session-run-log.js +358 -0
  237. package/dist/internal/tool-policy.d.ts +20 -8
  238. package/dist/internal/tool-policy.d.ts.map +1 -1
  239. package/dist/internal/tool-policy.js +11 -0
  240. package/dist/playground/assets/index-BszoQDc6.css +1 -0
  241. package/dist/playground/assets/index-DVs98vPL.js +69 -0
  242. package/dist/playground/index.html +2 -2
  243. package/dist/storage-backends/cursor-hosted-v2.d.ts +83 -0
  244. package/dist/storage-backends/cursor-hosted-v2.d.ts.map +1 -0
  245. package/dist/storage-backends/cursor-hosted-v2.js +164 -0
  246. package/dist/storage-backends/cursor-hosted.d.ts +6 -0
  247. package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
  248. package/dist/storage-backends/cursor-hosted.js +6 -1
  249. package/dist/storage-protocol.d.ts +8 -0
  250. package/dist/storage-protocol.d.ts.map +1 -1
  251. package/dist/storage-protocol.js +8 -0
  252. package/dist/tools.d.ts +12 -2
  253. package/dist/tools.d.ts.map +1 -1
  254. package/dist/types.d.ts +30 -0
  255. package/dist/types.d.ts.map +1 -1
  256. package/docs/README.md +1 -1
  257. package/docs/ab.md +1 -1
  258. package/docs/building-with-agents.md +14 -11
  259. package/docs/design/runtime-abstraction.md +1757 -0
  260. package/docs/evals.md +1 -1
  261. package/docs/guides/github.md +1 -1
  262. package/docs/guides/mcp-oauth.md +1 -1
  263. package/docs/guides/opentelemetry.md +2 -2
  264. package/docs/guides/slack.md +80 -1
  265. package/docs/hillclimbing.md +5 -5
  266. package/docs/quickstart.md +1 -1
  267. package/docs/reference/cli.md +1 -7
  268. package/docs/reference/connections.md +1 -1
  269. package/docs/reference/http-api.md +1 -0
  270. package/docs/reference/tools.md +25 -0
  271. package/docs/scaffolding-agents.md +3 -3
  272. package/docs/skills/index.md +26 -0
  273. package/docs/troubleshooting.md +1 -1
  274. package/package.json +1 -1
  275. package/src/bin/agent-serve.ts +6 -7
  276. package/src/channels/github/defaults.ts +36 -3
  277. package/src/channels/github/github-channel.ts +17 -0
  278. package/src/channels/github/progress.ts +7 -0
  279. package/src/channels/origin/origin-channel.ts +74 -10
  280. package/src/channels/slack/api.ts +35 -17
  281. package/src/channels/slack/constants.ts +6 -0
  282. package/src/channels/slack/defaults.ts +253 -144
  283. package/src/channels/slack/dispatch.ts +10 -1
  284. package/src/channels/slack/inbound.ts +17 -0
  285. package/src/channels/slack/index.ts +1 -0
  286. package/src/channels/slack/live-delivery.ts +135 -22
  287. package/src/channels/slack/progress-delivery.ts +133 -0
  288. package/src/channels/slack/reasoning-card.ts +140 -0
  289. package/src/channels/slack/redact.ts +6 -0
  290. package/src/channels/slack/reply-options.ts +229 -0
  291. package/src/channels/slack/slack-channel.ts +7 -2
  292. package/src/channels/slack/stream.ts +31 -24
  293. package/src/channels/slack/tool-cards.ts +221 -0
  294. package/src/channels/slack/types.ts +168 -7
  295. package/src/files-backends/cursor-hosted.ts +18 -7
  296. package/src/index.ts +4 -0
  297. package/src/internal/as-of.ts +107 -0
  298. package/src/internal/cli-deploy.ts +130 -10
  299. package/src/internal/conversation-mirror.ts +3 -8
  300. package/src/internal/cursor/hosted-store-secrets.ts +72 -0
  301. package/src/internal/cursor-event-relay.ts +5 -6
  302. package/src/internal/deploy-client.ts +10 -10
  303. package/src/internal/discovery.ts +9 -1
  304. package/src/internal/framework-file-storage.ts +6 -4
  305. package/src/internal/framework-storage-selection.ts +28 -25
  306. package/src/internal/hosted-admission-adapter.ts +42 -0
  307. package/src/internal/hosted-delivery-protocol.ts +7 -2
  308. package/src/internal/hosted-delivery.ts +88 -36
  309. package/src/internal/hosted-execution-diag.ts +45 -0
  310. package/src/internal/http-channel.ts +8 -0
  311. package/src/internal/server.ts +100 -2
  312. package/src/internal/session-engine.ts +32 -1
  313. package/src/internal/session-run-log.ts +579 -0
  314. package/src/internal/tool-policy.ts +31 -9
  315. package/src/storage-backends/cursor-hosted-v2.ts +219 -0
  316. package/src/storage-backends/cursor-hosted.ts +6 -1
  317. package/src/storage-protocol.ts +10 -0
  318. package/src/tools.ts +12 -2
  319. package/src/types.ts +30 -0
  320. package/dist/docs/assets/chunks/@localSearchIndexroot.BU9nHdnQ.js +0 -1
  321. package/dist/docs/assets/hillclimbing.md.DhESf3OO.js +0 -4
  322. package/dist/docs/assets/scaffolding-agents.md.D7UUkWw0.js +0 -1
  323. package/dist/playground/assets/index-DrkI6y5O.js +0 -88
  324. package/dist/playground/assets/index-DzNGwm7q.css +0 -1
  325. /package/dist/docs/assets/{ab.md.DJo5r4R-.lean.js → ab.md.mlVgqvSk.lean.js} +0 -0
  326. /package/dist/docs/assets/{building-with-agents.md.DI4mEzlt.lean.js → building-with-agents.md.CUSWxlP_.lean.js} +0 -0
  327. /package/dist/docs/assets/{evals.md.lfJoEVc8.lean.js → evals.md.CPzDAwoH.lean.js} +0 -0
  328. /package/dist/docs/assets/{guides_github.md.Cnh2mL4a.lean.js → guides_github.md.BtPr9GaP.lean.js} +0 -0
  329. /package/dist/docs/assets/{guides_mcp-oauth.md.CN-6YmTJ.lean.js → guides_mcp-oauth.md.Dp6cDP7f.lean.js} +0 -0
  330. /package/dist/docs/assets/{guides_opentelemetry.md.bmPmkvJu.lean.js → guides_opentelemetry.md.BVTXDCRg.lean.js} +0 -0
  331. /package/dist/docs/assets/{hillclimbing.md.DhESf3OO.lean.js → hillclimbing.md.CpTGTCle.lean.js} +0 -0
  332. /package/dist/docs/assets/{index.md.CVeRUOeZ.lean.js → index.md.Bb4k8kUm.lean.js} +0 -0
  333. /package/dist/docs/assets/{quickstart.md.Nj_LjW_a.lean.js → quickstart.md.DdQOF7Y8.lean.js} +0 -0
  334. /package/dist/docs/assets/{reference_connections.md.DxldvyIB.lean.js → reference_connections.md.BiGoBAk2.lean.js} +0 -0
  335. /package/dist/docs/assets/{reference_http-api.md.5zOAbV86.lean.js → reference_http-api.md.BEJx9XVj.lean.js} +0 -0
  336. /package/dist/docs/assets/{scaffolding-agents.md.D7UUkWw0.lean.js → scaffolding-agents.md.em43xlY1.lean.js} +0 -0
  337. /package/dist/docs/assets/{troubleshooting.md.DCiPBhYs.lean.js → troubleshooting.md.Cus_YZga.lean.js} +0 -0
@@ -61,8 +61,14 @@ export interface SlackChannelState {
61
61
  streamTs: string | null;
62
62
  /** Channel id used when the stream was started. */
63
63
  streamChannelId?: string | null;
64
- /** Last cumulative text sent via appendStream (for incremental append). */
64
+ /** Last assistant text delivered to the thread (stream or postMessage). */
65
65
  lastPostedText?: string | null;
66
+ /**
67
+ * Text of the current assistant block already written into the open stream.
68
+ * The harness restarts its cumulative text at every tool boundary, so the
69
+ * append delta cannot be measured against {@link lastPostedText}.
70
+ */
71
+ streamBlockText?: string | null;
66
72
  /**
67
73
  * Slack message ts of the agent's last delivered reply in this thread.
68
74
  * Warm turns use this as the `<slack_thread_delta>` watermark.
@@ -73,13 +79,160 @@ export interface SlackChannelState {
73
79
  * for the rest of the turn.
74
80
  */
75
81
  streamingUnavailable?: boolean;
82
+ /** The open stream hit Slack's size cap; appends stop until it closes. */
83
+ streamFull?: boolean;
84
+ /** Editable progress message ts when `chat.startStream` is unavailable. */
85
+ progressTs: string | null;
76
86
  /**
77
87
  * Message ts of approval cards keyed by tool call id (for
78
88
  * replacing Approve/Deny buttons after a decision).
79
89
  */
80
90
  approvalMessageByCallId?: Record<string, string>;
91
+ /** `reply.reasoningCard` bookkeeping for the current turn. */
92
+ reasoningCard?: ReasoningCardState;
93
+ /** `reply.toolCards` per-tool tallies for the current turn, keyed by tool name. */
94
+ toolCardCounts?: Record<string, ToolCardCount>;
81
95
  }
82
96
 
97
+ /**
98
+ * Slack appends a task card's `details` across updates, so the reasoning
99
+ * card is fed deltas: `blockSent` is how much of the current reasoning block
100
+ * is already on Slack, `pending` is buffered text awaiting a flush.
101
+ */
102
+ export interface ReasoningCardState {
103
+ status: "in_progress" | "complete" | null;
104
+ blockSent: number | null;
105
+ pending: string;
106
+ lastFlushMs: number | null;
107
+ chars: number;
108
+ }
109
+
110
+ /**
111
+ * `details` / `output` count the lines already on the card, so a later
112
+ * batch can start on a new line (Slack appends updates verbatim).
113
+ */
114
+ export interface ToolCardCount {
115
+ started: number;
116
+ done: number;
117
+ errors: number;
118
+ details?: number;
119
+ output?: number;
120
+ }
121
+
122
+ /** A tool call as the model requested it (`actions.requested`). */
123
+ export interface SlackToolCall {
124
+ callId: string;
125
+ toolName: string;
126
+ args?: unknown;
127
+ }
128
+
129
+ /** A finished tool call (`action.result`). */
130
+ export interface SlackToolResult {
131
+ callId: string;
132
+ toolName: string;
133
+ output?: unknown;
134
+ isError: boolean;
135
+ }
136
+
137
+ /**
138
+ * What the status chip under the thread shows while a turn runs. Slack caps
139
+ * each line at 50 characters. While a `chat.startStream` is open Slack shows
140
+ * its own generic "is working…" instead, so in `"stream"` mode these lines
141
+ * are only visible until the first chunk goes out.
142
+ */
143
+ export interface SlackStatusOptions {
144
+ /** First line of each reasoning block, throttled. Defaults to `true`. */
145
+ reasoning?: boolean;
146
+ /**
147
+ * Tool calls as they start: `"Running grep, glob…"` (tool names through
148
+ * {@link SlackChannelOptions.toolLabels}), or your own line. Defaults to
149
+ * `true`.
150
+ */
151
+ tools?: boolean | ((calls: readonly SlackToolCall[]) => string);
152
+ /**
153
+ * Rotation Slack cycles through while nothing more specific is known
154
+ * (turn start, long silent stretches). Up to 5 entries. Defaults to
155
+ * Thinking… / Working on it… / Almost there….
156
+ */
157
+ idle?: readonly string[];
158
+ }
159
+
160
+ export type SlackToolCardGroup = "per-call" | "per-tool";
161
+
162
+ /**
163
+ * Task cards for tool calls inside the streamed reply. Slack appends each
164
+ * update's `details` / `output` to the card, so the callbacks return the
165
+ * text to add, not the full card.
166
+ */
167
+ export interface SlackToolCardOptions {
168
+ /**
169
+ * `"per-tool"` (default) keeps one card per tool name and counts calls in
170
+ * the title (`grep ×3`). `"per-call"` shows one card per call.
171
+ */
172
+ group?: SlackToolCardGroup;
173
+ /**
174
+ * `true` (default): cards expand to show one line per call, the way the
175
+ * reasoning card does. `false`: cards are their titles only.
176
+ */
177
+ collapsible?: boolean;
178
+ /**
179
+ * The line a collapsible card shows for a call. Defaults to what the
180
+ * playground shows in that tool's header: the grep pattern, the file
181
+ * path, the shell command.
182
+ */
183
+ details?: (call: SlackToolCall) => string | undefined;
184
+ /** Text appended to a collapsible card when a call finishes. */
185
+ output?: (result: SlackToolResult) => string | undefined;
186
+ }
187
+
188
+ /**
189
+ * One task card that receives the model's reasoning as it streams. Its
190
+ * status is `in_progress` while the model thinks and `complete` once the
191
+ * answer text starts.
192
+ */
193
+ export interface SlackReasoningCardOptions {
194
+ /** Card title. Defaults to `"Thinking"`. */
195
+ title?: string;
196
+ /**
197
+ * Stop appending after this many characters. Defaults to 1500: Slack caps
198
+ * a streamed message (answer text plus cards) near 12k, so a long card
199
+ * shortens the answer that fits before the reply spills into a second
200
+ * message.
201
+ */
202
+ maxChars?: number;
203
+ }
204
+
205
+ /**
206
+ * How the reply reaches the thread while the turn runs.
207
+ *
208
+ * - `"post"` (default): live feedback is the status chip; the answer lands
209
+ * as one message when the turn finishes.
210
+ * - `"stream"`: the answer text streams into one message as it is written.
211
+ * Slack replaces the status chip with its generic "is working…" for the
212
+ * duration, so live feedback inside the message comes from cards.
213
+ */
214
+ export type SlackReplyOptions =
215
+ | {
216
+ mode: "post";
217
+ status?: SlackStatusOptions;
218
+ }
219
+ | {
220
+ mode: "stream";
221
+ status?: SlackStatusOptions;
222
+ /** Defaults to `false`. `true` is `{ group: "per-tool" }`. */
223
+ toolCards?: boolean | SlackToolCardOptions;
224
+ /** Defaults to `false`. */
225
+ reasoningCard?: boolean | SlackReasoningCardOptions;
226
+ };
227
+
228
+ /**
229
+ * Human labels for tool names, shared by the status chip and the cards.
230
+ * A function may return `undefined` to keep the raw tool name.
231
+ */
232
+ export type SlackToolLabels =
233
+ | Readonly<Record<string, string>>
234
+ | ((toolName: string) => string | undefined);
235
+
83
236
  export interface SlackAuthor {
84
237
  /** Slack user id. Empty string for bot posts with no `user` field. */
85
238
  userId: string;
@@ -494,13 +647,21 @@ export interface SlackChannelOptions {
494
647
  */
495
648
  deliverDefaults?: boolean;
496
649
  /**
497
- * Stream assistant text while the turn runs via `chat.startStream` /
498
- * `appendStream` / `stopStream` (defaults to `true`).
650
+ * How the reply reaches the thread: status chip + one message at the end
651
+ * (`"post"`, default), or a live-streamed message with optional tool and
652
+ * reasoning cards (`"stream"`). See {@link SlackReplyOptions}.
653
+ */
654
+ reply?: SlackReplyOptions;
655
+ /** Human labels for tool names in the status chip and cards. */
656
+ toolLabels?: SlackToolLabels;
657
+ /**
658
+ * @deprecated Use `reply: { mode: "stream" }` / `reply: { mode: "post" }`.
659
+ * Ignored when `reply` is set.
499
660
  */
500
661
  streaming?: boolean;
501
662
  /**
502
- * Show task-style thinking steps for tool calls (stream chunks or status).
503
- * Defaults to `true`.
663
+ * @deprecated Use `reply: { mode: "stream", toolCards: true }`. Ignored
664
+ * when `reply` is set.
504
665
  */
505
666
  thinkingSteps?: boolean;
506
667
  /**
@@ -548,8 +709,8 @@ export interface SlackChannelOptions {
548
709
  suggestedPrompts?: SlackSuggestedPrompt[];
549
710
  suggestedPromptsTitle?: string;
550
711
  /**
551
- * Rotating `assistant.threads.setStatus` loading lines (Slack caps each
552
- * entry at 50 chars). Defaults to Thinking… / Working on it… / Almost there….
712
+ * @deprecated Use `reply: { mode, status: { idle: [...] } }`. Ignored when
713
+ * `reply` is set.
553
714
  */
554
715
  loadingMessages?: string[];
555
716
  /**
@@ -51,6 +51,10 @@ import {
51
51
  type FileSinkEntry,
52
52
  type FileSinkPutResult,
53
53
  } from "../files.js";
54
+ import {
55
+ resolveDeploymentStoreSourceIdSync,
56
+ resolveFrameworkStoreSourceIdSync,
57
+ } from "../internal/cursor/hosted-store-secrets.js";
54
58
  import { createAgentStorePresignedUrlValidatorForBackend } from "./agent-store-presigned-url.js";
55
59
 
56
60
  /**
@@ -76,8 +80,9 @@ export const AGENT_SERVE_STORE_SOURCE_ID_ENV_VAR =
76
80
  * user-level store above. The user store carries author-facing bytes
77
81
  * (`ctx.host.files`, skills, memory, artifacts) and is browsable and
78
82
  * mountable; the framework store carries engine-owned session state —
79
- * session records, event transcripts, continuation index, and the SDK
80
- * conversation mirror — and is never exposed to authors or models.
83
+ * session records, event transcripts, hosted-execution run logs,
84
+ * continuation index, and the SDK conversation mirror — and is never
85
+ * exposed to authors or models.
81
86
  * Provisioned by the v2 deploy pipeline alongside the user store; v1
82
87
  * deployments have only the user store.
83
88
  */
@@ -110,8 +115,7 @@ const MAX_LIST_WALK_PAGES = 1_000;
110
115
  export function isCursorHostedFilesAvailable(
111
116
  env: NodeJS.ProcessEnv = process.env
112
117
  ): boolean {
113
- const sourceId = env[AGENT_SERVE_STORE_SOURCE_ID_ENV_VAR]?.trim();
114
- return sourceId !== undefined && sourceId !== "";
118
+ return resolveDeploymentStoreSourceIdSync(env) !== undefined;
115
119
  }
116
120
 
117
121
  /**
@@ -124,8 +128,7 @@ export function isCursorHostedFilesAvailable(
124
128
  export function cursorFrameworkStoreSourceId(
125
129
  env: NodeJS.ProcessEnv = process.env
126
130
  ): string | undefined {
127
- const sourceId = env[AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID_ENV_VAR]?.trim();
128
- return sourceId === undefined || sourceId === "" ? undefined : sourceId;
131
+ return resolveFrameworkStoreSourceIdSync(env);
129
132
  }
130
133
 
131
134
  /**
@@ -163,6 +166,12 @@ export interface CursorHostedFilesOptions {
163
166
  resolveApiKey?: () => string | undefined;
164
167
  /** File store to address (default: `AGENT_SERVE_STORE_SOURCE_ID`). */
165
168
  storeSourceId?: string;
169
+ /**
170
+ * Lazy store source id, re-resolved on every call and preferred over
171
+ * {@link storeSourceId} — freeze bind drops ids into `/run/cursor/secrets`
172
+ * after serve start without restarting July.
173
+ */
174
+ resolveStoreSourceId?: () => string | undefined;
166
175
  /** Test seam; defaults to global fetch. */
167
176
  fetch?: typeof fetch;
168
177
  }
@@ -649,7 +658,9 @@ function fetchImpl(options: CursorHostedFilesOptions): typeof fetch {
649
658
  */
650
659
  function resolveStoreSourceId(options: CursorHostedFilesOptions): string {
651
660
  const id = (
652
- options.storeSourceId ?? process.env[AGENT_SERVE_STORE_SOURCE_ID_ENV_VAR]
661
+ options.resolveStoreSourceId?.() ??
662
+ options.storeSourceId ??
663
+ resolveDeploymentStoreSourceIdSync(process.env)
653
664
  )?.trim();
654
665
  if (id === undefined || id === "") {
655
666
  throw new Error(
package/src/index.ts CHANGED
@@ -79,6 +79,10 @@ export {
79
79
  V2EngineError,
80
80
  } from "./continuation.js";
81
81
  export { defineHook } from "./hooks.js";
82
+ export {
83
+ InvalidAsOfError,
84
+ VacuousTimeArgsError,
85
+ } from "./internal/as-of.js";
82
86
  export type { LoadAgentProjectOptions } from "./internal/discovery.js";
83
87
  export {
84
88
  formatDiagnostics,
@@ -0,0 +1,107 @@
1
+ const TIMEZONE_SUFFIX = /(?:Z|[+-]\d{2}:?\d{2})$/i;
2
+
3
+ export class InvalidAsOfError extends Error {
4
+ constructor(value: string) {
5
+ super(
6
+ `asOf must be an ISO-8601 instant with a timezone (e.g. ` +
7
+ `2026-08-31T12:00:00Z); received ${JSON.stringify(value)}.`
8
+ );
9
+ this.name = "InvalidAsOfError";
10
+ }
11
+ }
12
+
13
+ function parseInstant(value: string): Date | undefined {
14
+ const trimmed = value.trim();
15
+ if (trimmed === "" || !TIMEZONE_SUFFIX.test(trimmed)) {
16
+ return undefined;
17
+ }
18
+ const instant = new Date(trimmed);
19
+ return Number.isNaN(instant.getTime()) ? undefined : instant;
20
+ }
21
+
22
+ export function normalizeAsOf(value: string | undefined): string | undefined {
23
+ if (value === undefined) {
24
+ return undefined;
25
+ }
26
+ const instant = parseInstant(value);
27
+ if (instant === undefined) {
28
+ throw new InvalidAsOfError(value);
29
+ }
30
+ return instant.toISOString();
31
+ }
32
+
33
+ export function sessionClock(asOf: string | undefined): () => Date {
34
+ if (asOf === undefined) {
35
+ return () => new Date();
36
+ }
37
+ const frozen = new Date(asOf).getTime();
38
+ return () => new Date(frozen);
39
+ }
40
+
41
+ export class VacuousTimeArgsError extends Error {
42
+ constructor(toolName: string, missing: readonly string[]) {
43
+ super(
44
+ `Tool "${toolName}" declares timeArgs ` +
45
+ `${JSON.stringify(missing)} that its input schema does not define, ` +
46
+ `so bounding would silently check nothing. Make the declaration ` +
47
+ `match the schema's property names.`
48
+ );
49
+ this.name = "VacuousTimeArgsError";
50
+ }
51
+ }
52
+
53
+ export function assertTimeArgs(
54
+ tools: readonly {
55
+ name: string;
56
+ definition: { timeArgs?: readonly string[] };
57
+ inputSchema?: { properties?: Record<string, unknown> };
58
+ }[],
59
+ asOf: string | undefined
60
+ ): void {
61
+ if (asOf === undefined) {
62
+ return;
63
+ }
64
+ for (const tool of tools) {
65
+ const declared = tool.definition.timeArgs;
66
+ if (declared === undefined || declared.length === 0) {
67
+ continue;
68
+ }
69
+ const properties = tool.inputSchema?.properties ?? {};
70
+ const missing = declared.filter((name) => !(name in properties));
71
+ if (missing.length > 0) {
72
+ throw new VacuousTimeArgsError(tool.name, missing);
73
+ }
74
+ }
75
+ }
76
+
77
+ export function timeArgViolation(
78
+ input: unknown,
79
+ timeArgs: readonly string[],
80
+ asOf: string
81
+ ): string | undefined {
82
+ const record =
83
+ typeof input === "object" && input !== null
84
+ ? (input as Record<string, unknown>)
85
+ : {};
86
+ const frozen = new Date(asOf).getTime();
87
+ for (const name of timeArgs) {
88
+ const value = record[name];
89
+ const instant = typeof value === "string" ? parseInstant(value) : undefined;
90
+ if (instant === undefined) {
91
+ return (
92
+ `Time argument "${name}" must be an absolute ISO-8601 instant with ` +
93
+ `a timezone (e.g. ${asOf}); received ${JSON.stringify(value)}. This ` +
94
+ `session reads the world as of ${asOf} — supply absolute bounds at ` +
95
+ `or before that instant and retry.`
96
+ );
97
+ }
98
+ if (instant.getTime() > frozen) {
99
+ return (
100
+ `Time argument "${name}" (${JSON.stringify(value)}) is later than ` +
101
+ `the instant this session reads the world as of (${asOf}). Supply ` +
102
+ `bounds at or before that instant and retry.`
103
+ );
104
+ }
105
+ }
106
+ return undefined;
107
+ }
@@ -66,6 +66,8 @@ import { stderrPalette } from "./terminal-style.js";
66
66
 
67
67
  const DEFAULT_POLL_INTERVAL_MS = 3_000;
68
68
  const DEFAULT_DEPLOY_TIMEOUT_MS = 10 * 60 * 1000;
69
+ /** `--multi-tenant` HTTP deploy is Anysphere-only (team id 1). */
70
+ const MULTI_TENANT_HTTP_DEPLOY_TEAM_ID = 1;
69
71
 
70
72
  /** One agent directory selected for deploy (single or multi-agent parent). */
71
73
  export type DeployTarget = ChildAgentDir;
@@ -114,7 +116,8 @@ export interface DeployCliOptions {
114
116
  allowDomains?: string[];
115
117
  /**
116
118
  * deploy `--multi-tenant`: add a release to an existing Cursor-managed
117
- * (multi-tenant) product. Cannot create a new multi-tenant application.
119
+ * (multi-tenant) product. Hidden Anysphere-only flag. Cannot create a
120
+ * new multi-tenant application.
118
121
  */
119
122
  multiTenant?: boolean;
120
123
  /** Test seams. */
@@ -297,6 +300,14 @@ export async function cmdDeploy(options: DeployCliOptions): Promise<number> {
297
300
  return ctx;
298
301
  }
299
302
 
303
+ if (
304
+ options.multiTenant === true &&
305
+ ctx.teamId !== MULTI_TENANT_HTTP_DEPLOY_TEAM_ID
306
+ ) {
307
+ ctx.err("--multi-tenant is not available for this team.\n");
308
+ return 1;
309
+ }
310
+
300
311
  const targets = await resolveDeployTargets(options, ctx);
301
312
  if (typeof targets === "number") {
302
313
  return targets;
@@ -947,7 +958,7 @@ async function deployAgentsdkApplication(
947
958
  }
948
959
 
949
960
  /**
950
- * `architecture: "v2"` deploy: POST `/internal/agentkit/deployments` and
961
+ * `architecture: "v2"` deploy: POST `/internal/agentsdk/deployments` and
951
962
  * poll the matching GET. The v2 accept path starts freeze bake; it does
952
963
  * not mint an engine alias or alias token.
953
964
  */
@@ -990,7 +1001,10 @@ async function deployOneAgentsdk(
990
1001
  ...(args.multiTenant ? { multiTenant: true } : {}),
991
1002
  });
992
1003
  } catch (error) {
993
- return renderApiError(error, ctx.err);
1004
+ return renderApiError(error, ctx.err, {
1005
+ multiTenant: args.multiTenant,
1006
+ teamId: ctx.teamId,
1007
+ });
994
1008
  }
995
1009
 
996
1010
  if (ctx.noWait) {
@@ -1301,6 +1315,21 @@ export async function cmdDeploymentStatus(
1301
1315
  if (typeof ctx === "number") {
1302
1316
  return ctx;
1303
1317
  }
1318
+ // Same dispatch as `stop`: v1 409s architecture-v2 slugs, so the v2
1319
+ // GET goes first. A v2 404 (missing slug, or an older backend) falls
1320
+ // through to the v1 agent-serve detail.
1321
+ try {
1322
+ const detail = await ctx.client.getAgentkitDeploy({
1323
+ teamId: ctx.teamId,
1324
+ slug,
1325
+ });
1326
+ renderAgentkitDeploymentStatus(ctx, detail);
1327
+ return 0;
1328
+ } catch (error) {
1329
+ if (!(error instanceof DeployApiError) || error.status !== 404) {
1330
+ return renderApiError(error, ctx.err);
1331
+ }
1332
+ }
1304
1333
  let detail: DeploymentDetail;
1305
1334
  try {
1306
1335
  detail = await ctx.client.getDeployment({ teamId: ctx.teamId, slug });
@@ -1393,6 +1422,40 @@ export async function cmdDeploymentStatus(
1393
1422
  return 0;
1394
1423
  }
1395
1424
 
1425
+ function renderAgentkitDeploymentStatus(
1426
+ ctx: DeployCliContext,
1427
+ detail: AgentkitDeployStatus
1428
+ ): void {
1429
+ if (ctx.json) {
1430
+ ctx.out(`${JSON.stringify(detail, null, 2)}\n`);
1431
+ return;
1432
+ }
1433
+ const lines = [
1434
+ `${detail.slug} (team ${detail.teamId})`,
1435
+ ` status: ${detail.status}`,
1436
+ ` architecture: v2`,
1437
+ ` application: ${detail.applicationId}`,
1438
+ ` release: ${detail.releaseId}`,
1439
+ ` progress: ${detail.progress}`,
1440
+ ];
1441
+ if (detail.statusMessage !== null && detail.statusMessage.trim() !== "") {
1442
+ lines.push(` step: ${detail.statusMessage}`);
1443
+ }
1444
+ if (detail.repositories !== undefined) {
1445
+ lines.push(
1446
+ ` watching: ${
1447
+ detail.repositories.length === 0
1448
+ ? "(nothing)"
1449
+ : detail.repositories.join(", ")
1450
+ }`
1451
+ );
1452
+ }
1453
+ if (detail.lastError !== null && detail.lastError !== undefined) {
1454
+ lines.push(` last error: ${sanitizeCustomerError(detail.lastError)}`);
1455
+ }
1456
+ ctx.out(`${lines.join("\n")}\n`);
1457
+ }
1458
+
1396
1459
  // ============================================================================
1397
1460
  // stop <slug>
1398
1461
  // ============================================================================
@@ -1415,7 +1478,7 @@ export async function cmdStop(
1415
1478
  // deploy). The v2 agentsdk control plane goes first: v1 endpoints refuse
1416
1479
  // `architecture: "v2"` slugs with a 409 rather than a 404, so v1-first
1417
1480
  // could not fall through. A v2 404 (including an older backend without
1418
- // the `/internal/agentkit` mount) falls back to the v1 stop.
1481
+ // the `/internal/agentsdk` mount) falls back to the v1 stop.
1419
1482
  let architecture: "v1" | "v2" = "v2";
1420
1483
  let accepted: StopAccepted | AgentkitStopAccepted;
1421
1484
  try {
@@ -1901,10 +1964,35 @@ async function pollUntil<
1901
1964
  };
1902
1965
 
1903
1966
  for (;;) {
1904
- const detail = await fetchDetail().catch((error: unknown) => {
1967
+ let detail: T;
1968
+ try {
1969
+ detail = await fetchDetail();
1970
+ } catch (error: unknown) {
1971
+ // Capacity / rate-limit on GET is not a bake failure. The v2 accept
1972
+ // already started freeze; keep polling until the wait budget expires.
1973
+ if (
1974
+ isTransientDeployStatusError(error) &&
1975
+ Date.now() - startedAt < ctx.timeoutMs
1976
+ ) {
1977
+ if (!ctx.json) {
1978
+ const elapsed = Math.round((Date.now() - startedAt) / 1000);
1979
+ const label = "Waiting for status (server busy)";
1980
+ if (tty) {
1981
+ ctx.err(`\r\x1b[2K${slug}: ${label} (${elapsed}s)`);
1982
+ sawProgress = true;
1983
+ } else if (label !== lastLabel) {
1984
+ ctx.err(`${slug}: ${label}\n`);
1985
+ }
1986
+ lastLabel = label;
1987
+ }
1988
+ const waitMs = transientDeployStatusWaitMs(error, ctx.pollIntervalMs);
1989
+ const remaining = ctx.timeoutMs - (Date.now() - startedAt);
1990
+ await sleep(Math.max(0, Math.min(waitMs, remaining)));
1991
+ continue;
1992
+ }
1905
1993
  finishProgressLine();
1906
1994
  throw error;
1907
- });
1995
+ }
1908
1996
  report(detail);
1909
1997
  if (terminal.has(detail.status)) {
1910
1998
  finishProgressLine();
@@ -1922,6 +2010,28 @@ async function pollUntil<
1922
2010
  }
1923
2011
  }
1924
2012
 
2013
+ /** Load-shed / rate-limit on status GET — the deploy itself may still be baking. */
2014
+ function isTransientDeployStatusError(error: unknown): error is DeployApiError {
2015
+ return (
2016
+ error instanceof DeployApiError &&
2017
+ (error.status === 503 || error.status === 429)
2018
+ );
2019
+ }
2020
+
2021
+ function transientDeployStatusWaitMs(
2022
+ error: DeployApiError,
2023
+ pollIntervalMs: number
2024
+ ): number {
2025
+ if (
2026
+ error.status === 429 &&
2027
+ error.retryAfterSeconds !== undefined &&
2028
+ error.retryAfterSeconds > 0
2029
+ ) {
2030
+ return Math.max(pollIntervalMs, error.retryAfterSeconds * 1000);
2031
+ }
2032
+ return pollIntervalMs;
2033
+ }
2034
+
1925
2035
  /**
1926
2036
  * Wait until GET 404s (the delete reconciler purged the record). Treats
1927
2037
  * other errors as failures. Throws DeployApiError on timeout.
@@ -2000,16 +2110,26 @@ function deployFailureDetail(lastError: string | null | undefined): string {
2000
2110
  return `: ${sanitizeCustomerError(lastError.trim())}`;
2001
2111
  }
2002
2112
 
2003
- function renderApiError(error: unknown, err: (text: string) => void): number {
2113
+ function renderApiError(
2114
+ error: unknown,
2115
+ err: (text: string) => void,
2116
+ context?: { multiTenant?: boolean; teamId?: number }
2117
+ ): number {
2004
2118
  if (error instanceof DeployApiError) {
2005
2119
  err(`${error.message}\n`);
2006
2120
  if (
2007
2121
  error.status === 409 &&
2008
2122
  error.message.includes("application multiTenant does not match")
2009
2123
  ) {
2010
- err(
2011
- "This slug is a Cursor-managed (multi-tenant) product. Redeploy it with --multi-tenant.\n"
2012
- );
2124
+ if (context?.multiTenant === true) {
2125
+ err(
2126
+ "This slug is a single-tenant application. Redeploy it without --multi-tenant.\n"
2127
+ );
2128
+ } else if (context?.teamId === MULTI_TENANT_HTTP_DEPLOY_TEAM_ID) {
2129
+ err(
2130
+ "This slug is a Cursor-managed (multi-tenant) product. Redeploy it with --multi-tenant.\n"
2131
+ );
2132
+ }
2013
2133
  }
2014
2134
  return 1;
2015
2135
  }
@@ -383,18 +383,13 @@ export function selectConversationMirror(input: {
383
383
  return undefined;
384
384
  }
385
385
  const env = input.env ?? process.env;
386
- const frameworkStoreId = cursorFrameworkStoreSourceId(
387
- env as NodeJS.ProcessEnv
388
- );
389
- if (
390
- env[AGENT_SERVE_GENERATION_ENV_VAR] === undefined ||
391
- frameworkStoreId === undefined
392
- ) {
386
+ if (env[AGENT_SERVE_GENERATION_ENV_VAR] === undefined) {
393
387
  return undefined;
394
388
  }
389
+ const envSnapshot = env as NodeJS.ProcessEnv;
395
390
  return createConversationMirror({
396
391
  sink: cursorHostedFiles({
397
- storeSourceId: frameworkStoreId,
392
+ resolveStoreSourceId: () => cursorFrameworkStoreSourceId(envSnapshot),
398
393
  // Full chain (env → key file → stored login): frozen engines listen
399
394
  // unsigned and bind CURSOR_API_KEY_FILE at task time, after this sink
400
395
  // is constructed.