@phnx-labs/agents-cli 1.22.39 → 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 +294 -0
  2. package/README.md +111 -70
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.js +45 -26
  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 +16 -3
  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 +160 -215
  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 +186 -64
  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 +2 -1
  191. package/dist/lib/config-keys.js +8 -4
  192. package/dist/lib/config-machine-keys.d.ts +4 -2
  193. package/dist/lib/config-machine-keys.js +5 -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 +85 -75
  206. package/dist/lib/device-config.js +279 -141
  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 +10 -5
  218. package/dist/lib/devices/pool.js +5 -7
  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 +4 -4
  239. package/dist/lib/exec.js +11 -11
  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} +13 -1
  304. package/dist/lib/{migrate.js → installations/migrate.js} +160 -40
  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 +4 -4
  474. package/dist/lib/smart-launch.js +6 -4
  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
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Per-box hosted webhook receivers: config + daemon host (RUSH-2548).
3
+ *
4
+ * `~/.agents/daemon/webhooks.yaml` declares which signed webhook receivers THIS
5
+ * box hosts — bundle, local port, rate limit, and an optional public Tailscale
6
+ * Funnel port. The daemon's `webhook-receiver` service reads it and binds one
7
+ * receiver per entry, drawing each receiver's signing secret from the broker /
8
+ * machine-local file store (no `AGENTS_SECRETS_PASSPHRASE`, no `nohup`). An
9
+ * absent or empty file hosts nothing, so an unconfigured box binds nothing.
10
+ *
11
+ * This is per-box operational state (a public receiver runs on exactly one box),
12
+ * so it is deliberately NOT part of the fleet-synced device config — it mirrors
13
+ * `services.yaml` / daemon-services.ts, not `agents config`.
14
+ */
15
+ import { type WebhookSecrets } from './triggers/webhook.js';
16
+ import { type FunnelPort } from './funnel.js';
17
+ export declare const DEFAULT_WEBHOOK_PORT = 8787;
18
+ export declare const DEFAULT_WEBHOOK_RATE_LIMIT = 60;
19
+ /** Optional public exposure for a hosted receiver via Tailscale Funnel. */
20
+ export interface HostedReceiverFunnel {
21
+ /** Public HTTPS port (Funnel allows 443 / 8443 / 10000). */
22
+ publicPort: FunnelPort;
23
+ }
24
+ /** One receiver this box hosts. */
25
+ export interface HostedReceiverConfig {
26
+ /** Secrets bundle holding GITHUB_WEBHOOK_SECRET and/or LINEAR_WEBHOOK_SECRET. */
27
+ bundle: string;
28
+ /** Local bind port (default 8787). */
29
+ port?: number;
30
+ /** Accepted deliveries per source per minute (default 60). */
31
+ rateLimit?: number;
32
+ /** Public Funnel exposure; omit to bind localhost only. */
33
+ funnel?: HostedReceiverFunnel;
34
+ }
35
+ export interface DaemonWebhooksConfig {
36
+ receivers: HostedReceiverConfig[];
37
+ }
38
+ /** Path to `~/.agents/daemon/webhooks.yaml`. */
39
+ export declare function getDaemonWebhooksConfigPath(): string;
40
+ /**
41
+ * Read the hosted-receivers config. A missing or malformed file yields an empty
42
+ * receiver list — never throws — so a box with no config hosts nothing.
43
+ */
44
+ export declare function readDaemonWebhooksConfig(): DaemonWebhooksConfig;
45
+ /** Write the hosted-receivers config, creating the daemon config dir if needed. */
46
+ export declare function writeDaemonWebhooksConfig(cfg: DaemonWebhooksConfig): void;
47
+ /** The port a receiver binds — its identity, since one port hosts one receiver. */
48
+ export declare function hostedReceiverPort(receiver: HostedReceiverConfig): number;
49
+ /**
50
+ * Declare a receiver on this box, replacing any existing entry on the same port.
51
+ * Port is the identity because two receivers cannot bind one port — a second
52
+ * `add` on a port is an edit, never a silently ignored duplicate.
53
+ */
54
+ export declare function addHostedReceiver(receiver: HostedReceiverConfig): DaemonWebhooksConfig;
55
+ /**
56
+ * Drop the receiver bound to `port`. Returns the removed entry, or null when
57
+ * nothing was declared there. The caller is responsible for taking down any
58
+ * public Funnel the removed entry declared — leaving it up would keep a public
59
+ * `https://<host>.ts.net` route pointed at a port nothing serves.
60
+ */
61
+ export declare function removeHostedReceiver(port: number): HostedReceiverConfig | null;
62
+ /**
63
+ * Resolve a receiver's signing secrets from its bundle. Reads `agentOnly` (no
64
+ * Touch ID — the daemon is a background service, SEC-13): a broker-held or
65
+ * file-store bundle resolves silently; a locked bundle THROWS the actionable
66
+ * unlock message, which fails the receiver LOUD rather than binding with no
67
+ * verifiable signature. Throws when neither webhook secret is present.
68
+ */
69
+ export declare function resolveReceiverSecrets(bundle: string): WebhookSecrets;
70
+ export interface HostedWebhookReceivers {
71
+ /** Number of receivers actually bound. */
72
+ count: number;
73
+ /** Stop every hosted receiver. Idempotent. */
74
+ close(): Promise<void>;
75
+ }
76
+ type Logger = (level: string, message: string) => void;
77
+ /**
78
+ * Start every receiver declared in `webhooks.yaml`. A receiver that cannot start
79
+ * — an unreadable secret (locked bundle, no webhook secret) or a failed bind
80
+ * (the port is already taken by a foreground `agents webhooks serve`, another
81
+ * daemon, or anything else) — is skipped with a loud WARN and does NOT take the
82
+ * others, or the daemon, down. Returns a handle that stops them all.
83
+ *
84
+ * This is async because a bind failure is only observable asynchronously:
85
+ * `server.listen()` surfaces EADDRINUSE as an `'error'` event, so a `try/catch`
86
+ * around the start call never sees it and the event reaches the process-level
87
+ * `uncaughtException` handler (`index.ts`), which exits 1 for the supervisor to
88
+ * restart — a crash loop that would take the secrets broker, scheduler,
89
+ * monitors, browser IPC, and self-heal down with it. `waitForListening` is what
90
+ * turns that into one skipped receiver.
91
+ */
92
+ export declare function startHostedWebhookReceivers(opts: {
93
+ log: Logger;
94
+ /**
95
+ * How a receiver's signing secrets are resolved. Defaults to
96
+ * `resolveReceiverSecrets` (the real broker read). Injectable for the same
97
+ * reason `FireWebhookOptions.dispatch` is — so a test can exercise the bind
98
+ * path against real sockets without a machine-local secrets bundle.
99
+ */
100
+ resolveSecrets?: (bundle: string) => WebhookSecrets;
101
+ }): Promise<HostedWebhookReceivers>;
102
+ export {};
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Per-box hosted webhook receivers: config + daemon host (RUSH-2548).
3
+ *
4
+ * `~/.agents/daemon/webhooks.yaml` declares which signed webhook receivers THIS
5
+ * box hosts — bundle, local port, rate limit, and an optional public Tailscale
6
+ * Funnel port. The daemon's `webhook-receiver` service reads it and binds one
7
+ * receiver per entry, drawing each receiver's signing secret from the broker /
8
+ * machine-local file store (no `AGENTS_SECRETS_PASSPHRASE`, no `nohup`). An
9
+ * absent or empty file hosts nothing, so an unconfigured box binds nothing.
10
+ *
11
+ * This is per-box operational state (a public receiver runs on exactly one box),
12
+ * so it is deliberately NOT part of the fleet-synced device config — it mirrors
13
+ * `services.yaml` / daemon-services.ts, not `agents config`.
14
+ */
15
+ import * as fs from 'fs';
16
+ import * as path from 'path';
17
+ import * as yaml from 'yaml';
18
+ import { exec } from 'child_process';
19
+ import { getDaemonConfigDir, getRuntimeStateDir } from './state.js';
20
+ import { atomicWriteFileSync } from './fs-atomic.js';
21
+ import { readAndResolveBundleEnv } from './secrets/bundles.js';
22
+ import { startWebhookServer, createFileDeliveryStore, waitForListening } from './triggers/webhook.js';
23
+ import { buildFunnelUpCommand, FUNNEL_PORTS } from './funnel.js';
24
+ export const DEFAULT_WEBHOOK_PORT = 8787;
25
+ export const DEFAULT_WEBHOOK_RATE_LIMIT = 60;
26
+ /** Path to `~/.agents/daemon/webhooks.yaml`. */
27
+ export function getDaemonWebhooksConfigPath() {
28
+ return path.join(getDaemonConfigDir(), 'webhooks.yaml');
29
+ }
30
+ function coerceReceiver(item) {
31
+ if (!item || typeof item !== 'object')
32
+ return null;
33
+ const obj = item;
34
+ if (typeof obj.bundle !== 'string' || obj.bundle.length === 0)
35
+ return null;
36
+ const rc = { bundle: obj.bundle };
37
+ if (typeof obj.port === 'number' && Number.isInteger(obj.port) && obj.port > 0)
38
+ rc.port = obj.port;
39
+ if (typeof obj.rateLimit === 'number' && Number.isInteger(obj.rateLimit) && obj.rateLimit > 0)
40
+ rc.rateLimit = obj.rateLimit;
41
+ const funnel = obj.funnel;
42
+ // A publicPort Funnel cannot serve is dropped rather than carried forward — the
43
+ // receiver still binds localhost, and `daemon webhooks add` rejects it up front.
44
+ if (funnel && typeof funnel === 'object' && FUNNEL_PORTS.includes(funnel.publicPort)) {
45
+ rc.funnel = { publicPort: funnel.publicPort };
46
+ }
47
+ return rc;
48
+ }
49
+ /**
50
+ * Read the hosted-receivers config. A missing or malformed file yields an empty
51
+ * receiver list — never throws — so a box with no config hosts nothing.
52
+ */
53
+ export function readDaemonWebhooksConfig() {
54
+ try {
55
+ const raw = fs.readFileSync(getDaemonWebhooksConfigPath(), 'utf-8');
56
+ const parsed = yaml.parse(raw);
57
+ const list = parsed && Array.isArray(parsed.receivers) ? parsed.receivers : [];
58
+ const receivers = list.map(coerceReceiver).filter((r) => r !== null);
59
+ return { receivers };
60
+ }
61
+ catch {
62
+ return { receivers: [] };
63
+ }
64
+ }
65
+ /** Write the hosted-receivers config, creating the daemon config dir if needed. */
66
+ export function writeDaemonWebhooksConfig(cfg) {
67
+ fs.mkdirSync(getDaemonConfigDir(), { recursive: true });
68
+ const out = yaml.stringify({ receivers: cfg.receivers }, { sortMapEntries: false });
69
+ atomicWriteFileSync(getDaemonWebhooksConfigPath(), out, 'utf-8');
70
+ }
71
+ /** The port a receiver binds — its identity, since one port hosts one receiver. */
72
+ export function hostedReceiverPort(receiver) {
73
+ return receiver.port ?? DEFAULT_WEBHOOK_PORT;
74
+ }
75
+ /**
76
+ * Declare a receiver on this box, replacing any existing entry on the same port.
77
+ * Port is the identity because two receivers cannot bind one port — a second
78
+ * `add` on a port is an edit, never a silently ignored duplicate.
79
+ */
80
+ export function addHostedReceiver(receiver) {
81
+ const port = hostedReceiverPort(receiver);
82
+ const existing = readDaemonWebhooksConfig().receivers.filter((r) => hostedReceiverPort(r) !== port);
83
+ const next = { receivers: [...existing, receiver] };
84
+ writeDaemonWebhooksConfig(next);
85
+ return next;
86
+ }
87
+ /**
88
+ * Drop the receiver bound to `port`. Returns the removed entry, or null when
89
+ * nothing was declared there. The caller is responsible for taking down any
90
+ * public Funnel the removed entry declared — leaving it up would keep a public
91
+ * `https://<host>.ts.net` route pointed at a port nothing serves.
92
+ */
93
+ export function removeHostedReceiver(port) {
94
+ const { receivers } = readDaemonWebhooksConfig();
95
+ const removed = receivers.find((r) => hostedReceiverPort(r) === port);
96
+ if (!removed)
97
+ return null;
98
+ writeDaemonWebhooksConfig({ receivers: receivers.filter((r) => hostedReceiverPort(r) !== port) });
99
+ return removed;
100
+ }
101
+ /**
102
+ * Resolve a receiver's signing secrets from its bundle. Reads `agentOnly` (no
103
+ * Touch ID — the daemon is a background service, SEC-13): a broker-held or
104
+ * file-store bundle resolves silently; a locked bundle THROWS the actionable
105
+ * unlock message, which fails the receiver LOUD rather than binding with no
106
+ * verifiable signature. Throws when neither webhook secret is present.
107
+ */
108
+ export function resolveReceiverSecrets(bundle) {
109
+ const { env } = readAndResolveBundleEnv(bundle, { caller: 'daemon webhook-receiver', agentOnly: true });
110
+ const secrets = {};
111
+ if (env.GITHUB_WEBHOOK_SECRET)
112
+ secrets.github = env.GITHUB_WEBHOOK_SECRET;
113
+ if (env.LINEAR_WEBHOOK_SECRET)
114
+ secrets.linear = env.LINEAR_WEBHOOK_SECRET;
115
+ if (!secrets.github && !secrets.linear) {
116
+ throw new Error(`bundle '${bundle}' has neither GITHUB_WEBHOOK_SECRET nor LINEAR_WEBHOOK_SECRET`);
117
+ }
118
+ return secrets;
119
+ }
120
+ /** Best-effort funnel reconcile: bring the declared public port up, log on failure. */
121
+ function reconcileFunnel(publicPort, localPort, log) {
122
+ let command;
123
+ try {
124
+ command = buildFunnelUpCommand(publicPort, localPort);
125
+ }
126
+ catch (err) {
127
+ log('WARN', `webhook funnel skipped (port ${publicPort}): ${err.message}`);
128
+ return;
129
+ }
130
+ exec(command, (err) => {
131
+ if (err) {
132
+ log('WARN', `webhook funnel reconcile failed (public ${publicPort} -> localhost:${localPort}); binding localhost only: ${err.message}`);
133
+ }
134
+ else {
135
+ log('INFO', `webhook funnel up: public ${publicPort} -> localhost:${localPort}`);
136
+ }
137
+ });
138
+ }
139
+ /**
140
+ * Start every receiver declared in `webhooks.yaml`. A receiver that cannot start
141
+ * — an unreadable secret (locked bundle, no webhook secret) or a failed bind
142
+ * (the port is already taken by a foreground `agents webhooks serve`, another
143
+ * daemon, or anything else) — is skipped with a loud WARN and does NOT take the
144
+ * others, or the daemon, down. Returns a handle that stops them all.
145
+ *
146
+ * This is async because a bind failure is only observable asynchronously:
147
+ * `server.listen()` surfaces EADDRINUSE as an `'error'` event, so a `try/catch`
148
+ * around the start call never sees it and the event reaches the process-level
149
+ * `uncaughtException` handler (`index.ts`), which exits 1 for the supervisor to
150
+ * restart — a crash loop that would take the secrets broker, scheduler,
151
+ * monitors, browser IPC, and self-heal down with it. `waitForListening` is what
152
+ * turns that into one skipped receiver.
153
+ */
154
+ export async function startHostedWebhookReceivers(opts) {
155
+ const { log } = opts;
156
+ const resolveSecrets = opts.resolveSecrets ?? resolveReceiverSecrets;
157
+ const { receivers } = readDaemonWebhooksConfig();
158
+ const servers = [];
159
+ for (const receiver of receivers) {
160
+ const port = receiver.port ?? DEFAULT_WEBHOOK_PORT;
161
+ let secrets;
162
+ try {
163
+ secrets = resolveSecrets(receiver.bundle);
164
+ }
165
+ catch (err) {
166
+ log('WARN', `webhook receiver on :${port} skipped: ${err.message}`);
167
+ continue;
168
+ }
169
+ let server = null;
170
+ try {
171
+ server = startWebhookServer({
172
+ host: '127.0.0.1',
173
+ port,
174
+ secrets,
175
+ rateLimitPerMinute: receiver.rateLimit ?? DEFAULT_WEBHOOK_RATE_LIMIT,
176
+ // Per-port durable delivery dedup so replays survive a daemon restart and
177
+ // two receivers on distinct ports never share a dedup ledger.
178
+ deliveryStore: createFileDeliveryStore(path.join(getRuntimeStateDir(), 'webhook', `deliveries-${port}.json`)),
179
+ onDelivery: (webhook, fired, handlers) => {
180
+ const parts = [];
181
+ if (fired.length)
182
+ parts.push(`routines ${fired.map((f) => f.jobName).join(', ')}`);
183
+ if (handlers.length)
184
+ parts.push(`handlers ${handlers.map((h) => h.handlerName).join(', ')}`);
185
+ log('INFO', `webhook ${webhook.source}:${webhook.event} ${parts.length ? `fired ${parts.join('; ')}` : 'no match'}`);
186
+ },
187
+ // The 202 ack means no HTTP status carries a settle failure — the daemon
188
+ // log is where it surfaces, so it is never swallowed.
189
+ onDeliveryError: (webhook, err) => {
190
+ log('WARN', `webhook ${webhook.source}:${webhook.event} dispatch failed after ack: ${err.message}`);
191
+ },
192
+ });
193
+ await waitForListening(server);
194
+ servers.push(server);
195
+ log('INFO', `webhook receiver bound on 127.0.0.1:${port} (bundle ${receiver.bundle})`);
196
+ if (receiver.funnel)
197
+ reconcileFunnel(receiver.funnel.publicPort, port, log);
198
+ }
199
+ catch (err) {
200
+ // Close the half-started server so a failed bind leaks no handle, and keep
201
+ // going: one unusable receiver must not cost the others their ingress.
202
+ server?.close(() => { });
203
+ log('WARN', `webhook receiver on :${port} failed to bind: ${err.message}`);
204
+ }
205
+ }
206
+ return {
207
+ count: servers.length,
208
+ close: () => Promise.all(servers.map((s) => new Promise((resolve) => s.close(() => resolve())))).then(() => undefined),
209
+ };
210
+ }
@@ -1,55 +1,46 @@
1
1
  /**
2
- * Device/user config keys — typed read/write over the central agents.yaml store.
2
+ * Device/user config keys — typed read/write over the three-layer store.
3
3
  *
4
4
  * One registry (`CONFIG_KEYS`) maps each CLI dotted name to where it lives:
5
- * - user scope → central `~/.agents/agents.yaml` under `config:` (syncs
6
- * fleet-wide via `agents repo push/pull`)
7
- * - device scope split by `visibility`, which asks WHO READS IT:
8
- * · `shared` → central `fleet.devices.<name>.config`, because a PEER
9
- * reads it (the ssh keys and platform to dial the box,
10
- * agents.max-concurrent for placement, auto-launch and
11
- * notes for fleet views). Names and non-secret values only
12
- * (a secrets-bundle NAME is fine; a credential never is).
13
- * · `machine` the owning box's own doc, never the shared file, because
14
- * nothing off-box reads it (browser.profile,
15
- * browser.remote-control, scheduler.enabled,
16
- * daemon.enabled).
5
+ * - user scope → central `~/.agents/agents.yaml` under `config:` (syncs
6
+ * fleet-wide via `agents repo push/pull`)
7
+ * - device scope the per-device TRACKED doc
8
+ * `~/.agents/devices/<name>/agents.yaml` under `config:`
9
+ * conflict-free by construction (each machine writes only
10
+ * its own folder, and the churny auto-written pins no longer
11
+ * share the file)
12
+ * - fleet layer → central `~/.agents/agents.yaml` under
13
+ * `fleet.defaults.config` fleet-wide defaults written by
14
+ * `agents devices config --fleet <key> <value>`
17
15
  *
18
- * That split exists because "central for everything" put 13 machines on one
19
- * tracked path and they stopped being able to pull. `browser.remote-control` is
20
- * also a consent flag syncing one box's opt-in to the rest was a security bug,
21
- * not just churn.
16
+ * Read order for a device-scope key: built-in default < fleet.defaults.config
17
+ * < per-device config:. Names and non-secret values only (a secrets-bundle
18
+ * NAME is fine; a credential never is).
22
19
  *
23
20
  * The device registry (`~/.agents/.history/devices/registry.json`) stays the
24
21
  * DISCOVERY cache (address, tailscale snapshot, reachability); the profile
25
22
  * fields config can override (ssh.*, platform, user) are overlaid onto it at
26
23
  * read time by `lib/devices/resolve-profile.ts`.
27
24
  *
28
- * Legacy stores (per-device `devices/<host>/agents.yaml` config and
29
- * `.history/devices/auto-launch.json`) are folded into the central block once
30
- * by `lib/devices/config-migration.ts`, invoked on the first read/write in a
31
- * process — after migration there is ONE read path, no fallback branches.
25
+ * Legacy stores (central `fleet.devices.<name>.config`, legacy auto-launch.json,
26
+ * doc-level defaultBrowserProfile, pins in tracked docs) are folded into this
27
+ * layout once by `lib/devices/config-migration.ts`, invoked on the first
28
+ * read/write in a process — after migration there is ONE read path per layer,
29
+ * no fallback branches.
32
30
  *
33
31
  * Unset always means today's behavior (the documented default).
34
32
  */
