@cursor/july 0.1.97 → 0.1.100

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (337) hide show
  1. package/AGENTS.md +5 -3
  2. package/dist/bin/agent-serve.js +6 -7
  3. package/dist/channels/github/defaults.d.ts.map +1 -1
  4. package/dist/channels/github/defaults.js +28 -3
  5. package/dist/channels/github/github-channel.d.ts.map +1 -1
  6. package/dist/channels/github/github-channel.js +16 -0
  7. package/dist/channels/github/progress.d.ts +7 -0
  8. package/dist/channels/github/progress.d.ts.map +1 -1
  9. package/dist/channels/origin/origin-channel.d.ts +2 -0
  10. package/dist/channels/origin/origin-channel.d.ts.map +1 -1
  11. package/dist/channels/origin/origin-channel.js +37 -4
  12. package/dist/channels/slack/api.d.ts +16 -7
  13. package/dist/channels/slack/api.d.ts.map +1 -1
  14. package/dist/channels/slack/api.js +29 -13
  15. package/dist/channels/slack/constants.d.ts +6 -0
  16. package/dist/channels/slack/constants.d.ts.map +1 -1
  17. package/dist/channels/slack/constants.js +6 -0
  18. package/dist/channels/slack/defaults.d.ts +9 -4
  19. package/dist/channels/slack/defaults.d.ts.map +1 -1
  20. package/dist/channels/slack/defaults.js +221 -122
  21. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  22. package/dist/channels/slack/dispatch.js +3 -3
  23. package/dist/channels/slack/inbound.d.ts +9 -0
  24. package/dist/channels/slack/inbound.d.ts.map +1 -1
  25. package/dist/channels/slack/inbound.js +14 -0
  26. package/dist/channels/slack/index.d.ts +1 -0
  27. package/dist/channels/slack/index.d.ts.map +1 -1
  28. package/dist/channels/slack/index.js +1 -0
  29. package/dist/channels/slack/live-delivery.d.ts +6 -1
  30. package/dist/channels/slack/live-delivery.d.ts.map +1 -1
  31. package/dist/channels/slack/live-delivery.js +110 -20
  32. package/dist/channels/slack/progress-delivery.d.ts +28 -0
  33. package/dist/channels/slack/progress-delivery.d.ts.map +1 -0
  34. package/dist/channels/slack/progress-delivery.js +115 -0
  35. package/dist/channels/slack/reasoning-card.d.ts +38 -0
  36. package/dist/channels/slack/reasoning-card.d.ts.map +1 -0
  37. package/dist/channels/slack/reasoning-card.js +104 -0
  38. package/dist/channels/slack/redact.d.ts +2 -0
  39. package/dist/channels/slack/redact.d.ts.map +1 -0
  40. package/dist/channels/slack/redact.js +5 -0
  41. package/dist/channels/slack/reply-options.d.ts +40 -0
  42. package/dist/channels/slack/reply-options.d.ts.map +1 -0
  43. package/dist/channels/slack/reply-options.js +150 -0
  44. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  45. package/dist/channels/slack/slack-channel.js +8 -4
  46. package/dist/channels/slack/stream.d.ts +22 -10
  47. package/dist/channels/slack/stream.d.ts.map +1 -1
  48. package/dist/channels/slack/stream.js +9 -16
  49. package/dist/channels/slack/tool-cards.d.ts +22 -0
  50. package/dist/channels/slack/tool-cards.d.ts.map +1 -0
  51. package/dist/channels/slack/tool-cards.js +178 -0
  52. package/dist/channels/slack/types.d.ts +154 -7
  53. package/dist/channels/slack/types.d.ts.map +1 -1
  54. package/dist/docs/404.html +2 -2
  55. package/dist/docs/ab.html +6 -6
  56. package/dist/docs/ab.md +1 -1
  57. package/dist/docs/assets/{ab.md.DJo5r4R-.js → ab.md.mlVgqvSk.js} +1 -1
  58. package/dist/docs/assets/{app.B3rWNYE1.js → app.DZ1e0Ycq.js} +1 -1
  59. package/dist/docs/assets/{building-with-agents.md.DI4mEzlt.js → building-with-agents.md.CUSWxlP_.js} +2 -2
  60. package/dist/docs/assets/chunks/@localSearchIndexroot.j70vvPL4.js +1 -0
  61. package/dist/docs/assets/chunks/{VPLocalSearchBox.C1lhqJJR.js → VPLocalSearchBox.l8omwc6D.js} +1 -1
  62. package/dist/docs/assets/chunks/{theme.B40_SXuv.js → theme.JVcD6gel.js} +2 -2
  63. package/dist/docs/assets/{evals.md.lfJoEVc8.js → evals.md.CPzDAwoH.js} +1 -1
  64. package/dist/docs/assets/{guides_github.md.Cnh2mL4a.js → guides_github.md.BtPr9GaP.js} +1 -1
  65. package/dist/docs/assets/{guides_mcp-oauth.md.CN-6YmTJ.js → guides_mcp-oauth.md.Dp6cDP7f.js} +1 -1
  66. package/dist/docs/assets/{guides_opentelemetry.md.bmPmkvJu.js → guides_opentelemetry.md.BVTXDCRg.js} +2 -2
  67. package/dist/docs/assets/{guides_slack.md.VDXQV3ja.js → guides_slack.md.9oHPye9o.js} +19 -3
  68. package/dist/docs/assets/{guides_slack.md.VDXQV3ja.lean.js → guides_slack.md.9oHPye9o.lean.js} +1 -1
  69. package/dist/docs/assets/hillclimbing.md.CpTGTCle.js +4 -0
  70. package/dist/docs/assets/{index.md.CVeRUOeZ.js → index.md.Bb4k8kUm.js} +1 -1
  71. package/dist/docs/assets/{quickstart.md.Nj_LjW_a.js → quickstart.md.DdQOF7Y8.js} +1 -1
  72. package/dist/docs/assets/{reference_cli.md.RyZf5OTE.js → reference_cli.md.DfoeyvL0.js} +4 -4
  73. package/dist/docs/assets/{reference_cli.md.RyZf5OTE.lean.js → reference_cli.md.DfoeyvL0.lean.js} +1 -1
  74. package/dist/docs/assets/{reference_connections.md.DxldvyIB.js → reference_connections.md.BiGoBAk2.js} +1 -1
  75. package/dist/docs/assets/{reference_http-api.md.5zOAbV86.js → reference_http-api.md.BEJx9XVj.js} +1 -1
  76. package/dist/docs/assets/{reference_tools.md.B84gw9Ii.js → reference_tools.md.CvAHsdSp.js} +10 -2
  77. package/dist/docs/assets/{reference_tools.md.B84gw9Ii.lean.js → reference_tools.md.CvAHsdSp.lean.js} +1 -1
  78. package/dist/docs/assets/scaffolding-agents.md.em43xlY1.js +1 -0
  79. package/dist/docs/assets/skills_ab.md.CsFNatVx.js +26 -0
  80. package/dist/docs/assets/skills_ab.md.CsFNatVx.lean.js +1 -0
  81. package/dist/docs/assets/skills_create-agent.md.BVoWPcan.js +8 -0
  82. package/dist/docs/assets/skills_create-agent.md.BVoWPcan.lean.js +1 -0
  83. package/dist/docs/assets/skills_debug.md.CDbPhHfg.js +1 -0
  84. package/dist/docs/assets/skills_debug.md.CDbPhHfg.lean.js +1 -0
  85. package/dist/docs/assets/skills_evals.md.723kpUmA.js +25 -0
  86. package/dist/docs/assets/skills_evals.md.723kpUmA.lean.js +1 -0
  87. package/dist/docs/assets/skills_framework-map.md.BTi817yv.js +1 -0
  88. package/dist/docs/assets/skills_framework-map.md.BTi817yv.lean.js +1 -0
  89. package/dist/docs/assets/skills_github.md.D0JahM8c.js +16 -0
  90. package/dist/docs/assets/skills_github.md.D0JahM8c.lean.js +1 -0
  91. package/dist/docs/assets/skills_hillclimb.md.B_zJerxA.js +7 -0
  92. package/dist/docs/assets/skills_hillclimb.md.B_zJerxA.lean.js +1 -0
  93. package/dist/docs/assets/skills_index.md.DKwIxzGg.js +1 -0
  94. package/dist/docs/assets/skills_index.md.DKwIxzGg.lean.js +1 -0
  95. package/dist/docs/assets/skills_mcp-auth.md.DGvFP3HE.js +18 -0
  96. package/dist/docs/assets/skills_mcp-auth.md.DGvFP3HE.lean.js +1 -0
  97. package/dist/docs/assets/skills_otel.md.CgiZryR3.js +8 -0
  98. package/dist/docs/assets/skills_otel.md.CgiZryR3.lean.js +1 -0
  99. package/dist/docs/assets/skills_setup-slack.md.BBgx8lUz.js +20 -0
  100. package/dist/docs/assets/skills_setup-slack.md.BBgx8lUz.lean.js +1 -0
  101. package/dist/docs/assets/{troubleshooting.md.DCiPBhYs.js → troubleshooting.md.Cus_YZga.js} +1 -1
  102. package/dist/docs/building-with-agents.html +6 -6
  103. package/dist/docs/building-with-agents.md +14 -11
  104. package/dist/docs/concepts.html +4 -4
  105. package/dist/docs/deployment.html +4 -4
  106. package/dist/docs/design/runtime-abstraction.md +1757 -0
  107. package/dist/docs/evals.html +6 -6
  108. package/dist/docs/evals.md +1 -1
  109. package/dist/docs/guides/agent-to-agent.html +4 -4
  110. package/dist/docs/guides/cloud-runtime.html +4 -4
  111. package/dist/docs/guides/convert-automation.html +4 -4
  112. package/dist/docs/guides/github.html +5 -5
  113. package/dist/docs/guides/github.md +1 -1
  114. package/dist/docs/guides/human-in-the-loop.html +4 -4
  115. package/dist/docs/guides/mcp-oauth.html +5 -5
  116. package/dist/docs/guides/mcp-oauth.md +1 -1
  117. package/dist/docs/guides/opentelemetry.html +7 -7
  118. package/dist/docs/guides/opentelemetry.md +2 -2
  119. package/dist/docs/guides/slack.html +22 -6
  120. package/dist/docs/guides/slack.md +80 -1
  121. package/dist/docs/guides/webhooks.html +5 -5
  122. package/dist/docs/hashmap.json +1 -1
  123. package/dist/docs/hillclimbing.html +6 -6
  124. package/dist/docs/hillclimbing.md +5 -5
  125. package/dist/docs/index.html +6 -6
  126. package/dist/docs/index.md +1 -1
  127. package/dist/docs/llms-full.txt +2830 -37
  128. package/dist/docs/llms.txt +15 -0
  129. package/dist/docs/quickstart.html +5 -5
  130. package/dist/docs/quickstart.md +1 -1
  131. package/dist/docs/reference/agent-config.html +4 -4
  132. package/dist/docs/reference/artifacts.html +4 -4
  133. package/dist/docs/reference/channels.html +4 -4
  134. package/dist/docs/reference/cli.html +7 -7
  135. package/dist/docs/reference/cli.md +1 -7
  136. package/dist/docs/reference/connections.html +6 -6
  137. package/dist/docs/reference/connections.md +1 -1
  138. package/dist/docs/reference/hooks.html +4 -4
  139. package/dist/docs/reference/http-api.html +6 -6
  140. package/dist/docs/reference/http-api.md +1 -0
  141. package/dist/docs/reference/instructions.html +4 -4
  142. package/dist/docs/reference/playground.html +4 -4
  143. package/dist/docs/reference/project-layout.html +4 -4
  144. package/dist/docs/reference/prompt.html +4 -4
  145. package/dist/docs/reference/schedules.html +4 -4
  146. package/dist/docs/reference/sessions.html +4 -4
  147. package/dist/docs/reference/skills.html +4 -4
  148. package/dist/docs/reference/subagents.html +4 -4
  149. package/dist/docs/reference/tools.html +14 -6
  150. package/dist/docs/reference/tools.md +25 -0
  151. package/dist/docs/scaffolding-agents.html +5 -5
  152. package/dist/docs/scaffolding-agents.md +3 -3
  153. package/dist/docs/skills/ab.html +52 -0
  154. package/dist/docs/skills/ab.md +50 -0
  155. package/dist/docs/skills/create-agent.html +34 -0
  156. package/dist/docs/skills/create-agent.md +160 -0
  157. package/dist/docs/skills/debug.html +27 -0
  158. package/dist/docs/skills/debug.md +36 -0
  159. package/dist/docs/skills/evals.html +51 -0
  160. package/dist/docs/skills/evals.md +99 -0
  161. package/dist/docs/skills/framework-map.html +27 -0
  162. package/dist/docs/skills/framework-map.md +95 -0
  163. package/dist/docs/skills/github.html +42 -0
  164. package/dist/docs/skills/github.md +93 -0
  165. package/dist/docs/skills/hillclimb.html +33 -0
  166. package/dist/docs/skills/hillclimb.md +55 -0
  167. package/dist/docs/skills/index.html +27 -0
  168. package/dist/docs/skills/index.md +21 -0
  169. package/dist/docs/skills/mcp-auth.html +44 -0
  170. package/dist/docs/skills/mcp-auth.md +76 -0
  171. package/dist/docs/skills/otel.html +34 -0
  172. package/dist/docs/skills/otel.md +48 -0
  173. package/dist/docs/skills/setup-slack.html +46 -0
  174. package/dist/docs/skills/setup-slack.md +141 -0
  175. package/dist/docs/storage.html +4 -4
  176. package/dist/docs/templates/agentic-owners.html +4 -4
  177. package/dist/docs/templates/agents-md.html +4 -4
  178. package/dist/docs/templates/code-wiki.html +4 -4
  179. package/dist/docs/templates/demo.html +4 -4
  180. package/dist/docs/templates/pr-autofixer.html +4 -4
  181. package/dist/docs/templates/security-help.html +4 -4
  182. package/dist/docs/templates/security-reviewer.html +4 -4
  183. package/dist/docs/templates/triage.html +4 -4
  184. package/dist/docs/troubleshooting.html +5 -5
  185. package/dist/docs/troubleshooting.md +1 -1
  186. package/dist/files-backends/cursor-hosted.d.ts +9 -2
  187. package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
  188. package/dist/files-backends/cursor-hosted.js +9 -11
  189. package/dist/index.d.ts +1 -0
  190. package/dist/index.d.ts.map +1 -1
  191. package/dist/index.js +1 -0
  192. package/dist/internal/as-of.d.ts +19 -0
  193. package/dist/internal/as-of.d.ts.map +1 -0
  194. package/dist/internal/as-of.js +82 -0
  195. package/dist/internal/cli-deploy.d.ts +2 -1
  196. package/dist/internal/cli-deploy.d.ts.map +1 -1
  197. package/dist/internal/cli-deploy.js +102 -7
  198. package/dist/internal/conversation-mirror.d.ts.map +1 -1
  199. package/dist/internal/conversation-mirror.js +3 -4
  200. package/dist/internal/cursor/hosted-store-secrets.d.ts +15 -0
  201. package/dist/internal/cursor/hosted-store-secrets.d.ts.map +1 -0
  202. package/dist/internal/cursor/hosted-store-secrets.js +48 -0
  203. package/dist/internal/cursor-event-relay.d.ts.map +1 -1
  204. package/dist/internal/cursor-event-relay.js +5 -6
  205. package/dist/internal/deploy-client.d.ts +6 -6
  206. package/dist/internal/deploy-client.js +7 -7
  207. package/dist/internal/discovery.d.ts.map +1 -1
  208. package/dist/internal/discovery.js +11 -1
  209. package/dist/internal/framework-file-storage.d.ts +5 -4
  210. package/dist/internal/framework-file-storage.d.ts.map +1 -1
  211. package/dist/internal/framework-file-storage.js +6 -4
  212. package/dist/internal/framework-storage-selection.d.ts +13 -11
  213. package/dist/internal/framework-storage-selection.d.ts.map +1 -1
  214. package/dist/internal/framework-storage-selection.js +28 -23
  215. package/dist/internal/hosted-admission-adapter.d.ts +28 -0
  216. package/dist/internal/hosted-admission-adapter.d.ts.map +1 -0
  217. package/dist/internal/hosted-admission-adapter.js +7 -0
  218. package/dist/internal/hosted-delivery-protocol.d.ts +6 -1
  219. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
  220. package/dist/internal/hosted-delivery-protocol.js +1 -1
  221. package/dist/internal/hosted-delivery.d.ts +15 -1
  222. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  223. package/dist/internal/hosted-delivery.js +47 -21
  224. package/dist/internal/hosted-execution-diag.d.ts +11 -0
  225. package/dist/internal/hosted-execution-diag.d.ts.map +1 -1
  226. package/dist/internal/hosted-execution-diag.js +39 -2
  227. package/dist/internal/http-channel.d.ts.map +1 -1
  228. package/dist/internal/http-channel.js +4 -1
  229. package/dist/internal/server.d.ts +3 -0
  230. package/dist/internal/server.d.ts.map +1 -1
  231. package/dist/internal/server.js +82 -19
  232. package/dist/internal/session-engine.d.ts.map +1 -1
  233. package/dist/internal/session-engine.js +24 -4
  234. package/dist/internal/session-run-log.d.ts +120 -0
  235. package/dist/internal/session-run-log.d.ts.map +1 -0
  236. package/dist/internal/session-run-log.js +358 -0
  237. package/dist/internal/tool-policy.d.ts +20 -8
  238. package/dist/internal/tool-policy.d.ts.map +1 -1
  239. package/dist/internal/tool-policy.js +11 -0
  240. package/dist/playground/assets/index-BszoQDc6.css +1 -0
  241. package/dist/playground/assets/index-DVs98vPL.js +69 -0
  242. package/dist/playground/index.html +2 -2
  243. package/dist/storage-backends/cursor-hosted-v2.d.ts +83 -0
  244. package/dist/storage-backends/cursor-hosted-v2.d.ts.map +1 -0
  245. package/dist/storage-backends/cursor-hosted-v2.js +164 -0
  246. package/dist/storage-backends/cursor-hosted.d.ts +6 -0
  247. package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
  248. package/dist/storage-backends/cursor-hosted.js +6 -1
  249. package/dist/storage-protocol.d.ts +8 -0
  250. package/dist/storage-protocol.d.ts.map +1 -1
  251. package/dist/storage-protocol.js +8 -0
  252. package/dist/tools.d.ts +12 -2
  253. package/dist/tools.d.ts.map +1 -1
  254. package/dist/types.d.ts +30 -0
  255. package/dist/types.d.ts.map +1 -1
  256. package/docs/README.md +1 -1
  257. package/docs/ab.md +1 -1
  258. package/docs/building-with-agents.md +14 -11
  259. package/docs/design/runtime-abstraction.md +1757 -0
  260. package/docs/evals.md +1 -1
  261. package/docs/guides/github.md +1 -1
  262. package/docs/guides/mcp-oauth.md +1 -1
  263. package/docs/guides/opentelemetry.md +2 -2
  264. package/docs/guides/slack.md +80 -1
  265. package/docs/hillclimbing.md +5 -5
  266. package/docs/quickstart.md +1 -1
  267. package/docs/reference/cli.md +1 -7
  268. package/docs/reference/connections.md +1 -1
  269. package/docs/reference/http-api.md +1 -0
  270. package/docs/reference/tools.md +25 -0
  271. package/docs/scaffolding-agents.md +3 -3
  272. package/docs/skills/index.md +26 -0
  273. package/docs/troubleshooting.md +1 -1
  274. package/package.json +1 -1
  275. package/src/bin/agent-serve.ts +6 -7
  276. package/src/channels/github/defaults.ts +36 -3
  277. package/src/channels/github/github-channel.ts +17 -0
  278. package/src/channels/github/progress.ts +7 -0
  279. package/src/channels/origin/origin-channel.ts +74 -10
  280. package/src/channels/slack/api.ts +35 -17
  281. package/src/channels/slack/constants.ts +6 -0
  282. package/src/channels/slack/defaults.ts +253 -144
  283. package/src/channels/slack/dispatch.ts +10 -1
  284. package/src/channels/slack/inbound.ts +17 -0
  285. package/src/channels/slack/index.ts +1 -0
  286. package/src/channels/slack/live-delivery.ts +135 -22
  287. package/src/channels/slack/progress-delivery.ts +133 -0
  288. package/src/channels/slack/reasoning-card.ts +140 -0
  289. package/src/channels/slack/redact.ts +6 -0
  290. package/src/channels/slack/reply-options.ts +229 -0
  291. package/src/channels/slack/slack-channel.ts +7 -2
  292. package/src/channels/slack/stream.ts +31 -24
  293. package/src/channels/slack/tool-cards.ts +221 -0
  294. package/src/channels/slack/types.ts +168 -7
  295. package/src/files-backends/cursor-hosted.ts +18 -7
  296. package/src/index.ts +4 -0
  297. package/src/internal/as-of.ts +107 -0
  298. package/src/internal/cli-deploy.ts +130 -10
  299. package/src/internal/conversation-mirror.ts +3 -8
  300. package/src/internal/cursor/hosted-store-secrets.ts +72 -0
  301. package/src/internal/cursor-event-relay.ts +5 -6
  302. package/src/internal/deploy-client.ts +10 -10
  303. package/src/internal/discovery.ts +9 -1
  304. package/src/internal/framework-file-storage.ts +6 -4
  305. package/src/internal/framework-storage-selection.ts +28 -25
  306. package/src/internal/hosted-admission-adapter.ts +42 -0
  307. package/src/internal/hosted-delivery-protocol.ts +7 -2
  308. package/src/internal/hosted-delivery.ts +88 -36
  309. package/src/internal/hosted-execution-diag.ts +45 -0
  310. package/src/internal/http-channel.ts +8 -0
  311. package/src/internal/server.ts +100 -2
  312. package/src/internal/session-engine.ts +32 -1
  313. package/src/internal/session-run-log.ts +579 -0
  314. package/src/internal/tool-policy.ts +31 -9
  315. package/src/storage-backends/cursor-hosted-v2.ts +219 -0
  316. package/src/storage-backends/cursor-hosted.ts +6 -1
  317. package/src/storage-protocol.ts +10 -0
  318. package/src/tools.ts +12 -2
  319. package/src/types.ts +30 -0
  320. package/dist/docs/assets/chunks/@localSearchIndexroot.BU9nHdnQ.js +0 -1
  321. package/dist/docs/assets/hillclimbing.md.DhESf3OO.js +0 -4
  322. package/dist/docs/assets/scaffolding-agents.md.D7UUkWw0.js +0 -1
  323. package/dist/playground/assets/index-DrkI6y5O.js +0 -88
  324. package/dist/playground/assets/index-DzNGwm7q.css +0 -1
  325. /package/dist/docs/assets/{ab.md.DJo5r4R-.lean.js → ab.md.mlVgqvSk.lean.js} +0 -0
  326. /package/dist/docs/assets/{building-with-agents.md.DI4mEzlt.lean.js → building-with-agents.md.CUSWxlP_.lean.js} +0 -0
  327. /package/dist/docs/assets/{evals.md.lfJoEVc8.lean.js → evals.md.CPzDAwoH.lean.js} +0 -0
  328. /package/dist/docs/assets/{guides_github.md.Cnh2mL4a.lean.js → guides_github.md.BtPr9GaP.lean.js} +0 -0
  329. /package/dist/docs/assets/{guides_mcp-oauth.md.CN-6YmTJ.lean.js → guides_mcp-oauth.md.Dp6cDP7f.lean.js} +0 -0
  330. /package/dist/docs/assets/{guides_opentelemetry.md.bmPmkvJu.lean.js → guides_opentelemetry.md.BVTXDCRg.lean.js} +0 -0
  331. /package/dist/docs/assets/{hillclimbing.md.DhESf3OO.lean.js → hillclimbing.md.CpTGTCle.lean.js} +0 -0
  332. /package/dist/docs/assets/{index.md.CVeRUOeZ.lean.js → index.md.Bb4k8kUm.lean.js} +0 -0
  333. /package/dist/docs/assets/{quickstart.md.Nj_LjW_a.lean.js → quickstart.md.DdQOF7Y8.lean.js} +0 -0
  334. /package/dist/docs/assets/{reference_connections.md.DxldvyIB.lean.js → reference_connections.md.BiGoBAk2.lean.js} +0 -0
  335. /package/dist/docs/assets/{reference_http-api.md.5zOAbV86.lean.js → reference_http-api.md.BEJx9XVj.lean.js} +0 -0
  336. /package/dist/docs/assets/{scaffolding-agents.md.D7UUkWw0.lean.js → scaffolding-agents.md.em43xlY1.lean.js} +0 -0
  337. /package/dist/docs/assets/{troubleshooting.md.DCiPBhYs.lean.js → troubleshooting.md.Cus_YZga.lean.js} +0 -0
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Task-time bind paths for hosted deployment file-store source ids.
3
+ *
4
+ * Freeze v2 snapshots start `agent-serve serve` at bake time without a service
5
+ * account, so neither store id is in process env. Execute-from-freeze binds
6
+ * the deployment credential and store ids into `/run/cursor/secrets/` without
7
+ * restarting July — the same pattern as {@link DEFAULT_CURSOR_API_KEY_FILE}.
8
+ */
9
+
10
+ import { readFileSync } from "node:fs";
11
+
12
+ export const DEFAULT_AGENT_SERVE_STORE_SOURCE_ID_FILE =
13
+ "/run/cursor/secrets/AGENT_SERVE_STORE_SOURCE_ID";
14
+
15
+ export const DEFAULT_AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID_FILE =
16
+ "/run/cursor/secrets/AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID";
17
+
18
+ const STORE_SOURCE_ID_ENV = "AGENT_SERVE_STORE_SOURCE_ID";
19
+ const FRAMEWORK_STORE_SOURCE_ID_ENV = "AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID";
20
+ const STORE_SOURCE_ID_FILE_ENV = "AGENT_SERVE_STORE_SOURCE_ID_FILE";
21
+ const FRAMEWORK_STORE_SOURCE_ID_FILE_ENV =
22
+ "AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID_FILE";
23
+
24
+ function readTrimmedFile(path: string): string | undefined {
25
+ try {
26
+ const raw = readFileSync(path, "utf8").trim();
27
+ return raw === "" ? undefined : raw;
28
+ } catch {
29
+ return undefined;
30
+ }
31
+ }
32
+
33
+ function readBoundSecretFile(
34
+ fileEnvVar: string,
35
+ defaultPath: string,
36
+ env: NodeJS.ProcessEnv
37
+ ): string | undefined {
38
+ const configured = env[fileEnvVar]?.trim();
39
+ const path =
40
+ configured !== undefined && configured !== "" ? configured : defaultPath;
41
+ return readTrimmedFile(path);
42
+ }
43
+
44
+ /** Deployment user-land store: env, then task-bind file. */
45
+ export function resolveDeploymentStoreSourceIdSync(
46
+ env: NodeJS.ProcessEnv = process.env
47
+ ): string | undefined {
48
+ const fromEnv = env[STORE_SOURCE_ID_ENV]?.trim();
49
+ if (fromEnv !== undefined && fromEnv !== "") {
50
+ return fromEnv;
51
+ }
52
+ return readBoundSecretFile(
53
+ STORE_SOURCE_ID_FILE_ENV,
54
+ DEFAULT_AGENT_SERVE_STORE_SOURCE_ID_FILE,
55
+ env
56
+ );
57
+ }
58
+
59
+ /** Engine framework store: env, then task-bind file. */
60
+ export function resolveFrameworkStoreSourceIdSync(
61
+ env: NodeJS.ProcessEnv = process.env
62
+ ): string | undefined {
63
+ const fromEnv = env[FRAMEWORK_STORE_SOURCE_ID_ENV]?.trim();
64
+ if (fromEnv !== undefined && fromEnv !== "") {
65
+ return fromEnv;
66
+ }
67
+ return readBoundSecretFile(
68
+ FRAMEWORK_STORE_SOURCE_ID_FILE_ENV,
69
+ DEFAULT_AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID_FILE,
70
+ env
71
+ );
72
+ }
@@ -616,12 +616,11 @@ export class CursorEventRelay {
616
616
  events: [...subscription.events],
617
617
  })),
