@cursor/july 0.1.107 → 0.1.108

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 (302) hide show
  1. package/README.md +10 -5
  2. package/dist/bin/agent-serve.js +30 -8
  3. package/dist/channels/github/github-channel.js +8 -5
  4. package/dist/channels/github/types.d.ts +5 -1
  5. package/dist/channels/github/types.d.ts.map +1 -1
  6. package/dist/channels/origin/origin-channel.d.ts.map +1 -1
  7. package/dist/channels/origin/origin-channel.js +27 -13
  8. package/dist/channels/origin/types.d.ts +5 -1
  9. package/dist/channels/origin/types.d.ts.map +1 -1
  10. package/dist/channels.d.ts +45 -0
  11. package/dist/channels.d.ts.map +1 -1
  12. package/dist/channels.js +106 -7
  13. package/dist/connections.d.ts +2 -1
  14. package/dist/connections.d.ts.map +1 -1
  15. package/dist/connections.js +2 -1
  16. package/dist/docs/404.html +2 -2
  17. package/dist/docs/ab.html +4 -4
  18. package/dist/docs/assets/{app.CtuckIiL.js → app.BASKM3M4.js} +1 -1
  19. package/dist/docs/assets/chunks/@localSearchIndexroot.BHZYsNVi.js +1 -0
  20. package/dist/docs/assets/chunks/{VPLocalSearchBox.Bkkhnu8K.js → VPLocalSearchBox.BOKxlYGP.js} +1 -1
  21. package/dist/docs/assets/chunks/{theme.DhpIe0Pa.js → theme.DbDZW-zb.js} +2 -2
  22. package/dist/docs/assets/{deployment.md.MFPKqsqI.js → deployment.md.JenwuCCB.js} +4 -4
  23. package/dist/docs/assets/{deployment.md.MFPKqsqI.lean.js → deployment.md.JenwuCCB.lean.js} +1 -1
  24. package/dist/docs/assets/{evals.md.CbMoebP1.js → evals.md.C1ekS3k2.js} +1 -1
  25. package/dist/docs/assets/guides_cloud-agents.md.BsloyHdY.js +9 -0
  26. package/dist/docs/assets/{guides_cloud-agents.md.DS8RIjwx.lean.js → guides_cloud-agents.md.BsloyHdY.lean.js} +1 -1
  27. package/dist/docs/assets/{guides_github.md.c0gdGJ-D.js → guides_github.md.BH33UEBJ.js} +1 -1
  28. package/dist/docs/assets/{guides_grokbot-agents.md.DVqdhBKb.js → guides_grokbot-agents.md.DyV-WArv.js} +1 -1
  29. package/dist/docs/assets/guides_improve.md.BGVk32bK.js +14 -0
  30. package/dist/docs/assets/guides_improve.md.BGVk32bK.lean.js +1 -0
  31. package/dist/docs/assets/{guides_slack.md.9oHPye9o.js → guides_slack.md.D4RVMM4G.js} +3 -3
  32. package/dist/docs/assets/{guides_slack.md.9oHPye9o.lean.js → guides_slack.md.D4RVMM4G.lean.js} +1 -1
  33. package/dist/docs/assets/index.md.BjH1w2ZW.js +5 -0
  34. package/dist/docs/assets/{reference_agent-config.md.CHNpiyp4.js → reference_agent-config.md.CvoL6pof.js} +1 -1
  35. package/dist/docs/assets/{reference_cli.md.Dm67hd2D.js → reference_cli.md.Ca26u0Es.js} +6 -6
  36. package/dist/docs/assets/{reference_cli.md.Dm67hd2D.lean.js → reference_cli.md.Ca26u0Es.lean.js} +1 -1
  37. package/dist/docs/assets/{reference_connections.md.Di6jJAXF.js → reference_connections.md.BojkC6c5.js} +1 -1
  38. package/dist/docs/assets/{reference_extensions.md.CGmMLblt.js → reference_extensions.md.CPWt00ds.js} +1 -1
  39. package/dist/docs/assets/{scaffolding-agents.md.em43xlY1.js → scaffolding-agents.md.Kctn3OVb.js} +1 -1
  40. package/dist/docs/assets/{skills_create-agent.md.BVoWPcan.js → skills_create-agent.md.Q3h6Je-e.js} +1 -1
  41. package/dist/docs/assets/{skills_debug.md.CDbPhHfg.js → skills_debug.md.CVjCXMFF.js} +1 -1
  42. package/dist/docs/assets/{skills_debug.md.CDbPhHfg.lean.js → skills_debug.md.CVjCXMFF.lean.js} +1 -1
  43. package/dist/docs/assets/{skills_evals.md.723kpUmA.js → skills_evals.md.BhovOvrl.js} +1 -1
  44. package/dist/docs/assets/skills_framework-map.md.D-tFZhFS.js +1 -0
  45. package/dist/docs/assets/{skills_framework-map.md.haibFyoB.lean.js → skills_framework-map.md.D-tFZhFS.lean.js} +1 -1
  46. package/dist/docs/assets/{skills_github.md.D0JahM8c.js → skills_github.md.hgFX_oKY.js} +1 -1
  47. package/dist/docs/assets/troubleshooting.md.CYEAO9bM.js +1 -0
  48. package/dist/docs/building-with-agents.html +4 -4
  49. package/dist/docs/concepts.html +4 -4
  50. package/dist/docs/deployment.html +7 -7
  51. package/dist/docs/deployment.md +7 -2
  52. package/dist/docs/evals.html +6 -6
  53. package/dist/docs/evals.md +3 -2
  54. package/dist/docs/guides/agent-to-agent.html +4 -4
  55. package/dist/docs/guides/cloud-agents.html +6 -6
  56. package/dist/docs/guides/cloud-agents.md +4 -3
  57. package/dist/docs/guides/convert-automation.html +4 -4
  58. package/dist/docs/guides/github.html +5 -5
  59. package/dist/docs/guides/github.md +2 -1
  60. package/dist/docs/guides/grokbot-agents.html +6 -6
  61. package/dist/docs/guides/grokbot-agents.md +2 -2
  62. package/dist/docs/guides/human-in-the-loop.html +4 -4
  63. package/dist/docs/guides/improve.html +40 -0
  64. package/dist/docs/guides/improve.md +91 -0
  65. package/dist/docs/guides/mcp-oauth.html +4 -4
  66. package/dist/docs/guides/opentelemetry.html +5 -5
  67. package/dist/docs/guides/slack.html +6 -6
  68. package/dist/docs/guides/slack.md +2 -1
  69. package/dist/docs/guides/webhooks.html +4 -4
  70. package/dist/docs/hashmap.json +1 -1
  71. package/dist/docs/hillclimbing.html +4 -4
  72. package/dist/docs/index.html +6 -6
  73. package/dist/docs/index.md +4 -0
  74. package/dist/docs/llms-full.txt +158 -33
  75. package/dist/docs/llms.txt +1 -0
  76. package/dist/docs/quickstart.html +4 -4
  77. package/dist/docs/reference/agent-config.html +6 -6
  78. package/dist/docs/reference/agent-config.md +5 -2
  79. package/dist/docs/reference/artifacts.html +4 -4
  80. package/dist/docs/reference/channels.html +4 -4
  81. package/dist/docs/reference/cli.html +10 -10
  82. package/dist/docs/reference/cli.md +18 -11
  83. package/dist/docs/reference/connections.html +6 -6
  84. package/dist/docs/reference/connections.md +2 -1
  85. package/dist/docs/reference/extensions.html +6 -6
  86. package/dist/docs/reference/extensions.md +2 -0
  87. package/dist/docs/reference/hooks.html +4 -4
  88. package/dist/docs/reference/http-api.html +4 -4
  89. package/dist/docs/reference/instructions.html +4 -4
  90. package/dist/docs/reference/playground.html +4 -4
  91. package/dist/docs/reference/project-layout.html +4 -4
  92. package/dist/docs/reference/prompt.html +4 -4
  93. package/dist/docs/reference/result.html +4 -4
  94. package/dist/docs/reference/schedules.html +4 -4
  95. package/dist/docs/reference/sessions.html +4 -4
  96. package/dist/docs/reference/skills.html +4 -4
  97. package/dist/docs/reference/subagents.html +4 -4
  98. package/dist/docs/reference/tools.html +4 -4
  99. package/dist/docs/scaffolding-agents.html +5 -5
  100. package/dist/docs/scaffolding-agents.md +2 -1
  101. package/dist/docs/skills/ab.html +4 -4
  102. package/dist/docs/skills/create-agent.html +6 -6
  103. package/dist/docs/skills/create-agent.md +1 -1
  104. package/dist/docs/skills/debug.html +5 -5
  105. package/dist/docs/skills/debug.md +1 -1
  106. package/dist/docs/skills/evals.html +6 -6
  107. package/dist/docs/skills/evals.md +1 -1
  108. package/dist/docs/skills/framework-map.html +5 -5
  109. package/dist/docs/skills/framework-map.md +4 -2
  110. package/dist/docs/skills/github.html +6 -6
  111. package/dist/docs/skills/github.md +1 -1
  112. package/dist/docs/skills/hillclimb.html +4 -4
  113. package/dist/docs/skills/index.html +4 -4
  114. package/dist/docs/skills/mcp-auth.html +4 -4
  115. package/dist/docs/skills/otel.html +4 -4
  116. package/dist/docs/skills/setup-slack.html +4 -4
  117. package/dist/docs/storage.html +4 -4
  118. package/dist/docs/templates/agentic-owners.html +4 -4
  119. package/dist/docs/templates/agents-md.html +4 -4
  120. package/dist/docs/templates/code-wiki.html +4 -4
  121. package/dist/docs/templates/demo.html +4 -4
  122. package/dist/docs/templates/grokbot-agents.html +4 -4
  123. package/dist/docs/templates/pr-autofixer.html +4 -4
  124. package/dist/docs/templates/security-help.html +4 -4
  125. package/dist/docs/templates/security-reviewer.html +4 -4
  126. package/dist/docs/templates/triage.html +4 -4
  127. package/dist/docs/troubleshooting.html +5 -5
  128. package/dist/docs/troubleshooting.md +1 -1
  129. package/dist/extensions/improve/extension.d.ts +46 -0
  130. package/dist/extensions/improve/extension.d.ts.map +1 -0
  131. package/dist/extensions/improve/extension.js +41 -0
  132. package/dist/extensions/improve/skills/yourself.d.ts +4 -0
  133. package/dist/extensions/improve/skills/yourself.d.ts.map +1 -0
  134. package/dist/extensions/improve/skills/yourself.js +43 -0
  135. package/dist/internal/builtin-tools/artifacts.d.ts.map +1 -1
  136. package/dist/internal/builtin-tools/artifacts.js +2 -3
  137. package/dist/internal/channel-route-dispatch.d.ts +13 -0
  138. package/dist/internal/channel-route-dispatch.d.ts.map +1 -0
  139. package/dist/internal/channel-route-dispatch.js +62 -0
  140. package/dist/internal/channel-state.d.ts +17 -0
  141. package/dist/internal/channel-state.d.ts.map +1 -0
  142. package/dist/internal/channel-state.js +78 -0
  143. package/dist/internal/cli-ax.d.ts +7 -0
  144. package/dist/internal/cli-ax.d.ts.map +1 -1
  145. package/dist/internal/cli-ax.js +99 -1
  146. package/dist/internal/cli-cursor.d.ts.map +1 -1
  147. package/dist/internal/cli-cursor.js +2 -0
  148. package/dist/internal/cli-deploy.d.ts.map +1 -1
  149. package/dist/internal/cli-deploy.js +38 -14
  150. package/dist/internal/cli-mcp-oauth.d.ts.map +1 -1
  151. package/dist/internal/cli-mcp-oauth.js +15 -0
  152. package/dist/internal/cli-mcp.d.ts.map +1 -1
  153. package/dist/internal/cli-mcp.js +12 -0
  154. package/dist/internal/cli-slack.d.ts.map +1 -1
  155. package/dist/internal/cli-slack.js +8 -2
  156. package/dist/internal/cursor/credentials.d.ts +8 -2
  157. package/dist/internal/cursor/credentials.d.ts.map +1 -1
  158. package/dist/internal/cursor/credentials.js +27 -5
  159. package/dist/internal/deploy-client.d.ts +27 -0
  160. package/dist/internal/deploy-client.d.ts.map +1 -1
  161. package/dist/internal/deploy-client.js +32 -0
  162. package/dist/internal/deploy-manifest.d.ts +23 -0
  163. package/dist/internal/deploy-manifest.d.ts.map +1 -1
  164. package/dist/internal/deploy-manifest.js +84 -1
  165. package/dist/internal/describe-error.d.ts +1 -0
  166. package/dist/internal/describe-error.d.ts.map +1 -1
  167. package/dist/internal/describe-error.js +25 -0
  168. package/dist/internal/guest-network.d.ts +4 -10
  169. package/dist/internal/guest-network.d.ts.map +1 -1
  170. package/dist/internal/guest-network.js +42 -26
  171. package/dist/internal/hosted-admission-adapter.d.ts +2 -0
  172. package/dist/internal/hosted-admission-adapter.d.ts.map +1 -1
  173. package/dist/internal/hosted-catch-protocol.d.ts +51 -0
  174. package/dist/internal/hosted-catch-protocol.d.ts.map +1 -0
  175. package/dist/internal/hosted-catch-protocol.js +103 -0
  176. package/dist/internal/hosted-catch.d.ts +40 -0
  177. package/dist/internal/hosted-catch.d.ts.map +1 -0
  178. package/dist/internal/hosted-catch.js +149 -0
  179. package/dist/internal/hosted-delivery-protocol.d.ts +41 -0
  180. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
  181. package/dist/internal/hosted-delivery-protocol.js +249 -0
  182. package/dist/internal/hosted-delivery.d.ts +10 -1
  183. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  184. package/dist/internal/hosted-delivery.js +100 -22
  185. package/dist/internal/hosted-execution-diag.d.ts +4 -1
  186. package/dist/internal/hosted-execution-diag.d.ts.map +1 -1
  187. package/dist/internal/hosted-execution-diag.js +13 -4
  188. package/dist/internal/hosted-execution-flush.d.ts +3 -0
  189. package/dist/internal/hosted-execution-flush.d.ts.map +1 -1
  190. package/dist/internal/hosted-execution-flush.js +2 -4
  191. package/dist/internal/http-control-plane-session.d.ts +30 -0
  192. package/dist/internal/http-control-plane-session.d.ts.map +1 -0
  193. package/dist/internal/http-control-plane-session.js +83 -0
  194. package/dist/internal/legacy-command-guard.d.ts +22 -0
  195. package/dist/internal/legacy-command-guard.d.ts.map +1 -0
  196. package/dist/internal/legacy-command-guard.js +51 -0
  197. package/dist/internal/platform-timers.d.ts +7 -0
  198. package/dist/internal/platform-timers.d.ts.map +1 -1
  199. package/dist/internal/platform-timers.js +139 -0
  200. package/dist/internal/reminder-control-plane-protocol.d.ts +2 -0
  201. package/dist/internal/reminder-control-plane-protocol.d.ts.map +1 -1
  202. package/dist/internal/reminder-control-plane-protocol.js +9 -2
  203. package/dist/internal/reminder-runner.d.ts +8 -0
  204. package/dist/internal/reminder-runner.d.ts.map +1 -1
  205. package/dist/internal/reminder-runner.js +36 -9
  206. package/dist/internal/resolve-prod-target.d.ts +2 -0
  207. package/dist/internal/resolve-prod-target.d.ts.map +1 -1
  208. package/dist/internal/resolve-prod-target.js +13 -0
  209. package/dist/internal/sdk-runner.d.ts.map +1 -1
  210. package/dist/internal/sdk-runner.js +4 -3
  211. package/dist/internal/server.d.ts.map +1 -1
  212. package/dist/internal/server.js +57 -56
  213. package/dist/internal/session-engine.d.ts +2 -6
  214. package/dist/internal/session-engine.d.ts.map +1 -1
  215. package/dist/internal/session-engine.js +95 -67
  216. package/dist/playground/assets/{index-Bq2HpEQB.js → index-BMDqAeXu.js} +28 -28
  217. package/dist/playground/assets/index-LUgJoWdL.css +1 -0
  218. package/dist/playground/index.html +2 -2
  219. package/dist/storage-backends/cursor-hosted.d.ts +6 -0
  220. package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
  221. package/dist/storage-backends/cursor-hosted.js +29 -1
  222. package/dist/types.d.ts +33 -5
  223. package/dist/types.d.ts.map +1 -1
  224. package/docs/README.md +4 -0
  225. package/docs/deployment.md +7 -2
  226. package/docs/evals.md +3 -2
  227. package/docs/guides/cloud-agents.md +4 -3
  228. package/docs/guides/github.md +2 -1
  229. package/docs/guides/grokbot-agents.md +2 -2
  230. package/docs/guides/improve.md +96 -0
  231. package/docs/guides/slack.md +2 -1
  232. package/docs/reference/agent-config.md +5 -2
  233. package/docs/reference/cli.md +18 -11
  234. package/docs/reference/connections.md +2 -1
  235. package/docs/reference/extensions.md +2 -0
  236. package/docs/scaffolding-agents.md +2 -1
  237. package/docs/troubleshooting.md +1 -1
  238. package/package.json +8 -1
  239. package/skills/create-agent/SKILL.md +1 -1
  240. package/skills/debug/SKILL.md +1 -1
  241. package/skills/evals/SKILL.md +1 -1
  242. package/skills/framework-map/SKILL.md +4 -2
  243. package/skills/github/SKILL.md +1 -1
  244. package/src/bin/agent-serve.ts +27 -2
  245. package/src/channels/github/github-channel.ts +8 -8
  246. package/src/channels/github/types.ts +5 -0
  247. package/src/channels/origin/origin-channel.ts +29 -13
  248. package/src/channels/origin/types.ts +5 -0
  249. package/src/channels.ts +157 -10
  250. package/src/connections.ts +2 -1
  251. package/src/extensions/improve/extension.ts +70 -0
  252. package/src/extensions/improve/skills/yourself.ts +50 -0
  253. package/src/internal/builtin-tools/artifacts.ts +2 -3
  254. package/src/internal/channel-route-dispatch.ts +66 -0
  255. package/src/internal/channel-state.ts +96 -0
  256. package/src/internal/cli-ax.ts +110 -1
  257. package/src/internal/cli-cursor.ts +4 -1
  258. package/src/internal/cli-deploy.ts +50 -10
  259. package/src/internal/cli-mcp-oauth.ts +18 -0
  260. package/src/internal/cli-mcp.ts +11 -0
  261. package/src/internal/cli-slack.ts +15 -2
  262. package/src/internal/cursor/credentials.ts +35 -7
  263. package/src/internal/deploy-client.ts +54 -0
  264. package/src/internal/deploy-manifest.ts +115 -1
  265. package/src/internal/describe-error.ts +28 -0
  266. package/src/internal/guest-network.ts +43 -29
  267. package/src/internal/hosted-admission-adapter.ts +2 -0
  268. package/src/internal/hosted-catch-protocol.ts +130 -0
  269. package/src/internal/hosted-catch.ts +192 -0
  270. package/src/internal/hosted-delivery-protocol.ts +387 -0
  271. package/src/internal/hosted-delivery.ts +155 -22
  272. package/src/internal/hosted-execution-diag.ts +21 -3
  273. package/src/internal/hosted-execution-flush.ts +6 -3
  274. package/src/internal/http-control-plane-session.ts +104 -0
  275. package/src/internal/legacy-command-guard.ts +59 -0
  276. package/src/internal/platform-timers.ts +191 -0
  277. package/src/internal/reminder-control-plane-protocol.ts +15 -2
  278. package/src/internal/reminder-runner.ts +60 -9
  279. package/src/internal/resolve-prod-target.ts +15 -0
  280. package/src/internal/sdk-runner.ts +2 -1
  281. package/src/internal/server.ts +89 -79
  282. package/src/internal/session-engine.ts +141 -83
  283. package/src/storage-backends/cursor-hosted.ts +40 -1
  284. package/src/types.ts +39 -6
  285. package/dist/docs/assets/chunks/@localSearchIndexroot.DXXZxiMv.js +0 -1
  286. package/dist/docs/assets/guides_cloud-agents.md.DS8RIjwx.js +0 -9
  287. package/dist/docs/assets/index.md.BW_6tOgR.js +0 -5
  288. package/dist/docs/assets/skills_framework-map.md.haibFyoB.js +0 -1
  289. package/dist/docs/assets/troubleshooting.md.Cus_YZga.js +0 -1
  290. package/dist/playground/assets/index-CZKKNlmb.css +0 -1
  291. /package/dist/docs/assets/{evals.md.CbMoebP1.lean.js → evals.md.C1ekS3k2.lean.js} +0 -0
  292. /package/dist/docs/assets/{guides_github.md.c0gdGJ-D.lean.js → guides_github.md.BH33UEBJ.lean.js} +0 -0
  293. /package/dist/docs/assets/{guides_grokbot-agents.md.DVqdhBKb.lean.js → guides_grokbot-agents.md.DyV-WArv.lean.js} +0 -0
  294. /package/dist/docs/assets/{index.md.BW_6tOgR.lean.js → index.md.BjH1w2ZW.lean.js} +0 -0
  295. /package/dist/docs/assets/{reference_agent-config.md.CHNpiyp4.lean.js → reference_agent-config.md.CvoL6pof.lean.js} +0 -0
  296. /package/dist/docs/assets/{reference_connections.md.Di6jJAXF.lean.js → reference_connections.md.BojkC6c5.lean.js} +0 -0
  297. /package/dist/docs/assets/{reference_extensions.md.CGmMLblt.lean.js → reference_extensions.md.CPWt00ds.lean.js} +0 -0
  298. /package/dist/docs/assets/{scaffolding-agents.md.em43xlY1.lean.js → scaffolding-agents.md.Kctn3OVb.lean.js} +0 -0
  299. /package/dist/docs/assets/{skills_create-agent.md.BVoWPcan.lean.js → skills_create-agent.md.Q3h6Je-e.lean.js} +0 -0
  300. /package/dist/docs/assets/{skills_evals.md.723kpUmA.lean.js → skills_evals.md.BhovOvrl.lean.js} +0 -0
  301. /package/dist/docs/assets/{skills_github.md.D0JahM8c.lean.js → skills_github.md.hgFX_oKY.lean.js} +0 -0
  302. /package/dist/docs/assets/{troubleshooting.md.Cus_YZga.lean.js → troubleshooting.md.CYEAO9bM.lean.js} +0 -0