35
33
  /** Which tier of the agents.yaml store a key lives in. */
36
34
  export type ConfigScope = 'user' | 'device';
37
35
  /**
38
- * For a device-scope key: WHO READS IT, which is what decides where it is stored.
36
+ * For a device-scope key: WHO READS IT. Storage is still the three-layer
37
+ * store (per-device doc / fleet.defaults.config); visibility only gates
38
+ * whether a PEER may read or write the key.
39
39
  *
40
- * - `shared` — a PEER reads it, so it must be visible fleet-wide and lives in the
41
- * tracked `fleet.devices.<name>.config`. `ssh.*` and `platform` are the
42
- * load-bearing cases: machine A resolves them to build the ssh target for B
43
- * (`lib/devices/resolve-profile.ts`), so it cannot ask B for them.
44
- * - `machine` — only the owning box ever reads it, so it belongs in that box's
45
- * own gitignored doc and must never reach the fleet-shared file. Storing these
46
- * centrally is what makes 13 machines write one tracked path.
47
- *
48
- * Declaring this is MANDATORY for a device-scope key — the union below makes
49
- * omitting it a compile error, mirroring how `META_KEY_SCOPE` (lib/state.ts) uses
50
- * an exhaustive `Record<keyof Meta, ...>`. Before this, a new key picked its home
51
- * by hand with no signal, which is how operator config drifted into the shared
52
- * file twice.
40
+ * - `shared` — a peer reads it (ssh.*, platform, role, caps), so any box
41
+ * may set it for any device. Lands in that device's tracked doc.
42
+ * - `machine` only the owning box ever reads it (scheduler, daemon, tmux,
43
+ * browser consent). Refused for a peer — run it on that box instead.
53
44
  */
