@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
@@ -3,6 +3,7 @@ import type {
3
3
  AuthPolicy,
4
4
  ChannelHandlerArgs,
5
5
  SendMessageOptions,
6
+ TurnOutcome,
6
7
  } from "../types.js";
7
8
  import { dispatchOutcome } from "./channel-dispatch.js";
8
9
  import {
@@ -20,7 +21,6 @@ import {
20
21
  GuestNetworkUnavailableError,
21
22
  type GuestNetworkWaitResult,
22
23
  type GuestNetworkWaitStats,
23
- isQuietGuestConnectStallMessage,
24
24
  waitForGuestNetworkReady,
25
25
  } from "./guest-network.js";
26
26
  import {
@@ -40,10 +40,13 @@ import {
40
40
  HOSTED_GUEST_RETRY_TRANSIENT,
41
41
  type HostedAdmission,
42
42
  type HostedGuestRetryDisposition,
43
+ type HostedReminderFireDescriptorPayload,
44
+ hostedFailureClassification,
43
45
  hostedGuestErrorResponse,
44
46
  isHostedReminderAdmission,
45
47
  parseHostedAdmission,
46
48
  parseHostedExecution,
49
+ parseHostedReminderFireDescriptorPayload,
47
50
  parseHostedReminderFirePayload,
48
51
  } from "./hosted-delivery-protocol.js";
49
52
  import {
@@ -63,7 +66,10 @@ import {
63
66
  ReminderValidationError,
64
67
  UnknownReminderError,
65
68
  } from "./reminder-runner.js";
66
- import { statusForThrownRequestError } from "./request-error-status.js";
69
+ import {
70
+ mapThrownRequestError,
71
+ statusForThrownRequestError,
72
+ } from "./request-error-status.js";
67
73
  import type { Router } from "./router.js";
68
74
  import type { SessionRunExecutionWrite } from "./session-run-log.js";
69
75
 
@@ -170,6 +176,31 @@ function nonRetryableRejection(error: unknown): AdmissionDispatch | undefined {
170
176
  };
171
177
  }
172
178
 
179
+ /**
180
+ * Prefer the shared throw → HTTP mapper (guest network / connect stall /
181
+ * session busy / …) before collapsing into agent_admission_threw or
182
+ * background_dispatch_failed. Those agent codes otherwise hide typed
183
+ * transient failures that the outer handleRequest boundary never sees.
184
+ */
185
+ function mappedAdmissionFailure(error: unknown): AdmissionDispatch | undefined {
186
+ const rejected = nonRetryableRejection(error);
187
+ if (rejected !== undefined) {
188
+ return rejected;
189
+ }
190
+ const mapped = mapThrownRequestError(error);
191
+ if (mapped === undefined) {
192
+ return undefined;
193
+ }
194
+ return {
195
+ response: hostedGuestErrorResponse({
196
+ status: mapped.status,
197
+ error: mapped.code,
198
+ retry: mapped.retry,
199
+ message: boundedMessage(mapped.message),
200
+ }),
201
+ };
202
+ }
203
+
173
204
  /**
174
205
  * Run authored admission without creating a framework session. Authored
175
206
  * `task` callbacks execute as sessionless work; the first `send` is captured
@@ -210,9 +241,57 @@ async function dispatchHostedReminderAdmission(
210
241
  outcome: "fired" | "noop";
211
242
  reason?: string;
212
243
  }>;
244
+ /**
245
+ * Architecture v2: execute an immutable CP descriptor and apply the
246
+ * structured outcome. Must not GET/PUT reminder lifecycle documents.
247
+ */
248
+ executeReminderDescriptor?(
249
+ descriptor: HostedReminderFireDescriptorPayload
250
+ ): Promise<{
251
+ reminderId: string;
252
+ outcome: "fired" | "noop";
253
+ reason?: string;
254
+ }>;
213
255
  },
214
256
  delivery: HostedAdmission
215
257
  ): Promise<Response> {
258
+ const descriptor = parseHostedReminderFireDescriptorPayload(delivery.payload);
259
+ if (descriptor !== undefined) {
260
+ if (input.executeReminderDescriptor === undefined) {
261
+ return transientHostedError(
262
+ 503,
263
+ "reminder_dispatch_unavailable",
264
+ "This guest has no reminder CP executor wired for hosted admission."
265
+ );
266
+ }
267
+ try {
268
+ const result = await input.executeReminderDescriptor(descriptor);
269
+ const outcome = result.outcome === "noop" ? "skip" : "task";
270
+ return Response.json({
271
+ ok: true,
272
+ v: HOSTED_DELIVERY_PROTOCOL_VERSION,
273
+ outcome,
274
+ });
275
+ } catch (error) {
276
+ if (error instanceof UnknownReminderError) {
277
+ return terminalHostedError(
278
+ 404,
279
+ "unknown_reminder",
280
+ boundedMessage(error.message)
281
+ );
282
+ }
283
+ if (error instanceof ReminderValidationError) {
284
+ return terminalHostedError(
285
+ 400,
286
+ "invalid_reminder",
287
+ boundedMessage(error.message)
288
+ );
289
+ }
290
+ // Transient CP apply/fetch failures must remain retryable.
291
+ throw error;
292
+ }
293
+ }
294
+
216
295
  if (input.fireReminder === undefined) {
217
296
  return transientHostedError(
218
297
  503,
@@ -225,7 +304,7 @@ async function dispatchHostedReminderAdmission(
225
304
  return terminalHostedError(
226
305
  400,
227
306
  "invalid_reminder_payload",
228
- "Expected reminder payload { reminderId, fireCount }."
307
+ "Expected reminder descriptor or legacy payload { reminderId, fireCount }."
229
308
  );
230
309
  }
231
310
  try {
@@ -281,17 +360,24 @@ async function runAdmission(
281
360
  let dispatched: Response;
282
361
  try {
283
362
  dispatched = await adapter.dispatch({
363
+ channelId: input.delivery.channelId,
284
364
  eventType: input.delivery.eventType,
285
365
  payload: input.delivery.payload,
286
366
  deliveryId: input.delivery.deliveryId,
287
367
  args,
288
368
  });
289
369
  } catch (error) {
290
- const rejected = nonRetryableRejection(error);
291
- if (rejected !== undefined) {
292
- return rejected;
370
+ const mapped = mappedAdmissionFailure(error);
371
+ if (mapped !== undefined) {
372
+ return mapped;
293
373
  }
294
- throw error;
374
+ return {
375
+ response: terminalHostedError(
376
+ 500,
377
+ "agent_admission_threw",
378
+ boundedMessage(error instanceof Error ? error.message : String(error))
379
+ ),
380
+ };
295
381
  }
296
382
  if (!dispatched.ok) {
297
383
  return {
@@ -305,9 +391,9 @@ async function runAdmission(
305
391
  try {
306
392
  await Promise.all(background);
307
393
  } catch (error) {
308
- const rejected = nonRetryableRejection(error);
309
- if (rejected !== undefined) {
310
- return rejected;
394
+ const mapped = mappedAdmissionFailure(error);
395
+ if (mapped !== undefined) {
396
+ return mapped;
311
397
  }
312
398
  return {
313
399
  response: terminalHostedError(
@@ -436,6 +522,17 @@ export function registerHostedDeliveryRoute(input: {
436
522
  outcome: "fired" | "noop";
437
523
  reason?: string;
438
524
  }>;
525
+ /**
526
+ * Architecture v2: execute an immutable CP fire descriptor and apply the
527
+ * structured outcome via the hosted ReminderControlPlane client.
528
+ */
529
+ executeReminderDescriptor?(
530
+ descriptor: HostedReminderFireDescriptorPayload
531
+ ): Promise<{
532
+ reminderId: string;
533
+ outcome: "fired" | "noop";
534
+ reason?: string;
535
+ }>;
439
536
  /**
440
537
  * Await the session's durable mirror (dispatch chain + storage queue)
441
538
  * before the execution reply: the control plane may park the pod the
@@ -735,8 +832,13 @@ export function registerHostedDeliveryRoute(input: {
735
832
  abortReason?:
736
833
  | ReturnType<typeof abortReasonFromTurnStatus>
737
834
  | "execute_throw";
835
+ failureCode?: string;
738
836
  error?: unknown;
739
837
  }): Promise<void> => {
838
+ const classification =
839
+ fields.failureCode === undefined
840
+ ? undefined
841
+ : hostedFailureClassification(fields.failureCode);
740
842
  await flushHostedExecutionRecord(sinks, {
741
843
  executionId,
742
844
  sessionPublicId: execution.sessionPublicId,
@@ -752,6 +854,8 @@ export function registerHostedDeliveryRoute(input: {
752
854
  ...(fields.abortReason === undefined
753
855
  ? {}
754
856
  : { abortReason: fields.abortReason }),
857
+ failureCode: fields.failureCode,
858
+ classification,
755
859
  ...(fields.error === undefined ? {} : { error: fields.error }),
756
860
  });
757
861
  };
@@ -788,28 +892,30 @@ export function registerHostedDeliveryRoute(input: {
788
892
  session.id,
789
893
  execution.sessionPublicId
790
894
  );
895
+ const hostedFailure =
896
+ outcome.status === "finished"
897
+ ? undefined
898
+ : hostedFailureForUnfinishedTurn(outcome);
791
899
  await writeDiag({
792
900
  sessionId: session.id,
793
901
  turnStatus: outcome.status,
794
902
  message: outcome.errorMessage,
795
903
  abortReason: abortReasonFromTurnStatus(
796
904
  outcome.status,
797
- outcome.errorMessage
905
+ outcome.cancellationReason
798
906
  ),
907
+ failureCode: hostedFailure?.error,
799
908
  });
800
- if (outcome.status !== "finished") {
801
- // waitForCompletion resolves (does not throw) on a quiet
802
- // Connect abort. Map that to guest_connect_stalled so TAS
803
- // retries the same pod. Real runner failures stay turn_failed.
804
- const hostedFailure = hostedFailureForUnfinishedTurn(
805
- outcome.errorMessage
806
- );
909
+ if (hostedFailure !== undefined) {
807
910
  return {
808
911
  status: 503,
809
912
  body: {
810
913
  ok: false,
811
914
  error: hostedFailure.error,
812
915
  retry: hostedFailure.retry,
916
+ classification: hostedFailureClassification(
917
+ hostedFailure.error
918
+ ),
813
919
  turnStatus: outcome.status,
814
920
  message: outcome.errorMessage,
815
921
  },
@@ -834,6 +940,7 @@ export function registerHostedDeliveryRoute(input: {
834
940
  turnStatus: "error",
835
941
  message: error instanceof Error ? error.message : String(error),
836
942
  abortReason: "execute_throw",
943
+ failureCode: "internal_error",
837
944
  error,
838
945
  });
839
946
  throw error;
@@ -862,19 +969,45 @@ function evictHostedSdkSessions(
862
969
  }
863
970
  }
864
971
 
865
- function hostedFailureForUnfinishedTurn(errorMessage: string | undefined): {
866
- error: typeof GUEST_CONNECT_STALLED | "turn_failed";
972
+ const TRANSIENT_TURN_ERROR_CODES: ReadonlySet<string> = new Set([
973
+ "ABORT_ERR",
974
+ "UND_ERR_BODY_TIMEOUT",
975
+ "UND_ERR_HEADERS_TIMEOUT",
976
+ "canceled",
977
+ "unavailable",
978
+ "unknown",
979
+ ]);
980
+
981
+ function hostedFailureForUnfinishedTurn(outcome: TurnOutcome): {
982
+ error:
983
+ | typeof GUEST_CONNECT_STALLED
984
+ | "agent_dependency_failed"
985
+ | "turn_cancelled"
986
+ | "turn_failed";
867
987
  retry: HostedGuestRetryDisposition;
868
988
  } {
989
+ if (outcome.errorCode === "agent_dependency_failed") {
990
+ return {
991
+ error: "agent_dependency_failed",
992
+ retry: HOSTED_GUEST_RETRY_TERMINAL,
993
+ };
994
+ }
869
995
  if (
870
- errorMessage !== undefined &&
871
- isQuietGuestConnectStallMessage(errorMessage)
996
+ outcome.status === "error" &&
997
+ outcome.errorCode !== undefined &&
998
+ TRANSIENT_TURN_ERROR_CODES.has(outcome.errorCode)
872
999
  ) {
873
1000
  return {
874
1001
  error: GUEST_CONNECT_STALLED,
875
1002
  retry: HOSTED_GUEST_RETRY_TRANSIENT,
876
1003
  };
877
1004
  }
1005
+ if (outcome.status === "cancelled") {
1006
+ return {
1007
+ error: "turn_cancelled",
1008
+ retry: HOSTED_GUEST_RETRY_TERMINAL,
1009
+ };
1010
+ }
878
1011
  return { error: "turn_failed", retry: HOSTED_GUEST_RETRY_TERMINAL };
879
1012
  }
880
1013
 
@@ -8,7 +8,11 @@ import { createHash, randomBytes } from "node:crypto";
8
8
  import { mkdir, rename, unlink, writeFile } from "node:fs/promises";
9
9
  import { join } from "node:path";
10
10
 
11
- import { HOSTED_EXECUTION_DIAG_FILENAME } from "./hosted-delivery-protocol.js";
11
+ import {
12
+ HOSTED_EXECUTION_DIAG_FILENAME,
13
+ type HostedFailureClassification,
14
+ parseHostedFailureClassification,
15
+ } from "./hosted-delivery-protocol.js";
12
16
 
13
17
  export const HOSTED_EXECUTION_DIAG_VERSION = 1;
14
18
  /** Cap so a runaway message cannot fill the guest disk or the host log. */
@@ -57,6 +61,8 @@ export type HostedExecutionDiag = {
57
61
  signalAborted?: boolean;
58
62
  requestId?: string;
59
63
  abortReason?: HostedExecutionDiagAbortReason;
64
+ failureCode?: string;
65
+ classification?: HostedFailureClassification;
60
66
  };
61
67
 
62
68
  /** Written before the turn starts so a stalled execution still has a record. */
@@ -75,6 +81,8 @@ const DIAG_KEYS = new Set([
75
81
  "signalAborted",
76
82
  "requestId",
77
83
  "abortReason",
84
+ "failureCode",
85
+ "classification",
78
86
  ]);
79
87
 
80
88
  const ABORT_REASONS = new Set<HostedExecutionDiagAbortReason>([
@@ -137,13 +145,13 @@ export function hostedExecutionDiagPath(stateRoot: string): string {
137
145
 
138
146
  export function abortReasonFromTurnStatus(
139
147
  status: string,
140
- message: string | undefined
148
+ cancellationReason: "signal" | "runner" | undefined
141
149
  ): HostedExecutionDiagAbortReason | undefined {
142
150
  if (status === "finished") {
143
151
  return undefined;
144
152
  }
145
153
  if (status === "cancelled") {
146
- return message !== undefined && /abort/i.test(message)
154
+ return cancellationReason === "signal"
147
155
  ? "signal_abort"
148
156
  : "runner_cancelled";
149
157
  }
@@ -197,6 +205,14 @@ export function parseHostedExecutionDiag(
197
205
  HOSTED_ERROR_SNIPPET_MAX_CHARS
198
206
  );
199
207
  const requestId = boundedOptionalString(body.requestId, 128);
208
+ const failureCode = boundedOptionalString(body.failureCode, 64);
209
+ const classification =
210
+ body.classification === undefined
211
+ ? undefined
212
+ : parseHostedFailureClassification(body.classification);
213
+ if (body.classification !== undefined && classification === undefined) {
214
+ return undefined;
215
+ }
200
216
  const abortReason =
201
217
  body.abortReason === undefined
202
218
  ? undefined
@@ -226,6 +242,8 @@ export function parseHostedExecutionDiag(
226
242
  ...(body.signalAborted === true ? { signalAborted: true } : {}),
227
243
  ...(requestId === undefined ? {} : { requestId }),
228
244
  ...(abortReason === undefined ? {} : { abortReason }),
245
+ ...(failureCode === undefined ? {} : { failureCode }),
246
+ ...(classification === undefined ? {} : { classification }),
229
247
  };
230
248
  }
231
249
 
@@ -9,6 +9,7 @@
9
9
  * so TAS does not treat a previous delivery's terminal record as this one.
10
10
  */
11
11
 
12
+ import type { HostedFailureClassification } from "./hosted-delivery-protocol.js";
12
13
  import {
13
14
  type HostedExecutionDiagAbortReason,
14
15
  hostedErrorStackSnippet,
@@ -46,6 +47,8 @@ export type HostedExecutionFlushFields = {
46
47
  durationMs: number;
47
48
  message?: string;
48
49
  abortReason?: HostedExecutionDiagAbortReason;
50
+ failureCode?: string;
51
+ classification?: HostedFailureClassification;
49
52
  error?: unknown;
50
53
  };
51
54
 
@@ -75,12 +78,12 @@ export async function flushHostedExecutionRecord(
75
78
  durationMs: fields.durationMs,
76
79
  ...(message === undefined ? {} : { message }),
77
80
  ...(stack === undefined || stack.length === 0 ? {} : { stack }),
78
- ...(message !== undefined && /abort/i.test(message)
79
- ? { signalAborted: true }
80
- : {}),
81
+ signalAborted: fields.abortReason === "signal_abort" ? true : undefined,
81
82
  ...(fields.abortReason === undefined
82
83
  ? {}
83
84
  : { abortReason: fields.abortReason }),
85
+ failureCode: fields.failureCode,
86
+ classification: fields.classification,
84
87
  });
85
88
  }
86
89
  if (sinks.persistSessionRun !== undefined) {
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Built-in HTTP channel admission for control-plane session starts.
3
+ *
4
+ * `agent-sdk run --prod` reaches the authenticated CP start route, which
5
+ * delivers `agentsdk.session` to the built-in `http` channel of every v2
6
+ * agent. The wake is `send(message, { dryRun, asOf })`; the session id, when
7
+ * the caller resumed an explicit `ses_…`, arrives through the hosted
8
+ * execution (never through this payload), so authored code cannot pick one.
9
+ */
10
+
11
+ import type { ChannelHandlerArgs, HttpChannelDefinition } from "../types.js";
12
+ import { skipped, turnStarted } from "./channel-dispatch.js";
13
+ import { attachHostedAdmissionAdapter } from "./hosted-admission-adapter.js";
14
+ import {
15
+ AGENT_SDK_HTTP_CHANNEL_KIND,
16
+ AGENT_SDK_SESSION_EVENT_TYPE,
17
+ } from "./hosted-catch-protocol.js";
18
+
19
+ export type ControlPlaneSessionPayload = {
20
+ message: string;
21
+ dryRun?: boolean | undefined;
22
+ asOf?: string | undefined;
23
+ };
24
+
25
+ const PAYLOAD_KEYS = new Set(["message", "dryRun", "asOf"]);
26
+ const MAX_MESSAGE_CHARS = 64 * 1024;
27
+
28
+ function isRecord(value: unknown): value is Record<string, unknown> {
29
+ return typeof value === "object" && value !== null && !Array.isArray(value);
30
+ }
31
+
32
+ export function parseControlPlaneSessionPayload(
33
+ payload: unknown
34
+ ):
35
+ | { ok: true; data: ControlPlaneSessionPayload }
36
+ | { ok: false; error: string } {
37
+ if (!isRecord(payload)) {
38
+ return { ok: false, error: "payload must be an object" };
39
+ }
40
+ if (Object.keys(payload).some((key) => !PAYLOAD_KEYS.has(key))) {
41
+ return { ok: false, error: "payload carries an unsupported field" };
42
+ }
43
+ const message =
44
+ typeof payload.message === "string" ? payload.message.trim() : "";
45
+ if (message.length === 0 || message.length > MAX_MESSAGE_CHARS) {
46
+ return { ok: false, error: "payload.message is required" };
47
+ }
48
+ if (payload.dryRun !== undefined && typeof payload.dryRun !== "boolean") {
49
+ return { ok: false, error: "payload.dryRun must be a boolean" };
50
+ }
51
+ if (
52
+ payload.asOf !== undefined &&
53
+ (typeof payload.asOf !== "string" || payload.asOf.trim().length === 0)
54
+ ) {
55
+ return { ok: false, error: "payload.asOf must be a non-empty string" };
56
+ }
57
+ return {
58
+ ok: true,
59
+ data: {
60
+ message,
61
+ dryRun: payload.dryRun === true ? true : undefined,
62
+ asOf: typeof payload.asOf === "string" ? payload.asOf.trim() : undefined,
63
+ },
64
+ };
65
+ }
66
+
67
+ export async function dispatchHttpControlPlaneSession(input: {
68
+ eventType: string;
69
+ payload: unknown;
70
+ args: ChannelHandlerArgs;
71
+ onMessage?: HttpChannelDefinition["onMessage"];
72
+ }): Promise<Response> {
73
+ if (input.eventType !== AGENT_SDK_SESSION_EVENT_TYPE) {
74
+ return skipped("not a control-plane session");
75
+ }
76
+ const parsed = parseControlPlaneSessionPayload(input.payload);
77
+ if (!parsed.ok) {
78
+ return Response.json({ ok: false, error: parsed.error }, { status: 400 });
79
+ }
80
+ const message =
81
+ input.onMessage === undefined
82
+ ? parsed.data.message
83
+ : await input.onMessage(parsed.data.message, { auth: null });
84
+ const session = await input.args.send(message, {
85
+ dryRun: parsed.data.dryRun,
86
+ asOf: parsed.data.asOf,
87
+ });
88
+ return turnStarted(session);
89
+ }
90
+
91
+ export function attachHttpControlPlaneAdmission(
92
+ definition: HttpChannelDefinition
93
+ ): void {
94
+ attachHostedAdmissionAdapter(definition, {
95
+ kind: AGENT_SDK_HTTP_CHANNEL_KIND,
96
+ dispatch: ({ eventType, payload, args }) =>
97
+ dispatchHttpControlPlaneSession({
98
+ eventType,
99
+ payload,
100
+ args,
101
+ onMessage: definition.onMessage,
102
+ }),
103
+ });
104
+ }
@@ -0,0 +1,59 @@
1
+ import {
2
+ type AgentServeDeployClient,
3
+ DeployApiError,
4
+ } from "./deploy-client.js";
5
+
6
+ /**
7
+ * Classify a hosted slug by probing the v2 control plane.
8
+ *
9
+ * Only HTTP 404 means “not v2.” Auth, 5xx, and transport errors fail closed
10
+ * so a v2 slug cannot fall through to `/internal/agent-serve`. That probe
11
+ * shares the factory microlith path used by secrets; a factory outage will
12
+ * also block legacy `--prod` until it recovers.
13
+ */
14
+ export async function deploymentArchitecture(args: {
15
+ client: AgentServeDeployClient;
16
+ teamId: number;
17
+ slug: string;
18
+ }): Promise<"v1" | "v2"> {
19
+ try {
20
+ await args.client.getAgentkitDeploy({
21
+ teamId: args.teamId,
22
+ slug: args.slug,
23
+ });
24
+ return "v2";
25
+ } catch (error) {
26
+ if (error instanceof DeployApiError && error.status === 404) {
27
+ return "v1";
28
+ }
29
+ throw error;
30
+ }
31
+ }
32
+
33
+ export function unsupportedV2LegacyCommandError(slug: string): DeployApiError {
34
+ return new DeployApiError(
35
+ `This command is not supported for architecture v2 deployment "${slug}". The command stopped before calling the legacy v1 deployment API.`,
36
+ 409
37
+ );
38
+ }
39
+
40
+ export function isUnsupportedV2LegacyCommandError(
41
+ error: unknown
42
+ ): error is DeployApiError {
43
+ return (
44
+ error instanceof DeployApiError &&
45
+ error.status === 409 &&
46
+ error.message.includes("not supported for architecture v2")
47
+ );
48
+ }
49
+
50
+ export async function rejectV2ForLegacyCommand(args: {
51
+ client: AgentServeDeployClient;
52
+ teamId: number;
53
+ slug: string;
54
+ }): Promise<void> {
55
+ const architecture = await deploymentArchitecture(args);
56
+ if (architecture === "v2") {
57
+ throw unsupportedV2LegacyCommandError(args.slug);
58
+ }
59
+ }