@phnx-labs/agents-cli 1.22.38 → 1.22.40

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 (554) hide show
  1. package/CHANGELOG.md +302 -0
  2. package/README.md +111 -70
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.js +46 -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 +260 -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.js +206 -94
  13. package/dist/commands/budget.d.ts +7 -6
  14. package/dist/commands/budget.js +8 -7
  15. package/dist/commands/cloud.js +17 -20
  16. package/dist/commands/commands.js +1 -1
  17. package/dist/commands/computer-actions.d.ts +1 -35
  18. package/dist/commands/computer-actions.js +13 -181
  19. package/dist/commands/computer.d.ts +28 -3
  20. package/dist/commands/computer.js +93 -65
  21. package/dist/commands/config.js +47 -4
  22. package/dist/commands/cost.d.ts +2 -1
  23. package/dist/commands/cost.js +7 -6
  24. package/dist/commands/daemon.js +151 -4
  25. package/dist/commands/detach.js +1 -1
  26. package/dist/commands/doctor.js +19 -11
  27. package/dist/commands/events.js +1 -1
  28. package/dist/commands/exec.d.ts +2 -50
  29. package/dist/commands/exec.js +161 -216
  30. package/dist/commands/factory.js +1 -1
  31. package/dist/commands/feed.d.ts +2 -2
  32. package/dist/commands/feed.js +9 -12
  33. package/dist/commands/fleet-capture.js +25 -27
  34. package/dist/commands/focus.d.ts +2 -3
  35. package/dist/commands/focus.js +34 -9
  36. package/dist/commands/go.js +15 -5
  37. package/dist/commands/harness.d.ts +3 -3
  38. package/dist/commands/harness.js +53 -5
  39. package/dist/commands/hooks.js +1 -1
  40. package/dist/commands/import.js +2 -2
  41. package/dist/commands/insights.d.ts +5 -5
  42. package/dist/commands/insights.js +15 -9
  43. package/dist/commands/inspect.d.ts +2 -3
  44. package/dist/commands/inspect.js +4 -16
  45. package/dist/commands/logs.d.ts +2 -2
  46. package/dist/commands/logs.js +9 -9
  47. package/dist/commands/mcp.js +2 -2
  48. package/dist/commands/memory.js +1 -1
  49. package/dist/commands/message.d.ts +1 -1
  50. package/dist/commands/message.js +7 -7
  51. package/dist/commands/mine.d.ts +11 -8
  52. package/dist/commands/mine.js +11 -10
  53. package/dist/commands/models.js +1 -1
  54. package/dist/commands/modes.js +1 -1
  55. package/dist/commands/monitors.js +23 -6
  56. package/dist/commands/output.d.ts +7 -6
  57. package/dist/commands/output.js +11 -10
  58. package/dist/commands/packages.js +4 -4
  59. package/dist/commands/perf.js +1 -1
  60. package/dist/commands/permissions.js +49 -32
  61. package/dist/commands/plugins.d.ts +1 -1
  62. package/dist/commands/plugins.js +3 -3
  63. package/dist/commands/profiles.d.ts +6 -9
  64. package/dist/commands/profiles.js +8 -321
  65. package/dist/commands/projects.d.ts +9 -0
  66. package/dist/commands/projects.js +140 -8
  67. package/dist/commands/prune.js +5 -13
  68. package/dist/commands/refresh-rules.js +1 -1
  69. package/dist/commands/repo.d.ts +5 -7
  70. package/dist/commands/repo.js +34 -18
  71. package/dist/commands/resource-view.js +4 -0
  72. package/dist/commands/resume.d.ts +11 -7
  73. package/dist/commands/resume.js +82 -98
  74. package/dist/commands/route.d.ts +12 -0
  75. package/dist/commands/route.js +261 -0
  76. package/dist/commands/routines.d.ts +2 -3
  77. package/dist/commands/routines.js +120 -145
  78. package/dist/commands/rules.js +1 -1
  79. package/dist/commands/run-account-picker.d.ts +1 -1
  80. package/dist/commands/run-account-picker.js +2 -2
  81. package/dist/commands/run-broadcast.d.ts +21 -0
  82. package/dist/commands/run-broadcast.js +89 -0
  83. package/dist/commands/run-cloud.js +1 -1
  84. package/dist/commands/secrets-vault.d.ts +10 -0
  85. package/dist/commands/{login.js → secrets-vault.js} +34 -14
  86. package/dist/commands/secrets.d.ts +4 -4
  87. package/dist/commands/secrets.js +72 -63
  88. package/dist/commands/sessions-backfill.js +1 -1
  89. package/dist/commands/sessions-browser.d.ts +1 -1
  90. package/dist/commands/sessions-browser.js +9 -5
  91. package/dist/commands/sessions-export.js +2 -2
  92. package/dist/commands/sessions-inject.js +4 -5
  93. package/dist/commands/sessions-migrate.js +16 -27
  94. package/dist/commands/sessions-picker.d.ts +13 -0
  95. package/dist/commands/sessions-picker.js +182 -8
  96. package/dist/commands/sessions-resume.d.ts +7 -3
  97. package/dist/commands/sessions-resume.js +81 -33
  98. package/dist/commands/sessions-stats.js +2 -2
  99. package/dist/commands/sessions.d.ts +75 -68
  100. package/dist/commands/sessions.js +142 -180
  101. package/dist/commands/setup-computer.js +1 -1
  102. package/dist/commands/setup-fleet.js +3 -0
  103. package/dist/commands/setup-mine.d.ts +7 -3
  104. package/dist/commands/setup-mine.js +13 -8
  105. package/dist/commands/setup-secrets.js +2 -2
  106. package/dist/commands/setup-watchdog.js +2 -2
  107. package/dist/commands/setup.js +7 -2
  108. package/dist/commands/share.d.ts +65 -0
  109. package/dist/commands/share.js +253 -20
  110. package/dist/commands/skills.js +3 -3
  111. package/dist/commands/snapshot.d.ts +2 -2
  112. package/dist/commands/snapshot.js +9 -9
  113. package/dist/commands/ssh.d.ts +1 -1
  114. package/dist/commands/ssh.js +318 -48
  115. package/dist/commands/subagents.js +1 -1
  116. package/dist/commands/sync.js +24 -9
  117. package/dist/commands/teams.d.ts +2 -2
  118. package/dist/commands/teams.js +9 -18
  119. package/dist/commands/tmux.js +5 -1
  120. package/dist/commands/trash.js +1 -1
  121. package/dist/commands/usage.d.ts +1 -1
  122. package/dist/commands/usage.js +2 -2
  123. package/dist/commands/utils.d.ts +4 -14
  124. package/dist/commands/utils.js +6 -27
  125. package/dist/commands/versions.js +2 -2
  126. package/dist/commands/view.d.ts +9 -77
  127. package/dist/commands/view.js +23 -8
  128. package/dist/commands/watchdog.js +1 -1
  129. package/dist/commands/webhook.js +11 -25
  130. package/dist/commands/workflows.js +1 -1
  131. package/dist/index.js +1 -1
  132. package/dist/lib/account-capabilities.d.ts +39 -0
  133. package/dist/lib/account-capabilities.js +59 -0
  134. package/dist/lib/account-catalog.js +1 -1
  135. package/dist/lib/account-registry.d.ts +66 -0
  136. package/dist/lib/account-registry.js +151 -5
  137. package/dist/lib/{rotate.d.ts → accounting/rotate.d.ts} +4 -4
  138. package/dist/lib/{rotate.js → accounting/rotate.js} +8 -8
  139. package/dist/lib/{usage.d.ts → accounting/usage.d.ts} +4 -4
  140. package/dist/lib/{usage.js → accounting/usage.js} +11 -11
  141. package/dist/lib/agent-spec/provider.js +1 -1
  142. package/dist/lib/agents.d.ts +72 -4
  143. package/dist/lib/agents.js +231 -199
  144. package/dist/lib/answer-router.d.ts +2 -2
  145. package/dist/lib/ask-classifier.d.ts +1 -1
  146. package/dist/lib/ask-classifier.js +1 -1
  147. package/dist/lib/audit/log.js +1 -1
  148. package/dist/lib/auth-health.d.ts +1 -1
  149. package/dist/lib/auth-health.js +2 -2
  150. package/dist/lib/brand.js +1 -1
  151. package/dist/lib/browser/caller-identity.d.ts +28 -0
  152. package/dist/lib/browser/caller-identity.js +156 -0
  153. package/dist/lib/browser/cdp.js +1 -1
  154. package/dist/lib/browser/drivers/ssh.d.ts +1 -1
  155. package/dist/lib/browser/drivers/ssh.js +2 -2
  156. package/dist/lib/browser/hygiene.d.ts +10 -2
  157. package/dist/lib/browser/hygiene.js +7 -4
  158. package/dist/lib/browser/ipc.d.ts +22 -2
  159. package/dist/lib/browser/ipc.js +185 -21
  160. package/dist/lib/browser/profiles.d.ts +67 -3
  161. package/dist/lib/browser/profiles.js +129 -7
  162. package/dist/lib/browser/remote-control.d.ts +2 -2
  163. package/dist/lib/browser/remote-control.js +3 -3
  164. package/dist/lib/browser/runtime-state.d.ts +79 -0
  165. package/dist/lib/browser/runtime-state.js +119 -1
  166. package/dist/lib/browser/service.d.ts +113 -1
  167. package/dist/lib/browser/service.js +454 -40
  168. package/dist/lib/browser/sessions-list.d.ts +2 -1
  169. package/dist/lib/browser/sessions-list.js +4 -13
  170. package/dist/lib/browser/types.d.ts +18 -0
  171. package/dist/lib/budget/config.js +1 -1
  172. package/dist/lib/budget/ledger.js +1 -1
  173. package/dist/lib/byok-usage.js +1 -1
  174. package/dist/lib/capabilities.js +3 -15
  175. package/dist/lib/catchup.d.ts +1 -1
  176. package/dist/lib/catchup.js +1 -1
  177. package/dist/lib/cloud/dispatch.js +1 -1
  178. package/dist/lib/cloud/host.d.ts +3 -3
  179. package/dist/lib/cloud/host.js +5 -5
  180. package/dist/lib/cloud/rush.d.ts +9 -21
  181. package/dist/lib/cloud/rush.js +33 -120
  182. package/dist/lib/cloud/types.d.ts +2 -2
  183. package/dist/lib/commands.js +3 -13
  184. package/dist/lib/computer/actions.d.ts +36 -0
  185. package/dist/lib/computer/actions.js +162 -0
  186. package/dist/lib/computer/dispatch.d.ts +2 -2
  187. package/dist/lib/computer/dispatch.js +2 -2
  188. package/dist/lib/computer/sessions-list.d.ts +3 -3
  189. package/dist/lib/computer/sessions-list.js +2 -2
  190. package/dist/lib/config-keys.d.ts +12 -3
  191. package/dist/lib/config-keys.js +29 -6
  192. package/dist/lib/config-machine-keys.d.ts +4 -2
  193. package/dist/lib/config-machine-keys.js +6 -2
  194. package/dist/lib/crabbox/lease.js +9 -1
  195. package/dist/lib/crabbox/runtimes.d.ts +32 -7
  196. package/dist/lib/crabbox/runtimes.js +72 -30
  197. package/dist/lib/{daemon.d.ts → daemon/daemon.d.ts} +59 -1
  198. package/dist/lib/{daemon.js → daemon/daemon.js} +237 -49
  199. package/dist/lib/daemon-services.d.ts +1 -1
  200. package/dist/lib/daemon-services.js +5 -0
  201. package/dist/lib/daemon-ticks.d.ts +25 -0
  202. package/dist/lib/daemon-ticks.js +31 -1
  203. package/dist/lib/daemon-webhooks.d.ts +102 -0
  204. package/dist/lib/daemon-webhooks.js +210 -0
  205. package/dist/lib/device-config.d.ts +116 -72
  206. package/dist/lib/device-config.js +366 -132
  207. package/dist/lib/devices/config-migration.d.ts +29 -34
  208. package/dist/lib/devices/config-migration.js +209 -130
  209. package/dist/lib/devices/connect.d.ts +2 -2
  210. package/dist/lib/devices/connect.js +2 -2
  211. package/dist/lib/devices/discovery-policy.d.ts +30 -0
  212. package/dist/lib/devices/discovery-policy.js +101 -0
  213. package/dist/lib/devices/fleet-inventory.js +8 -3
  214. package/dist/lib/devices/harness-inventory.d.ts +1 -1
  215. package/dist/lib/devices/harness-inventory.js +12 -3
  216. package/dist/lib/devices/known-hosts.js +1 -1
  217. package/dist/lib/devices/pool.d.ts +61 -0
  218. package/dist/lib/devices/pool.js +83 -0
  219. package/dist/lib/devices/registry.d.ts +1 -1
  220. package/dist/lib/devices/registry.js +1 -1
  221. package/dist/lib/devices/resolve-profile.d.ts +2 -2
  222. package/dist/lib/devices/resolve-profile.js +2 -2
  223. package/dist/lib/devices/resolve-target.d.ts +1 -1
  224. package/dist/lib/devices/resolve-target.js +4 -4
  225. package/dist/lib/devices/self-host.d.ts +1 -1
  226. package/dist/lib/devices/self-host.js +3 -3
  227. package/dist/lib/devices/ssh-config.d.ts +1 -1
  228. package/dist/lib/devices/stats-cache.js +1 -1
  229. package/dist/lib/devices/sync.d.ts +3 -1
  230. package/dist/lib/devices/sync.js +3 -3
  231. package/dist/lib/doctor-diff.js +4 -4
  232. package/dist/lib/drift-sync.js +2 -2
  233. package/dist/lib/drift.js +2 -2
  234. package/dist/lib/event-families.d.ts +1 -1
  235. package/dist/lib/event-stream.d.ts +1 -1
  236. package/dist/lib/event-stream.js +2 -2
  237. package/dist/lib/events-ingest.js +2 -2
  238. package/dist/lib/exec.d.ts +8 -5
  239. package/dist/lib/exec.js +19 -13
  240. package/dist/lib/factory/snapshot.d.ts +1 -1
  241. package/dist/lib/factory/snapshot.js +1 -1
  242. package/dist/lib/{activity.d.ts → feed/activity.d.ts} +1 -1
  243. package/dist/lib/{activity.js → feed/activity.js} +7 -7
  244. package/dist/lib/{events.d.ts → feed/events.d.ts} +2 -2
  245. package/dist/lib/{events.js → feed/events.js} +5 -5
  246. package/dist/lib/{feed.js → feed/feed.js} +4 -4
  247. package/dist/lib/feed-outcome.d.ts +1 -1
  248. package/dist/lib/feed-policy.d.ts +1 -1
  249. package/dist/lib/feed-policy.js +1 -1
  250. package/dist/lib/feed-post.d.ts +1 -1
  251. package/dist/lib/feed-post.js +1 -1
  252. package/dist/lib/feed-ranking.d.ts +1 -1
  253. package/dist/lib/fleet/apply.d.ts +0 -6
  254. package/dist/lib/fleet/apply.js +18 -45
  255. package/dist/lib/fleet/auth-sync.d.ts +16 -35
  256. package/dist/lib/fleet/auth-sync.js +16 -75
  257. package/dist/lib/fleet/capture.js +8 -6
  258. package/dist/lib/fleet/manifest.js +23 -11
  259. package/dist/lib/fleet/types.d.ts +19 -7
  260. package/dist/lib/fleet-cache.d.ts +1 -1
  261. package/dist/lib/fleet-cache.js +1 -1
  262. package/dist/lib/format.d.ts +19 -0
  263. package/dist/lib/format.js +44 -1
  264. package/dist/lib/friction-heuristics.d.ts +1 -1
  265. package/dist/lib/git.d.ts +24 -1
  266. package/dist/lib/git.js +82 -38
  267. package/dist/lib/heal.js +3 -3
  268. package/dist/lib/hooks.d.ts +18 -0
  269. package/dist/lib/hooks.js +113 -1
  270. package/dist/lib/hosts/credentials.d.ts +30 -10
  271. package/dist/lib/hosts/credentials.js +38 -26
  272. package/dist/lib/hosts/dispatch.d.ts +3 -3
  273. package/dist/lib/hosts/dispatch.js +3 -3
  274. package/dist/lib/hosts/option.d.ts +3 -3
  275. package/dist/lib/hosts/option.js +7 -8
  276. package/dist/lib/hosts/passthrough.d.ts +17 -17
  277. package/dist/lib/hosts/passthrough.js +67 -50
  278. package/dist/lib/hosts/providers/devices.d.ts +1 -1
  279. package/dist/lib/hosts/providers/devices.js +1 -1
  280. package/dist/lib/hosts/reconcile.d.ts +1 -1
  281. package/dist/lib/hosts/reconcile.js +1 -1
  282. package/dist/lib/hosts/reconnect.d.ts +1 -1
  283. package/dist/lib/hosts/reconnect.js +2 -2
  284. package/dist/lib/hosts/registry.d.ts +5 -5
  285. package/dist/lib/hosts/registry.js +5 -5
  286. package/dist/lib/hosts/remote-cmd.d.ts +10 -10
  287. package/dist/lib/hosts/remote-cmd.js +25 -18
  288. package/dist/lib/hosts/remote-os.d.ts +4 -4
  289. package/dist/lib/hosts/remote-os.js +4 -4
  290. package/dist/lib/hosts/remote-session-id.d.ts +2 -2
  291. package/dist/lib/hosts/remote-session-id.js +2 -2
  292. package/dist/lib/hosts/routing-flag.d.ts +3 -3
  293. package/dist/lib/hosts/routing-flag.js +4 -5
  294. package/dist/lib/hosts/run-target.d.ts +4 -4
  295. package/dist/lib/hosts/run-target.js +4 -4
  296. package/dist/lib/hosts/session-index.d.ts +2 -2
  297. package/dist/lib/hosts/session-index.js +1 -1
  298. package/dist/lib/hosts/session-marker.d.ts +1 -1
  299. package/dist/lib/hosts/session-marker.js +1 -1
  300. package/dist/lib/hosts/types.d.ts +2 -2
  301. package/dist/lib/hosts/types.js +2 -2
  302. package/dist/lib/import.js +1 -1
  303. package/dist/lib/{migrate.d.ts → installations/migrate.d.ts} +49 -1
  304. package/dist/lib/{migrate.js → installations/migrate.js} +265 -38
  305. package/dist/lib/installations/resolve.js +1 -1
  306. package/dist/lib/installations/strategies.js +1 -1
  307. package/dist/lib/installations/update.js +2 -2
  308. package/dist/lib/{versions.d.ts → installations/versions.d.ts} +12 -3
  309. package/dist/lib/{versions.js → installations/versions.js} +51 -31
  310. package/dist/lib/isolation-boundary-report.js +1 -1
  311. package/dist/lib/linear-projects.d.ts +28 -0
  312. package/dist/lib/linear-projects.js +30 -0
  313. package/dist/lib/loop.js +1 -1
  314. package/dist/lib/mailbox-gc.js +1 -1
  315. package/dist/lib/mailbox.js +1 -1
  316. package/dist/lib/mcp-registry.d.ts +62 -0
  317. package/dist/lib/mcp-registry.js +177 -0
  318. package/dist/lib/mcp.d.ts +5 -0
  319. package/dist/lib/mcp.js +124 -307
  320. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  321. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  322. package/dist/lib/menubar/install-menubar.d.ts +7 -0
  323. package/dist/lib/menubar/install-menubar.js +24 -6
  324. package/dist/lib/menubar/snapshot.d.ts +7 -0
  325. package/dist/lib/menubar/snapshot.js +8 -6
  326. package/dist/lib/models.js +1 -1
  327. package/dist/lib/monitors/config.d.ts +12 -0
  328. package/dist/lib/monitors/config.js +3 -0
  329. package/dist/lib/monitors/dispatch.js +26 -5
  330. package/dist/lib/monitors/engine.js +10 -0
  331. package/dist/lib/monitors/sources/webhook.d.ts +1 -1
  332. package/dist/lib/monitors/state.d.ts +42 -0
  333. package/dist/lib/monitors/state.js +30 -0
  334. package/dist/lib/notify.d.ts +1 -1
  335. package/dist/lib/observe-aliases.d.ts +2 -2
  336. package/dist/lib/observe-aliases.js +2 -11
  337. package/dist/lib/output/git-output.js +2 -2
  338. package/dist/lib/overdue.d.ts +1 -1
  339. package/dist/lib/overdue.js +1 -1
  340. package/dist/lib/permissions-registry.d.ts +65 -0
  341. package/dist/lib/permissions-registry.js +599 -0
  342. package/dist/lib/permissions.d.ts +24 -13
  343. package/dist/lib/permissions.js +52 -271
  344. package/dist/lib/picker.d.ts +16 -0
  345. package/dist/lib/picker.js +33 -3
  346. package/dist/lib/placement.d.ts +1 -1
  347. package/dist/lib/placement.js +4 -4
  348. package/dist/lib/platform/paths.d.ts +8 -0
  349. package/dist/lib/platform/paths.js +11 -0
  350. package/dist/lib/platform/posixpath.js +3 -3
  351. package/dist/lib/{plugin-marketplace.d.ts → plugins/plugin-marketplace.d.ts} +1 -1
  352. package/dist/lib/{plugin-marketplace.js → plugins/plugin-marketplace.js} +2 -2
  353. package/dist/lib/{plugins.d.ts → plugins/plugins.d.ts} +1 -1
  354. package/dist/lib/{plugins.js → plugins/plugins.js} +7 -7
  355. package/dist/lib/{skills.d.ts → plugins/skills.d.ts} +1 -1
  356. package/dist/lib/{skills.js → plugins/skills.js} +7 -7
  357. package/dist/lib/pricing/cost.d.ts +1 -1
  358. package/dist/lib/pricing/cost.js +1 -1
  359. package/dist/lib/profiles-presets.d.ts +1 -1
  360. package/dist/lib/profiles-presets.js +1 -1
  361. package/dist/lib/profiles.js +2 -2
  362. package/dist/lib/project-import.js +4 -1
  363. package/dist/lib/project-launch.d.ts +1 -1
  364. package/dist/lib/project-launch.js +3 -3
  365. package/dist/lib/project-pull.d.ts +128 -0
  366. package/dist/lib/project-pull.js +384 -0
  367. package/dist/lib/project-root.d.ts +2 -2
  368. package/dist/lib/project-root.js +2 -2
  369. package/dist/lib/project-status.js +1 -1
  370. package/dist/lib/projects.d.ts +23 -0
  371. package/dist/lib/projects.js +29 -6
  372. package/dist/lib/refresh.d.ts +12 -1
  373. package/dist/lib/refresh.js +16 -9
  374. package/dist/lib/registry.d.ts +9 -2
  375. package/dist/lib/registry.js +11 -4
  376. package/dist/lib/resources.d.ts +2 -2
  377. package/dist/lib/resources.js +2 -2
  378. package/dist/lib/routers.d.ts +81 -0
  379. package/dist/lib/routers.js +153 -0
  380. package/dist/lib/routine-context.d.ts +1 -0
  381. package/dist/lib/routine-context.js +7 -2
  382. package/dist/lib/routine-notify-owner.d.ts +1 -1
  383. package/dist/lib/routine-notify.d.ts +1 -1
  384. package/dist/lib/routine-notify.js +1 -1
  385. package/dist/lib/routine-process-cleanup.d.ts +1 -1
  386. package/dist/lib/routine-readiness.d.ts +1 -1
  387. package/dist/lib/routine-readiness.js +11 -4
  388. package/dist/lib/routines-placement.d.ts +12 -2
  389. package/dist/lib/routines-placement.js +20 -3
  390. package/dist/lib/routines-project.d.ts +1 -1
  391. package/dist/lib/routines-project.js +1 -1
  392. package/dist/lib/rules/compile.d.ts +1 -0
  393. package/dist/lib/rules/compile.js +10 -2
  394. package/dist/lib/rules/rules.js +1 -1
  395. package/dist/lib/run-notify.js +1 -1
  396. package/dist/lib/runner.d.ts +80 -2
  397. package/dist/lib/runner.js +241 -62
  398. package/dist/lib/sandbox.d.ts +1 -1
  399. package/dist/lib/scheduler.d.ts +1 -1
  400. package/dist/lib/scheduler.js +1 -1
  401. package/dist/lib/{routines.d.ts → scheduling/routines.d.ts} +54 -9
  402. package/dist/lib/{routines.js → scheduling/routines.js} +173 -14
  403. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  404. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  405. package/dist/lib/secrets/agent.js +2 -2
  406. package/dist/lib/secrets/audit.js +1 -1
  407. package/dist/lib/secrets/bundles.d.ts +3 -3
  408. package/dist/lib/secrets/bundles.js +7 -7
  409. package/dist/lib/secrets/index.js +1 -1
  410. package/dist/lib/secrets/list-filter.d.ts +1 -1
  411. package/dist/lib/secrets/list-filter.js +2 -2
  412. package/dist/lib/secrets/push.d.ts +1 -1
  413. package/dist/lib/secrets/push.js +10 -12
  414. package/dist/lib/secrets/remote.d.ts +12 -10
  415. package/dist/lib/secrets/remote.js +21 -14
  416. package/dist/lib/secrets/vault.js +2 -2
  417. package/dist/lib/self-heal/checks/shadowing.js +1 -1
  418. package/dist/lib/self-heal/checks/shims.js +1 -1
  419. package/dist/lib/self-update.d.ts +39 -4
  420. package/dist/lib/self-update.js +78 -25
  421. package/dist/lib/serve/control.d.ts +1 -1
  422. package/dist/lib/serve/control.js +4 -4
  423. package/dist/lib/serve/data.d.ts +1 -1
  424. package/dist/lib/serve/data.js +1 -1
  425. package/dist/lib/serve/stream.js +1 -1
  426. package/dist/lib/service-manifest.d.ts +29 -0
  427. package/dist/lib/service-manifest.js +80 -0
  428. package/dist/lib/session/active.d.ts +59 -7
  429. package/dist/lib/session/active.js +158 -17
  430. package/dist/lib/session/bash-command.js +1 -1
  431. package/dist/lib/session/claude-accounts.d.ts +1 -1
  432. package/dist/lib/session/claude-accounts.js +1 -1
  433. package/dist/lib/session/db.d.ts +10 -2
  434. package/dist/lib/session/db.js +25 -6
  435. package/dist/lib/session/discover.d.ts +77 -0
  436. package/dist/lib/session/discover.js +130 -25
  437. package/dist/lib/session/fork.js +1 -1
  438. package/dist/lib/session/inject.d.ts +1 -1
  439. package/dist/lib/session/insights.d.ts +1 -1
  440. package/dist/lib/session/insights.js +1 -1
  441. package/dist/lib/session/live-metadata.d.ts +15 -0
  442. package/dist/lib/session/live-metadata.js +76 -0
  443. package/dist/lib/session/migrate-targets.d.ts +1 -1
  444. package/dist/lib/session/recovery.d.ts +1 -1
  445. package/dist/lib/session/recovery.js +2 -2
  446. package/dist/lib/session/remote-active.d.ts +10 -1
  447. package/dist/lib/session/remote-active.js +8 -3
  448. package/dist/lib/session/remote-bundle.d.ts +1 -1
  449. package/dist/lib/session/remote-bundle.js +2 -2
  450. package/dist/lib/session/remote-list.d.ts +15 -4
  451. package/dist/lib/session/remote-list.js +40 -3
  452. package/dist/lib/session/remote.d.ts +5 -5
  453. package/dist/lib/session/remote.js +13 -17
  454. package/dist/lib/session/resume-command.d.ts +3 -2
  455. package/dist/lib/session/resume-command.js +4 -3
  456. package/dist/lib/session/resume-owner.d.ts +3 -3
  457. package/dist/lib/session/resume-owner.js +3 -3
  458. package/dist/lib/session/session-cache.d.ts +12 -0
  459. package/dist/lib/session/session-cache.js +2 -0
  460. package/dist/lib/session/shell-programs.js +1 -1
  461. package/dist/lib/session/state.js +5 -5
  462. package/dist/lib/session/team-filter.d.ts +1 -1
  463. package/dist/lib/session/team-filter.js +1 -1
  464. package/dist/lib/session/types.d.ts +3 -3
  465. package/dist/lib/session/width.d.ts +2 -2
  466. package/dist/lib/session/width.js +2 -2
  467. package/dist/lib/share/delete.d.ts +21 -0
  468. package/dist/lib/share/delete.js +42 -0
  469. package/dist/lib/share/publish.d.ts +82 -0
  470. package/dist/lib/share/publish.js +170 -18
  471. package/dist/lib/share/worker-template.js +172 -9
  472. package/dist/lib/shims.js +35 -7
  473. package/dist/lib/smart-launch.d.ts +36 -6
  474. package/dist/lib/smart-launch.js +65 -8
  475. package/dist/lib/snapshot.d.ts +4 -4
  476. package/dist/lib/snapshot.js +2 -2
  477. package/dist/lib/ssh-exec.d.ts +1 -1
  478. package/dist/lib/ssh-exec.js +2 -2
  479. package/dist/lib/ssh-tunnel.d.ts +10 -10
  480. package/dist/lib/ssh-tunnel.js +12 -12
  481. package/dist/lib/staleness/checkers/hooks.d.ts +1 -1
  482. package/dist/lib/staleness/checkers/hooks.js +1 -1
  483. package/dist/lib/staleness/detectors/permissions.js +0 -23
  484. package/dist/lib/staleness/detectors/plugins.js +1 -1
  485. package/dist/lib/staleness/fingerprint.js +1 -1
  486. package/dist/lib/staleness/layers.d.ts +1 -1
  487. package/dist/lib/staleness/layers.js +1 -1
  488. package/dist/lib/staleness/writers/mcp.js +3 -1
  489. package/dist/lib/staleness/writers/plugins.js +1 -1
  490. package/dist/lib/staleness/writers/types.d.ts +8 -0
  491. package/dist/lib/startup/command-registry.d.ts +5 -147
  492. package/dist/lib/startup/command-registry.js +38 -303
  493. package/dist/lib/startup/dev-build.d.ts +0 -21
  494. package/dist/lib/startup/dev-build.js +29 -8
  495. package/dist/lib/state.d.ts +19 -1
  496. package/dist/lib/state.js +120 -51
  497. package/dist/lib/subagents.js +1 -1
  498. package/dist/lib/sync-status.js +1 -1
  499. package/dist/lib/sync-umbrella.d.ts +6 -1
  500. package/dist/lib/sync-umbrella.js +9 -4
  501. package/dist/lib/teams/agents.js +2 -2
  502. package/dist/lib/teams/registry.js +1 -1
  503. package/dist/lib/terminal/backends/vscodium-agent.js +1 -1
  504. package/dist/lib/terminal/engine.js +1 -1
  505. package/dist/lib/terminal/index.d.ts +4 -0
  506. package/dist/lib/terminal/index.js +3 -0
  507. package/dist/lib/terminal/inject.d.ts +2 -2
  508. package/dist/lib/terminal/inject.js +2 -2
  509. package/dist/lib/terminal/transport.js +1 -1
  510. package/dist/lib/tmux/index.d.ts +1 -1
  511. package/dist/lib/tmux/index.js +1 -1
  512. package/dist/lib/tmux/session.d.ts +21 -5
  513. package/dist/lib/tmux/session.js +76 -22
  514. package/dist/lib/triggers/handlers.d.ts +1 -1
  515. package/dist/lib/triggers/handlers.js +2 -2
  516. package/dist/lib/triggers/webhook.d.ts +36 -2
  517. package/dist/lib/triggers/webhook.js +97 -42
  518. package/dist/lib/types.d.ts +18 -6
  519. package/dist/lib/usage-fleet.d.ts +1 -1
  520. package/dist/lib/usage-fleet.js +1 -1
  521. package/dist/lib/usage-refresh.d.ts +1 -1
  522. package/dist/lib/usage-refresh.js +3 -3
  523. package/dist/lib/version-duplicates.js +2 -2
  524. package/dist/lib/view-types.d.ts +56 -0
  525. package/dist/lib/view-types.js +1 -0
  526. package/dist/lib/watchdog/rotate.d.ts +2 -2
  527. package/dist/lib/watchdog/rotate.js +3 -3
  528. package/dist/lib/watchdog/runner.d.ts +2 -3
  529. package/dist/lib/watchdog/runner.js +3 -4
  530. package/dist/lib/workflows.js +1 -1
  531. package/package.json +2 -1
  532. package/scripts/postinstall.js +2 -2
  533. package/dist/commands/bench.d.ts +0 -2
  534. package/dist/commands/bench.js +0 -101
  535. package/dist/commands/cp.d.ts +0 -84
  536. package/dist/commands/cp.js +0 -231
  537. package/dist/commands/login.d.ts +0 -2
  538. package/dist/lib/resources/commands.d.ts +0 -46
  539. package/dist/lib/resources/commands.js +0 -211
  540. package/dist/lib/resources/hooks.d.ts +0 -16
  541. package/dist/lib/resources/hooks.js +0 -153
  542. package/dist/lib/resources/mcp.d.ts +0 -34
  543. package/dist/lib/resources/mcp.js +0 -250
  544. package/dist/lib/resources/memory.d.ts +0 -15
  545. package/dist/lib/resources/memory.js +0 -46
  546. package/dist/lib/resources/permissions.d.ts +0 -13
  547. package/dist/lib/resources/permissions.js +0 -202
  548. package/dist/lib/resources/rules.d.ts +0 -46
  549. package/dist/lib/resources/rules.js +0 -179
  550. package/dist/lib/resources/skills.d.ts +0 -37
  551. package/dist/lib/resources/skills.js +0 -247
  552. package/dist/lib/resources/subagents.d.ts +0 -46
  553. package/dist/lib/resources/subagents.js +0 -202
  554. /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,7 +5,7 @@
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
10
  import type { IncomingWebhook, WebhookSource } from './webhook.js';