54
45
  export type ConfigVisibility = 'shared' | 'machine';
55
46
  /** Value type of a config key — drives validation and `--json` rendering. */
@@ -79,17 +70,21 @@ export type ConfigKeySpec = (ConfigKeySpecBase & {
79
70
  scope: 'device';
80
71
  visibility: ConfigVisibility;
81
72
  });
73
+ /** Which layer set a key's effective value (`default` = unset, built-in behavior). */
74
+ export type ConfigSource = 'user' | 'device' | 'fleet' | 'default';
82
75
  /** A key with its resolved value and the layer that set it. */
83
76
  export interface ConfigEntry {
84
77
  spec: ConfigKeySpec;
85
- /** The stored value, or undefined when unset (unset = default behavior). */
78
+ /** The effective value, or undefined when unset (unset = default behavior). */
86
79
  value: unknown;
87
- /** Which layer set it; undefined when unset. */
88
- layer?: ConfigScope;
80
+ /** Which layer set the effective value. */
81
+ source: ConfigSource;
89
82
  }
90
- /** Options scoping a read/write to a specific device (default: this machine). */
83
+ /** Options scoping a read/write: a specific device (default: this machine), or the fleet-defaults layer. */
91
84
  export interface ConfigTarget {
92
85
  device?: string;
86
+ /** Write/read the fleet-wide defaults layer (central fleet.defaults.config). */
87
+ fleet?: boolean;
93
88
  }
