@cursor/july 0.1.96 → 0.1.99

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 (381) hide show
  1. package/AGENTS.md +1 -1
  2. package/README.md +3 -2
  3. package/dist/bin/agent-serve.js +13 -3
  4. package/dist/channels/github/github-channel.d.ts.map +1 -1
  5. package/dist/channels/github/github-channel.js +16 -0
  6. package/dist/channels/origin/api.d.ts +15 -4
  7. package/dist/channels/origin/api.d.ts.map +1 -1
  8. package/dist/channels/origin/api.js +19 -3
  9. package/dist/channels/origin/binding.d.ts +11 -0
  10. package/dist/channels/origin/binding.d.ts.map +1 -1
  11. package/dist/channels/origin/binding.js +41 -25
  12. package/dist/channels/origin/index.d.ts +1 -0
  13. package/dist/channels/origin/index.d.ts.map +1 -1
  14. package/dist/channels/origin/index.js +1 -0
  15. package/dist/channels/origin/origin-channel.d.ts +2 -0
  16. package/dist/channels/origin/origin-channel.d.ts.map +1 -1
  17. package/dist/channels/origin/origin-channel.js +40 -4
  18. package/dist/channels/origin/reactions.d.ts +56 -0
  19. package/dist/channels/origin/reactions.d.ts.map +1 -0
  20. package/dist/channels/origin/reactions.js +67 -0
  21. package/dist/channels/origin/types.d.ts +11 -0
  22. package/dist/channels/origin/types.d.ts.map +1 -1
  23. package/dist/channels/slack/approvals.d.ts +16 -0
  24. package/dist/channels/slack/approvals.d.ts.map +1 -1
  25. package/dist/channels/slack/approvals.js +86 -0
  26. package/dist/channels/slack/cli-project.d.ts +19 -0
  27. package/dist/channels/slack/cli-project.d.ts.map +1 -0
  28. package/dist/channels/slack/cli-project.js +234 -0
  29. package/dist/channels/slack/defaults.d.ts.map +1 -1
  30. package/dist/channels/slack/defaults.js +142 -63
  31. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  32. package/dist/channels/slack/dispatch.js +1 -1
  33. package/dist/channels/slack/init.d.ts +3 -2
  34. package/dist/channels/slack/init.d.ts.map +1 -1
  35. package/dist/channels/slack/init.js +5 -5
  36. package/dist/channels/slack/interactive.d.ts +2 -1
  37. package/dist/channels/slack/interactive.d.ts.map +1 -1
  38. package/dist/channels/slack/interactive.js +15 -4
  39. package/dist/channels/slack/live-delivery.d.ts +1 -1
  40. package/dist/channels/slack/live-delivery.d.ts.map +1 -1
  41. package/dist/channels/slack/live-delivery.js +4 -2
  42. package/dist/channels/slack/manifest.d.ts +1 -1
  43. package/dist/channels/slack/manifest.js +1 -1
  44. package/dist/channels/slack/progress-delivery.d.ts +28 -0
  45. package/dist/channels/slack/progress-delivery.d.ts.map +1 -0
  46. package/dist/channels/slack/progress-delivery.js +115 -0
  47. package/dist/channels/slack/setup.d.ts +1 -1
  48. package/dist/channels/slack/setup.d.ts.map +1 -1
  49. package/dist/channels/slack/setup.js +10 -6
  50. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  51. package/dist/channels/slack/slack-channel.js +1 -0
  52. package/dist/channels/slack/tool-approval-events.d.ts.map +1 -1
  53. package/dist/channels/slack/tool-approval-events.js +91 -1
  54. package/dist/channels/slack/types.d.ts +9 -1
  55. package/dist/channels/slack/types.d.ts.map +1 -1
  56. package/dist/docs/404.html +2 -2
  57. package/dist/docs/ab.html +4 -4
  58. package/dist/docs/assets/{app.jXleCmOc.js → app.BplEAZ3S.js} +1 -1
  59. package/dist/docs/assets/chunks/@localSearchIndexroot.DpuI4i7Z.js +1 -0
  60. package/dist/docs/assets/chunks/{VPLocalSearchBox.8LhyglIT.js → VPLocalSearchBox.CHXyv4wP.js} +1 -1
  61. package/dist/docs/assets/chunks/{theme.9ged-pr2.js → theme.BTcsZmjQ.js} +2 -2
  62. package/dist/docs/assets/{deployment.md.D9msOFOW.js → deployment.md.MFPKqsqI.js} +2 -2
  63. package/dist/docs/assets/{guides_mcp-oauth.md.DPYmBCbV.js → guides_mcp-oauth.md.CN-6YmTJ.js} +4 -4
  64. package/dist/docs/assets/{guides_mcp-oauth.md.DPYmBCbV.lean.js → guides_mcp-oauth.md.CN-6YmTJ.lean.js} +1 -1
  65. package/dist/docs/assets/guides_slack.md.VDXQV3ja.js +22 -0
  66. package/dist/docs/assets/guides_slack.md.VDXQV3ja.lean.js +1 -0
  67. package/dist/docs/assets/index.md.CVeRUOeZ.js +5 -0
  68. package/dist/docs/assets/{reference_agent-config.md.Cp_x38Nl.js → reference_agent-config.md.BHeYMgme.js} +1 -1
  69. package/dist/docs/assets/{reference_cli.md.CCnG-nJx.js → reference_cli.md.DfoeyvL0.js} +9 -6
  70. package/dist/docs/assets/{reference_cli.md.CCnG-nJx.lean.js → reference_cli.md.DfoeyvL0.lean.js} +1 -1
  71. package/dist/docs/assets/{reference_connections.md.BH8Oc0D0.js → reference_connections.md.DxldvyIB.js} +4 -3
  72. package/dist/docs/assets/{reference_http-api.md.D89k1mdm.js → reference_http-api.md.BEJx9XVj.js} +2 -2
  73. package/dist/docs/assets/reference_sessions.md.NxFP_CAC.js +1 -0
  74. package/dist/docs/assets/{reference_tools.md.BHeXn2id.js → reference_tools.md.CvAHsdSp.js} +10 -2
  75. package/dist/docs/assets/{reference_tools.md.BHeXn2id.lean.js → reference_tools.md.CvAHsdSp.lean.js} +1 -1
  76. package/dist/docs/assets/templates_agents-md.md.CXSMZljE.js +2 -0
  77. package/dist/docs/assets/templates_agents-md.md.CXSMZljE.lean.js +1 -0
  78. package/dist/docs/assets/troubleshooting.md.DCiPBhYs.js +1 -0
  79. package/dist/docs/building-with-agents.html +4 -4
  80. package/dist/docs/concepts.html +4 -4
  81. package/dist/docs/deployment.html +7 -7
  82. package/dist/docs/deployment.md +5 -4
  83. package/dist/docs/design/runtime-abstraction.md +1757 -0
  84. package/dist/docs/evals.html +4 -4
  85. package/dist/docs/guides/agent-to-agent.html +4 -4
  86. package/dist/docs/guides/cloud-runtime.html +4 -4
  87. package/dist/docs/guides/convert-automation.html +4 -4
  88. package/dist/docs/guides/github.html +4 -4
  89. package/dist/docs/guides/human-in-the-loop.html +4 -4
  90. package/dist/docs/guides/mcp-oauth.html +8 -8
  91. package/dist/docs/guides/mcp-oauth.md +26 -8
  92. package/dist/docs/guides/opentelemetry.html +4 -4
  93. package/dist/docs/guides/slack.html +17 -33
  94. package/dist/docs/guides/slack.md +92 -201
  95. package/dist/docs/guides/webhooks.html +4 -4
  96. package/dist/docs/hashmap.json +1 -1
  97. package/dist/docs/hillclimbing.html +4 -4
  98. package/dist/docs/index.html +6 -6
  99. package/dist/docs/index.md +5 -3
  100. package/dist/docs/llms-full.txt +2065 -637
  101. package/dist/docs/llms.txt +3 -2
  102. package/dist/docs/quickstart.html +4 -4
  103. package/dist/docs/reference/agent-config.html +6 -6
  104. package/dist/docs/reference/agent-config.md +2 -2
  105. package/dist/docs/reference/artifacts.html +4 -4
  106. package/dist/docs/reference/channels.html +4 -4
  107. package/dist/docs/reference/cli.html +13 -10
  108. package/dist/docs/reference/cli.md +32 -16
  109. package/dist/docs/reference/connections.html +9 -8
  110. package/dist/docs/reference/connections.md +6 -3
  111. package/dist/docs/reference/hooks.html +4 -4
  112. package/dist/docs/reference/http-api.html +7 -7
  113. package/dist/docs/reference/http-api.md +3 -1
  114. package/dist/docs/reference/instructions.html +4 -4
  115. package/dist/docs/reference/playground.html +4 -4
  116. package/dist/docs/reference/project-layout.html +4 -4
  117. package/dist/docs/reference/prompt.html +4 -4
  118. package/dist/docs/reference/schedules.html +4 -4
  119. package/dist/docs/reference/sessions.html +5 -5
  120. package/dist/docs/reference/sessions.md +4 -2
  121. package/dist/docs/reference/skills.html +4 -4
  122. package/dist/docs/reference/subagents.html +4 -4
  123. package/dist/docs/reference/tools.html +15 -7
  124. package/dist/docs/reference/tools.md +34 -2
  125. package/dist/docs/scaffolding-agents.html +4 -4
  126. package/dist/docs/storage.html +4 -4
  127. package/dist/docs/templates/agentic-owners.html +4 -4
  128. package/dist/docs/templates/agents-md.html +28 -0
  129. package/dist/docs/templates/agents-md.md +105 -0
  130. package/dist/docs/templates/code-wiki.html +5 -5
  131. package/dist/docs/templates/demo.html +4 -4
  132. package/dist/docs/templates/pr-autofixer.html +4 -4
  133. package/dist/docs/templates/security-help.html +4 -4
  134. package/dist/docs/templates/security-reviewer.html +5 -5
  135. package/dist/docs/templates/triage.html +4 -4
  136. package/dist/docs/troubleshooting.html +5 -5
  137. package/dist/docs/troubleshooting.md +2 -2
  138. package/dist/evals/run-facts.d.ts.map +1 -1
  139. package/dist/evals/run-facts.js +27 -0
  140. package/dist/files-backends/cursor-hosted.d.ts +3 -2
  141. package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
  142. package/dist/files-backends/cursor-hosted.js +3 -2
  143. package/dist/index.d.ts +1 -0
  144. package/dist/index.d.ts.map +1 -1
  145. package/dist/index.js +1 -0
  146. package/dist/internal/advertise-tools.d.ts.map +1 -1
  147. package/dist/internal/advertise-tools.js +15 -9
  148. package/dist/internal/approval-gate.d.ts +12 -13
  149. package/dist/internal/approval-gate.d.ts.map +1 -1
  150. package/dist/internal/approval-gate.js +16 -21
  151. package/dist/internal/as-of.d.ts +19 -0
  152. package/dist/internal/as-of.d.ts.map +1 -0
  153. package/dist/internal/as-of.js +82 -0
  154. package/dist/internal/chat-client.js +10 -0
  155. package/dist/internal/cli-deploy.d.ts +6 -0
  156. package/dist/internal/cli-deploy.d.ts.map +1 -1
  157. package/dist/internal/cli-deploy.js +149 -21
  158. package/dist/internal/cli-mcp-oauth.js +8 -18
  159. package/dist/internal/cli-slack-manual.d.ts +24 -2
  160. package/dist/internal/cli-slack-manual.d.ts.map +1 -1
  161. package/dist/internal/cli-slack-manual.js +251 -20
  162. package/dist/internal/cli-slack.d.ts +9 -2
  163. package/dist/internal/cli-slack.d.ts.map +1 -1
  164. package/dist/internal/cli-slack.js +29 -82
  165. package/dist/internal/cursor/account-mcp.d.ts +1 -0
  166. package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
  167. package/dist/internal/cursor/account-mcp.js +17 -0
  168. package/dist/internal/cursor-agent-template.d.ts +1 -1
  169. package/dist/internal/cursor-agent-template.d.ts.map +1 -1
  170. package/dist/internal/cursor-agent-template.js +1 -0
  171. package/dist/internal/cursor-event-relay.d.ts.map +1 -1
  172. package/dist/internal/cursor-event-relay.js +5 -6
  173. package/dist/internal/deploy-client.d.ts +17 -0
  174. package/dist/internal/deploy-client.d.ts.map +1 -1
  175. package/dist/internal/deploy-client.js +31 -10
  176. package/dist/internal/env-file.d.ts +19 -0
  177. package/dist/internal/env-file.d.ts.map +1 -0
  178. package/dist/internal/env-file.js +90 -0
  179. package/dist/internal/framework-file-storage.d.ts +11 -17
  180. package/dist/internal/framework-file-storage.d.ts.map +1 -1
  181. package/dist/internal/framework-file-storage.js +17 -40
  182. package/dist/internal/framework-storage-selection.d.ts +13 -11
  183. package/dist/internal/framework-storage-selection.d.ts.map +1 -1
  184. package/dist/internal/framework-storage-selection.js +37 -26
  185. package/dist/internal/hosted-admission-adapter.d.ts +28 -0
  186. package/dist/internal/hosted-admission-adapter.d.ts.map +1 -0
  187. package/dist/internal/hosted-admission-adapter.js +7 -0
  188. package/dist/internal/hosted-delivery-protocol.d.ts +13 -1
  189. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
  190. package/dist/internal/hosted-delivery-protocol.js +8 -1
  191. package/dist/internal/hosted-delivery.d.ts +21 -1
  192. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  193. package/dist/internal/hosted-delivery.js +101 -34
  194. package/dist/internal/hosted-execution-diag.d.ts +59 -0
  195. package/dist/internal/hosted-execution-diag.d.ts.map +1 -0
  196. package/dist/internal/hosted-execution-diag.js +187 -0
  197. package/dist/internal/http-channel.d.ts.map +1 -1
  198. package/dist/internal/http-channel.js +85 -2
  199. package/dist/internal/init-project.d.ts.map +1 -1
  200. package/dist/internal/init-project.js +2 -0
  201. package/dist/internal/logs-client.d.ts +5 -0
  202. package/dist/internal/logs-client.d.ts.map +1 -1
  203. package/dist/internal/logs-client.js +5 -0
  204. package/dist/internal/mcp-endpoint.js +2 -3
  205. package/dist/internal/mcp-host.d.ts +10 -0
  206. package/dist/internal/mcp-host.d.ts.map +1 -1
  207. package/dist/internal/mcp-host.js +57 -8
  208. package/dist/internal/mcp-oauth-on-demand.d.ts +68 -0
  209. package/dist/internal/mcp-oauth-on-demand.d.ts.map +1 -0
  210. package/dist/internal/mcp-oauth-on-demand.js +287 -0
  211. package/dist/internal/mcp-oauth-persist.d.ts +42 -0
  212. package/dist/internal/mcp-oauth-persist.d.ts.map +1 -0
  213. package/dist/internal/mcp-oauth-persist.js +92 -0
  214. package/dist/internal/mcp-oauth.d.ts +1 -0
  215. package/dist/internal/mcp-oauth.d.ts.map +1 -1
  216. package/dist/internal/mcp-oauth.js +10 -2
  217. package/dist/internal/null-kv-storage.d.ts +48 -0
  218. package/dist/internal/null-kv-storage.d.ts.map +1 -0
  219. package/dist/internal/null-kv-storage.js +58 -0
  220. package/dist/internal/otel/collector.d.ts.map +1 -1
  221. package/dist/internal/otel/collector.js +22 -9
  222. package/dist/internal/server.d.ts +6 -0
  223. package/dist/internal/server.d.ts.map +1 -1
  224. package/dist/internal/server.js +123 -33
  225. package/dist/internal/session-engine.d.ts +88 -3
  226. package/dist/internal/session-engine.d.ts.map +1 -1
  227. package/dist/internal/session-engine.js +538 -46
  228. package/dist/internal/session-run-log.d.ts +120 -0
  229. package/dist/internal/session-run-log.d.ts.map +1 -0
  230. package/dist/internal/session-run-log.js +359 -0
  231. package/dist/internal/sessions-client.d.ts +9 -7
  232. package/dist/internal/sessions-client.d.ts.map +1 -1
  233. package/dist/internal/sessions-client.js +3 -1
  234. package/dist/internal/storage-coordinator.d.ts +13 -0
  235. package/dist/internal/storage-coordinator.d.ts.map +1 -1
  236. package/dist/internal/storage-coordinator.js +37 -6
  237. package/dist/internal/storage-roles.d.ts +5 -0
  238. package/dist/internal/storage-roles.d.ts.map +1 -1
  239. package/dist/internal/stream-progress.d.ts.map +1 -1
  240. package/dist/internal/stream-progress.js +10 -0
  241. package/dist/internal/tool-policy.d.ts +29 -9
  242. package/dist/internal/tool-policy.d.ts.map +1 -1
  243. package/dist/internal/tool-policy.js +24 -0
  244. package/dist/internal/trajectory.d.ts.map +1 -1
  245. package/dist/internal/trajectory.js +10 -0
  246. package/dist/internal/turn-outbox.d.ts +24 -0
  247. package/dist/internal/turn-outbox.d.ts.map +1 -0
  248. package/dist/internal/turn-outbox.js +80 -0
  249. package/dist/playground/assets/index-D7rGZNjy.css +1 -0
  250. package/dist/playground/assets/index-jzNbJENa.js +69 -0
  251. package/dist/playground/index.html +2 -2
  252. package/dist/storage-backends/cursor-hosted.d.ts +1 -1
  253. package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
  254. package/dist/storage-backends/cursor-hosted.js +12 -0
  255. package/dist/storage-protocol.d.ts +8 -0
  256. package/dist/storage-protocol.d.ts.map +1 -1
  257. package/dist/storage-protocol.js +8 -0
  258. package/dist/storage.d.ts +8 -0
  259. package/dist/storage.d.ts.map +1 -1
  260. package/dist/tools.d.ts +12 -2
  261. package/dist/tools.d.ts.map +1 -1
  262. package/dist/types.d.ts +88 -7
  263. package/dist/types.d.ts.map +1 -1
  264. package/docs/README.md +5 -3
  265. package/docs/deployment.md +5 -4
  266. package/docs/design/runtime-abstraction.md +1757 -0
  267. package/docs/guides/mcp-oauth.md +26 -8
  268. package/docs/guides/slack.md +93 -202
  269. package/docs/reference/agent-config.md +2 -2
  270. package/docs/reference/cli.md +32 -16
  271. package/docs/reference/connections.md +6 -3
  272. package/docs/reference/http-api.md +3 -1
  273. package/docs/reference/sessions.md +4 -2
  274. package/docs/reference/tools.md +34 -2
  275. package/docs/templates/agents-md.md +110 -0
  276. package/docs/troubleshooting.md +2 -2
  277. package/package.json +1 -1
  278. package/skills/create-agent/SKILL.md +2 -1
  279. package/skills/mcp-auth/SKILL.md +6 -3
  280. package/skills/setup-slack/SKILL.md +23 -13
  281. package/src/bin/agent-serve.ts +12 -1
  282. package/src/channels/github/github-channel.ts +17 -0
  283. package/src/channels/origin/api.ts +24 -5
  284. package/src/channels/origin/binding.ts +55 -26
  285. package/src/channels/origin/index.ts +1 -0
  286. package/src/channels/origin/origin-channel.ts +78 -10
  287. package/src/channels/origin/reactions.ts +82 -0
  288. package/src/channels/origin/types.ts +11 -0
  289. package/src/channels/slack/approvals.ts +105 -0
  290. package/src/channels/slack/cli-project.ts +267 -0
  291. package/src/channels/slack/defaults.ts +165 -74
  292. package/src/channels/slack/dispatch.ts +2 -0
  293. package/src/channels/slack/init.ts +10 -5
  294. package/src/channels/slack/interactive.ts +35 -9
  295. package/src/channels/slack/live-delivery.ts +5 -3
  296. package/src/channels/slack/manifest.ts +1 -1
  297. package/src/channels/slack/progress-delivery.ts +133 -0
  298. package/src/channels/slack/setup.ts +10 -6
  299. package/src/channels/slack/slack-channel.ts +1 -0
  300. package/src/channels/slack/tool-approval-events.ts +93 -0
  301. package/src/channels/slack/types.ts +9 -1
  302. package/src/evals/run-facts.ts +32 -0
  303. package/src/files-backends/cursor-hosted.ts +3 -2
  304. package/src/index.ts +4 -0
  305. package/src/internal/advertise-tools.ts +31 -10
  306. package/src/internal/approval-gate.ts +20 -29
  307. package/src/internal/as-of.ts +107 -0
  308. package/src/internal/chat-client.ts +19 -0
  309. package/src/internal/cli-deploy.ts +203 -13
  310. package/src/internal/cli-mcp-oauth.ts +7 -21
  311. package/src/internal/cli-slack-manual.ts +350 -18
  312. package/src/internal/cli-slack.ts +40 -84
  313. package/src/internal/cursor/account-mcp.ts +21 -0
  314. package/src/internal/cursor-agent-template.ts +1 -0
  315. package/src/internal/cursor-event-relay.ts +5 -6
  316. package/src/internal/deploy-client.ts +43 -0
  317. package/src/internal/env-file.ts +84 -0
  318. package/src/internal/framework-file-storage.ts +18 -46
  319. package/src/internal/framework-storage-selection.ts +41 -25
  320. package/src/internal/hosted-admission-adapter.ts +42 -0
  321. package/src/internal/hosted-delivery-protocol.ts +14 -2
  322. package/src/internal/hosted-delivery.ts +169 -44
  323. package/src/internal/hosted-execution-diag.ts +252 -0
  324. package/src/internal/http-channel.ts +107 -0
  325. package/src/internal/init-project.ts +2 -0
  326. package/src/internal/logs-client.ts +5 -0
  327. package/src/internal/mcp-endpoint.ts +13 -4
  328. package/src/internal/mcp-host.ts +77 -11
  329. package/src/internal/mcp-oauth-on-demand.ts +352 -0
  330. package/src/internal/mcp-oauth-persist.ts +127 -0
  331. package/src/internal/mcp-oauth.ts +17 -1
  332. package/src/internal/null-kv-storage.ts +74 -0
  333. package/src/internal/otel/collector.ts +30 -0
  334. package/src/internal/server.ts +159 -11
  335. package/src/internal/session-engine.ts +691 -57
  336. package/src/internal/session-run-log.ts +584 -0
  337. package/src/internal/sessions-client.ts +17 -8
  338. package/src/internal/storage-coordinator.ts +49 -9
  339. package/src/internal/storage-roles.ts +7 -0
  340. package/src/internal/stream-progress.ts +19 -0
  341. package/src/internal/tool-policy.ts +49 -9
  342. package/src/internal/trajectory.ts +10 -0
  343. package/src/internal/turn-outbox.ts +85 -0
  344. package/src/storage-backends/cursor-hosted.ts +13 -1
  345. package/src/storage-protocol.ts +10 -0
  346. package/src/storage.ts +12 -0
  347. package/src/tools.ts +12 -2
  348. package/src/types.ts +93 -8
  349. package/templates/agents-md/README.md +39 -0
  350. package/templates/agents-md/agent/agent.ts +8 -0
  351. package/templates/agents-md/agent/channels/github.ts +10 -0
  352. package/templates/agents-md/agent/channels/queue.ts +28 -0
  353. package/templates/agents-md/agent/channels/slack.ts +9 -0
  354. package/templates/agents-md/agent/instructions.md +39 -0
  355. package/templates/agents-md/agent/lib/collect.ts +439 -0
  356. package/templates/agents-md/agent/lib/config.ts +8 -0
  357. package/templates/agents-md/agent/lib/paths.ts +51 -0
  358. package/templates/agents-md/agent/schedules/weekly.ts +17 -0
  359. package/templates/agents-md/agent/tools/apply_agents.ts +226 -0
  360. package/templates/agents-md/evals/agents.eval.ts +135 -0
  361. package/templates/agents-md/evals/evals.config.ts +5 -0
  362. package/templates/agents-md/init.json +38 -0
  363. package/templates/agents-md/package.json +18 -0
  364. package/templates/agents-md/tsconfig.json +12 -0
  365. package/dist/docs/assets/chunks/@localSearchIndexroot.DFoGuETX.js +0 -1
  366. package/dist/docs/assets/guides_slack.md.C32HsdKk.js +0 -38
  367. package/dist/docs/assets/guides_slack.md.C32HsdKk.lean.js +0 -1
  368. package/dist/docs/assets/index.md.CI93Ltlb.js +0 -5
  369. package/dist/docs/assets/reference_sessions.md.D0mIh4KK.js +0 -1
  370. package/dist/docs/assets/troubleshooting.md.Ctv3T8C2.js +0 -1
  371. package/dist/docs/design/agsh.md +0 -406
  372. package/dist/playground/assets/index-B1DDvBeC.css +0 -1
  373. package/dist/playground/assets/index-Cx9CclK_.js +0 -88
  374. package/docs/design/agsh.md +0 -406
  375. /package/dist/docs/assets/{deployment.md.D9msOFOW.lean.js → deployment.md.MFPKqsqI.lean.js} +0 -0
  376. /package/dist/docs/assets/{index.md.CI93Ltlb.lean.js → index.md.CVeRUOeZ.lean.js} +0 -0
  377. /package/dist/docs/assets/{reference_agent-config.md.Cp_x38Nl.lean.js → reference_agent-config.md.BHeYMgme.lean.js} +0 -0
  378. /package/dist/docs/assets/{reference_connections.md.BH8Oc0D0.lean.js → reference_connections.md.DxldvyIB.lean.js} +0 -0
  379. /package/dist/docs/assets/{reference_http-api.md.D89k1mdm.lean.js → reference_http-api.md.BEJx9XVj.lean.js} +0 -0
  380. /package/dist/docs/assets/{reference_sessions.md.D0mIh4KK.lean.js → reference_sessions.md.NxFP_CAC.lean.js} +0 -0
  381. /package/dist/docs/assets/{troubleshooting.md.Ctv3T8C2.lean.js → troubleshooting.md.DCiPBhYs.lean.js} +0 -0
