toolroll 0.5.0

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 (626) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1113 -0
  3. package/THIRD_PARTY_NOTICES.md +449 -0
  4. package/dist/accent-colors.d.ts +48 -0
  5. package/dist/accent-colors.js +122 -0
  6. package/dist/action-ledger.d.ts +26 -0
  7. package/dist/action-ledger.js +75 -0
  8. package/dist/agent-fence.d.ts +42 -0
  9. package/dist/agent-fence.js +183 -0
  10. package/dist/agentconfig.d.ts +216 -0
  11. package/dist/agentconfig.js +454 -0
  12. package/dist/api-tokens.d.ts +16 -0
  13. package/dist/api-tokens.js +27 -0
  14. package/dist/approval-policy.d.ts +69 -0
  15. package/dist/approval-policy.js +137 -0
  16. package/dist/approval-rules-ui.d.ts +25 -0
  17. package/dist/approval-rules-ui.js +39 -0
  18. package/dist/assignment-adapters.d.ts +180 -0
  19. package/dist/assignment-adapters.js +239 -0
  20. package/dist/assignment-brief.d.ts +71 -0
  21. package/dist/assignment-brief.js +129 -0
  22. package/dist/assignment-delivery.d.ts +56 -0
  23. package/dist/assignment-delivery.js +160 -0
  24. package/dist/assignment-presentation.d.ts +26 -0
  25. package/dist/assignment-presentation.js +80 -0
  26. package/dist/assignment-status.d.ts +62 -0
  27. package/dist/assignment-status.js +152 -0
  28. package/dist/assignment-ui.d.ts +71 -0
  29. package/dist/assignment-ui.js +103 -0
  30. package/dist/assignment.d.ts +222 -0
  31. package/dist/assignment.js +399 -0
  32. package/dist/attest.d.ts +56 -0
  33. package/dist/attest.js +153 -0
  34. package/dist/backend.d.ts +97 -0
  35. package/dist/backend.js +166 -0
  36. package/dist/backup-ui.d.ts +22 -0
  37. package/dist/backup-ui.js +59 -0
  38. package/dist/backup.d.ts +84 -0
  39. package/dist/backup.js +421 -0
  40. package/dist/beads.d.ts +34 -0
  41. package/dist/beads.js +135 -0
  42. package/dist/bin.d.ts +2 -0
  43. package/dist/bin.js +22 -0
  44. package/dist/board.d.ts +150 -0
  45. package/dist/board.js +210 -0
  46. package/dist/boot-identity.d.ts +63 -0
  47. package/dist/boot-identity.js +99 -0
  48. package/dist/browser/THIRD_PARTY_NOTICES.txt +2295 -0
  49. package/dist/browser/workspace.css +4 -0
  50. package/dist/browser/workspace.js +225 -0
  51. package/dist/browser-crew.d.ts +11 -0
  52. package/dist/browser-crew.js +50 -0
  53. package/dist/browser-shell.d.ts +8 -0
  54. package/dist/browser-shell.js +60 -0
  55. package/dist/browser-workspace.d.ts +780 -0
  56. package/dist/browser-workspace.js +47 -0
  57. package/dist/budget-alerts.d.ts +19 -0
  58. package/dist/budget-alerts.js +46 -0
  59. package/dist/builder.d.ts +370 -0
  60. package/dist/builder.js +3262 -0
  61. package/dist/capscan.d.ts +35 -0
  62. package/dist/capscan.js +113 -0
  63. package/dist/chat-acceptance.d.ts +71 -0
  64. package/dist/chat-acceptance.js +120 -0
  65. package/dist/chat-actions.d.ts +265 -0
  66. package/dist/chat-actions.js +1273 -0
  67. package/dist/chat-channel.d.ts +109 -0
  68. package/dist/chat-channel.js +652 -0
  69. package/dist/chat-continuity.d.ts +32 -0
  70. package/dist/chat-continuity.js +317 -0
  71. package/dist/chat-controls.d.ts +113 -0
  72. package/dist/chat-controls.js +53 -0
  73. package/dist/chat-delivery-state.d.ts +159 -0
  74. package/dist/chat-delivery-state.js +309 -0
  75. package/dist/chat-delivery.d.ts +38 -0
  76. package/dist/chat-delivery.js +693 -0
  77. package/dist/chat-display.d.ts +1 -0
  78. package/dist/chat-display.js +18 -0
  79. package/dist/chat-evidence.d.ts +123 -0
  80. package/dist/chat-evidence.js +207 -0
  81. package/dist/chat-flow.d.ts +44 -0
  82. package/dist/chat-flow.js +215 -0
  83. package/dist/chat-inbox.d.ts +57 -0
  84. package/dist/chat-inbox.js +123 -0
  85. package/dist/chat-polish.d.ts +16 -0
  86. package/dist/chat-polish.js +135 -0
  87. package/dist/chat-review.d.ts +46 -0
  88. package/dist/chat-review.js +98 -0
  89. package/dist/chat-rooms.d.ts +123 -0
  90. package/dist/chat-rooms.js +216 -0
  91. package/dist/chat-task-actions.d.ts +44 -0
  92. package/dist/chat-task-actions.js +79 -0
  93. package/dist/check-progress.d.ts +51 -0
  94. package/dist/check-progress.js +290 -0
  95. package/dist/child-database.d.ts +12 -0
  96. package/dist/child-database.js +30 -0
  97. package/dist/claim.d.ts +688 -0
  98. package/dist/claim.js +1740 -0
  99. package/dist/cli.d.ts +137 -0
  100. package/dist/cli.js +1461 -0
  101. package/dist/codex-limits.d.ts +15 -0
  102. package/dist/codex-limits.js +145 -0
  103. package/dist/coding-context.d.ts +55 -0
  104. package/dist/coding-context.js +92 -0
  105. package/dist/coding-handoff.d.ts +57 -0
  106. package/dist/coding-handoff.js +277 -0
  107. package/dist/coding-provider.d.ts +72 -0
  108. package/dist/coding-provider.js +424 -0
  109. package/dist/coding-shipping-ui.d.ts +4 -0
  110. package/dist/coding-shipping-ui.js +12 -0
  111. package/dist/coding-types.d.ts +62 -0
  112. package/dist/coding-types.js +1 -0
  113. package/dist/coding-ui.d.ts +17 -0
  114. package/dist/coding-ui.js +364 -0
  115. package/dist/coding-update.d.ts +15 -0
  116. package/dist/coding-update.js +149 -0
  117. package/dist/coding-workspace.d.ts +124 -0
  118. package/dist/coding-workspace.js +768 -0
  119. package/dist/container-state.d.ts +5 -0
  120. package/dist/container-state.js +62 -0
  121. package/dist/containment.d.ts +197 -0
  122. package/dist/containment.js +559 -0
  123. package/dist/contest.d.ts +318 -0
  124. package/dist/contest.js +753 -0
  125. package/dist/control-setup.d.ts +35 -0
  126. package/dist/control-setup.js +40 -0
  127. package/dist/control-ui.d.ts +29 -0
  128. package/dist/control-ui.js +53 -0
  129. package/dist/controller-service.d.ts +1 -0
  130. package/dist/controller-service.js +19 -0
  131. package/dist/controller-supervisor.d.ts +30 -0
  132. package/dist/controller-supervisor.js +104 -0
  133. package/dist/converse.d.ts +304 -0
  134. package/dist/converse.js +849 -0
  135. package/dist/coordinator-proposals.d.ts +29 -0
  136. package/dist/coordinator-proposals.js +137 -0
  137. package/dist/coordinator.d.ts +186 -0
  138. package/dist/coordinator.js +447 -0
  139. package/dist/credentials-ui.d.ts +25 -0
  140. package/dist/credentials-ui.js +48 -0
  141. package/dist/daemon.d.ts +209 -0
  142. package/dist/daemon.js +604 -0
  143. package/dist/decision.d.ts +120 -0
  144. package/dist/decision.js +388 -0
  145. package/dist/demo.d.ts +55 -0
  146. package/dist/demo.js +992 -0
  147. package/dist/desktop-access.d.ts +28 -0
  148. package/dist/desktop-access.js +88 -0
  149. package/dist/desktop-bundle.d.ts +16 -0
  150. package/dist/desktop-bundle.js +74 -0
  151. package/dist/desktop-host.d.ts +54 -0
  152. package/dist/desktop-host.js +508 -0
  153. package/dist/desktop-update-gate.d.ts +12 -0
  154. package/dist/desktop-update-gate.js +91 -0
  155. package/dist/desktop-update-recovery.d.ts +14 -0
  156. package/dist/desktop-update-recovery.js +243 -0
  157. package/dist/desktop-update.d.ts +110 -0
  158. package/dist/desktop-update.js +740 -0
  159. package/dist/discord-api.d.ts +20 -0
  160. package/dist/discord-api.js +138 -0
  161. package/dist/discord-chat.d.ts +16 -0
  162. package/dist/discord-chat.js +381 -0
  163. package/dist/discord-settings.d.ts +7 -0
  164. package/dist/discord-settings.js +75 -0
  165. package/dist/discord.d.ts +10 -0
  166. package/dist/discord.js +169 -0
  167. package/dist/discover.d.ts +75 -0
  168. package/dist/discover.js +150 -0
  169. package/dist/dispatch.d.ts +100 -0
  170. package/dist/dispatch.js +311 -0
  171. package/dist/dispose.d.ts +161 -0
  172. package/dist/dispose.js +803 -0
  173. package/dist/email-settings.d.ts +34 -0
  174. package/dist/email-settings.js +50 -0
  175. package/dist/envelope.d.ts +47 -0
  176. package/dist/envelope.js +105 -0
  177. package/dist/evidence-pack.d.ts +185 -0
  178. package/dist/evidence-pack.js +258 -0
  179. package/dist/evidence.d.ts +345 -0
  180. package/dist/evidence.js +782 -0
  181. package/dist/exec.d.ts +285 -0
  182. package/dist/exec.js +1841 -0
  183. package/dist/exhaustion.d.ts +85 -0
  184. package/dist/exhaustion.js +141 -0
  185. package/dist/export-ui.d.ts +4 -0
  186. package/dist/export-ui.js +17 -0
  187. package/dist/export.d.ts +48 -0
  188. package/dist/export.js +305 -0
  189. package/dist/flow-actions.d.ts +77 -0
  190. package/dist/flow-actions.js +203 -0
  191. package/dist/flow-code.d.ts +50 -0
  192. package/dist/flow-code.js +159 -0
  193. package/dist/flow-draft.d.ts +38 -0
  194. package/dist/flow-draft.js +80 -0
  195. package/dist/flow-engine.d.ts +66 -0
  196. package/dist/flow-engine.js +416 -0
  197. package/dist/flow-insights.d.ts +95 -0
  198. package/dist/flow-insights.js +149 -0
  199. package/dist/flow-live.d.ts +24 -0
  200. package/dist/flow-live.js +150 -0
  201. package/dist/flow-people.d.ts +24 -0
  202. package/dist/flow-people.js +91 -0
  203. package/dist/flow-replies.d.ts +48 -0
  204. package/dist/flow-replies.js +113 -0
  205. package/dist/flow-scripts.d.ts +38 -0
  206. package/dist/flow-scripts.js +73 -0
  207. package/dist/flow-secrets.d.ts +13 -0
  208. package/dist/flow-secrets.js +45 -0
  209. package/dist/flow-sort.d.ts +82 -0
  210. package/dist/flow-sort.js +153 -0
  211. package/dist/flow-steps.d.ts +40 -0
  212. package/dist/flow-steps.js +408 -0
  213. package/dist/flow-triggers.d.ts +244 -0
  214. package/dist/flow-triggers.js +959 -0
  215. package/dist/flows-ui.d.ts +20 -0
  216. package/dist/flows-ui.js +175 -0
  217. package/dist/flows.d.ts +229 -0
  218. package/dist/flows.js +968 -0
  219. package/dist/fonts.d.ts +19 -0
  220. package/dist/fonts.js +19 -0
  221. package/dist/gaps.d.ts +35 -0
  222. package/dist/gaps.js +101 -0
  223. package/dist/gate-failure.d.ts +40 -0
  224. package/dist/gate-failure.js +66 -0
  225. package/dist/git.d.ts +54 -0
  226. package/dist/git.js +94 -0
  227. package/dist/google-mail.d.ts +58 -0
  228. package/dist/google-mail.js +151 -0
  229. package/dist/grant.d.ts +136 -0
  230. package/dist/grant.js +238 -0
  231. package/dist/graph.d.ts +164 -0
  232. package/dist/graph.js +383 -0
  233. package/dist/guides.d.ts +22 -0
  234. package/dist/guides.js +363 -0
  235. package/dist/held.d.ts +150 -0
  236. package/dist/held.js +799 -0
  237. package/dist/invoke.d.ts +112 -0
  238. package/dist/invoke.js +780 -0
  239. package/dist/issues.d.ts +41 -0
  240. package/dist/issues.js +131 -0
  241. package/dist/job-object-helper.ps1 +252 -0
  242. package/dist/jsonl-discriminants.d.ts +11 -0
  243. package/dist/jsonl-discriminants.js +93 -0
  244. package/dist/keys.d.ts +104 -0
  245. package/dist/keys.js +229 -0
  246. package/dist/kits-ui.d.ts +17 -0
  247. package/dist/kits-ui.js +46 -0
  248. package/dist/kits.d.ts +86 -0
  249. package/dist/kits.js +215 -0
  250. package/dist/knowledge-cli.d.ts +101 -0
  251. package/dist/knowledge-cli.js +92 -0
  252. package/dist/knowledge-ui.d.ts +24 -0
  253. package/dist/knowledge-ui.js +40 -0
  254. package/dist/lead-context.d.ts +8 -0
  255. package/dist/lead-context.js +56 -0
  256. package/dist/lead-follow.d.ts +22 -0
  257. package/dist/lead-follow.js +167 -0
  258. package/dist/lead-status.d.ts +75 -0
  259. package/dist/lead-status.js +285 -0
  260. package/dist/ledger-chain.d.ts +46 -0
  261. package/dist/ledger-chain.js +187 -0
  262. package/dist/ledger-csv.d.ts +4 -0
  263. package/dist/ledger-csv.js +11 -0
  264. package/dist/ledger-view.d.ts +24 -0
  265. package/dist/ledger-view.js +58 -0
  266. package/dist/limits-ui.d.ts +26 -0
  267. package/dist/limits-ui.js +67 -0
  268. package/dist/link.d.ts +72 -0
  269. package/dist/link.js +217 -0
  270. package/dist/live.d.ts +96 -0
  271. package/dist/live.js +366 -0
  272. package/dist/liveness.d.ts +30 -0
  273. package/dist/liveness.js +42 -0
  274. package/dist/log.d.ts +7 -0
  275. package/dist/log.js +25 -0
  276. package/dist/mailbox.d.ts +57 -0
  277. package/dist/mailbox.js +150 -0
  278. package/dist/maintenance.d.ts +11 -0
  279. package/dist/maintenance.js +35 -0
  280. package/dist/mate-cli.d.ts +52 -0
  281. package/dist/mate-cli.js +345 -0
  282. package/dist/mate-contract.d.ts +10 -0
  283. package/dist/mate-contract.js +30 -0
  284. package/dist/mate-doors.d.ts +69 -0
  285. package/dist/mate-doors.js +548 -0
  286. package/dist/mate-progress.d.ts +29 -0
  287. package/dist/mate-progress.js +121 -0
  288. package/dist/mate-tools.d.ts +94 -0
  289. package/dist/mate-tools.js +1878 -0
  290. package/dist/mate.d.ts +92 -0
  291. package/dist/mate.js +435 -0
  292. package/dist/mcp-connect.d.ts +103 -0
  293. package/dist/mcp-connect.js +252 -0
  294. package/dist/mcp.d.ts +27 -0
  295. package/dist/mcp.js +651 -0
  296. package/dist/memory-cli.d.ts +466 -0
  297. package/dist/memory-cli.js +111 -0
  298. package/dist/memory-pass.d.ts +160 -0
  299. package/dist/memory-pass.js +409 -0
  300. package/dist/metrics.d.ts +3 -0
  301. package/dist/metrics.js +56 -0
  302. package/dist/mobile-viewport.d.ts +3 -0
  303. package/dist/mobile-viewport.js +37 -0
  304. package/dist/model-catalog.d.ts +118 -0
  305. package/dist/model-catalog.js +376 -0
  306. package/dist/models-cli.d.ts +102 -0
  307. package/dist/models-cli.js +66 -0
  308. package/dist/models-ui.d.ts +34 -0
  309. package/dist/models-ui.js +68 -0
  310. package/dist/modes.d.ts +80 -0
  311. package/dist/modes.js +182 -0
  312. package/dist/monitoring-settings.d.ts +44 -0
  313. package/dist/monitoring-settings.js +173 -0
  314. package/dist/monitoring-ui.d.ts +20 -0
  315. package/dist/monitoring-ui.js +51 -0
  316. package/dist/monitoring.d.ts +34 -0
  317. package/dist/monitoring.js +221 -0
  318. package/dist/names.d.ts +67 -0
  319. package/dist/names.js +102 -0
  320. package/dist/observations.d.ts +40 -0
  321. package/dist/observations.js +211 -0
  322. package/dist/oidc.d.ts +71 -0
  323. package/dist/oidc.js +182 -0
  324. package/dist/onboard.d.ts +108 -0
  325. package/dist/onboard.js +325 -0
  326. package/dist/openrouter-models.d.ts +30 -0
  327. package/dist/openrouter-models.js +120 -0
  328. package/dist/operate.d.ts +118 -0
  329. package/dist/operate.js +11321 -0
  330. package/dist/peek-cli.d.ts +97 -0
  331. package/dist/peek-cli.js +215 -0
  332. package/dist/peek.d.ts +134 -0
  333. package/dist/peek.js +578 -0
  334. package/dist/phase-routing.d.ts +307 -0
  335. package/dist/phase-routing.js +658 -0
  336. package/dist/plan-auto.d.ts +14 -0
  337. package/dist/plan-auto.js +92 -0
  338. package/dist/plan.d.ts +186 -0
  339. package/dist/plan.js +401 -0
  340. package/dist/planner-source.d.ts +251 -0
  341. package/dist/planner-source.js +460 -0
  342. package/dist/planner.d.ts +75 -0
  343. package/dist/planner.js +992 -0
  344. package/dist/policy-ui.d.ts +20 -0
  345. package/dist/policy-ui.js +41 -0
  346. package/dist/policy.d.ts +111 -0
  347. package/dist/policy.js +231 -0
  348. package/dist/prepared-evidence.d.ts +16 -0
  349. package/dist/prepared-evidence.js +96 -0
  350. package/dist/pricing.d.ts +45 -0
  351. package/dist/pricing.js +77 -0
  352. package/dist/principal.d.ts +42 -0
  353. package/dist/principal.js +82 -0
  354. package/dist/probe.d.ts +46 -0
  355. package/dist/probe.js +79 -0
  356. package/dist/process-custody.d.ts +17 -0
  357. package/dist/process-custody.js +91 -0
  358. package/dist/process-liveness.d.ts +10 -0
  359. package/dist/process-liveness.js +81 -0
  360. package/dist/process-recovery-anchor.d.ts +75 -0
  361. package/dist/process-recovery-anchor.js +188 -0
  362. package/dist/process-recovery-coalition.d.ts +25 -0
  363. package/dist/process-recovery-coalition.js +105 -0
  364. package/dist/process-recovery-eligibility.d.ts +178 -0
  365. package/dist/process-recovery-eligibility.js +170 -0
  366. package/dist/process-recovery-native.d.ts +172 -0
  367. package/dist/process-recovery-native.js +592 -0
  368. package/dist/process-recovery-provenance.d.ts +163 -0
  369. package/dist/process-recovery-provenance.js +292 -0
  370. package/dist/process-recovery-services.d.ts +56 -0
  371. package/dist/process-recovery-services.js +191 -0
  372. package/dist/process-recovery-settlement.d.ts +32 -0
  373. package/dist/process-recovery-settlement.js +132 -0
  374. package/dist/process-recovery.d.ts +41 -0
  375. package/dist/process-recovery.js +91 -0
  376. package/dist/process-tree.d.ts +41 -0
  377. package/dist/process-tree.js +264 -0
  378. package/dist/project-access.d.ts +14 -0
  379. package/dist/project-access.js +34 -0
  380. package/dist/project-cli.d.ts +18 -0
  381. package/dist/project-cli.js +104 -0
  382. package/dist/project-delete-ui.d.ts +22 -0
  383. package/dist/project-delete-ui.js +48 -0
  384. package/dist/project-delete.d.ts +55 -0
  385. package/dist/project-delete.js +413 -0
  386. package/dist/project-knowledge.d.ts +111 -0
  387. package/dist/project-knowledge.js +241 -0
  388. package/dist/project-learning.d.ts +100 -0
  389. package/dist/project-learning.js +438 -0
  390. package/dist/project-memory.d.ts +81 -0
  391. package/dist/project-memory.js +264 -0
  392. package/dist/project-skills.d.ts +152 -0
  393. package/dist/project-skills.js +660 -0
  394. package/dist/project-tools.d.ts +219 -0
  395. package/dist/project-tools.js +796 -0
  396. package/dist/project.d.ts +61 -0
  397. package/dist/project.js +125 -0
  398. package/dist/prompt.d.ts +22 -0
  399. package/dist/prompt.js +72 -0
  400. package/dist/proof.d.ts +513 -0
  401. package/dist/proof.js +1140 -0
  402. package/dist/proposal.d.ts +82 -0
  403. package/dist/proposal.js +210 -0
  404. package/dist/provider-connection.d.ts +22 -0
  405. package/dist/provider-connection.js +98 -0
  406. package/dist/provider-limits.d.ts +35 -0
  407. package/dist/provider-limits.js +95 -0
  408. package/dist/provider.d.ts +279 -0
  409. package/dist/provider.js +935 -0
  410. package/dist/publish.d.ts +107 -0
  411. package/dist/publish.js +650 -0
  412. package/dist/pulls.d.ts +118 -0
  413. package/dist/pulls.js +240 -0
  414. package/dist/push.d.ts +95 -0
  415. package/dist/push.js +353 -0
  416. package/dist/quality.d.ts +8 -0
  417. package/dist/quality.js +6 -0
  418. package/dist/recipe-ui.d.ts +18 -0
  419. package/dist/recipe-ui.js +152 -0
  420. package/dist/recipes.d.ts +81 -0
  421. package/dist/recipes.js +332 -0
  422. package/dist/remote.d.ts +67 -0
  423. package/dist/remote.js +122 -0
  424. package/dist/render.d.ts +64 -0
  425. package/dist/render.js +587 -0
  426. package/dist/report-summary.d.ts +13 -0
  427. package/dist/report-summary.js +15 -0
  428. package/dist/repos.d.ts +65 -0
  429. package/dist/repos.js +277 -0
  430. package/dist/repository-context-ui.d.ts +2 -0
  431. package/dist/repository-context-ui.js +10 -0
  432. package/dist/repository-context.d.ts +67 -0
  433. package/dist/repository-context.js +376 -0
  434. package/dist/restart-certification.d.ts +134 -0
  435. package/dist/restart-certification.js +226 -0
  436. package/dist/result-actions.d.ts +28 -0
  437. package/dist/result-actions.js +270 -0
  438. package/dist/result-completion.d.ts +18 -0
  439. package/dist/result-completion.js +66 -0
  440. package/dist/result-review.d.ts +213 -0
  441. package/dist/result-review.js +430 -0
  442. package/dist/retention-ui.d.ts +12 -0
  443. package/dist/retention-ui.js +39 -0
  444. package/dist/retention.d.ts +72 -0
  445. package/dist/retention.js +288 -0
  446. package/dist/review-context.d.ts +243 -0
  447. package/dist/review-context.js +1043 -0
  448. package/dist/review-evidence.d.ts +33 -0
  449. package/dist/review-evidence.js +56 -0
  450. package/dist/reviewer.d.ts +97 -0
  451. package/dist/reviewer.js +202 -0
  452. package/dist/routine.d.ts +228 -0
  453. package/dist/routine.js +764 -0
  454. package/dist/runner.d.ts +266 -0
  455. package/dist/runner.js +399 -0
  456. package/dist/scan.d.ts +32 -0
  457. package/dist/scan.js +92 -0
  458. package/dist/scope.d.ts +695 -0
  459. package/dist/scope.js +1176 -0
  460. package/dist/scout-report.d.ts +42 -0
  461. package/dist/scout-report.js +108 -0
  462. package/dist/scout.d.ts +69 -0
  463. package/dist/scout.js +351 -0
  464. package/dist/serve.d.ts +313 -0
  465. package/dist/serve.js +21776 -0
  466. package/dist/session-brief.d.ts +8 -0
  467. package/dist/session-brief.js +24 -0
  468. package/dist/session-cli.d.ts +13 -0
  469. package/dist/session-cli.js +284 -0
  470. package/dist/session-contract.d.ts +183 -0
  471. package/dist/session-contract.js +122 -0
  472. package/dist/session-http.d.ts +19 -0
  473. package/dist/session-http.js +154 -0
  474. package/dist/session-server.d.ts +12 -0
  475. package/dist/session-server.js +37 -0
  476. package/dist/session-service.d.ts +22 -0
  477. package/dist/session-service.js +157 -0
  478. package/dist/setup-guide.d.ts +39 -0
  479. package/dist/setup-guide.js +93 -0
  480. package/dist/sign-in-guard.d.ts +45 -0
  481. package/dist/sign-in-guard.js +74 -0
  482. package/dist/skills-ui.d.ts +11 -0
  483. package/dist/skills-ui.js +58 -0
  484. package/dist/skills.d.ts +97 -0
  485. package/dist/skills.js +276 -0
  486. package/dist/slack-api.d.ts +55 -0
  487. package/dist/slack-api.js +229 -0
  488. package/dist/slack-chat.d.ts +28 -0
  489. package/dist/slack-chat.js +413 -0
  490. package/dist/slack-settings.d.ts +7 -0
  491. package/dist/slack-settings.js +75 -0
  492. package/dist/slack-state.d.ts +13 -0
  493. package/dist/slack-state.js +9 -0
  494. package/dist/slack.d.ts +13 -0
  495. package/dist/slack.js +167 -0
  496. package/dist/spend-ui.d.ts +28 -0
  497. package/dist/spend-ui.js +95 -0
  498. package/dist/spend.d.ts +142 -0
  499. package/dist/spend.js +313 -0
  500. package/dist/sqlite-runtime.d.ts +3 -0
  501. package/dist/sqlite-runtime.js +6 -0
  502. package/dist/sso-settings.d.ts +33 -0
  503. package/dist/sso-settings.js +103 -0
  504. package/dist/sso-ui.d.ts +22 -0
  505. package/dist/sso-ui.js +39 -0
  506. package/dist/storage.d.ts +15 -0
  507. package/dist/storage.js +84 -0
  508. package/dist/store.d.ts +7754 -0
  509. package/dist/store.js +23279 -0
  510. package/dist/structured-output.d.ts +58 -0
  511. package/dist/structured-output.js +103 -0
  512. package/dist/style-asset.d.ts +7 -0
  513. package/dist/style-asset.js +41 -0
  514. package/dist/subscription-chat.d.ts +46 -0
  515. package/dist/subscription-chat.js +275 -0
  516. package/dist/summary.d.ts +33 -0
  517. package/dist/summary.js +71 -0
  518. package/dist/supervisor.mjs +297 -0
  519. package/dist/surface.d.ts +63 -0
  520. package/dist/surface.js +352 -0
  521. package/dist/sync.d.ts +94 -0
  522. package/dist/sync.js +279 -0
  523. package/dist/task-composer.d.ts +13 -0
  524. package/dist/task-composer.js +52 -0
  525. package/dist/task-control.d.ts +165 -0
  526. package/dist/task-control.js +214 -0
  527. package/dist/task-outcome-cli.d.ts +10 -0
  528. package/dist/task-outcome-cli.js +92 -0
  529. package/dist/task-text.d.ts +30 -0
  530. package/dist/task-text.js +41 -0
  531. package/dist/team-cli.d.ts +15 -0
  532. package/dist/team-cli.js +618 -0
  533. package/dist/team-contract.d.ts +92 -0
  534. package/dist/team-contract.js +1 -0
  535. package/dist/team-http.d.ts +17 -0
  536. package/dist/team-http.js +144 -0
  537. package/dist/team-leads.d.ts +81 -0
  538. package/dist/team-leads.js +565 -0
  539. package/dist/team-runtime.d.ts +27 -0
  540. package/dist/team-runtime.js +264 -0
  541. package/dist/team-ui.d.ts +3 -0
  542. package/dist/team-ui.js +9 -0
  543. package/dist/team-updates.d.ts +8 -0
  544. package/dist/team-updates.js +57 -0
  545. package/dist/teammate-admin.d.ts +53 -0
  546. package/dist/teammate-admin.js +111 -0
  547. package/dist/teammate-desk.d.ts +60 -0
  548. package/dist/teammate-desk.js +154 -0
  549. package/dist/teammate-memory.d.ts +64 -0
  550. package/dist/teammate-memory.js +196 -0
  551. package/dist/teammate-question.d.ts +59 -0
  552. package/dist/teammate-question.js +175 -0
  553. package/dist/teammate-tools.d.ts +108 -0
  554. package/dist/teammate-tools.js +271 -0
  555. package/dist/teammate-week.d.ts +68 -0
  556. package/dist/teammate-week.js +132 -0
  557. package/dist/teammate-work.d.ts +76 -0
  558. package/dist/teammate-work.js +280 -0
  559. package/dist/teammates-ui.d.ts +20 -0
  560. package/dist/teammates-ui.js +166 -0
  561. package/dist/teammates.d.ts +180 -0
  562. package/dist/teammates.js +253 -0
  563. package/dist/teams-api.d.ts +33 -0
  564. package/dist/teams-api.js +204 -0
  565. package/dist/teams-chat.d.ts +26 -0
  566. package/dist/teams-chat.js +215 -0
  567. package/dist/teams-settings.d.ts +12 -0
  568. package/dist/teams-settings.js +57 -0
  569. package/dist/teams.d.ts +21 -0
  570. package/dist/teams.js +124 -0
  571. package/dist/telegram-flow.d.ts +49 -0
  572. package/dist/telegram-flow.js +110 -0
  573. package/dist/telegram-mate.d.ts +137 -0
  574. package/dist/telegram-mate.js +707 -0
  575. package/dist/telegram-progress.d.ts +14 -0
  576. package/dist/telegram-progress.js +129 -0
  577. package/dist/telegram-settings.d.ts +9 -0
  578. package/dist/telegram-settings.js +36 -0
  579. package/dist/telegram-status.d.ts +75 -0
  580. package/dist/telegram-status.js +265 -0
  581. package/dist/telegram-team.d.ts +85 -0
  582. package/dist/telegram-team.js +359 -0
  583. package/dist/telegram.d.ts +230 -0
  584. package/dist/telegram.js +1931 -0
  585. package/dist/templates.d.ts +65 -0
  586. package/dist/templates.js +118 -0
  587. package/dist/tool-launcher.d.ts +1 -0
  588. package/dist/tool-launcher.js +101 -0
  589. package/dist/tools-ui.d.ts +30 -0
  590. package/dist/tools-ui.js +40 -0
  591. package/dist/transitions-recipes.d.ts +1 -0
  592. package/dist/transitions-recipes.js +203 -0
  593. package/dist/tree-proof.d.ts +34 -0
  594. package/dist/tree-proof.js +58 -0
  595. package/dist/verification-evidence.d.ts +44 -0
  596. package/dist/verification-evidence.js +238 -0
  597. package/dist/version.d.ts +2 -0
  598. package/dist/version.js +10 -0
  599. package/dist/webhooks.d.ts +91 -0
  600. package/dist/webhooks.js +283 -0
  601. package/dist/work-index.d.ts +68 -0
  602. package/dist/work-index.js +384 -0
  603. package/dist/work-summary.d.ts +57 -0
  604. package/dist/work-summary.js +116 -0
  605. package/dist/workspace-motion.d.ts +4 -0
  606. package/dist/workspace-motion.js +133 -0
  607. package/dist/workspace-revision.d.ts +19 -0
  608. package/dist/workspace-revision.js +92 -0
  609. package/dist/workspace-ui.d.ts +204 -0
  610. package/dist/workspace-ui.js +411 -0
  611. package/dist/worktree-notices.d.ts +13 -0
  612. package/dist/worktree-notices.js +17 -0
  613. package/dist/worktree.d.ts +249 -0
  614. package/dist/worktree.js +720 -0
  615. package/package.json +122 -0
  616. package/scripts/canary-assertions.mjs +42 -0
  617. package/scripts/crash-canary.mjs +253 -0
  618. package/scripts/fixtures/crash-process.mjs +74 -0
  619. package/scripts/fixtures/pilot-scenarios.mjs +85 -0
  620. package/scripts/fixtures/restart-service.mjs +27 -0
  621. package/scripts/launchd-certification.mjs +143 -0
  622. package/scripts/pilot.mjs +121 -0
  623. package/scripts/proof-preflight.mjs +140 -0
  624. package/scripts/provider-canary.mjs +379 -0
  625. package/scripts/recovery-canary.mjs +135 -0
  626. package/scripts/restart-certification.mjs +98 -0