94
89
  /** Roles a device can be marked with — see the `role` key below. */
95
90
  declare const DEVICE_ROLES: readonly ["worker", "personal"];
@@ -99,40 +94,31 @@ export declare const CONFIG_KEYS: readonly ConfigKeySpec[];
99
94
  /** Look up a key spec by CLI dotted name, or throw listing the known keys. */
100
95
  export declare function configKeySpec(name: string): ConfigKeySpec;
101
96
  /**
102
- * Fold the legacy per-device config stores into the central block, once per
97
+ * Fold the legacy config/pins stores into the current layout, once per
103
98
  * process. A failure is loud but non-fatal — config reads must keep working,
104
99
  * and the next process retries the fold. Honors AGENTS_SKIP_MIGRATION=1, the
105
100
  * same gate bootstrap's runMigration uses (tests pin it so a fork never folds
106
101
  * the developer's real ~/.agents as a side effect).
107
- *
108
- * Call this ONLY from a lifecycle entry point (daemon boot, `runMigration`).
109
- * It must never hang off a config read or write: `~/.agents/agents.yaml` is a
110
- * tracked file shared by every machine in the fleet, so a migration on the read
111
- * path means an ordinary `agents config get` can dirty the shared file. That is
112
- * what left yosemite-s0 unable to pull — 13 machines each rewriting one tracked
113
- * path, on nearly every command.
114
102
  */