package/src/channels.ts CHANGED
@@ -64,9 +64,11 @@ export {
64
64
  } from "./channels/checks.js";
65
65
 
66
66
  import { Buffer } from "node:buffer";
67
- import { timingSafeEqual } from "node:crypto";
67
+ import { createHmac, timingSafeEqual } from "node:crypto";
68
68
  import { brandDefinition } from "./internal/brand.js";
69
69
  import { normalizeIdentity } from "./internal/continuation-identity.js";
70
+ import { attachCatchAdmission } from "./internal/hosted-catch.js";
71
+ import { attachHttpControlPlaneAdmission } from "./internal/http-control-plane-session.js";
70
72
  import { isLoopbackAddress, isLoopbackHostname } from "./internal/net.js";
71
73
  import type {
72
74
  AuthContext,
@@ -117,7 +119,16 @@ export type {
117
119
  export function defineChannel<TState = JsonValue>(
118
120
  config: ChannelConfig<TState>
119
121
  ): ChannelDefinition<TState> {
120
- return brandDefinition("channel", config);
122
+ const definition = brandDefinition("channel", config);
123
+ if (config.routes !== undefined && config.routes.length > 0) {
124
+ // Hosted: the control plane catches declared routes and replays them
125
+ // here. Provider packs attach their own admission afterwards.
126
+ attachCatchAdmission(
127
+ definition as ChannelDefinition<unknown>,
128
+ config.routes
129
+ );
130
+ }
131
+ return definition;
121
132
  }
122
133
 
123
134
  /**
@@ -127,13 +138,15 @@ export function defineChannel<TState = JsonValue>(
127
138
  export function httpChannel(
128
139
  config: HttpChannelConfig = {}
129
140
  ): HttpChannelDefinition {
130
- if (config.continuation !== undefined) {
131
- return brandDefinition("http-channel", {
132
- ...config,
133
- continuation: normalizeIdentity(config.continuation, "http"),
134
- });
135
- }
136
- return brandDefinition("http-channel", config);
141
+ const definition =
142
+ config.continuation !== undefined
143
+ ? brandDefinition("http-channel", {
144
+ ...config,
145
+ continuation: normalizeIdentity(config.continuation, "http"),
146
+ })
147
+ : brandDefinition("http-channel", config);
148
+ attachHttpControlPlaneAdmission(definition);
149
+ return definition;
137
150
  }
138
151
 
139
152
  // ============================================================================
@@ -432,7 +445,13 @@ export function publicEndpoint(): AuthPolicy {
432
445
  principalId: "anonymous",
433
446
  principalType: "user",
434
447
  });
435
- return Object.assign(policy, { [PUBLIC_ENDPOINT_MARKER]: true as const });
448
+ // On the v2 control plane this also makes the channel's routes catchable
449
+ // with handler-side verification (the v1 alias posture): the CP admits
450
+ // every request on a declared route and the handler rejects bad ones.
451
+ return markCatchAuth(
452
+ Object.assign(policy, { [PUBLIC_ENDPOINT_MARKER]: true as const }),
453
+ { kind: "public" }
454
+ );
436
455
  }
437
456
 
438
457
  /** True when a policy was created by {@link publicEndpoint}. */
@@ -443,3 +462,131 @@ export function isPublicEndpointPolicy(policy: AuthPolicy): boolean {
443
462
  ] === true
444
463
  );
445
464
  }
