@cursor/july 0.1.94 → 0.1.96

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 (332) hide show
  1. package/AGENTS.md +3 -4
  2. package/dist/channels/deployments/types.d.ts +1 -1
  3. package/dist/channels/deployments/types.d.ts.map +1 -1
  4. package/dist/channels/deployments/types.js +1 -0
  5. package/dist/channels/github/github-channel.d.ts.map +1 -1
  6. package/dist/channels/github/github-channel.js +14 -2
  7. package/dist/channels/github/types.d.ts +18 -3
  8. package/dist/channels/github/types.d.ts.map +1 -1
  9. package/dist/channels/origin/api.d.ts +59 -13
  10. package/dist/channels/origin/api.d.ts.map +1 -1
  11. package/dist/channels/origin/api.js +168 -27
  12. package/dist/channels/origin/binding.d.ts +2 -2
  13. package/dist/channels/origin/checks.d.ts +6 -6
  14. package/dist/channels/origin/checks.js +6 -6
  15. package/dist/channels/origin/cursor-account.d.ts +5 -3
  16. package/dist/channels/origin/cursor-account.d.ts.map +1 -1
  17. package/dist/channels/origin/cursor-account.js +5 -3
  18. package/dist/channels/origin/origin-channel.d.ts.map +1 -1
  19. package/dist/channels/origin/origin-channel.js +11 -3
  20. package/dist/channels/origin/origin-webhook.d.ts +11 -1
  21. package/dist/channels/origin/origin-webhook.d.ts.map +1 -1
  22. package/dist/channels/origin/origin-webhook.js +23 -3
  23. package/dist/channels/origin/types.d.ts +8 -0
  24. package/dist/channels/origin/types.d.ts.map +1 -1
  25. package/dist/channels/slack/api.d.ts +9 -0
  26. package/dist/channels/slack/api.d.ts.map +1 -1
  27. package/dist/channels/slack/api.js +36 -5
  28. package/dist/channels/slack/defaults.d.ts.map +1 -1
  29. package/dist/channels/slack/defaults.js +17 -46
  30. package/dist/channels/slack/dispatch.d.ts +7 -1
  31. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  32. package/dist/channels/slack/dispatch.js +47 -23
  33. package/dist/channels/slack/inbound.d.ts +8 -0
  34. package/dist/channels/slack/inbound.d.ts.map +1 -1
  35. package/dist/channels/slack/inbound.js +32 -0
  36. package/dist/channels/slack/live-delivery.d.ts +26 -29
  37. package/dist/channels/slack/live-delivery.d.ts.map +1 -1
  38. package/dist/channels/slack/live-delivery.js +172 -73
  39. package/dist/channels/slack/manifest.d.ts.map +1 -1
  40. package/dist/channels/slack/manifest.js +5 -1
  41. package/dist/channels/slack/nudge-carrier.d.ts +2 -0
  42. package/dist/channels/slack/nudge-carrier.d.ts.map +1 -1
  43. package/dist/channels/slack/nudge-carrier.js +48 -1
  44. package/dist/channels/slack/pr-ref.d.ts +7 -1
  45. package/dist/channels/slack/pr-ref.d.ts.map +1 -1
  46. package/dist/channels/slack/pr-ref.js +42 -23
  47. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  48. package/dist/channels/slack/slack-channel.js +2 -2
  49. package/dist/docs/404.html +2 -2
  50. package/dist/docs/ab.html +4 -4
  51. package/dist/docs/assets/{app.CFDEas4I.js → app.jXleCmOc.js} +1 -1
  52. package/dist/docs/assets/chunks/@localSearchIndexroot.DFoGuETX.js +1 -0
  53. package/dist/docs/assets/chunks/{VPLocalSearchBox.B1IIYpYS.js → VPLocalSearchBox.8LhyglIT.js} +1 -1
  54. package/dist/docs/assets/chunks/{theme.Ct4NSiLm.js → theme.9ged-pr2.js} +2 -2
  55. package/dist/docs/assets/index.md.CI93Ltlb.js +5 -0
  56. package/dist/docs/assets/{index.md.DRakGHFe.lean.js → index.md.CI93Ltlb.lean.js} +1 -1
  57. package/dist/docs/assets/{reference_cli.md.Cw6_ICYG.js → reference_cli.md.CCnG-nJx.js} +4 -2
  58. package/dist/docs/assets/{reference_cli.md.Cw6_ICYG.lean.js → reference_cli.md.CCnG-nJx.lean.js} +1 -1
  59. package/dist/docs/assets/{reference_skills.md.8son6Hjm.js → reference_skills.md.BFW9retM.js} +3 -3
  60. package/dist/docs/assets/{templates_agentic-owners.md.DqtPdm6f.js → templates_agentic-owners.md.BZSH4N9z.js} +1 -1
  61. package/dist/docs/assets/templates_code-wiki.md.CDYZIBFN.js +2 -0
  62. package/dist/docs/assets/templates_code-wiki.md.CDYZIBFN.lean.js +1 -0
  63. package/dist/docs/assets/{templates_demo.md.DhFcWN6j.js → templates_demo.md.BeQX9V3H.js} +1 -1
  64. package/dist/docs/assets/{templates_pr-autofixer.md.DU7dQpor.js → templates_pr-autofixer.md.x5zl6-GT.js} +2 -2
  65. package/dist/docs/assets/{templates_pr-autofixer.md.DU7dQpor.lean.js → templates_pr-autofixer.md.x5zl6-GT.lean.js} +1 -1
  66. package/dist/docs/assets/templates_security-help.md.C3Ny_Qr2.js +4 -0
  67. package/dist/docs/assets/templates_security-help.md.C3Ny_Qr2.lean.js +1 -0
  68. package/dist/docs/assets/{templates_security-reviewer.md.CTa7u_l1.js → templates_security-reviewer.md.lshxbCLK.js} +2 -2
  69. package/dist/docs/assets/{templates_security-reviewer.md.CTa7u_l1.lean.js → templates_security-reviewer.md.lshxbCLK.lean.js} +1 -1
  70. package/dist/docs/assets/{templates_triage.md.CVlpctKS.js → templates_triage.md.Co4UNzkZ.js} +3 -3
  71. package/dist/docs/assets/{templates_triage.md.CVlpctKS.lean.js → templates_triage.md.Co4UNzkZ.lean.js} +1 -1
  72. package/dist/docs/building-with-agents.html +4 -4
  73. package/dist/docs/concepts.html +4 -4
  74. package/dist/docs/deployment.html +4 -4
  75. package/dist/docs/evals.html +4 -4
  76. package/dist/docs/guides/agent-to-agent.html +4 -4
  77. package/dist/docs/guides/cloud-runtime.html +4 -4
  78. package/dist/docs/guides/convert-automation.html +4 -4
  79. package/dist/docs/guides/github.html +4 -4
  80. package/dist/docs/guides/human-in-the-loop.html +4 -4
  81. package/dist/docs/guides/mcp-oauth.html +4 -4
  82. package/dist/docs/guides/opentelemetry.html +4 -4
  83. package/dist/docs/guides/slack.html +4 -4
  84. package/dist/docs/guides/webhooks.html +4 -4
  85. package/dist/docs/hashmap.json +1 -1
  86. package/dist/docs/hillclimbing.html +4 -4
  87. package/dist/docs/index.html +6 -6
  88. package/dist/docs/index.md +5 -1
  89. package/dist/docs/llms-full.txt +189 -26
  90. package/dist/docs/llms.txt +2 -0
  91. package/dist/docs/quickstart.html +4 -4
  92. package/dist/docs/reference/agent-config.html +4 -4
  93. package/dist/docs/reference/artifacts.html +4 -4
  94. package/dist/docs/reference/channels.html +4 -4
  95. package/dist/docs/reference/cli.html +8 -6
  96. package/dist/docs/reference/cli.md +4 -1
  97. package/dist/docs/reference/connections.html +4 -4
  98. package/dist/docs/reference/hooks.html +4 -4
  99. package/dist/docs/reference/http-api.html +4 -4
  100. package/dist/docs/reference/instructions.html +4 -4
  101. package/dist/docs/reference/playground.html +4 -4
  102. package/dist/docs/reference/project-layout.html +4 -4
  103. package/dist/docs/reference/prompt.html +4 -4
  104. package/dist/docs/reference/schedules.html +4 -4
  105. package/dist/docs/reference/sessions.html +4 -4
  106. package/dist/docs/reference/skills.html +7 -7
  107. package/dist/docs/reference/subagents.html +4 -4
  108. package/dist/docs/reference/tools.html +4 -4
  109. package/dist/docs/scaffolding-agents.html +4 -4
  110. package/dist/docs/storage.html +4 -4
  111. package/dist/docs/templates/agentic-owners.html +7 -7
  112. package/dist/docs/templates/agentic-owners.md +1 -1
  113. package/dist/docs/templates/code-wiki.html +28 -0
  114. package/dist/docs/templates/code-wiki.md +91 -0
  115. package/dist/docs/templates/demo.html +6 -6
  116. package/dist/docs/templates/demo.md +3 -2
  117. package/dist/docs/templates/pr-autofixer.html +6 -6
  118. package/dist/docs/templates/pr-autofixer.md +7 -13
  119. package/dist/docs/templates/security-help.html +30 -0
  120. package/dist/docs/templates/security-help.md +65 -0
  121. package/dist/docs/templates/security-reviewer.html +6 -6
  122. package/dist/docs/templates/security-reviewer.md +1 -2
  123. package/dist/docs/templates/triage.html +7 -7
  124. package/dist/docs/templates/triage.md +2 -6
  125. package/dist/docs/troubleshooting.html +4 -4
  126. package/dist/files-backends/cursor-hosted.d.ts +26 -0
  127. package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
  128. package/dist/files-backends/cursor-hosted.js +32 -4
  129. package/dist/files.d.ts +2 -0
  130. package/dist/files.d.ts.map +1 -1
  131. package/dist/files.js +5 -0
  132. package/dist/internal/advertise-tools.d.ts +2 -0
  133. package/dist/internal/advertise-tools.d.ts.map +1 -1
  134. package/dist/internal/advertise-tools.js +15 -1
  135. package/dist/internal/bounded.d.ts +7 -0
  136. package/dist/internal/bounded.d.ts.map +1 -0
  137. package/dist/internal/bounded.js +32 -0
  138. package/dist/internal/cli-deploy.d.ts.map +1 -1
  139. package/dist/internal/cli-deploy.js +142 -7
  140. package/dist/internal/conversation-mirror.d.ts +85 -0
  141. package/dist/internal/conversation-mirror.d.ts.map +1 -0
  142. package/dist/internal/conversation-mirror.js +312 -0
  143. package/dist/internal/cursor/backend-client.d.ts.map +1 -1
  144. package/dist/internal/cursor/backend-client.js +22 -48
  145. package/dist/internal/cursor/session-token.d.ts +45 -0
  146. package/dist/internal/cursor/session-token.d.ts.map +1 -0
  147. package/dist/internal/cursor/session-token.js +99 -0
  148. package/dist/internal/cursor-agent-template.d.ts +1 -1
  149. package/dist/internal/cursor-agent-template.d.ts.map +1 -1
  150. package/dist/internal/cursor-agent-template.js +1 -0
  151. package/dist/internal/deferred-channel-session.d.ts +20 -0
  152. package/dist/internal/deferred-channel-session.d.ts.map +1 -0
  153. package/dist/internal/deferred-channel-session.js +62 -0
  154. package/dist/internal/deploy-client.d.ts +13 -1
  155. package/dist/internal/deploy-client.d.ts.map +1 -1
  156. package/dist/internal/deploy-client.js +11 -1
  157. package/dist/internal/deploy-manifest.d.ts.map +1 -1
  158. package/dist/internal/deploy-manifest.js +11 -5
  159. package/dist/internal/discovery.d.ts.map +1 -1
  160. package/dist/internal/discovery.js +22 -2
  161. package/dist/internal/framework-file-storage.d.ts +61 -0
  162. package/dist/internal/framework-file-storage.d.ts.map +1 -0
  163. package/dist/internal/framework-file-storage.js +204 -0
  164. package/dist/internal/framework-storage-selection.d.ts +38 -16
  165. package/dist/internal/framework-storage-selection.d.ts.map +1 -1
  166. package/dist/internal/framework-storage-selection.js +78 -17
  167. package/dist/internal/hosted-admission-context.d.ts +20 -0
  168. package/dist/internal/hosted-admission-context.d.ts.map +1 -0
  169. package/dist/internal/hosted-admission-context.js +31 -0
  170. package/dist/internal/hosted-delivery-protocol.d.ts +5 -0
  171. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
  172. package/dist/internal/hosted-delivery-protocol.js +33 -1
  173. package/dist/internal/hosted-delivery.d.ts +11 -2
  174. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  175. package/dist/internal/hosted-delivery.js +79 -35
  176. package/dist/internal/hosted-managed-automation.d.ts +30 -0
  177. package/dist/internal/hosted-managed-automation.d.ts.map +1 -0
  178. package/dist/internal/hosted-managed-automation.js +58 -0
  179. package/dist/internal/init-project.d.ts.map +1 -1
  180. package/dist/internal/init-project.js +2 -0
  181. package/dist/internal/install-cursor-skills.d.ts.map +1 -1
  182. package/dist/internal/install-cursor-skills.js +1 -3
  183. package/dist/internal/managed-delivery.d.ts +80 -0
  184. package/dist/internal/managed-delivery.d.ts.map +1 -0
  185. package/dist/internal/managed-delivery.js +86 -0
  186. package/dist/internal/review-comments.d.ts.map +1 -1
  187. package/dist/internal/review-comments.js +10 -98
  188. package/dist/internal/runtime-dispatch-runner.d.ts +5 -1
  189. package/dist/internal/runtime-dispatch-runner.d.ts.map +1 -1
  190. package/dist/internal/runtime-dispatch-runner.js +7 -0
  191. package/dist/internal/scm/pr-url.d.ts +14 -0
  192. package/dist/internal/scm/pr-url.d.ts.map +1 -0
  193. package/dist/internal/scm/pr-url.js +65 -0
  194. package/dist/internal/sdk-runner.d.ts +25 -0
  195. package/dist/internal/sdk-runner.d.ts.map +1 -1
  196. package/dist/internal/sdk-runner.js +70 -0
  197. package/dist/internal/server.d.ts.map +1 -1
  198. package/dist/internal/server.js +11 -2
  199. package/dist/internal/session-engine.d.ts +13 -0
  200. package/dist/internal/session-engine.d.ts.map +1 -1
  201. package/dist/internal/session-engine.js +71 -3
  202. package/dist/internal/steering.d.ts +15 -0
  203. package/dist/internal/steering.d.ts.map +1 -0
  204. package/dist/internal/steering.js +18 -0
  205. package/dist/playground/assets/index-B1DDvBeC.css +1 -0
  206. package/dist/playground/assets/{index-B3JCyigB.js → index-Cx9CclK_.js} +47 -47
  207. package/dist/playground/index.html +2 -2
  208. package/dist/storage-backends/cursor-hosted.d.ts +8 -0
  209. package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
  210. package/dist/storage-backends/cursor-hosted.js +4 -3
  211. package/dist/types.d.ts +2 -1
  212. package/dist/types.d.ts.map +1 -1
  213. package/docs/README.md +5 -1
  214. package/docs/reference/cli.md +4 -1
  215. package/docs/templates/agentic-owners.md +1 -1
  216. package/docs/templates/code-wiki.md +96 -0
  217. package/docs/templates/demo.md +3 -2
  218. package/docs/templates/pr-autofixer.md +7 -13
  219. package/docs/templates/security-help.md +70 -0
  220. package/docs/templates/security-reviewer.md +1 -2
  221. package/docs/templates/triage.md +2 -6
  222. package/package.json +2 -2
  223. package/skills/ab/SKILL.md +13 -97
  224. package/skills/create-agent/SKILL.md +123 -223
  225. package/skills/debug/SKILL.md +34 -68
  226. package/skills/evals/SKILL.md +55 -180
  227. package/skills/framework-map/SKILL.md +83 -145
  228. package/skills/github/SKILL.md +53 -111
  229. package/skills/hillclimb/SKILL.md +40 -163
  230. package/skills/mcp-auth/SKILL.md +48 -107
  231. package/skills/otel/SKILL.md +22 -68
  232. package/skills/setup-slack/SKILL.md +77 -208
  233. package/src/channels/deployments/types.ts +1 -0
  234. package/src/channels/github/github-channel.ts +23 -8
  235. package/src/channels/github/types.ts +19 -2
  236. package/src/channels/origin/api.ts +242 -30
  237. package/src/channels/origin/binding.ts +2 -2
  238. package/src/channels/origin/checks.ts +6 -6
  239. package/src/channels/origin/cursor-account.ts +5 -3
  240. package/src/channels/origin/origin-channel.ts +13 -1
  241. package/src/channels/origin/origin-webhook.ts +27 -3
  242. package/src/channels/origin/types.ts +8 -0
  243. package/src/channels/slack/api.ts +41 -5
  244. package/src/channels/slack/defaults.ts +15 -49
  245. package/src/channels/slack/dispatch.ts +56 -22
  246. package/src/channels/slack/inbound.ts +43 -0
  247. package/src/channels/slack/live-delivery.ts +235 -114
  248. package/src/channels/slack/manifest.ts +5 -1
  249. package/src/channels/slack/nudge-carrier.ts +48 -1
  250. package/src/channels/slack/pr-ref.ts +56 -25
  251. package/src/channels/slack/slack-channel.ts +2 -0
  252. package/src/files-backends/cursor-hosted.ts +41 -2
  253. package/src/files.ts +11 -0
  254. package/src/internal/advertise-tools.ts +18 -2
  255. package/src/internal/bounded.ts +28 -0
  256. package/src/internal/cli-deploy.ts +183 -7
  257. package/src/internal/conversation-mirror.ts +406 -0
  258. package/src/internal/cursor/backend-client.ts +34 -58
  259. package/src/internal/cursor/session-token.ts +115 -0
  260. package/src/internal/cursor-agent-template.ts +1 -0
  261. package/src/internal/deferred-channel-session.ts +61 -0
  262. package/src/internal/deploy-client.ts +24 -1
  263. package/src/internal/deploy-manifest.ts +10 -5
  264. package/src/internal/discovery.ts +25 -2
  265. package/src/internal/framework-file-storage.ts +222 -0
  266. package/src/internal/framework-storage-selection.ts +101 -19
  267. package/src/internal/hosted-admission-context.ts +37 -0
  268. package/src/internal/hosted-delivery-protocol.ts +44 -1
  269. package/src/internal/hosted-delivery.ts +105 -40
  270. package/src/internal/hosted-managed-automation.ts +72 -0
  271. package/src/internal/init-project.ts +2 -0
  272. package/src/internal/install-cursor-skills.ts +1 -4
  273. package/src/internal/managed-delivery.ts +125 -0
  274. package/src/internal/review-comments.ts +10 -113
  275. package/src/internal/runtime-dispatch-runner.ts +10 -0
  276. package/src/internal/scm/pr-url.ts +95 -0
  277. package/src/internal/sdk-runner.ts +103 -0
  278. package/src/internal/server.ts +12 -0
  279. package/src/internal/session-engine.ts +76 -4
  280. package/src/internal/steering.ts +17 -0
  281. package/src/storage-backends/cursor-hosted.ts +10 -1
  282. package/src/types.ts +2 -1
  283. package/templates/agentic-owners/README.md +1 -1
  284. package/templates/agentic-owners/agent/agent.ts +0 -10
  285. package/templates/agentic-owners/agent/channels/github.ts +5 -14
  286. package/templates/agentic-owners/agent/lib/config.ts +0 -8
  287. package/templates/agentic-owners/agent/lib/review.ts +2 -15
  288. package/templates/agentic-owners/agent/tools/record_review.ts +2 -4
  289. package/templates/code-wiki/README.md +34 -0
  290. package/templates/code-wiki/agent/agent.ts +8 -0
  291. package/templates/code-wiki/agent/channels/github.ts +144 -0
  292. package/templates/code-wiki/agent/instructions.md +39 -0
  293. package/templates/code-wiki/agent/lib/repos.ts +5 -0
  294. package/templates/code-wiki/agent/lib/wiki.ts +22 -0
  295. package/templates/code-wiki/agent/tools/apply_wiki.ts +219 -0
  296. package/templates/code-wiki/evals/evals.config.ts +5 -0
  297. package/templates/code-wiki/evals/wiki.eval.ts +132 -0
  298. package/templates/code-wiki/init.json +25 -0
  299. package/templates/code-wiki/package.json +18 -0
  300. package/templates/code-wiki/tsconfig.json +12 -0
  301. package/templates/demo/agent/agent.ts +0 -10
  302. package/templates/pr-autofixer/README.md +0 -2
  303. package/templates/pr-autofixer/agent/agent.ts +0 -11
  304. package/templates/pr-autofixer/agent/channels/slack.ts +0 -7
  305. package/templates/pr-autofixer/agent/lib/pr-state.ts +5 -17
  306. package/templates/pr-autofixer/agent/lib/repos.ts +0 -1
  307. package/templates/security-help/README.md +2 -2
  308. package/templates/security-help/agent/agent.ts +1 -2
  309. package/templates/security-help/agent/channels/slack.ts +0 -3
  310. package/templates/security-help/agent/instructions.md +9 -10
  311. package/templates/security-help/agent/skills/access-request.md +1 -1
  312. package/templates/security-help/agent/skills/faq.md +31 -0
  313. package/templates/security-help/agent/skills/security-playbooks.md +1 -1
  314. package/templates/security-help/package.json +1 -2
  315. package/templates/security-reviewer/agent/agent.ts +0 -10
  316. package/templates/triage/agent/agent.ts +0 -10
  317. package/templates/triage/agent/channels/queue.ts +1 -1
  318. package/templates/triage/agent/channels/webhook.ts +1 -3
  319. package/dist/docs/assets/chunks/@localSearchIndexroot.DU3U2Ij2.js +0 -1
  320. package/dist/docs/assets/index.md.DRakGHFe.js +0 -5
  321. package/dist/internal/deployment-scm-event-stream.d.ts +0 -116
  322. package/dist/internal/deployment-scm-event-stream.d.ts.map +0 -1
  323. package/dist/internal/deployment-scm-event-stream.js +0 -474
  324. package/dist/playground/assets/index-D9N7-q97.css +0 -1
  325. package/src/internal/deployment-scm-event-stream.ts +0 -593
  326. package/templates/security-help/agent/knowledge/faq/approvals.md +0 -5
  327. package/templates/security-help/agent/knowledge/faq/channels.md +0 -6
  328. package/templates/security-help/agent/knowledge/faq/phishing.md +0 -10
  329. package/templates/security-help/agent/skills/security-first-pass.md +0 -15
  330. /package/dist/docs/assets/{reference_skills.md.8son6Hjm.lean.js → reference_skills.md.BFW9retM.lean.js} +0 -0
  331. /package/dist/docs/assets/{templates_agentic-owners.md.DqtPdm6f.lean.js → templates_agentic-owners.md.BZSH4N9z.lean.js} +0 -0
  332. /package/dist/docs/assets/{templates_demo.md.DhFcWN6j.lean.js → templates_demo.md.BeQX9V3H.lean.js} +0 -0