115
103
  export declare function ensureDeviceConfigMigrated(): void;
104
+ /** The fleet-defaults config layer (central `fleet.defaults.config`; {} when unset). */
105
+ export declare function readFleetConfigDefaults(): Record<string, unknown>;
116
106
  /**
117
- * The raw device-scope config block for `device` from the central
118
- * `fleet.devices.<name>.config` map ({} when unset). This is the single read
119
- * path post-migration — the profile resolver (`lib/devices/resolve-profile.ts`)
107
+ * The effective device-scope config block for `device`: fleet.defaults.config
108
+ * overlaid with the per-device doc's config:. This is the single read path
109
+ * post-migration — the profile resolver (`lib/devices/resolve-profile.ts`)
120
110
  * goes through here. Deliberately does NOT auto-trigger the migration: it
121
- * serves the hot dial/render paths, and the keys it resolves (ssh.*, platform)
122
- * are new — they never existed in the legacy stores. Keys with legacy data are
123
- * read through the public API below, which triggers the fold.
111
+ * serves the hot dial/render paths. Sync and cheap (small local files).
124
112
  */
125
113
  export declare function readDeviceConfigValues(device: string): Record<string, unknown>;
126
- /** Get one config key's value and the layer that set it. */
114
+ /** Get one config key's effective value and the layer that set it. */
127
115
  export declare function getConfigValue(name: string, opts?: ConfigTarget): ConfigEntry;