618
618
  }),
619
- // Empty subscriptions drop this consumer's registration on clean stop
620
- // instead of leaving it to lapse by TTL.
621
- buildDeregistrationBody: (consumerId) => ({
622
- consumerId,
623
- subscriptions: [],
624
- }),
619
+ // No deregistration on stop: the backend only records events for a
620
+ // repo that some consumer is subscribed to, so dropping the
621
+ // registration leaves a hole in the log until the next process
622
+ // registers, and the durable offset cannot replay what was never
623
+ // written. A consumer that does not come back lapses by TTL.
625
624
  applyRegistrationResponse: (json) => {
626
625
  const result = json as { repos?: SubscriptionStatus[] };
627
626
  const statuses = result.repos ?? [];
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Thin client for the Agent Serve deployment management API
3
3
  * (`/internal/agent-serve/deployments` on the Cursor backend) and the v2
4
- * AgentSDK accept path (`/internal/agentkit/deployments`). Pure
4
+ * AgentSDK accept path (`/internal/agentsdk/deployments`). Pure
5
5
  * request/response + error mapping — no console I/O, no polling loops;
6
6
  * rendering lives in `cli-deploy.ts`.
7
7
  *
@@ -214,7 +214,7 @@ export interface StopAccepted {
214
214
  export type DeleteAccepted = StopAccepted;
215
215
 
216
216
  /**
217
- * `POST /internal/agentkit/deployments` 202 body. Distinct from v1
217
+ * `POST /internal/agentsdk/deployments` 202 body. Distinct from v1
218
218
  * {@link DeployAccepted}: the v2 control plane returns catalog ids, not
219
219
  * an engine alias or one-shot alias token.
220
220
  */
@@ -234,7 +234,7 @@ export interface AgentkitDeployComponent {
234
234
  agentPath?: string;
235
235
  }
236
236
 
237
- /** Customer-visible v2 deploy status (`GET /internal/agentkit/deployments/:slug`). */
237
+ /** Customer-visible v2 deploy status (`GET /internal/agentsdk/deployments/:slug`). */
238
238
  export type AgentkitCustomerStatus =
239
239
  | "pending"
240
240
  | "deploying"
@@ -273,7 +273,7 @@ export const TERMINAL_AGENTKIT_DEPLOY_STATUSES: ReadonlySet<AgentkitCustomerStat
273
273
  new Set(["running", "failed", "stopped"]);
274
274
 
275
275
  /**
276
- * `POST /internal/agentkit/deployments/:slug/stop` 202 body. Like v1
276
+ * `POST /internal/agentsdk/deployments/:slug/stop` 202 body. Like v1
277
277
  * {@link StopAccepted} but keyed by catalog ids instead of the numeric
278
278
  * deployment row id.
279
279
  */
@@ -594,7 +594,7 @@ export class AgentServeDeployClient {
594
594
 
595
595
  /**
596
596
  * Create or redeploy onto the v2 control plane
597
- * (`POST /internal/agentkit/deployments`). 202 means accepted; poll
597
+ * (`POST /internal/agentsdk/deployments`). 202 means accepted; poll
598
598
  * {@link getAgentkitDeploy} until a terminal status. `components` deploys
599
599
  * one application with several release components (one per agent
600
600
  * directory); it is mutually exclusive with `agentPath`.
@@ -625,7 +625,7 @@ export class AgentServeDeployClient {
625
625
  }
626
626
  const raw = await this.request({
627
627
  method: "POST",
628
- path: "/internal/agentkit/deployments",
628
+ path: "/internal/agentsdk/deployments",
629
629
  body: {
630
630
  teamId: args.teamId,
631
631
  slug: args.slug,
@@ -650,14 +650,14 @@ export class AgentServeDeployClient {
650
650
  }): Promise<AgentkitDeployStatus> {
651
651
  const raw = await this.request({
652
652
  method: "GET",
653
- path: `/internal/agentkit/deployments/${encodeURIComponent(args.slug)}?teamId=${args.teamId}`,
653
+ path: `/internal/agentsdk/deployments/${encodeURIComponent(args.slug)}?teamId=${args.teamId}`,
654
654
  context: { verb: "get deployment", slug: args.slug },
655
655
  });
656
656
  return agentkitDeployStatusSchema.parse(raw);
657
657
  }
658
658
 
659
659
  /**
660
- * Stop a v2 deployment (`POST /internal/agentkit/deployments/:slug/stop`).
660
+ * Stop a v2 deployment (`POST /internal/agentsdk/deployments/:slug/stop`).
661
661
  * 202 means accepted; poll {@link getAgentkitDeploy} until `stopped`.
662
662
  */
663
663
  async stopAgentkit(args: {
@@ -666,7 +666,7 @@ export class AgentServeDeployClient {
666
666
  }): Promise<AgentkitStopAccepted> {
667
667
  const raw = await this.request({
668
668
  method: "POST",
669
- path: `/internal/agentkit/deployments/${encodeURIComponent(args.slug)}/stop?teamId=${args.teamId}`,
669
+ path: `/internal/agentsdk/deployments/${encodeURIComponent(args.slug)}/stop?teamId=${args.teamId}`,
670
670
  context: { verb: "stop", slug: args.slug },
671
671
  });
672
672
  return agentkitStopAcceptedSchema.parse(raw);
@@ -977,7 +977,7 @@ function mapErrorResponse(
977
977
  // (api2 vs api.cursor.com), not a missing deployment / closed gate.
978
978
  if (/Route \S+ not found/i.test(bodyText)) {
979
979
  return new DeployApiError(
980
- `Agent Serve deploy API not found on this host — use the default api.cursor.com (unset CURSOR_API_BASE_URL), or point CURSOR_API_BASE_URL at a backend that mounts /internal/agent-serve/* and /internal/agentkit/*.`,
980
+ `Agent Serve deploy API not found on this host — use the default api.cursor.com (unset CURSOR_API_BASE_URL), or point CURSOR_API_BASE_URL at a backend that mounts /internal/agent-serve/* and /internal/agentsdk/*.`,
981
981
  404
982
982
  );
983
983
  }
@@ -1928,7 +1928,15 @@ async function loadChannels(
1928
1928
  });
1929
1929
  continue;
1930
1930
  }
1931
- channels.push({ id, definition: mod.default as ChannelDefinition });
1931
+ const definition = mod.default as ChannelDefinition;
1932
+ for (const notice of definition.meta?.deprecations ?? []) {
1933
+ ctx.diagnostics.push({
1934
+ severity: "warning",
1935
+ path: displayPath(ctx, entryPath),
1936
+ message: notice,
1937
+ });
1938
+ }
1939
+ channels.push({ id, definition });
1932
1940
  }
1933
1941
  return { channels, httpChannelDefinition };
1934
1942
  }
@@ -8,15 +8,16 @@
8
8
  * is browsable from the dashboard and mountable on cloud-runtime VMs;
9
9
  * - the **framework-level** store (`AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID`)
10
10
  * holds engine-owned session state — session records, event transcripts,
11
- * the continuation index, and the SDK conversation mirror — and is never
12
- * exposed to authors or models.
11
+ * hosted-execution run logs, the continuation index, and the SDK
12
+ * conversation mirror — and is never exposed to authors or models.
13
13
  *
14
14
  * This module puts framework session state on the framework store. The
15
15
  * {@link storageKeys} scheme was designed for exactly this: keys are a
16
16
  * stable versioned contract that sinks may route on, so
17
17
  * {@link composeFrameworkStorage} splits one {@link StorageConfig} by key
18
- * kind — `session` / `session-events` / `continuation` go to the framework
19
- * file store (file-shaped; the store accepts values up to 64 MiB per
18
+ * kind — `session` / `session-events` / `session-runs` / `continuation`
19
+ * go to the framework file store (file-shaped; the store accepts values
20
+ * up to 64 MiB per
20
21
  * object without chunking, versus the KV proxy's 1 MiB row cap), while
21
22
  * author `kv`, eval runs, A/B samples, and conditional writes stay on the
22
23
  * control-plane KV proxy (the dashboard reads them there, and CAS needs a
@@ -40,6 +41,7 @@ import { mapBounded } from "./bounded.js";
40
41
  const FRAMEWORK_FILE_KINDS: ReadonlySet<string> = new Set([
41
42
  "session",
42
43
  "session-events",
44
+ "session-runs",
43
45
  "continuation",
44
46
  ]);
45
47
 
@@ -17,17 +17,19 @@
17
17
  *
18
18
  * - **Cursor-managed hosting** (the deployment-generation environment
19
19
  * variable is set, same signal that registers `GET /v1/manifest`):
20
- * the Cursor-hosted backend. When the deployment carries a
21
- * **framework-level file store**
22
- * (`AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID`), session records, event
23
- * transcripts, and the continuation index live there file-shaped state
24
- * on file storage, apart from the author-facing user store — while
25
- * `host.kv`, eval runs, A/B samples, and conditional writes stay on the
26
- * control-plane KV proxy (see framework-file-storage.ts). Without one
27
- * (a deploy predating framework-store provisioning), everything goes to
28
- * the KV proxy as before. The API key resolves through the full
29
- * credential chain on every call because hosted freeze snapshots listen
30
- * unsigned and the binder drops the key file after restore.
20
+ * the deployment's **framework-level file store**
21
+ * (`AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID`, bound at task time) holds
22
+ * session records, event transcripts, and the continuation index —
23
+ * file-shaped state on file storage, apart from the author-facing user
24
+ * store. Author `host.kv`, eval runs, A/B samples, and conditional writes
25
+ * ride the AgentSDK v2 KV proxy (cursor-hosted-v2.ts), which resolves the
26
+ * pod service account to the factorydb deployment row (the v1 Bugbot
27
+ * proxy cannot resolve v2 pods at all). Framework session state never
28
+ * routes to the KV proxy the composite splits by key kind so
29
+ * transcripts stay off the author-reachable KV namespace. The API key
30
+ * resolves through the full credential chain on every call because hosted
31
+ * freeze snapshots listen unsigned and the binder drops the key file
32
+ * after restore.
31
33
  * - **Self-hosted**: no mirror. `--state-root` is the durable copy, which
32
34
  * is correct when the operator owns the disk.
33
35
  *
@@ -45,7 +47,7 @@ import {
45
47
  cursorHostedFiles,
46
48
  } from "../files-backends/cursor-hosted.js";
47
49
  import { defineStorage, type StorageDefinition } from "../storage.js";
48
- import { cursorHostedStorage } from "../storage-backends/cursor-hosted.js";
50
+ import { cursorHostedStorageV2 } from "../storage-backends/cursor-hosted-v2.js";
49
51
  import type { AgentArchitecture } from "../types.js";
50
52
  import { resolveApiKeySync } from "./cursor/credentials.js";
51
53
  import { AGENT_SERVE_GENERATION_ENV_VAR } from "./cursor-relay-core.js";
@@ -96,20 +98,18 @@ export function selectFrameworkStorageDefinition(
96
98
  // comes up). Follow-ups restore lazily by continuation or session id;
97
99
  // GET /v1/sessions lists from the sink either way.
98
100
  const policy = { restore: "off" } as const;
99
- // Full chain (env key file → stored login): frozen engines listen
100
- // unsigned and bind CURSOR_API_KEY_FILE at task time, after this
101
+ const envSnapshot = env as NodeJS.ProcessEnv;
102
+ // Full chain (env → bind file stored login): frozen engines listen
103
+ // unsigned and bind store ids + CURSOR_API_KEY at task time, after this
101
104
  // definition is constructed.
102
105
  const resolveApiKey = (): string | undefined => resolveApiKeySync()?.apiKey;
103
- const kv = cursorHostedStorage({ resolveApiKey });
104
- const frameworkStoreId = cursorFrameworkStoreSourceId(
105
- env as NodeJS.ProcessEnv
106
- );
107
- if (frameworkStoreId === undefined) {
108
- return defineStorage({ name: "cursor-hosted", policy, ...kv });
109
- }
110
- // Framework session state on the framework-level file store; author kv,
111
- // evals, and A/B tables stay on the KV proxy (spread from `kv`, which
112
- // also carries the cursor-hosted marker for GET /v1/sessions).
106
+ // v2 pods carry a factorydb-bound service account, which the v1 Bugbot
107
+ // storage proxy cannot resolve; author KV, CAS coordination, and the
108
+ // eval/A-B tables speak the AgentSDK v2 KV proxy instead. It also carries
109
+ // the cursor-hosted marker, so GET /v1/sessions prefers the durable list
110
+ // (session records are on the framework store, which the composed core
111
+ // lists).
112
+ const kv = cursorHostedStorageV2({ resolveApiKey });
113
113
  return defineStorage({
114
114
  name: "cursor-hosted (framework files)",
115
115
  policy,
@@ -117,7 +117,10 @@ export function selectFrameworkStorageDefinition(
117
117
  ...composeFrameworkStorage({
118
118
  kv,
119
119
  files: fileSinkStorageCore(
120
- cursorHostedFiles({ storeSourceId: frameworkStoreId, resolveApiKey })
120
+ cursorHostedFiles({
121
+ resolveStoreSourceId: () => cursorFrameworkStoreSourceId(envSnapshot),
122
+ resolveApiKey,
123
+ })
121
124
  ),
122
125
  }),
123
126
  // CAS stays on the KV proxy but must refuse framework-file keys, or a
@@ -0,0 +1,42 @@
1
+ import type { ChannelHandlerArgs } from "../types.js";
2
+
3
+ /**
4
+ * Hosted-admission hook a channel pack attaches to its definition.
5
+ *
6
+ * Hosted delivery looks this up from the mounted definition — it does not
7
+ * switch on `channelKind`. A new forge implements `dispatch` / `getOutcome`
8
+ * next to its webhook handler and calls {@link attachHostedAdmissionAdapter}
9
+ * from the channel constructor.
10
+ */
11
+ export type HostedAdmissionDispatchOutcome = "skip" | "task";
12
+
13
+ export type HostedAdmissionAdapter = {
14
+ kind: string;
15
+ /**
16
+ * Optional wrap of the capturing `send` / `waitUntil` args (GitHub uses
17
+ * this to propagate background-task errors). Identity when omitted.
18
+ */
19
+ prepareArgs?(args: ChannelHandlerArgs): ChannelHandlerArgs;
20
+ dispatch(input: {
21
+ eventType: string;
22
+ payload: unknown;
23
+ deliveryId: string;
24
+ args: ChannelHandlerArgs;
25
+ }): Promise<Response>;
26
+ getOutcome(response: Response): HostedAdmissionDispatchOutcome | undefined;
27
+ };
28
+
29
+ const adapters = new WeakMap<object, HostedAdmissionAdapter>();
30
+
31
+ export function attachHostedAdmissionAdapter(
32
+ definition: object,
33
+ adapter: HostedAdmissionAdapter
34
+ ): void {
35
+ adapters.set(definition, adapter);
36
+ }
37
+
38
+ export function getHostedAdmissionAdapter(
39
+ definition: object
40
+ ): HostedAdmissionAdapter | undefined {
41
+ return adapters.get(definition);
42
+ }
@@ -18,7 +18,12 @@ export type HostedAdmissionManagedAutomation = {
18
18
  export type HostedAdmission = {
19
19
  v: 2;
20
20
  channelId: string;
21
- channelKind: "github";
21
+ /**
22
+ * Mailbox / subscription channel kind (`github`, `origin`, …). The guest
23
+ * resolves dispatch from the mounted definition's hosted-admission
24
+ * adapter; this field is not an allowlist.
25
+ */
26
+ channelKind: string;
22
27
  eventType: string;
23
28
  deliveryId: string;
24
29
  sessionMode: "event" | "continuation";
@@ -107,7 +112,7 @@ export function parseHostedAdmission(
107
112
  !Object.hasOwn(body, "payload") ||
108
113
  body.v !== HOSTED_DELIVERY_PROTOCOL_VERSION ||
109
114
  !boundedString(body.channelId, 128) ||
110
- body.channelKind !== "github" ||
115
+ !boundedString(body.channelKind, 128) ||
111
116
  !boundedString(body.eventType, 128) ||
112
117
  !boundedString(body.deliveryId, 256) ||
113
118
  (body.sessionMode !== "event" && body.sessionMode !== "continuation") ||
@@ -1,10 +1,4 @@
1
1
  import { randomBytes } from "node:crypto";
2
- import {
3
- dispatchGitHubWebhook,
4
- getGitHubChannelOptions,
5
- getGitHubDispatchOutcome,
6
- withPropagatingGitHubBackgroundErrors,
7
- } from "../channels/github/github-channel.js";
8
2
  import type {
9
3
  AuthPolicy,
10
4
  ChannelHandlerArgs,
@@ -14,6 +8,10 @@ import {
14
8
  createDeferredChannelSession,
15
9
  DeferredChannelSessionError,
16
10
  } from "./deferred-channel-session.js";
11
+ import {
12
+ getHostedAdmissionAdapter,
13
+ type HostedAdmissionAdapter,
14
+ } from "./hosted-admission-adapter.js";
17
15
  import {
18
16
  HostedAdmissionLocalSendError,
19
17
  runDuringHostedAdmission,
@@ -30,12 +28,19 @@ import {
30
28
  import {
31
29
  abortReasonFromTurnStatus,
32
30
  HOSTED_EXECUTION_DIAG_RUNNING_STATUS,
31
+ hostedErrorStackSnippet,
33
32
  hostedExecutionDiagId,
34
33
  writeHostedExecutionDiag,
35
34
  } from "./hosted-execution-diag.js";
36
35
  import { recordHostedManagedAutomation } from "./hosted-managed-automation.js";
37
36
  import { errorResponse, readJsonObject } from "./http-channel.js";
37
+ import type { LogRingEntry } from "./log-ring.js";
38
38
  import type { Router } from "./router.js";
39
+ import {
40
+ type SessionRunExecutionWrite,
41
+ serializeSessionRunError,
42
+ snapshotSessionRunLogs,
43
+ } from "./session-run-log.js";
39
44
 
40
45
  type DispatchInput = {
41
46
  delivery: HostedAdmission;
@@ -115,17 +120,20 @@ function nonRetryableRejection(error: unknown): AdmissionDispatch | undefined {
115
120
  }
116
121
 
117
122
  /**
118
- * Run authored admission without creating a framework session. V1 GitHub
123
+ * Run authored admission without creating a framework session. Authored
119
124
  * `task` callbacks execute as sessionless work; the first `send` is captured
120
125
  * and executed only after the control plane allocates `ses_…`. Capturing
121
126
  * does not terminate the caller — `send` returns an inert deferred handle so
122
127
  * a task body runs to completion before the admission response is computed.
128
+ *
129
+ * Dispatch is the adapter the mounted channel attached. Hosted delivery
130
+ * does not switch on `channelKind`.
123
131
  */
124
132
  export async function dispatchHostedAdmission(
125
133
  input: DispatchInput
126
134
  ): Promise<AdmissionDispatch> {
127
- const github = getGitHubChannelOptions(input.definition);
128
- if (github === undefined) {
135
+ const adapter = getHostedAdmissionAdapter(input.definition);
136
+ if (adapter === undefined || adapter.kind !== input.delivery.channelKind) {
129
137
  return {
130
138
  response: Response.json(
131
139
  { ok: false, error: "channel_kind_mismatch" },
@@ -135,16 +143,16 @@ export async function dispatchHostedAdmission(
135
143
  }
136
144
  // The admission window marker follows the async graph into task bodies so
137
145
  // the engine can refuse local sends that would bypass the capture stub.
138
- return runDuringHostedAdmission(() => runAdmission(input, github));
146
+ return runDuringHostedAdmission(() => runAdmission(input, adapter));
139
147
  }
140
148
 
141
149
  async function runAdmission(
142
150
  input: DispatchInput,
143
- github: NonNullable<ReturnType<typeof getGitHubChannelOptions>>
151
+ adapter: HostedAdmissionAdapter
144
152
  ): Promise<AdmissionDispatch> {
145
153
  const background: Promise<unknown>[] = [];
146
154
  let captured: { message: string; options: SendMessageOptions } | undefined;
147
- const args = withPropagatingGitHubBackgroundErrors({
155
+ const capturingArgs: ChannelHandlerArgs = {
148
156
  ...input.args,
149
157
  send: async (message, options = {}) => {
150
158
  if (captured !== undefined) {
@@ -156,12 +164,12 @@ async function runAdmission(
156
164
  waitUntil: (promise) => {
157
165
  background.push(promise);
158
166
  },
159
- });
167
+ };
168
+ const args = adapter.prepareArgs?.(capturingArgs) ?? capturingArgs;
160
169
  let dispatched: Response;
161
170
  try {
162
- dispatched = await dispatchGitHubWebhook({
163
- options: github,
164
- eventName: input.delivery.eventType,
171
+ dispatched = await adapter.dispatch({
172
+ eventType: input.delivery.eventType,
165
173
  payload: input.delivery.payload,
166
174
  deliveryId: input.delivery.deliveryId,
167
175
  args,
@@ -212,7 +220,7 @@ async function runAdmission(
212
220
  },
213
221
  };
214
222
  }
215
- const outcome = getGitHubDispatchOutcome(dispatched);
223
+ const outcome = adapter.getOutcome(dispatched);
216
224
  if (outcome === undefined) {
217
225
  return {
218
226
  response: Response.json(
@@ -264,6 +272,15 @@ export function registerHostedDeliveryRoute(input: {
264
272
  * `hosted-execution.json` from that path after the POST returns.
265
273
  */
266
274
  stateRoot?: string;
275
+ /**
276
+ * Upsert this execution into the v2 session-level framework-store log.
277
+ * Called for the pre-turn `running` claim and every terminal outcome so
278
+ * a dead Node process still leaves a leftover. Soft-fail inside the
279
+ * store; this path still awaits so a parked pod cannot shed the write.
280
+ */
281
+ persistSessionRun?(write: SessionRunExecutionWrite): Promise<void>;
282
+ /** Snapshot of the process log ring at persist time. */
283
+ snapshotLogs?(): LogRingEntry[];
267
284
  }): void {
268
285
  const pending = new Map<
269
286
  string,
@@ -404,30 +421,64 @@ export function registerHostedDeliveryRoute(input: {
404
421
  abortReason?:
405
422
  | ReturnType<typeof abortReasonFromTurnStatus>
406
423
  | "execute_throw";
424
+ error?: unknown;
407
425
  }): Promise<void> => {
408
- if (input.stateRoot === undefined) {
409
- return;
410
- }
426
+ const durationMs = Math.max(
427
+ 0,
428
+ Math.round(performance.now() - startedAt)
429
+ );
411
430
  const message =
412
431
  fields.message === undefined
413
432
  ? undefined
414
433
  : boundedMessage(fields.message);
415
- await writeHostedExecutionDiag(input.stateRoot, {
416
- v: 1,
417
- executionId,
418
- writtenAt: new Date().toISOString(),
419
- sessionPublicId: execution.sessionPublicId,
420
- sessionId: fields.sessionId,
421
- turnStatus: fields.turnStatus,
422
- durationMs: Math.max(0, Math.round(performance.now() - startedAt)),
423
- ...(message === undefined ? {} : { message }),
424
- ...(message !== undefined && /abort/i.test(message)
425
- ? { signalAborted: true }
426
- : {}),
427
- ...(fields.abortReason === undefined
428
- ? {}
429
- : { abortReason: fields.abortReason }),
430
- });
434
+ const stack =
435
+ fields.error === undefined
436
+ ? undefined
437
+ : hostedErrorStackSnippet(fields.error);
438
+ if (input.stateRoot !== undefined) {
439
+ await writeHostedExecutionDiag(input.stateRoot, {
440
+ v: 1,
441
+ executionId,
442
+ writtenAt: new Date().toISOString(),
443
+ sessionPublicId: execution.sessionPublicId,
444
+ sessionId: fields.sessionId,
445
+ turnStatus: fields.turnStatus,
446
+ durationMs,
447
+ ...(message === undefined ? {} : { message }),
448
+ ...(stack === undefined || stack.length === 0 ? {} : { stack }),
449
+ ...(message !== undefined && /abort/i.test(message)
450
+ ? { signalAborted: true }
451
+ : {}),
452
+ ...(fields.abortReason === undefined
453
+ ? {}
454
+ : { abortReason: fields.abortReason }),
455
+ });
456
+ }
457
+ if (input.persistSessionRun === undefined) {
458
+ return;
459
+ }
460
+ const error =
461
+ fields.error === undefined
462
+ ? undefined
463
+ : serializeSessionRunError(fields.error);
464
+ try {
465
+ await input.persistSessionRun({
466
+ executionId,
467
+ writtenAt: new Date().toISOString(),
468
+ sessionPublicId: execution.sessionPublicId,
469
+ sessionId: fields.sessionId,
470
+ turnStatus: fields.turnStatus,
471
+ durationMs,
472
+ ...(fields.abortReason === undefined
473
+ ? {}
474
+ : { abortReason: fields.abortReason }),
475
+ ...(message === undefined ? {} : { message }),
476
+ ...(error === undefined ? {} : { error }),
477
+ logs: snapshotSessionRunLogs(input.snapshotLogs?.() ?? []),
478
+ });
479
+ } catch {
480
+ // Soft-fail: a store outage must not change the HTTP reply.
481
+ }
431
482
  };
432
483
  // Claim the file before the turn runs. The host reads it after its
433
484
  // own POST returns, which for a 9-minute timeout is while this turn
@@ -486,6 +537,7 @@ export function registerHostedDeliveryRoute(input: {
486
537
  turnStatus: "error",
487
538
  message: error instanceof Error ? error.message : String(error),
488
539
  abortReason: "execute_throw",
540
+ error,
489
541
  });
490
542
  throw error;
491
543
  }