@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
@@ -15,9 +15,9 @@ import * as crypto from 'crypto';
15
15
  import * as fs from 'fs';
16
16
  import * as http from 'http';
17
17
  import * as path from 'path';
18
- import { jobRunsOnThisDevice, listJobs, substituteWebhookPrompt } from '../routines.js';
18
+ import { jobRunsOnThisDevice, listJobs, substituteWebhookPrompt } from '../scheduling/routines.js';
19
19
  import { executeJobDetached } from '../runner.js';
20
- import { emit } from '../events.js';
20
+ import { emit } from '../feed/events.js';
21
21
  import { listHandlers, handlerMatchesWebhook, executeHandler, buildWebhookContext, } from './handlers.js';
22
22
  /** Read `repository.full_name` (`owner/name`) from a webhook payload, if present. */
23
23
  export function webhookRepo(payload) {
@@ -264,6 +264,76 @@ export function verifyLinearTimestamp(payload, now = Date.now(), toleranceMs = 6
264
264
  const ts = payload.webhookTimestamp;
265
265
  return typeof ts === 'number' && Math.abs(now - ts) <= toleranceMs;
266
266
  }
267
+ /**
268
+ * Verify a Slack request signature (the `v0` scheme). Slack signs the base
269
+ * string `v0:${timestamp}:${rawBody}` with the app's signing secret and sends
270
+ * the hex digest as `X-Slack-Signature: v0=<hex>`, alongside the unix
271
+ * `X-Slack-Request-Timestamp`. The timestamp is BOTH part of the signed base
272
+ * string AND checked for freshness here — a request older than `toleranceSec`
273
+ * (default 5 min) is rejected, so a captured, correctly-signed body cannot be
274
+ * replayed later. Fails closed on any missing/malformed header.
275
+ */
276
+ export function verifySlackSignature(headers, rawBody, secret, now = Date.now(), toleranceSec = 300) {
277
+ const ts = header(headers, 'x-slack-request-timestamp');
278
+ if (!ts || !/^\d+$/.test(ts))
279
+ return false;
280
+ if (Math.abs(Math.floor(now / 1000) - Number(ts)) > toleranceSec)
281
+ return false;
282
+ const received = header(headers, 'x-slack-signature');
283
+ const signature = received?.startsWith('v0=') ? received.slice('v0='.length) : undefined;
284
+ // Concatenate the base-string prefix with the raw body bytes so a non-ASCII
285
+ // payload hashes identically to Slack's own `v0:${ts}:${body}` string.
286
+ const base = Buffer.concat([Buffer.from(`v0:${ts}:`, 'utf-8'), rawBody]);
287
+ const expected = crypto.createHmac('sha256', secret).update(base).digest('hex');
288
+ return timingSafeHexEqual(signature, expected);
289
+ }
290
+ /**
291
+ * Parse a Slack delivery body into a normalized {@link SlackPayload}. Slack
292
+ * sends slash commands as `application/x-www-form-urlencoded` and Events API
293
+ * deliveries (including the `url_verification` handshake) as
294
+ * `application/json` — this is the one place that content-type branch lives.
295
+ */
296
+ export function parseSlackBody(contentType, rawBody) {
297
+ if ((contentType ?? '').includes('application/x-www-form-urlencoded')) {
298
+ const form = new URLSearchParams(rawBody.toString('utf-8'));
299
+ // A slash command carries no thread; its reply posts to the channel.
300
+ return {
301
+ type: 'slash_command',
302
+ command: form.get('command') ?? undefined,
303
+ text: form.get('text') ?? undefined,
304
+ channel: form.get('channel_id') ?? undefined,
305
+ user: form.get('user_id') ?? undefined,
306
+ response_url: form.get('response_url') ?? undefined,
307
+ team: form.get('team_id') ?? undefined,
308
+ };
309
+ }
310
+ const json = rawBody.length > 0 ? JSON.parse(rawBody.toString('utf-8')) : {};
311
+ const type = String(json.type ?? '');
312
+ if (type === 'url_verification') {
313
+ return { type, challenge: typeof json.challenge === 'string' ? json.challenge : '' };
314
+ }
315
+ const event = (json.event ?? {});
316
+ return {
317
+ type: type || 'event_callback',
318
+ event_id: typeof json.event_id === 'string' ? json.event_id : undefined,
319
+ event_type: typeof event.type === 'string' ? event.type : undefined,
320
+ text: typeof event.text === 'string' ? event.text : undefined,
321
+ channel: typeof event.channel === 'string' ? event.channel : undefined,
322
+ thread_ts: typeof event.thread_ts === 'string'
323
+ ? event.thread_ts
324
+ : typeof event.ts === 'string'
325
+ ? event.ts
326
+ : undefined,
327
+ user: typeof event.user === 'string' ? event.user : undefined,
328
+ team: typeof json.team_id === 'string' ? json.team_id : undefined,
329
+ };
330
+ }
331
+ /** The `event` name a Slack delivery fires under: the slash command, or the event subtype. */
332
+ export function slackEventName(payload) {
333
+ if (payload.type === 'slash_command')
334
+ return payload.command ?? 'slash_command';
335
+ return payload.event_type ?? payload.type;
336
+ }
267
337
  export function createMemoryDeliveryStore(maxEntries = 1000) {
268
338
  const seen = new Map();
269
339
  const touch = (id) => {
@@ -405,7 +475,7 @@ function deliveryId(source, headers, rawBody) {
405
475
  return `${source}:${named ?? crypto.createHash('sha256').update(rawBody).digest('hex')}`;
406
476
  }
407
477
  function sourceFromPath(pathname) {
408
- const match = /^\/hooks\/(github|linear)\/?$/.exec(pathname ?? '');
478
+ const match = /^\/hooks\/(github|linear|slack)\/?$/.exec(pathname ?? '');
409
479
  return match ? match[1] : null;
410
480
  }
411
481
  async function readRawBody(req, maxBytes) {
@@ -420,18 +490,119 @@ async function readRawBody(req, maxBytes) {
420
490
  }
421
491
  return Buffer.concat(chunks);
422
492
  }
493
+ /**
494
+ * Resolve once a receiver is actually accepting connections, REJECT if the bind
495
+ * failed. `server.listen()` reports a bind failure (EADDRINUSE, EACCES) as an
496
+ * asynchronous `'error'` event, never a throw — so a `try/catch` around
497
+ * `startWebhookServer` cannot see it, and without this the event reaches Node's
498
+ * default handler and takes the whole process down. Every caller that hosts a
499
+ * receiver MUST await this rather than assuming the return means "bound".
500
+ */
501
+ export function waitForListening(server) {
502
+ if (server.listening)
503
+ return Promise.resolve();
504
+ return new Promise((resolve, reject) => {
505
+ const cleanup = () => {
506
+ server.off('listening', onListening);
507
+ server.off('error', onError);
508
+ };
509
+ const onListening = () => { cleanup(); resolve(); };
510
+ const onError = (err) => { cleanup(); reject(err); };
511
+ server.once('listening', onListening);
512
+ server.once('error', onError);
513
+ });
514
+ }
423
515
  /**
424
516
  * Start a localhost-bound receiver. It accepts only:
425
517
  * POST /hooks/github with X-Hub-Signature-256
426
518
  * POST /hooks/linear with Linear-Signature + fresh webhookTimestamp
427
519
  *
520
+ * **The ack is asynchronous (RUSH-2548).** Once a delivery has passed signature
521
+ * verification, freshness, dedup, and rate limiting, the receiver writes
522
+ * `202 {ok:true, accepted:true}` IMMEDIATELY and dispatches the matched routines
523
+ * and handlers afterwards. Dispatch starts an agent run and takes 15-20s, which
524
+ * exceeds Linear's delivery timeout — holding the socket open across it made
525
+ * every real delivery log a timeout + retry on Linear's side. Nothing about the
526
+ * dedup ledger changes: the `<source>:<delivery-id>` key is still what makes a
527
+ * retry a no-op, per-job `markJob` still lets a retry finish only the matches
528
+ * that failed, and the delivery is marked complete only after it settles.
529
+ *
530
+ * A retry that lands WHILE the first is still settling is answered as a
531
+ * duplicate from an in-flight set, since `deliveryStore.seen` only reports
532
+ * completed deliveries and would otherwise let a mid-flight retry double-fire.
533
+ *
534
+ * `onMatch` fires as soon as matching is known, before any dispatch; `onDelivery`
535
+ * fires only once every matched routine/handler has settled — see their docs on
536
+ * `WebhookServerOptions`. A caller that wants a prompt "this fired" log uses
537
+ * `onMatch`, not `onDelivery` (RUSH-2722).
538
+ *
428
539
  * Returns the underlying server so callers can `close()` it.
429
540
  */
430
541
  export function startWebhookServer(options) {
431
542
  const deliveryStore = options.deliveryStore ?? createMemoryDeliveryStore();
543
+ /** Delivery ids acked but not yet settled — dedup across the async window. */
544
+ const inFlight = new Set();
432
545
  const rateLimiter = options.rateLimiter ?? createMemoryRateLimiter(options.rateLimitPerMinute ?? 60, 60_000);
433
546
  const ipRateLimiter = options.ipRateLimiter ?? createMemoryRateLimiter(options.ipRateLimitPerMinute ?? 120, 60_000);
434
547
  const maxBodyBytes = options.maxBodyBytes ?? 1024 * 1024;
548
+ /**
549
+ * Dispatch an already-acked delivery: matched routines first, then matched
550
+ * handlers, then mark the delivery complete. A failure leaves the delivery
551
+ * UNMARKED (its per-job `markJob` entries survive), so a later retry of the
552
+ * same delivery id re-runs only what did not complete — the same partial-retry
553
+ * ledger the synchronous receiver had, minus the 4xx that used to request it.
554
+ */
555
+ async function settleDelivery(webhook, id) {
556
+ const { source, event: webhookEvent } = webhook;
557
+ try {
558
+ const context = buildWebhookContext(webhook);
559
+ const fireOptions = options.fire ?? {};
560
+ // Match FIRST, before any dispatch — matching is a pure in-memory lookup,
561
+ // so this is the earliest point the receiver knows what fired, and the
562
+ // right time to log it (RUSH-2722). Dispatching a `run.command` handler
563
+ // can then block on the shelled-out process for minutes; that must never
564
+ // hold the "fired" log back with it.
565
+ const matchedJobs = matchJobsToWebhook(fireOptions.jobs ?? listJobs(), webhook);
566
+ const matchedHandlers = listHandlers().filter((handler) => handlerMatchesWebhook(handler, webhook));
567
+ options.onMatch?.(webhook, matchedJobs.map((job) => job.name), matchedHandlers.map((handler) => handler.name));
568
+ const firedJobs = await fireWebhookJobs(webhook, {
569
+ ...fireOptions,
570
+ jobs: matchedJobs,
571
+ context,
572
+ skipJobNames: deliveryStore.completedJobs(id),
573
+ onJobFired: (job, firedJob) => {
574
+ emit('webhook.fired', { source, event: webhookEvent, deliveryId: id, jobName: job.name, runId: firedJob.runId });
575
+ deliveryStore.markJob(id, job.name);
576
+ fireOptions.onJobFired?.(job, firedJob);
577
+ },
578
+ });
579
+ const firedHandlers = [];
580
+ const handlerErrors = [];
581
+ await Promise.allSettled(matchedHandlers.map(async (handler) => {
582
+ if (deliveryStore.completedJobs(id).has(handler.name))
583
+ return;
584
+ emit('webhook.matched', { source, event: webhookEvent, deliveryId: id, handlerName: handler.name });
585
+ try {
586
+ const result = await executeHandler(handler, webhook);
587
+ deliveryStore.markJob(id, handler.name);
588
+ firedHandlers.push(result);
589
+ }
590
+ catch (err) {
591
+ handlerErrors.push({ handlerName: handler.name, error: err.message });
592
+ }
593
+ }));
594
+ deliveryStore.mark(id);
595
+ for (const failure of handlerErrors) {
596
+ emit('webhook.failed', { source, event: webhookEvent, deliveryId: id, handlerName: failure.handlerName, error: failure.error });
597
+ }
598
+ options.onDelivery?.(webhook, firedJobs, firedHandlers);
599
+ }
600
+ catch (err) {
601
+ const error = err;
602
+ emit('webhook.failed', { source, event: webhookEvent, deliveryId: id, error: error.message });
603
+ options.onDeliveryError?.(webhook, error);
604
+ }
605
+ }
435
606
  const server = http.createServer((req, res) => {
436
607
  void (async () => {
437
608
  if (req.method !== 'POST') {
@@ -475,17 +646,58 @@ export function startWebhookServer(options) {
475
646
  const rawBody = await readRawBody(req, maxBodyBytes);
476
647
  const valid = source === 'github'
477
648
  ? verifyGithubSignature(req.headers, rawBody, secret)
478
- : verifyLinearSignature(req.headers, rawBody, secret);
649
+ : source === 'linear'
650
+ ? verifyLinearSignature(req.headers, rawBody, secret)
651
+ : verifySlackSignature(req.headers, rawBody, secret);
479
652
  if (!valid) {
480
653
  emit('webhook.rejected', { source, reason: 'invalid signature' });
481
654
  res.writeHead(401, { 'content-type': 'application/json' });
482
655
  res.end(JSON.stringify({ ok: false, error: 'invalid signature' }));
483
656
  return;
484
657
  }
658
+ // Slack diverges from the GitHub/Linear JSON path: two content-types
659
+ // (slash = form, events = JSON), a one-time url_verification handshake,
660
+ // a body-carried event id, and a 200 ack Slack shows to the caller.
661
+ if (source === 'slack') {
662
+ const slack = parseSlackBody(header(req.headers, 'content-type'), rawBody);
663
+ // One-time Events API URL handshake: echo the challenge, dispatch nothing.
664
+ if (slack.type === 'url_verification') {
665
+ res.writeHead(200, { 'content-type': 'application/json' });
666
+ res.end(JSON.stringify({ challenge: slack.challenge ?? '' }));
667
+ return;
668
+ }
669
+ const slackEvent = slackEventName(slack);
670
+ // Slash commands carry no event_id, so fall back to a body hash for dedup.
671
+ const slackId = `slack:${slack.event_id ?? crypto.createHash('sha256').update(rawBody).digest('hex')}`;
672
+ emit('webhook.received', { source, event: slackEvent, deliveryId: slackId });
673
+ if (deliveryStore.seen(slackId) || inFlight.has(slackId)) {
674
+ res.writeHead(200, { 'content-type': 'application/json' });
675
+ res.end(JSON.stringify({ ok: true, duplicate: true }));
676
+ return;
677
+ }
678
+ if (!rateLimiter.take(source)) {
679
+ emit('webhook.rejected', { source, event: slackEvent, deliveryId: slackId, reason: 'rate limit exceeded' });
680
+ res.writeHead(429, { 'content-type': 'application/json' });
681
+ res.end(JSON.stringify({ ok: false, error: 'rate limit exceeded' }));
682
+ return;
683
+ }
684
+ const slackWebhook = { source, event: slackEvent, payload: slack };
685
+ emit('webhook.authorized', { source, event: slackEvent, deliveryId: slackId });
686
+ // ACK FIRST (RUSH-2548): a 200 inside Slack's 3s window. A slash
687
+ // command renders the ack text to the caller; an event delivery
688
+ // ignores the body. Dispatch outlives the ack, same as GitHub/Linear.
689
+ inFlight.add(slackId);
690
+ res.writeHead(200, { 'content-type': 'application/json' });
691
+ res.end(slack.type === 'slash_command'
692
+ ? JSON.stringify({ response_type: 'ephemeral', text: 'On it — replying in this thread.' })
693
+ : '');
694
+ void settleDelivery(slackWebhook, slackId).finally(() => inFlight.delete(slackId));
695
+ return;
696
+ }
485
697
  const id = deliveryId(source, req.headers, rawBody);
486
698
  const event = source === 'github' ? (header(req.headers, 'x-github-event') ?? '') : '';
487
699
  emit('webhook.received', { source, event, deliveryId: id });
488
- if (deliveryStore.seen(id)) {
700
+ if (deliveryStore.seen(id) || inFlight.has(id)) {
489
701
  res.writeHead(200, { 'content-type': 'application/json' });
490
702
  res.end(JSON.stringify({ ok: true, duplicate: true, fired: [] }));
491
703
  return;
@@ -510,45 +722,12 @@ export function startWebhookServer(options) {
510
722
  payload,
511
723
  };
512
724
  emit('webhook.authorized', { source, event: webhookEvent, deliveryId: id });
513
- const context = buildWebhookContext(webhook);
514
- const fireOptions = options.fire ?? {};
515
- const firedJobs = await fireWebhookJobs(webhook, {
516
- ...fireOptions,
517
- context,
518
- skipJobNames: deliveryStore.completedJobs(id),
519
- onJobFired: (job, firedJob) => {
520
- emit('webhook.fired', { source, event: webhookEvent, deliveryId: id, jobName: job.name, runId: firedJob.runId });
521
- deliveryStore.markJob(id, job.name);
522
- fireOptions.onJobFired?.(job, firedJob);
523
- },
524
- });
525
- const handlers = listHandlers();
526
- const matchedHandlers = handlers.filter((handler) => handlerMatchesWebhook(handler, webhook));
527
- const firedHandlers = [];
528
- const handlerErrors = [];
529
- await Promise.allSettled(matchedHandlers.map(async (handler) => {
530
- if (deliveryStore.completedJobs(id).has(handler.name))
531
- return;
532
- emit('webhook.matched', { source, event: webhookEvent, deliveryId: id, handlerName: handler.name });
533
- try {
534
- const result = await executeHandler(handler, webhook);
535
- deliveryStore.markJob(id, handler.name);
536
- firedHandlers.push(result);
537
- }
538
- catch (err) {
539
- handlerErrors.push({ handlerName: handler.name, error: err.message });
540
- }
541
- }));
542
- deliveryStore.mark(id);
543
- options.onDelivery?.(webhook, firedJobs, firedHandlers);
544
- res.writeHead(200, { 'content-type': 'application/json' });
545
- res.end(JSON.stringify({
546
- ok: true,
547
- fired: firedJobs.map((f) => f.jobName),
548
- runs: firedJobs,
549
- handlers: firedHandlers,
550
- ...(handlerErrors.length > 0 ? { handlerErrors } : {}),
551
- }));
725
+ // ACK FIRST (RUSH-2548). Everything that could reject this delivery has
726
+ // run; what remains starts agent runs and outlives any sender timeout.
727
+ inFlight.add(id);
728
+ res.writeHead(202, { 'content-type': 'application/json' });
729
+ res.end(JSON.stringify({ ok: true, accepted: true, deliveryId: id }));
730
+ void settleDelivery(webhook, id).finally(() => inFlight.delete(id));
552
731
  }
553
732
  catch (err) {
554
733
  res.writeHead(400, { 'content-type': 'application/json' });
@@ -790,6 +790,17 @@ export interface Meta {
790
790
  /** Preferred provider account per harness. Explicit --account wins. */
791
791
  accounts?: {
792
792
  defaults?: Partial<Record<AgentId, string>>;
793
+ /** Named harness-owned identities. Metadata only; OAuth credentials stay in the harness home. */
794
+ native?: Record<string, {
795
+ id: string;
796
+ name: string;
797
+ agent: AgentId;
798
+ identityKey: string;
799
+ identityLabel?: string;
800
+ scope: 'version' | 'device';
801
+ }>;
802
+ /** Exact installation/custom-harness target -> stable account id. */
803
+ bindings?: Record<string, string>;
793
804
  };
794
805
  agents?: Partial<Record<AgentId, string>>;
795
806
  /**
@@ -955,8 +966,9 @@ export interface Meta {
955
966
  * user-scope keys from the device-config registry (`lib/device-config.ts`) —
956
967
  * currently `interactiveHost` and `usagePrimaryHost`. Syncs fleet-wide via
957
968
  * `agents repo push/pull`.
958
- * Device-scope keys live under `fleet.devices.<name>.config` instead (see
959
- * {@link Meta.fleet}).
969
+ * Device-scope keys live in the per-device doc
970
+ * `devices/<name>/agents.yaml` `config:` block, layered over the fleet-wide
971
+ * defaults in {@link Meta.fleet} (`fleet.defaults.config`).
960
972
  */
961
973
  config?: Record<string, unknown>;
962
974
  /**
@@ -979,7 +991,7 @@ export interface Meta {
979
991
  */
980
992
  deviceConfig?: Record<string, unknown>;
981
993
  /**
982
- * Agent-host registry keyed by host name (the `--host`/`--device` dispatch overlay). Portable user
994
+ * Agent-host registry keyed by host name (the `--device` dispatch overlay). Portable user
983
995
  * config synced with `agents repo push/pull`. For `ssh-config` hosts this is
984
996
  * just an overlay (caps/os) — the connection details stay in ~/.ssh/config and
985
997
  * are never copied. `inline` hosts carry their own address/user.
@@ -989,9 +1001,9 @@ export interface Meta {
989
1001
  * Declarative fleet profile (`agents apply` / `ag apply`). Additive to the
990
1002
  * schema — project `agents:` version-pins are untouched. Declares which agents
991
1003
  * every device should have, which config to sync, and how login propagates.
992
- * `fleet.devices.<name>.config` is also the central store for per-device
993
- * operator config (`agents devices config <name>`) — the device-scope keys of
994
- * the `lib/device-config.ts` registry.
1004
+ * `fleet.defaults.config` is also the fleet-wide DEFAULTS layer of the
1005
+ * device-config store (`agents devices config --fleet <key> <value>`) — read
1006
+ * between the built-in default and the per-device doc's `config:` block.
995
1007
  * Full shape in `lib/fleet/types.ts` (FleetManifest).
996
1008
  */
997
1009
  fleet?: import('./fleet/types.js').FleetManifest;
@@ -1098,7 +1110,7 @@ export interface HostEntry {
1098
1110
  /** Browser profile definition stored in agents.yaml. */
1099
1111
  export interface BrowserProfileConfig {
1100
1112
  description?: string;
1101
- browser: 'chrome' | 'comet' | 'chromium' | 'brave' | 'edge' | 'custom';
1113
+ browser: 'chrome' | 'comet' | 'chromium' | 'brave' | 'edge' | 'arc' | 'custom';
1102
1114
  binary?: string;
1103
1115
  electron?: boolean;
1104
1116
  /**
@@ -1,5 +1,5 @@
1
1
  import { type HeadroomEntry } from './usage-refresh.js';
2
- import { type UsageWindow } from './usage.js';
2
+ import { type UsageWindow } from './accounting/usage.js';
3
3
  export declare const USAGE_FLEET_VERSION = 1;
4
4
  export declare const USAGE_FLEET_FILE = ".usage-fleet.json";
5
5
  export interface UsageFleetWindow {
@@ -13,7 +13,7 @@ import { loadDevices } from './devices/registry.js';
13
13
  import { atomicWriteFileSync } from './fs-atomic.js';
14
14
  import { getCacheDir } from './state.js';
15
15
  import { readHeadroomCache, writeHeadroomEntries, } from './usage-refresh.js';
16
- import { readClaudeUsageCache, writeClaudeUsageCache, } from './usage.js';
16
+ import { readClaudeUsageCache, writeClaudeUsageCache, } from './accounting/usage.js';
17
17
  export const USAGE_FLEET_VERSION = 1;
18
18
  export const USAGE_FLEET_FILE = '.usage-fleet.json';
19
19
  /** Publisher/subscriber role selection, kept pure for the daemon gate test. */
@@ -1,4 +1,4 @@
1
- import { type UsageHeadroom, type UsageSnapshot, type UsageInfo } from './usage.js';
1
+ import { type UsageHeadroom, type UsageSnapshot, type UsageInfo } from './accounting/usage.js';
2
2
  import type { AgentId } from './types.js';
3
3
  /**
4
4
  * Default schedule between successful (or attempted) live usage fetches for one
@@ -50,9 +50,9 @@ import * as fs from 'fs';
50
50
  import * as path from 'path';
51
51
  import { getCacheDir } from './state.js';
52
52
  import { atomicWriteFileSync, ensureLockTarget, withFileLock } from './fs-atomic.js';
53
- import { deriveUsageHeadroom, buildCanonicalUsageContext, USAGE_SOURCE_AGENT_IDS, } from './usage.js';
53
+ import { deriveUsageHeadroom, buildCanonicalUsageContext, USAGE_SOURCE_AGENT_IDS, } from './accounting/usage.js';
54
54
  import { getAccountInfo } from './agents.js';
55
- import { listInstalledVersions, getVersionHomePath } from './versions.js';
55
+ import { listInstalledVersions, getVersionHomePath } from './installations/versions.js';
56
56
  /**
57
57
  * Default schedule between successful (or attempted) live usage fetches for one
58
58
  * account. Floor and ceiling of the delay helper are pinned to this so the
@@ -202,7 +202,7 @@ export async function buildLocalUsageAccounts() {
202
202
  // only, never the interactive login (see loadClaudeOauth); no setup-token
203
203
  // reads as "usage pending".
204
204
  fetch: async () => {
205
- const { getUsageInfoForIdentity } = await import('./usage.js');
205
+ const { getUsageInfoForIdentity } = await import('./accounting/usage.js');
206
206
  return getUsageInfoForIdentity({
207
207
  agentId,
208
208
  home: fetchInput.home,
@@ -1,7 +1,7 @@
1
1
  import chalk from 'chalk';
2
2
  import { getAccountInfo, agentLabel } from './agents.js';
3
- import { compareVersions, getVersionHomePath, listInstalledVersions, } from './versions.js';
4
- import { buildCanonicalUsageContext, getUsageLookupKey, } from './usage.js';
3
+ import { compareVersions, getVersionHomePath, listInstalledVersions, } from './installations/versions.js';
4
+ import { buildCanonicalUsageContext, getUsageLookupKey, } from './accounting/usage.js';
5
5
  function duplicateIdentity(info) {
6
6
  if (!info)
7
7
  return null;
@@ -0,0 +1,56 @@
1
+ import type { ConfiguredModelSource } from './models.js';
2
+ import type { ProfileSummary } from './profiles.js';
3
+ import type { AgentId } from './types.js';
4
+ export type SyncState = 'synced' | 'new' | 'modified' | 'deleted';
5
+ export interface ViewJsonVersion {
6
+ version: string;
7
+ isDefault: boolean;
8
+ isolated: boolean;
9
+ isIsolatedDefault: boolean;
10
+ signedIn: boolean;
11
+ email: string | null;
12
+ accountId?: string | null;
13
+ organizationType?: string | null;
14
+ organizationName?: string | null;
15
+ plan: string | null;
16
+ usageStatus: 'available' | 'rate_limited' | 'out_of_credits' | null;
17
+ overageCredits?: {
18
+ amount: number;
19
+ currency: string;
20
+ } | null;
21
+ windows: Array<{
22
+ key: 'session' | 'week' | 'sonnet_week' | 'month';
23
+ label?: string;
24
+ usedPercent: number;
25
+ resetsAt: string | null;
26
+ }>;
27
+ lastActive: string | null;
28
+ path: string;
29
+ configuredModel?: {
30
+ model: string;
31
+ source: ConfiguredModelSource;
32
+ } | null;
33
+ resources?: VersionResourcesJson;
34
+ }
35
+ export interface ViewJsonAgent {
36
+ agent: AgentId;
37
+ versions: ViewJsonVersion[];
38
+ harnesses: ProfileSummary[];
39
+ }
40
+ export type ResourceSection = 'commands' | 'skills' | 'mcp' | 'memory' | 'hooks' | 'workflows' | 'plugins';
41
+ export interface ResourceItemJson {
42
+ name: string;
43
+ scope?: 'user' | 'project';
44
+ syncState?: SyncState;
45
+ description?: string;
46
+ ruleCount?: number;
47
+ }
48
+ export interface VersionResourcesJson {
49
+ commands?: ResourceItemJson[];
50
+ skills?: ResourceItemJson[];
51
+ mcp?: ResourceItemJson[];
52
+ memory?: ResourceItemJson[];
53
+ hooks?: ResourceItemJson[];
54
+ workflows?: ResourceItemJson[];
55
+ plugins?: ResourceItemJson[];
56
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -27,7 +27,7 @@
27
27
  *
28
28
  * Config: `watchdog.rotate: on|off` in agents.yaml (default on), read per tick.
29
29
  */
30
- import type { InjectTarget } from '../terminal/inject.js';
30
+ import type { InjectTarget } from '../terminal/index.js';
31
31
  import type { ActiveSession } from '../session/active.js';
32
32
  /**
33
33
  * Agent-reported hard-limit texts, matched against a session transcript tail.
@@ -78,7 +78,7 @@ export declare function exitSequenceFor(agent: string): string[];
78
78
  * host (affinity) → harness (cross-harness headroom) → account (balanced) and
79
79
  * exits nonzero when every layer is exhausted. Ported from apps/ext
80
80
  * autoRotate.ts buildAutoRotateLaunchCommand. A terminal on a REMOTE device
81
- * rotates ON that device (`--host`); a local terminal omits it. `--session-id`
81
+ * rotates ON that device (`--device`); a local terminal omits it. `--session-id`
82
82
  * is honored only when the CLI picks claude (existing claude-only semantics)
83
83
  * and ignored otherwise — passing it unconditionally keeps the terminal's
84
84
  * AGENT_SESSION_ID aligned with the session Claude actually creates.
@@ -30,7 +30,7 @@
30
30
  import * as fs from 'fs';
31
31
  import * as path from 'path';
32
32
  import { readMeta, writeMeta } from '../state.js';
33
- import { collectHarnessCandidates, classifyHarnessCandidates, pickHarnessWeighted, earliestResetAcross, formatNoHealthyHarnessError, } from '../rotate.js';
33
+ import { collectHarnessCandidates, classifyHarnessCandidates, pickHarnessWeighted, earliestResetAcross, formatNoHealthyHarnessError, } from '../accounting/rotate.js';
34
34
  import { resolveWatchdogSessionPath } from './read.js';
35
35
  // --- detection ---------------------------------------------------------------
36
36
  /**
@@ -160,7 +160,7 @@ export function exitSequenceFor(agent) {
160
160
  * host (affinity) → harness (cross-harness headroom) → account (balanced) and
161
161
  * exits nonzero when every layer is exhausted. Ported from apps/ext
162
162
  * autoRotate.ts buildAutoRotateLaunchCommand. A terminal on a REMOTE device
163
- * rotates ON that device (`--host`); a local terminal omits it. `--session-id`
163
+ * rotates ON that device (`--device`); a local terminal omits it. `--session-id`
164
164
  * is honored only when the CLI picks claude (existing claude-only semantics)
165
165
  * and ignored otherwise — passing it unconditionally keeps the terminal's
166
166
  * AGENT_SESSION_ID aligned with the session Claude actually creates.
@@ -168,7 +168,7 @@ export function exitSequenceFor(agent) {
168
168
  export function buildRotateLaunchCommand(opts) {
169
169
  let cmd = 'agents run auto --interactive';
170
170
  if (opts.host) {
171
- cmd += ` --host ${shellQuoteHost(opts.host)}`;
171
+ cmd += ` --device ${shellQuoteHost(opts.host)}`;
172
172
  }
173
173
  cmd += ` --session-id ${opts.sessionId}`;
174
174
  return cmd;
@@ -32,10 +32,9 @@
32
32
  */
33
33
  import type { ActiveSession } from '../session/active.js';
34
34
  import { type PresenceTransition } from '../session/presence.js';
35
- import { type InjectRail } from '../terminal/resolve.js';
36
- import { type InjectResult, type InjectTarget } from '../terminal/inject.js';
35
+ import { type InjectRail, type InjectResult, type InjectTarget } from '../terminal/index.js';
37
36
  import { type StallStatus, type WatchdogCandidate } from './watchdog.js';
38
- import { type OpenBlock } from '../feed.js';
37
+ import { type OpenBlock } from '../feed/feed.js';
39
38
  import { type RotateGateResult, type RotatePhase, type RotateState } from './rotate.js';
40
39
  /** Per-session policy sentinel. `keep` is the default (watchdog may nudge). */
41
40
  export type WatchdogPolicy = 'off' | 'keep' | 'handsoff';
@@ -35,8 +35,7 @@ import * as path from 'path';
35
35
  import * as crypto from 'crypto';
36
36
  import { getActiveSessions } from '../session/active.js';
37
37
  import { reconcilePresence, loadPresence, savePresence, observedFromActive, } from '../session/presence.js';
38
- import { resolveInjectTargetForSession, } from '../terminal/resolve.js';
39
- import { injectIntoTerminal } from '../terminal/inject.js';
38
+ import { resolveInjectTargetForSession, injectIntoTerminal, } from '../terminal/index.js';
40
39
  import { classifyTerminal, isLikelyTrulyBlocked, renderWatchdogPrompt, parseWatchdogResponse, } from './watchdog.js';
41
40
  import { readWatchdogTail, WATCHDOG_STALL_MS, WATCHDOG_COOLDOWN_MS, WATCHDOG_DORMANT_MS, WATCHDOG_TAIL_LINES, } from './read.js';
42
41
  import { getRuntimeStateDir } from '../state.js';
@@ -44,7 +43,7 @@ import { withFileLock, atomicWriteFileSync, ensureLockTarget } from '../fs-atomi
44
43
  import { resolveAnswerRoute, isOpenQuestionBlock } from '../answer-router.js';
45
44
  import { enqueue, mailboxDir } from '../mailbox.js';
46
45
  import { mailboxIdForActiveSession } from '../mailbox-target.js';
47
- import { readBlock, blockIdForSession, buildDeclaredBlock, publishBlock } from '../feed.js';
46
+ import { readBlock, blockIdForSession, buildDeclaredBlock, publishBlock } from '../feed/feed.js';
48
47
  import { summarizeWatchdogTail } from './watchdogTail.js';
49
48
  import { appendWatchdogEvents } from './log.js';
50
49
  import { buildRotateLaunchCommand, buildRotateReplayText, classifyTailForRotate, defaultRotateGate, defaultTuiLiveFor, exitSequenceFor, isInflightPhase, isWatchdogRotateEnabled, listInflightRotates, readRotateState, recordRotateSkip, shouldLogRotateSkip, writeRotateState, DEFAULT_ROTATE_READINESS_MS, DEFAULT_ROTATE_SKIP_COOLDOWN_MS, DEFAULT_ROTATE_FAILED_COOLDOWN_MS, } from './rotate.js';
@@ -239,7 +238,7 @@ async function deliverViaResume(session, text) {
239
238
  return { ok: false, error: 'no session id to resume' };
240
239
  try {
241
240
  const [{ getAgentsInvocation }, { spawn }] = await Promise.all([
242
- import('../daemon.js'),
241
+ import('../daemon/daemon.js'),
243
242
  import('child_process'),
244
243
  ]);
245
244
  const inv = getAgentsInvocation(['run', session.kind, '--resume', sid, '--', text]);
@@ -11,7 +11,7 @@ import * as path from 'path';
11
11
  import * as yaml from 'yaml';
12
12
  import { capableAgents, supports } from './capabilities.js';
13
13
  import { getProjectAgentsDir, getSystemWorkflowsDir, getUserWorkflowsDir, getTrashWorkflowsDir, getEnabledExtraRepos, getPluginsDir, getSystemPluginsDir, getProjectPluginsDir, } from './state.js';
14
- import { listInstalledVersions, getVersionHomePath } from './versions.js';
14
+ import { listInstalledVersions, getVersionHomePath } from './installations/versions.js';
15
15
  /**
16
16
  * Hard upper bound on items a single `for_each` expands, absent an explicit
17
17
  * `max_items`. A guard against a runaway producer spawning unbounded teammates
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Terminal word-wrap — one shared helper for the whole CLI.
3
+ *
4
+ * Multi-line word wrapping is the gap the single-line helpers in
5
+ * `session/width.ts` (`truncateToWidth`, `padToWidth`) do not fill. Anywhere that
6
+ * renders variable-length text into a fixed-width terminal wraps through THIS,
7
+ * never a per-field slice.
8
+ *
9
+ * Width is measured with `stringWidth` (from the canonical `session/width.ts`),
10
+ * NOT `String.length`: the text this wraps is routinely ANSI-coloured (chalk /
11
+ * marked-terminal output) and may carry OSC-8 hyperlinks, where `.length`
12
+ * over-counts the invisible escape bytes. Words are split on whitespace, so a
13
+ * wrap boundary always falls between escape sequences, never inside one.
14
+ */
15
+ /**
16
+ * Hard-wrap `text` to `cols` visible columns.
17
+ *
18
+ * - Splits on existing newlines first (each paragraph wraps independently).
19
+ * - Wraps on whitespace; a single word wider than the available width is emitted
20
+ * on its own line rather than split mid-word (and never mid-escape).
21
+ * - Width is the visible display width via `stringWidth`, so ANSI colour and
22
+ * OSC-8 hyperlink escapes do not inflate the count.
23
+ * - `hangingIndent` pads every line AFTER the first with that many spaces, so a
24
+ * labelled value ("Latest <text>") keeps its continuation lines aligned under
25
+ * the value. The wrapping width is `cols - indent`.
26
+ * - Floor: when `hangingIndent` is set, the width is floored at 8 so a
27
+ * pathologically large indent still makes forward progress. With no indent the
28
+ * floor is 1, so a legitimately small `cols` is respected, never overridden. A
29
+ * non-finite `cols` degrades to the floor rather than silently disabling wrap.
30
+ *
31
+ * Returns the wrapped lines (never mutates input). An empty string yields [''].
32
+ */
33
+ export declare function wrapToWidth(text: string, cols: number, hangingIndent?: number): string[];