@cursor/july 0.1.100 → 0.1.102

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 (484) hide show
  1. package/README.md +27 -0
  2. package/dist/bin/agent-serve.js +3 -2
  3. package/dist/channels/deployments/deployments-channel.d.ts +41 -5
  4. package/dist/channels/deployments/deployments-channel.d.ts.map +1 -1
  5. package/dist/channels/deployments/deployments-channel.js +88 -8
  6. package/dist/channels/deployments/types.d.ts +4 -3
  7. package/dist/channels/deployments/types.d.ts.map +1 -1
  8. package/dist/channels/origin/defaults.d.ts +43 -0
  9. package/dist/channels/origin/defaults.d.ts.map +1 -0
  10. package/dist/channels/origin/defaults.js +111 -0
  11. package/dist/channels/origin/index.d.ts +2 -0
  12. package/dist/channels/origin/index.d.ts.map +1 -1
  13. package/dist/channels/origin/index.js +2 -0
  14. package/dist/channels/origin/origin-channel.d.ts +2 -1
  15. package/dist/channels/origin/origin-channel.d.ts.map +1 -1
  16. package/dist/channels/origin/origin-channel.js +24 -3
  17. package/dist/channels/origin/state.d.ts +32 -0
  18. package/dist/channels/origin/state.d.ts.map +1 -0
  19. package/dist/channels/origin/state.js +23 -0
  20. package/dist/channels/origin/types.d.ts +23 -1
  21. package/dist/channels/origin/types.d.ts.map +1 -1
  22. package/dist/channels/slack/api.d.ts +1 -1
  23. package/dist/channels/slack/api.d.ts.map +1 -1
  24. package/dist/channels/slack/api.js +5 -2
  25. package/dist/channels/slack/assistant.d.ts +1 -1
  26. package/dist/channels/slack/assistant.d.ts.map +1 -1
  27. package/dist/channels/slack/code-fences.d.ts +17 -0
  28. package/dist/channels/slack/code-fences.d.ts.map +1 -0
  29. package/dist/channels/slack/code-fences.js +168 -0
  30. package/dist/channels/slack/dispatch.d.ts +3 -2
  31. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  32. package/dist/channels/slack/dispatch.js +28 -8
  33. package/dist/channels/slack/inbound.d.ts +8 -0
  34. package/dist/channels/slack/inbound.d.ts.map +1 -1
  35. package/dist/channels/slack/inbound.js +28 -0
  36. package/dist/channels/slack/index.d.ts +1 -0
  37. package/dist/channels/slack/index.d.ts.map +1 -1
  38. package/dist/channels/slack/index.js +1 -0
  39. package/dist/channels/slack/live-delivery.d.ts.map +1 -1
  40. package/dist/channels/slack/live-delivery.js +11 -4
  41. package/dist/channels/slack/manifest.d.ts.map +1 -1
  42. package/dist/channels/slack/manifest.js +2 -1
  43. package/dist/connections.d.ts +18 -2
  44. package/dist/connections.d.ts.map +1 -1
  45. package/dist/connections.js +18 -2
  46. package/dist/docs/404.html +2 -2
  47. package/dist/docs/ab.html +4 -4
  48. package/dist/docs/assets/{app.DZ1e0Ycq.js → app.CLA03RCz.js} +1 -1
  49. package/dist/docs/assets/chunks/@localSearchIndexroot.FAqdWIXo.js +1 -0
  50. package/dist/docs/assets/chunks/{VPLocalSearchBox.l8omwc6D.js → VPLocalSearchBox.ifxv-cJV.js} +1 -1
  51. package/dist/docs/assets/chunks/{theme.JVcD6gel.js → theme.DWCwM6p-.js} +2 -2
  52. package/dist/docs/assets/concepts.md.rPzW2HZN.js +1 -0
  53. package/dist/docs/assets/guides_cloud-agents.md.DumwWXba.js +9 -0
  54. package/dist/docs/assets/guides_cloud-agents.md.DumwWXba.lean.js +1 -0
  55. package/dist/docs/assets/{guides_cloud-runtime.md.CkYbjnAX.js → guides_cloud-runtime.md.BRirbRAN.js} +1 -1
  56. package/dist/docs/assets/index.md.Kiht7ell.js +5 -0
  57. package/dist/docs/assets/{index.md.Bb4k8kUm.lean.js → index.md.Kiht7ell.lean.js} +1 -1
  58. package/dist/docs/assets/{reference_connections.md.BiGoBAk2.js → reference_connections.md.Di6jJAXF.js} +12 -2
  59. package/dist/docs/assets/{reference_connections.md.BiGoBAk2.lean.js → reference_connections.md.Di6jJAXF.lean.js} +1 -1
  60. package/dist/docs/assets/reference_extensions.md.9WQMZe1l.js +56 -0
  61. package/dist/docs/assets/reference_extensions.md.9WQMZe1l.lean.js +1 -0
  62. package/dist/docs/assets/{reference_http-api.md.BEJx9XVj.js → reference_http-api.md.oySXBO8o.js} +1 -1
  63. package/dist/docs/assets/{reference_project-layout.md.Bv4KOtlB.js → reference_project-layout.md.CA6QP6Lw.js} +2 -2
  64. package/dist/docs/assets/{reference_project-layout.md.Bv4KOtlB.lean.js → reference_project-layout.md.CA6QP6Lw.lean.js} +1 -1
  65. package/dist/docs/assets/{reference_skills.md.BFW9retM.js → reference_skills.md.l2ezAcaN.js} +1 -1
  66. package/dist/docs/assets/{reference_tools.md.CvAHsdSp.js → reference_tools.md.B1up2r9W.js} +1 -1
  67. package/dist/docs/assets/skills_framework-map.md.DDa4MeEW.js +1 -0
  68. package/dist/docs/assets/{skills_framework-map.md.BTi817yv.lean.js → skills_framework-map.md.DDa4MeEW.lean.js} +1 -1
  69. package/dist/docs/building-with-agents.html +4 -4
  70. package/dist/docs/concepts.html +5 -5
  71. package/dist/docs/concepts.md +3 -3
  72. package/dist/docs/deployment.html +4 -4
  73. package/dist/docs/evals.html +4 -4
  74. package/dist/docs/guides/agent-to-agent.html +4 -4
  75. package/dist/docs/guides/cloud-agents.html +35 -0
  76. package/dist/docs/guides/cloud-agents.md +93 -0
  77. package/dist/docs/guides/cloud-runtime.html +6 -6
  78. package/dist/docs/guides/cloud-runtime.md +2 -0
  79. package/dist/docs/guides/convert-automation.html +4 -4
  80. package/dist/docs/guides/github.html +4 -4
  81. package/dist/docs/guides/human-in-the-loop.html +4 -4
  82. package/dist/docs/guides/mcp-oauth.html +4 -4
  83. package/dist/docs/guides/opentelemetry.html +5 -5
  84. package/dist/docs/guides/slack.html +4 -4
  85. package/dist/docs/guides/webhooks.html +4 -4
  86. package/dist/docs/hashmap.json +1 -1
  87. package/dist/docs/hillclimbing.html +4 -4
  88. package/dist/docs/index.html +6 -6
  89. package/dist/docs/index.md +5 -1
  90. package/dist/docs/llms-full.txt +353 -5
  91. package/dist/docs/llms.txt +2 -0
  92. package/dist/docs/quickstart.html +4 -4
  93. package/dist/docs/reference/agent-config.html +4 -4
  94. package/dist/docs/reference/artifacts.html +4 -4
  95. package/dist/docs/reference/channels.html +5 -5
  96. package/dist/docs/reference/cli.html +4 -4
  97. package/dist/docs/reference/connections.html +16 -6
  98. package/dist/docs/reference/connections.md +31 -0
  99. package/dist/docs/reference/extensions.html +82 -0
  100. package/dist/docs/reference/extensions.md +200 -0
  101. package/dist/docs/reference/hooks.html +4 -4
  102. package/dist/docs/reference/http-api.html +6 -6
  103. package/dist/docs/reference/http-api.md +1 -1
  104. package/dist/docs/reference/instructions.html +4 -4
  105. package/dist/docs/reference/playground.html +4 -4
  106. package/dist/docs/reference/project-layout.html +6 -6
  107. package/dist/docs/reference/project-layout.md +3 -0
  108. package/dist/docs/reference/prompt.html +4 -4
  109. package/dist/docs/reference/schedules.html +4 -4
  110. package/dist/docs/reference/sessions.html +4 -4
  111. package/dist/docs/reference/skills.html +6 -6
  112. package/dist/docs/reference/skills.md +2 -0
  113. package/dist/docs/reference/subagents.html +5 -5
  114. package/dist/docs/reference/tools.html +6 -6
  115. package/dist/docs/reference/tools.md +2 -0
  116. package/dist/docs/scaffolding-agents.html +4 -4
  117. package/dist/docs/skills/ab.html +4 -4
  118. package/dist/docs/skills/create-agent.html +4 -4
  119. package/dist/docs/skills/debug.html +4 -4
  120. package/dist/docs/skills/evals.html +4 -4
  121. package/dist/docs/skills/framework-map.html +5 -5
  122. package/dist/docs/skills/framework-map.md +1 -0
  123. package/dist/docs/skills/github.html +4 -4
  124. package/dist/docs/skills/hillclimb.html +4 -4
  125. package/dist/docs/skills/index.html +4 -4
  126. package/dist/docs/skills/mcp-auth.html +4 -4
  127. package/dist/docs/skills/otel.html +4 -4
  128. package/dist/docs/skills/setup-slack.html +4 -4
  129. package/dist/docs/storage.html +4 -4
  130. package/dist/docs/templates/agentic-owners.html +4 -4
  131. package/dist/docs/templates/agents-md.html +4 -4
  132. package/dist/docs/templates/code-wiki.html +4 -4
  133. package/dist/docs/templates/demo.html +4 -4
  134. package/dist/docs/templates/pr-autofixer.html +4 -4
  135. package/dist/docs/templates/security-help.html +4 -4
  136. package/dist/docs/templates/security-reviewer.html +4 -4
  137. package/dist/docs/templates/triage.html +4 -4
  138. package/dist/docs/troubleshooting.html +4 -4
  139. package/dist/extensions/cursor-cloud-agents/extension.d.ts +57 -0
  140. package/dist/extensions/cursor-cloud-agents/extension.d.ts.map +1 -0
  141. package/dist/extensions/cursor-cloud-agents/extension.js +66 -0
  142. package/dist/extensions/cursor-cloud-agents/lib/backend.d.ts +78 -0
  143. package/dist/extensions/cursor-cloud-agents/lib/backend.d.ts.map +1 -0
  144. package/dist/extensions/cursor-cloud-agents/lib/backend.js +286 -0
  145. package/dist/extensions/cursor-cloud-agents/lib/fleet.d.ts +25 -0
  146. package/dist/extensions/cursor-cloud-agents/lib/fleet.d.ts.map +1 -0
  147. package/dist/extensions/cursor-cloud-agents/lib/fleet.js +85 -0
  148. package/dist/extensions/cursor-cloud-agents/lib/inputs.d.ts +5 -0
  149. package/dist/extensions/cursor-cloud-agents/lib/inputs.d.ts.map +1 -0
  150. package/dist/extensions/cursor-cloud-agents/lib/inputs.js +4 -0
  151. package/dist/extensions/cursor-cloud-agents/lib/repos.d.ts +15 -0
  152. package/dist/extensions/cursor-cloud-agents/lib/repos.d.ts.map +1 -0
  153. package/dist/extensions/cursor-cloud-agents/lib/repos.js +55 -0
  154. package/dist/extensions/cursor-cloud-agents/lib/transcript.d.ts +8 -0
  155. package/dist/extensions/cursor-cloud-agents/lib/transcript.d.ts.map +1 -0
  156. package/dist/extensions/cursor-cloud-agents/lib/transcript.js +15 -0
  157. package/dist/extensions/cursor-cloud-agents/skills/handoff.md +41 -0
  158. package/dist/extensions/cursor-cloud-agents/tools/cancel.d.ts +4 -0
  159. package/dist/extensions/cursor-cloud-agents/tools/cancel.d.ts.map +1 -0
  160. package/dist/extensions/cursor-cloud-agents/tools/cancel.js +26 -0
  161. package/dist/extensions/cursor-cloud-agents/tools/dump.d.ts +4 -0
  162. package/dist/extensions/cursor-cloud-agents/tools/dump.d.ts.map +1 -0
  163. package/dist/extensions/cursor-cloud-agents/tools/dump.js +54 -0
  164. package/dist/extensions/cursor-cloud-agents/tools/get.d.ts +4 -0
  165. package/dist/extensions/cursor-cloud-agents/tools/get.d.ts.map +1 -0
  166. package/dist/extensions/cursor-cloud-agents/tools/get.js +25 -0
  167. package/dist/extensions/cursor-cloud-agents/tools/launch.d.ts +4 -0
  168. package/dist/extensions/cursor-cloud-agents/tools/launch.d.ts.map +1 -0
  169. package/dist/extensions/cursor-cloud-agents/tools/launch.js +59 -0
  170. package/dist/extensions/cursor-cloud-agents/tools/list.d.ts +4 -0
  171. package/dist/extensions/cursor-cloud-agents/tools/list.d.ts.map +1 -0
  172. package/dist/extensions/cursor-cloud-agents/tools/list.js +36 -0
  173. package/dist/extensions/cursor-cloud-agents/tools/reply.d.ts +4 -0
  174. package/dist/extensions/cursor-cloud-agents/tools/reply.d.ts.map +1 -0
  175. package/dist/extensions/cursor-cloud-agents/tools/reply.js +35 -0
  176. package/dist/extensions.d.ts +73 -0
  177. package/dist/extensions.d.ts.map +1 -0
  178. package/dist/extensions.js +112 -0
  179. package/dist/files-backends/cursor-hosted.d.ts +0 -8
  180. package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
  181. package/dist/files-backends/cursor-hosted.js +1 -11
  182. package/dist/files.d.ts +5 -1
  183. package/dist/files.d.ts.map +1 -1
  184. package/dist/files.js +22 -18
  185. package/dist/index.d.ts +4 -3
  186. package/dist/index.d.ts.map +1 -1
  187. package/dist/index.js +3 -2
  188. package/dist/internal/advertise-tools.d.ts +4 -1
  189. package/dist/internal/advertise-tools.d.ts.map +1 -1
  190. package/dist/internal/advertise-tools.js +20 -1
  191. package/dist/internal/as-of.d.ts +18 -0
  192. package/dist/internal/as-of.d.ts.map +1 -1
  193. package/dist/internal/as-of.js +131 -0
  194. package/dist/internal/cli-deploy.d.ts.map +1 -1
  195. package/dist/internal/cli-deploy.js +64 -19
  196. package/dist/internal/continuation-identity.d.ts.map +1 -1
  197. package/dist/internal/continuation-identity.js +3 -1
  198. package/dist/internal/conversation-mirror.d.ts.map +1 -1
  199. package/dist/internal/conversation-mirror.js +13 -15
  200. package/dist/internal/cursor/backend-client.d.ts +8 -1
  201. package/dist/internal/cursor/backend-client.d.ts.map +1 -1
  202. package/dist/internal/cursor/backend-client.js +25 -9
  203. package/dist/internal/cursor/hosted-deployment-secrets.d.ts +16 -0
  204. package/dist/internal/cursor/hosted-deployment-secrets.d.ts.map +1 -0
  205. package/dist/internal/cursor/hosted-deployment-secrets.js +61 -0
  206. package/dist/internal/cursor/hosted-store-secrets.d.ts +11 -0
  207. package/dist/internal/cursor/hosted-store-secrets.d.ts.map +1 -1
  208. package/dist/internal/cursor/hosted-store-secrets.js +15 -0
  209. package/dist/internal/cursor-deployment-relay.d.ts +15 -1
  210. package/dist/internal/cursor-deployment-relay.d.ts.map +1 -1
  211. package/dist/internal/cursor-deployment-relay.js +46 -7
  212. package/dist/internal/deploy-client.d.ts +23 -0
  213. package/dist/internal/deploy-client.d.ts.map +1 -1
  214. package/dist/internal/deploy-client.js +54 -12
  215. package/dist/internal/discovery/ab.d.ts +9 -0
  216. package/dist/internal/discovery/ab.d.ts.map +1 -0
  217. package/dist/internal/discovery/ab.js +101 -0
  218. package/dist/internal/discovery/agent-config.d.ts +35 -0
  219. package/dist/internal/discovery/agent-config.d.ts.map +1 -0
  220. package/dist/internal/discovery/agent-config.js +173 -0
  221. package/dist/internal/discovery/agent.d.ts +11 -0
  222. package/dist/internal/discovery/agent.d.ts.map +1 -0
  223. package/dist/internal/discovery/agent.js +306 -0
  224. package/dist/internal/discovery/channels.d.ts +10 -0
  225. package/dist/internal/discovery/channels.d.ts.map +1 -0
  226. package/dist/internal/discovery/channels.js +97 -0
  227. package/dist/internal/discovery/connections.d.ts +17 -0
  228. package/dist/internal/discovery/connections.d.ts.map +1 -0
  229. package/dist/internal/discovery/connections.js +436 -0
  230. package/dist/internal/discovery/context.d.ts +20 -0
  231. package/dist/internal/discovery/context.d.ts.map +1 -0
  232. package/dist/internal/discovery/context.js +30 -0
  233. package/dist/internal/discovery/cursor-plugin.d.ts +25 -0
  234. package/dist/internal/discovery/cursor-plugin.d.ts.map +1 -0
  235. package/dist/internal/discovery/cursor-plugin.js +570 -0
  236. package/dist/internal/discovery/extensions.d.ts +19 -0
  237. package/dist/internal/discovery/extensions.d.ts.map +1 -0
  238. package/dist/internal/discovery/extensions.js +238 -0
  239. package/dist/internal/discovery/fs.d.ts +15 -0
  240. package/dist/internal/discovery/fs.d.ts.map +1 -0
  241. package/dist/internal/discovery/fs.js +115 -0
  242. package/dist/internal/discovery/hooks.d.ts +7 -0
  243. package/dist/internal/discovery/hooks.d.ts.map +1 -0
  244. package/dist/internal/discovery/hooks.js +48 -0
  245. package/dist/internal/discovery/info.d.ts +6 -0
  246. package/dist/internal/discovery/info.d.ts.map +1 -0
  247. package/dist/internal/discovery/info.js +141 -0
  248. package/dist/internal/discovery/instructions.d.ts +7 -0
  249. package/dist/internal/discovery/instructions.d.ts.map +1 -0
  250. package/dist/internal/discovery/instructions.js +95 -0
  251. package/dist/internal/discovery/modules.d.ts +20 -0
  252. package/dist/internal/discovery/modules.d.ts.map +1 -0
  253. package/dist/internal/discovery/modules.js +101 -0
  254. package/dist/internal/discovery/names.d.ts +12 -0
  255. package/dist/internal/discovery/names.d.ts.map +1 -0
  256. package/dist/internal/discovery/names.js +36 -0
  257. package/dist/internal/discovery/project.d.ts +53 -0
  258. package/dist/internal/discovery/project.d.ts.map +1 -0
  259. package/dist/internal/discovery/project.js +239 -0
  260. package/dist/internal/discovery/runtime.d.ts +34 -0
  261. package/dist/internal/discovery/runtime.d.ts.map +1 -0
  262. package/dist/internal/discovery/runtime.js +98 -0
  263. package/dist/internal/discovery/schedules.d.ts +7 -0
  264. package/dist/internal/discovery/schedules.d.ts.map +1 -0
  265. package/dist/internal/discovery/schedules.js +97 -0
  266. package/dist/internal/discovery/seed-files.d.ts +7 -0
  267. package/dist/internal/discovery/seed-files.d.ts.map +1 -0
  268. package/dist/internal/discovery/seed-files.js +41 -0
  269. package/dist/internal/discovery/services.d.ts +17 -0
  270. package/dist/internal/discovery/services.d.ts.map +1 -0
  271. package/dist/internal/discovery/services.js +104 -0
  272. package/dist/internal/discovery/skills.d.ts +16 -0
  273. package/dist/internal/discovery/skills.d.ts.map +1 -0
  274. package/dist/internal/discovery/skills.js +151 -0
  275. package/dist/internal/discovery/subagent.d.ts +13 -0
  276. package/dist/internal/discovery/subagent.d.ts.map +1 -0
  277. package/dist/internal/discovery/subagent.js +19 -0
  278. package/dist/internal/discovery/tools.d.ts +18 -0
  279. package/dist/internal/discovery/tools.d.ts.map +1 -0
  280. package/dist/internal/discovery/tools.js +159 -0
  281. package/dist/internal/discovery.d.ts +8 -62
  282. package/dist/internal/discovery.d.ts.map +1 -1
  283. package/dist/internal/discovery.js +8 -2210
  284. package/dist/internal/distribution.d.ts.map +1 -1
  285. package/dist/internal/distribution.js +5 -0
  286. package/dist/internal/framework-file-storage.d.ts +3 -3
  287. package/dist/internal/framework-file-storage.d.ts.map +1 -1
  288. package/dist/internal/framework-file-storage.js +38 -9
  289. package/dist/internal/framework-storage-selection.d.ts.map +1 -1
  290. package/dist/internal/framework-storage-selection.js +8 -7
  291. package/dist/internal/frontmatter.d.ts +11 -3
  292. package/dist/internal/frontmatter.d.ts.map +1 -1
  293. package/dist/internal/frontmatter.js +29 -3
  294. package/dist/internal/hosted-delivery.d.ts +3 -1
  295. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  296. package/dist/internal/hosted-delivery.js +19 -32
  297. package/dist/internal/hosted-execution-diag.d.ts +5 -0
  298. package/dist/internal/hosted-execution-diag.d.ts.map +1 -1
  299. package/dist/internal/hosted-execution-diag.js +5 -0
  300. package/dist/internal/hosted-execution-flush.d.ts +46 -0
  301. package/dist/internal/hosted-execution-flush.d.ts.map +1 -0
  302. package/dist/internal/hosted-execution-flush.js +81 -0
  303. package/dist/internal/mcp-endpoint.js +1 -0
  304. package/dist/internal/mcp-host.d.ts +2 -1
  305. package/dist/internal/mcp-host.d.ts.map +1 -1
  306. package/dist/internal/mcp-host.js +66 -29
  307. package/dist/internal/otel/collector.d.ts +13 -0
  308. package/dist/internal/otel/collector.d.ts.map +1 -1
  309. package/dist/internal/otel/collector.js +84 -17
  310. package/dist/internal/otel/http.d.ts.map +1 -1
  311. package/dist/internal/otel/http.js +2 -10
  312. package/dist/internal/otel/mcp.d.ts +16 -0
  313. package/dist/internal/otel/mcp.d.ts.map +1 -0
  314. package/dist/internal/otel/mcp.js +68 -0
  315. package/dist/internal/otel/propagation.d.ts +6 -0
  316. package/dist/internal/otel/propagation.d.ts.map +1 -0
  317. package/dist/internal/otel/propagation.js +14 -0
  318. package/dist/internal/otel/runtime.d.ts.map +1 -1
  319. package/dist/internal/otel/runtime.js +2 -0
  320. package/dist/internal/review-comments.d.ts +1 -1
  321. package/dist/internal/review-comments.d.ts.map +1 -1
  322. package/dist/internal/review-comments.js +4 -4
  323. package/dist/internal/server.d.ts +3 -0
  324. package/dist/internal/server.d.ts.map +1 -1
  325. package/dist/internal/server.js +79 -104
  326. package/dist/internal/session-engine.d.ts +14 -7
  327. package/dist/internal/session-engine.d.ts.map +1 -1
  328. package/dist/internal/session-engine.js +113 -66
  329. package/dist/internal/session-run-log.d.ts +3 -1
  330. package/dist/internal/session-run-log.d.ts.map +1 -1
  331. package/dist/internal/session-run-log.js +14 -14
  332. package/dist/internal/start-log-store.d.ts +60 -0
  333. package/dist/internal/start-log-store.d.ts.map +1 -0
  334. package/dist/internal/start-log-store.js +149 -0
  335. package/dist/internal/storage-coordinator.d.ts +4 -1
  336. package/dist/internal/storage-coordinator.d.ts.map +1 -1
  337. package/dist/internal/storage-coordinator.js +15 -13
  338. package/dist/internal/tool-catalog.d.ts.map +1 -1
  339. package/dist/internal/tool-catalog.js +9 -6
  340. package/dist/internal/tool-policy.d.ts +8 -0
  341. package/dist/internal/tool-policy.d.ts.map +1 -1
  342. package/dist/internal/tool-policy.js +19 -7
  343. package/dist/internal/turn-cost.d.ts +14 -0
  344. package/dist/internal/turn-cost.d.ts.map +1 -1
  345. package/dist/internal/turn-cost.js +41 -9
  346. package/dist/internal/v2-hosting.d.ts +22 -0
  347. package/dist/internal/v2-hosting.d.ts.map +1 -0
  348. package/dist/internal/v2-hosting.js +23 -0
  349. package/dist/otel.d.ts +16 -0
  350. package/dist/otel.d.ts.map +1 -1
  351. package/dist/otel.js +26 -0
  352. package/dist/playground/assets/index-B6C9S9nG.css +1 -0
  353. package/dist/playground/assets/{index-DVs98vPL.js → index-ZqNoT8Ie.js} +45 -45
  354. package/dist/playground/index.html +2 -2
  355. package/dist/storage-protocol.d.ts +47 -22
  356. package/dist/storage-protocol.d.ts.map +1 -1
  357. package/dist/storage-protocol.js +90 -54
  358. package/dist/storage.d.ts +2 -2
  359. package/dist/storage.d.ts.map +1 -1
  360. package/dist/storage.js +1 -1
  361. package/dist/tools.d.ts +9 -0
  362. package/dist/tools.d.ts.map +1 -1
  363. package/dist/tools.js +9 -0
  364. package/dist/types.d.ts +154 -6
  365. package/dist/types.d.ts.map +1 -1
  366. package/dist/types.js +29 -1
  367. package/docs/README.md +5 -1
  368. package/docs/concepts.md +3 -3
  369. package/docs/guides/cloud-agents.md +98 -0
  370. package/docs/guides/cloud-runtime.md +2 -0
  371. package/docs/reference/connections.md +31 -0
  372. package/docs/reference/extensions.md +205 -0
  373. package/docs/reference/http-api.md +1 -1
  374. package/docs/reference/project-layout.md +3 -0
  375. package/docs/reference/skills.md +2 -0
  376. package/docs/reference/tools.md +2 -0
  377. package/package.json +18 -4
  378. package/skills/framework-map/SKILL.md +1 -0
  379. package/src/bin/agent-serve.ts +11 -2
  380. package/src/channels/deployments/deployments-channel.ts +117 -8
  381. package/src/channels/deployments/types.ts +4 -3
  382. package/src/channels/origin/defaults.ts +143 -0
  383. package/src/channels/origin/index.ts +2 -0
  384. package/src/channels/origin/origin-channel.ts +37 -1
  385. package/src/channels/origin/state.ts +54 -0
  386. package/src/channels/origin/types.ts +24 -0
  387. package/src/channels/slack/api.ts +6 -3
  388. package/src/channels/slack/assistant.ts +1 -1
  389. package/src/channels/slack/code-fences.ts +183 -0
  390. package/src/channels/slack/dispatch.ts +27 -2
  391. package/src/channels/slack/inbound.ts +37 -0
  392. package/src/channels/slack/index.ts +1 -0
  393. package/src/channels/slack/live-delivery.ts +16 -13
  394. package/src/channels/slack/manifest.ts +2 -1
  395. package/src/connections.ts +18 -1
  396. package/src/extensions/cursor-cloud-agents/extension.ts +120 -0
  397. package/src/extensions/cursor-cloud-agents/lib/backend.ts +395 -0
  398. package/src/extensions/cursor-cloud-agents/lib/fleet.ts +109 -0
  399. package/src/extensions/cursor-cloud-agents/lib/inputs.ts +5 -0
  400. package/src/extensions/cursor-cloud-agents/lib/repos.ts +81 -0
  401. package/src/extensions/cursor-cloud-agents/lib/transcript.ts +23 -0
  402. package/src/extensions/cursor-cloud-agents/skills/handoff.md +41 -0
  403. package/src/extensions/cursor-cloud-agents/tools/cancel.ts +19 -0
  404. package/src/extensions/cursor-cloud-agents/tools/dump.ts +51 -0
  405. package/src/extensions/cursor-cloud-agents/tools/get.ts +18 -0
  406. package/src/extensions/cursor-cloud-agents/tools/launch.ts +64 -0
  407. package/src/extensions/cursor-cloud-agents/tools/list.ts +31 -0
  408. package/src/extensions/cursor-cloud-agents/tools/reply.ts +34 -0
  409. package/src/extensions.ts +141 -0
  410. package/src/files-backends/cursor-hosted.ts +1 -17
  411. package/src/files.ts +43 -34
  412. package/src/index.ts +11 -0
  413. package/src/internal/advertise-tools.ts +37 -12
  414. package/src/internal/as-of.ts +163 -0
  415. package/src/internal/cli-deploy.ts +86 -23
  416. package/src/internal/continuation-identity.ts +3 -1
  417. package/src/internal/conversation-mirror.ts +23 -18
  418. package/src/internal/cursor/backend-client.ts +32 -10
  419. package/src/internal/cursor/hosted-deployment-secrets.ts +72 -0
  420. package/src/internal/cursor/hosted-store-secrets.ts +27 -0
  421. package/src/internal/cursor-deployment-relay.ts +65 -8
  422. package/src/internal/deploy-client.ts +73 -18
  423. package/src/internal/discovery/ab.ts +111 -0
  424. package/src/internal/discovery/agent-config.ts +222 -0
  425. package/src/internal/discovery/agent.ts +360 -0
  426. package/src/internal/discovery/channels.ts +103 -0
  427. package/src/internal/discovery/connections.ts +540 -0
  428. package/src/internal/discovery/context.ts +46 -0
  429. package/src/internal/discovery/cursor-plugin.ts +708 -0
  430. package/src/internal/discovery/extensions.ts +348 -0
  431. package/src/internal/discovery/fs.ts +108 -0
  432. package/src/internal/discovery/hooks.ts +45 -0
  433. package/src/internal/discovery/info.ts +179 -0
  434. package/src/internal/discovery/instructions.ts +113 -0
  435. package/src/internal/discovery/modules.ts +107 -0
  436. package/src/internal/discovery/names.ts +44 -0
  437. package/src/internal/discovery/project.ts +270 -0
  438. package/src/internal/discovery/runtime.ts +159 -0
  439. package/src/internal/discovery/schedules.ts +94 -0
  440. package/src/internal/discovery/seed-files.ts +37 -0
  441. package/src/internal/discovery/services.ts +124 -0
  442. package/src/internal/discovery/skills.ts +176 -0
  443. package/src/internal/discovery/subagent.ts +29 -0
  444. package/src/internal/discovery/tools.ts +182 -0
  445. package/src/internal/discovery.ts +20 -2724
  446. package/src/internal/distribution.ts +5 -0
  447. package/src/internal/framework-file-storage.ts +43 -9
  448. package/src/internal/framework-storage-selection.ts +9 -9
  449. package/src/internal/frontmatter.ts +36 -3
  450. package/src/internal/hosted-delivery.ts +38 -63
  451. package/src/internal/hosted-execution-diag.ts +6 -0
  452. package/src/internal/hosted-execution-flush.ts +142 -0
  453. package/src/internal/mcp-endpoint.ts +1 -0
  454. package/src/internal/mcp-host.ts +116 -37
  455. package/src/internal/otel/collector.ts +125 -25
  456. package/src/internal/otel/http.ts +2 -12
  457. package/src/internal/otel/mcp.ts +69 -0
  458. package/src/internal/otel/propagation.ts +17 -0
  459. package/src/internal/otel/runtime.ts +2 -0
  460. package/src/internal/review-comments.ts +5 -2
  461. package/src/internal/server.ts +81 -100
  462. package/src/internal/session-engine.ts +152 -39
  463. package/src/internal/session-run-log.ts +18 -16
  464. package/src/internal/start-log-store.ts +174 -0
  465. package/src/internal/storage-coordinator.ts +19 -16
  466. package/src/internal/tool-catalog.ts +9 -6
  467. package/src/internal/tool-policy.ts +39 -9
  468. package/src/internal/turn-cost.ts +47 -4
  469. package/src/internal/v2-hosting.ts +38 -0
  470. package/src/otel.ts +38 -0
  471. package/src/storage-protocol.ts +126 -79
  472. package/src/storage.ts +5 -0
  473. package/src/tools.ts +18 -0
  474. package/src/types.ts +213 -14
  475. package/dist/docs/assets/chunks/@localSearchIndexroot.j70vvPL4.js +0 -1
  476. package/dist/docs/assets/concepts.md.lwAgBIMI.js +0 -1
  477. package/dist/docs/assets/index.md.Bb4k8kUm.js +0 -5
  478. package/dist/docs/assets/skills_framework-map.md.BTi817yv.js +0 -1
  479. package/dist/playground/assets/index-BszoQDc6.css +0 -1
  480. /package/dist/docs/assets/{concepts.md.lwAgBIMI.lean.js → concepts.md.rPzW2HZN.lean.js} +0 -0
  481. /package/dist/docs/assets/{guides_cloud-runtime.md.CkYbjnAX.lean.js → guides_cloud-runtime.md.BRirbRAN.lean.js} +0 -0
  482. /package/dist/docs/assets/{reference_http-api.md.BEJx9XVj.lean.js → reference_http-api.md.oySXBO8o.lean.js} +0 -0
  483. /package/dist/docs/assets/{reference_skills.md.BFW9retM.lean.js → reference_skills.md.l2ezAcaN.lean.js} +0 -0
  484. /package/dist/docs/assets/{reference_tools.md.CvAHsdSp.lean.js → reference_tools.md.B1up2r9W.lean.js} +0 -0