128
116
  /**
129
- * List every known key with its value and the layer that set it.
117
+ * List every known key with its effective value and the layer that set it.
130
118
  *
131
- * Listing a PEER omits its machine-local keys rather than throwing. Their values
132
- * live in that box's own doc and are genuinely unknowable from here, but a bulk
133
- * listing must not hard-fail because one key in the registry is unreadable
134
- * `agents devices config <peer>` should still show everything it CAN resolve.
135
- * Asking for such a key by name still errors, with the `agents ssh` fix named.
119
+ * Listing a PEER omits its machine-local keys rather than throwing those
120
+ * values live on that box and are unknowable from here, but a bulk listing
121
+ * must not hard-fail. Asking for such a key by name still errors.
136
122
  */
137
123
  export declare function listConfig(opts?: ConfigTarget): ConfigEntry[];
138
124
  /** List user-scope config keys with their values. Used to show inherited settings
@@ -140,9 +126,14 @@ export declare function listConfig(opts?: ConfigTarget): ConfigEntry[];
140
126
  export declare function listUserConfig(): ConfigEntry[];
141
127
  /** Resolve the explicit usage host, falling back to the user's interactive host. */
142
128
  export declare function resolveUsagePrimaryHost(): string | null;
143
- /** Set a config key (validated). Device-scope keys target this machine unless `opts.device` names a peer. */
129
+ /**
130
+ * Set a config key (validated). Device-scope keys target this machine unless
131
+ * `opts.device` names a peer; `opts.fleet` writes the fleet-wide defaults layer
132
+ * instead. User-scope keys reject `fleet` (they are already fleet-wide).
133
+ */
144
134
  export declare function setConfigValue(name: string, value: unknown, opts?: ConfigTarget): void;