465
+
466
+ const CATCH_AUTH_MARKER = Symbol.for("agent-serve.catch-auth");
467
+
468
+ /**
469
+ * What `deploy` extracts from a {@link sharedSecretAuth} /
470
+ * {@link hmacSignatureAuth} policy into the manifest: the control plane runs
471
+ * the same check with the deployment secret of the same name before any
472
+ * compute starts. `secret` is a name, never a value.
473
+ */
474
+ export type CatchAuthDeclaration =
475
+ | { kind: "header"; header: string; secret: string }
476
+ | { kind: "hmac-sha256"; header: string; secret: string; prefix?: string }
477
+ /** `publicEndpoint()`: the handler verifies; the control plane only rate limits. */
478
+ | { kind: "public" };
479
+
480
+ function markCatchAuth(
481
+ policy: AuthPolicy,
482
+ declaration: CatchAuthDeclaration
483
+ ): AuthPolicy {
484
+ return Object.assign(policy, { [CATCH_AUTH_MARKER]: declaration });
485
+ }
486
+
487
+ /** The catch declaration a policy carries, if it is a catch-capable policy. */
488
+ export function catchAuthDeclaration(
489
+ policy: AuthPolicy
490
+ ): CatchAuthDeclaration | undefined {
491
+ const declaration = (policy as { [CATCH_AUTH_MARKER]?: unknown })[
492
+ CATCH_AUTH_MARKER
493
+ ];
494
+ return typeof declaration === "object" && declaration !== null
495
+ ? (declaration as CatchAuthDeclaration)
496
+ : undefined;
497
+ }
498
+
499
+ function presentedHeaderSecret(headerName: string, value: string): string {
500
+ if (
501
+ headerName === "authorization" &&
502
+ value.toLowerCase().startsWith("bearer ")
503
+ ) {
504
+ return value.slice("bearer ".length).trim();
505
+ }
506
+ return value.trim();
507
+ }
508
+
509
+ /**
510
+ * Admit requests whose `header` equals the secret named `secret` (an
511
+ * `Authorization: Bearer <secret>` header also matches). Locally the value
512
+ * is `process.env[secret]`; hosted, the deployment secret of that name. On
513
+ * Cursor hosting this ALSO declares the channel's routes reachable through
514
+ * the control-plane catch API, which runs the same comparison before any
515
+ * compute exists. An unset secret admits nothing.
516
+ */
517
+ export function sharedSecretAuth(options: {
518
+ header: string;
519
+ secret: string;
520
+ }): AuthPolicy {
521
+ const header = options.header.toLowerCase();
522
+ const policy: AuthPolicy = (request) => {
523
+ const expected = process.env[options.secret];
524
+ const presented = request.headers.get(header);
525
+ if (
526
+ expected === undefined ||
527
+ expected.length === 0 ||
528
+ presented === null ||
529
+ !constantTimeEquals(presentedHeaderSecret(header, presented), expected)
530
+ ) {
531
+ return null;
532
+ }
533
+ return {
534
+ authenticator: "shared-secret",
535
+ principalId: "webhook",
536
+ principalType: "service",
537
+ };
538
+ };
539
+ return markCatchAuth(policy, {
540
+ kind: "header",
541
+ header,
542
+ secret: options.secret,
543
+ });
544
+ }
545
+
546
+ /**
547
+ * Admit requests whose `header` carries the hex HMAC-SHA256 of the raw body
548
+ * under the secret named `secret` (optionally behind a literal `prefix`
549
+ * such as `sha256=`). Same local / hosted / catch semantics as
550
+ * {@link sharedSecretAuth}.
551
+ */
552
+ export function hmacSignatureAuth(options: {
553
+ header: string;
554
+ secret: string;
555
+ prefix?: string;
556
+ }): AuthPolicy {
557
+ const header = options.header.toLowerCase();
558
+ const prefix = options.prefix ?? "";
559
+ const policy: AuthPolicy = async (request) => {
560
+ const secret = process.env[options.secret];
561
+ const presented = request.headers.get(header)?.trim();
562
+ if (
563
+ secret === undefined ||
564
+ secret.length === 0 ||
565
+ presented === undefined ||
566
+ !presented.startsWith(prefix)
567
+ ) {
568
+ return null;
569
+ }
570
+ const body = Buffer.from(await request.clone().arrayBuffer());
571
+ const expected = createHmac("sha256", secret).update(body).digest("hex");
572
+ if (
573
+ !constantTimeEquals(
574
+ presented.slice(prefix.length).toLowerCase(),
575
+ expected
576
+ )
577
+ ) {
578
+ return null;
579
+ }
580
+ return {
581
+ authenticator: "hmac-signature",
582
+ principalId: "webhook",
583
+ principalType: "service",
584
+ };
585
+ };
586
+ return markCatchAuth(policy, {
587
+ kind: "hmac-sha256",
588
+ header,
589
+ secret: options.secret,
590
+ prefix: options.prefix,
591
+ });
592
+ }
@@ -65,7 +65,8 @@
65
65
  * executes **on the Cursor backend** with the account's stored OAuth