@@ -10,6 +10,14 @@ import type {
10
10
  ChannelHandlerArgs,
11
11
  SendMessageOptions,
12
12
  } from "../types.js";
13
+ import {
14
+ createDeferredChannelSession,
15
+ DeferredChannelSessionError,
16
+ } from "./deferred-channel-session.js";
17
+ import {
18
+ HostedAdmissionLocalSendError,
19
+ runDuringHostedAdmission,
20
+ } from "./hosted-admission-context.js";
13
21
  import {
14
22
  HOSTED_ADMISSION_PATH,
15
23
  HOSTED_DELIVERY_HEADER,
@@ -19,6 +27,7 @@ import {
19
27
  parseHostedAdmission,
20
28
  parseHostedExecution,
21
29
  } from "./hosted-delivery-protocol.js";
30
+ import { recordHostedManagedAutomation } from "./hosted-managed-automation.js";
22
31
  import { errorResponse, readJsonObject } from "./http-channel.js";
23
32
  import type { Router } from "./router.js";
24
33
 
@@ -45,19 +54,66 @@ type ExecutionReply = {
45
54
  body: Record<string, unknown>;
46
55
  };
47
56
 
48
- class HostedSendAdmitted extends Error {
49
- constructor(
50
- readonly prompt: string,
51
- readonly options: SendMessageOptions
52
- ) {
53
- super("hosted channel admitted a send");
57
+ /**
58
+ * A second `send()` in one delivery is a deterministic authored bug — the
59
+ * wire protocol carries exactly one pending send per delivery — so it must
60
+ * fail the delivery exactly once. It surfaces as a 422 because the control
61
+ * plane retries 5xx admissions (fresh pod, side effects re-run, identical
62
+ * failure, up to the Temporal attempt cap); a non-5xx/408/429 status makes
63
+ * it reject the delivery non-retryably instead.
64
+ */
65
+ class HostedSendLimitExceeded extends Error {
66
+ constructor() {
67
+ super(
68
+ "The hosted delivery protocol carries exactly one pending send per " +
69
+ "delivery, and this delivery already captured one. Combine both " +
70
+ "messages into a single send(), or split the work across deliveries."
71
+ );
54
72
  }
55
73
  }
56
74
 
75
+ // Authored/task-derived text stays bounded on this internal response path
76
+ // (and is never persisted to Temporal history by the control plane).
77
+ const MAX_ERROR_MESSAGE_LENGTH = 1024;
78
+
79
+ function boundedMessage(text: string): string {
80
+ return text.length > MAX_ERROR_MESSAGE_LENGTH
81
+ ? `${text.slice(0, MAX_ERROR_MESSAGE_LENGTH)}…`
82
+ : text;
83
+ }
84
+
85
+ /**
86
+ * Classify deterministic authored protocol violations as non-retryable 422
87
+ * admissions. Anything else returns `undefined` so callers fall through to
88
+ * the existing (retryable or rethrow) handling.
89
+ */
90
+ function nonRetryableRejection(error: unknown): AdmissionDispatch | undefined {
91
+ const code =
92
+ error instanceof HostedSendLimitExceeded
93
+ ? "hosted_send_limit_exceeded"
94
+ : error instanceof DeferredChannelSessionError
95
+ ? "hosted_deferred_session_unusable"
96
+ : error instanceof HostedAdmissionLocalSendError
97
+ ? "hosted_local_send_rejected"
98
+ : undefined;
99
+ if (code === undefined) {
100
+ return undefined;
101
+ }
102
+ return {
103
+ response: errorResponse(
104
+ 422,
105
+ code,
106
+ boundedMessage((error as Error).message)
107
+ ),
108
+ };
109
+ }
110
+
57
111
  /**
58
112
  * Run authored admission without creating a framework session. V1 GitHub
59
- * `task` callbacks execute as sessionless work; `send` is captured and
60
- * resumed only after the control plane allocates `ses_…`.
113
+ * `task` callbacks execute as sessionless work; the first `send` is captured
114
+ * and executed only after the control plane allocates `ses_…`. Capturing
115
+ * does not terminate the caller — `send` returns an inert deferred handle so
116
+ * a task body runs to completion before the admission response is computed.
61
117
  */
62
118
  export async function dispatchHostedAdmission(
63
119
  input: DispatchInput
@@ -71,24 +127,28 @@ export async function dispatchHostedAdmission(
71
127
  ),
72
128
  };
73
129
  }
130
+ // The admission window marker follows the async graph into task bodies so
131
+ // the engine can refuse local sends that would bypass the capture stub.
132
+ return runDuringHostedAdmission(() => runAdmission(input, github));
133
+ }
74
134
 
135
+ async function runAdmission(
136
+ input: DispatchInput,
137
+ github: NonNullable<ReturnType<typeof getGitHubChannelOptions>>
138
+ ): Promise<AdmissionDispatch> {
75
139
  const background: Promise<unknown>[] = [];
76
- let deferredSend: HostedSendAdmitted | undefined;
140
+ let captured: { message: string; options: SendMessageOptions } | undefined;
77
141
  const args = withPropagatingGitHubBackgroundErrors({
78
142
  ...input.args,
79
143
  send: async (message, options = {}) => {
80
- throw new HostedSendAdmitted(message, options);
144
+ if (captured !== undefined) {
145
+ throw new HostedSendLimitExceeded();
146
+ }
147
+ captured = { message, options };
148
+ return createDeferredChannelSession();
81
149
  },
82
150
  waitUntil: (promise) => {
83
- background.push(
84
- promise.catch((error: unknown) => {
85
- if (error instanceof HostedSendAdmitted) {
86
- deferredSend = error;
87
- return;
88
- }
89
- throw error;
90
- })
91
- );
151
+ background.push(promise);
92
152
  },
93
153
  });
94
154
  let dispatched: Response;
@@ -101,20 +161,9 @@ export async function dispatchHostedAdmission(
101
161
  args,
102
162
  });
103
163
  } catch (error) {
104
- if (error instanceof HostedSendAdmitted) {
105
- return {
106
- response: Response.json({
107
- ok: true,
108
- v: HOSTED_DELIVERY_PROTOCOL_VERSION,
109
- outcome: "send",
110
- }),
111
- pendingSend: {
112
- channelId: input.delivery.channelId,
113
- message: error.prompt,
114
- options: error.options,
115
- mailboxContinuationKey: input.delivery.mailboxContinuationKey,
116
- },
117
- };
164
+ const rejected = nonRetryableRejection(error);
165
+ if (rejected !== undefined) {
166
+ return rejected;
118
167
  }
119
168
  throw error;
120
169
  }
@@ -129,15 +178,20 @@ export async function dispatchHostedAdmission(
129
178
 
130
179
  try {
131
180
  await Promise.all(background);
132
- } catch {
181
+ } catch (error) {
182
+ const rejected = nonRetryableRejection(error);
183
+ if (rejected !== undefined) {
184
+ return rejected;
185
+ }
133
186
  return {
134
- response: Response.json(
135
- { ok: false, error: "background_dispatch_failed" },
136
- { status: 503 }
187
+ response: errorResponse(
188
+ 503,
189
+ "background_dispatch_failed",
190
+ boundedMessage(error instanceof Error ? error.message : String(error))
137
191
  ),
138
192
  };
139
193
  }
140
- if (deferredSend !== undefined) {
194
+ if (captured !== undefined) {
141
195
  return {
142
196
  response: Response.json({
143
197
  ok: true,
@@ -146,8 +200,8 @@ export async function dispatchHostedAdmission(
146
200
  }),
147
201
  pendingSend: {
148
202
  channelId: input.delivery.channelId,
149
- message: deferredSend.prompt,
150
- options: deferredSend.options,
203
+ message: captured.message,
204
+ options: captured.options,
151
205
  mailboxContinuationKey: input.delivery.mailboxContinuationKey,
152
206
  },
153
207
  };
@@ -191,6 +245,13 @@ export function registerHostedDeliveryRoute(input: {
191
245
  channelId: string,
192
246
  sessionPublicId?: string
193
247
  ): ChannelHandlerArgs;
248
+ /**
249
+ * Await the session's durable mirror (dispatch chain + storage queue)
250
+ * before the execution reply: the control plane may park the pod the
251
+ * moment the reply lands, and a shed session-record flush would strand
252
+ * the conversation on the next wake.
253
+ */
254
+ drainSessionDurability?(sessionId: string): Promise<void>;
194
255
  }): void {
195
256
  const pending = new Map<
196
257
  string,
@@ -241,6 +302,7 @@ export function registerHostedDeliveryRoute(input: {
241
302
  )
242
303
  );
243
304
  }
305
+ recordHostedManagedAutomation(delivery);
244
306
  const channel = input.channels.find(
245
307
  (candidate) => candidate.id === delivery.channelId
246
308
  );
@@ -332,6 +394,9 @@ export function registerHostedDeliveryRoute(input: {
332
394
  },
333
395
  });
334
396
  const outcome = await session.waitForCompletion();
397
+ // Failed turns drain too: their record/continuation updates must
398
+ // survive the park just like a finished turn's.
399
+ await input.drainSessionDurability?.(session.id);
335
400
  if (outcome.status !== "finished") {
336
401
  return {
337
402
  status: 503,
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Managed-automation envelope slices by provider delivery id (plan 0002
3
+ * G2), recorded at hosted admission so channel code running the delivery's
4
+ * task (or session turn) can attach the customer's MCP servers through the
5
+ * control-plane relay. In-memory and TTL-bounded like the hosted pending-
6
+ * send table: the envelope slice carries names only (never credentials)
7
+ * and evaporates with the process.
8
+ *
9
+ * A leaf module (protocol type import only) so product channels can read
10
+ * it without pulling the hosted-delivery route — and its session-engine
11
+ * dependency graph — into their bundles.
12
+ *
13
+ * INTERNAL: first-party multi-tenant deployment plumbing. Deliberately
14
+ * excluded from the published `@cursor/july` npm package (see the `files`
15
+ * whitelist); consumed by internal deployments via relative source imports.
16
+ */
17
+
18
+ import type { HostedAdmissionManagedAutomation } from "./hosted-delivery-protocol.js";
19
+
20
+ const managedAutomationByDelivery = new Map<
21
+ string,
22
+ { managedAutomation: HostedAdmissionManagedAutomation; expiresAt: number }
23
+ >();
24
+ /** Long enough to outlive a slow review run kicked off by the delivery. */
25
+ const MANAGED_AUTOMATION_TTL_MS = 60 * 60_000;
26
+ const MANAGED_AUTOMATION_MAX_ENTRIES = 10_000;
27
+
28
+ export function recordHostedManagedAutomation(delivery: {
29
+ deliveryId: string;
30
+ managedAutomation?: HostedAdmissionManagedAutomation;
31
+ }): void {
32
+ if (delivery.managedAutomation === undefined) {
33
+ return;
34
+ }
35
+ const now = Date.now();
36
+ for (const [key, entry] of managedAutomationByDelivery) {
37
+ if (entry.expiresAt <= now) {
38
+ managedAutomationByDelivery.delete(key);
39
+ }
40
+ }
41
+ if (managedAutomationByDelivery.size >= MANAGED_AUTOMATION_MAX_ENTRIES) {
42
+ managedAutomationByDelivery.clear();
43
+ }
44
+ managedAutomationByDelivery.set(delivery.deliveryId, {
45
+ managedAutomation: delivery.managedAutomation,
46
+ expiresAt: now + MANAGED_AUTOMATION_TTL_MS,
47
+ });
48
+ }
49
+
50
+ /**
51
+ * The managed automation the control plane attributed to a hosted delivery,
52
+ * when the envelope carried one. Undefined for non-managed deliveries,
53
+ * expired entries, and non-hosted (webhook/stream) dispatch paths.
54
+ */
55
+ export function getHostedManagedAutomation(
56
+ deliveryId: string
57
+ ): HostedAdmissionManagedAutomation | undefined {
58
+ const entry = managedAutomationByDelivery.get(deliveryId);
59
+ if (entry === undefined) {
60
+ return undefined;
61
+ }
62
+ if (entry.expiresAt <= Date.now()) {
63
+ managedAutomationByDelivery.delete(deliveryId);
64
+ return undefined;
65
+ }
66
+ return entry.managedAutomation;
67
+ }
68
+
69
+ /** Drop recorded managed-automation slices (tests only). */
70
+ export function resetHostedManagedAutomationForTest(): void {
71
+ managedAutomationByDelivery.clear();
72
+ }
@@ -74,6 +74,7 @@ type TemplateEntry = {
74
74
 
75
75
  const TEMPLATES: Readonly<Record<TemplateName, TemplateEntry>> = {
76
76
  "agentic-owners": { dir: "agentic-owners" },
77
+ "code-wiki": { dir: "code-wiki" },
77
78
  demo: { dir: "demo" },
78
79
  "pr-autofixer": { dir: "pr-autofixer" },
79
80
  "security-help": { dir: "security-help" },
@@ -709,6 +710,7 @@ export function printInitGuide(): void {
709
710
  Scaffold a project, then open the playground:
710
711
  npx ${PACKAGE_NAME} init ./my-agent # installs deps + links agent-sdk onto PATH
711
712
  npx ${PACKAGE_NAME} init ./my-demo --template demo # record a PR walkthrough
713
+ npx ${PACKAGE_NAME} init ./code-wiki --template code-wiki # keep wiki pages current after merge
712
714
  npx ${PACKAGE_NAME} init ./my-reviewer --template security-reviewer # review PRs for security bugs
713
715
  npx ${PACKAGE_NAME} init ./security-help --template security-help # answer security questions in Slack
714
716
  npx ${PACKAGE_NAME} init ./my-triage --template triage-linear # comment on Linear issues
@@ -31,9 +31,6 @@ import { CLI_COMMAND_NAME, packageRootDir } from "./distribution.js";
31
31
  import { parseFrontmatter } from "./frontmatter.js";
32
32
  import { stdoutPalette } from "./terminal-style.js";
33
33
 
34
- /** Monorepo-only skill; excluded from the published package. */
35
- const SKIP_SKILL_DIRS = new Set(["operate"]);
36
-
37
34
  /** Category folder under ~/.cursor/skills (Cursor discovers nested skills). */
38
35
  export const CURSOR_SKILLS_NAMESPACE = "agentsdk";
39
36
 
@@ -122,7 +119,7 @@ export async function listShippedPackageSkills(
122
119
 
123
120
  const skills: PackageSkill[] = [];
124
121
  for (const entry of entries) {
125
- if (!entry.isDirectory() || SKIP_SKILL_DIRS.has(entry.name)) {
122
+ if (!entry.isDirectory()) {
126
123
  continue;
127
124
  }
128
125
  const sourceDir = join(skillsRoot, entry.name);
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Envelope-carried installation config for managed-product deliveries
3
+ * (plan 0002 Stack H1; envelope shape from Stack B1).
4
+ *
5
+ * On the v2 architecture a managed product (security-reviewer, …) is many
6
+ * single-tenant deployments: the pre-signal trigger gate matches the
7
+ * customer's automation trigger before a workflow starts and stamps the
8
+ * matched automation uuid + an opaque installation-config reference on the
9
+ * attributed session envelope. The delivery activity forwards the matched
10
+ * installation-config document to the fork **inside the webhook payload it
11
+ * POSTs to the channel**, under {@link MANAGED_DELIVERY_PAYLOAD_KEY} — the
12
+ * same embed-in-payload pattern the legacy deployment event stream used
13
+ * for its source marker.
14
+ *
15
+ * This module is the one contract both sides share: the control-plane
16
+ * delivery path embeds with {@link withManagedDeliveryConfig}; the agent's
17
+ * channels detect and read with {@link parseManagedDeliveryConfig}. The
18
+ * document mirrors the sync layer's `ManagedAutomationConfigDoc` **policy**
19
+ * fields that "ride the delivery envelope to the fork" (posting mode,
20
+ * managed config, trigger snapshots for the channel's staleness guard);
21
+ * readers ignore unknown fields so a newer sync can add material without
22
+ * breaking older forks. The automation's MCP server refs deliberately do
23
+ * NOT ride here: they travel on the hosted-admission envelope's
24
+ * `managedAutomation` slice (plan 0002 G2, `hosted-delivery-protocol.ts` /
25
+ * `hosted-managed-automation.ts`) so one mechanism owns MCP attach.
26
+ *
27
+ * INTERNAL: first-party host plumbing shared by agents in `factory/*`,
28
+ * consumed via relative source imports. Deliberately excluded from the
29
+ * published `@cursor/july` npm package (see the `files` whitelist).
30
+ */
31
+
32
+ /**
33
+ * Key inside the delivered webhook payload under which the delivery
34
+ * activity embeds the matched installation config. Chosen to never
35
+ * collide with a provider webhook field (GitHub and Origin payloads have
36
+ * no `cursor*` keys).
37
+ */
38
+ export const MANAGED_DELIVERY_PAYLOAD_KEY = "cursorManagedDelivery" as const;
39
+
40
+ /**
41
+ * The matched installation-config document as it rides the delivery to
42
+ * the fork. Required: the matched automation uuid (B1 attribution).
43
+ * Everything else is optional; absent fields keep the channel's default
44
+ * posture (post, all modules enabled, no staleness guard).
45
+ */
46
+ export interface ManagedDeliveryInstallationConfig {
47
+ /** Source managed automation uuid the pre-signal gate matched. */
48
+ matchedAutomationUuid: string;
49
+ /** Opaque `<installationId>@<resourceVersion>` config reference. */
50
+ installationConfigRef?: string;
51
+ managedType?: string;
52
+ name?: string;
53
+ /**
54
+ * Whether product output (PR comments, …) posts for this installation,
55
+ * or the run stays check/shadow-only. Channels post only on `"post"`
56
+ * (or when the field is absent) — any other value fails closed to
57
+ * shadow, so a newer mode name never posts by accident.
58
+ */
59
+ postingMode?: string;
60
+ managedConfig?: Record<string, unknown>;
61
+ /**
62
+ * The automation's git triggers as `GitTrigger.toJson()` snapshots.
63
+ * The channel re-checks the delivery against them (staleness guard:
64
+ * the config may have changed between admission and delivery).
65
+ */
66
+ triggerSnapshots?: unknown[];
67
+ }
68
+
69
+ function isRecord(value: unknown): value is Record<string, unknown> {
70
+ return typeof value === "object" && value !== null && !Array.isArray(value);
71
+ }
72
+
73
+ function nonEmptyString(value: unknown): string | undefined {
74
+ if (typeof value !== "string") {
75
+ return undefined;
76
+ }
77
+ const trimmed = value.trim();
78
+ return trimmed === "" ? undefined : trimmed;
79
+ }
80
+
81
+ /**
82
+ * Read the embedded installation config out of a delivered webhook
83
+ * payload. Returns undefined for payloads without the key (legacy
84
+ * deliveries, host relay, fixtures) and for documents missing the
85
+ * required matched automation uuid — the channel then runs its legacy
86
+ * path unchanged. Malformed optional fields are dropped, not fatal.
87
+ */
88
+ export function parseManagedDeliveryConfig(
89
+ payload: unknown
90
+ ): ManagedDeliveryInstallationConfig | undefined {
91
+ if (!isRecord(payload)) {
92
+ return undefined;
93
+ }
94
+ const doc = payload[MANAGED_DELIVERY_PAYLOAD_KEY];
95
+ if (!isRecord(doc)) {
96
+ return undefined;
97
+ }
98
+ const matchedAutomationUuid = nonEmptyString(doc.matchedAutomationUuid);
99
+ if (matchedAutomationUuid === undefined) {
100
+ return undefined;
101
+ }
102
+ return {
103
+ matchedAutomationUuid,
104
+ installationConfigRef: nonEmptyString(doc.installationConfigRef),
105
+ managedType: nonEmptyString(doc.managedType),
106
+ name: nonEmptyString(doc.name),
107
+ postingMode: nonEmptyString(doc.postingMode),
108
+ managedConfig: isRecord(doc.managedConfig) ? doc.managedConfig : undefined,
109
+ triggerSnapshots: Array.isArray(doc.triggerSnapshots)
110
+ ? doc.triggerSnapshots
111
+ : undefined,
112
+ };
113
+ }
114
+
115
+ /**
116
+ * Embed one matched installation config into the webhook payload the
117
+ * delivery activity POSTs to the channel. Pure; used by the control-plane
118
+ * delivery path and by channel tests building fixture envelopes.
119
+ */
120
+ export function withManagedDeliveryConfig(
121
+ payload: Record<string, unknown>,
122
+ config: ManagedDeliveryInstallationConfig
123
+ ): Record<string, unknown> {
124
+ return { ...payload, [MANAGED_DELIVERY_PAYLOAD_KEY]: config };
125
+ }
@@ -1,5 +1,6 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import type { HostGitHubClient } from "../types.js";
3
+ import { parsePrUrl } from "./scm/pr-url.js";
3
4
 
4
5
  export type ReviewCommentPublisher = "local_gh" | "host_github" | "host_origin";
5
6
 
@@ -198,8 +199,15 @@ export type ReviewThreadResolverImplementation = {
198
199
  export function resolveScmReviewTarget(
199
200
  prUrl: string
200
201
  ): ScmReviewTarget | undefined {
201
- const parsed = parseReviewPrUrl(prUrl);
202
- return parsed.kind === "valid" ? parsed.value : undefined;
202
+ const parsed = parsePrUrl(prUrl);
203
+ if (parsed === undefined) {
204
+ return undefined;
205
+ }
206
+ return {
207
+ provider: parsed.provider,
208
+ repo: `${parsed.owner}/${parsed.repo}`,
209
+ prNumber: parsed.number,
210
+ };
203
211
  }
204
212
 
205
213
  /**
@@ -1243,117 +1251,6 @@ function skippedResolve(detail: string): ResolveReviewThreadsResult {
1243
1251
  };
1244
1252
  }
1245
1253
 
1246
- const ORIGIN_PR_PAGE_HOST_PATTERN = /^origin(-[a-z0-9]+)?\.cursor\.com$/i;
1247
-
1248
- /**
1249
- * Provider-neutral PR URL parse. GitHub.com plus the Origin page shapes
1250
- * `parsePrTarget` in security-review-lib accepts. Duplicated here so
1251
- * agent-serve does not import that package.
1252
- */
1253
- function parseReviewPrUrl(
1254
- prUrl: string
1255
- ):
1256
- | { kind: "valid"; value: ScmReviewTarget }
1257
- | { kind: "invalid"; detail: string } {
1258
- let url: URL;
1259
- try {
1260
- url = new URL(prUrl);
1261
- } catch (error) {
1262
- return {
1263
- kind: "invalid",
1264
- detail: `unparseable PR URL: ${error instanceof Error ? error.message : String(error)}`,
1265
- };
1266
- }
1267
-
1268
- const parts = url.pathname.split("/").filter(Boolean);
1269
- const hostname = url.hostname;
1270
-
1271
- if (hostname === "github.com" && parts.length >= 4 && parts[2] === "pull") {
1272
- const prNumber = Number(parts[3]);
1273
- if (Number.isInteger(prNumber) && prNumber > 0) {
1274
- return {
1275
- kind: "valid",
1276
- value: {
1277
- provider: "github",
1278
- repo: `${parts[0]}/${parts[1]}`,
1279
- prNumber,
1280
- },
1281
- };
1282
- }
1283
- }
1284
-
1285
- if (
1286
- ORIGIN_PR_PAGE_HOST_PATTERN.test(hostname) &&
1287
- parts.length >= 4 &&
1288
- parts[2] === "github"
1289
- ) {
1290
- const prNumber = Number(parts[3]);
1291
- if (Number.isInteger(prNumber) && prNumber > 0) {
1292
- return {
1293
- kind: "valid",
1294
- value: {
1295
- provider: "origin",
1296
- repo: `${parts[0]}/${parts[1]}`,
1297
- prNumber,
1298
- },
1299
- };
1300
- }
1301
- }
1302
-
1303
- if (
1304
- /^(www\.)?cursor\.com$/i.test(hostname) &&
1305
- parts[0] === "codebase" &&
1306
- parts.length >= 5 &&
1307
- parts[3] === "pull"
1308
- ) {
1309
- const prNumber = Number(parts[4]);
1310
- if (Number.isInteger(prNumber) && prNumber > 0) {
1311
- return {
1312
- kind: "valid",
1313
- value: {
1314
- provider: "origin",
1315
- repo: `${parts[1]}/${parts[2]}`,
1316
- prNumber,
1317
- },
1318
- };
1319
- }
1320
- }
1321
-
1322
- if (hostname === "review.cursor.com" && parts[0] === "pr") {
1323
- if (parts.length >= 5 && parts[3] === "github") {
1324
- const prNumber = Number(parts[4]);
1325
- if (Number.isInteger(prNumber) && prNumber > 0) {
1326
- return {
1327
- kind: "valid",
1328
- value: {
1329
- provider: "origin",
1330
- repo: `${parts[1]}/${parts[2]}`,
1331
- prNumber,
1332
- },
1333
- };
1334
- }
1335
- }
1336
- if (parts.length >= 4) {
1337
- const prNumber = Number(parts[3]);
1338
- if (Number.isInteger(prNumber) && prNumber > 0) {
1339
- return {
1340
- kind: "valid",
1341
- value: {
1342
- provider: "origin",
1343
- repo: `${parts[1]}/${parts[2]}`,
1344
- prNumber,
1345
- },
1346
- };
1347
- }
1348
- }
1349
- }
1350
-
1351
- return {
1352
- kind: "invalid",
1353
- detail: "unparseable PR URL: not a GitHub or Origin pull request",
1354
- };
1355
- }
1356
-
1357
1254
  function parseGithubPrUrl(
1358
1255
  prUrl: string
1359
1256
  ):
@@ -13,6 +13,7 @@ import type {
13
13
  AgentRunner,
14
14
  PrewarmOutcome,
15
15
  RunnerPrewarmRequest,
16
+ SteerAckOutcome,
16
17
  } from "./sdk-runner.js";
17
18
 
18
19
  export interface RuntimeDispatchingRunnerOptions {
@@ -45,6 +46,15 @@ export class RuntimeDispatchingRunner implements AgentRunner {
45
46
  return this.options.sdkRunner.runTurn(request);
46
47
  }
47
48
 
49
+ async steer(request: {
50
+ sessionId: string;
51
+ text: string;
52
+ }): Promise<SteerAckOutcome> {
53
+ return (
54
+ (await this.options.sdkRunner.steer?.(request)) ?? "revert_to_followup"
55
+ );
56
+ }
57
+
48
58
  async prewarm(request: RunnerPrewarmRequest): Promise<PrewarmOutcome> {
49
59
  // Prewarming is a local-harness concern; the engine only calls it for
50
60
  // local-runtime agents.