@cursor/july 0.1.99 → 0.1.101

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 (420) hide show
  1. package/AGENTS.md +4 -2
  2. package/dist/bin/agent-serve.js +3 -2
  3. package/dist/channels/deployments/deployments-channel.d.ts +41 -5
  4. package/dist/channels/deployments/deployments-channel.d.ts.map +1 -1
  5. package/dist/channels/deployments/deployments-channel.js +88 -8
  6. package/dist/channels/deployments/types.d.ts +4 -3
  7. package/dist/channels/deployments/types.d.ts.map +1 -1
  8. package/dist/channels/github/defaults.d.ts.map +1 -1
  9. package/dist/channels/github/defaults.js +28 -3
  10. package/dist/channels/github/progress.d.ts +7 -0
  11. package/dist/channels/github/progress.d.ts.map +1 -1
  12. package/dist/channels/origin/defaults.d.ts +43 -0
  13. package/dist/channels/origin/defaults.d.ts.map +1 -0
  14. package/dist/channels/origin/defaults.js +111 -0
  15. package/dist/channels/origin/index.d.ts +2 -0
  16. package/dist/channels/origin/index.d.ts.map +1 -1
  17. package/dist/channels/origin/index.js +2 -0
  18. package/dist/channels/origin/origin-channel.d.ts +2 -1
  19. package/dist/channels/origin/origin-channel.d.ts.map +1 -1
  20. package/dist/channels/origin/origin-channel.js +24 -3
  21. package/dist/channels/origin/state.d.ts +32 -0
  22. package/dist/channels/origin/state.d.ts.map +1 -0
  23. package/dist/channels/origin/state.js +23 -0
  24. package/dist/channels/origin/types.d.ts +23 -1
  25. package/dist/channels/origin/types.d.ts.map +1 -1
  26. package/dist/channels/slack/api.d.ts +16 -7
  27. package/dist/channels/slack/api.d.ts.map +1 -1
  28. package/dist/channels/slack/api.js +31 -14
  29. package/dist/channels/slack/code-fences.d.ts +17 -0
  30. package/dist/channels/slack/code-fences.d.ts.map +1 -0
  31. package/dist/channels/slack/code-fences.js +168 -0
  32. package/dist/channels/slack/constants.d.ts +6 -0
  33. package/dist/channels/slack/constants.d.ts.map +1 -1
  34. package/dist/channels/slack/constants.js +6 -0
  35. package/dist/channels/slack/defaults.d.ts +9 -4
  36. package/dist/channels/slack/defaults.d.ts.map +1 -1
  37. package/dist/channels/slack/defaults.js +154 -76
  38. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  39. package/dist/channels/slack/dispatch.js +3 -3
  40. package/dist/channels/slack/inbound.d.ts +9 -0
  41. package/dist/channels/slack/inbound.d.ts.map +1 -1
  42. package/dist/channels/slack/inbound.js +14 -0
  43. package/dist/channels/slack/index.d.ts +2 -0
  44. package/dist/channels/slack/index.d.ts.map +1 -1
  45. package/dist/channels/slack/index.js +2 -0
  46. package/dist/channels/slack/live-delivery.d.ts +5 -0
  47. package/dist/channels/slack/live-delivery.d.ts.map +1 -1
  48. package/dist/channels/slack/live-delivery.js +116 -21
  49. package/dist/channels/slack/reasoning-card.d.ts +38 -0
  50. package/dist/channels/slack/reasoning-card.d.ts.map +1 -0
  51. package/dist/channels/slack/reasoning-card.js +104 -0
  52. package/dist/channels/slack/redact.d.ts +2 -0
  53. package/dist/channels/slack/redact.d.ts.map +1 -0
  54. package/dist/channels/slack/redact.js +5 -0
  55. package/dist/channels/slack/reply-options.d.ts +40 -0
  56. package/dist/channels/slack/reply-options.d.ts.map +1 -0
  57. package/dist/channels/slack/reply-options.js +150 -0
  58. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  59. package/dist/channels/slack/slack-channel.js +8 -4
  60. package/dist/channels/slack/stream.d.ts +22 -10
  61. package/dist/channels/slack/stream.d.ts.map +1 -1
  62. package/dist/channels/slack/stream.js +9 -16
  63. package/dist/channels/slack/tool-cards.d.ts +22 -0
  64. package/dist/channels/slack/tool-cards.d.ts.map +1 -0
  65. package/dist/channels/slack/tool-cards.js +178 -0
  66. package/dist/channels/slack/types.d.ts +145 -6
  67. package/dist/channels/slack/types.d.ts.map +1 -1
  68. package/dist/connections.d.ts +18 -2
  69. package/dist/connections.d.ts.map +1 -1
  70. package/dist/connections.js +18 -2
  71. package/dist/docs/404.html +2 -2
  72. package/dist/docs/ab.html +6 -6
  73. package/dist/docs/ab.md +1 -1
  74. package/dist/docs/assets/{ab.md.DJo5r4R-.js → ab.md.mlVgqvSk.js} +1 -1
  75. package/dist/docs/assets/{app.BplEAZ3S.js → app.BASO9Kih.js} +1 -1
  76. package/dist/docs/assets/{building-with-agents.md.DI4mEzlt.js → building-with-agents.md.CUSWxlP_.js} +2 -2
  77. package/dist/docs/assets/chunks/@localSearchIndexroot.DbFXINq2.js +1 -0
  78. package/dist/docs/assets/chunks/{VPLocalSearchBox.CHXyv4wP.js → VPLocalSearchBox.DwkqxoE0.js} +1 -1
  79. package/dist/docs/assets/chunks/{theme.BTcsZmjQ.js → theme.CCil_13e.js} +2 -2
  80. package/dist/docs/assets/{evals.md.lfJoEVc8.js → evals.md.CPzDAwoH.js} +1 -1
  81. package/dist/docs/assets/{guides_github.md.Cnh2mL4a.js → guides_github.md.BtPr9GaP.js} +1 -1
  82. package/dist/docs/assets/{guides_mcp-oauth.md.CN-6YmTJ.js → guides_mcp-oauth.md.Dp6cDP7f.js} +1 -1
  83. package/dist/docs/assets/{guides_opentelemetry.md.bmPmkvJu.js → guides_opentelemetry.md.BVTXDCRg.js} +2 -2
  84. package/dist/docs/assets/{guides_slack.md.VDXQV3ja.js → guides_slack.md.9oHPye9o.js} +19 -3
  85. package/dist/docs/assets/{guides_slack.md.VDXQV3ja.lean.js → guides_slack.md.9oHPye9o.lean.js} +1 -1
  86. package/dist/docs/assets/hillclimbing.md.CpTGTCle.js +4 -0
  87. package/dist/docs/assets/{index.md.CVeRUOeZ.js → index.md.Bb4k8kUm.js} +1 -1
  88. package/dist/docs/assets/{quickstart.md.Nj_LjW_a.js → quickstart.md.DdQOF7Y8.js} +1 -1
  89. package/dist/docs/assets/{reference_connections.md.DxldvyIB.js → reference_connections.md.Di6jJAXF.js} +13 -3
  90. package/dist/docs/assets/{reference_connections.md.DxldvyIB.lean.js → reference_connections.md.Di6jJAXF.lean.js} +1 -1
  91. package/dist/docs/assets/{reference_http-api.md.BEJx9XVj.js → reference_http-api.md.oySXBO8o.js} +1 -1
  92. package/dist/docs/assets/scaffolding-agents.md.em43xlY1.js +1 -0
  93. package/dist/docs/assets/skills_ab.md.CsFNatVx.js +26 -0
  94. package/dist/docs/assets/skills_ab.md.CsFNatVx.lean.js +1 -0
  95. package/dist/docs/assets/skills_create-agent.md.BVoWPcan.js +8 -0
  96. package/dist/docs/assets/skills_create-agent.md.BVoWPcan.lean.js +1 -0
  97. package/dist/docs/assets/skills_debug.md.CDbPhHfg.js +1 -0
  98. package/dist/docs/assets/skills_debug.md.CDbPhHfg.lean.js +1 -0
  99. package/dist/docs/assets/skills_evals.md.723kpUmA.js +25 -0
  100. package/dist/docs/assets/skills_evals.md.723kpUmA.lean.js +1 -0
  101. package/dist/docs/assets/skills_framework-map.md.BTi817yv.js +1 -0
  102. package/dist/docs/assets/skills_framework-map.md.BTi817yv.lean.js +1 -0
  103. package/dist/docs/assets/skills_github.md.D0JahM8c.js +16 -0
  104. package/dist/docs/assets/skills_github.md.D0JahM8c.lean.js +1 -0
  105. package/dist/docs/assets/skills_hillclimb.md.B_zJerxA.js +7 -0
  106. package/dist/docs/assets/skills_hillclimb.md.B_zJerxA.lean.js +1 -0
  107. package/dist/docs/assets/skills_index.md.DKwIxzGg.js +1 -0
  108. package/dist/docs/assets/skills_index.md.DKwIxzGg.lean.js +1 -0
  109. package/dist/docs/assets/skills_mcp-auth.md.DGvFP3HE.js +18 -0
  110. package/dist/docs/assets/skills_mcp-auth.md.DGvFP3HE.lean.js +1 -0
  111. package/dist/docs/assets/skills_otel.md.CgiZryR3.js +8 -0
  112. package/dist/docs/assets/skills_otel.md.CgiZryR3.lean.js +1 -0
  113. package/dist/docs/assets/skills_setup-slack.md.BBgx8lUz.js +20 -0
  114. package/dist/docs/assets/skills_setup-slack.md.BBgx8lUz.lean.js +1 -0
  115. package/dist/docs/assets/{troubleshooting.md.DCiPBhYs.js → troubleshooting.md.Cus_YZga.js} +1 -1
  116. package/dist/docs/building-with-agents.html +6 -6
  117. package/dist/docs/building-with-agents.md +14 -11
  118. package/dist/docs/concepts.html +4 -4
  119. package/dist/docs/deployment.html +4 -4
  120. package/dist/docs/evals.html +6 -6
  121. package/dist/docs/evals.md +1 -1
  122. package/dist/docs/guides/agent-to-agent.html +4 -4
  123. package/dist/docs/guides/cloud-runtime.html +4 -4
  124. package/dist/docs/guides/convert-automation.html +4 -4
  125. package/dist/docs/guides/github.html +5 -5
  126. package/dist/docs/guides/github.md +1 -1
  127. package/dist/docs/guides/human-in-the-loop.html +4 -4
  128. package/dist/docs/guides/mcp-oauth.html +5 -5
  129. package/dist/docs/guides/mcp-oauth.md +1 -1
  130. package/dist/docs/guides/opentelemetry.html +7 -7
  131. package/dist/docs/guides/opentelemetry.md +2 -2
  132. package/dist/docs/guides/slack.html +22 -6
  133. package/dist/docs/guides/slack.md +80 -1
  134. package/dist/docs/guides/webhooks.html +5 -5
  135. package/dist/docs/hashmap.json +1 -1
  136. package/dist/docs/hillclimbing.html +6 -6
  137. package/dist/docs/hillclimbing.md +5 -5
  138. package/dist/docs/index.html +6 -6
  139. package/dist/docs/index.md +1 -1
  140. package/dist/docs/llms-full.txt +1073 -31
  141. package/dist/docs/llms.txt +14 -0
  142. package/dist/docs/quickstart.html +5 -5
  143. package/dist/docs/quickstart.md +1 -1
  144. package/dist/docs/reference/agent-config.html +4 -4
  145. package/dist/docs/reference/artifacts.html +4 -4
  146. package/dist/docs/reference/channels.html +4 -4
  147. package/dist/docs/reference/cli.html +4 -4
  148. package/dist/docs/reference/connections.html +17 -7
  149. package/dist/docs/reference/connections.md +32 -1
  150. package/dist/docs/reference/hooks.html +4 -4
  151. package/dist/docs/reference/http-api.html +6 -6
  152. package/dist/docs/reference/http-api.md +1 -1
  153. package/dist/docs/reference/instructions.html +4 -4
  154. package/dist/docs/reference/playground.html +4 -4
  155. package/dist/docs/reference/project-layout.html +4 -4
  156. package/dist/docs/reference/prompt.html +4 -4
  157. package/dist/docs/reference/schedules.html +4 -4
  158. package/dist/docs/reference/sessions.html +4 -4
  159. package/dist/docs/reference/skills.html +4 -4
  160. package/dist/docs/reference/subagents.html +4 -4
  161. package/dist/docs/reference/tools.html +4 -4
  162. package/dist/docs/scaffolding-agents.html +5 -5
  163. package/dist/docs/scaffolding-agents.md +3 -3
  164. package/dist/docs/skills/ab.html +52 -0
  165. package/dist/docs/skills/ab.md +50 -0
  166. package/dist/docs/skills/create-agent.html +34 -0
  167. package/dist/docs/skills/create-agent.md +160 -0
  168. package/dist/docs/skills/debug.html +27 -0
  169. package/dist/docs/skills/debug.md +36 -0
  170. package/dist/docs/skills/evals.html +51 -0
  171. package/dist/docs/skills/evals.md +99 -0
  172. package/dist/docs/skills/framework-map.html +27 -0
  173. package/dist/docs/skills/framework-map.md +95 -0
  174. package/dist/docs/skills/github.html +42 -0
  175. package/dist/docs/skills/github.md +93 -0
  176. package/dist/docs/skills/hillclimb.html +33 -0
  177. package/dist/docs/skills/hillclimb.md +55 -0
  178. package/dist/docs/skills/index.html +27 -0
  179. package/dist/docs/skills/index.md +21 -0
  180. package/dist/docs/skills/mcp-auth.html +44 -0
  181. package/dist/docs/skills/mcp-auth.md +76 -0
  182. package/dist/docs/skills/otel.html +34 -0
  183. package/dist/docs/skills/otel.md +48 -0
  184. package/dist/docs/skills/setup-slack.html +46 -0
  185. package/dist/docs/skills/setup-slack.md +141 -0
  186. package/dist/docs/storage.html +4 -4
  187. package/dist/docs/templates/agentic-owners.html +4 -4
  188. package/dist/docs/templates/agents-md.html +4 -4
  189. package/dist/docs/templates/code-wiki.html +4 -4
  190. package/dist/docs/templates/demo.html +4 -4
  191. package/dist/docs/templates/pr-autofixer.html +4 -4
  192. package/dist/docs/templates/security-help.html +4 -4
  193. package/dist/docs/templates/security-reviewer.html +4 -4
  194. package/dist/docs/templates/triage.html +4 -4
  195. package/dist/docs/troubleshooting.html +5 -5
  196. package/dist/docs/troubleshooting.md +1 -1
  197. package/dist/extensions/cursor-cloud-agents/extension.d.ts +55 -0
  198. package/dist/extensions/cursor-cloud-agents/extension.d.ts.map +1 -0
  199. package/dist/extensions/cursor-cloud-agents/extension.js +64 -0
  200. package/dist/extensions/cursor-cloud-agents/lib/cloud.d.ts +30 -0
  201. package/dist/extensions/cursor-cloud-agents/lib/cloud.d.ts.map +1 -0
  202. package/dist/extensions/cursor-cloud-agents/lib/cloud.js +45 -0
  203. package/dist/extensions/cursor-cloud-agents/lib/fleet.d.ts +25 -0
  204. package/dist/extensions/cursor-cloud-agents/lib/fleet.d.ts.map +1 -0
  205. package/dist/extensions/cursor-cloud-agents/lib/fleet.js +85 -0
  206. package/dist/extensions/cursor-cloud-agents/lib/repos.d.ts +15 -0
  207. package/dist/extensions/cursor-cloud-agents/lib/repos.d.ts.map +1 -0
  208. package/dist/extensions/cursor-cloud-agents/lib/repos.js +55 -0
  209. package/dist/extensions/cursor-cloud-agents/skills/handoff.md +27 -0
  210. package/dist/extensions/cursor-cloud-agents/tools/follow_up.d.ts +4 -0
  211. package/dist/extensions/cursor-cloud-agents/tools/follow_up.d.ts.map +1 -0
  212. package/dist/extensions/cursor-cloud-agents/tools/follow_up.js +37 -0
  213. package/dist/extensions/cursor-cloud-agents/tools/launch.d.ts +4 -0
  214. package/dist/extensions/cursor-cloud-agents/tools/launch.d.ts.map +1 -0
  215. package/dist/extensions/cursor-cloud-agents/tools/launch.js +83 -0
  216. package/dist/extensions/cursor-cloud-agents/tools/list.d.ts +4 -0
  217. package/dist/extensions/cursor-cloud-agents/tools/list.d.ts.map +1 -0
  218. package/dist/extensions/cursor-cloud-agents/tools/list.js +36 -0
  219. package/dist/extensions/cursor-cloud-agents/tools/status.d.ts +4 -0
  220. package/dist/extensions/cursor-cloud-agents/tools/status.d.ts.map +1 -0
  221. package/dist/extensions/cursor-cloud-agents/tools/status.js +41 -0
  222. package/dist/extensions.d.ts +49 -0
  223. package/dist/extensions.d.ts.map +1 -0
  224. package/dist/extensions.js +75 -0
  225. package/dist/files-backends/cursor-hosted.d.ts +6 -0
  226. package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
  227. package/dist/files-backends/cursor-hosted.js +6 -9
  228. package/dist/index.d.ts +2 -1
  229. package/dist/index.d.ts.map +1 -1
  230. package/dist/index.js +2 -1
  231. package/dist/internal/advertise-tools.d.ts +4 -1
  232. package/dist/internal/advertise-tools.d.ts.map +1 -1
  233. package/dist/internal/advertise-tools.js +20 -1
  234. package/dist/internal/as-of.d.ts +18 -0
  235. package/dist/internal/as-of.d.ts.map +1 -1
  236. package/dist/internal/as-of.js +131 -0
  237. package/dist/internal/cli-deploy.d.ts.map +1 -1
  238. package/dist/internal/cli-deploy.js +66 -21
  239. package/dist/internal/continuation-identity.d.ts.map +1 -1
  240. package/dist/internal/continuation-identity.js +3 -1
  241. package/dist/internal/conversation-mirror.d.ts.map +1 -1
  242. package/dist/internal/conversation-mirror.js +3 -4
  243. package/dist/internal/cursor/hosted-deployment-secrets.d.ts +16 -0
  244. package/dist/internal/cursor/hosted-deployment-secrets.d.ts.map +1 -0
  245. package/dist/internal/cursor/hosted-deployment-secrets.js +61 -0
  246. package/dist/internal/cursor/hosted-store-secrets.d.ts +15 -0
  247. package/dist/internal/cursor/hosted-store-secrets.d.ts.map +1 -0
  248. package/dist/internal/cursor/hosted-store-secrets.js +48 -0
  249. package/dist/internal/cursor-deployment-relay.d.ts +15 -1
  250. package/dist/internal/cursor-deployment-relay.d.ts.map +1 -1
  251. package/dist/internal/cursor-deployment-relay.js +46 -7
  252. package/dist/internal/deploy-client.d.ts +29 -6
  253. package/dist/internal/deploy-client.d.ts.map +1 -1
  254. package/dist/internal/deploy-client.js +61 -19
  255. package/dist/internal/discovery.d.ts.map +1 -1
  256. package/dist/internal/discovery.js +426 -121
  257. package/dist/internal/distribution.d.ts.map +1 -1
  258. package/dist/internal/distribution.js +5 -0
  259. package/dist/internal/framework-file-storage.d.ts +15 -8
  260. package/dist/internal/framework-file-storage.d.ts.map +1 -1
  261. package/dist/internal/framework-file-storage.js +70 -10
  262. package/dist/internal/framework-storage-selection.d.ts +12 -12
  263. package/dist/internal/framework-storage-selection.d.ts.map +1 -1
  264. package/dist/internal/framework-storage-selection.js +33 -39
  265. package/dist/internal/hosted-delivery.d.ts +3 -1
  266. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  267. package/dist/internal/hosted-delivery.js +19 -32
  268. package/dist/internal/hosted-execution-diag.d.ts +5 -0
  269. package/dist/internal/hosted-execution-diag.d.ts.map +1 -1
  270. package/dist/internal/hosted-execution-diag.js +5 -0
  271. package/dist/internal/hosted-execution-flush.d.ts +46 -0
  272. package/dist/internal/hosted-execution-flush.d.ts.map +1 -0
  273. package/dist/internal/hosted-execution-flush.js +81 -0
  274. package/dist/internal/mcp-endpoint.js +1 -0
  275. package/dist/internal/mcp-host.d.ts +2 -1
  276. package/dist/internal/mcp-host.d.ts.map +1 -1
  277. package/dist/internal/mcp-host.js +35 -15
  278. package/dist/internal/review-comments.d.ts +1 -1
  279. package/dist/internal/review-comments.d.ts.map +1 -1
  280. package/dist/internal/review-comments.js +4 -4
  281. package/dist/internal/server.d.ts +3 -0
  282. package/dist/internal/server.d.ts.map +1 -1
  283. package/dist/internal/server.js +79 -104
  284. package/dist/internal/session-engine.d.ts +9 -7
  285. package/dist/internal/session-engine.d.ts.map +1 -1
  286. package/dist/internal/session-engine.js +45 -34
  287. package/dist/internal/session-run-log.d.ts +5 -4
  288. package/dist/internal/session-run-log.d.ts.map +1 -1
  289. package/dist/internal/session-run-log.js +8 -8
  290. package/dist/internal/start-log-store.d.ts +60 -0
  291. package/dist/internal/start-log-store.d.ts.map +1 -0
  292. package/dist/internal/start-log-store.js +151 -0
  293. package/dist/internal/storage-coordinator.d.ts +0 -6
  294. package/dist/internal/storage-coordinator.d.ts.map +1 -1
  295. package/dist/internal/storage-coordinator.js +1 -9
  296. package/dist/internal/tool-policy.d.ts +8 -0
  297. package/dist/internal/tool-policy.d.ts.map +1 -1
  298. package/dist/internal/tool-policy.js +19 -7
  299. package/dist/playground/assets/{index-jzNbJENa.js → index-BnNN1-EK.js} +45 -45
  300. package/dist/playground/assets/index-DBQCwFp0.css +1 -0
  301. package/dist/playground/index.html +2 -2
  302. package/dist/storage-backends/cursor-hosted-v2.d.ts +83 -0
  303. package/dist/storage-backends/cursor-hosted-v2.d.ts.map +1 -0
  304. package/dist/storage-backends/cursor-hosted-v2.js +164 -0
  305. package/dist/storage-backends/cursor-hosted.d.ts +6 -0
  306. package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
  307. package/dist/storage-backends/cursor-hosted.js +6 -1
  308. package/dist/storage-protocol.d.ts +24 -0
  309. package/dist/storage-protocol.d.ts.map +1 -1
  310. package/dist/storage-protocol.js +33 -0
  311. package/dist/storage.d.ts +1 -1
  312. package/dist/storage.d.ts.map +1 -1
  313. package/dist/storage.js +1 -1
  314. package/dist/types.d.ts +123 -6
  315. package/dist/types.d.ts.map +1 -1
  316. package/dist/types.js +29 -1
  317. package/docs/README.md +1 -1
  318. package/docs/ab.md +1 -1
  319. package/docs/building-with-agents.md +14 -11
  320. package/docs/evals.md +1 -1
  321. package/docs/guides/github.md +1 -1
  322. package/docs/guides/mcp-oauth.md +1 -1
  323. package/docs/guides/opentelemetry.md +2 -2
  324. package/docs/guides/slack.md +80 -1
  325. package/docs/hillclimbing.md +5 -5
  326. package/docs/quickstart.md +1 -1
  327. package/docs/reference/connections.md +32 -1
  328. package/docs/reference/http-api.md +1 -1
  329. package/docs/scaffolding-agents.md +3 -3
  330. package/docs/skills/index.md +26 -0
  331. package/docs/troubleshooting.md +1 -1
  332. package/package.json +18 -4
  333. package/src/bin/agent-serve.ts +11 -2
  334. package/src/channels/deployments/deployments-channel.ts +117 -8
  335. package/src/channels/deployments/types.ts +4 -3
  336. package/src/channels/github/defaults.ts +36 -3
  337. package/src/channels/github/progress.ts +7 -0
  338. package/src/channels/origin/defaults.ts +143 -0
  339. package/src/channels/origin/index.ts +2 -0
  340. package/src/channels/origin/origin-channel.ts +37 -1
  341. package/src/channels/origin/state.ts +54 -0
  342. package/src/channels/origin/types.ts +24 -0
  343. package/src/channels/slack/api.ts +37 -18
  344. package/src/channels/slack/code-fences.ts +183 -0
  345. package/src/channels/slack/constants.ts +6 -0
  346. package/src/channels/slack/defaults.ts +173 -92
  347. package/src/channels/slack/dispatch.ts +8 -1
  348. package/src/channels/slack/inbound.ts +17 -0
  349. package/src/channels/slack/index.ts +2 -0
  350. package/src/channels/slack/live-delivery.ts +142 -28
  351. package/src/channels/slack/reasoning-card.ts +140 -0
  352. package/src/channels/slack/redact.ts +6 -0
  353. package/src/channels/slack/reply-options.ts +229 -0
  354. package/src/channels/slack/slack-channel.ts +7 -2
  355. package/src/channels/slack/stream.ts +31 -24
  356. package/src/channels/slack/tool-cards.ts +221 -0
  357. package/src/channels/slack/types.ts +159 -6
  358. package/src/connections.ts +18 -1
  359. package/src/extensions/cursor-cloud-agents/extension.ts +118 -0
  360. package/src/extensions/cursor-cloud-agents/lib/cloud.ts +79 -0
  361. package/src/extensions/cursor-cloud-agents/lib/fleet.ts +109 -0
  362. package/src/extensions/cursor-cloud-agents/lib/repos.ts +81 -0
  363. package/src/extensions/cursor-cloud-agents/skills/handoff.md +27 -0
  364. package/src/extensions/cursor-cloud-agents/tools/follow_up.ts +29 -0
  365. package/src/extensions/cursor-cloud-agents/tools/launch.ts +84 -0
  366. package/src/extensions/cursor-cloud-agents/tools/list.ts +31 -0
  367. package/src/extensions/cursor-cloud-agents/tools/status.ts +39 -0
  368. package/src/extensions.ts +98 -0
  369. package/src/files-backends/cursor-hosted.ts +15 -5
  370. package/src/index.ts +2 -0
  371. package/src/internal/advertise-tools.ts +37 -12
  372. package/src/internal/as-of.ts +163 -0
  373. package/src/internal/cli-deploy.ts +88 -25
  374. package/src/internal/continuation-identity.ts +3 -1
  375. package/src/internal/conversation-mirror.ts +3 -8
  376. package/src/internal/cursor/hosted-deployment-secrets.ts +72 -0
  377. package/src/internal/cursor/hosted-store-secrets.ts +72 -0
  378. package/src/internal/cursor-deployment-relay.ts +65 -8
  379. package/src/internal/deploy-client.ts +83 -28
  380. package/src/internal/discovery.ts +479 -114
  381. package/src/internal/distribution.ts +5 -0
  382. package/src/internal/framework-file-storage.ts +80 -10
  383. package/src/internal/framework-storage-selection.ts +31 -44
  384. package/src/internal/hosted-delivery.ts +38 -63
  385. package/src/internal/hosted-execution-diag.ts +6 -0
  386. package/src/internal/hosted-execution-flush.ts +142 -0
  387. package/src/internal/mcp-endpoint.ts +1 -0
  388. package/src/internal/mcp-host.ts +40 -14
  389. package/src/internal/review-comments.ts +5 -2
  390. package/src/internal/server.ts +81 -100
  391. package/src/internal/session-engine.ts +56 -28
  392. package/src/internal/session-run-log.ts +8 -12
  393. package/src/internal/start-log-store.ts +177 -0
  394. package/src/internal/storage-coordinator.ts +1 -11
  395. package/src/internal/tool-policy.ts +39 -9
  396. package/src/storage-backends/cursor-hosted-v2.ts +219 -0
  397. package/src/storage-backends/cursor-hosted.ts +6 -1
  398. package/src/storage-protocol.ts +37 -0
  399. package/src/storage.ts +1 -0
  400. package/src/types.ts +177 -14
  401. package/dist/docs/assets/chunks/@localSearchIndexroot.DpuI4i7Z.js +0 -1
  402. package/dist/docs/assets/hillclimbing.md.DhESf3OO.js +0 -4
  403. package/dist/docs/assets/scaffolding-agents.md.D7UUkWw0.js +0 -1
  404. package/dist/internal/null-kv-storage.d.ts +0 -48
  405. package/dist/internal/null-kv-storage.d.ts.map +0 -1
  406. package/dist/internal/null-kv-storage.js +0 -58
  407. package/dist/playground/assets/index-D7rGZNjy.css +0 -1
  408. package/src/internal/null-kv-storage.ts +0 -74
  409. /package/dist/docs/assets/{ab.md.DJo5r4R-.lean.js → ab.md.mlVgqvSk.lean.js} +0 -0
  410. /package/dist/docs/assets/{building-with-agents.md.DI4mEzlt.lean.js → building-with-agents.md.CUSWxlP_.lean.js} +0 -0
  411. /package/dist/docs/assets/{evals.md.lfJoEVc8.lean.js → evals.md.CPzDAwoH.lean.js} +0 -0
  412. /package/dist/docs/assets/{guides_github.md.Cnh2mL4a.lean.js → guides_github.md.BtPr9GaP.lean.js} +0 -0
  413. /package/dist/docs/assets/{guides_mcp-oauth.md.CN-6YmTJ.lean.js → guides_mcp-oauth.md.Dp6cDP7f.lean.js} +0 -0
  414. /package/dist/docs/assets/{guides_opentelemetry.md.bmPmkvJu.lean.js → guides_opentelemetry.md.BVTXDCRg.lean.js} +0 -0
  415. /package/dist/docs/assets/{hillclimbing.md.DhESf3OO.lean.js → hillclimbing.md.CpTGTCle.lean.js} +0 -0
  416. /package/dist/docs/assets/{index.md.CVeRUOeZ.lean.js → index.md.Bb4k8kUm.lean.js} +0 -0
  417. /package/dist/docs/assets/{quickstart.md.Nj_LjW_a.lean.js → quickstart.md.DdQOF7Y8.lean.js} +0 -0
  418. /package/dist/docs/assets/{reference_http-api.md.BEJx9XVj.lean.js → reference_http-api.md.oySXBO8o.lean.js} +0 -0
  419. /package/dist/docs/assets/{scaffolding-agents.md.D7UUkWw0.lean.js → scaffolding-agents.md.em43xlY1.lean.js} +0 -0
  420. /package/dist/docs/assets/{troubleshooting.md.DCiPBhYs.lean.js → troubleshooting.md.Cus_YZga.lean.js} +0 -0
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Default stream-event handlers for the Origin channel: reply delivery.
3
+ *
4
+ * The GitHub channel posts completed assistant messages back to the PR via
5
+ * `buildDefaultGitHubEvents`; this is the Origin analogue. Outbound
6
+ * credentials resolve exactly like `ctx.origin` in hooks (see
7
+ * ./binding.ts): channel app credentials / `ORIGIN_APP_*` env when
8
+ * configured, otherwise — for `cursorAccount` channels — the Cursor-account
9
+ * session exchange, which on hosted v2 acts as the deployment
10
+ * service-account principal. The `agent-serve` SA scope allowlist includes
11
+ * `repository:pull_requests:reviews:write`, the scope
12
+ * `CreatePullRequestComment` checks, so no extra grant is needed.
13
+ */
14
+
15
+ import type { ChannelEventHandlers } from "../../types.js";
16
+ import { buildOriginBinding, type OriginHandle } from "./binding.js";
17
+ import type { OriginChannelState } from "./state.js";
18
+ import type { OriginAppOptions } from "./types.js";
19
+
20
+ /** Hidden marker on outbound Origin comments so consumers can spot them. */
21
+ export const ORIGIN_OUTBOUND_MARKER = "<!-- agent-serve-origin -->";
22
+
23
+ export function formatOriginOutboundComment(body: string): string {
24
+ if (body.includes(ORIGIN_OUTBOUND_MARKER)) {
25
+ return body;
26
+ }
27
+ return `${body.trimEnd()}\n\n${ORIGIN_OUTBOUND_MARKER}`;
28
+ }
29
+
30
+ export interface BuildDefaultOriginEventsOptions {
31
+ /** Force the signed-in Cursor account / deployment SA credential path. */
32
+ cursorAccount?: boolean | { repos: readonly string[] };
33
+ /** Channel-authored outbound app credentials / API base. */
34
+ app?: OriginAppOptions;
35
+ /**
36
+ * When false, skip posting completed assistant messages (and failure
37
+ * notices) back to the Origin pull request. Defaults to true.
38
+ */
39
+ deliverReplies?: boolean;
40
+ /** Injectable binding builder for tests. */
41
+ buildBinding?: typeof buildOriginBinding;
42
+ }
43
+
44
+ function bindingForState(
45
+ options: BuildDefaultOriginEventsOptions,
46
+ state: OriginChannelState
47
+ ): OriginHandle {
48
+ const build = options.buildBinding ?? buildOriginBinding;
49
+ return build({
50
+ repository: {
51
+ owner: state.owner,
52
+ name: state.repo,
53
+ fullName: `${state.owner}/${state.repo}`,
54
+ },
55
+ ...(state.installationId === null
56
+ ? {}
57
+ : { installationId: state.installationId }),
58
+ cursorAccount:
59
+ options.cursorAccount !== undefined && options.cursorAccount !== false,
60
+ app: options.app,
61
+ });
62
+ }
63
+
64
+ async function postPullRequestComment(
65
+ options: BuildDefaultOriginEventsOptions,
66
+ state: OriginChannelState,
67
+ body: string
68
+ ): Promise<void> {
69
+ if (
70
+ state.owner === "" ||
71
+ state.repo === "" ||
72
+ state.pullRequestNumber === null
73
+ ) {
74
+ return;
75
+ }
76
+ const origin = bindingForState(options, state);
77
+ await origin.request({
78
+ method: "POST",
79
+ path: `/v1/origin/repos/${encodeURIComponent(state.owner)}/${encodeURIComponent(
80
+ state.repo
81
+ )}/pulls/${state.pullRequestNumber}/comments`,
82
+ body: { body: formatOriginOutboundComment(body) },
83
+ });
84
+ }
85
+
86
+ /**
87
+ * Built-in delivery: post assistant text on `message.completed`, and a
88
+ * short error comment on turn/session failure. Every post soft-fails so a
89
+ * missing outbound credential (or an Origin refusal) never crashes the
90
+ * session — the GitHub defaults' posture.
91
+ */
92
+ export function buildDefaultOriginEvents(
93
+ options: BuildDefaultOriginEventsOptions = {}
94
+ ): ChannelEventHandlers<OriginChannelState> {
95
+ const deliverReplies = options.deliverReplies !== false;
96
+
97
+ return {
98
+ async "message.completed"(event, channel) {
99
+ if (!deliverReplies) {
100
+ return;
101
+ }
102
+ if (event.data.finishReason === "tool_call" || event.data.text === "") {
103
+ return;
104
+ }
105
+ try {
106
+ await postPullRequestComment(options, channel.state, event.data.text);
107
+ } catch {
108
+ // Soft-fail delivery so a missing credential does not crash the session.
109
+ }
110
+ },
111
+
112
+ async "turn.failed"(_event, channel) {
113
+ await postFailure(options, channel, deliverReplies);
114
+ },
115
+
116
+ async "session.failed"(_event, channel) {
117
+ await postFailure(options, channel, deliverReplies);
118
+ },
119
+ };
120
+ }
121
+
122
+ async function postFailure(
123
+ options: BuildDefaultOriginEventsOptions,
124
+ channel: { state: OriginChannelState },
125
+ deliverReplies: boolean
126
+ ): Promise<void> {
127
+ if (!deliverReplies) {
128
+ return;
129
+ }
130
+ try {
131
+ await postPullRequestComment(
132
+ options,
133
+ channel.state,
134
+ [
135
+ "I hit an error while handling your request.",
136
+ "",
137
+ "Please try again, or reach out if it keeps failing.",
138
+ ].join("\n")
139
+ );
140
+ } catch {
141
+ // Soft-fail.
142
+ }
143
+ }
@@ -26,8 +26,10 @@ export * from "./api.js";
26
26
  export * from "./binding.js";