66
66
  * credentials, so the agent gets Linear / Notion / Slack / … tools with
67
67
  * zero token plumbing and no OAuth secrets on this host. Requires the host
68
- * to be signed in (`agent-sdk login` or `CURSOR_API_KEY`):
68
+ * to be signed in (`agent-sdk login`, `CURSOR_API_KEY`, or
69
+ * `CURSOR_SERVICE_ACCOUNT_KEY`):
69
70
  *
70
71
  * ```ts
71
72
  * // agent/mcp-connections/account.ts — every connected server (no allowlist)
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Self-improvement as an extension. An agent's behaviour is source in a
3
+ * repository, so changing how it behaves is a change to that source: a
4
+ * one-off Cursor cloud agent does the coding on a branch and opens a pull
5
+ * request, the agent that mounted this writes the brief and reports the
6
+ * pull request, and the tree it runs from is never edited.
7
+ *
8
+ * ```ts
9
+ * // agent/extensions/improve.ts
10
+ * import improve from "@cursor/july/extensions/improve";
11
+ *
12
+ * export default improve({
13
+ * repo: "https://github.com/acme/agents",
14
+ * path: "agents/concierge",
15
+ * });
16
+ * ```
17
+ *
18
+ * Contributes the `<namespace>__yourself` skill; mount it as `improve` so
19
+ * the skill reads `improve__yourself`. The coding goes through the
20
+ * cursor-cloud-agents extension, so mount that too, with `repo` among its
21
+ * `cloud.repos`. An agent whose own turns run on a cloud VM with the
22
+ * repository checked out needs no second mount: the skill has it work in
23
+ * that checkout.
24
+ */
25
+
26
+ import { z } from "zod";
27
+ import { defineExtension } from "../../extensions.js";
28
+ import type { Extension } from "../../types.js";
29
+
30
+ export interface ImproveOptions {
31
+ /** Repository that holds the agent's source. One of the cloud agents mount's `cloud.repos`. */
32
+ repo: string;
33
+ /** The agent's directory in the repository, as `agent-sdk deploy --path` names it. */
34
+ path: string;
35
+ /** Ref the deployment tracks: branches start there and pull requests target it. Defaults to `main`. */
36
+ ref?: string;
37
+ /** What a coding agent must know about this tree beyond the Agent SDK layout, one line each. */
38
+ notes?: string[];
39
+ /** Who deploys a merged change and when it is live. Defaults to "It takes effect at the next deploy." */
40
+ deploy?: string;
41
+ }
42
+
43
+ /** {@link ImproveOptions} with defaults applied. */
44
+ export interface ImproveConfig extends ImproveOptions {
45
+ ref: string;
46
+ notes: string[];
47
+ deploy: string;
48
+ }
49
+
50
+ const line = z.string().trim().min(1);
51
+
52
+ const improve: Extension<ImproveConfig, ImproveOptions> = defineExtension({
53
+ root: import.meta.dirname,
54
+ description:
55
+ "Change your own source through a one-off cloud agent and a pull request, never the running tree.",
56
+ config: z.object({
57
+ repo: z.string().url(),
58
+ path: z
59
+ .string()
60
+ .regex(
61
+ /^[^\s/]+(\/[^\s/]+)*$/,
62
+ "Expected a repository-relative path like agents/concierge"
63
+ ),
64
+ ref: line.default("main"),
65
+ notes: z.array(line).default([]),
66
+ deploy: line.default("It takes effect at the next deploy."),
67
+ }),
68
+ });
69
+
70
+ export default improve;
@@ -0,0 +1,50 @@
1
+ import { defineSkill } from "../../../skills.js";
2
+ import type { SkillDefinition } from "../../../types.js";
3
+ import extension from "../extension.js";
4
+
5
+ const { repo, path, ref, notes, deploy } = extension.config;
6
+
7
+ const treeNotes =
8
+ notes.length === 0
9
+ ? ""
10
+ : `\nAbout this tree in particular; copy these into the brief verbatim:\n\n${notes.map((note) => `- ${note}`).join("\n")}\n`;
11
+
12
+ const yourself: SkillDefinition = defineSkill({
13
+ description:
14
+ "Change your own source (instructions, skills, tools, channels, connections, model, deployment) through a one-off Cursor cloud agent and a pull request. Use whenever the ask is about how you yourself behave, including adding or editing a skill, so the change lands in the repository instead of the tree you happen to be running from.",
15
+ markdown: `# Improve yourself
16
+
17
+ You are the Agent SDK agent at \`${path}\` in ${repo}, deployed from \`${ref}\`. A change to how you behave is a change to that source, and it goes through the repository like any other change: a branch, a pull request, review, a deploy. Nothing about it is special except that people describe it in the second person.
18
+
19
+ ## What changes where
20
+
21
+ Under \`${path}/agent/\`:
22
+
23
+ - \`instructions.md\` is the always-on system prompt: identity, tool-choice rules, the output contract.
24
+ - \`skills/<name>.md\` is a procedure loaded on demand; a \`<name>/SKILL.md\` directory carries sibling files. The \`description\` frontmatter is the routing rule the model sees.
25
+ - \`tools/<name>.ts\` is typed, executable behaviour: anything that must be right every time.
26
+ - \`channels/\`, \`mcp-connections/\`, and \`host-connections/\` are the surfaces and connectors.
27
+ - \`agent.ts\` is the model, its parameters, and the runtime.
28
+ - \`extensions/<ns>.ts\` mounts an extension. This skill arrives through one.
29
+ ${treeNotes}
30
+ ## The change is made on a clean checkout
31
+
32
+ Never edit the tree you run from: it is a deployed copy of \`${path}\`, and nothing changed there lasts. The change is made on a clean checkout of ${repo} at \`${ref}\`. When your own turn runs on a cloud VM with that repository checked out, that VM is the checkout: branch there. Otherwise hand the coding to a one-off Cursor cloud agent through the cloud agents extension, with \`launch\` under its mount namespace, \`repo\` set to ${repo}, and \`starting_ref\` to \`${ref}\`. One agent per change; steer it with \`reply\` rather than launching another.
33
+
34
+ ## The brief
35
+
36
+ Whoever makes the change works from the same brief. For a cloud agent it is the whole handoff, because it cannot see this conversation:
37
+
38
+ - Who and why. A change to the source of the Agent SDK agent at \`${path}\`, asked for by the person in front of you: the change in their words, and what you know about why they want it.
39
+ - Where. Repository ${repo}, ref \`${ref}\`, directory \`${path}\`, the layout above, and the files you expect to change.
40
+ - How. Follow the repository's own conventions (its \`AGENTS.md\` files and rules along the paths touched). Keep the diff to the change. Run the checks the repository defines for \`${path}\`. Open a pull request against \`${ref}\`; never merge it.
41
+ - Report. The pull request URL, what changed, what was verified and how, and anything left unverified.
42
+
43
+ ## Report
44
+
45
+ If you launched a cloud agent, give the person its URL with the full id, read its report with \`dump\` (\`get\` for status), and read the pull request before repeating its claims. Report the pull request, not that you delegated.
46
+
47
+ A merged pull request changes nothing by itself. ${deploy} Never say you have already changed yourself. Editing your own source is still an edit: do it when asked, and stop at the pull request. Deploying is a separate authorization.`,
48
+ });
49
+
50
+ export default yourself;
@@ -30,7 +30,7 @@ function kindVariant(name: string, schema: z.ZodType | undefined) {
30
30
  .min(1)
31
31
  .optional()
32
32
  .describe(
33
- "Stable upsert key: tagging the same key again updates the existing record instead of creating a new one."
33
+ "Stable key, unique across kinds. Reusing it replaces that record instead of adding a new one."
34
34
  ),
35
35
  });