@@ -37,16 +37,13 @@
37
37
  */
38
38
 
39
39
  import type { LocalAgentDocument, LocalAgentStore } from "@cursor/sdk";
40
- import { agentStoreKeys, type FileSink } from "../files.js";
41
- import {
42
- cursorFrameworkStoreSourceId,
43
- cursorHostedFiles,
44
- } from "../files-backends/cursor-hosted.js";
40
+ import { agentSdkAgentStoreKeys, type FileSink } from "../files.js";
41
+ import { cursorHostedFiles } from "../files-backends/cursor-hosted.js";
45
42
  import type { AgentProject } from "../types.js";
46
43
  import { mapBounded } from "./bounded.js";
47
44
  import { resolveApiKeySync } from "./cursor/credentials.js";
48
- import { AGENT_SERVE_GENERATION_ENV_VAR } from "./cursor-relay-core.js";
49
45
  import { describeError } from "./describe-error.js";
46
+ import { resolveAgentV2Hosting } from "./v2-hosting.js";
50
47
 
51
48
  /**
52
49
  * Persist/restore one SDK conversation between a {@link LocalAgentStore} and
@@ -70,7 +67,7 @@ export interface ConversationMirror {
70
67
  persist(store: LocalAgentStore, sdkAgentId: string): Promise<void>;
71
68
  }
72
69
 
73
- /** Wire shape at {@link agentStoreKeys.conversationManifest}. */
70
+ /** Wire shape at {@link agentSdkAgentStoreKeys.conversationManifest}. */
74
71
  interface ConversationManifestV1 {
75
72
  v: 1;
76
73
  /** The SDK agent document, verbatim apart from `activeRunId` (nulled). */
@@ -181,7 +178,11 @@ export function createConversationMirror(
181
178
  continue;
182
179
  }
183
180
  await sink.put(
184
- agentStoreKeys.conversationBlob(agentName, sdkAgentId, blobId),
181
+ agentSdkAgentStoreKeys.conversationBlob(
182
+ agentName,
183
+ sdkAgentId,
184
+ blobId
185
+ ),
185
186
  bytes
186
187
  );
187
188
  // Content-addressed: once in the sink, never re-uploaded.
@@ -197,7 +198,7 @@ export function createConversationMirror(
197
198
  };
198
199
  // Manifest last: it only ever references blobs already uploaded.
199
200
  await sink.put(
200
- agentStoreKeys.conversationManifest(agentName, sdkAgentId),
201
+ agentSdkAgentStoreKeys.conversationManifest(agentName, sdkAgentId),
201
202
  new TextEncoder().encode(JSON.stringify(manifest))
202
203
  );
203
204
  });