11
11
  export interface WebhookHandler {
@@ -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,
@@ -13,7 +13,7 @@
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
18
  export type WebhookSource = 'github' | 'linear';
19
19
  export interface IncomingWebhook {
@@ -123,6 +123,15 @@ export interface RateLimiter {
123
123
  take(key: string): boolean;
124
124
  }
125
125
  export declare function createMemoryRateLimiter(limit: number, windowMs: number): RateLimiter;
126
+ /**
127
+ * Resolve once a receiver is actually accepting connections, REJECT if the bind
128
+ * failed. `server.listen()` reports a bind failure (EADDRINUSE, EACCES) as an
129
+ * asynchronous `'error'` event, never a throw — so a `try/catch` around
130
+ * `startWebhookServer` cannot see it, and without this the event reaches Node's
131
+ * default handler and takes the whole process down. Every caller that hosts a
132
+ * receiver MUST await this rather than assuming the return means "bound".
133
+ */
134
+ export declare function waitForListening(server: http.Server): Promise<void>;
126
135
  /** Options for the local webhook http listener. */
127
136
  export interface WebhookServerOptions {
128
137
  port?: number;
@@ -131,8 +140,19 @@ export interface WebhookServerOptions {
131
140
  secrets: WebhookSecrets;
132
141
  /** Override the fire options (mainly for tests). */
133
142
  fire?: FireWebhookOptions;
134
- /** Called after each delivery is handled (mainly for tests/observability). */
143
+ /**
144
+ * Called after a delivery has fully settled — every matched routine and
145
+ * handler dispatched. Because the receiver acks the HTTP response BEFORE
146
+ * dispatch (see `startWebhookServer`), this fires strictly after the response
147
+ * has been written, and is the only way a caller observes the outcome.
148
+ */
135
149
  onDelivery?: (webhook: IncomingWebhook, fired: FiredJob[], handlers: FiredHandler[]) => void;
150
+ /**
151
+ * Called when settling an already-acked delivery threw. The HTTP status can
152
+ * no longer carry the failure, so this is the loud path — the daemon host and
153
+ * `agents webhooks serve` both log it. Never swallowed silently.
154
+ */
155
+ onDeliveryError?: (webhook: IncomingWebhook, error: Error) => void;
136
156
  deliveryStore?: DeliveryStore;
137
157
  rateLimiter?: RateLimiter;
138
158
  rateLimitPerMinute?: number;
@@ -149,6 +169,20 @@ export interface WebhookServerOptions {
149
169
  * POST /hooks/github with X-Hub-Signature-256
150
170
  * POST /hooks/linear with Linear-Signature + fresh webhookTimestamp
151
171
  *
172
+ * **The ack is asynchronous (RUSH-2548).** Once a delivery has passed signature
173
+ * verification, freshness, dedup, and rate limiting, the receiver writes
174
+ * `202 {ok:true, accepted:true}` IMMEDIATELY and dispatches the matched routines
175
+ * and handlers afterwards. Dispatch starts an agent run and takes 15-20s, which
176
+ * exceeds Linear's delivery timeout — holding the socket open across it made
177
+ * every real delivery log a timeout + retry on Linear's side. Nothing about the
178
+ * dedup ledger changes: the `<source>:<delivery-id>` key is still what makes a
179
+ * retry a no-op, per-job `markJob` still lets a retry finish only the matches
180
+ * that failed, and the delivery is marked complete only after it settles.
181
+ *
182
+ * A retry that lands WHILE the first is still settling is answered as a
183
+ * duplicate from an in-flight set, since `deliveryStore.seen` only reports
184
+ * completed deliveries and would otherwise let a mid-flight retry double-fire.
185
+ *
152
186
  * Returns the underlying server so callers can `close()` it.
153
187
  */
154
188
  export declare function startWebhookServer(options: WebhookServerOptions): http.Server;
@@ -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) {
@@ -420,18 +420,106 @@ async function readRawBody(req, maxBytes) {
420
420
  }
421
421
  return Buffer.concat(chunks);
422
422
  }
423
+ /**
424
+ * Resolve once a receiver is actually accepting connections, REJECT if the bind
425
+ * failed. `server.listen()` reports a bind failure (EADDRINUSE, EACCES) as an
426
+ * asynchronous `'error'` event, never a throw — so a `try/catch` around
427
+ * `startWebhookServer` cannot see it, and without this the event reaches Node's
428
+ * default handler and takes the whole process down. Every caller that hosts a
429
+ * receiver MUST await this rather than assuming the return means "bound".
430
+ */
431
+ export function waitForListening(server) {
432
+ if (server.listening)
433
+ return Promise.resolve();
434
+ return new Promise((resolve, reject) => {
435
+ const cleanup = () => {
436
+ server.off('listening', onListening);
437
+ server.off('error', onError);
438
+ };
439
+ const onListening = () => { cleanup(); resolve(); };
440
+ const onError = (err) => { cleanup(); reject(err); };
441
+ server.once('listening', onListening);
442
+ server.once('error', onError);
443
+ });
444
+ }
423
445
  /**
424
446
  * Start a localhost-bound receiver. It accepts only:
425
447
  * POST /hooks/github with X-Hub-Signature-256
426
448
  * POST /hooks/linear with Linear-Signature + fresh webhookTimestamp
427
449
  *
450
+ * **The ack is asynchronous (RUSH-2548).** Once a delivery has passed signature
451
+ * verification, freshness, dedup, and rate limiting, the receiver writes
452
+ * `202 {ok:true, accepted:true}` IMMEDIATELY and dispatches the matched routines
453
+ * and handlers afterwards. Dispatch starts an agent run and takes 15-20s, which
454
+ * exceeds Linear's delivery timeout — holding the socket open across it made
455
+ * every real delivery log a timeout + retry on Linear's side. Nothing about the
456
+ * dedup ledger changes: the `<source>:<delivery-id>` key is still what makes a
457
+ * retry a no-op, per-job `markJob` still lets a retry finish only the matches
458
+ * that failed, and the delivery is marked complete only after it settles.
459
+ *
460
+ * A retry that lands WHILE the first is still settling is answered as a
461
+ * duplicate from an in-flight set, since `deliveryStore.seen` only reports
462
+ * completed deliveries and would otherwise let a mid-flight retry double-fire.
463
+ *
428
464
  * Returns the underlying server so callers can `close()` it.
429
465
  */
430
466
  export function startWebhookServer(options) {
431
467
  const deliveryStore = options.deliveryStore ?? createMemoryDeliveryStore();
468
+ /** Delivery ids acked but not yet settled — dedup across the async window. */
469
+ const inFlight = new Set();
432
470
  const rateLimiter = options.rateLimiter ?? createMemoryRateLimiter(options.rateLimitPerMinute ?? 60, 60_000);
433
471
  const ipRateLimiter = options.ipRateLimiter ?? createMemoryRateLimiter(options.ipRateLimitPerMinute ?? 120, 60_000);
434
472
  const maxBodyBytes = options.maxBodyBytes ?? 1024 * 1024;
473
+ /**
474
+ * Dispatch an already-acked delivery: matched routines first, then matched
475
+ * handlers, then mark the delivery complete. A failure leaves the delivery
476
+ * UNMARKED (its per-job `markJob` entries survive), so a later retry of the
477
+ * same delivery id re-runs only what did not complete — the same partial-retry
478
+ * ledger the synchronous receiver had, minus the 4xx that used to request it.
479
+ */
480
+ async function settleDelivery(webhook, id) {
481
+ const { source, event: webhookEvent } = webhook;
482
+ try {
483
+ const context = buildWebhookContext(webhook);
484
+ const fireOptions = options.fire ?? {};
485
+ const firedJobs = await fireWebhookJobs(webhook, {
486
+ ...fireOptions,
487
+ context,
488
+ skipJobNames: deliveryStore.completedJobs(id),
489
+ onJobFired: (job, firedJob) => {
490
+ emit('webhook.fired', { source, event: webhookEvent, deliveryId: id, jobName: job.name, runId: firedJob.runId });
491
+ deliveryStore.markJob(id, job.name);
492
+ fireOptions.onJobFired?.(job, firedJob);
493
+ },
494
+ });
495
+ const matchedHandlers = listHandlers().filter((handler) => handlerMatchesWebhook(handler, webhook));
496
+ const firedHandlers = [];
497
+ const handlerErrors = [];
498
+ await Promise.allSettled(matchedHandlers.map(async (handler) => {
499
+ if (deliveryStore.completedJobs(id).has(handler.name))
500
+ return;
501
+ emit('webhook.matched', { source, event: webhookEvent, deliveryId: id, handlerName: handler.name });
502
+ try {
503
+ const result = await executeHandler(handler, webhook);
504
+ deliveryStore.markJob(id, handler.name);
505
+ firedHandlers.push(result);
506
+ }
507
+ catch (err) {
508
+ handlerErrors.push({ handlerName: handler.name, error: err.message });
509
+ }
510
+ }));
511
+ deliveryStore.mark(id);
512
+ for (const failure of handlerErrors) {
513
+ emit('webhook.failed', { source, event: webhookEvent, deliveryId: id, handlerName: failure.handlerName, error: failure.error });
514
+ }
515
+ options.onDelivery?.(webhook, firedJobs, firedHandlers);
516
+ }
517
+ catch (err) {
518
+ const error = err;
519
+ emit('webhook.failed', { source, event: webhookEvent, deliveryId: id, error: error.message });
520
+ options.onDeliveryError?.(webhook, error);
521
+ }
522
+ }
435
523
  const server = http.createServer((req, res) => {
436
524
  void (async () => {
437
525
  if (req.method !== 'POST') {
@@ -485,7 +573,7 @@ export function startWebhookServer(options) {
485
573
  const id = deliveryId(source, req.headers, rawBody);
486
574
  const event = source === 'github' ? (header(req.headers, 'x-github-event') ?? '') : '';
487
575
  emit('webhook.received', { source, event, deliveryId: id });
488
- if (deliveryStore.seen(id)) {
576
+ if (deliveryStore.seen(id) || inFlight.has(id)) {
489
577
  res.writeHead(200, { 'content-type': 'application/json' });
490
578
  res.end(JSON.stringify({ ok: true, duplicate: true, fired: [] }));
491
579
  return;
@@ -510,45 +598,12 @@ export function startWebhookServer(options) {
510
598
  payload,
511
599
  };
512
600
  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
- }));
601
+ // ACK FIRST (RUSH-2548). Everything that could reject this delivery has
602
+ // run; what remains starts agent runs and outlives any sender timeout.
603
+ inFlight.add(id);
604
+ res.writeHead(202, { 'content-type': 'application/json' });
605
+ res.end(JSON.stringify({ ok: true, accepted: true, deliveryId: id }));
606
+ void settleDelivery(webhook, id).finally(() => inFlight.delete(id));
552
607
  }
553
608
  catch (err) {
554
609
  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;
@@ -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.