@phnx-labs/agents-cli 1.22.39 → 1.22.41

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 (569) hide show
  1. package/CHANGELOG.md +316 -0
  2. package/README.md +116 -70
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.js +45 -27
  5. package/dist/browser.js +2 -2
  6. package/dist/cli/command-registry.d.ts +135 -0
  7. package/dist/cli/command-registry.js +259 -0
  8. package/dist/commands/accounts.d.ts +20 -0
  9. package/dist/commands/accounts.js +186 -25
  10. package/dist/commands/apply.d.ts +3 -3
  11. package/dist/commands/apply.js +20 -63
  12. package/dist/commands/browser.d.ts +15 -0
  13. package/dist/commands/browser.js +318 -131
  14. package/dist/commands/budget.d.ts +7 -6
  15. package/dist/commands/budget.js +8 -7
  16. package/dist/commands/cloud.js +17 -20
  17. package/dist/commands/commands.js +1 -1
  18. package/dist/commands/computer-actions.d.ts +1 -35
  19. package/dist/commands/computer-actions.js +13 -181
  20. package/dist/commands/computer.d.ts +28 -3
  21. package/dist/commands/computer.js +93 -65
  22. package/dist/commands/config.js +16 -3
  23. package/dist/commands/cost.d.ts +2 -1
  24. package/dist/commands/cost.js +7 -6
  25. package/dist/commands/daemon.js +151 -4
  26. package/dist/commands/detach.js +1 -1
  27. package/dist/commands/doctor.js +19 -11
  28. package/dist/commands/events.js +1 -1
  29. package/dist/commands/exec.d.ts +2 -50
  30. package/dist/commands/exec.js +160 -215
  31. package/dist/commands/factory.js +1 -1
  32. package/dist/commands/feed.d.ts +2 -2
  33. package/dist/commands/feed.js +12 -23
  34. package/dist/commands/fleet-capture.js +25 -27
  35. package/dist/commands/focus.d.ts +2 -3
  36. package/dist/commands/focus.js +34 -9
  37. package/dist/commands/go.js +15 -5
  38. package/dist/commands/harness.d.ts +3 -3
  39. package/dist/commands/harness.js +53 -5
  40. package/dist/commands/hooks.js +1 -1
  41. package/dist/commands/import.js +2 -2
  42. package/dist/commands/insights.d.ts +5 -5
  43. package/dist/commands/insights.js +15 -9
  44. package/dist/commands/inspect.d.ts +2 -3
  45. package/dist/commands/inspect.js +4 -16
  46. package/dist/commands/logs.d.ts +2 -2
  47. package/dist/commands/logs.js +9 -9
  48. package/dist/commands/mcp.js +2 -2
  49. package/dist/commands/memory.js +1 -1
  50. package/dist/commands/message.d.ts +1 -1
  51. package/dist/commands/message.js +7 -7
  52. package/dist/commands/mine.d.ts +11 -8
  53. package/dist/commands/mine.js +11 -10
  54. package/dist/commands/models.js +1 -1
  55. package/dist/commands/modes.js +1 -1
  56. package/dist/commands/monitors.js +23 -6
  57. package/dist/commands/output.d.ts +7 -6
  58. package/dist/commands/output.js +11 -10
  59. package/dist/commands/packages.js +4 -4
  60. package/dist/commands/perf.js +1 -1
  61. package/dist/commands/permissions.js +49 -32
  62. package/dist/commands/plugins.d.ts +1 -1
  63. package/dist/commands/plugins.js +3 -3
  64. package/dist/commands/profiles.d.ts +6 -9
  65. package/dist/commands/profiles.js +8 -321
  66. package/dist/commands/projects.d.ts +9 -0
  67. package/dist/commands/projects.js +140 -8
  68. package/dist/commands/prune.js +5 -13
  69. package/dist/commands/refresh-rules.js +1 -1
  70. package/dist/commands/repo.d.ts +5 -7
  71. package/dist/commands/repo.js +34 -18
  72. package/dist/commands/resource-view.js +4 -0
  73. package/dist/commands/resume.d.ts +11 -7
  74. package/dist/commands/resume.js +82 -98
  75. package/dist/commands/route.d.ts +12 -0
  76. package/dist/commands/route.js +261 -0
  77. package/dist/commands/routines.d.ts +2 -3
  78. package/dist/commands/routines.js +120 -145
  79. package/dist/commands/rules.js +1 -1
  80. package/dist/commands/run-account-picker.d.ts +1 -1
  81. package/dist/commands/run-account-picker.js +2 -2
  82. package/dist/commands/run-broadcast.d.ts +21 -0
  83. package/dist/commands/run-broadcast.js +89 -0
  84. package/dist/commands/run-cloud.js +1 -1
  85. package/dist/commands/secrets-vault.d.ts +10 -0
  86. package/dist/commands/{login.js → secrets-vault.js} +34 -14
  87. package/dist/commands/secrets.d.ts +4 -4
  88. package/dist/commands/secrets.js +158 -159
  89. package/dist/commands/sessions-backfill.js +1 -1
  90. package/dist/commands/sessions-browser.d.ts +1 -1
  91. package/dist/commands/sessions-browser.js +9 -5
  92. package/dist/commands/sessions-export.js +2 -2
  93. package/dist/commands/sessions-inject.js +4 -5
  94. package/dist/commands/sessions-migrate.js +16 -27
  95. package/dist/commands/sessions-picker.d.ts +14 -0
  96. package/dist/commands/sessions-picker.js +209 -13
  97. package/dist/commands/sessions-resume.d.ts +7 -3
  98. package/dist/commands/sessions-resume.js +81 -33
  99. package/dist/commands/sessions-share.d.ts +25 -0
  100. package/dist/commands/sessions-share.js +166 -0
  101. package/dist/commands/sessions-stats.js +2 -2
  102. package/dist/commands/sessions.d.ts +75 -68
  103. package/dist/commands/sessions.js +144 -180
  104. package/dist/commands/setup-browser.js +1 -1
  105. package/dist/commands/setup-computer.js +1 -1
  106. package/dist/commands/setup-fleet.js +3 -0
  107. package/dist/commands/setup-mine.d.ts +7 -3
  108. package/dist/commands/setup-mine.js +13 -8
  109. package/dist/commands/setup-preferences.js +2 -2
  110. package/dist/commands/setup-secrets.js +2 -2
  111. package/dist/commands/setup-watchdog.js +2 -2
  112. package/dist/commands/setup.js +7 -2
  113. package/dist/commands/share.d.ts +65 -0
  114. package/dist/commands/share.js +253 -20
  115. package/dist/commands/skills.js +3 -3
  116. package/dist/commands/snapshot.d.ts +2 -2
  117. package/dist/commands/snapshot.js +9 -9
  118. package/dist/commands/ssh.d.ts +1 -1
  119. package/dist/commands/ssh.js +186 -64
  120. package/dist/commands/subagents.js +1 -1
  121. package/dist/commands/sync.js +24 -9
  122. package/dist/commands/teams.d.ts +2 -2
  123. package/dist/commands/teams.js +9 -18
  124. package/dist/commands/tmux.js +5 -1
  125. package/dist/commands/trash.js +1 -1
  126. package/dist/commands/usage.d.ts +1 -1
  127. package/dist/commands/usage.js +2 -2
  128. package/dist/commands/utils.d.ts +4 -14
  129. package/dist/commands/utils.js +6 -27
  130. package/dist/commands/versions.js +2 -2
  131. package/dist/commands/view.d.ts +9 -77
  132. package/dist/commands/view.js +23 -8
  133. package/dist/commands/watchdog.js +1 -1
  134. package/dist/commands/webhook.js +25 -34
  135. package/dist/commands/workflows.js +1 -1
  136. package/dist/index.js +1 -1
  137. package/dist/lib/account-capabilities.d.ts +39 -0
  138. package/dist/lib/account-capabilities.js +59 -0
  139. package/dist/lib/account-catalog.js +1 -1
  140. package/dist/lib/account-registry.d.ts +66 -0
  141. package/dist/lib/account-registry.js +151 -5
  142. package/dist/lib/{rotate.d.ts → accounting/rotate.d.ts} +4 -4
  143. package/dist/lib/{rotate.js → accounting/rotate.js} +8 -8
  144. package/dist/lib/{usage.d.ts → accounting/usage.d.ts} +4 -4
  145. package/dist/lib/{usage.js → accounting/usage.js} +11 -11
  146. package/dist/lib/agent-spec/provider.js +1 -1
  147. package/dist/lib/agents.d.ts +72 -4
  148. package/dist/lib/agents.js +231 -199
  149. package/dist/lib/answer-router.d.ts +2 -2
  150. package/dist/lib/ask-classifier.d.ts +1 -1
  151. package/dist/lib/ask-classifier.js +1 -1
  152. package/dist/lib/audit/log.js +1 -1
  153. package/dist/lib/auth-health.d.ts +1 -1
  154. package/dist/lib/auth-health.js +2 -2
  155. package/dist/lib/brand.js +1 -1
  156. package/dist/lib/browser/caller-identity.d.ts +28 -0
  157. package/dist/lib/browser/caller-identity.js +156 -0
  158. package/dist/lib/browser/cdp.js +5 -1
  159. package/dist/lib/browser/chrome.js +12 -1
  160. package/dist/lib/browser/drivers/ssh.d.ts +1 -1
  161. package/dist/lib/browser/drivers/ssh.js +3 -2
  162. package/dist/lib/browser/hygiene.d.ts +10 -2
  163. package/dist/lib/browser/hygiene.js +7 -4
  164. package/dist/lib/browser/ipc.d.ts +22 -2
  165. package/dist/lib/browser/ipc.js +185 -21
  166. package/dist/lib/browser/profiles.d.ts +69 -5
  167. package/dist/lib/browser/profiles.js +135 -13
  168. package/dist/lib/browser/remote-control.d.ts +2 -2
  169. package/dist/lib/browser/remote-control.js +3 -3
  170. package/dist/lib/browser/runtime-state.d.ts +79 -0
  171. package/dist/lib/browser/runtime-state.js +119 -1
  172. package/dist/lib/browser/service.d.ts +137 -2
  173. package/dist/lib/browser/service.js +492 -54
  174. package/dist/lib/browser/sessions-list.d.ts +2 -1
  175. package/dist/lib/browser/sessions-list.js +4 -13
  176. package/dist/lib/browser/types.d.ts +19 -1
  177. package/dist/lib/budget/config.js +1 -1
  178. package/dist/lib/budget/ledger.js +1 -1
  179. package/dist/lib/byok-usage.js +1 -1
  180. package/dist/lib/capabilities.js +3 -15
  181. package/dist/lib/catchup.d.ts +1 -1
  182. package/dist/lib/catchup.js +1 -1
  183. package/dist/lib/cloud/dispatch.js +1 -1
  184. package/dist/lib/cloud/host.d.ts +3 -3
  185. package/dist/lib/cloud/host.js +5 -5
  186. package/dist/lib/cloud/rush.d.ts +9 -21
  187. package/dist/lib/cloud/rush.js +33 -120
  188. package/dist/lib/cloud/types.d.ts +2 -2
  189. package/dist/lib/commands.js +3 -13
  190. package/dist/lib/computer/actions.d.ts +36 -0
  191. package/dist/lib/computer/actions.js +162 -0
  192. package/dist/lib/computer/dispatch.d.ts +2 -2
  193. package/dist/lib/computer/dispatch.js +2 -2
  194. package/dist/lib/computer/sessions-list.d.ts +3 -3
  195. package/dist/lib/computer/sessions-list.js +2 -2
  196. package/dist/lib/config-keys.d.ts +2 -1
  197. package/dist/lib/config-keys.js +8 -4
  198. package/dist/lib/config-machine-keys.d.ts +4 -2
  199. package/dist/lib/config-machine-keys.js +5 -2
  200. package/dist/lib/crabbox/lease.js +9 -1
  201. package/dist/lib/crabbox/runtimes.d.ts +32 -7
  202. package/dist/lib/crabbox/runtimes.js +72 -30
  203. package/dist/lib/{daemon.d.ts → daemon/daemon.d.ts} +59 -1
  204. package/dist/lib/{daemon.js → daemon/daemon.js} +237 -49
  205. package/dist/lib/daemon-services.d.ts +1 -1
  206. package/dist/lib/daemon-services.js +5 -0
  207. package/dist/lib/daemon-ticks.d.ts +25 -0
  208. package/dist/lib/daemon-ticks.js +31 -1
  209. package/dist/lib/daemon-webhooks.d.ts +104 -0
  210. package/dist/lib/daemon-webhooks.js +215 -0
  211. package/dist/lib/device-config.d.ts +85 -75
  212. package/dist/lib/device-config.js +280 -142
  213. package/dist/lib/devices/config-migration.d.ts +29 -34
  214. package/dist/lib/devices/config-migration.js +209 -130
  215. package/dist/lib/devices/connect.d.ts +2 -2
  216. package/dist/lib/devices/connect.js +2 -2
  217. package/dist/lib/devices/discovery-policy.d.ts +30 -0
  218. package/dist/lib/devices/discovery-policy.js +101 -0
  219. package/dist/lib/devices/fleet-inventory.js +8 -3
  220. package/dist/lib/devices/harness-inventory.d.ts +1 -1
  221. package/dist/lib/devices/harness-inventory.js +12 -3
  222. package/dist/lib/devices/known-hosts.js +1 -1
  223. package/dist/lib/devices/pool.d.ts +10 -5
  224. package/dist/lib/devices/pool.js +5 -7
  225. package/dist/lib/devices/registry.d.ts +1 -1
  226. package/dist/lib/devices/registry.js +1 -1
  227. package/dist/lib/devices/resolve-profile.d.ts +2 -2
  228. package/dist/lib/devices/resolve-profile.js +2 -2
  229. package/dist/lib/devices/resolve-target.d.ts +1 -1
  230. package/dist/lib/devices/resolve-target.js +4 -4
  231. package/dist/lib/devices/self-host.d.ts +1 -1
  232. package/dist/lib/devices/self-host.js +3 -3
  233. package/dist/lib/devices/ssh-config.d.ts +1 -1
  234. package/dist/lib/devices/stats-cache.js +1 -1
  235. package/dist/lib/devices/sync.d.ts +3 -1
  236. package/dist/lib/devices/sync.js +3 -3
  237. package/dist/lib/doctor-diff.js +4 -4
  238. package/dist/lib/drift-sync.js +2 -2
  239. package/dist/lib/drift.js +2 -2
  240. package/dist/lib/event-families.d.ts +1 -1
  241. package/dist/lib/event-stream.d.ts +1 -1
  242. package/dist/lib/event-stream.js +2 -2
  243. package/dist/lib/events-ingest.js +2 -2
  244. package/dist/lib/exec.d.ts +4 -4
  245. package/dist/lib/exec.js +11 -11
  246. package/dist/lib/factory/snapshot.d.ts +1 -1
  247. package/dist/lib/factory/snapshot.js +1 -1
  248. package/dist/lib/{activity.d.ts → feed/activity.d.ts} +1 -1
  249. package/dist/lib/{activity.js → feed/activity.js} +7 -7
  250. package/dist/lib/{events.d.ts → feed/events.d.ts} +2 -2
  251. package/dist/lib/{events.js → feed/events.js} +5 -5
  252. package/dist/lib/{feed.js → feed/feed.js} +4 -4
  253. package/dist/lib/feed-outcome.d.ts +1 -1
  254. package/dist/lib/feed-policy.d.ts +1 -1
  255. package/dist/lib/feed-policy.js +1 -1
  256. package/dist/lib/feed-post.d.ts +1 -1
  257. package/dist/lib/feed-post.js +1 -1
  258. package/dist/lib/feed-ranking.d.ts +1 -1
  259. package/dist/lib/fleet/apply.d.ts +0 -6
  260. package/dist/lib/fleet/apply.js +18 -45
  261. package/dist/lib/fleet/auth-sync.d.ts +16 -35
  262. package/dist/lib/fleet/auth-sync.js +16 -75
  263. package/dist/lib/fleet/capture.js +8 -6
  264. package/dist/lib/fleet/manifest.js +23 -11
  265. package/dist/lib/fleet/types.d.ts +19 -7
  266. package/dist/lib/fleet-cache.d.ts +1 -1
  267. package/dist/lib/fleet-cache.js +1 -1
  268. package/dist/lib/format.d.ts +19 -0
  269. package/dist/lib/format.js +44 -1
  270. package/dist/lib/friction-heuristics.d.ts +1 -1
  271. package/dist/lib/git.d.ts +24 -1
  272. package/dist/lib/git.js +82 -38
  273. package/dist/lib/heal.js +3 -3
  274. package/dist/lib/hooks.d.ts +18 -0
  275. package/dist/lib/hooks.js +113 -1
  276. package/dist/lib/hosts/credentials.d.ts +30 -10
  277. package/dist/lib/hosts/credentials.js +38 -26
  278. package/dist/lib/hosts/dispatch.d.ts +3 -3
  279. package/dist/lib/hosts/dispatch.js +3 -3
  280. package/dist/lib/hosts/option.d.ts +3 -3
  281. package/dist/lib/hosts/option.js +7 -8
  282. package/dist/lib/hosts/passthrough.d.ts +17 -17
  283. package/dist/lib/hosts/passthrough.js +67 -50
  284. package/dist/lib/hosts/providers/devices.d.ts +1 -1
  285. package/dist/lib/hosts/providers/devices.js +1 -1
  286. package/dist/lib/hosts/reconcile.d.ts +1 -1
  287. package/dist/lib/hosts/reconcile.js +1 -1
  288. package/dist/lib/hosts/reconnect.d.ts +1 -1
  289. package/dist/lib/hosts/reconnect.js +2 -2
  290. package/dist/lib/hosts/registry.d.ts +5 -5
  291. package/dist/lib/hosts/registry.js +5 -5
  292. package/dist/lib/hosts/remote-cmd.d.ts +10 -10
  293. package/dist/lib/hosts/remote-cmd.js +25 -18
  294. package/dist/lib/hosts/remote-os.d.ts +4 -4
  295. package/dist/lib/hosts/remote-os.js +4 -4
  296. package/dist/lib/hosts/remote-session-id.d.ts +2 -2
  297. package/dist/lib/hosts/remote-session-id.js +2 -2
  298. package/dist/lib/hosts/routing-flag.d.ts +3 -3
  299. package/dist/lib/hosts/routing-flag.js +4 -5
  300. package/dist/lib/hosts/run-target.d.ts +4 -4
  301. package/dist/lib/hosts/run-target.js +4 -4
  302. package/dist/lib/hosts/session-index.d.ts +2 -2
  303. package/dist/lib/hosts/session-index.js +1 -1
  304. package/dist/lib/hosts/session-marker.d.ts +1 -1
  305. package/dist/lib/hosts/session-marker.js +1 -1
  306. package/dist/lib/hosts/types.d.ts +2 -2
  307. package/dist/lib/hosts/types.js +2 -2
  308. package/dist/lib/import.js +1 -1
  309. package/dist/lib/{migrate.d.ts → installations/migrate.d.ts} +13 -1
  310. package/dist/lib/{migrate.js → installations/migrate.js} +160 -40
  311. package/dist/lib/installations/resolve.js +1 -1
  312. package/dist/lib/installations/strategies.js +1 -1
  313. package/dist/lib/installations/update.js +2 -2
  314. package/dist/lib/{versions.d.ts → installations/versions.d.ts} +12 -3
  315. package/dist/lib/{versions.js → installations/versions.js} +51 -31
  316. package/dist/lib/isolation-boundary-report.js +1 -1
  317. package/dist/lib/linear-projects.d.ts +28 -0
  318. package/dist/lib/linear-projects.js +30 -0
  319. package/dist/lib/loop.js +1 -1
  320. package/dist/lib/mailbox-gc.js +1 -1
  321. package/dist/lib/mailbox.js +1 -1
  322. package/dist/lib/mcp-registry.d.ts +62 -0
  323. package/dist/lib/mcp-registry.js +177 -0
  324. package/dist/lib/mcp.d.ts +5 -0
  325. package/dist/lib/mcp.js +124 -307
  326. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  327. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  328. package/dist/lib/menubar/install-menubar.d.ts +7 -0
  329. package/dist/lib/menubar/install-menubar.js +24 -6
  330. package/dist/lib/menubar/snapshot.d.ts +7 -0
  331. package/dist/lib/menubar/snapshot.js +8 -6
  332. package/dist/lib/models.js +1 -1
  333. package/dist/lib/monitors/config.d.ts +12 -0
  334. package/dist/lib/monitors/config.js +3 -0
  335. package/dist/lib/monitors/dispatch.js +26 -5
  336. package/dist/lib/monitors/engine.js +10 -0
  337. package/dist/lib/monitors/sources/webhook.d.ts +1 -1
  338. package/dist/lib/monitors/state.d.ts +42 -0
  339. package/dist/lib/monitors/state.js +30 -0
  340. package/dist/lib/notify.d.ts +1 -1
  341. package/dist/lib/observe-aliases.d.ts +3 -3
  342. package/dist/lib/observe-aliases.js +3 -21
  343. package/dist/lib/output/git-output.js +2 -2
  344. package/dist/lib/overdue.d.ts +1 -1
  345. package/dist/lib/overdue.js +1 -1
  346. package/dist/lib/permissions-registry.d.ts +65 -0
  347. package/dist/lib/permissions-registry.js +599 -0
  348. package/dist/lib/permissions.d.ts +24 -13
  349. package/dist/lib/permissions.js +52 -271
  350. package/dist/lib/picker.d.ts +16 -0
  351. package/dist/lib/picker.js +33 -3
  352. package/dist/lib/placement.d.ts +1 -1
  353. package/dist/lib/placement.js +4 -4
  354. package/dist/lib/platform/paths.d.ts +8 -0
  355. package/dist/lib/platform/paths.js +11 -0
  356. package/dist/lib/platform/posixpath.js +3 -3
  357. package/dist/lib/{plugin-marketplace.d.ts → plugins/plugin-marketplace.d.ts} +1 -1
  358. package/dist/lib/{plugin-marketplace.js → plugins/plugin-marketplace.js} +2 -2
  359. package/dist/lib/{plugins.d.ts → plugins/plugins.d.ts} +1 -1
  360. package/dist/lib/{plugins.js → plugins/plugins.js} +7 -7
  361. package/dist/lib/{skills.d.ts → plugins/skills.d.ts} +1 -1
  362. package/dist/lib/{skills.js → plugins/skills.js} +7 -7
  363. package/dist/lib/pricing/cost.d.ts +1 -1
  364. package/dist/lib/pricing/cost.js +1 -1
  365. package/dist/lib/profiles-presets.d.ts +1 -1
  366. package/dist/lib/profiles-presets.js +1 -1
  367. package/dist/lib/profiles.js +2 -2
  368. package/dist/lib/project-import.js +4 -1
  369. package/dist/lib/project-key.js +7 -0
  370. package/dist/lib/project-launch.d.ts +1 -1
  371. package/dist/lib/project-launch.js +3 -3
  372. package/dist/lib/project-pull.d.ts +128 -0
  373. package/dist/lib/project-pull.js +384 -0
  374. package/dist/lib/project-root.d.ts +2 -2
  375. package/dist/lib/project-root.js +2 -2
  376. package/dist/lib/project-status.js +1 -1
  377. package/dist/lib/projects.d.ts +23 -0
  378. package/dist/lib/projects.js +29 -6
  379. package/dist/lib/refresh.d.ts +12 -1
  380. package/dist/lib/refresh.js +16 -9
  381. package/dist/lib/registry.d.ts +9 -2
  382. package/dist/lib/registry.js +11 -4
  383. package/dist/lib/resources.d.ts +2 -2
  384. package/dist/lib/resources.js +2 -2
  385. package/dist/lib/routers.d.ts +81 -0
  386. package/dist/lib/routers.js +153 -0
  387. package/dist/lib/routine-context.d.ts +1 -0
  388. package/dist/lib/routine-context.js +7 -2
  389. package/dist/lib/routine-notify-owner.d.ts +1 -1
  390. package/dist/lib/routine-notify.d.ts +1 -1
  391. package/dist/lib/routine-notify.js +1 -1
  392. package/dist/lib/routine-process-cleanup.d.ts +1 -1
  393. package/dist/lib/routine-readiness.d.ts +1 -1
  394. package/dist/lib/routine-readiness.js +11 -4
  395. package/dist/lib/routines-placement.d.ts +12 -2
  396. package/dist/lib/routines-placement.js +20 -3
  397. package/dist/lib/routines-project.d.ts +1 -1
  398. package/dist/lib/routines-project.js +1 -1
  399. package/dist/lib/rules/compile.d.ts +1 -0
  400. package/dist/lib/rules/compile.js +10 -2
  401. package/dist/lib/rules/rules.js +1 -1
  402. package/dist/lib/run-notify.js +1 -1
  403. package/dist/lib/runner.d.ts +80 -2
  404. package/dist/lib/runner.js +261 -67
  405. package/dist/lib/sandbox.d.ts +1 -1
  406. package/dist/lib/scheduler.d.ts +1 -1
  407. package/dist/lib/scheduler.js +1 -1
  408. package/dist/lib/{routines.d.ts → scheduling/routines.d.ts} +54 -9
  409. package/dist/lib/{routines.js → scheduling/routines.js} +173 -14
  410. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  411. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  412. package/dist/lib/secrets/agent.js +2 -2
  413. package/dist/lib/secrets/audit.js +1 -1
  414. package/dist/lib/secrets/bundles.d.ts +4 -4
  415. package/dist/lib/secrets/bundles.js +8 -8
  416. package/dist/lib/secrets/headless.d.ts +16 -0
  417. package/dist/lib/secrets/headless.js +21 -0
  418. package/dist/lib/secrets/index.js +1 -1
  419. package/dist/lib/secrets/list-filter.d.ts +1 -1
  420. package/dist/lib/secrets/list-filter.js +2 -2
  421. package/dist/lib/secrets/push.d.ts +1 -1
  422. package/dist/lib/secrets/push.js +10 -12
  423. package/dist/lib/secrets/remote.d.ts +21 -17
  424. package/dist/lib/secrets/remote.js +39 -23
  425. package/dist/lib/secrets/vault.js +2 -2
  426. package/dist/lib/self-heal/checks/shadowing.js +1 -1
  427. package/dist/lib/self-heal/checks/shims.js +1 -1
  428. package/dist/lib/self-update.d.ts +39 -4
  429. package/dist/lib/self-update.js +78 -25
  430. package/dist/lib/serve/control.d.ts +1 -1
  431. package/dist/lib/serve/control.js +4 -4
  432. package/dist/lib/serve/data.d.ts +1 -1
  433. package/dist/lib/serve/data.js +1 -1
  434. package/dist/lib/serve/stream.js +1 -1
  435. package/dist/lib/service-manifest.d.ts +29 -0
  436. package/dist/lib/service-manifest.js +80 -0
  437. package/dist/lib/session/active.d.ts +59 -7
  438. package/dist/lib/session/active.js +158 -17
  439. package/dist/lib/session/bash-command.js +1 -1
  440. package/dist/lib/session/claude-accounts.d.ts +1 -1
  441. package/dist/lib/session/claude-accounts.js +1 -1
  442. package/dist/lib/session/db.d.ts +10 -2
  443. package/dist/lib/session/db.js +25 -6
  444. package/dist/lib/session/discover.d.ts +77 -0
  445. package/dist/lib/session/discover.js +130 -25
  446. package/dist/lib/session/fork.js +1 -1
  447. package/dist/lib/session/inject.d.ts +1 -1
  448. package/dist/lib/session/insights.d.ts +1 -1
  449. package/dist/lib/session/insights.js +1 -1
  450. package/dist/lib/session/live-metadata.d.ts +15 -0
  451. package/dist/lib/session/live-metadata.js +76 -0
  452. package/dist/lib/session/migrate-targets.d.ts +1 -1
  453. package/dist/lib/session/recovery.d.ts +1 -1
  454. package/dist/lib/session/recovery.js +2 -2
  455. package/dist/lib/session/remote-active.d.ts +10 -1
  456. package/dist/lib/session/remote-active.js +8 -3
  457. package/dist/lib/session/remote-bundle.d.ts +1 -1
  458. package/dist/lib/session/remote-bundle.js +2 -2
  459. package/dist/lib/session/remote-list.d.ts +15 -4
  460. package/dist/lib/session/remote-list.js +40 -3
  461. package/dist/lib/session/remote.d.ts +5 -5
  462. package/dist/lib/session/remote.js +13 -17
  463. package/dist/lib/session/resume-command.d.ts +3 -2
  464. package/dist/lib/session/resume-command.js +4 -3
  465. package/dist/lib/session/resume-owner.d.ts +3 -3
  466. package/dist/lib/session/resume-owner.js +3 -3
  467. package/dist/lib/session/session-cache.d.ts +12 -0
  468. package/dist/lib/session/session-cache.js +2 -0
  469. package/dist/lib/session/share-html.d.ts +55 -0
  470. package/dist/lib/session/share-html.js +319 -0
  471. package/dist/lib/session/shell-programs.js +1 -1
  472. package/dist/lib/session/state.js +5 -5
  473. package/dist/lib/session/team-filter.d.ts +1 -1
  474. package/dist/lib/session/team-filter.js +1 -1
  475. package/dist/lib/session/types.d.ts +3 -3
  476. package/dist/lib/session/width.d.ts +2 -2
  477. package/dist/lib/session/width.js +2 -2
  478. package/dist/lib/settings-manifest.d.ts +2 -0
  479. package/dist/lib/settings-manifest.js +81 -3
  480. package/dist/lib/share/delete.d.ts +21 -0
  481. package/dist/lib/share/delete.js +42 -0
  482. package/dist/lib/share/publish.d.ts +120 -0
  483. package/dist/lib/share/publish.js +243 -18
  484. package/dist/lib/share/worker-template.js +172 -9
  485. package/dist/lib/shims.js +35 -7
  486. package/dist/lib/smart-launch.d.ts +4 -4
  487. package/dist/lib/smart-launch.js +6 -4
  488. package/dist/lib/snapshot.d.ts +4 -4
  489. package/dist/lib/snapshot.js +2 -2
  490. package/dist/lib/ssh-exec.d.ts +1 -1
  491. package/dist/lib/ssh-exec.js +2 -2
  492. package/dist/lib/ssh-tunnel.d.ts +10 -10
  493. package/dist/lib/ssh-tunnel.js +12 -12
  494. package/dist/lib/staleness/checkers/hooks.d.ts +1 -1
  495. package/dist/lib/staleness/checkers/hooks.js +1 -1
  496. package/dist/lib/staleness/detectors/permissions.js +0 -23
  497. package/dist/lib/staleness/detectors/plugins.js +1 -1
  498. package/dist/lib/staleness/fingerprint.js +1 -1
  499. package/dist/lib/staleness/layers.d.ts +1 -1
  500. package/dist/lib/staleness/layers.js +1 -1
  501. package/dist/lib/staleness/writers/mcp.js +3 -1
  502. package/dist/lib/staleness/writers/plugins.js +1 -1
  503. package/dist/lib/staleness/writers/types.d.ts +8 -0
  504. package/dist/lib/startup/command-registry.d.ts +6 -147
  505. package/dist/lib/startup/command-registry.js +40 -303
  506. package/dist/lib/startup/dev-build.d.ts +0 -21
  507. package/dist/lib/startup/dev-build.js +29 -8
  508. package/dist/lib/state.d.ts +19 -1
  509. package/dist/lib/state.js +120 -51
  510. package/dist/lib/subagents.js +1 -1
  511. package/dist/lib/sync-status.js +1 -1
  512. package/dist/lib/sync-umbrella.d.ts +6 -1
  513. package/dist/lib/sync-umbrella.js +9 -4
  514. package/dist/lib/teams/agents.js +2 -2
  515. package/dist/lib/teams/registry.js +1 -1
  516. package/dist/lib/terminal/backends/vscodium-agent.js +1 -1
  517. package/dist/lib/terminal/engine.js +1 -1
  518. package/dist/lib/terminal/index.d.ts +4 -0
  519. package/dist/lib/terminal/index.js +3 -0
  520. package/dist/lib/terminal/inject.d.ts +2 -2
  521. package/dist/lib/terminal/inject.js +2 -2
  522. package/dist/lib/terminal/transport.js +1 -1
  523. package/dist/lib/tmux/index.d.ts +1 -1
  524. package/dist/lib/tmux/index.js +1 -1
  525. package/dist/lib/tmux/session.d.ts +21 -5
  526. package/dist/lib/tmux/session.js +76 -22
  527. package/dist/lib/triggers/handlers.d.ts +38 -3
  528. package/dist/lib/triggers/handlers.js +58 -7
  529. package/dist/lib/triggers/webhook.d.ts +113 -5
  530. package/dist/lib/triggers/webhook.js +223 -44
  531. package/dist/lib/types.d.ts +19 -7
  532. package/dist/lib/usage-fleet.d.ts +1 -1
  533. package/dist/lib/usage-fleet.js +1 -1
  534. package/dist/lib/usage-refresh.d.ts +1 -1
  535. package/dist/lib/usage-refresh.js +3 -3
  536. package/dist/lib/version-duplicates.js +2 -2
  537. package/dist/lib/view-types.d.ts +56 -0
  538. package/dist/lib/view-types.js +1 -0
  539. package/dist/lib/watchdog/rotate.d.ts +2 -2
  540. package/dist/lib/watchdog/rotate.js +3 -3
  541. package/dist/lib/watchdog/runner.d.ts +2 -3
  542. package/dist/lib/watchdog/runner.js +3 -4
  543. package/dist/lib/workflows.js +1 -1
  544. package/dist/lib/wrap.d.ts +33 -0
  545. package/dist/lib/wrap.js +70 -0
  546. package/package.json +2 -1
  547. package/scripts/postinstall.js +2 -2
  548. package/dist/commands/bench.d.ts +0 -2
  549. package/dist/commands/bench.js +0 -101
  550. package/dist/commands/cp.d.ts +0 -84
  551. package/dist/commands/cp.js +0 -231
  552. package/dist/commands/login.d.ts +0 -2
  553. package/dist/lib/resources/commands.d.ts +0 -46
  554. package/dist/lib/resources/commands.js +0 -211
  555. package/dist/lib/resources/hooks.d.ts +0 -16
  556. package/dist/lib/resources/hooks.js +0 -153
  557. package/dist/lib/resources/mcp.d.ts +0 -34
  558. package/dist/lib/resources/mcp.js +0 -250
  559. package/dist/lib/resources/memory.d.ts +0 -15
  560. package/dist/lib/resources/memory.js +0 -46
  561. package/dist/lib/resources/permissions.d.ts +0 -13
  562. package/dist/lib/resources/permissions.js +0 -202
  563. package/dist/lib/resources/rules.d.ts +0 -46
  564. package/dist/lib/resources/rules.js +0 -179
  565. package/dist/lib/resources/skills.d.ts +0 -37
  566. package/dist/lib/resources/skills.js +0 -247
  567. package/dist/lib/resources/subagents.d.ts +0 -46
  568. package/dist/lib/resources/subagents.js +0 -202
  569. /package/dist/lib/{feed.d.ts → feed/feed.d.ts} +0 -0