@@ -242,7 +243,11 @@ export function createConversationMirror(
242
243
  async (blobId) => ({
243
244
  blobId,
244
245
  body: await sink.get(
245
- agentStoreKeys.conversationBlob(agentName, sdkAgentId, blobId)
246
+ agentSdkAgentStoreKeys.conversationBlob(
247
+ agentName,
248
+ sdkAgentId,
249
+ blobId
250
+ )
246
251
  ),
247
252
  })
248
253
  );
@@ -317,7 +322,7 @@ async function readManifest(
317
322
  sdkAgentId: string
318
323
  ): Promise<ManifestRead> {
319
324
  const body = await sink.get(
320
- agentStoreKeys.conversationManifest(agentName, sdkAgentId)
325
+ agentSdkAgentStoreKeys.conversationManifest(agentName, sdkAgentId)
321
326
  );
322
327
  if (body === undefined) {
323
328
  return { outcome: "miss" };
@@ -379,17 +384,17 @@ export function selectConversationMirror(input: {
379
384
  logger?: (line: string) => void;
380
385
  env?: Record<string, string | undefined>;
381
386
  }): ConversationMirror | undefined {
382
- if (input.project.agent.architecture !== "v2") {
383
- return undefined;
384
- }
385
- const env = input.env ?? process.env;
386
- if (env[AGENT_SERVE_GENERATION_ENV_VAR] === undefined) {
387
+ const hosting = resolveAgentV2Hosting({
388
+ architecture: input.project.agent.architecture,
389
+ env: input.env as NodeJS.ProcessEnv | undefined,
390
+ });
391
+ if (hosting.kind !== "cursor-managed") {
387
392
  return undefined;
388
393
  }
389
- const envSnapshot = env as NodeJS.ProcessEnv;
390
394
  return createConversationMirror({
391
395
  sink: cursorHostedFiles({
392
- resolveStoreSourceId: () => cursorFrameworkStoreSourceId(envSnapshot),
396
+ resolveStoreSourceId: () =>
397
+ hosting.resolveStoreIds().frameworkStoreSourceId,
393
398
  // Full chain (env → key file → stored login): frozen engines listen
394
399
  // unsigned and bind CURSOR_API_KEY_FILE at task time, after this sink
395
400
  // is constructed.
@@ -2,7 +2,8 @@
2
2
  * Minimal Connect-JSON client for the handful of `aiserver.v1.DashboardService`
3
3
  * RPCs agent-serve needs — `GetMe`, `ListSandMcpTools`, `ExecuteSandMcpTool`,
4
4
  * and the login-time key lifecycle (`CreateUserApiKey`, `ListUserApiKeys`,
5
- * `RevokeUserApiKey`).
5
+ * `RevokeUserApiKey`) — plus {@link CursorBackendClient.serviceRpc} for the
6
+ * odd unary call on another `aiserver.v1` service under the same token.
6
7
  *
7
8
  * Plain `fetch` POSTs with proto-JSON bodies and zod-validated responses:
8
9
  * agent-serve is a published package and should not pull the generated
@@ -25,7 +26,7 @@ import {
25
26
  } from "./session-token.js";
26
27
 
27
28
  const CLIENT_VERSION = "agent-serve-0.1.0";
28
- const SERVICE_PREFIX = "/aiserver.v1.DashboardService";
29
+ const DASHBOARD_SERVICE = "DashboardService";
29
30
  const LIST_TIMEOUT_MS = 60_000;
30
31
  /** Backend-executed tools call out to third-party servers; be generous. */
31
32
  const EXECUTE_TIMEOUT_MS = 120_000;
@@ -235,9 +236,10 @@ export interface AccountMcpCallResult {
235
236
  // ============================================================================
236
237
 
237
238
  /** One DashboardService Connect-JSON POST; auth is the caller's bearer. */
238
- async function dashboardRpc(args: {
239
+ async function connectRpc(args: {
239
240
  fetchImpl: typeof fetch;
240
241
  backendUrl: string;
242
+ service: string;
241
243
  method: string;
242
244
  bearer: string;
243
245
  body: unknown;
@@ -246,7 +248,7 @@ async function dashboardRpc(args: {
246
248
  }): Promise<Response> {
247
249
  try {
248
250
  return await args.fetchImpl(
249
- `${args.backendUrl}${SERVICE_PREFIX}/${args.method}`,
251
+ `${args.backendUrl}/aiserver.v1.${args.service}/${args.method}`,
250
252
  {
251
253
  method: "POST",
252
254
  headers: {
@@ -485,20 +487,36 @@ export class CursorBackendClient {
485
487
  return githubTokenResponseSchema.parse(parsed);
486
488
  }
487
489
 
490
+ /**
491
+ * One unary Connect-JSON call on `aiserver.v1.<service>` with the same
492
+ * token exchange and 401 retry as the dashboard RPCs. Callers parse the
493
+ * proto-JSON response themselves.
494
+ */
495
+ serviceRpc(
496
+ service: string,
497
+ method: string,
498
+ body: unknown,
499
+ timeoutMs: number = LIST_TIMEOUT_MS
500
+ ): Promise<unknown> {
501
+ return this.rpc(method, body, timeoutMs, { service });
502
+ }
503
+
488
504
  private async rpc(
489
505
  method: string,
490
506
  body: unknown,
491
507
  timeoutMs = LIST_TIMEOUT_MS,
492
- options?: { teamId?: number }
508
+ options?: { teamId?: number; service?: string }
493
509
  ): Promise<unknown> {
510
+ const service = options?.service ?? DASHBOARD_SERVICE;
494
511
  const extraHeaders =
495
512
  options?.teamId === undefined
496
513
  ? undefined
497
514
  : { "x-cursor-team-id": String(options.teamId) };
498
515
  const bearer = await this.getAccessToken();
499
- const first = await dashboardRpc({
516
+ const first = await connectRpc({
500
517
  fetchImpl: this.fetchImpl,
501
518
  backendUrl: this.backendUrl,
519
+ service,
502
520
  method,
503
521
  bearer,
504
522
  body,
@@ -516,9 +534,10 @@ export class CursorBackendClient {
516
534
  this.token = undefined;
517
535
  }
518
536
  const retryBearer = await this.getAccessToken();
519
- const second = await dashboardRpc({
537
+ const second = await connectRpc({
520
538
  fetchImpl: this.fetchImpl,
521
539
  backendUrl: this.backendUrl,
540
+ service,
522
541
  method,
523
542
  bearer: retryBearer,
524
543
  body,
@@ -612,11 +631,12 @@ export async function createUserApiKeyWithSessionToken(args: {
612
631
  keyName: string;
613
632
  fetchImpl?: typeof fetch;
614
633
  }): Promise<string> {
615
- const response = await dashboardRpc({
634
+ const response = await connectRpc({
616
635
  fetchImpl: args.fetchImpl ?? fetch,
617
636
  backendUrl: args.backendUrl.endsWith("/")
618
637
  ? args.backendUrl.slice(0, -1)
619
638
  : args.backendUrl,
639
+ service: DASHBOARD_SERVICE,
620
640
  method: "CreateUserApiKey",
621
641
  bearer: args.sessionToken,
622
642
  body: { name: args.keyName },
@@ -666,9 +686,10 @@ export async function revokeMintedUserApiKey(args: {
666
686
  ? args.backendUrl.slice(0, -1)
667
687
  : args.backendUrl;
668
688
 
669
- const listResponse = await dashboardRpc({
689
+ const listResponse = await connectRpc({
670
690
  fetchImpl,
671
691
  backendUrl,
692
+ service: DASHBOARD_SERVICE,
672
693
  method: "ListUserApiKeys",
673
694
  bearer: args.sessionToken,
674
695
  body: {},
@@ -686,9 +707,10 @@ export async function revokeMintedUserApiKey(args: {
686
707
  // lagging replica — skip rather than touch any other key.
687
708
  return;
688
709
  }
689
- const revokeResponse = await dashboardRpc({
710
+ const revokeResponse = await connectRpc({
690
711
  fetchImpl,
691
712
  backendUrl,
713
+ service: DASHBOARD_SERVICE,
692
714
  method: "RevokeUserApiKey",
693
715
  bearer: args.sessionToken,
694
716
  body: { id: match.id },
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Task-time application secrets for hosted v2 freeze restores.
3
+ *
4
+ * The deployment host rewrites this tmpfs document before each admission and
5
+ * execution request. July reloads it synchronously because the process was
6
+ * already running in the frozen snapshot when the task-specific values
7
+ * arrived.
8
+ */
9
+
10
+ import { readFileSync } from "node:fs";
11
+
12
+ export const DEFAULT_AGENT_SERVE_DEPLOYMENT_SECRETS_FILE =
13
+ "/run/cursor/secrets/AGENT_SERVE_DEPLOYMENT_SECRETS.json";
14
+
15
+ const SECRET_NAME_PATTERN = /^[A-Z][A-Z0-9_]{0,63}$/;
16
+ const appliedSecretNames = new Set<string>();
17
+
18
+ function parseBoundSecrets(path: string): Record<string, string> | undefined {
19
+ let parsed: unknown;
20
+ try {
21
+ parsed = JSON.parse(readFileSync(path, "utf8"));
22
+ } catch {
23
+ return undefined;
24
+ }
25
+ if (parsed === null || typeof parsed !== "object") {
26
+ return undefined;
27
+ }
28
+ const envelope = parsed as { v?: unknown; secrets?: unknown };
29
+ if (
30
+ envelope.v !== 1 ||
31
+ envelope.secrets === null ||
32
+ typeof envelope.secrets !== "object" ||
33
+ Array.isArray(envelope.secrets)
34
+ ) {
35
+ return undefined;
36
+ }
37
+ const secrets: Record<string, string> = {};
38
+ for (const [name, value] of Object.entries(envelope.secrets)) {
39
+ if (
40
+ SECRET_NAME_PATTERN.test(name) &&
41
+ !name.startsWith("CURSOR_") &&
42
+ typeof value === "string"
43
+ ) {
44
+ secrets[name] = value;
45
+ }
46
+ }
47
+ return secrets;
48
+ }
49
+
50
+ /**
51
+ * Refresh `process.env` from the latest bound document. A missing or malformed
52
+ * file is a no-op; an empty valid document removes values loaded by an earlier
53
+ * bind after the deployment secret was unset.
54
+ */
55
+ export function refreshBoundDeploymentSecrets(
56
+ path: string = DEFAULT_AGENT_SERVE_DEPLOYMENT_SECRETS_FILE
57
+ ): void {
58
+ const secrets = parseBoundSecrets(path);
59
+ if (secrets === undefined) {
60
+ return;
61
+ }
62
+ for (const name of appliedSecretNames) {
63
+ if (!(name in secrets)) {
64
+ delete process.env[name];
65
+ }
66
+ }
67
+ appliedSecretNames.clear();
68
+ for (const [name, value] of Object.entries(secrets)) {
69
+ process.env[name] = value;
70
+ appliedSecretNames.add(name);
71
+ }
72
+ }
@@ -70,3 +70,30 @@ export function resolveFrameworkStoreSourceIdSync(
70
70
  env
71
71
  );
72
72
  }
73
+
74
+ export type CursorManagedV2StoreIds = {
75
+ deploymentStoreSourceId: string;
76
+ frameworkStoreSourceId: string;
77
+ };
78
+
79
+ /**
80
+ * Resolve the complete managed-v2 store identity at the process boundary.
81
+ *
82
+ * Freeze snapshots construct storage before task bind, so callers keep this
83
+ * resolver lazy. Once an operation needs storage, both ids are mandatory.
84
+ */
85
+ export function requireCursorManagedV2StoreIdsSync(
86
+ env: NodeJS.ProcessEnv = process.env
87
+ ): CursorManagedV2StoreIds {
88
+ const deploymentStoreSourceId = resolveDeploymentStoreSourceIdSync(env);
89
+ const frameworkStoreSourceId = resolveFrameworkStoreSourceIdSync(env);
90
+ if (
91
+ deploymentStoreSourceId === undefined ||
92
+ frameworkStoreSourceId === undefined
93
+ ) {
94
+ throw new Error(
95
+ "Cursor-managed AgentSDK v2 requires AGENT_SERVE_STORE_SOURCE_ID and AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID"
96
+ );
97
+ }
98
+ return { deploymentStoreSourceId, frameworkStoreSourceId };
99
+ }
@@ -33,17 +33,33 @@ interface SubscriptionStatus {
33
33
  detail?: string;
34
34
  }
35
35
 
36
+ export type DeploymentSubscriptionSource =
37
+ | readonly ResolvedSubscription[]
38
+ | (() => readonly ResolvedSubscription[]);
39
+
36
40
  export interface DeploymentEventRelayOptions {
37
41
  baseUrl: string;
38
42
  apiKey: string;
39
43
  stateDir: string;
40
- subscriptions: readonly ResolvedSubscription[];
44
+ /**
45
+ * Snapshot or a getter. A getter is re-read on every registration
46
+ * heartbeat so a channel that refreshes `deploySourceUris` after start
47
+ * can add sources without restarting the relay.
48
+ */
49
+ subscriptions: DeploymentSubscriptionSource;
41
50
  dispatch: (event: DeploymentEvent) => Promise<void>;
42
51
  logger: (line: string) => void;
43
52
  fetchImpl?: typeof fetch;
44
53
  pollWaitMs?: number;
45
54
  }
46
55
 
56
+ /** Current subscriptions: a live getter, otherwise the snapshot. */
57
+ export function currentDeploymentSubscriptions(
58
+ subscriptions: DeploymentSubscriptionSource
59
+ ): readonly ResolvedSubscription[] {
60
+ return typeof subscriptions === "function" ? subscriptions() : subscriptions;
61
+ }
62
+
47
63
  /** Normalize the channel's `deploySourceUris` option into concrete subscriptions. */
48
64
  export function resolveDeploymentSubscriptions(options: {
49
65
  deploySourceUris: readonly (string | DeploymentSubscription)[];
@@ -90,10 +106,46 @@ export function resolveDeploymentSubscriptions(options: {
90
106
  ? []
91
107
  : [...new Set([...existing.environments, ...environments])];
92
108
  }
93
- // Empty is legal here and means "this channel wants nothing", which is how
94
- // an env-configured channel stays inert without a deploy-source list. The
95
- // wire-level empty list means deregister, so the host simply never
96
- // registers it.
109
+ // Empty is legal here and means "this channel wants nothing". The
110
+ // wire-level empty list means deregister. The host re-resolves on each
111
+ // heartbeat, so a channel that later fills `deploySourceUris` can
112
+ // register without a restart.
113
+ return [...bySource.values()];
114
+ }
115
+
116
+ /**
117
+ * Union per-channel subscriptions, widening events and environments when
118
+ * the same deploy source appears more than once. An empty environment
119
+ * list means every environment and absorbs a narrower list.
120
+ */
121
+ export function mergeResolvedSubscriptions(
122
+ groups: readonly (readonly ResolvedSubscription[])[]
123
+ ): ResolvedSubscription[] {
124
+ const bySource = new Map<string, ResolvedSubscription>();
125
+ for (const group of groups) {
126
+ for (const subscription of group) {
127
+ const existing = bySource.get(subscription.deploySourceUri);
128
+ if (existing === undefined) {
129
+ bySource.set(subscription.deploySourceUri, {
130
+ deploySourceUri: subscription.deploySourceUri,
131
+ environments: [...subscription.environments],
132
+ events: new Set(subscription.events),
133
+ });
134
+ continue;
135
+ }
136
+ for (const event of subscription.events) existing.events.add(event);
137
+ existing.environments =
138
+ existing.environments.length === 0 ||
139
+ subscription.environments.length === 0
140
+ ? []
141
+ : [
142
+ ...new Set([
143
+ ...existing.environments,
144
+ ...subscription.environments,
145
+ ]),
146
+ ];
147
+ }
148
+ }
97
149
  return [...bySource.values()];
98
150
  }
99
151
 
@@ -176,7 +228,9 @@ export class DeploymentEventRelay {
176
228
  pollPath: "/v0/deployment-events",
177
229
  buildRegistrationBody: (consumerId) => ({
178
230
  consumerId,
179
- subscriptions: options.subscriptions.map((subscription) => ({
231
+ subscriptions: currentDeploymentSubscriptions(
232
+ options.subscriptions
233
+ ).map((subscription) => ({
180
234
  deploySourceUri: subscription.deploySourceUri,
181
235
  environments: subscription.environments,
182
236
  events: [...subscription.events],
@@ -190,12 +244,15 @@ export class DeploymentEventRelay {
190
244
  }),
191
245
  applyRegistrationResponse: (json) => {
192
246
  const result = json as { deploySourceUris?: SubscriptionStatus[] };
247
+ const wantedSubscriptions = currentDeploymentSubscriptions(
248
+ options.subscriptions
249
+ );
193
250
  this.subscribed = new Map();
194
251
  this.loggedSkippedSources.clear();
195
252
  const lines: string[] = [];
196
253
  const confirmed: string[] = [];
197
254
  for (const status of result.deploySourceUris ?? []) {
198
- const wanted = options.subscriptions.find(
255
+ const wanted = wantedSubscriptions.find(
199
256
  (subscription) =>
200
257
  subscription.deploySourceUri === status.deploySourceUri
201
258
  );
@@ -210,7 +267,7 @@ export class DeploymentEventRelay {
210
267
  }
211
268
  if (confirmed.length > 0) {
212
269
  const kinds = [
213
- ...new Set(options.subscriptions.flatMap((s) => [...s.events])),
270
+ ...new Set(wantedSubscriptions.flatMap((s) => [...s.events])),
214
271
  ];
215
272
  lines.push(
216
273
  `subscribed to ${confirmed.join(", ")} for events: ${kinds.join(", ")}`
@@ -267,6 +267,8 @@ export interface AgentkitDeployStatus {
267
267
  * Absent on control planes that predate the field.
268
268
  */
269
269
  repositories?: string[];
270
+ /** Names of application-scoped secrets (values are never returned). */
271
+ secretNames?: string[];
270
272
  }
271
273
 
272
274
  export const TERMINAL_AGENTKIT_DEPLOY_STATUSES: ReadonlySet<AgentkitCustomerStatus> =
@@ -359,6 +361,7 @@ const agentkitDeployStatusSchema = z
359
361
  statusMessage: z.string().nullable(),
360
362
  // Optional: backends that predate the v2 bake-failure column omit it.
361
363
  lastError: z.string().nullable().optional(),
364
+ secretNames: z.array(z.string()).optional(),
362
365
  })
363
366
  .passthrough();
364
367
 
@@ -740,24 +743,7 @@ export class AgentServeDeployClient {
740
743
  slug: string;
741
744
  secrets: Array<{ name: string; value: string }>;
742
745
  }): Promise<string[]> {
743
- for (const { name, value } of args.secrets) {
744
- const nameError = validateSettableSecretName(name);
745
- if (nameError !== undefined) {
746
- throw new DeployApiError(nameError, 400);
747
- }
748
- if (Buffer.byteLength(value, "utf8") > MAX_SECRET_VALUE_BYTES) {
749
- throw new DeployApiError(
750
- `The value for ${name} is too large (max ${MAX_SECRET_VALUE_BYTES} bytes).`,
751
- 400
752
- );
753
- }
754
- }
755
- if (args.secrets.length > MAX_SECRETS) {
756
- throw new DeployApiError(
757
- `Too many secrets in one request (${args.secrets.length}); deployments hold at most ${MAX_SECRETS}.`,
758
- 400
759
- );
760
- }
746
+ this.validateSecrets(args.secrets);
761
747
  const raw = await this.request({
762
748
  method: "PUT",
763
749
  path: `/internal/agent-serve/deployments/${encodeURIComponent(args.slug)}/secrets`,
@@ -767,6 +753,22 @@ export class AgentServeDeployClient {
767
753
  return setSecretsResponseSchema.parse(raw).secretNames;
768
754
  }
769
755
 
756
+ /** Upsert application-scoped secrets on an AgentSDK v2 deployment. */
757
+ async setAgentkitSecrets(args: {
758
+ teamId: number;
759
+ slug: string;
760
+ secrets: Array<{ name: string; value: string }>;
761
+ }): Promise<string[]> {
762
+ this.validateSecrets(args.secrets);
763
+ const raw = await this.request({
764
+ method: "PUT",
765
+ path: `/internal/agentsdk/deployments/${encodeURIComponent(args.slug)}/secrets`,
766
+ body: { teamId: args.teamId, secrets: args.secrets },
767
+ context: { verb: "set secrets", slug: args.slug },
768
+ });
769
+ return setSecretsResponseSchema.parse(raw).secretNames;
770
+ }
771
+
770
772
  /** Secret names + creation times; values are never returned. */
771
773
  async listSecrets(args: {
772
774
  teamId: number;
@@ -780,6 +782,19 @@ export class AgentServeDeployClient {
780
782
  return listSecretsResponseSchema.parse(raw).secrets;
781
783
  }
782
784
 
785
+ /** Secret names + creation times for an AgentSDK v2 application. */
786
+ async listAgentkitSecrets(args: {
787
+ teamId: number;
788
+ slug: string;
789
+ }): Promise<SecretInfo[]> {
790
+ const raw = await this.request({
791
+ method: "GET",
792
+ path: `/internal/agentsdk/deployments/${encodeURIComponent(args.slug)}/secrets?teamId=${args.teamId}`,
793
+ context: { verb: "list secrets", slug: args.slug },
794
+ });
795
+ return listSecretsResponseSchema.parse(raw).secrets;
796
+ }
797
+
783
798
  /** Remove one secret by name; 404 when it is not set. */
784
799
  async deleteSecret(args: {
785
800
  teamId: number;
@@ -797,6 +812,46 @@ export class AgentServeDeployClient {
797
812
  });
798
813
  }
799
814
 
815
+ /** Remove one application-scoped secret from an AgentSDK v2 deployment. */
816
+ async deleteAgentkitSecret(args: {
817
+ teamId: number;
818
+ slug: string;
819
+ name: string;
820
+ }): Promise<void> {
821
+ const nameError = validateSettableSecretName(args.name);
822
+ if (nameError !== undefined) {
823
+ throw new DeployApiError(nameError, 400);
824
+ }
825
+ await this.request({
826
+ method: "DELETE",
827
+ path: `/internal/agentsdk/deployments/${encodeURIComponent(args.slug)}/secrets/${encodeURIComponent(args.name)}?teamId=${args.teamId}`,
828
+ context: { verb: "unset secret", slug: args.slug },
829
+ });
830
+ }
831
+
832
+ private validateSecrets(
833
+ secrets: Array<{ name: string; value: string }>
834
+ ): void {
835
+ for (const { name, value } of secrets) {
836
+ const nameError = validateSettableSecretName(name);
837
+ if (nameError !== undefined) {
838
+ throw new DeployApiError(nameError, 400);
839
+ }
840
+ if (Buffer.byteLength(value, "utf8") > MAX_SECRET_VALUE_BYTES) {
841
+ throw new DeployApiError(
842
+ `The value for ${name} is too large (max ${MAX_SECRET_VALUE_BYTES} bytes).`,
843
+ 400
844
+ );
845
+ }
846
+ }
847
+ if (secrets.length > MAX_SECRETS) {
848
+ throw new DeployApiError(
849
+ `Too many secrets in one request (${secrets.length}); deployments hold at most ${MAX_SECRETS}.`,
850
+ 400
851
+ );
852
+ }
853
+ }
854
+
800
855
  /**
801
856
  * Rotate the deployment's pod credential. Returns the masked new key —
802
857
  * the raw key is injected into the pod on the next deploy, never
@@ -0,0 +1,111 @@
1
+ /**
2
+ * `agent/ab.ts` or `agent/ab/*.ts` plus `agent/ab.config.ts`: live A/B experiments.
3
+ */
4
+
5
+ import { basename, extname, join, relative } from "node:path";
6
+ import type { ABConfigFile } from "../../ab.js";
7
+ import type { DiscoveredAB } from "../../types.js";
8
+ import { type DiscoveryContext, displayPath } from "./context.js";
9
+ import {
10
+ findModuleFile,
11
+ isDirectory,
12
+ isModuleFile,
13
+ toPosix,
14
+ walkFiles,
15
+ } from "./fs.js";
16
+ import { importDefault } from "./modules.js";
17
+
18
+ export async function loadABs(
19
+ ctx: DiscoveryContext,
20
+ agentDir: string
21
+ ): Promise<DiscoveredAB[]> {
22
+ const abs: DiscoveredAB[] = [];
23
+ const seen = new Set<string>();
24
+
25
+ const single = await findModuleFile(agentDir, "ab");
26
+ if (single !== undefined) {
27
+ const definition = await importDefault(ctx, single, "ab");
28
+ if (definition !== undefined) {
29
+ const name = resolveABName(definition, "ab");
30
+ seen.add(name);
31
+ abs.push({
32
+ name,
33
+ definition: definition as DiscoveredAB["definition"],
34
+ });
35
+ }
36
+ }
37
+
38
+ const absDir = join(agentDir, "ab");
39
+ if (await isDirectory(absDir)) {
40
+ for (const filePath of await walkFiles(absDir)) {
41
+ if (!isModuleFile(basename(filePath))) {
42
+ continue;
43
+ }
44
+ const rel = toPosix(relative(absDir, filePath));
45
+ const stem = rel.slice(0, -extname(rel).length);
46
+ const definition = await importDefault(ctx, filePath, "ab");
47
+ if (definition === undefined) {
48
+ continue;
49
+ }
50
+ const name = resolveABName(definition, stem);
51
+ if (seen.has(name)) {
52
+ ctx.diagnostics.push({
53
+ severity: "error",
54
+ path: displayPath(ctx, filePath),
55
+ message: `Duplicate A/B experiment name ${JSON.stringify(name)}.`,
56
+ });
57
+ continue;
58
+ }
59
+ seen.add(name);
60
+ abs.push({
61
+ name,
62
+ definition: definition as DiscoveredAB["definition"],
63
+ });
64
+ }
65
+ }
66
+
67
+ return abs;
68
+ }
69
+
70
+ export async function loadABConfig(
71
+ ctx: DiscoveryContext,
72
+ agentDir: string
73
+ ): Promise<ABConfigFile | undefined> {
74
+ const path = await findModuleFile(agentDir, "ab.config");
75
+ if (path === undefined) {
76
+ return undefined;
77
+ }
78
+ try {
79
+ const mod = await ctx.importModule(path);
80
+ if (mod.default === null || typeof mod.default !== "object") {
81
+ ctx.diagnostics.push({
82
+ severity: "error",
83
+ path: displayPath(ctx, path),
84
+ message:
85
+ "ab.config.ts must default-export defineABConfig({ ... }) from @cursor/july/ab.",
86
+ });
87
+ return undefined;
88
+ }
89
+ return mod.default as ABConfigFile;
90
+ } catch (error) {
91
+ ctx.diagnostics.push({
92
+ severity: "error",
93
+ path: displayPath(ctx, path),
94
+ message: `Failed to load ab.config: ${error instanceof Error ? error.message : String(error)}`,
95
+ });
96
+ return undefined;
97
+ }
98
+ }
99
+
100
+ function resolveABName(definition: unknown, fallback: string): string {
101
+ if (
102
+ typeof definition === "object" &&
103
+ definition !== null &&
104
+ "name" in definition &&
105
+ typeof (definition as { name: unknown }).name === "string" &&
106
+ (definition as { name: string }).name.length > 0
107
+ ) {
108
+ return (definition as { name: string }).name;
109
+ }
110
+ return fallback;
111
+ }