36
36
  }
@@ -47,10 +47,9 @@ export function tagArtifactTool(config: ArtifactsConfig): ToolDefinition {
47
47
  );
48
48
  }
49
49
  const description = [
50
- "Tag a durable artifact: a record of a notable output you produced, kept across sessions and listed for the people supervising this agent. Tag one whenever you finish something worth surfacing durably.",
50
+ "Tag a finished output as an artifact. Artifacts persist across sessions and are listed for the people supervising this agent.",
51
51
  "Kinds:",
52
52
  ...kinds.map(([name, kind]) => `- ${name}: ${kind.description}`),
53
- "Same `key` upserts: tagging it again updates that record — use a stable key when re-tagging the same underlying thing (e.g. the same PR URL).",
54
53
  ].join("\n");
55
54
  return defineTool({
56
55
  description,
@@ -0,0 +1,66 @@
1
+ import type { ChannelHandlerArgs, ChannelRoute } from "../types.js";
2
+ import { jsonResponse } from "./http-channel.js";
3
+ import { validateToolInput } from "./json-schema.js";
4
+
5
+ /**
6
+ * Run one authored channel route: validate the declared Zod query / body
7
+ * schemas onto `handlerArgs`, then call the handler. Shared by the local
8
+ * router mount and hosted catch replay so a caught request meets exactly
9
+ * the same schema gate as a direct one.
10
+ */
11
+ export async function invokeChannelRoute(input: {
12
+ route: ChannelRoute;
13
+ request: Request;
14
+ handlerArgs: ChannelHandlerArgs;
15
+ }): Promise<Response> {
16
+ const { route, handlerArgs } = input;
17
+ let request = input.request;
18
+
19
+ if (route.querySchema !== undefined) {
20
+ const rawQuery = Object.fromEntries(
21
+ new URL(request.url).searchParams.entries()
22
+ );
23
+ const queryValidation = validateToolInput(route.querySchema, rawQuery);
24
+ if (!queryValidation.ok) {
25
+ return jsonResponse({ error: queryValidation.message }, { status: 400 });
26
+ }
27
+ handlerArgs.query = queryValidation.value;
28
+ }
29
+
30
+ if (route.bodySchema !== undefined) {
31
+ // Buffer once so handlers that need the raw body (e.g. GitHub HMAC) can
32
+ // still read `request.text()` / `request.json()`.
33
+ let bodyText: string;
34
+ try {
35
+ bodyText = await request.text();
36
+ } catch {
37
+ return jsonResponse(
38
+ { error: "Failed to read request body" },
39
+ { status: 400 }
40
+ );
41
+ }
42
+ let rawBody: unknown;
43
+ try {
44
+ rawBody = bodyText === "" ? {} : JSON.parse(bodyText);
45
+ } catch {
46
+ return jsonResponse(
47
+ { error: "Request body must be valid JSON" },
48
+ { status: 400 }
49
+ );
50
+ }
51
+ const bodyValidation = validateToolInput(route.bodySchema, rawBody);
52
+ if (!bodyValidation.ok) {
53
+ return jsonResponse({ error: bodyValidation.message }, { status: 400 });
54
+ }
55
+ handlerArgs.body = bodyValidation.value;
56
+ request = new Request(request.url, {
57
+ method: request.method,
58
+ headers: request.headers,
59
+ body: bodyText === "" ? undefined : bodyText,
60
+ // node: undici / fetch may require duplex for streamed bodies;
61
+ // a string body does not.
62
+ });
63
+ }
64
+
65
+ return route.handler(request, handlerArgs);
66
+ }
@@ -0,0 +1,96 @@
1
+ import { isDeepStrictEqual } from "node:util";
2
+ import type { JsonValue } from "../types.js";
3
+
4
+ type JsonRecord = Record<string, JsonValue>;
5
+
6
+ function asRecord(value: JsonValue | undefined): JsonRecord | undefined {
7
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
8
+ return undefined;
9
+ }
10
+ return value as JsonRecord;
11
+ }
12
+
13
+ /**
14
+ * Shallow-merge a wake patch into durable channel state. Null / undefined
15
+ * patch values leave the existing key alone so sticky fields survive.
16
+ */
17
+ export function mergeChannelStateSkipNull(
18
+ current: JsonValue | undefined,
19
+ patch: JsonValue | undefined
20
+ ): JsonValue | undefined {
21
+ if (patch === undefined) {
22
+ return current;
23
+ }
24
+ const currentRecord = asRecord(current);
25
+ const patchRecord = asRecord(patch);
26
+ if (currentRecord === undefined || patchRecord === undefined) {
27
+ return structuredClone(patch);
28
+ }
29
+ const merged = { ...currentRecord };
30
+ for (const [key, value] of Object.entries(patchRecord)) {
31
+ if (value !== null && value !== undefined) {
32
+ merged[key] = value;
33
+ }
34
+ }
35
+ return merged;
36
+ }
37
+
38
+ /**
39
+ * Apply handler mutations made against a turn snapshot without reverting
40
+ * unchanged fields refreshed by a later delivery. At a changed path, objects
41
+ * merge recursively, arrays and scalars replace, and deletions win.
42
+ */
43
+ export function mergeChannelStateMutation(args: {
44
+ current: JsonValue | undefined;
45
+ before: JsonValue;
46
+ after: JsonValue;
47
+ }): JsonValue | undefined {
48
+ const { current, before, after } = args;
49
+ if (isDeepStrictEqual(before, after)) {
50
+ return current;
51
+ }
52
+ const currentRecord = asRecord(current);
53
+ const beforeRecord = asRecord(before);
54
+ const afterRecord = asRecord(after);
55
+ if (
56
+ currentRecord === undefined ||
57
+ beforeRecord === undefined ||
58
+ afterRecord === undefined
59
+ ) {
60
+ return structuredClone(after);
61
+ }
62
+
63
+ const merged = structuredClone(currentRecord);
64
+ const keys = new Set([
65
+ ...Object.keys(beforeRecord),
66
+ ...Object.keys(afterRecord),
67
+ ]);
68
+ for (const key of keys) {
69
+ const hadBefore = Object.hasOwn(beforeRecord, key);
70
+ const hasAfter = Object.hasOwn(afterRecord, key);
71
+ if (
72
+ hadBefore &&
73
+ hasAfter &&
74
+ isDeepStrictEqual(beforeRecord[key], afterRecord[key])
75
+ ) {
76
+ continue;
77
+ }
78
+ if (!hasAfter) {
79
+ delete merged[key];
80
+ continue;
81
+ }
82
+ const currentValue = merged[key];
83
+ const afterValue = afterRecord[key]!;
84
+ merged[key] =
85
+ hadBefore ||
86
+ (asRecord(currentValue) !== undefined &&
87
+ asRecord(afterValue) !== undefined)
88
+ ? (mergeChannelStateMutation({
89
+ current: currentValue,
90
+ before: hadBefore ? beforeRecord[key]! : {},
91
+ after: afterValue,
92
+ }) as JsonValue)
93
+ : structuredClone(afterValue);
94
+ }
95
+ return merged;
96
+ }
@@ -23,6 +23,7 @@ import { lookupSessionContinuation, runChat } from "./chat-client.js";
23
23
  import { ensureCursorLogin } from "./cli-cursor.js";
24
24
  import { resolveDeployAuth } from "./cli-deploy.js";
25
25
  import { resolveApiKey } from "./cursor/credentials.js";
26
+ import { DeployApiError } from "./deploy-client.js";
26
27
  import { CLI_COMMAND_NAME, PACKAGE_NAME } from "./distribution.js";
27
28
  import {
28
29
  discoverEvals,
@@ -53,6 +54,7 @@ import {
53
54
  resolveTemplate,
54
55
  } from "./init-project.js";
55
56
  import { offerInstallCursorSkills } from "./install-cursor-skills.js";
57
+ import { rejectV2ForLegacyCommand } from "./legacy-command-guard.js";
56
58
  import { runLogsTail, sanitizeCustomerError } from "./logs-client.js";
57
59
  import { mapPool } from "./map-pool.js";
58
60
  import { openBrowser } from "./open-browser.js";
@@ -189,6 +191,13 @@ export interface AxCliOptions {
189
191
  resume?: boolean;
190
192
  /** Abort signal (tests / programmatic stop of `playground` proxy). */
191
193
  signal?: AbortSignal;
194
+ /**
195
+ * `run --prod` / `session --prod --message`: hosted v2 session start on
196
+ * the agentsdk control plane. `--dry-run` marks the turn non-mutating;
197
+ * `--as-of` freezes the session clock at a timezone-bearing instant.
198
+ */
199
+ dryRun?: boolean;
200
+ asOf?: string;
192
201
  }
193
202
 
194
203
  export interface ResolvedAgentTarget {
@@ -594,6 +603,15 @@ export async function cmdChat(options: AxCliOptions): Promise<number> {
594
603
  }
595
604
 
596
605
  export async function cmdRun(options: AxCliOptions): Promise<number> {
606
+ // Only a v2-shaped request tries the control plane; every v1 `run --prod`
607
+ // form (multi-turn, continuation token, local session id, --url) keeps its
608
+ // engine-alias path untouched.
609
+ if (options.prod === true && hostedSessionRejection(options) === undefined) {
610
+ const started = await cmdHostedSession(options);
611
+ if (started !== "fallback") {
612
+ return started;
613
+ }
614
+ }
597
615
  const messages = options.messages ?? [];
598
616
  if (messages.length === 0) {
599
617
  die("Provide --message (repeatable) or --messages-file");
@@ -703,6 +721,74 @@ export async function cmdRun(options: AxCliOptions): Promise<number> {
703
721
  }
704
722
  }
705
723
 
724
+ const HOSTED_SESSION_ID_RE = /^ses_[a-f0-9]{24}$/;
725
+
726
+ /**
727
+ * Hosted v2 session start: POST the agentsdk control plane, which hands the
728
+ * wake to Temporal (no resident engine, no `/engine/*` alias). `--session
729
+ * ses_…` resumes that exact session; there is no continuation token on
730
+ * this path. A 404 means the slug is not a v2 control-plane deployment, so
731
+ * `run --prod` falls back to the v1 engine alias.
732
+ */
733
+ /** Why these options cannot be a hosted v2 session start, if they cannot. */
734
+ function hostedSessionRejection(options: AxCliOptions): string | undefined {
735
+ if (options.url !== undefined) {
736
+ return "--prod session start talks to the agentsdk control plane; do not pass --url";
737
+ }
738
+ const messages = options.messages ?? [];
739
+ if (messages.length !== 1 || messages[0]?.trim() === "") {
740
+ return "Provide exactly one --message (the wake). Multi-turn runs are local-only.";
741
+ }
742
+ if (trimNonEmpty(options.continuationToken) !== undefined) {
743
+ return "--continuation-token is not a hosted v2 identity; pass --session ses_… to resume a session";
744
+ }
745
+ const sessionId = trimNonEmpty(options.sessionId);
746
+ if (sessionId !== undefined && !HOSTED_SESSION_ID_RE.test(sessionId)) {
747
+ return `--session must be a hosted session id (ses_…), got ${sessionId}`;
748
+ }
749
+ return undefined;
750
+ }
751
+
752
+ async function cmdHostedSession(
753
+ options: AxCliOptions
754
+ ): Promise<number | "fallback"> {
755
+ const rejection = hostedSessionRejection(options);
756
+ if (rejection !== undefined) {
757
+ die(rejection);
758
+ }
759
+ const messages = options.messages ?? [];
760
+ const sessionId = trimNonEmpty(options.sessionId);
761
+ const auth = await resolveDeployAuth({
762
+ team: options.team,
763
+ apiKey: options.apiKey,
764
+ fetchImpl: options.fetchImpl,
765
+ });
766
+ if (typeof auth === "number") {
767
+ return auth;
768
+ }
769
+ const slug = resolveProdSlug(options);
770
+ try {
771
+ const accepted = await auth.client.startSession({
772
+ teamId: auth.teamId,
773
+ slug,
774
+ message: messages[0]!.trim(),
775
+ sessionId,
776
+ dryRun: options.dryRun,
777
+ asOf: options.asOf,
778
+ });
779
+ console.log(JSON.stringify(accepted, null, 2));
780
+ return 0;
781
+ } catch (error) {
782
+ if (error instanceof DeployApiError && error.status === 404) {
783
+ return "fallback";
784
+ }
785
+ process.stderr.write(
786
+ `${error instanceof Error ? error.message : String(error)}\n`
787
+ );
788
+ return 1;
789
+ }
790
+ }
791
+
706
792
  /**
707
793
  * `agent-sdk call <tool>` — deterministic tool invocation over
708
794
  * `POST /v1/tools/:toolName` (ephemeral local server unless --url).
@@ -1727,6 +1813,11 @@ export async function cmdLogs(options: AxCliOptions): Promise<number> {
1727
1813
  if (typeof auth === "number") {
1728
1814
  return auth;
1729
1815
  }
1816
+ await rejectV2ForLegacyCommand({
1817
+ client: auth.client,
1818
+ teamId: auth.teamId,
1819
+ slug,
1820
+ });
1730
1821
  await runLogsTail({
1731
1822
  prod: true,
1732
1823
  dir: options.dir,
@@ -1750,6 +1841,7 @@ export async function cmdLogs(options: AxCliOptions): Promise<number> {
1750
1841
  apiKey: options.apiKey,
1751
1842
  fetchImpl: options.fetchImpl,
1752
1843
  err: () => {},
1844
+ skipLegacyArchitectureCheck: true,
1753
1845
  });
1754
1846
  return { agentUrl: target.agentUrl, headers: target.headers };
1755
1847
  },
@@ -1864,9 +1956,26 @@ export async function cmdSession(
1864
1956
  sessionId: string | undefined,
1865
1957
  options: AxCliOptions
1866
1958
  ): Promise<number> {
1959
+ if (options.prod === true && (options.messages?.length ?? 0) > 0) {
1960
+ // `session --prod [ses_…] --message` is the same hosted start as
1961
+ // `run --prod`, with the positional id as the session to resume. Unlike
1962
+ // `run`, a 404 is an error here: this form is explicitly v2.
1963
+ const started = await cmdHostedSession({
1964
+ ...options,
1965
+ sessionId: trimNonEmpty(sessionId) ?? options.sessionId,
1966
+ });
1967
+ if (started === "fallback") {
1968
+ process.stderr.write(
1969
+ `Hosted session start returned 404 for slug ${resolveProdSlug(options)}: deploy a running AgentSDK v2 agent, or use \`${CLI_COMMAND_NAME} run --prod\` (falls back to the v1 engine).\n`
1970
+ );
1971
+ return 1;
1972
+ }
1973
+ return started;
1974
+ }
1867
1975
  if (sessionId === undefined || sessionId.trim() === "") {
1868
1976
  process.stderr.write(
1869
- `Usage: ${CLI_COMMAND_NAME} session <sessionId> [--url | --prod] [--json | --text | --events] [--out <file.ndjson>]\n`
1977
+ `Usage: ${CLI_COMMAND_NAME} session <sessionId> [--url | --prod] [--json | --text | --events] [--out <file.ndjson>]\n` +
1978
+ ` or: ${CLI_COMMAND_NAME} session --prod [<sessionId>] --slug <slug> --message "…" [--dry-run] [--as-of <instant>]\n`
1870
1979
  );
1871
1980
  return 2;
1872
1981
  }