@@ -367,13 +367,14 @@ export async function paneExitStatus(pane, socket) {
367
367
  * Best-effort — returns false when tmux rejects the hook so callers do not
368
368
  * stamp a schema marker and daemon reconciliation can retry later.
369
369
  */
370
- export async function setSessionHook(name, hook, command, socket) {
370
+ export async function setSessionHook(name, hook, command, socket, timeoutMs) {
371
371
  assertValidSessionName(name);
372
372
  const sock = socket ?? getDefaultSocketPath();
373
373
  const result = await runTmux({
374
374
  socket: sock,
375
375
  args: ['set-hook', '-t', name, hook, command],
376
376
  throwOnError: false,
377
+ timeoutMs,
377
378
  }).catch(() => null);
378
379
  return result?.code === 0;
379
380
  }
@@ -405,6 +406,15 @@ export async function setSessionHook(name, hook, command, socket) {
405
406
  export const AGENT_HOOK_SCHEMA = 5;
406
407
  /** Per-session tmux user-option that records which AGENT_HOOK_SCHEMA a session's hook is at. */
407
408
  const HOOK_SCHEMA_OPTION = '@ag_hook_schema';
409
+ /**
410
+ * Bound on every tmux call made by the hook-repair path (daemon startup,
411
+ * upgrade migration, and single-session repair-before-attach). A wedged tmux
412
+ * server would otherwise hang the caller indefinitely — exactly the class of
413
+ * bug RUSH-2507 fixed for `listTmuxAgentSessions`'s `list-panes` call, applied
414
+ * here to `reconcileSessionHooks`/`repairSessionHookIfStale`'s calls so a
415
+ * wedged shared socket can no longer wedge daemon startup (RUSH-2435 review).
416
+ */
417
+ const TMUX_HOOK_REPAIR_TIMEOUT_MS = 5_000;
408
418
  /**
409
419
  * The guarded `pane-died` hook. Detach the client ONLY when the agent pane dies
410
420
  * (so the blocking attach in runInTmux returns and the exit status can be read);
@@ -423,13 +433,13 @@ export function agentPaneDiedHook(sessionName, agentPane) {
423
433
  return `if -F '#{==:#{hook_pane},${agentPane}}' 'detach-client -s =${sessionName}' 'run-shell -b -C "kill-pane -t #{hook_pane}"'`;
424
434
  }
425
435
  /** Stamp a session's hook-schema marker to the current version. */
426
- export async function markSessionHookSchema(name, socket) {
436
+ export async function markSessionHookSchema(name, socket, timeoutMs) {
427
437
  const sock = socket ?? getDefaultSocketPath();
428
- await runTmux({ socket: sock, args: ['set-option', '-t', name, HOOK_SCHEMA_OPTION, String(AGENT_HOOK_SCHEMA)], throwOnError: false }).catch(() => { });
438
+ await runTmux({ socket: sock, args: ['set-option', '-t', name, HOOK_SCHEMA_OPTION, String(AGENT_HOOK_SCHEMA)], throwOnError: false, timeoutMs }).catch(() => { });
429
439
  }
430
440
  /** Read a session's hook-schema marker; undefined when unset (pre-marker sessions). */
431
- async function readHookSchema(name, socket) {
432
- const res = await runTmux({ socket, args: ['show-options', '-v', '-t', name, HOOK_SCHEMA_OPTION], throwOnError: false }).catch(() => null);
441
+ async function readHookSchema(name, socket, timeoutMs) {
442
+ const res = await runTmux({ socket, args: ['show-options', '-v', '-t', name, HOOK_SCHEMA_OPTION], throwOnError: false, timeoutMs }).catch(() => null);
433
443
  if (!res || res.code !== 0)
434
444
  return undefined;
435
445
  const v = res.stdout.trim();
@@ -441,8 +451,8 @@ async function readHookSchema(name, socket) {
441
451
  * for sessions whose SessionMeta (which records the agent pane) predates meta
442
452
  * persistence. Undefined when the session has no panes (already torn down).
443
453
  */
444
- async function lowestPaneId(name, socket) {
445
- const res = await runTmux({ socket, args: ['list-panes', '-t', name, '-F', '#{pane_id}'], throwOnError: false }).catch(() => null);
454
+ async function lowestPaneId(name, socket, timeoutMs) {
455
+ const res = await runTmux({ socket, args: ['list-panes', '-t', name, '-F', '#{pane_id}'], throwOnError: false, timeoutMs }).catch(() => null);
446
456
  if (!res || res.code !== 0)
447
457
  return undefined;
448
458
  const ids = res.stdout.split('\n').map(l => l.trim()).filter(id => /^%\d+$/.test(id));
@@ -467,11 +477,35 @@ export async function prepareSessionForResume(name, socket) {
467
477
  ? recordedPane
468
478
  : await lowestPaneId(name, sock);
469
479
  const state = pane ? await paneExitStatus(pane, sock) : undefined;
470
- if (pane && state?.found && !state.dead)
480
+ if (pane && state?.found && !state.dead) {
481
+ // Self-heal a legacy/stale hook right before handing the session back to
482
+ // an attach client — the steady-state repair point between the daemon's
483
+ // startup and upgrade one-shots (RUSH-2435).
484
+ await ensureSessionHookRepaired(name, sock);
471
485
  return { decision: 'attach', pane };
486
+ }
472
487
  await killSession(name, sock);
473
488
  return { decision: 'create' };
474
489
  }
490
+ /**
491
+ * Repair ONE session's `pane-died` hook if it predates AGENT_HOOK_SCHEMA.
492
+ * Idempotent and NON-DESTRUCTIVE — only `set-hook`s, never kills a pane or
493
+ * detaches a client. Shared by {@link reconcileSessionHooks} (full sweep) and
494
+ * {@link ensureSessionHookRepaired} (single session, called before attach) so
495
+ * the two can never drift on what counts as "repaired" (RUSH-2435).
496
+ */
497
+ async function repairSessionHookIfStale(name, sock, meta, timeoutMs = TMUX_HOOK_REPAIR_TIMEOUT_MS) {
498
+ if (await readHookSchema(name, sock, timeoutMs) === String(AGENT_HOOK_SCHEMA))
499
+ return false;
500
+ const agentPane = meta?.pane ?? await lowestPaneId(name, sock, timeoutMs);
501
+ if (!agentPane)
502
+ return false;
503
+ const installed = await setSessionHook(name, 'pane-died', agentPaneDiedHook(name, agentPane), sock, timeoutMs);
504
+ if (!installed)
505
+ return false;
506
+ await markSessionHookSchema(name, sock, timeoutMs);
507
+ return true;
508
+ }
475
509
  /**
476
510
  * Retrofit the current guarded `pane-died` hook onto every managed `agents run`
477
511
  * session whose hook predates AGENT_HOOK_SCHEMA. Idempotent and NON-DESTRUCTIVE:
@@ -481,9 +515,15 @@ export async function prepareSessionForResume(name, socket) {
481
515
  * exited a split — self-heals in place, without waiting for those agents to exit
482
516
  * or for the server to be recycled.
483
517
  *
484
- * The daemon calls this on a light interval. The per-session `@ag_hook_schema`
485
- * marker makes steady-state a cheap no-op: a session already at the current
486
- * schema is skipped. Only run-wrapped sessions (`ag-` prefix) are touched an
518
+ * NOT a daemon poll the 5-minute `tmux-reconcile` routine that used to call this
519
+ * was deleted (RUSH-2495). It survives as the version-skew ONE-SHOT: the daemon
520
+ * calls it once at startup (`runDaemon` in `../daemon.js`) and once from the
521
+ * upgrade-time migration (`runMigration` in `../migrate.js`), so a session a
522
+ * pre-fix binary left with a stale hook still self-heals without a live poller.
523
+ * `ensureSessionHookRepaired` covers the steady-state gap between those two
524
+ * points by repairing a single session right before it's attached to. The
525
+ * per-session `@ag_hook_schema` marker makes both paths a cheap no-op once a
526
+ * session is current. Only run-wrapped sessions (`ag-` prefix) are touched — an
487
527
  * externally-created session on the socket keeps whatever hook it set.
488
528
  */
489
529
  export async function reconcileSessionHooks(socket) {
@@ -492,7 +532,7 @@ export async function reconcileSessionHooks(socket) {
492
532
  return { scanned: 0, reconciled: 0 };
493
533
  let sessions;
494
534
  try {
495
- sessions = await listSessions({ socket: sock });
535
+ sessions = await listSessions({ socket: sock, timeoutMs: TMUX_HOOK_REPAIR_TIMEOUT_MS });
496
536
  }
497
537
  catch {
498
538
  return { scanned: 0, reconciled: 0 };
@@ -501,19 +541,32 @@ export async function reconcileSessionHooks(socket) {
501
541
  for (const s of sessions) {
502
542
  if (!s.name.startsWith('ag-'))
503
543
  continue; // only run-wrapped sessions
504
- if (await readHookSchema(s.name, sock) === String(AGENT_HOOK_SCHEMA))
505
- continue;
506
- const agentPane = s.meta?.pane ?? await lowestPaneId(s.name, sock);
507
- if (!agentPane)
508
- continue;
509
- const installed = await setSessionHook(s.name, 'pane-died', agentPaneDiedHook(s.name, agentPane), sock);
510
- if (!installed)
511
- continue;
512
- await markSessionHookSchema(s.name, sock);
513
- reconciled++;
544
+ if (await repairSessionHookIfStale(s.name, sock, s.meta))
545
+ reconciled++;
514
546
  }
515
547
  return { scanned: sessions.length, reconciled };
516
548
  }
549
+ /**
550
+ * Repair a single managed session's `pane-died` hook right before it is
551
+ * attached to, so a legacy session left by a pre-fix binary self-heals on the
552
+ * next touch instead of waiting for the next daemon-startup/upgrade one-shot
553
+ * (RUSH-2435). Only `ag-`-prefixed (run-wrapped) sessions are touched; a no-op
554
+ * for anything else. Best-effort — never throws, so a repair failure can never
555
+ * block the attach it is protecting.
556
+ */
557
+ export async function ensureSessionHookRepaired(name, socket) {
558
+ if (!name.startsWith('ag-'))
559
+ return;
560
+ const sock = socket ?? getDefaultSocketPath();
561
+ if (!fs.existsSync(sock))
562
+ return;
563
+ try {
564
+ await repairSessionHookIfStale(name, sock, readSessionMeta(name) ?? undefined);
565
+ }
566
+ catch {
567
+ // best-effort — an attach must never fail because a repair attempt did
568
+ }
569
+ }
517
570
  /**
518
571
  * List live sessions on the socket. Reconciles meta JSONs against tmux's view:
519
572
  * - tmux session with no meta → returned without `meta` (external session)
@@ -532,6 +585,7 @@ export async function listSessions(opts = {}) {
532
585
  socket,
533
586
  args: ['list-sessions', '-F', fmt],
534
587
  throwOnError: false,
588
+ timeoutMs: opts.timeoutMs,
535
589
  });
536
590
  // tmux returns nonzero with "no server running" or "no sessions" — both mean empty.
537
591
  if (res.code !== 0) {
@@ -5,9 +5,9 @@
5
5
  * project/system layers). They complement routine triggers: a matching webhook
6
6
  * can run an agent, workflow, shell command, or delegate to a routine.
7
7
  */
8
- import type { JobConfig, RunMeta, WebhookContext } from '../routines.js';
8
+ import type { JobConfig, RunMeta, WebhookContext } from '../scheduling/routines.js';
9
9
  import type { AgentId } from '../types.js';
10
- import type { IncomingWebhook, WebhookSource } from './webhook.js';
10
+ import type { IncomingWebhook, SlackPayload, WebhookSource } from './webhook.js';
11
11
  export interface WebhookHandler {
12
12
  name: string;
13
13
  enabled?: boolean;
@@ -21,6 +21,11 @@ export interface WebhookHandler {
21
21
  label?: string;
22
22
  repo?: string;
23
23
  branch?: string;
24
+ /** Slack (source: slack) only — match one slash command, e.g. `/agents`. */
25
+ command?: string;
26
+ /** Slack (source: slack) only — restrict to one channel id (`C0…`). Lets a
27
+ * channel imply a project via a per-channel handler. */
28
+ channel?: string;
24
29
  /**
25
30
  * Where to run the action. A device name (`yosemite-s0`) runs there over SSH;
26
31
  * `fleet` picks any eligible online worker; `fleet/<platform>` (or
@@ -92,10 +97,40 @@ export declare function resolveHandlerHost(host: string | undefined): HandlerHos
92
97
  export declare function listHandlers(cwd?: string): WebhookHandler[];
93
98
  /** Pure matcher: does this handler match the incoming webhook? */
94
99
  export declare function handlerMatchesWebhook(handler: WebhookHandler, webhook: IncomingWebhook): boolean;
100
+ /**
101
+ * The `{{slack.*}}` substitution namespace: a Slack message split into an
102
+ * agent-actionable project + prompt, plus the coordinates a reply threads into.
103
+ */
104
+ export interface SlackMessageContext {
105
+ /** The message with a leading bot mention stripped. */
106
+ text: string;
107
+ /** The `PROJECT:` token at the head of the message, or '' when absent. */
108
+ project: string;
109
+ /** The request — the text after `PROJECT:`, or the whole message. */
110
+ prompt: string;
111
+ /** Channel id to reply into (`C0…`). */
112
+ channel: string;
113
+ /** Thread ts to reply into (empty for a slash command → reply to the channel). */
114
+ thread_ts: string;
115
+ /** Invoking user id (`U0…`). */
116
+ user: string;
117
+ /** Slash command name (`/agents`), or '' for an event delivery. */
118
+ command: string;
119
+ }
120
+ /**
121
+ * Split a Slack message into a `{{slack.*}}` context. Strips a leading bot
122
+ * mention (`<@U0BOT> …`), then reads an optional `PROJECT:` prefix — a single
123
+ * bare token followed by a colon and a space — as the project, with the
124
+ * remainder the prompt. `AGI: rebase my PR` → project `AGI`, prompt
125
+ * `rebase my PR`; a message with no such prefix leaves `project` empty and the
126
+ * whole text as the prompt. The token pattern forbids slashes, so a project
127
+ * value can never carry a path into a `cwd`/`project` substitution.
128
+ */
129
+ export declare function parseSlackMessage(payload: SlackPayload): SlackMessageContext;
95
130
  /**
96
131
  * Build the variable-substitution context for a webhook. Linear events expose
97
132
  * `issue` and `updatedFrom`; GitHub events expose `repository`, `pull_request`,
98
- * and `issue`.
133
+ * and `issue`; Slack events expose the `{{slack.*}}` namespace above.
99
134
  */
100
135
  export declare function buildWebhookContext(webhook: IncomingWebhook): WebhookContext;
101
136
  export interface ExecuteHandlerOptions {
@@ -9,11 +9,11 @@ import { exec } from 'child_process';
9
9
  import * as fs from 'fs';
10
10
  import * as path from 'path';
11
11
  import * as yaml from 'yaml';
12
- import { emit } from '../events.js';
12
+ import { emit } from '../feed/events.js';
13
13
  import { machineId, normalizeHost } from '../machine-id.js';
14
14
  import { safeJoin } from '../paths.js';
15
15
  import { pickFleetDevice } from '../routines-placement.js';
16
- import { assertShellSubstitutionSupported, readJob, substituteWebhookCommand, substituteWebhookPrompt, } from '../routines.js';
16
+ import { assertShellSubstitutionSupported, readJob, substituteWebhookCommand, substituteWebhookPrompt, } from '../scheduling/routines.js';
17
17
  import { ensureAgentsDir, getProjectWebhooksDir, getSystemWebhooksDir, getWebhooksDir } from '../state.js';
18
18
  const HANDLER_DEFAULTS = {
19
19
  enabled: true,
@@ -208,6 +208,17 @@ export function handlerMatchesWebhook(handler, webhook) {
208
208
  return false;
209
209
  if (!handlerRunsOnThisDevice(handler))
210
210
  return false;
211
+ // Slack has no GitHub/Linear action/label/branch vocabulary; it matches on the
212
+ // slash command and (optionally) the channel. `event` already pinned the
213
+ // subtype (`app_mention`) or the slash command name above.
214
+ if (webhook.source === 'slack') {
215
+ const slack = webhook.payload;
216
+ if (handler.command && slack.command !== handler.command)
217
+ return false;
218
+ if (handler.channel && slack.channel !== handler.channel)
219
+ return false;
220
+ return true;
221
+ }
211
222
  if (handler.action) {
212
223
  const action = webhook.source === 'github' ? githubAction(webhook.payload) : linearAction(webhook.payload);
213
224
  if (action !== handler.action)
@@ -262,12 +273,47 @@ export function handlerMatchesWebhook(handler, webhook) {
262
273
  }
263
274
  return true;
264
275
  }
276
+ const asString = (v) => (typeof v === 'string' ? v : '');
277
+ /**
278
+ * Split a Slack message into a `{{slack.*}}` context. Strips a leading bot
279
+ * mention (`<@U0BOT> …`), then reads an optional `PROJECT:` prefix — a single
280
+ * bare token followed by a colon and a space — as the project, with the
281
+ * remainder the prompt. `AGI: rebase my PR` → project `AGI`, prompt
282
+ * `rebase my PR`; a message with no such prefix leaves `project` empty and the
283
+ * whole text as the prompt. The token pattern forbids slashes, so a project
284
+ * value can never carry a path into a `cwd`/`project` substitution.
285
+ */
286
+ export function parseSlackMessage(payload) {
287
+ const cleaned = asString(payload.text).replace(/^\s*<@[^>]+>\s*/, '').trim();
288
+ const m = /^([A-Za-z0-9][\w.-]*)\s*:\s+([\s\S]+)$/.exec(cleaned);
289
+ return {
290
+ text: cleaned,
291
+ project: m ? m[1] : '',
292
+ prompt: m ? m[2].trim() : cleaned,
293
+ channel: asString(payload.channel),
294
+ thread_ts: asString(payload.thread_ts),
295
+ user: asString(payload.user),
296
+ command: asString(payload.command),
297
+ };
298
+ }
265
299
  /**
266
300
  * Build the variable-substitution context for a webhook. Linear events expose
267
301
  * `issue` and `updatedFrom`; GitHub events expose `repository`, `pull_request`,
268
- * and `issue`.
302
+ * and `issue`; Slack events expose the `{{slack.*}}` namespace above.
269
303
  */
270
304
  export function buildWebhookContext(webhook) {
305
+ if (webhook.source === 'slack') {
306
+ // The `{{slack.*}}` namespace rides an intersection over WebhookContext (a
307
+ // subtype of it) rather than a field on the shared type, so a Slack-only
308
+ // addition never touches the scheduling hub every routine test depends on.
309
+ // `substituteWebhookPrompt`/`getPath` read it dynamically at runtime.
310
+ const ctx = {
311
+ source: webhook.source,
312
+ event: webhook.event,
313
+ slack: parseSlackMessage(webhook.payload),
314
+ };
315
+ return ctx;
316
+ }
271
317
  const action = webhook.source === 'github'
272
318
  ? githubAction(webhook.payload) ?? undefined
273
319
  : linearAction(webhook.payload) ?? undefined;
@@ -346,6 +392,11 @@ export async function executeHandler(handler, webhook, opts = {}) {
346
392
  }
347
393
  async function executeHandlerAction(handler, webhook, context, opts) {
348
394
  const substitutedPrompt = handler.run?.prompt ? substituteWebhookPrompt(handler.run.prompt, context) : '';
395
+ // Slack routes the project per-message (`AGI: …`), so a handler may template
396
+ // its project/cwd — e.g. `project: "{{slack.project}}"`. Substitute + trim; an
397
+ // empty result omits the field (falls back to the run's default cwd / $HOME).
398
+ const substitutedProject = handler.project ? substituteWebhookPrompt(handler.project, context).trim() : '';
399
+ const substitutedCwd = handler.cwd ? substituteWebhookPrompt(handler.cwd, context).trim() : '';
349
400
  // Resolved once so a fleet pick can't differ between the two dispatch paths.
350
401
  const hostFields = resolveHandlerHost(handler.host);
351
402
  if (handler.run?.agent || handler.run?.workflow) {
@@ -359,8 +410,8 @@ async function executeHandlerAction(handler, webhook, context, opts) {
359
410
  ...(handler.run.agent ? { agent: handler.run.agent } : { workflow: handler.run.workflow }),
360
411
  ...(handler.devices ? { devices: handler.devices } : {}),
361
412
  ...(handler.run.env ? { env: handler.run.env } : {}),
362
- ...(handler.project ? { project: handler.project } : {}),
363
- ...(handler.cwd ? { cwd: handler.cwd } : {}),
413
+ ...(substitutedProject ? { project: substitutedProject } : {}),
414
+ ...(substitutedCwd ? { cwd: substitutedCwd } : {}),
364
415
  ...(hostFields.host ? { host: hostFields.host } : {}),
365
416
  ...(hostFields.hostStrategy ? { hostStrategy: hostFields.hostStrategy } : {}),
366
417
  };
@@ -385,8 +436,8 @@ async function executeHandlerAction(handler, webhook, context, opts) {
385
436
  ...routine,
386
437
  prompt: substituteWebhookPrompt(routine.prompt, context),
387
438
  ...(handler.devices ? { devices: handler.devices } : {}),
388
- ...(handler.project ? { project: handler.project } : {}),
389
- ...(handler.cwd ? { cwd: handler.cwd } : {}),
439
+ ...(substitutedProject ? { project: substitutedProject } : {}),
440
+ ...(substitutedCwd ? { cwd: substitutedCwd } : {}),
390
441
  ...(handler.mode ? { mode: handler.mode } : {}),
391
442
  ...(hostFields.host ? { host: hostFields.host } : {}),
392
443
  ...(hostFields.hostStrategy ? { hostStrategy: hostFields.hostStrategy } : {}),
@@ -13,15 +13,17 @@
13
13
  */
14
14
  import * as http from 'http';
15
15
  import type { IncomingHttpHeaders } from 'http';
16
- import type { JobConfig, RunMeta, WebhookContext } from '../routines.js';
16
+ import type { JobConfig, RunMeta, WebhookContext } from '../scheduling/routines.js';
17
17
  import { type FiredHandler } from './handlers.js';
18
- export type WebhookSource = 'github' | 'linear';
18
+ export type WebhookSource = 'github' | 'linear' | 'slack';
19
19
  export interface IncomingWebhook {
20
20
  /** Delivery source, derived from `/hooks/<source>` or one-shot command flags. */
21
21
  source: WebhookSource;
22
- /** Source event name: GitHub header event or Linear payload `type`. */
22
+ /** Source event name: GitHub header event, Linear payload `type`, or the Slack
23
+ * event subtype (`app_mention`) / slash command (`/agents`). */
23
24
  event: string;
24
- /** Decoded JSON request body. */
25
+ /** Decoded request body (JSON for GitHub/Linear/Slack-events; the normalized
26
+ * {@link SlackPayload} for a Slack slash command's form body). */
25
27
  payload: Record<string, unknown>;
26
28
  }
27
29
  export type GithubWebhook = IncomingWebhook & {
@@ -30,6 +32,9 @@ export type GithubWebhook = IncomingWebhook & {
30
32
  export type LinearWebhook = IncomingWebhook & {
31
33
  source: 'linear';
32
34
  };
35
+ export type SlackWebhook = IncomingWebhook & {
36
+ source: 'slack';
37
+ };
33
38
  /** Read `repository.full_name` (`owner/name`) from a webhook payload, if present. */
34
39
  export declare function webhookRepo(payload: Record<string, unknown>): string | null;
35
40
  /**
@@ -96,9 +101,59 @@ export declare function fireWebhookJobs(webhook: IncomingWebhook, options?: Fire
96
101
  export declare function verifyGithubSignature(headers: IncomingHttpHeaders, rawBody: Buffer, secret: string): boolean;
97
102
  export declare function verifyLinearSignature(headers: IncomingHttpHeaders, rawBody: Buffer, secret: string): boolean;
98
103
  export declare function verifyLinearTimestamp(payload: Record<string, unknown>, now?: number, toleranceMs?: number): boolean;
104
+ /**
105
+ * Verify a Slack request signature (the `v0` scheme). Slack signs the base
106
+ * string `v0:${timestamp}:${rawBody}` with the app's signing secret and sends
107
+ * the hex digest as `X-Slack-Signature: v0=<hex>`, alongside the unix
108
+ * `X-Slack-Request-Timestamp`. The timestamp is BOTH part of the signed base
109
+ * string AND checked for freshness here — a request older than `toleranceSec`
110
+ * (default 5 min) is rejected, so a captured, correctly-signed body cannot be
111
+ * replayed later. Fails closed on any missing/malformed header.
112
+ */
113
+ export declare function verifySlackSignature(headers: IncomingHttpHeaders, rawBody: Buffer, secret: string, now?: number, toleranceSec?: number): boolean;
114
+ /**
115
+ * Normalized fields extracted from a Slack slash-command or Events API delivery.
116
+ * This is the `payload` of a Slack {@link IncomingWebhook}: transport-level
117
+ * parsing lives here, message *semantics* (splitting the mention text into an
118
+ * agent / project / prompt) live in `handlers.ts` `buildWebhookContext`.
119
+ */
120
+ export interface SlackPayload extends Record<string, unknown> {
121
+ /** `url_verification` | `event_callback` | `slash_command`. */
122
+ type: string;
123
+ /** Echoed back for the one-time Events API URL-verification handshake. */
124
+ challenge?: string;
125
+ /** Slack event id (Events API) — the dedup key when present. */
126
+ event_id?: string;
127
+ /** Event subtype, e.g. `app_mention` (Events API). */
128
+ event_type?: string;
129
+ /** Raw message text (the mention body, or the slash-command text). */
130
+ text?: string;
131
+ /** Channel id (`C0…`) the message arrived in. */
132
+ channel?: string;
133
+ /** Thread to reply into: an existing thread's parent ts, else the message ts. */
134
+ thread_ts?: string;
135
+ /** Invoking user id (`U0…`). */
136
+ user?: string;
137
+ /** Slash command name, e.g. `/agents`. */
138
+ command?: string;
139
+ /** Slash-command `response_url` (valid ~30 min, 5 uses). */
140
+ response_url?: string;
141
+ /** Slack team / workspace id. */
142
+ team?: string;
143
+ }
144
+ /**
145
+ * Parse a Slack delivery body into a normalized {@link SlackPayload}. Slack
146
+ * sends slash commands as `application/x-www-form-urlencoded` and Events API
147
+ * deliveries (including the `url_verification` handshake) as
148
+ * `application/json` — this is the one place that content-type branch lives.
149
+ */
150
+ export declare function parseSlackBody(contentType: string | undefined, rawBody: Buffer): SlackPayload;
151
+ /** The `event` name a Slack delivery fires under: the slash command, or the event subtype. */
152
+ export declare function slackEventName(payload: SlackPayload): string;
99
153
  export interface WebhookSecrets {
100
154
  github?: string;
101
155
  linear?: string;
156
+ slack?: string;
102
157
  }
103
158
  export interface DeliveryStore {
104
159
  seen(id: string): boolean;
@@ -123,6 +178,15 @@ export interface RateLimiter {
123
178
  take(key: string): boolean;
124
179
  }
125
180
  export declare function createMemoryRateLimiter(limit: number, windowMs: number): RateLimiter;
181
+ /**
182
+ * Resolve once a receiver is actually accepting connections, REJECT if the bind
183
+ * failed. `server.listen()` reports a bind failure (EADDRINUSE, EACCES) as an
184
+ * asynchronous `'error'` event, never a throw — so a `try/catch` around
185
+ * `startWebhookServer` cannot see it, and without this the event reaches Node's
186
+ * default handler and takes the whole process down. Every caller that hosts a
187
+ * receiver MUST await this rather than assuming the return means "bound".
188
+ */
189
+ export declare function waitForListening(server: http.Server): Promise<void>;
126
190
  /** Options for the local webhook http listener. */
127
191
  export interface WebhookServerOptions {
128
192
  port?: number;
@@ -131,8 +195,33 @@ export interface WebhookServerOptions {
131
195
  secrets: WebhookSecrets;
132
196
  /** Override the fire options (mainly for tests). */
133
197
  fire?: FireWebhookOptions;
134
- /** Called after each delivery is handled (mainly for tests/observability). */
198
+ /**
199
+ * Called the moment a delivery's matches are known — BEFORE any routine or
200
+ * handler is dispatched. Matching is a pure, synchronous lookup (no I/O), so
201
+ * this fires immediately after the ack, regardless of how long the matched
202
+ * work then takes to run. This is the right hook for a "webhook X fired Y"
203
+ * log line: a `run.command` handler that shells out a long agent session
204
+ * (`exec()`, which only resolves on process exit) used to hold that log back
205
+ * for as long as the session ran — `ps` would show the agent already running
206
+ * while the log still implied nothing had matched (RUSH-2722). Names only
207
+ * (no runId/exitCode yet — those aren't known until dispatch settles).
208
+ */
209
+ onMatch?: (webhook: IncomingWebhook, matchedJobNames: string[], matchedHandlerNames: string[]) => void;
210
+ /**
211
+ * Called after a delivery has fully settled — every matched routine and
212
+ * handler dispatched (and, for `run.command` handlers, exited). Because the
213
+ * receiver acks the HTTP response BEFORE dispatch (see `startWebhookServer`),
214
+ * this fires strictly after the response has been written, and is the only
215
+ * way a caller observes the dispatch outcome (runId/exitCode/output). It is
216
+ * NOT the right hook for "did this webhook match" logging — use `onMatch`.
217
+ */
135
218
  onDelivery?: (webhook: IncomingWebhook, fired: FiredJob[], handlers: FiredHandler[]) => void;
219
+ /**
220
+ * Called when settling an already-acked delivery threw. The HTTP status can
221
+ * no longer carry the failure, so this is the loud path — the daemon host and
222
+ * `agents webhooks serve` both log it. Never swallowed silently.
223
+ */
224
+ onDeliveryError?: (webhook: IncomingWebhook, error: Error) => void;
136
225
  deliveryStore?: DeliveryStore;
137
226
  rateLimiter?: RateLimiter;
138
227
  rateLimitPerMinute?: number;
@@ -149,6 +238,25 @@ export interface WebhookServerOptions {
149
238
  * POST /hooks/github with X-Hub-Signature-256
150
239
  * POST /hooks/linear with Linear-Signature + fresh webhookTimestamp
151
240
  *
241
+ * **The ack is asynchronous (RUSH-2548).** Once a delivery has passed signature
242
+ * verification, freshness, dedup, and rate limiting, the receiver writes
243
+ * `202 {ok:true, accepted:true}` IMMEDIATELY and dispatches the matched routines
244
+ * and handlers afterwards. Dispatch starts an agent run and takes 15-20s, which
245
+ * exceeds Linear's delivery timeout — holding the socket open across it made
246
+ * every real delivery log a timeout + retry on Linear's side. Nothing about the
247
+ * dedup ledger changes: the `<source>:<delivery-id>` key is still what makes a
248
+ * retry a no-op, per-job `markJob` still lets a retry finish only the matches
249
+ * that failed, and the delivery is marked complete only after it settles.
250
+ *
251
+ * A retry that lands WHILE the first is still settling is answered as a
252
+ * duplicate from an in-flight set, since `deliveryStore.seen` only reports
253
+ * completed deliveries and would otherwise let a mid-flight retry double-fire.
254
+ *
255
+ * `onMatch` fires as soon as matching is known, before any dispatch; `onDelivery`
256
+ * fires only once every matched routine/handler has settled — see their docs on
257
+ * `WebhookServerOptions`. A caller that wants a prompt "this fired" log uses
258
+ * `onMatch`, not `onDelivery` (RUSH-2722).
259
+ *
152
260
  * Returns the underlying server so callers can `close()` it.
153
261
  */
154
262
  export declare function startWebhookServer(options: WebhookServerOptions): http.Server;