@@ -2,7 +2,7 @@
2
2
  * Default inbound handlers and stream-event sinks for the Slack channel.
3
3
  */
4
4
 
5
- import type { ChannelEventHandlers } from "../../types.js";
5
+ import type { ChannelEventContext, ChannelEventHandlers } from "../../types.js";
6
6
  import {
7
7
  appendChatStream,
8
8
  postMessage,
@@ -18,6 +18,7 @@ import {
18
18
  } from "./constants.js";
19
19
  import { createStreamDeliveryStrategy } from "./live-delivery.js";
20
20
  import { defaultSlackLog, type SlackLog } from "./log.js";
21
+ import { createProgressDelivery } from "./progress-delivery.js";
21
22
  import { buildTaskChunkForResult, buildTaskChunksForCalls } from "./stream.js";
22
23
  import type {
23
24
  SlackAccessPolicy,
@@ -154,6 +155,10 @@ export function buildDefaultEvents(
154
155
  const botToken = credentials?.botToken;
155
156
  const getLog = options.getLog ?? (() => defaultSlackLog);
156
157
  const strategy = createStreamDeliveryStrategy({ botToken, getLog });
158
+ const progress = createProgressDelivery({ botToken, getLog });
159
+
160
+ const streamLive = (state: SlackChannelState): boolean =>
161
+ streaming && !state.streamingUnavailable;
157
162
 
158
163
  const clearWorkingStatus = async (
159
164
  channelId: string,
@@ -174,15 +179,126 @@ export function buildDefaultEvents(
174
179
  }
175
180
  };
176
181
 
182
+ const finishProgress = async (args: {
183
+ channel: ChannelEventContext<SlackChannelState>;
184
+ text: string;
185
+ sessionId: string;
186
+ }): Promise<boolean> => {
187
+ const log = getLog();
188
+ const state = args.channel.state;
189
+ if (
190
+ state.channelId === null ||
191
+ state.threadTs === null ||
192
+ args.text === ""
193
+ ) {
194
+ return false;
195
+ }
196
+ if (await progress.replace({ channel: args.channel, text: args.text })) {
197
+ log.info("reply delivered via progress update", {
198
+ channel: state.channelId,
199
+ thread_ts: state.threadTs,
200
+ session: args.sessionId,
201
+ chars: args.text.length,
202
+ });
203
+ return true;
204
+ }
205
+ await progress.clear({ channel: args.channel });
206
+ try {
207
+ const posted = await postMessage({
208
+ botToken,
209
+ channel: state.channelId,
210
+ text: args.text,
211
+ threadTs: state.threadTs,
212
+ });
213
+ state.lastPostedText = args.text;
214
+ state.lastBotMessageTs = posted.ts;
215
+ log.info("reply delivered via postMessage", {
216
+ channel: state.channelId,
217
+ thread_ts: state.threadTs,
218
+ message_ts: posted.ts,
219
+ session: args.sessionId,
220
+ chars: args.text.length,
221
+ });
222
+ return true;
223
+ } catch (error) {
224
+ log.error(
225
+ `postMessage failed: ${
226
+ error instanceof Error ? error.message : String(error)
227
+ }`,
228
+ {
229
+ channel: state.channelId,
230
+ thread_ts: state.threadTs,
231
+ session: args.sessionId,
232
+ }
233
+ );
234
+ return false;
235
+ }
236
+ };
237
+
238
+ /**
239
+ * Deliver assistant text to the bound Slack thread. Used by a stop-reason
240
+ * `message.completed` and by `turn.completed` when the last assistant
241
+ * block was `finishReason: "tool_call"` (answer then `tag_artifact`,
242
+ * etc.) so the playground result still reaches Slack.
243
+ */
244
+ const deliverReplyText = async (args: {
245
+ channel: ChannelEventContext<SlackChannelState>;
246
+ text: string;
247
+ sessionId: string;
248
+ }): Promise<boolean> => {
249
+ const state = args.channel.state;
250
+ if (
251
+ state.channelId === null ||
252
+ state.threadTs === null ||
253
+ args.text === ""
254
+ ) {
255
+ return false;
256
+ }
257
+ if (state.lastPostedText === args.text) {
258
+ // Stream append sets this watermark while chat.stopStream is still
259
+ // pending. Treat a match as "already on Slack", not "already finalized".
260
+ const streamTs = state.streamTs;
261
+ if (streamTs !== null && streamTs !== "") {
262
+ if (streamLive(state)) {
263
+ await strategy.finalize({
264
+ channel: args.channel,
265
+ channelId: state.streamChannelId ?? state.channelId,
266
+ text: args.text,
267
+ sessionId: args.sessionId,
268
+ });
269
+ } else {
270
+ await strategy.cleanupOrphan({ channel: args.channel });
271
+ }
272
+ }
273
+ return true;
274
+ }
275
+
276
+ if (streamLive(state)) {
277
+ const { delivered } = await strategy.finalize({
278
+ channel: args.channel,
279
+ channelId: state.streamChannelId ?? state.channelId,
280
+ text: args.text,
281
+ sessionId: args.sessionId,
282
+ });
283
+ if (delivered) {
284
+ return true;
285
+ }
286
+ }
287
+
288
+ return finishProgress(args);
289
+ };
290
+
177
291
  return {
178
292
  async "turn.started"(event, channel) {
179
293
  const log = getLog();
294
+ await progress.clear({ channel });
180
295
  channel.state.pendingToolCallMessage = null;
181
296
  channel.state.lastReasoningTypingAtMs = null;
182
297
  channel.state.lastReasoningTypingStatus = null;
183
298
  channel.state.streamTs = null;
184
299
  channel.state.streamChannelId = null;
185
300
  channel.state.lastPostedText = null;
301
+ channel.state.streamBlockText = null;
186
302
  // Keep lastBotMessageTs across turns — warm delta watermark.
187
303
  channel.state.approvalMessageByCallId = {};
188
304
 
@@ -208,7 +324,7 @@ export function buildDefaultEvents(
208
324
  },
209
325
 
210
326
  async "message.appended"(event, channel) {
211
- if (!streaming || channel.state.streamingUnavailable === true) {
327
+ if (!streamLive(channel.state)) {
212
328
  return;
213
329
  }
214
330
  const channelId =
@@ -277,8 +393,7 @@ export function buildDefaultEvents(
277
393
  if (
278
394
  strategy.inlineToolSteps &&
279
395
  thinkingSteps &&
280
- streaming &&
281
- channel.state.streamingUnavailable !== true
396
+ streamLive(channel.state)
282
397
  ) {
283
398
  const channelId =
284
399
  channel.state.streamChannelId ?? channel.state.channelId;
@@ -318,17 +433,24 @@ export function buildDefaultEvents(
318
433
  threadTs: channel.state.threadTs,
319
434
  status: statusText,
320
435
  });
436
+ if (
437
+ thinkingSteps &&
438
+ channel.state.streamingUnavailable === true &&
439
+ (channel.state.streamTs === null || channel.state.streamTs === "")
440
+ ) {
441
+ await progress.upsert({ channel, text: statusText });
442
+ }
321
443
  }
322
444
  },
323
445
 
324
446
  async "action.result"(event, channel) {
447
+ const streamTs = channel.state.streamTs;
325
448
  if (
326
449
  !strategy.inlineToolSteps ||
327
450
  !thinkingSteps ||
328
- !streaming ||
329
- channel.state.streamingUnavailable === true ||
330
- channel.state.streamTs === null ||
331
- channel.state.streamTs === ""
451
+ !streamLive(channel.state) ||
452
+ streamTs === null ||
453
+ streamTs === ""
332
454
  ) {
333
455
  return;
334
456
  }
@@ -345,16 +467,18 @@ export function buildDefaultEvents(
345
467
  await appendChatStream({
346
468
  botToken,
347
469
  channel: channelId,
348
- ts: channel.state.streamTs,
470
+ ts: streamTs,
349
471
  chunks: [chunk],
350
472
  });
351
473
  },
352
474
 
353
475
  async "message.completed"(event, channel) {
354
- const log = getLog();
355
476
  if (event.data.finishReason === "tool_call") {
356
477
  channel.state.pendingToolCallMessage =
357
478
  firstNonEmptyLine(event.data.text) ?? null;
479
+ // The harness restarts its cumulative text after a tool call, so the
480
+ // next block appends in full instead of diffing against this one.
481
+ channel.state.streamBlockText = null;
358
482
  return;
359
483
  }
360
484
  channel.state.pendingToolCallMessage = null;
@@ -368,54 +492,16 @@ export function buildDefaultEvents(
368
492
  // and clear typing.
369
493
  if (event.data.text === "") {
370
494
  await strategy.finalizeEmpty({ channel });
495
+ await progress.clear({ channel });
371
496
  await clearWorkingStatus(state.channelId, state.threadTs);
372
497
  return;
373
498
  }
374
499
 
375
- const canStream = streaming && state.streamingUnavailable !== true;
376
-
377
- if (canStream) {
378
- const { delivered } = await strategy.finalize({
379
- channel,
380
- channelId: state.streamChannelId ?? state.channelId,
381
- text: event.data.text,
382
- sessionId: event.sessionId,
383
- });
384
- if (delivered) {
385
- await clearWorkingStatus(state.channelId, state.threadTs);
386
- return;
387
- }
388
- }
389
-
390
- try {
391
- const posted = await postMessage({
392
- botToken,
393
- channel: state.channelId,
394
- text: event.data.text,
395
- threadTs: state.threadTs,
396
- });
397
- channel.state.lastPostedText = event.data.text;
398
- channel.state.lastBotMessageTs = posted.ts;
399
- log.info("reply delivered via postMessage", {
400
- channel: state.channelId,
401
- thread_ts: state.threadTs,
402
- message_ts: posted.ts,
403
- session: event.sessionId,
404
- chars: event.data.text.length,
405
- });
406
- } catch (error) {
407
- log.error(
408
- `postMessage failed: ${
409
- error instanceof Error ? error.message : String(error)
410
- }`,
411
- {
412
- channel: state.channelId,
413
- thread_ts: state.threadTs,
414
- session: event.sessionId,
415
- }
416
- );
417
- }
418
-
500
+ await deliverReplyText({
501
+ channel,
502
+ text: event.data.text,
503
+ sessionId: event.sessionId,
504
+ });
419
505
  await clearWorkingStatus(state.channelId, state.threadTs);
420
506
  },
421
507
 
@@ -428,7 +514,26 @@ export function buildDefaultEvents(
428
514
  thread_ts: channel.state.threadTs,
429
515
  });
430
516
 
517
+ // Mid-turn `tool_call` text is held as status, not posted. If the
518
+ // turn ends without a later `finishReason: "stop"` block, the
519
+ // playground still has `result` (last assistant text) and Slack
520
+ // would otherwise stay silent.
521
+ const result = event.data.result;
522
+ const unpublished =
523
+ typeof result === "string" &&
524
+ result !== "" &&
525
+ result !== channel.state.lastPostedText;
526
+ if (unpublished) {
527
+ await deliverReplyText({
528
+ channel,
529
+ text: result,
530
+ sessionId: event.sessionId,
531
+ });
532
+ }
533
+ // Always close leftovers. deliverReplyText may fall through to
534
+ // postMessage when streaming is unavailable and leave streamTs open.
431
535
  await strategy.cleanupOrphan({ channel });
536
+ await progress.clear({ channel });
432
537
 
433
538
  // Always drop the assistant chip. message.completed already clears
434
539
  // after a normal reply, but a tool-call-only finish (or a missed
@@ -476,7 +581,7 @@ export function buildDefaultEvents(
476
581
  const errorText = formatSlackTurnFailureMessage(event.data.message);
477
582
 
478
583
  let delivered = false;
479
- if (streaming && state.streamingUnavailable !== true) {
584
+ if (streamLive(state)) {
480
585
  ({ delivered } = await strategy.fail({
481
586
  channel,
482
587
  channelId: state.streamChannelId ?? state.channelId,
@@ -485,25 +590,11 @@ export function buildDefaultEvents(
485
590
  }));
486
591
  }
487
592
  if (!delivered) {
488
- try {
489
- await postMessage({
490
- botToken,
491
- channel: state.channelId,
492
- text: errorText,
493
- threadTs: state.threadTs,
494
- });
495
- } catch (error) {
496
- log.error(
497
- `turn.failed postMessage failed: ${
498
- error instanceof Error ? error.message : String(error)
499
- }`,
500
- {
501
- channel: state.channelId,
502
- thread_ts: state.threadTs,
503
- session: event.sessionId,
504
- }
505
- );
506
- }
593
+ await finishProgress({
594
+ channel,
595
+ text: errorText,
596
+ sessionId: event.sessionId,
597
+ });
507
598
  }
508
599
  await clearWorkingStatus(state.channelId, state.threadTs);
509
600
  },
@@ -126,8 +126,10 @@ export function emptySlackChannelState(
126
126
  streamTs: null,
127
127
  streamChannelId: null,
128
128
  lastPostedText: null,
129
+ streamBlockText: null,
129
130
  lastBotMessageTs: null,
130
131
  streamingUnavailable: false,
132
+ progressTs: null,
131
133
  approvalMessageByCallId: {},
132
134
  ...patch,
133
135
  };
@@ -2,13 +2,14 @@
2
2
  * Scaffold a Slack channel into an agent-serve project.
3
3
  *
4
4
  * `initSlackChannel` is the create-safe writer: `agent/channels/slack.ts`
5
- * only. DIY manifests for paste at api.slack.com live in
5
+ * only. DIY manifests + Slack CLI `.slack/` live in
6
6
  * {@link initSlackManual} so `slack create` cannot reach them.
7
7
  */
8
8
 
9
9
  import { mkdir, writeFile } from "node:fs/promises";
10
10
  import { basename, join, resolve } from "node:path";
11
11
  import { PACKAGE_NAME } from "../../internal/distribution.js";
12
+ import { writeSlackCliProject } from "./cli-project.js";
12
13
  import { envPrefixFromName, slackEnvKeys } from "./credentials.js";
13
14
  import {
14
15
  buildSlackManifestPair,
@@ -131,7 +132,8 @@ export async function initSlackChannel(
131
132
 
132
133
  /**
133
134
  * `slack init --manual`: channel file plus DIY manifests
134
- * (`managedByCursor: false`), env.example, and setup-status.json.
135
+ * (`managedByCursor: false`), Slack CLI `.slack/` project, env.example,
136
+ * and setup-status.json.
135
137
  */
136
138
  export async function initSlackManual(
137
139
  options: InitSlackManualOptions
@@ -151,9 +153,6 @@ export async function initSlackManual(
151
153
  description: options.description,
152
154
  channelPosts: options.channelPosts,
153
155
  });
154
- for (const file of slackManifestFileEntries(pair)) {
155
- await write(`.agent-serve/slack/${file.name}`, file.contents);
156
- }
157
156
  await write(
158
157
  ".agent-serve/slack/env.example",
159
158
  `# Copy to .env.local (or export in your shell). Use the *dev* Slack app
@@ -176,6 +175,12 @@ ${target.envKeys.app}=xapp-...
176
175
  2
177
176
  )}\n`
178
177
  );
178
+ files.push(
179
+ ...(await writeSlackCliProject(
180
+ target.rootDir,
181
+ slackManifestFileEntries(pair)
182
+ ))
183
+ );
179
184
 
180
185
  return {
181
186
  rootDir: target.rootDir,
@@ -15,10 +15,15 @@ import type {
15
15
  ChannelSession,
16
16
  HostContext,
17
17
  PendingApproval,
18
+ PendingAuth,
18
19
  SendMessageFn,
19
20
  } from "../../types.js";
20
21
  import { updateMessage } from "./api.js";
21
- import { decisionFromActionId, parseApprovalActionValue } from "./approvals.js";
22
+ import {
23
+ decisionFromActionId,
24
+ decisionFromAuthActionId,
25
+ parseApprovalActionValue,
26
+ } from "./approvals.js";
22
27
  import { buildSlackInteractiveApprovalAuth } from "./auth.js";
23
28
  import { dispatchInboundMessage } from "./dispatch.js";
24
29
  import { isExternalSlackSender } from "./external-policy.js";
@@ -41,6 +46,12 @@ export interface SlackInteractiveDispatchDeps {
41
46
  decision: ApprovalDecision,
42
47
  auth: AuthContext | null
43
48
  ) => Promise<PendingApproval>;
49
+ resolveAuth: (
50
+ sessionId: string,
51
+ callId: string,
52
+ decision: ApprovalDecision,
53
+ auth: AuthContext | null
54
+ ) => Promise<PendingAuth>;
44
55
  waitUntil: (promise: Promise<unknown>) => void;
45
56
  log?: SlackLog;
46
57
  /** Defaults to true. */
@@ -61,11 +72,17 @@ export async function dispatchInteractiveFromPayload(
61
72
  return false;
62
73
  }
63
74
 
64
- const decision = decisionFromActionId(parsed.actionId);
75
+ const approvalDecision = decisionFromActionId(parsed.actionId);
76
+ const authDecision = decisionFromAuthActionId(parsed.actionId);
65
77
  const value = parseApprovalActionValue(parsed.value);
66
- if (decision === null || value === null) {
78
+ if (value === null || (approvalDecision === null && authDecision === null)) {
67
79
  return false;
68
80
  }
81
+ const decision = approvalDecision ?? authDecision;
82
+ if (decision === null) {
83
+ return false;
84
+ }
85
+ const kind = approvalDecision !== null ? "approval" : "auth";
69
86
 
70
87
  log.info("interactive approval", {
71
88
  decision,
@@ -153,12 +170,21 @@ export async function dispatchInteractiveFromPayload(
153
170
  });
154
171
 
155
172
  try {
156
- await deps.resolveApproval(
157
- value.sessionId,
158
- value.callId,
159
- decision,
160
- clickingAuth
161
- );
173
+ if (kind === "auth") {
174
+ await deps.resolveAuth(
175
+ value.sessionId,
176
+ value.callId,
177
+ decision,
178
+ clickingAuth
179
+ );
180
+ } else {
181
+ await deps.resolveApproval(
182
+ value.sessionId,
183
+ value.callId,
184
+ decision,
185
+ clickingAuth
186
+ );
187
+ }
162
188
  } catch (error) {
163
189
  log.warn("interactive approval resolve failed", {
164
190
  session: value.sessionId,
@@ -41,7 +41,7 @@ type StreamArgs = {
41
41
  /**
42
42
  * How the default handlers deliver an in-progress reply. Methods write live
43
43
  * delivery state (`streamTs`, `streamChannelId`, `lastPostedText`,
44
- * `streamingUnavailable`) on `channel.state` directly.
44
+ * `streamBlockText`, `streamingUnavailable`) on `channel.state` directly.
45
45
  */
46
46
  export interface LiveDeliveryStrategy {
47
47
  readonly inlineToolSteps: boolean;
@@ -127,6 +127,7 @@ export function createStreamDeliveryStrategy(
127
127
  channel.state.streamTs = started.ts;
128
128
  channel.state.streamChannelId = started.channel;
129
129
  channel.state.lastPostedText = hasMarkdown ? (markdown_text ?? "") : "";
130
+ channel.state.streamBlockText = channel.state.lastPostedText;
130
131
  log.info("chat.startStream ok", {
131
132
  channel: started.channel,
132
133
  stream_ts: started.ts,
@@ -167,7 +168,7 @@ export function createStreamDeliveryStrategy(
167
168
  text: string;
168
169
  }): Promise<{ ok: boolean; error?: string }> => {
169
170
  const appendText = computeStreamAppend(
170
- args.channel.state.lastPostedText,
171
+ args.channel.state.streamBlockText,
171
172
  args.text
172
173
  );
173
174
  const stopped = await stopChatStream({
@@ -213,7 +214,7 @@ export function createStreamDeliveryStrategy(
213
214
  return;
214
215
  }
215
216
  const appendText = computeStreamAppend(
216
- channel.state.lastPostedText,
217
+ channel.state.streamBlockText,
217
218
  text
218
219
  );
219
220
  if (appendText === "") {
@@ -238,6 +239,7 @@ export function createStreamDeliveryStrategy(
238
239
  return;
239
240
  }
240
241
  channel.state.lastPostedText = text;
242
+ channel.state.streamBlockText = text;
241
243
  },
242
244
 
243
245
  async appendChunks({ channel, channelId, chunks, sessionId }) {
@@ -222,7 +222,7 @@ export function buildSlackManifestPair(
222
222
  };
223
223
  }
224
224
 
225
- /** Relative names under `.agent-serve/slack/`. */
225
+ /** Manifest filenames written under `.slack/`. */
226
226
  export function slackManifestFileEntries(
227
227
  pair: { dev: SlackAppManifest; prod: SlackAppManifest },
228
228
  env: "dev" | "prod" | "both" = "both"
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Mid-turn thread progress when `chat.startStream` is unavailable.
3
+ * One editable message; `setThreadStatus` stays on the caller.
4
+ */
5
+
6
+ import type { ChannelEventContext } from "../../types.js";
7
+ import { deleteMessage, postMessage, updateMessage } from "./api.js";
8
+ import type { SlackLog } from "./log.js";
9
+ import type { SlackBotToken, SlackChannelState } from "./types.js";
10
+
11
+ type SlackChannel = ChannelEventContext<SlackChannelState>;
12
+
13
+ export interface ProgressDeliveryDeps {
14
+ botToken: SlackBotToken | undefined;
15
+ getLog: () => SlackLog;
16
+ }
17
+
18
+ function activeProgressTs(state: SlackChannelState): string | null {
19
+ const ts = state.progressTs;
20
+ return ts == null || ts === "" ? null : ts;
21
+ }
22
+
23
+ export interface ProgressDelivery {
24
+ upsert(args: { channel: SlackChannel; text: string }): Promise<void>;
25
+ replace(args: { channel: SlackChannel; text: string }): Promise<boolean>;
26
+ clear(args: { channel: SlackChannel }): Promise<void>;
27
+ }
28
+
29
+ export function createProgressDelivery(
30
+ deps: ProgressDeliveryDeps
31
+ ): ProgressDelivery {
32
+ const { botToken, getLog } = deps;
33
+
34
+ const clear: ProgressDelivery["clear"] = async (args) => {
35
+ const state = args.channel.state;
36
+ const ts = activeProgressTs(state);
37
+ state.progressTs = null;
38
+ if (ts === null || state.channelId === null) {
39
+ return;
40
+ }
41
+ const deleted = await deleteMessage({
42
+ botToken,
43
+ channel: state.channelId,
44
+ ts,
45
+ });
46
+ if (!deleted.ok) {
47
+ getLog().warn("progress delete failed", {
48
+ error: deleted.error,
49
+ channel: state.channelId,
50
+ progress_ts: ts,
51
+ });
52
+ }
53
+ };
54
+
55
+ return {
56
+ async upsert(args) {
57
+ const state = args.channel.state;
58
+ if (
59
+ state.channelId === null ||
60
+ state.threadTs === null ||
61
+ args.text === ""
62
+ ) {
63
+ return;
64
+ }
65
+ const existing = activeProgressTs(state);
66
+ if (existing !== null) {
67
+ const updated = await updateMessage({
68
+ botToken,
69
+ channel: state.channelId,
70
+ ts: existing,
71
+ text: args.text,
72
+ });
73
+ if (updated.ok) {
74
+ return;
75
+ }
76
+ getLog().warn("progress update failed; posting a new message", {
77
+ error: updated.error,
78
+ channel: state.channelId,
79
+ thread_ts: state.threadTs,
80
+ progress_ts: existing,
81
+ });
82
+ await clear({ channel: args.channel });
83
+ }
84
+ try {
85
+ const posted = await postMessage({
86
+ botToken,
87
+ channel: state.channelId,
88
+ threadTs: state.threadTs,
89
+ text: args.text,
90
+ });
91
+ state.progressTs = posted.ts;
92
+ } catch (error) {
93
+ getLog().warn(
94
+ `progress post failed: ${
95
+ error instanceof Error ? error.message : String(error)
96
+ }`,
97
+ {
98
+ channel: state.channelId,
99
+ thread_ts: state.threadTs,
100
+ }
101
+ );
102
+ }
103
+ },
104
+
105
+ async replace(args) {
106
+ const state = args.channel.state;
107
+ const ts = activeProgressTs(state);
108
+ if (ts === null || state.channelId === null || args.text === "") {
109
+ return false;
110
+ }
111
+ const updated = await updateMessage({
112
+ botToken,
113
+ channel: state.channelId,
114
+ ts,
115
+ text: args.text,
116
+ });
117
+ if (!updated.ok) {
118
+ getLog().warn("progress replace failed", {
119
+ error: updated.error,
120
+ channel: state.channelId,
121
+ progress_ts: ts,
122
+ });
123
+ return false;
124
+ }
125
+ state.lastPostedText = args.text;
126
+ state.lastBotMessageTs = ts;
127
+ state.progressTs = null;
128
+ return true;
129
+ },
130
+
131
+ clear,
132
+ };
133
+ }