145
- /** Unset a config key — restores default behavior. No-op when already unset. */
135
+ /** Unset a config key — restores the next layer down (fleet default, then the
136
+ * built-in default). No-op when already unset at that layer. */
146
137
  export declare function unsetConfigValue(name: string, opts?: ConfigTarget): void;
147
138
  /** A role an operator marked a device with (`agents devices role <name> <role>`). */
148
139
  export type ConfiguredDeviceRole = (typeof DEVICE_ROLES)[number];
@@ -159,13 +150,18 @@ export declare function configuredDeviceRole(name: string): ConfiguredDeviceRole
159
150
  /** Mark a device's role fleet-wide; `undefined` clears the mark. */
160
151
  export declare function setConfiguredDeviceRole(name: string, role: ConfiguredDeviceRole | undefined): void;
161
152
  /**
162
- * Every device an operator has marked, keyed by device name. Devices with no
163
- * mark are absent that absence is what makes the worker allowlist opt-in.
153
+ * Every device with an effective role, keyed by device name. Layers like every
154
+ * other device-scope key: the fleet default (central fleet.defaults.config)
155
+ * applies fleet-wide and the per-device doc wins on conflict. `roster` (the
156
+ * registered device names) lets a fleet default reach devices that have no doc
157
+ * of their own; without it only devices with docs are considered — so a
158
+ * fleet-wide `role` default would silently miss a doc-less device and drop it
159
+ * from the worker allowlist. Mirrors {@link loadAutoLaunchPreferences}.
164
160
  */