27
27
  export * from "./checks.js";
28
28
  export * from "./cursor-account.js";
29
+ export * from "./defaults.js";
29
30
  export * from "./events.js";
30
31
  export * from "./origin-channel.js";
31
32
  export * from "./origin-webhook.js";
32
33
  export * from "./reactions.js";
34
+ export * from "./state.js";
33
35
  export * from "./types.js";
@@ -18,13 +18,16 @@ import type {
18
18
  AgentCloudOptions,
19
19
  AuthContext,
20
20
  ChannelDefinition,
21
+ ChannelEventHandlers,
21
22
  ChannelHandlerArgs,
23
+ JsonValue,
22
24
  } from "../../types.js";
23
25
  import { buildOriginBinding } from "./binding.js";
24
26
  import {
25
27
  parseCursorOriginRepoScope,
26
28
  registerOriginCursorAccountRuntime,
27
29
  } from "./cursor-account.js";
30
+ import { buildDefaultOriginEvents } from "./defaults.js";
28
31
  import { deriveOriginWebhookEvents, ORIGIN_CHANNEL_KIND } from "./events.js";
29
32
  import {
30
33
  DEFAULT_ORIGIN_API_BASE_URL,
@@ -32,6 +35,11 @@ import {
32
35
  type OriginWebhookHeaders,
33
36
  verifyOriginWebhook,
34
37
  } from "./origin-webhook.js";
38
+ import {
39
+ emptyOriginChannelState,
40
+ type OriginChannelState,
41
+ originChannelStateForEvent,
42
+ } from "./state.js";
35
43
  import type {
36
44
  OriginActor,
37
45
  OriginChannelOptions,
@@ -432,6 +440,7 @@ function enrichEventContext(input: {
432
440
  ...input.ctx,
433
441
  host: input.args.host,
434
442
  artifacts: input.args.artifacts,
443
+ send: input.args.send,
435
444
  origin: buildOriginBinding({
436
445
  repository: input.ctx.repository,
437
446
  installationId: input.ctx.installationId,
@@ -504,6 +513,7 @@ async function startTurn(input: {
504
513
  message: string;
505
514
  dispatch: OriginTurnDispatch;
506
515
  cloud?: AgentCloudOptions;
516
+ state: OriginChannelState;
507
517
  }): Promise<Response> {
508
518
  const source = continuationSource(input.options.continuation, "origin");
509
519
  const session = await input.args.send(input.message, {
@@ -513,6 +523,10 @@ async function startTurn(input: {
513
523
  : {}),
514
524
  title: input.dispatch.title ?? defaultOriginTitle(input.ctx),
515
525
  ...(input.cloud === undefined ? {} : { cloud: input.cloud }),
526
+ state: input.state as unknown as JsonValue,
527
+ // Resume must refresh the triggering comment / delivery identifiers so
528
+ // reply delivery targets the latest wake, not the session's first.
529
+ refreshState: input.state as unknown as JsonValue,
516
530
  });
517
531
  if (isDeferredChannelSession(session)) {
518
532
  // Hosted admission captured the send; the control plane allocates the
@@ -569,6 +583,8 @@ async function applyDispatch(input: {
569
583
  extra: Record<string, unknown>;
570
584
  message: string;
571
585
  cloud?: AgentCloudOptions;
586
+ /** Comment id that woke this dispatch (comment events only). */
587
+ triggeringCommentId?: string;
572
588
  }): Promise<Response> {
573
589
  if (input.dispatch === null) {
574
590
  return skipped("not_dispatched", input.extra);
@@ -587,6 +603,14 @@ async function applyDispatch(input: {
587
603
  message,
588
604
  dispatch: input.dispatch,
589
605
  cloud: input.cloud,
606
+ state: originChannelStateForEvent({
607
+ repository: input.ctx.repository,
608
+ pullRequestNumber: input.ctx.pullRequestNumber,
609
+ installationId: input.ctx.installationId,
610
+ deliveryId: input.ctx.deliveryId,
611
+ eventType: input.ctx.eventType,
612
+ triggeringCommentId: input.triggeringCommentId,
613
+ }),
590
614
  });
591
615
  }
592
616
 
@@ -654,6 +678,7 @@ export async function dispatchOriginWebhook(input: {
654
678
  dispatch,
655
679
  extra: { event: eventType },
656
680
  message: `Origin comment on ${ctx.repository.fullName}#${ctx.pullRequestNumber}`,
681
+ triggeringCommentId: commentId,
657
682
  });
658
683
  }
659
684
 
@@ -798,7 +823,7 @@ export function getOriginChannelOptions(
798
823
 
799
824
  export function originChannel(
800
825
  options: OriginChannelOptions = {}
801
- ): ChannelDefinition {
826
+ ): ChannelDefinition<OriginChannelState> {
802
827
  const usesCursorAccount =
803
828
  options.cursorAccount === true || typeof options.cursorAccount === "object";
804
829
  const cursorScope =
@@ -833,8 +858,19 @@ export function originChannel(
833
858
  );
834
859
  }
835
860
 
861
+ const events: ChannelEventHandlers<OriginChannelState> = {
862
+ ...buildDefaultOriginEvents({
863
+ cursorAccount: channelOptions.cursorAccount,
864
+ app: channelOptions.app,
865
+ deliverReplies: channelOptions.deliverReplies,
866
+ }),
867
+ ...options.events,
868
+ };
869
+
836
870
  const definition = defineChannel({
837
871
  auth,
872
+ state: emptyOriginChannelState(),
873
+ events,
838
874
  onStart: options.onStart,
839
875
  onStop: options.onStop,
840
876
  meta: {
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Durable per-session Origin channel state.
3
+ *
4
+ * Persisted with the turn (same mechanism as `GitHubChannelState`) so
5
+ * channel stream-event handlers — reply delivery in ./defaults.ts — can
6
+ * rebuild a repo-bound Origin handle without re-parsing the webhook.
7
+ */
8
+
9
+ export interface OriginChannelState {
10
+ owner: string;
11
+ repo: string;
12
+ pullRequestNumber: number | null;
13
+ /** Origin app installation id from the delivery envelope, when present. */
14
+ installationId: string | null;
15
+ /** Comment id that woke the turn (comment events only). */
16
+ triggeringCommentId: string | null;
17
+ deliveryId: string | null;
18
+ eventType: string | null;
19
+ }
20
+
21
+ export function emptyOriginChannelState(
22
+ overrides: Partial<OriginChannelState> = {}
23
+ ): OriginChannelState {
24
+ return {
25
+ owner: "",
26
+ repo: "",
27
+ pullRequestNumber: null,
28
+ installationId: null,
29
+ triggeringCommentId: null,
30
+ deliveryId: null,
31
+ eventType: null,
32
+ ...overrides,
33
+ };
34
+ }
35
+
36
+ /** Build the per-turn channel state from a dispatched event's context. */
37
+ export function originChannelStateForEvent(input: {
38
+ repository: { owner: string; name: string };
39
+ pullRequestNumber: number;
40
+ installationId?: string;
41
+ deliveryId?: string;
42
+ eventType: string;
43
+ triggeringCommentId?: string;
44
+ }): OriginChannelState {
45
+ return emptyOriginChannelState({
46
+ owner: input.repository.owner,
47
+ repo: input.repository.name,
48
+ pullRequestNumber: input.pullRequestNumber,
49
+ installationId: input.installationId ?? null,
50
+ triggeringCommentId: input.triggeringCommentId ?? null,
51
+ deliveryId: input.deliveryId ?? null,
52
+ eventType: input.eventType,
53
+ });
54
+ }
@@ -4,11 +4,14 @@ import type {
4
4
  ArtifactsApi,
5
5
  AuthContext,
6
6
  AuthPolicy,
7
+ ChannelEventHandlers,
7
8
  ChannelStartArgs,
8
9
  HostContext,
10
+ SendMessageFn,
9
11
  } from "../../types.js";
10
12
  import type { OriginTokenProvider } from "./api.js";
11
13
  import type { OriginHandle } from "./binding.js";
14
+ import type { OriginChannelState } from "./state.js";
12
15
 
13
16
  export interface OriginActor {
14
17
  id: string;
@@ -70,6 +73,12 @@ export interface OriginEventContext {
70
73
  */
71
74
  payload: Record<string, unknown>;
72
75
  sender?: OriginActor;
76
+ /**
77
+ * Channel `send`. Set on every delivery path (HTTP webhook, hosted
78
+ * admission, SCM events) so a hook can start a turn itself instead of
79
+ * returning `{ auth, message }` or a deferred `{ task }`.
80
+ */
81
+ send?: SendMessageFn;
73
82
  host: HostContext;
74
83
  artifacts: ArtifactsApi;
75
84
  /**
@@ -242,6 +251,21 @@ export interface OriginChannelOptions {
242
251
  * pull request URL, or a resolver for custom cloud options.
243
252
  */
244
253
  cloud?: boolean | AgentCloudOptions | OriginCloudOptionsResolver;
254
+ /**
255
+ * When false, skip posting completed assistant messages (and failure
256
+ * notices) back to the Origin pull request. Defaults to true — the GitHub
257
+ * channel's reply-delivery posture. Outbound credentials resolve like
258
+ * `ctx.origin`: {@link app} / `ORIGIN_APP_*` env when configured,
259
+ * otherwise the Cursor-account session exchange (hosted v2 deployments
260
+ * post as the deployment service-account principal).
261
+ */
262
+ deliverReplies?: boolean;
263
+ /**
264
+ * Channel stream-event handlers, merged over the built-in reply-delivery
265
+ * defaults (`buildDefaultOriginEvents`) — same override contract as the
266
+ * GitHub channel's `events`.
267
+ */
268
+ events?: ChannelEventHandlers<OriginChannelState>;
245
269
  /** Called once when the server mounts this channel. */
246
270
  onStart?: (args: ChannelStartArgs) => void | Promise<void>;
247
271
  /** Called when the server shuts down. */
@@ -5,6 +5,7 @@
5
5
  import { ErrorCode, type WebAPIPlatformError, WebClient } from "@slack/web-api";
6
6
  import { slackifyMarkdown } from "slackify-markdown";
7
7
  import type { ArtifactsApi, HostContext } from "../../types.js";
8
+ import { highlightCodeFences } from "./code-fences.js";
8
9
  import {
9
10
  SLACK_DEFAULT_LOADING_MESSAGES,
10
11
  SLACK_LOADING_MESSAGE_MAX_LEN,
@@ -16,7 +17,7 @@ import {
16
17
  } from "./constants.js";
17
18
  import { tryResolveAppToken, tryResolveBotToken } from "./credentials.js";
18
19
  import { defaultSlackLog, type SlackLog } from "./log.js";
19
- import type { StreamTaskChunk } from "./stream.js";
20
+ import type { StreamChunk } from "./stream.js";
20
21
  import type {
21
22
  SlackApiTransport,
22
23
  SlackBinding,
@@ -194,10 +195,18 @@ export function truncateTitle(title: string, max?: number): string {
194
195
  // ---------------------------------------------------------------------------
195
196
 
196
197
  /**
197
- * Show or clear the Working chip. Agent UX ignores empty
198
- * `assistant.threads.setStatus`; `agents.sessions.setStatus` `active` is
199
- * what actually clears it. The assistant call stays for loading_messages
200
- * and older workspaces.
198
+ * Show or clear the status chip under the thread.
199
+ *
200
+ * Status text goes through `assistant.threads.setStatus` alone. The agent
201
+ * session is only written when clearing: Agent UX ignores an empty assistant
202
+ * status, so `agents.sessions.setStatus` `active` is what actually drops the
203
+ * chip. That same write must not accompany status text — Slack applies it
204
+ * asynchronously and it blanks the chip when it lands after the text, which
205
+ * reads as flicker between updates. A `processing` write would be worse:
206
+ * Agent UX paints its own generic "is working…" over the assistant text
207
+ * while the session is `processing`. An open `chat.startStream` also flips
208
+ * the session to `processing` on Slack's side, so status text only shows on
209
+ * non-streaming turns. The empty assistant call stays for older workspaces.
201
210
  */
202
211
  export async function setThreadStatus(args: {
203
212
  botToken: SlackBotToken | undefined;
@@ -210,21 +219,12 @@ export async function setThreadStatus(args: {
210
219
  return { ok: false, error: "missing_channel_or_thread" };
211
220
  }
212
221
  const status = truncateTypingStatus(args.status);
213
- const sessionResult = await callSlackApiSoft({
214
- botToken: args.botToken,
215
- operation: "agents.sessions.setStatus",
216
- body: {
217
- channel_id: args.channelId,
218
- thread_ts: args.threadTs,
219
- status: status.length > 0 ? "processing" : "active",
220
- },
221
- });
222
-
223
222
  const body: Record<string, unknown> = {
224
223
  channel_id: args.channelId,
225
224
  thread_ts: args.threadTs,
226
225
  status,
227
226
  };
227
+
228
228
  if (status.length > 0) {
229
229
  const loadingRaw =
230
230
  args.loadingMessages !== undefined && args.loadingMessages.length > 0
@@ -237,7 +237,22 @@ export async function setThreadStatus(args: {
237
237
  if (loading_messages.length > 0) {
238
238
  body.loading_messages = loading_messages;
239
239
  }
240
+ return callSlackApiSoft({
241
+ botToken: args.botToken,
242
+ operation: "assistant.threads.setStatus",
243
+ body,
244
+ });
240
245
  }
246
+
247
+ const sessionResult = await callSlackApiSoft({
248
+ botToken: args.botToken,
249
+ operation: "agents.sessions.setStatus",
250
+ body: {
251
+ channel_id: args.channelId,
252
+ thread_ts: args.threadTs,
253
+ status: "active",
254
+ },
255
+ });
241
256
  const assistantResult = await callSlackApiSoft({
242
257
  botToken: args.botToken,
243
258
  operation: "assistant.threads.setStatus",
@@ -300,7 +315,7 @@ export async function startChatStream(args: {
300
315
  channel: string;
301
316
  thread_ts?: string;
302
317
  markdown_text?: string;
303
- chunks?: StreamTaskChunk[];
318
+ chunks?: StreamChunk[];
304
319
  recipient_user_id?: string;
305
320
  recipient_team_id?: string;
306
321
  }): Promise<SoftSlackResult<{ ts: string; channel: string }>> {
@@ -346,7 +361,7 @@ export async function appendChatStream(args: {
346
361
  channel: string;
347
362
  ts: string;
348
363
  markdown_text?: string;
349
- chunks?: StreamTaskChunk[];
364
+ chunks?: StreamChunk[];
350
365
  }): Promise<SoftSlackResult> {
351
366
  const body: Record<string, unknown> = {
352
367
  channel: args.channel,
@@ -370,6 +385,7 @@ export async function stopChatStream(args: {
370
385
  channel: string;
371
386
  ts: string;
372
387
  markdown_text?: string;
388
+ chunks?: StreamChunk[];
373
389
  blocks?: unknown[];
374
390
  }): Promise<SoftSlackResult> {
375
391
  const body: Record<string, unknown> = {
@@ -379,6 +395,9 @@ export async function stopChatStream(args: {
379
395
  if (args.markdown_text !== undefined) {
380
396
  body.markdown_text = args.markdown_text;
381
397
  }
398
+ if (args.chunks !== undefined && args.chunks.length > 0) {
399
+ body.chunks = args.chunks;
400
+ }
382
401
  if (args.blocks !== undefined && args.blocks.length > 0) {
383
402
  body.blocks = args.blocks;
384
403
  }
@@ -477,7 +496,7 @@ export async function postMessage(args: {
477
496
  operation: "chat.postMessage",
478
497
  body: {
479
498
  ...base,
480
- markdown_text: args.text,
499
+ markdown_text: highlightCodeFences(args.text),
481
500
  },
482
501
  });
483
502
  // Older workspaces / scopes may not accept markdown_text — retry with text.
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Slack highlights a fenced code block only when its info string is a
3
+ * language it knows (`ts`, `python`, …). Models on this harness cite code
4
+ * with Cursor's `startLine:endLine:path` form, or a bare path, which Slack
5
+ * shows verbatim as the block's header with no highlighting. The header is
6
+ * the only slot Slack offers, so a block gets colors by moving the reference
7
+ * to a comment on its first line. Files whose language has no comment
8
+ * syntax, or that Slack cannot color anyway, keep the reference as header.
9
+ */
10
+
11
+ const FENCE = /^(\s*)(`{3,}|~{3,})(.*)$/;
12
+ /** A line that may still grow into a fence. */
13
+ const FENCE_START = /^\s*(`{1,2}|~{1,2})$/;
14
+ const CITATION = /^(\d+):(\d+):(\S+)$/;
15
+
16
+ const LANGUAGE_BY_EXTENSION: Readonly<Record<string, string>> = {
17
+ ts: "ts",
18
+ mts: "ts",
19
+ cts: "ts",
20
+ tsx: "tsx",
21
+ js: "js",
22
+ mjs: "js",
23
+ cjs: "js",
24
+ jsx: "jsx",
25
+ py: "python",
26
+ go: "go",
27
+ rs: "rust",
28
+ java: "java",
29
+ kt: "kotlin",
30
+ swift: "swift",
31
+ rb: "ruby",
32
+ php: "php",
33
+ c: "c",
34
+ h: "c",
35
+ cc: "cpp",
36
+ cpp: "cpp",
37
+ hpp: "cpp",
38
+ cs: "csharp",
39
+ json: "json",
40
+ jsonc: "jsonc",
41
+ yaml: "yaml",
42
+ yml: "yaml",
43
+ toml: "toml",
44
+ xml: "xml",
45
+ html: "html",
46
+ css: "css",
47
+ scss: "scss",
48
+ md: "markdown",
49
+ mdx: "mdx",
50
+ sh: "bash",
51
+ bash: "bash",
52
+ zsh: "bash",
53
+ sql: "sql",
54
+ proto: "protobuf",
55
+ tf: "hcl",
56
+ graphql: "graphql",
57
+ dockerfile: "dockerfile",
58
+ ini: "ini",
59
+ };
60
+
61
+ /** `[open, close]` comment delimiters; languages without one (JSON) are absent. */
62
+ const COMMENT_BY_LANGUAGE: Readonly<Record<string, readonly [string, string]>> =
63
+ {
64
+ ts: ["//", ""],
65
+ tsx: ["//", ""],
66
+ js: ["//", ""],
67
+ jsx: ["//", ""],
68
+ go: ["//", ""],
69
+ rust: ["//", ""],
70
+ java: ["//", ""],
71
+ kotlin: ["//", ""],
72
+ swift: ["//", ""],
73
+ php: ["//", ""],
74
+ c: ["//", ""],
75
+ cpp: ["//", ""],
76
+ csharp: ["//", ""],
77
+ jsonc: ["//", ""],
78
+ protobuf: ["//", ""],
79
+ python: ["#", ""],
80
+ ruby: ["#", ""],
81
+ yaml: ["#", ""],
82
+ toml: ["#", ""],
83
+ bash: ["#", ""],
84
+ dockerfile: ["#", ""],
85
+ ini: ["#", ""],
86
+ hcl: ["#", ""],
87
+ graphql: ["#", ""],
88
+ sql: ["--", ""],
89
+ css: ["/*", "*/"],
90
+ scss: ["/*", "*/"],
91
+ html: ["<!--", "-->"],
92
+ xml: ["<!--", "-->"],
93
+ markdown: ["<!--", "-->"],
94
+ mdx: ["<!--", "-->"],
95
+ };
96
+
97
+ function languageForPath(path: string): string | undefined {
98
+ const base = path.slice(path.lastIndexOf("/") + 1).toLowerCase();
99
+ const ext = base.includes(".") ? base.slice(base.lastIndexOf(".") + 1) : base;
100
+ return LANGUAGE_BY_EXTENSION[ext];
101
+ }
102
+
103
+ function looksLikePath(info: string): boolean {
104
+ return info.includes("/") || languageForPath(info) !== undefined;
105
+ }
106
+
107
+ /**
108
+ * Replacement lines for an opening fence whose info string is a citation or
109
+ * a path: the fence tagged with the language, then the reference as a
110
+ * comment. Falls back to the reference as the header when the block cannot
111
+ * carry a comment. `null` when the info string is neither.
112
+ */
113
+ function rewriteOpening(
114
+ indent: string,
115
+ marks: string,
116
+ info: string
117
+ ): string[] | null {
118
+ const token = info.trim().split(/\s+/)[0] ?? "";
119
+ const cited = CITATION.exec(token);
120
+ const path = cited?.[3] ?? (looksLikePath(token) ? token : undefined);
121
+ if (path === undefined) {
122
+ return null;
123
+ }
124
+ const reference = cited === null ? path : `${path}:${cited[1]}-${cited[2]}`;
125
+ const language = languageForPath(path);
126
+ const comment =
127
+ language === undefined ? undefined : COMMENT_BY_LANGUAGE[language];
128
+ if (comment === undefined) {
129
+ return [`${indent}${marks}${reference}`];
130
+ }
131
+ const [open, close] = comment;
132
+ const commented =
133
+ close === "" ? `${open} ${reference}` : `${open} ${reference} ${close}`;
134
+ return [`${indent}${marks}${language}`, `${indent}${commented}`];
135
+ }
136
+
137
+ /**
138
+ * Rewrite fence info strings so Slack highlights the block. Safe to run on
139
+ * a growing stream: the output for a prefix is a prefix of the output for
140
+ * the full text, because an opening fence whose line has not ended yet is
141
+ * held back rather than emitted half-formed.
142
+ */
143
+ export function highlightCodeFences(markdown: string): string {
144
+ const complete = markdown.endsWith("\n");
145
+ const lines = markdown.split("\n");
146
+ if (complete) {
147
+ lines.pop();
148
+ }
149
+ const out: string[] = [];
150
+ let open: { marks: string } | null = null;
151
+ const heldBack = (): string =>
152
+ `${out.join("\n")}${out.length > 0 ? "\n" : ""}`;
153
+ for (const [index, line] of lines.entries()) {
154
+ const last = index === lines.length - 1 && !complete;
155
+ const fence = FENCE.exec(line);
156
+ if (fence === null) {
157
+ if (last && open === null && FENCE_START.test(line)) {
158
+ return heldBack();
159
+ }
160
+ out.push(line);
161
+ continue;
162
+ }
163
+ const [, indent = "", marks = "", info = ""] = fence;
164
+ if (open !== null) {
165
+ if (
166
+ marks[0] === open.marks[0] &&
167
+ marks.length >= open.marks.length &&
168
+ info.trim() === ""
169
+ ) {
170
+ open = null;
171
+ }
172
+ out.push(line);
173
+ continue;
174
+ }
175
+ if (last) {
176
+ // Opening fence still being written: wait for the whole line.
177
+ return heldBack();
178
+ }
179
+ open = { marks };
180
+ out.push(...(rewriteOpening(indent, marks, info) ?? [line]));
181
+ }
182
+ return complete ? `${out.join("\n")}\n` : out.join("\n");
183
+ }
@@ -13,6 +13,12 @@ export const SLACK_LOADING_MESSAGE_MAX_LEN = 50;
13
13
  /** Slack `assistant.threads.setStatus` accepts at most 5 `loading_messages`. */
14
14
  export const SLACK_LOADING_MESSAGES_MAX = 5;
15
15
  export const SLACK_TITLE_MAX_LEN = 80;
16
+ /**
17
+ * `markdown_text` (and so a streamed message, cards included) tops out near
18
+ * 12k characters; past it Slack answers `msg_too_long`. Plain `text` allows
19
+ * about 40k.
20
+ */
21
+ export const SLACK_MARKDOWN_TEXT_MAX_LEN = 12_000;
16
22
 
17
23
  /** Rotating assistant status lines (Slack `loading_messages`). */
18
24
  export const SLACK_DEFAULT_LOADING_MESSAGES = [