@@ -0,0 +1,229 @@
1
+ import { ChatDeliveryError } from "./chat-delivery-state.js";
2
+ import { chmodSync, readFileSync, renameSync, rmSync, writeFileSync, } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { randomBytes } from "node:crypto";
5
+ import { slackHash } from "./slack-state.js";
6
+ export class SlackError extends ChatDeliveryError {
7
+ constructor(code, retryMs = 5_000, uncertain = false) {
8
+ super(code, retryMs, uncertain);
9
+ this.message =
10
+ {
11
+ invalid_auth: "Slack access expired. Disconnect and reconnect with the current tokens.",
12
+ not_authed: "Slack access expired. Reconnect the app.",
13
+ token_revoked: "Slack access was revoked. Reconnect the app.",
14
+ token_expired: "Slack access expired. Reconnect the app.",
15
+ account_inactive: "This Slack account is no longer active.",
16
+ missing_scope: "The Slack app needs additional permissions. Reinstall it with the supplied manifest.",
17
+ no_permission: "Slack refused access to this conversation. Check the app permissions.",
18
+ ratelimited: "Slack asked us to wait. Saved replies will retry.",
19
+ channel_not_found: "The Slack conversation is unavailable. Pair your account again.",
20
+ message_not_found: "The original Slack message was removed. Open the saved chat to recover it.",
21
+ already_complete: "Waiting to confirm the uploaded file’s receipt.",
22
+ }[code] ?? code;
23
+ }
24
+ }
25
+ const errors = new Set([
26
+ "invalid_auth",
27
+ "not_authed",
28
+ "token_revoked",
29
+ "token_expired",
30
+ "account_inactive",
31
+ "missing_scope",
32
+ "no_permission",
33
+ "channel_not_found",
34
+ "message_not_found",
35
+ "ratelimited",
36
+ "file_not_found",
37
+ "already_complete",
38
+ "not_in_channel",
39
+ ]);
40
+ export function slackApi(token, fetcher = fetch) {
41
+ return async (method, args = {}) => {
42
+ if (!/^[a-zA-Z]+(?:\.[a-zA-Z]+){1,2}$/.test(method))
43
+ throw new SlackError("Invalid Slack method");
44
+ let response;
45
+ try {
46
+ response = await fetcher(`https://slack.com/api/${method}`, {
47
+ method: "POST",
48
+ redirect: "error",
49
+ headers: {
50
+ Authorization: `Bearer ${token}`,
51
+ "Content-Type": "application/json; charset=utf-8",
52
+ },
53
+ body: JSON.stringify(args),
54
+ signal: AbortSignal.timeout(15_000),
55
+ });
56
+ }
57
+ catch {
58
+ throw new SlackError("Slack did not confirm delivery", 15_000, true);
59
+ }
60
+ if (response.status === 429) {
61
+ const seconds = Number(response.headers.get("retry-after"));
62
+ throw new SlackError("ratelimited", Number.isFinite(seconds) && seconds > 0
63
+ ? Math.ceil(seconds) * 1000
64
+ : 60_000);
65
+ }
66
+ if (!response.ok)
67
+ throw new SlackError("Slack is unavailable", 15_000, true);
68
+ let body;
69
+ try {
70
+ body = (await response.json());
71
+ }
72
+ catch {
73
+ throw new SlackError("Slack returned an incomplete receipt", 15_000, true);
74
+ }
75
+ if (body.ok !== true)
76
+ throw new SlackError(errors.has(String(body.error))
77
+ ? String(body.error)
78
+ : "Slack could not complete the request", 5_000, body.error === "internal_error" || body.error === "fatal_error");
79
+ return body;
80
+ };
81
+ }
82
+ export const slackCredentialFile = (dir) => join(dir, "slack-connection.json");
83
+ export function loadSlackCredentials(dir) {
84
+ try {
85
+ const value = JSON.parse(readFileSync(slackCredentialFile(dir), "utf8"));
86
+ return /^xapp-\S+$/.test(value.appToken) &&
87
+ /^xoxb-\S+$/.test(value.botToken) &&
88
+ [value.team, value.app, value.bot, value.installation].every((v) => typeof v === "string" && v.length > 0)
89
+ ? value
90
+ : null;
91
+ }
92
+ catch {
93
+ return null;
94
+ }
95
+ }
96
+ export function saveSlackCredentials(dir, value) {
97
+ const target = slackCredentialFile(dir), temp = `${target}.${randomBytes(8).toString("hex")}.tmp`;
98
+ try {
99
+ writeFileSync(temp, JSON.stringify(value) + "\n", {
100
+ mode: 0o600,
101
+ flag: "wx",
102
+ });
103
+ chmodSync(temp, 0o600);
104
+ renameSync(temp, target);
105
+ }
106
+ finally {
107
+ rmSync(temp, { force: true });
108
+ }
109
+ }
110
+ export function clearSlackCredentials(dir) {
111
+ rmSync(slackCredentialFile(dir), { force: true });
112
+ }
113
+ export async function checkSlackCredentials(appToken, botToken, fetcher = fetch) {
114
+ if (!/^xapp-\S{10,}$/.test(appToken) || !/^xoxb-\S{10,}$/.test(botToken))
115
+ throw new SlackError("Enter the app token and bot token from your Slack app");
116
+ const api = slackApi(botToken, fetcher), auth = await api("auth.test");
117
+ const bot = await api("bots.info", { bot: auth.bot_id });
118
+ const detail = object(bot.bot);
119
+ if (!slackId(auth.team_id, "T") ||
120
+ !slackId(auth.user_id, "UW") ||
121
+ !slackId(detail.app_id, "A"))
122
+ throw new SlackError("Slack did not return a workspace and bot identity");
123
+ await slackApi(appToken, fetcher)("apps.connections.open");
124
+ return {
125
+ appToken,
126
+ botToken,
127
+ team: String(auth.team_id),
128
+ app: String(detail.app_id),
129
+ bot: String(auth.user_id),
130
+ workspace: typeof auth.team === "string" ? auth.team : "Slack",
131
+ installation: slackHash(`${auth.team_id}:${detail.app_id}:${auth.user_id}`),
132
+ };
133
+ }
134
+ export function object(value) {
135
+ return value !== null && typeof value === "object" && !Array.isArray(value)
136
+ ? value
137
+ : {};
138
+ }
139
+ export function slackId(value, prefix) {
140
+ return (typeof value === "string" &&
141
+ new RegExp(`^[${prefix}][A-Z0-9]{2,80}$`).test(value));
142
+ }
143
+ export function slackTs(value) {
144
+ return typeof value === "string" && /^\d{10,16}\.\d{6}$/.test(value);
145
+ }
146
+ export async function slackMember(api, identity, member, channel) {
147
+ const user = object((await api("users.info", { user: member })).user);
148
+ if (user.id !== member ||
149
+ user.team_id !== identity.team ||
150
+ user.deleted === true ||
151
+ user.is_bot === true ||
152
+ user.is_app_user === true)
153
+ return false;
154
+ const conversation = object((await api("conversations.info", { channel })).channel);
155
+ return (conversation.id === channel &&
156
+ conversation.is_im === true &&
157
+ conversation.user === member &&
158
+ conversation.is_ext_shared !== true);
159
+ }
160
+ export async function uploadSlackBytes(url, bytes, fetcher = fetch) {
161
+ const target = new URL(url);
162
+ if (target.protocol !== "https:" ||
163
+ target.hostname !== "files.slack.com" ||
164
+ target.username ||
165
+ target.password ||
166
+ target.port)
167
+ throw new SlackError("Slack returned an invalid upload address");
168
+ try {
169
+ const response = await fetcher(url, {
170
+ method: "POST",
171
+ redirect: "error",
172
+ headers: { "Content-Type": "application/octet-stream" },
173
+ body: Buffer.from(bytes),
174
+ signal: AbortSignal.timeout(30_000),
175
+ });
176
+ if (!response.ok)
177
+ throw new Error();
178
+ }
179
+ catch {
180
+ throw new SlackError("Slack did not confirm the file upload", 15_000, true);
181
+ }
182
+ }
183
+ /** DM scopes plus channel history for rooms that follow a team conversation. */
184
+ export const SLACK_MANIFEST = {
185
+ display_information: {
186
+ name: "Toolroll",
187
+ description: "Manage your projects and review results in a private chat",
188
+ background_color: "#142b2b",
189
+ },
190
+ features: {
191
+ bot_user: { display_name: "Toolroll", always_online: false },
192
+ app_home: {
193
+ home_tab_enabled: false,
194
+ messages_tab_enabled: true,
195
+ messages_tab_read_only_enabled: false,
196
+ },
197
+ },
198
+ oauth_config: {
199
+ scopes: {
200
+ bot: [
201
+ "chat:write",
202
+ "im:history",
203
+ "im:read",
204
+ "channels:history",
205
+ "channels:read",
206
+ "groups:history",
207
+ "groups:read",
208
+ "users:read",
209
+ "files:read",
210
+ "files:write",
211
+ ],
212
+ },
213
+ },
214
+ settings: {
215
+ event_subscriptions: {
216
+ bot_events: [
217
+ "message.im",
218
+ "message.channels",
219
+ "message.groups",
220
+ "app_uninstalled",
221
+ "tokens_revoked",
222
+ "user_change",
223
+ ],
224
+ },
225
+ interactivity: { is_enabled: true },
226
+ socket_mode_enabled: true,
227
+ token_rotation_enabled: false,
228
+ },
229
+ };
@@ -0,0 +1,28 @@
1
+ import { type DoorOptions } from "./mate-doors.js";
2
+ import { SlackState, type SlackIdentity, type SlackBinding, type SlackEvent } from "./slack-state.js";
3
+ import { uploadSlackBytes, type SlackApi } from "./slack-api.js";
4
+ import { type Store } from "./store.js";
5
+ import type { SubscriptionMateRunner } from "./subscription-chat.js";
6
+ export type SlackChatOptions = {
7
+ store: Store;
8
+ identity: SlackIdentity;
9
+ api: SlackApi;
10
+ owner: string;
11
+ readProjects: () => Promise<readonly string[]>;
12
+ evidenceRoot: string;
13
+ current: () => boolean;
14
+ origin: () => string | null;
15
+ subscriptionRunner?: SubscriptionMateRunner;
16
+ held?: DoorOptions["held"];
17
+ canNotify?: () => boolean;
18
+ clock?: () => Date;
19
+ upload?: typeof uploadSlackBytes;
20
+ };
21
+ /** Synchronous receipt before ACK. Never stores response_url, raw tokens, or a pairing code. */
22
+ export declare function receiveSlack(state: SlackState, identity: SlackIdentity, type: string, raw: unknown, now: Date): boolean;
23
+ export declare const processSlackEvent: (options: SlackChatOptions) => Promise<boolean>;
24
+ export declare const applySlackAction: (options: SlackChatOptions, event: SlackEvent, binding: SlackBinding, repos: readonly string[]) => void;
25
+ export declare const planSlackNotifications: (options: SlackChatOptions) => Promise<void>;
26
+ export declare const planSlackRooms: (options: SlackChatOptions) => Promise<void>;
27
+ export declare function slackBlocks(text: string, buttons?: Record<string, unknown>[]): Record<string, unknown>[];
28
+ export declare function deliverSlackPart(options: SlackChatOptions): Promise<boolean>;
@@ -0,0 +1,413 @@
1
+ import { chatFlowButtons } from "./chat-flow.js";
2
+ import { chatQuestionButtons } from "./teammate-question.js";
3
+ import { channelInbox } from "./chat-inbox.js";
4
+ import { roomCommand } from "./chat-rooms.js";
5
+ import { processChatEvent, applyChatAction, planChatNotifications, channelAccess, planRoomMessages, } from "./chat-delivery.js";
6
+ /** Slack is a transport for the same saved assistant and confirmation doors. */
7
+ import { proposalPreview, proposalLink, proposalOutcomeText, armedCardText, armedYesLabel, } from "./chat-channel.js";
8
+ import { MATE_MESSAGE_MAX_CHARS } from "./mate.js";
9
+ import {} from "./mate-doors.js";
10
+ import { SlackState, slackHash, } from "./slack-state.js";
11
+ import { object, slackId, slackTs, slackMember, SlackError, uploadSlackBytes, } from "./slack-api.js";
12
+ import { resultImageFileName, safeResultImageCaption, verifyResultImage, } from "./chat-evidence.js";
13
+ import {} from "./store.js";
14
+ const nowOf = (options) => options.clock?.() ?? new Date();
15
+ const split = (text, size = 2800) => {
16
+ const parts = [];
17
+ for (let at = 0; at < text.length;) {
18
+ let end = Math.min(at + size, text.length);
19
+ if (end < text.length && /[\uD800-\uDBFF]/.test(text[end - 1]))
20
+ end--;
21
+ parts.push(text.slice(at, end));
22
+ at = end;
23
+ }
24
+ return parts.length ? parts : ["No reply was recorded."];
25
+ };
26
+ /** Synchronous receipt before ACK. Never stores response_url, raw tokens, or a pairing code. */
27
+ export function receiveSlack(state, identity, type, raw, now) {
28
+ const body = object(raw);
29
+ if (body.api_app_id !== identity.app)
30
+ return false;
31
+ const team = type === "events_api" ? body.team_id : object(body.team).id;
32
+ if (team !== identity.team || body.is_ext_shared_channel === true)
33
+ return false;
34
+ const event = type === "events_api" ? object(body.event) : body;
35
+ if (type === "events_api" &&
36
+ (event.type === "app_uninstalled" || event.type === "tokens_revoked")) {
37
+ state.revoke(identity.installation, now);
38
+ return true;
39
+ }
40
+ if (type === "events_api" && event.type === "user_change") {
41
+ const user = object(event.user), binding = typeof user.id === "string" ? state.bindingFor(identity.installation, user.id) : null;
42
+ if (binding !== null && user.deleted === true)
43
+ state.revokeBinding(binding, now);
44
+ return true;
45
+ }
46
+ let member, channel, ts, thread, id, payload, kind;
47
+ if (type === "events_api" && event.type === "message") {
48
+ if (event.subtype !== undefined ||
49
+ event.bot_id !== undefined ||
50
+ !["im", "channel", "group"].includes(String(event.channel_type)) ||
51
+ typeof event.text !== "string")
52
+ return false;
53
+ if (typeof body.event_id !== "string" || body.event_id.length > 120)
54
+ return false;
55
+ member = event.user;
56
+ channel = event.channel;
57
+ ts = event.ts;
58
+ thread = event.thread_ts ?? event.ts;
59
+ const match = /^pair ([a-f0-9]{32})$/.exec(event.text.trim());
60
+ kind = match ? "pair" : "message";
61
+ payload = match
62
+ ? { hash: slackHash(match[1]) }
63
+ : {
64
+ text: event.text.slice(0, MATE_MESSAGE_MAX_CHARS + 1),
65
+ originalLength: event.text.length,
66
+ };
67
+ id = slackHash(`${identity.installation}:event:${body.event_id}`);
68
+ }
69
+ else if (type === "interactive" && body.type === "block_actions") {
70
+ const actions = Array.isArray(body.actions) ? body.actions : [];
71
+ if (actions.length !== 1)
72
+ return false;
73
+ const action = object(actions[0]), container = object(body.container);
74
+ if (
75
+ // toolroll_* since the rename; standing_orders_* buttons on older messages still work.
76
+ !/^(?:toolroll|standing_orders)_(confirm|dismiss|yes|cancel|flow_approve|flow_edit|flow_send_back|question_choice|question_words)$/.test(String(action.action_id)) ||
77
+ typeof action.value !== "string" ||
78
+ !/^[a-f0-9]{32}$/.test(action.value) ||
79
+ !slackTs(action.action_ts) ||
80
+ container.type !== "message")
81
+ return false;
82
+ member = object(body.user).id;
83
+ channel = container.channel_id;
84
+ ts = container.message_ts;
85
+ thread = object(body.message).thread_ts ?? ts;
86
+ kind = "action";
87
+ payload = { token: action.value };
88
+ id = slackHash(`${identity.installation}:action:${member}:${ts}:${action.value}:${action.action_ts}`);
89
+ }
90
+ else
91
+ return false;
92
+ if (!slackId(member, "UW") ||
93
+ !slackId(channel, "DCG") ||
94
+ !slackTs(ts) ||
95
+ !slackTs(thread) ||
96
+ member === identity.bot)
97
+ return false;
98
+ // A channel or private group is a room: accepted only while it follows a
99
+ // conversation, or for the `/team` words that make it follow one.
100
+ const isRoom = !slackId(channel, "D");
101
+ // v89: a channel that feeds a flow takes anyone's message (as a card, with no say over anything); "flow 12" connects one.
102
+ const inbox = isRoom && kind === "message" ? channelInbox(state.store, "slack", identity.installation, String(channel), String(payload.text ?? "")) : { watched: false, command: false };
103
+ const roomish = isRoom && (state.room(identity.installation, String(channel)) !== null || (kind === "message" && roomCommand(String(payload.text ?? "")) !== null) || inbox.watched || inbox.command);
104
+ if (isRoom && !roomish)
105
+ return false;
106
+ const binding = state.bindingFor(identity.installation, member);
107
+ const open = inbox.watched && !inbox.command;
108
+ if (kind !== "pair" && !open &&
109
+ (!binding ||
110
+ !state.live(binding) ||
111
+ (binding.channel !== channel && !roomish)))
112
+ return false;
113
+ if (kind === "pair" && (binding || isRoom))
114
+ return false;
115
+ return state.enqueue({
116
+ id,
117
+ installation: identity.installation,
118
+ binding: kind === "pair" || binding === null ? null : binding.id,
119
+ kind,
120
+ channel,
121
+ member,
122
+ ts,
123
+ thread,
124
+ payload: JSON.stringify(payload),
125
+ created: now.toISOString(),
126
+ });
127
+ }
128
+ const delivery = (options) => ({
129
+ ...options,
130
+ state: new SlackState(options.store),
131
+ label: "Slack",
132
+ member: (member, channel) => slackMember(options.api, options.identity, member, channel),
133
+ });
134
+ export const processSlackEvent = (options) => processChatEvent(delivery(options));
135
+ export const applySlackAction = (options, event, binding, repos) => applyChatAction(delivery(options), event, binding, repos);
136
+ export const planSlackNotifications = (options) => planChatNotifications(delivery(options));
137
+ export const planSlackRooms = (options) => planRoomMessages(delivery(options));
138
+ const access = (options, binding, ceiling) => channelAccess(delivery(options), binding, ceiling);
139
+ export function slackBlocks(text, buttons = []) {
140
+ const lines = text.split("\n"), title = lines[0] ?? "Toolroll";
141
+ const blocks = [];
142
+ if (title.length <= 150 && lines.length > 1) {
143
+ blocks.push({
144
+ type: "header",
145
+ text: { type: "plain_text", text: title, emoji: true },
146
+ });
147
+ text = lines.slice(1).join("\n").trim();
148
+ }
149
+ for (const part of split(text))
150
+ blocks.push({
151
+ type: "section",
152
+ text: { type: "plain_text", text: part, emoji: true },
153
+ });
154
+ if (buttons.length)
155
+ blocks.push({ type: "actions", elements: buttons });
156
+ return blocks;
157
+ }
158
+ function linkButton(origin, link) {
159
+ if (!origin ||
160
+ !link ||
161
+ !link.path.startsWith("/") ||
162
+ link.path.startsWith("//"))
163
+ return [];
164
+ try {
165
+ const url = new URL(origin);
166
+ if (url.protocol !== "https:" ||
167
+ url.username ||
168
+ url.password ||
169
+ url.search ||
170
+ url.hash)
171
+ return [];
172
+ return [
173
+ {
174
+ type: "button",
175
+ text: { type: "plain_text", text: link.label },
176
+ url: `${url.origin}${link.path}`,
177
+ action_id: "toolroll_link",
178
+ },
179
+ ];
180
+ }
181
+ catch {
182
+ return [];
183
+ }
184
+ }
185
+ export async function deliverSlackPart(options) {
186
+ const state = new SlackState(options.store), { store, identity } = options, now = nowOf(options);
187
+ if (!state.owns(identity.installation, options.owner, now) ||
188
+ !options.current())
189
+ return false;
190
+ const row = state.db
191
+ .prepare("SELECT p.* FROM slack_part p JOIN slack_event e ON e.id=p.event WHERE e.installation=? AND p.state='pending' AND (e.kind!='notice' OR ?=1) AND (p.next_at IS NULL OR p.next_at<=?) ORDER BY p.id LIMIT 1")
192
+ .get(identity.installation, options.canNotify?.() === false ? 0 : 1, now.toISOString());
193
+ if (!row)
194
+ return false;
195
+ const event = state.event(row.event), binding = event.binding === null ? null : state.bindingById(event.binding);
196
+ if (!binding) {
197
+ state.db
198
+ .prepare("UPDATE slack_part SET state='dropped',problem='Chat access changed' WHERE id=?")
199
+ .run(row.id);
200
+ return true;
201
+ }
202
+ if (new Date(row.created).getTime() + 86_400_000 < now.getTime()) {
203
+ state.db
204
+ .prepare("UPDATE slack_part SET state='dropped',problem='Delivery expired; open the saved chat to recover it' WHERE id=?")
205
+ .run(row.id);
206
+ return true;
207
+ }
208
+ try {
209
+ const session = event.session === null ? null : store.getMateSession(event.session);
210
+ const repos = await access(options, binding, session?.ceilingDigest);
211
+ if (event.kind === "notice" && options.canNotify?.() === false)
212
+ return false;
213
+ const content = JSON.parse(row.payload);
214
+ const destination = content.channel ?? binding.channel;
215
+ let text = content.text, buttons = [];
216
+ if (content.task &&
217
+ !repos.includes(store.lookupRef(content.task)?.repo ?? ""))
218
+ throw new SlackError("Connected projects changed");
219
+ if (content.image) {
220
+ const verified = verifyResultImage(store, options.evidenceRoot, repos, content.image);
221
+ if (!verified.ok) {
222
+ text = `Screenshot not sent\n${verified.problem}. Open the saved result to review it.`;
223
+ }
224
+ else {
225
+ let file = row.file;
226
+ if (!row.uploaded) {
227
+ const allocated = await options.api("files.getUploadURLExternal", {
228
+ filename: resultImageFileName(content.image.taskId, content.image.run, content.image.artifact, verified.format),
229
+ length: verified.bytes.length,
230
+ });
231
+ if (!slackId(allocated.file_id, "F") ||
232
+ typeof allocated.upload_url !== "string")
233
+ throw new SlackError("Slack did not identify the upload");
234
+ file = allocated.file_id;
235
+ state.db
236
+ .prepare("UPDATE slack_part SET file=? WHERE id=?")
237
+ .run(file, row.id);
238
+ await access(options, binding, session?.ceilingDigest);
239
+ const fresh = verifyResultImage(store, options.evidenceRoot, repos, content.image);
240
+ if (!fresh.ok)
241
+ throw new SlackError("Screenshot evidence changed before upload");
242
+ await (options.upload ?? uploadSlackBytes)(allocated.upload_url, fresh.bytes);
243
+ state.db
244
+ .prepare("UPDATE slack_part SET uploaded=1 WHERE id=?")
245
+ .run(row.id);
246
+ }
247
+ await access(options, binding, session?.ceilingDigest);
248
+ if (!verifyResultImage(store, options.evidenceRoot, repos, content.image)
249
+ .ok)
250
+ throw new SlackError("Screenshot evidence changed before sharing");
251
+ // A lost completion response is reconciled against Slack's file receipt.
252
+ if (row.uncertain && file) {
253
+ const remote = object((await options.api("files.info", { file })).file), shares = object(object(remote.shares).private);
254
+ const receipts = Array.isArray(shares[destination])
255
+ ? shares[destination]
256
+ : [];
257
+ const found = receipts
258
+ .map(object)
259
+ .find((receipt) => receipt.thread_ts === event.thread && slackTs(receipt.ts));
260
+ if (found) {
261
+ state.db
262
+ .prepare("UPDATE slack_part SET state='sent',message=?,problem=NULL WHERE id=?")
263
+ .run(String(found.ts), row.id);
264
+ return true;
265
+ }
266
+ }
267
+ const completed = await options.api("files.completeUploadExternal", {
268
+ files: [
269
+ {
270
+ id: file,
271
+ title: safeResultImageCaption(content.text, content.image.taskId, content.image.run),
272
+ },
273
+ ],
274
+ channel_id: destination,
275
+ thread_ts: event.thread,
276
+ initial_comment: safeResultImageCaption(content.text, content.image.taskId, content.image.run),
277
+ });
278
+ if (!Array.isArray(completed.files) ||
279
+ !completed.files.some((value) => object(value).id === file))
280
+ throw new SlackError("Slack did not confirm the file identity", 15_000, true);
281
+ state.db
282
+ .prepare("UPDATE slack_part SET state='sent',problem=NULL WHERE id=?")
283
+ .run(row.id);
284
+ return true;
285
+ }
286
+ }
287
+ if (content.proposal) {
288
+ const proposal = store.getMateProposal(content.proposal);
289
+ if (!proposal)
290
+ text = "This proposal is unavailable.";
291
+ else if (proposal.state !== "pending")
292
+ text = proposalOutcomeText(proposal);
293
+ else {
294
+ const preview = proposalPreview(store, proposal, repos, "slack");
295
+ text =
296
+ content.phase === "armed"
297
+ ? armedCardText(proposal, preview.text)
298
+ : preview.text.replace("\n\nConfirm or Dismiss below. Nothing changes until you confirm.", "");
299
+ if (preview.buttons && preview.text.length <= 10_000) {
300
+ const tokens = state.db
301
+ .prepare("SELECT token,phase FROM slack_action WHERE part=? AND consumed IS NULL AND expires>? ORDER BY rowid")
302
+ .all(row.id, now.toISOString());
303
+ buttons = tokens.map((action) => ({
304
+ type: "button",
305
+ text: {
306
+ type: "plain_text",
307
+ text: action.phase === "yes"
308
+ ? armedYesLabel(proposal)
309
+ : action.phase === "cancel"
310
+ ? "Cancel"
311
+ : action.phase === "dismiss"
312
+ ? "Dismiss"
313
+ : "Confirm",
314
+ },
315
+ action_id: `toolroll_${action.phase}`,
316
+ value: String(action.token),
317
+ ...(action.phase === "confirm"
318
+ ? { style: "primary" }
319
+ : action.phase === "yes"
320
+ ? { style: "danger" }
321
+ : {}),
322
+ }));
323
+ if (!buttons.length)
324
+ text = "This confirmation expired. Ask for a fresh proposal.";
325
+ }
326
+ else {
327
+ const link = proposalLink(store, proposal, repos) ?? {
328
+ label: "Review action",
329
+ path: `/chat`,
330
+ };
331
+ buttons = linkButton(options.origin(), link);
332
+ if (!buttons.length)
333
+ text +=
334
+ "\n\nOpen Toolroll on your computer to review this action.";
335
+ if (text.length > 10_000)
336
+ text =
337
+ "Review the full action in Toolroll before confirming.";
338
+ }
339
+ }
340
+ }
341
+ else
342
+ buttons = [
343
+ // A flow decision (v88): Approve / Edit / Send back, then the link.
344
+ ...(content.flow
345
+ ? chatFlowButtons(state, row.id, now).map((one) => ({
346
+ type: "button",
347
+ text: { type: "plain_text", text: one.label },
348
+ action_id: `toolroll_flow_${one.action.replace("-", "_")}`,
349
+ value: one.token,
350
+ ...(one.action === "approve" ? { style: "primary" } : {}),
351
+ }))
352
+ : []),
353
+ // A teammate's question (v93): its options, then "Answer in words".
354
+ ...(content.question
355
+ ? chatQuestionButtons(state, row.id, now).map((one) => ({
356
+ type: "button",
357
+ text: { type: "plain_text", text: one.label },
358
+ action_id: one.words ? "toolroll_question_words" : "toolroll_question_choice",
359
+ value: one.token,
360
+ }))
361
+ : []),
362
+ ...linkButton(options.origin(), content.link),
363
+ ];
364
+ const target = content.edit ?? row.message;
365
+ const args = {
366
+ channel: destination,
367
+ text: text
368
+ .replaceAll("&", "&amp;")
369
+ .replaceAll("<", "&lt;")
370
+ .replaceAll(">", "&gt;"),
371
+ blocks: slackBlocks(text, buttons),
372
+ mrkdwn: false,
373
+ parse: "none",
374
+ unfurl_links: false,
375
+ unfurl_media: false,
376
+ };
377
+ const answer = target
378
+ ? await options.api("chat.update", { ...args, ts: target })
379
+ : await options.api("chat.postMessage", {
380
+ ...args,
381
+ thread_ts: event.kind === "notice" && event.thread === ""
382
+ ? undefined
383
+ : event.thread,
384
+ });
385
+ if (!slackTs(answer.ts) || (target && answer.ts !== target))
386
+ throw new SlackError("Slack did not confirm the message identity", 15_000, true);
387
+ state.db
388
+ .prepare("UPDATE slack_part SET state='sent',message=?,attempts=attempts+1,problem=NULL,next_at=NULL WHERE id=?")
389
+ .run(answer.ts, row.id);
390
+ state.db
391
+ .prepare("UPDATE slack_runtime SET problem=NULL WHERE installation=? AND owner=?")
392
+ .run(identity.installation, options.owner);
393
+ return true;
394
+ }
395
+ catch (error) {
396
+ const problem = error instanceof SlackError
397
+ ? error
398
+ : new SlackError("Slack delivery is waiting to retry", 15_000, true);
399
+ state.db
400
+ .prepare("UPDATE slack_runtime SET problem=? WHERE installation=? AND owner=?")
401
+ .run(problem.message, identity.installation, options.owner);
402
+ const until = new Date(nowOf(options).getTime() +
403
+ Math.max(problem.retryMs, [5000, 15000, 60000, 300000][Math.min(row.attempts, 3)])).toISOString();
404
+ state.db
405
+ .prepare("UPDATE slack_part SET attempts=attempts+1,uncertain=uncertain+?,next_at=?,problem=? WHERE id=?")
406
+ .run(problem.uncertain ? 1 : 0, until, problem.message, row.id);
407
+ if (problem.code === "ratelimited")
408
+ state.db
409
+ .prepare("UPDATE slack_runtime SET retry_at=? WHERE installation=?")
410
+ .run(until, identity.installation);
411
+ return true;
412
+ }
413
+ }
@@ -0,0 +1,7 @@
1
+ import type { Store } from "./store.js";
2
+ export declare function slackSettingsHtml(store: Store, dir: string, csrf: string, options?: {
3
+ code?: string;
4
+ problem?: string;
5
+ now?: Date;
6
+ who?: string;
7
+ }): string;