165
- export declare function listConfiguredDeviceRoles(): Record<string, ConfiguredDeviceRole>;
161
+ export declare function listConfiguredDeviceRoles(roster?: string[]): Record<string, ConfiguredDeviceRole>;
166
162
  /** The configured automatic-placement pool mode. Unset means `workers`. */
167
163
  export declare function autoPoolMode(): AutoPoolMode;
168
- /** A device's auto-launch flags, as read by the ext's launch ranking. */
164
+ /** A device's auto-launch flags, as read by Factory's launch ranking. */
169
165
  export interface AutoLaunchPreference {
170
166
  enabled?: boolean;
171
167
  preferred?: boolean;
@@ -173,16 +169,22 @@ export interface AutoLaunchPreference {
173
169
  /** True if the device is enabled for auto-launch. Unset defaults to true. */
174
170
  export declare function isAutoLaunchEnabled(name: string): boolean;
175
171
  /** Set whether a device is enabled for auto-launch. Setting the default
176
- * (enabled) removes the key to keep the block minimal. */
172
+ * (enabled) removes the key to keep the doc minimal. */
177
173
  export declare function setAutoLaunchEnabled(name: string, enabled: boolean): void;
178
174
  /** True if the device is preferred for auto-launch ranking. */
179
175
  export declare function isAutoLaunchPreferred(name: string): boolean;
180
176
  /** Set whether a device is preferred for auto-launch. Setting the default
181
- * (not preferred) removes the key to keep the block minimal. */
177
+ * (not preferred) removes the key to keep the doc minimal. */
182
178
  export declare function setAutoLaunchPreferred(name: string, preferred: boolean): void;
183
- /** Every device's auto-launch flags, keyed by device name (set flags only) —
184
- * the shape the ext's launch ranking consumes. */
185
- export declare function loadAutoLaunchPreferences(): Record<string, AutoLaunchPreference>;
179
+ /**
180
+ * Every device's effective auto-launch flags, keyed by device name — the shape
181
+ * the menu-bar snapshot consumes. Layers like every other device-scope key: the
182
+ * fleet default (central fleet.defaults.config) applies fleet-wide and the
183
+ * per-device doc wins on conflict. `roster` (the registered device names) lets
184
+ * a fleet default reach devices that have no doc of their own; without it only
185
+ * devices with docs are listed.
186
+ */
187
+ export declare function loadAutoLaunchPreferences(roster?: string[]): Record<string, AutoLaunchPreference>;
186
188
  /** True unless this machine's config disables the routines scheduler. */
187
189
  export declare function isSchedulerEnabled(): boolean;
188
190
  /**
@@ -212,10 +214,18 @@ export declare function isDaemonEnabled(): boolean;
212
214
  */
213
215
  export declare function assertDaemonEnabled(): void;
214
216
  /**
215
- * Read the `agents.max-concurrent` cap for each named device from the central
216
- * config block (no SSH). Devices without a cap are omitted — uncapped is the
217
- * default. Used as an input to host ranking (teams placement, Factory
218
- * auto-launch), never as a remote probe.
217
+ * Idle window (ms) the browser-task reaper (`browser/hygiene.ts`) uses on THIS
218
+ * machine, or `null` when idle reaping is off (`browser.task-idle-minutes=0`)
219
+ * session-dead reaping is unaffected either way. Unset means the default 30
220
+ * minutes. Read by the daemon's periodic tick and, as the fallback when a
221
+ * caller omits `--idle-minutes`, by the `gc` IPC action.
222
+ */
223
+ export declare function resolveBrowserTaskIdleMs(): number | null;
224
+ /**
225
+ * Read the effective `agents.max-concurrent` cap for each named device (fleet
226
+ * defaults layered under the per-device doc; no SSH). Devices without a cap
227
+ * are omitted — uncapped is the default. Used as an input to host ranking
228
+ * (teams placement, AGI EXT auto-launch), never as a remote probe.
219
229
  */
220
230
  export declare function readMaxConcurrentCaps(devices: string[]): Record<string, number>;
221
231
  export {};