@phnx-labs/agents-cli 1.22.39 → 1.22.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (569) hide show
  1. package/CHANGELOG.md +316 -0
  2. package/README.md +116 -70
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.js +45 -27
  5. package/dist/browser.js +2 -2
  6. package/dist/cli/command-registry.d.ts +135 -0
  7. package/dist/cli/command-registry.js +259 -0
  8. package/dist/commands/accounts.d.ts +20 -0
  9. package/dist/commands/accounts.js +186 -25
  10. package/dist/commands/apply.d.ts +3 -3
  11. package/dist/commands/apply.js +20 -63
  12. package/dist/commands/browser.d.ts +15 -0
  13. package/dist/commands/browser.js +318 -131
  14. package/dist/commands/budget.d.ts +7 -6
  15. package/dist/commands/budget.js +8 -7
  16. package/dist/commands/cloud.js +17 -20
  17. package/dist/commands/commands.js +1 -1
  18. package/dist/commands/computer-actions.d.ts +1 -35
  19. package/dist/commands/computer-actions.js +13 -181
  20. package/dist/commands/computer.d.ts +28 -3
  21. package/dist/commands/computer.js +93 -65
  22. package/dist/commands/config.js +16 -3
  23. package/dist/commands/cost.d.ts +2 -1
  24. package/dist/commands/cost.js +7 -6
  25. package/dist/commands/daemon.js +151 -4
  26. package/dist/commands/detach.js +1 -1
  27. package/dist/commands/doctor.js +19 -11
  28. package/dist/commands/events.js +1 -1
  29. package/dist/commands/exec.d.ts +2 -50
  30. package/dist/commands/exec.js +160 -215
  31. package/dist/commands/factory.js +1 -1
  32. package/dist/commands/feed.d.ts +2 -2
  33. package/dist/commands/feed.js +12 -23
  34. package/dist/commands/fleet-capture.js +25 -27
  35. package/dist/commands/focus.d.ts +2 -3
  36. package/dist/commands/focus.js +34 -9
  37. package/dist/commands/go.js +15 -5
  38. package/dist/commands/harness.d.ts +3 -3
  39. package/dist/commands/harness.js +53 -5
  40. package/dist/commands/hooks.js +1 -1
  41. package/dist/commands/import.js +2 -2
  42. package/dist/commands/insights.d.ts +5 -5
  43. package/dist/commands/insights.js +15 -9
  44. package/dist/commands/inspect.d.ts +2 -3
  45. package/dist/commands/inspect.js +4 -16
  46. package/dist/commands/logs.d.ts +2 -2
  47. package/dist/commands/logs.js +9 -9
  48. package/dist/commands/mcp.js +2 -2
  49. package/dist/commands/memory.js +1 -1
  50. package/dist/commands/message.d.ts +1 -1
  51. package/dist/commands/message.js +7 -7
  52. package/dist/commands/mine.d.ts +11 -8
  53. package/dist/commands/mine.js +11 -10
  54. package/dist/commands/models.js +1 -1
  55. package/dist/commands/modes.js +1 -1
  56. package/dist/commands/monitors.js +23 -6
  57. package/dist/commands/output.d.ts +7 -6
  58. package/dist/commands/output.js +11 -10
  59. package/dist/commands/packages.js +4 -4
  60. package/dist/commands/perf.js +1 -1
  61. package/dist/commands/permissions.js +49 -32
  62. package/dist/commands/plugins.d.ts +1 -1
  63. package/dist/commands/plugins.js +3 -3
  64. package/dist/commands/profiles.d.ts +6 -9
  65. package/dist/commands/profiles.js +8 -321
  66. package/dist/commands/projects.d.ts +9 -0
  67. package/dist/commands/projects.js +140 -8
  68. package/dist/commands/prune.js +5 -13
  69. package/dist/commands/refresh-rules.js +1 -1
  70. package/dist/commands/repo.d.ts +5 -7
  71. package/dist/commands/repo.js +34 -18
  72. package/dist/commands/resource-view.js +4 -0
  73. package/dist/commands/resume.d.ts +11 -7
  74. package/dist/commands/resume.js +82 -98
  75. package/dist/commands/route.d.ts +12 -0
  76. package/dist/commands/route.js +261 -0
  77. package/dist/commands/routines.d.ts +2 -3
  78. package/dist/commands/routines.js +120 -145
  79. package/dist/commands/rules.js +1 -1
  80. package/dist/commands/run-account-picker.d.ts +1 -1
  81. package/dist/commands/run-account-picker.js +2 -2
  82. package/dist/commands/run-broadcast.d.ts +21 -0
  83. package/dist/commands/run-broadcast.js +89 -0
  84. package/dist/commands/run-cloud.js +1 -1
  85. package/dist/commands/secrets-vault.d.ts +10 -0
  86. package/dist/commands/{login.js → secrets-vault.js} +34 -14
  87. package/dist/commands/secrets.d.ts +4 -4
  88. package/dist/commands/secrets.js +158 -159
  89. package/dist/commands/sessions-backfill.js +1 -1
  90. package/dist/commands/sessions-browser.d.ts +1 -1
  91. package/dist/commands/sessions-browser.js +9 -5
  92. package/dist/commands/sessions-export.js +2 -2
  93. package/dist/commands/sessions-inject.js +4 -5
  94. package/dist/commands/sessions-migrate.js +16 -27
  95. package/dist/commands/sessions-picker.d.ts +14 -0
  96. package/dist/commands/sessions-picker.js +209 -13
  97. package/dist/commands/sessions-resume.d.ts +7 -3
  98. package/dist/commands/sessions-resume.js +81 -33
  99. package/dist/commands/sessions-share.d.ts +25 -0
  100. package/dist/commands/sessions-share.js +166 -0
  101. package/dist/commands/sessions-stats.js +2 -2
  102. package/dist/commands/sessions.d.ts +75 -68
  103. package/dist/commands/sessions.js +144 -180
  104. package/dist/commands/setup-browser.js +1 -1
  105. package/dist/commands/setup-computer.js +1 -1
  106. package/dist/commands/setup-fleet.js +3 -0
  107. package/dist/commands/setup-mine.d.ts +7 -3
  108. package/dist/commands/setup-mine.js +13 -8
  109. package/dist/commands/setup-preferences.js +2 -2
  110. package/dist/commands/setup-secrets.js +2 -2
  111. package/dist/commands/setup-watchdog.js +2 -2
  112. package/dist/commands/setup.js +7 -2
  113. package/dist/commands/share.d.ts +65 -0
  114. package/dist/commands/share.js +253 -20
  115. package/dist/commands/skills.js +3 -3
  116. package/dist/commands/snapshot.d.ts +2 -2
  117. package/dist/commands/snapshot.js +9 -9
  118. package/dist/commands/ssh.d.ts +1 -1
  119. package/dist/commands/ssh.js +186 -64
  120. package/dist/commands/subagents.js +1 -1
  121. package/dist/commands/sync.js +24 -9
  122. package/dist/commands/teams.d.ts +2 -2
  123. package/dist/commands/teams.js +9 -18
  124. package/dist/commands/tmux.js +5 -1
  125. package/dist/commands/trash.js +1 -1
  126. package/dist/commands/usage.d.ts +1 -1
  127. package/dist/commands/usage.js +2 -2
  128. package/dist/commands/utils.d.ts +4 -14
  129. package/dist/commands/utils.js +6 -27
  130. package/dist/commands/versions.js +2 -2
  131. package/dist/commands/view.d.ts +9 -77
  132. package/dist/commands/view.js +23 -8
  133. package/dist/commands/watchdog.js +1 -1
  134. package/dist/commands/webhook.js +25 -34
  135. package/dist/commands/workflows.js +1 -1
  136. package/dist/index.js +1 -1
  137. package/dist/lib/account-capabilities.d.ts +39 -0
  138. package/dist/lib/account-capabilities.js +59 -0
  139. package/dist/lib/account-catalog.js +1 -1
  140. package/dist/lib/account-registry.d.ts +66 -0
  141. package/dist/lib/account-registry.js +151 -5
  142. package/dist/lib/{rotate.d.ts → accounting/rotate.d.ts} +4 -4
  143. package/dist/lib/{rotate.js → accounting/rotate.js} +8 -8
  144. package/dist/lib/{usage.d.ts → accounting/usage.d.ts} +4 -4
  145. package/dist/lib/{usage.js → accounting/usage.js} +11 -11
  146. package/dist/lib/agent-spec/provider.js +1 -1
  147. package/dist/lib/agents.d.ts +72 -4
  148. package/dist/lib/agents.js +231 -199
  149. package/dist/lib/answer-router.d.ts +2 -2
  150. package/dist/lib/ask-classifier.d.ts +1 -1
  151. package/dist/lib/ask-classifier.js +1 -1
  152. package/dist/lib/audit/log.js +1 -1
  153. package/dist/lib/auth-health.d.ts +1 -1
  154. package/dist/lib/auth-health.js +2 -2
  155. package/dist/lib/brand.js +1 -1
  156. package/dist/lib/browser/caller-identity.d.ts +28 -0
  157. package/dist/lib/browser/caller-identity.js +156 -0
  158. package/dist/lib/browser/cdp.js +5 -1
  159. package/dist/lib/browser/chrome.js +12 -1
  160. package/dist/lib/browser/drivers/ssh.d.ts +1 -1
  161. package/dist/lib/browser/drivers/ssh.js +3 -2
  162. package/dist/lib/browser/hygiene.d.ts +10 -2
  163. package/dist/lib/browser/hygiene.js +7 -4
  164. package/dist/lib/browser/ipc.d.ts +22 -2
  165. package/dist/lib/browser/ipc.js +185 -21
  166. package/dist/lib/browser/profiles.d.ts +69 -5
  167. package/dist/lib/browser/profiles.js +135 -13
  168. package/dist/lib/browser/remote-control.d.ts +2 -2
  169. package/dist/lib/browser/remote-control.js +3 -3
  170. package/dist/lib/browser/runtime-state.d.ts +79 -0
  171. package/dist/lib/browser/runtime-state.js +119 -1
  172. package/dist/lib/browser/service.d.ts +137 -2
  173. package/dist/lib/browser/service.js +492 -54
  174. package/dist/lib/browser/sessions-list.d.ts +2 -1
  175. package/dist/lib/browser/sessions-list.js +4 -13
  176. package/dist/lib/browser/types.d.ts +19 -1
  177. package/dist/lib/budget/config.js +1 -1
  178. package/dist/lib/budget/ledger.js +1 -1
  179. package/dist/lib/byok-usage.js +1 -1
  180. package/dist/lib/capabilities.js +3 -15
  181. package/dist/lib/catchup.d.ts +1 -1
  182. package/dist/lib/catchup.js +1 -1
  183. package/dist/lib/cloud/dispatch.js +1 -1
  184. package/dist/lib/cloud/host.d.ts +3 -3
  185. package/dist/lib/cloud/host.js +5 -5
  186. package/dist/lib/cloud/rush.d.ts +9 -21
  187. package/dist/lib/cloud/rush.js +33 -120
  188. package/dist/lib/cloud/types.d.ts +2 -2
  189. package/dist/lib/commands.js +3 -13
  190. package/dist/lib/computer/actions.d.ts +36 -0
  191. package/dist/lib/computer/actions.js +162 -0
  192. package/dist/lib/computer/dispatch.d.ts +2 -2
  193. package/dist/lib/computer/dispatch.js +2 -2
  194. package/dist/lib/computer/sessions-list.d.ts +3 -3
  195. package/dist/lib/computer/sessions-list.js +2 -2
  196. package/dist/lib/config-keys.d.ts +2 -1
  197. package/dist/lib/config-keys.js +8 -4
  198. package/dist/lib/config-machine-keys.d.ts +4 -2
  199. package/dist/lib/config-machine-keys.js +5 -2
  200. package/dist/lib/crabbox/lease.js +9 -1
  201. package/dist/lib/crabbox/runtimes.d.ts +32 -7
  202. package/dist/lib/crabbox/runtimes.js +72 -30
  203. package/dist/lib/{daemon.d.ts → daemon/daemon.d.ts} +59 -1
  204. package/dist/lib/{daemon.js → daemon/daemon.js} +237 -49
  205. package/dist/lib/daemon-services.d.ts +1 -1
  206. package/dist/lib/daemon-services.js +5 -0
  207. package/dist/lib/daemon-ticks.d.ts +25 -0
  208. package/dist/lib/daemon-ticks.js +31 -1
  209. package/dist/lib/daemon-webhooks.d.ts +104 -0
  210. package/dist/lib/daemon-webhooks.js +215 -0
  211. package/dist/lib/device-config.d.ts +85 -75
  212. package/dist/lib/device-config.js +280 -142
  213. package/dist/lib/devices/config-migration.d.ts +29 -34
  214. package/dist/lib/devices/config-migration.js +209 -130
  215. package/dist/lib/devices/connect.d.ts +2 -2
  216. package/dist/lib/devices/connect.js +2 -2
  217. package/dist/lib/devices/discovery-policy.d.ts +30 -0
  218. package/dist/lib/devices/discovery-policy.js +101 -0
  219. package/dist/lib/devices/fleet-inventory.js +8 -3
  220. package/dist/lib/devices/harness-inventory.d.ts +1 -1
  221. package/dist/lib/devices/harness-inventory.js +12 -3
  222. package/dist/lib/devices/known-hosts.js +1 -1
  223. package/dist/lib/devices/pool.d.ts +10 -5
  224. package/dist/lib/devices/pool.js +5 -7
  225. package/dist/lib/devices/registry.d.ts +1 -1
  226. package/dist/lib/devices/registry.js +1 -1
  227. package/dist/lib/devices/resolve-profile.d.ts +2 -2
  228. package/dist/lib/devices/resolve-profile.js +2 -2
  229. package/dist/lib/devices/resolve-target.d.ts +1 -1
  230. package/dist/lib/devices/resolve-target.js +4 -4
  231. package/dist/lib/devices/self-host.d.ts +1 -1
  232. package/dist/lib/devices/self-host.js +3 -3
  233. package/dist/lib/devices/ssh-config.d.ts +1 -1
  234. package/dist/lib/devices/stats-cache.js +1 -1
  235. package/dist/lib/devices/sync.d.ts +3 -1
  236. package/dist/lib/devices/sync.js +3 -3
  237. package/dist/lib/doctor-diff.js +4 -4
  238. package/dist/lib/drift-sync.js +2 -2
  239. package/dist/lib/drift.js +2 -2
  240. package/dist/lib/event-families.d.ts +1 -1
  241. package/dist/lib/event-stream.d.ts +1 -1
  242. package/dist/lib/event-stream.js +2 -2
  243. package/dist/lib/events-ingest.js +2 -2
  244. package/dist/lib/exec.d.ts +4 -4
  245. package/dist/lib/exec.js +11 -11
  246. package/dist/lib/factory/snapshot.d.ts +1 -1
  247. package/dist/lib/factory/snapshot.js +1 -1
  248. package/dist/lib/{activity.d.ts → feed/activity.d.ts} +1 -1
  249. package/dist/lib/{activity.js → feed/activity.js} +7 -7
  250. package/dist/lib/{events.d.ts → feed/events.d.ts} +2 -2
  251. package/dist/lib/{events.js → feed/events.js} +5 -5
  252. package/dist/lib/{feed.js → feed/feed.js} +4 -4
  253. package/dist/lib/feed-outcome.d.ts +1 -1
  254. package/dist/lib/feed-policy.d.ts +1 -1
  255. package/dist/lib/feed-policy.js +1 -1
  256. package/dist/lib/feed-post.d.ts +1 -1
  257. package/dist/lib/feed-post.js +1 -1
  258. package/dist/lib/feed-ranking.d.ts +1 -1
  259. package/dist/lib/fleet/apply.d.ts +0 -6
  260. package/dist/lib/fleet/apply.js +18 -45
  261. package/dist/lib/fleet/auth-sync.d.ts +16 -35
  262. package/dist/lib/fleet/auth-sync.js +16 -75
  263. package/dist/lib/fleet/capture.js +8 -6
  264. package/dist/lib/fleet/manifest.js +23 -11
  265. package/dist/lib/fleet/types.d.ts +19 -7
  266. package/dist/lib/fleet-cache.d.ts +1 -1
  267. package/dist/lib/fleet-cache.js +1 -1
  268. package/dist/lib/format.d.ts +19 -0
  269. package/dist/lib/format.js +44 -1
  270. package/dist/lib/friction-heuristics.d.ts +1 -1
  271. package/dist/lib/git.d.ts +24 -1
  272. package/dist/lib/git.js +82 -38
  273. package/dist/lib/heal.js +3 -3
  274. package/dist/lib/hooks.d.ts +18 -0
  275. package/dist/lib/hooks.js +113 -1
  276. package/dist/lib/hosts/credentials.d.ts +30 -10
  277. package/dist/lib/hosts/credentials.js +38 -26
  278. package/dist/lib/hosts/dispatch.d.ts +3 -3
  279. package/dist/lib/hosts/dispatch.js +3 -3
  280. package/dist/lib/hosts/option.d.ts +3 -3
  281. package/dist/lib/hosts/option.js +7 -8
  282. package/dist/lib/hosts/passthrough.d.ts +17 -17
  283. package/dist/lib/hosts/passthrough.js +67 -50
  284. package/dist/lib/hosts/providers/devices.d.ts +1 -1
  285. package/dist/lib/hosts/providers/devices.js +1 -1
  286. package/dist/lib/hosts/reconcile.d.ts +1 -1
  287. package/dist/lib/hosts/reconcile.js +1 -1
  288. package/dist/lib/hosts/reconnect.d.ts +1 -1
  289. package/dist/lib/hosts/reconnect.js +2 -2
  290. package/dist/lib/hosts/registry.d.ts +5 -5
  291. package/dist/lib/hosts/registry.js +5 -5
  292. package/dist/lib/hosts/remote-cmd.d.ts +10 -10
  293. package/dist/lib/hosts/remote-cmd.js +25 -18
  294. package/dist/lib/hosts/remote-os.d.ts +4 -4
  295. package/dist/lib/hosts/remote-os.js +4 -4
  296. package/dist/lib/hosts/remote-session-id.d.ts +2 -2
  297. package/dist/lib/hosts/remote-session-id.js +2 -2
  298. package/dist/lib/hosts/routing-flag.d.ts +3 -3
  299. package/dist/lib/hosts/routing-flag.js +4 -5
  300. package/dist/lib/hosts/run-target.d.ts +4 -4
  301. package/dist/lib/hosts/run-target.js +4 -4
  302. package/dist/lib/hosts/session-index.d.ts +2 -2
  303. package/dist/lib/hosts/session-index.js +1 -1
  304. package/dist/lib/hosts/session-marker.d.ts +1 -1
  305. package/dist/lib/hosts/session-marker.js +1 -1
  306. package/dist/lib/hosts/types.d.ts +2 -2
  307. package/dist/lib/hosts/types.js +2 -2
  308. package/dist/lib/import.js +1 -1
  309. package/dist/lib/{migrate.d.ts → installations/migrate.d.ts} +13 -1
  310. package/dist/lib/{migrate.js → installations/migrate.js} +160 -40
  311. package/dist/lib/installations/resolve.js +1 -1
  312. package/dist/lib/installations/strategies.js +1 -1
  313. package/dist/lib/installations/update.js +2 -2
  314. package/dist/lib/{versions.d.ts → installations/versions.d.ts} +12 -3
  315. package/dist/lib/{versions.js → installations/versions.js} +51 -31
  316. package/dist/lib/isolation-boundary-report.js +1 -1
  317. package/dist/lib/linear-projects.d.ts +28 -0
  318. package/dist/lib/linear-projects.js +30 -0
  319. package/dist/lib/loop.js +1 -1
  320. package/dist/lib/mailbox-gc.js +1 -1
  321. package/dist/lib/mailbox.js +1 -1
  322. package/dist/lib/mcp-registry.d.ts +62 -0
  323. package/dist/lib/mcp-registry.js +177 -0
  324. package/dist/lib/mcp.d.ts +5 -0
  325. package/dist/lib/mcp.js +124 -307
  326. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  327. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  328. package/dist/lib/menubar/install-menubar.d.ts +7 -0
  329. package/dist/lib/menubar/install-menubar.js +24 -6
  330. package/dist/lib/menubar/snapshot.d.ts +7 -0
  331. package/dist/lib/menubar/snapshot.js +8 -6
  332. package/dist/lib/models.js +1 -1
  333. package/dist/lib/monitors/config.d.ts +12 -0
  334. package/dist/lib/monitors/config.js +3 -0
  335. package/dist/lib/monitors/dispatch.js +26 -5
  336. package/dist/lib/monitors/engine.js +10 -0
  337. package/dist/lib/monitors/sources/webhook.d.ts +1 -1
  338. package/dist/lib/monitors/state.d.ts +42 -0
  339. package/dist/lib/monitors/state.js +30 -0
  340. package/dist/lib/notify.d.ts +1 -1
  341. package/dist/lib/observe-aliases.d.ts +3 -3
  342. package/dist/lib/observe-aliases.js +3 -21
  343. package/dist/lib/output/git-output.js +2 -2
  344. package/dist/lib/overdue.d.ts +1 -1
  345. package/dist/lib/overdue.js +1 -1
  346. package/dist/lib/permissions-registry.d.ts +65 -0
  347. package/dist/lib/permissions-registry.js +599 -0
  348. package/dist/lib/permissions.d.ts +24 -13
  349. package/dist/lib/permissions.js +52 -271
  350. package/dist/lib/picker.d.ts +16 -0
  351. package/dist/lib/picker.js +33 -3
  352. package/dist/lib/placement.d.ts +1 -1
  353. package/dist/lib/placement.js +4 -4
  354. package/dist/lib/platform/paths.d.ts +8 -0
  355. package/dist/lib/platform/paths.js +11 -0
  356. package/dist/lib/platform/posixpath.js +3 -3
  357. package/dist/lib/{plugin-marketplace.d.ts → plugins/plugin-marketplace.d.ts} +1 -1
  358. package/dist/lib/{plugin-marketplace.js → plugins/plugin-marketplace.js} +2 -2
  359. package/dist/lib/{plugins.d.ts → plugins/plugins.d.ts} +1 -1
  360. package/dist/lib/{plugins.js → plugins/plugins.js} +7 -7
  361. package/dist/lib/{skills.d.ts → plugins/skills.d.ts} +1 -1
  362. package/dist/lib/{skills.js → plugins/skills.js} +7 -7
  363. package/dist/lib/pricing/cost.d.ts +1 -1
  364. package/dist/lib/pricing/cost.js +1 -1
  365. package/dist/lib/profiles-presets.d.ts +1 -1
  366. package/dist/lib/profiles-presets.js +1 -1
  367. package/dist/lib/profiles.js +2 -2
  368. package/dist/lib/project-import.js +4 -1
  369. package/dist/lib/project-key.js +7 -0
  370. package/dist/lib/project-launch.d.ts +1 -1
  371. package/dist/lib/project-launch.js +3 -3
  372. package/dist/lib/project-pull.d.ts +128 -0
  373. package/dist/lib/project-pull.js +384 -0
  374. package/dist/lib/project-root.d.ts +2 -2
  375. package/dist/lib/project-root.js +2 -2
  376. package/dist/lib/project-status.js +1 -1
  377. package/dist/lib/projects.d.ts +23 -0
  378. package/dist/lib/projects.js +29 -6
  379. package/dist/lib/refresh.d.ts +12 -1
  380. package/dist/lib/refresh.js +16 -9
  381. package/dist/lib/registry.d.ts +9 -2
  382. package/dist/lib/registry.js +11 -4
  383. package/dist/lib/resources.d.ts +2 -2
  384. package/dist/lib/resources.js +2 -2
  385. package/dist/lib/routers.d.ts +81 -0
  386. package/dist/lib/routers.js +153 -0
  387. package/dist/lib/routine-context.d.ts +1 -0
  388. package/dist/lib/routine-context.js +7 -2
  389. package/dist/lib/routine-notify-owner.d.ts +1 -1
  390. package/dist/lib/routine-notify.d.ts +1 -1
  391. package/dist/lib/routine-notify.js +1 -1
  392. package/dist/lib/routine-process-cleanup.d.ts +1 -1
  393. package/dist/lib/routine-readiness.d.ts +1 -1
  394. package/dist/lib/routine-readiness.js +11 -4
  395. package/dist/lib/routines-placement.d.ts +12 -2
  396. package/dist/lib/routines-placement.js +20 -3
  397. package/dist/lib/routines-project.d.ts +1 -1
  398. package/dist/lib/routines-project.js +1 -1
  399. package/dist/lib/rules/compile.d.ts +1 -0
  400. package/dist/lib/rules/compile.js +10 -2
  401. package/dist/lib/rules/rules.js +1 -1
  402. package/dist/lib/run-notify.js +1 -1
  403. package/dist/lib/runner.d.ts +80 -2
  404. package/dist/lib/runner.js +261 -67
  405. package/dist/lib/sandbox.d.ts +1 -1
  406. package/dist/lib/scheduler.d.ts +1 -1
  407. package/dist/lib/scheduler.js +1 -1
  408. package/dist/lib/{routines.d.ts → scheduling/routines.d.ts} +54 -9
  409. package/dist/lib/{routines.js → scheduling/routines.js} +173 -14
  410. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  411. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  412. package/dist/lib/secrets/agent.js +2 -2
  413. package/dist/lib/secrets/audit.js +1 -1
  414. package/dist/lib/secrets/bundles.d.ts +4 -4
  415. package/dist/lib/secrets/bundles.js +8 -8
  416. package/dist/lib/secrets/headless.d.ts +16 -0
  417. package/dist/lib/secrets/headless.js +21 -0
  418. package/dist/lib/secrets/index.js +1 -1
  419. package/dist/lib/secrets/list-filter.d.ts +1 -1
  420. package/dist/lib/secrets/list-filter.js +2 -2
  421. package/dist/lib/secrets/push.d.ts +1 -1
  422. package/dist/lib/secrets/push.js +10 -12
  423. package/dist/lib/secrets/remote.d.ts +21 -17
  424. package/dist/lib/secrets/remote.js +39 -23
  425. package/dist/lib/secrets/vault.js +2 -2
  426. package/dist/lib/self-heal/checks/shadowing.js +1 -1
  427. package/dist/lib/self-heal/checks/shims.js +1 -1
  428. package/dist/lib/self-update.d.ts +39 -4
  429. package/dist/lib/self-update.js +78 -25
  430. package/dist/lib/serve/control.d.ts +1 -1
  431. package/dist/lib/serve/control.js +4 -4
  432. package/dist/lib/serve/data.d.ts +1 -1
  433. package/dist/lib/serve/data.js +1 -1
  434. package/dist/lib/serve/stream.js +1 -1
  435. package/dist/lib/service-manifest.d.ts +29 -0
  436. package/dist/lib/service-manifest.js +80 -0
  437. package/dist/lib/session/active.d.ts +59 -7
  438. package/dist/lib/session/active.js +158 -17
  439. package/dist/lib/session/bash-command.js +1 -1
  440. package/dist/lib/session/claude-accounts.d.ts +1 -1
  441. package/dist/lib/session/claude-accounts.js +1 -1
  442. package/dist/lib/session/db.d.ts +10 -2
  443. package/dist/lib/session/db.js +25 -6
  444. package/dist/lib/session/discover.d.ts +77 -0
  445. package/dist/lib/session/discover.js +130 -25
  446. package/dist/lib/session/fork.js +1 -1
  447. package/dist/lib/session/inject.d.ts +1 -1
  448. package/dist/lib/session/insights.d.ts +1 -1
  449. package/dist/lib/session/insights.js +1 -1
  450. package/dist/lib/session/live-metadata.d.ts +15 -0
  451. package/dist/lib/session/live-metadata.js +76 -0
  452. package/dist/lib/session/migrate-targets.d.ts +1 -1
  453. package/dist/lib/session/recovery.d.ts +1 -1
  454. package/dist/lib/session/recovery.js +2 -2
  455. package/dist/lib/session/remote-active.d.ts +10 -1
  456. package/dist/lib/session/remote-active.js +8 -3
  457. package/dist/lib/session/remote-bundle.d.ts +1 -1
  458. package/dist/lib/session/remote-bundle.js +2 -2
  459. package/dist/lib/session/remote-list.d.ts +15 -4
  460. package/dist/lib/session/remote-list.js +40 -3
  461. package/dist/lib/session/remote.d.ts +5 -5
  462. package/dist/lib/session/remote.js +13 -17
  463. package/dist/lib/session/resume-command.d.ts +3 -2
  464. package/dist/lib/session/resume-command.js +4 -3
  465. package/dist/lib/session/resume-owner.d.ts +3 -3
  466. package/dist/lib/session/resume-owner.js +3 -3
  467. package/dist/lib/session/session-cache.d.ts +12 -0
  468. package/dist/lib/session/session-cache.js +2 -0
  469. package/dist/lib/session/share-html.d.ts +55 -0
  470. package/dist/lib/session/share-html.js +319 -0
  471. package/dist/lib/session/shell-programs.js +1 -1
  472. package/dist/lib/session/state.js +5 -5
  473. package/dist/lib/session/team-filter.d.ts +1 -1
  474. package/dist/lib/session/team-filter.js +1 -1
  475. package/dist/lib/session/types.d.ts +3 -3
  476. package/dist/lib/session/width.d.ts +2 -2
  477. package/dist/lib/session/width.js +2 -2
  478. package/dist/lib/settings-manifest.d.ts +2 -0
  479. package/dist/lib/settings-manifest.js +81 -3
  480. package/dist/lib/share/delete.d.ts +21 -0
  481. package/dist/lib/share/delete.js +42 -0
  482. package/dist/lib/share/publish.d.ts +120 -0
  483. package/dist/lib/share/publish.js +243 -18
  484. package/dist/lib/share/worker-template.js +172 -9
  485. package/dist/lib/shims.js +35 -7
  486. package/dist/lib/smart-launch.d.ts +4 -4
  487. package/dist/lib/smart-launch.js +6 -4
  488. package/dist/lib/snapshot.d.ts +4 -4
  489. package/dist/lib/snapshot.js +2 -2
  490. package/dist/lib/ssh-exec.d.ts +1 -1
  491. package/dist/lib/ssh-exec.js +2 -2
  492. package/dist/lib/ssh-tunnel.d.ts +10 -10
  493. package/dist/lib/ssh-tunnel.js +12 -12
  494. package/dist/lib/staleness/checkers/hooks.d.ts +1 -1
  495. package/dist/lib/staleness/checkers/hooks.js +1 -1
  496. package/dist/lib/staleness/detectors/permissions.js +0 -23
  497. package/dist/lib/staleness/detectors/plugins.js +1 -1
  498. package/dist/lib/staleness/fingerprint.js +1 -1
  499. package/dist/lib/staleness/layers.d.ts +1 -1
  500. package/dist/lib/staleness/layers.js +1 -1
  501. package/dist/lib/staleness/writers/mcp.js +3 -1
  502. package/dist/lib/staleness/writers/plugins.js +1 -1
  503. package/dist/lib/staleness/writers/types.d.ts +8 -0
  504. package/dist/lib/startup/command-registry.d.ts +6 -147
  505. package/dist/lib/startup/command-registry.js +40 -303
  506. package/dist/lib/startup/dev-build.d.ts +0 -21
  507. package/dist/lib/startup/dev-build.js +29 -8
  508. package/dist/lib/state.d.ts +19 -1
  509. package/dist/lib/state.js +120 -51
  510. package/dist/lib/subagents.js +1 -1
  511. package/dist/lib/sync-status.js +1 -1
  512. package/dist/lib/sync-umbrella.d.ts +6 -1
  513. package/dist/lib/sync-umbrella.js +9 -4
  514. package/dist/lib/teams/agents.js +2 -2
  515. package/dist/lib/teams/registry.js +1 -1
  516. package/dist/lib/terminal/backends/vscodium-agent.js +1 -1
  517. package/dist/lib/terminal/engine.js +1 -1
  518. package/dist/lib/terminal/index.d.ts +4 -0
  519. package/dist/lib/terminal/index.js +3 -0
  520. package/dist/lib/terminal/inject.d.ts +2 -2
  521. package/dist/lib/terminal/inject.js +2 -2
  522. package/dist/lib/terminal/transport.js +1 -1
  523. package/dist/lib/tmux/index.d.ts +1 -1
  524. package/dist/lib/tmux/index.js +1 -1
  525. package/dist/lib/tmux/session.d.ts +21 -5
  526. package/dist/lib/tmux/session.js +76 -22
  527. package/dist/lib/triggers/handlers.d.ts +38 -3
  528. package/dist/lib/triggers/handlers.js +58 -7
  529. package/dist/lib/triggers/webhook.d.ts +113 -5
  530. package/dist/lib/triggers/webhook.js +223 -44
  531. package/dist/lib/types.d.ts +19 -7
  532. package/dist/lib/usage-fleet.d.ts +1 -1
  533. package/dist/lib/usage-fleet.js +1 -1
  534. package/dist/lib/usage-refresh.d.ts +1 -1
  535. package/dist/lib/usage-refresh.js +3 -3
  536. package/dist/lib/version-duplicates.js +2 -2
  537. package/dist/lib/view-types.d.ts +56 -0
  538. package/dist/lib/view-types.js +1 -0
  539. package/dist/lib/watchdog/rotate.d.ts +2 -2
  540. package/dist/lib/watchdog/rotate.js +3 -3
  541. package/dist/lib/watchdog/runner.d.ts +2 -3
  542. package/dist/lib/watchdog/runner.js +3 -4
  543. package/dist/lib/workflows.js +1 -1
  544. package/dist/lib/wrap.d.ts +33 -0
  545. package/dist/lib/wrap.js +70 -0
  546. package/package.json +2 -1
  547. package/scripts/postinstall.js +2 -2
  548. package/dist/commands/bench.d.ts +0 -2
  549. package/dist/commands/bench.js +0 -101
  550. package/dist/commands/cp.d.ts +0 -84
  551. package/dist/commands/cp.js +0 -231
  552. package/dist/commands/login.d.ts +0 -2
  553. package/dist/lib/resources/commands.d.ts +0 -46
  554. package/dist/lib/resources/commands.js +0 -211
  555. package/dist/lib/resources/hooks.d.ts +0 -16
  556. package/dist/lib/resources/hooks.js +0 -153
  557. package/dist/lib/resources/mcp.d.ts +0 -34
  558. package/dist/lib/resources/mcp.js +0 -250
  559. package/dist/lib/resources/memory.d.ts +0 -15
  560. package/dist/lib/resources/memory.js +0 -46
  561. package/dist/lib/resources/permissions.d.ts +0 -13
  562. package/dist/lib/resources/permissions.js +0 -202
  563. package/dist/lib/resources/rules.d.ts +0 -46
  564. package/dist/lib/resources/rules.js +0 -179
  565. package/dist/lib/resources/skills.d.ts +0 -37
  566. package/dist/lib/resources/skills.js +0 -247
  567. package/dist/lib/resources/subagents.d.ts +0 -46
  568. package/dist/lib/resources/subagents.js +0 -202
  569. /package/dist/lib/{feed.d.ts → feed/feed.d.ts} +0 -0
@@ -16,14 +16,14 @@ import * as path from 'path';
16
16
  import * as os from 'os';
17
17
  import { createHash } from 'node:crypto';
18
18
  import { gzipSync, gunzipSync } from 'node:zlib';
19
- import { ensureLockTarget, withFileLock } from './fs-atomic.js';
20
- import { getUserAgentsDir } from './state.js';
21
- import { stampProvenance, resetEventProvenanceForTest } from './event-provenance.js';
19
+ import { ensureLockTarget, withFileLock } from '../fs-atomic.js';
20
+ import { getUserAgentsDir } from '../state.js';
21
+ import { stampProvenance, resetEventProvenanceForTest } from '../event-provenance.js';
22
22
  /** Lazy perf warehouse write — avoids a hard cycle at module load. */
23
23
  function recordPerfTiming(payload) {
24
24
  try {
25
25
  // Dynamic import keeps events.ts free of a load-time dependency on perf/db.
26
- void import('./perf/spool.js').then(({ recordSample }) => {
26
+ void import('../perf/spool.js').then(({ recordSample }) => {
27
27
  recordSample({
28
28
  kind: 'perf.timing',
29
29
  label: payload.label,
@@ -128,7 +128,7 @@ const EVENT_TYPE_TABLE = {
128
128
  'perf.timing': true,
129
129
  'session.start': true, 'session.end': true,
130
130
  'webhook.received': true, 'webhook.authorized': true, 'webhook.rejected': true, 'webhook.matched': true,
131
- 'webhook.fired': true, 'webhook.handler.start': true, 'webhook.handler.end': true,
131
+ 'webhook.fired': true, 'webhook.failed': true, 'webhook.handler.start': true, 'webhook.handler.end': true,
132
132
  'plan.created': true, 'pr.opened': true, 'pr.merged': true, 'worktree.created': true,
133
133
  'worktree.removed': true, 'commit.created': true, 'pushed': true, 'subagent.spawned': true,
134
134
  'artifact.created': true, 'task.completed': true, 'checklist.created': true, 'status.posted': true,
@@ -24,10 +24,10 @@
24
24
  import * as fs from 'fs';
25
25
  import * as path from 'path';
26
26
  import * as yaml from 'yaml';
27
- import { stringifyDoc } from './yaml-io.js';
28
- import { getFeedDir, getUserAgentsDir } from './state.js';
29
- import { isAdmin, isHighConsequenceAllowed, isKnownOperator } from './operator.js';
30
- import { projectKeyFromCwd } from './project-key.js';
27
+ import { stringifyDoc } from '../yaml-io.js';
28
+ import { getFeedDir, getUserAgentsDir } from '../state.js';
29
+ import { isAdmin, isHighConsequenceAllowed, isKnownOperator } from '../operator.js';
30
+ import { projectKeyFromCwd } from '../project-key.js';
31
31
  /**
32
32
  * Stable block id for a session. One block per session -- a new question
33
33
  * replaces the previous one (the agent can only ask one question at a time).
@@ -1,4 +1,4 @@
1
- import type { OpenBlock } from './feed.js';
1
+ import type { OpenBlock } from './feed/feed.js';
2
2
  export type OutcomeKind = 'ticket' | 'pr' | 'worktree' | 'unassigned';
3
3
  /** Stable attribution of a block (or agent) to one deliverable. */
4
4
  export interface OutcomeRef {
@@ -1,4 +1,4 @@
1
- import { type OpenBlock, type AnswerRecord } from './feed.js';
1
+ import { type OpenBlock, type AnswerRecord } from './feed/feed.js';
2
2
  export type BlockClass = 'approval' | 'decision';
3
3
  export interface ClassPolicy {
4
4
  timeoutMinutes: number;
@@ -16,7 +16,7 @@ import * as fs from 'fs';
16
16
  import * as path from 'path';
17
17
  import * as yaml from 'yaml';
18
18
  import { getUserAgentsDir } from './state.js';
19
- import { recordAnswer, recordDefaulted, recordMessageReceipt, recordParked, } from './feed.js';
19
+ import { recordAnswer, recordDefaulted, recordMessageReceipt, recordParked, } from './feed/feed.js';
20
20
  import { enqueue, mailboxDir } from './mailbox.js';
21
21
  const POLICY_FILE = 'feed-policy.yaml';
22
22
  const COST_RANK = { low: 0, medium: 1, high: 2 };
@@ -1,4 +1,4 @@
1
- import { type ActivityEvent, type Attachment } from './activity.js';
1
+ import { type ActivityEvent, type Attachment } from './feed/activity.js';
2
2
  import { type PidSessionEntry } from './session/pid-registry.js';
3
3
  /** Soft cap so a runaway agent can't flood the activity lane with essays. */
4
4
  export declare const STATUS_POST_MAX_CHARS = 500;
@@ -16,7 +16,7 @@
16
16
  import * as fs from 'fs';
17
17
  import * as path from 'path';
18
18
  import { spawnSync } from 'child_process';
19
- import { appendActivityEvent, readRecentActivity, } from './activity.js';
19
+ import { appendActivityEvent, readRecentActivity, } from './feed/activity.js';
20
20
  import { resolveProjectNameForCwd, listProjectDefs } from './projects.js';
21
21
  import { getHistoryDir } from './state.js';
22
22
  import { machineId } from './machine-id.js';
@@ -1,4 +1,4 @@
1
- import type { OpenBlock, FeedAskStats } from './feed.js';
1
+ import type { OpenBlock, FeedAskStats } from './feed/feed.js';
2
2
  import type { Classification } from './ask-classifier.js';
3
3
  import type { ActiveSession } from './session/active.js';
4
4
  import type { SessionMeta } from './session/types.js';
@@ -45,12 +45,6 @@ export interface SourceAuth {
45
45
  /** The captured file payloads, keyed by agent. */
46
46
  filesByAgent: Map<string, AuthFilePayload[]>;
47
47
  }
48
- /**
49
- * Can we propagate `agent`'s login to a target on `targetPlatform`? False when
50
- * the agent has no portable file, the source can't provide it (bound / not
51
- * signed in), or the target consumes credentials from its own keychain.
52
- */
53
- export declare function canPushLogin(agent: string, targetPlatform: string | undefined, src: SourceAuth): boolean;
54
48
  export interface DiffContext {
55
49
  /** agents-cli version the source is on — the fleet target version. */
56
50
  targetCliVersion: string;
@@ -13,7 +13,7 @@ import { deviceIdentityArgs, sshTargetFor } from '../devices/connect.js';
13
13
  import { readyProbe, bootstrapAgentsCli } from '../hosts/ready.js';
14
14
  import { buildRemoteAgentsInvocation } from '../hosts/remote-cmd.js';
15
15
  import { sshExec } from '../ssh-exec.js';
16
- import { isPropagatableAgent, hasPortableAuthFiles, isCredentialSafeToPropagate, KEYCHAIN_BOUND_ON_MAC, buildAuthBundle, } from './auth-sync.js';
16
+ import { hasPortableAuthFiles } from './auth-sync.js';
17
17
  /** Strip a version suffix from an agent spec: `claude@latest` -> `claude`. */
18
18
  export function agentIdOf(spec) {
19
19
  return spec.split('@')[0].trim();
@@ -88,20 +88,6 @@ export function parseInstalledVersions(stdout) {
88
88
  return undefined;
89
89
  }
90
90
  }
91
- /**
92
- * Can we propagate `agent`'s login to a target on `targetPlatform`? False when
93
- * the agent has no portable file, the source can't provide it (bound / not
94
- * signed in), or the target consumes credentials from its own keychain.
95
- */
96
- export function canPushLogin(agent, targetPlatform, src) {
97
- if (!isPropagatableAgent(agent))
98
- return false;
99
- if (src.bound.has(agent))
100
- return false;
101
- if (targetPlatform === 'macos' && KEYCHAIN_BOUND_ON_MAC.has(agent))
102
- return false;
103
- return src.available.has(agent);
104
- }
105
91
  /** Pure: desired vs probed -> per-device diff + flat action list. */
106
92
  export function diffFleet(desired, probes, ctx) {
107
93
  const devices = [];
@@ -143,28 +129,24 @@ export function diffFleet(desired, probes, ctx) {
143
129
  rowActions.push({ device: d.device, kind: 'sync-config', detail: `sync config (${d.sync.join(', ')})` });
144
130
  }
145
131
  // login — per agent id, not per spec: `claude@all` names one id many times,
146
- // but login propagates once per agent (its credential is version-shared).
132
+ // but a login is established once per agent (its credential is version-shared).
147
133
  if (d.login === 'sync') {
148
134
  for (const id of [...new Set(d.agents.map(agentIdOf))]) {
149
- if (canPushLogin(id, probe.platform, ctx.sourceAuth)) {
150
- rowActions.push({ device: d.device, kind: 'push-login', agent: id, detail: `propagate ${id} login` });
151
- }
152
- else if (hasPortableAuthFiles(id) && !isCredentialSafeToPropagate(id)) {
153
- // Single-use rotating refresh tokens (e.g. droid/WorkOS) must never be
154
- // copied across boxes the first refresh invalidates every other copy.
155
- // Surface per-machine login guidance instead of silently propagating.
156
- loginBlocked.push(id);
157
- rowActions.push({ device: d.device, kind: 'needs-login', agent: id, detail: `${id} login uses a single-use rotating refresh token — log in on ${d.device} itself` });
158
- }
159
- else if (isPropagatableAgent(id) &&
160
- (ctx.sourceAuth.bound.has(id) || (probe.platform === 'macos' && KEYCHAIN_BOUND_ON_MAC.has(id)))) {
161
- // A login-propagation candidate we still can't push: the source token
162
- // is keychain-bound (unextractable), or the macOS target consumes its
163
- // own keychain. Surface those as manual — don't fake. Agents that were
164
- // never propagation candidates (no portable file), or a source that
165
- // simply isn't signed in, are silently skipped the same on every OS.
135
+ // SING-1b: a native OAuth / session login MUST NOT be copied between
136
+ // devices a rotating token invalidates the fleet on its next refresh
137
+ // (droid/WorkOS collapsed 10 boxes to 1 overnight). `apply` therefore no
138
+ // longer propagates any login; it surfaces per-box login / portable
139
+ // provider-account guidance for every agent that has a login to
140
+ // establish. An agent with no portable login file, or a source that
141
+ // isn't signed in, is silently skipped the same on every OS.
142
+ if (hasPortableAuthFiles(id)) {
166
143
  loginBlocked.push(id);
167
- rowActions.push({ device: d.device, kind: 'needs-login', agent: id, detail: `${id} needs a manual login` });
144
+ rowActions.push({
145
+ device: d.device,
146
+ kind: 'needs-login',
147
+ agent: id,
148
+ detail: `${id}: a native OAuth login can't be copied between devices (SING-1b) — log in on ${d.device} itself, or sync a portable provider account (agents accounts sync)`,
149
+ });
168
150
  }
169
151
  }
170
152
  }
@@ -414,17 +396,8 @@ export function reconcileDevice(row, device, ctx) {
414
396
  steps.push({ kind: 'sync-config', ok: syncOk, detail: `sync config (${row.desired.sync.join(', ') || 'default'})` });
415
397
  ok = ok && syncOk;
416
398
  }
417
- // 4. login propagation one bundle for all pushable agents on this device.
418
- const pushAgents = [...new Set(row.actions.filter((a) => a.kind === 'push-login').map((a) => a.agent))];
419
- if (pushAgents.length > 0) {
420
- const files = [];
421
- for (const agent of pushAgents)
422
- files.push(...(ctx.sourceAuth.filesByAgent.get(agent) ?? []));
423
- const bundle = buildAuthBundle(ctx.source, files);
424
- const r = sshAgents(['apply', '--recv-auth'], JSON.stringify(bundle));
425
- steps.push({ kind: 'push-login', ok: r.code === 0, detail: `propagate login: ${pushAgents.join(', ')}` });
426
- ok = ok && r.code === 0;
427
- }
399
+ // 4. Native login materialization does not exist. Every agent that needs a login is surfaced as
400
+ // `needs-login` (per-box login / portable-account guidance) in the diff above.
428
401
  // 5. secrets provisioning — LAST, and deliberately so. It is the most
429
402
  // sensitive mutation apply performs (credential VALUES crossing to another
430
403
  // machine), so every lower-risk step above is already recorded before we
@@ -1,19 +1,13 @@
1
1
  /**
2
- * Login/token propagation the "one login instead of ~48 OAuth flows" core of
3
- * `agents apply`.
4
- *
5
- * A source machine that is already signed in to a set of harnesses has portable
6
- * credential files on disk (verified per-agent locations below). `snapshotAuth`
7
- * captures those; `materializeAuth` writes them into the corresponding paths on
8
- * a target device. Transport is the caller's job — `apply` streams the bundle
9
- * over the existing (encrypted, authenticated) SSH channel via `sshExec`'s
10
- * stdin `input`, so no app-layer crypto is layered on top of SSH here.
2
+ * Native-login inventory for `agents apply` and `agents fleet login`.
3
+ * Native OAuth/session files are identified only to report device readiness;
4
+ * agents-cli never serializes or materializes them on another device.
11
5
  *
12
6
  * Honest boundary: on macOS, claude and antigravity keep their tokens in the
13
7
  * login keychain, ACL-bound to the harness process — unreadable by us. Those are
14
8
  * classified `bound` and surfaced for a one-time manual login, never faked.
15
9
  */
16
- import type { AuthFilePayload, AuthBundle, AuthSnapshotResult } from './types.js';
10
+ import type { AuthSnapshotResult } from './types.js';
17
11
  /** A portable credential file location, relative to $HOME. */
18
12
  interface AuthFileSpec {
19
13
  rel: string;
@@ -37,10 +31,18 @@ export declare const KEYCHAIN_BOUND_ON_MAC: ReadonlySet<string>;
37
31
  * made. See also `remote-login.ts` and `usage.ts` for the per-machine-login policy.
38
32
  */
39
33
  export declare const SINGLE_USE_ROTATING_REFRESH_AGENTS: ReadonlySet<string>;
40
- /** True when `agent`'s portable credential file(s) are safe to copy between
41
- * machines. Single-use rotating refresh tokens are never safe; keychain-bound
42
- * tokens are handled separately by the caller via {@link KEYCHAIN_BOUND_ON_MAC}. */
43
- export declare function isCredentialSafeToPropagate(agent: string): boolean;
34
+ /**
35
+ * Whether `agent`'s login may be copied between machines by `apply`. Always
36
+ * **false** now (RUSH-2527): every `FLEET_AUTH_FILES` entry is a native,
37
+ * rotating OAuth / session login, and the fleet-auth contract forbids copying any
38
+ * of them between devices (`docs/specifications.md` SING-1b) — not just the
39
+ * single-use-rotating subset (`SINGLE_USE_ROTATING_REFRESH_AGENTS`) that first
40
+ * motivated this gate. `apply` therefore never propagates a login; it surfaces
41
+ * per-box login / portable-account guidance instead. `snapshotAuth` reads no
42
+ * credential file as a result, so a native login never leaves its origin box.
43
+ * The `agent` parameter is retained for the stable call signature.
44
+ */
45
+ export declare function isCredentialSafeToPropagate(_agent: string): boolean;
44
46
  /** True when the agent stores credentials in portable files we can read. This
45
47
  * does NOT mean it is safe to propagate — check {@link isCredentialSafeToPropagate}. */
46
48
  export declare function hasPortableAuthFiles(agent: string): boolean;
@@ -113,25 +115,4 @@ export interface SnapshotOptions {
113
115
  * propagate, not an error.
114
116
  */
115
117
  export declare function snapshotAuth(agents: string[], opts: SnapshotOptions): AuthSnapshotResult;
116
- /** Assemble the plaintext bundle shipped to a target. */
117
- export declare function buildAuthBundle(source: string, files: AuthFilePayload[]): AuthBundle;
118
- export interface MaterializeOptions {
119
- /** Home directory to write credential files into. */
120
- home: string;
121
- }
122
- export interface MaterializeResult {
123
- /** Agent ids that received at least one file. */
124
- written: string[];
125
- /** `rel: reason` for any file that failed. */
126
- errors: string[];
127
- }
128
- /**
129
- * Write a captured auth bundle into a target home. Parent dirs are created; the
130
- * captured POSIX mode is restored (0600 for credentials). Writing through an
131
- * existing symlink lands in the agent's active version home, which is exactly
132
- * what per-version credential carry-forward expects.
133
- */
134
- export declare function materializeAuth(bundle: AuthBundle, opts: MaterializeOptions): MaterializeResult;
135
- /** Parse + validate a bundle received on stdin (the remote `--_recv-auth` path). */
136
- export declare function parseAuthBundle(raw: string): AuthBundle;
137
118
  export {};
@@ -1,13 +1,7 @@
1
1
  /**
2
- * Login/token propagation the "one login instead of ~48 OAuth flows" core of
3
- * `agents apply`.
4
- *
5
- * A source machine that is already signed in to a set of harnesses has portable
6
- * credential files on disk (verified per-agent locations below). `snapshotAuth`
7
- * captures those; `materializeAuth` writes them into the corresponding paths on
8
- * a target device. Transport is the caller's job — `apply` streams the bundle
9
- * over the existing (encrypted, authenticated) SSH channel via `sshExec`'s
10
- * stdin `input`, so no app-layer crypto is layered on top of SSH here.
2
+ * Native-login inventory for `agents apply` and `agents fleet login`.
3
+ * Native OAuth/session files are identified only to report device readiness;
4
+ * agents-cli never serializes or materializes them on another device.
11
5
  *
12
6
  * Honest boundary: on macOS, claude and antigravity keep their tokens in the
13
7
  * login keychain, ACL-bound to the harness process — unreadable by us. Those are
@@ -44,11 +38,19 @@ export const KEYCHAIN_BOUND_ON_MAC = new Set(['claude', 'antigravity']);
44
38
  * made. See also `remote-login.ts` and `usage.ts` for the per-machine-login policy.
45
39
  */
46
40
  export const SINGLE_USE_ROTATING_REFRESH_AGENTS = new Set(['droid']);
47
- /** True when `agent`'s portable credential file(s) are safe to copy between
48
- * machines. Single-use rotating refresh tokens are never safe; keychain-bound
49
- * tokens are handled separately by the caller via {@link KEYCHAIN_BOUND_ON_MAC}. */
50
- export function isCredentialSafeToPropagate(agent) {
51
- return !SINGLE_USE_ROTATING_REFRESH_AGENTS.has(agent);
41
+ /**
42
+ * Whether `agent`'s login may be copied between machines by `apply`. Always
43
+ * **false** now (RUSH-2527): every `FLEET_AUTH_FILES` entry is a native,
44
+ * rotating OAuth / session login, and the fleet-auth contract forbids copying any
45
+ * of them between devices (`docs/specifications.md` SING-1b) — not just the
46
+ * single-use-rotating subset (`SINGLE_USE_ROTATING_REFRESH_AGENTS`) that first
47
+ * motivated this gate. `apply` therefore never propagates a login; it surfaces
48
+ * per-box login / portable-account guidance instead. `snapshotAuth` reads no
49
+ * credential file as a result, so a native login never leaves its origin box.
50
+ * The `agent` parameter is retained for the stable call signature.
51
+ */
52
+ export function isCredentialSafeToPropagate(_agent) {
53
+ return false;
52
54
  }
53
55
  /** True when the agent stores credentials in portable files we can read. This
54
56
  * does NOT mean it is safe to propagate — check {@link isCredentialSafeToPropagate}. */
@@ -185,64 +187,3 @@ export function snapshotAuth(agents, opts) {
185
187
  }
186
188
  return { files, bound };
187
189
  }
188
- /** Assemble the plaintext bundle shipped to a target. */
189
- export function buildAuthBundle(source, files) {
190
- return { v: 1, source, files };
191
- }
192
- /**
193
- * Write a captured auth bundle into a target home. Parent dirs are created; the
194
- * captured POSIX mode is restored (0600 for credentials). Writing through an
195
- * existing symlink lands in the agent's active version home, which is exactly
196
- * what per-version credential carry-forward expects.
197
- */
198
- export function materializeAuth(bundle, opts) {
199
- const written = new Set();
200
- const errors = [];
201
- for (const f of bundle.files) {
202
- const abs = path.join(opts.home, f.rel);
203
- try {
204
- fs.mkdirSync(path.dirname(abs), { recursive: true });
205
- fs.writeFileSync(abs, Buffer.from(f.contentB64, 'base64'));
206
- fs.chmodSync(abs, f.mode || 0o600);
207
- written.add(f.agent);
208
- }
209
- catch (e) {
210
- errors.push(`${f.rel}: ${e.message}`);
211
- }
212
- }
213
- return { written: [...written], errors };
214
- }
215
- /** Parse + validate a bundle received on stdin (the remote `--_recv-auth` path). */
216
- export function parseAuthBundle(raw) {
217
- let doc;
218
- try {
219
- doc = JSON.parse(raw);
220
- }
221
- catch (e) {
222
- throw new Error(`auth bundle is not valid JSON: ${e.message}`);
223
- }
224
- if (typeof doc !== 'object' || doc === null)
225
- throw new Error('auth bundle must be an object.');
226
- const o = doc;
227
- if (o.v !== 1)
228
- throw new Error(`unsupported auth bundle version ${JSON.stringify(o.v)}.`);
229
- if (typeof o.source !== 'string')
230
- throw new Error('auth bundle missing source.');
231
- if (!Array.isArray(o.files))
232
- throw new Error('auth bundle missing files[].');
233
- for (const f of o.files) {
234
- if (typeof f !== 'object' || f === null ||
235
- typeof f.agent !== 'string' ||
236
- typeof f.rel !== 'string' ||
237
- typeof f.contentB64 !== 'string' ||
238
- typeof f.mode !== 'number') {
239
- throw new Error('auth bundle has a malformed file entry.');
240
- }
241
- // Reject path traversal — rel must stay under $HOME.
242
- const rel = f.rel;
243
- if (rel.startsWith('/') || rel.split('/').includes('..')) {
244
- throw new Error(`auth bundle rejected unsafe path: ${rel}`);
245
- }
246
- }
247
- return doc;
248
- }
@@ -28,12 +28,11 @@ export function captureFleet(prev, inputs) {
28
28
  // when the manifest didn't already pin one for that device.
29
29
  //
30
30
  // A device absent from `inputs.devices` drops OUT of the roster — that is the
31
- // intended "live state is the source of truth for WHICH devices exist". But
32
- // `fleet.devices.<name>.config` is also the operator-config store, and a
33
- // capture run from a box whose registry has not seen a peer would silently
34
- // erase that peer's settings. Observed for real: capturing on yosemite-s0
35
- // deleted zion's whole config block from the shared agents.yaml. So carry a
36
- // dropped device's `config:` forward — config only, never its roster fields.
31
+ // intended "live state is the source of truth for WHICH devices exist". A
32
+ // leftover `config:` on an override is the LEGACY #2458 store (folded into
33
+ // per-device docs by migrateDeviceConfigStores). Carry it forward so a
34
+ // capture from a box that has not seen a peer cannot re-strip a not-yet-
35
+ // migrated peer's settings. Config only, never its roster fields.
37
36
  const devices = {};
38
37
  for (const [name, prevOverride] of Object.entries(prevDevices)) {
39
38
  if (inputs.devices.includes(name))
@@ -56,6 +55,9 @@ export function captureFleet(prev, inputs) {
56
55
  defaults: prev?.defaults ?? inputs.defaults ?? {},
57
56
  devices,
58
57
  };
58
+ if (prev?.discovery && Object.keys(prev.discovery).length > 0) {
59
+ manifest.discovery = { ...prev.discovery };
60
+ }
59
61
  const bundles = inputs.secretsBundles ?? prev?.secrets?.bundles;
60
62
  if (bundles && bundles.length > 0)
61
63
  manifest.secrets = { bundles: [...bundles].sort() };
@@ -34,10 +34,16 @@ function validateDefaults(v, where) {
34
34
  if (o.sync !== undefined && !isStringArray(o.sync)) {
35
35
  throw new Error(`fleet: ${where}.sync must be a list of scope names (e.g. [user]).`);
36
36
  }
37
+ if (o.config !== undefined && (typeof o.config !== 'object' || o.config === null || Array.isArray(o.config))) {
38
+ throw new Error(`fleet: ${where}.config must be a mapping of config keys to values.`);
39
+ }
37
40
  return {
38
41
  agents: o.agents,
39
42
  sync: o.sync,
40
43
  login: validateLogin(o.login, where),
44
+ // `config:` is operator config (`agents devices config`); inert to the
45
+ // reconcile engine but part of the manifest shape.
46
+ config: o.config,
41
47
  };
42
48
  }
43
49
  /** Validate a raw `fleet:` object (already YAML-parsed) into a typed manifest. */
@@ -58,17 +64,10 @@ export function parseFleetManifest(raw) {
58
64
  const map = {};
59
65
  for (const [name, ov] of Object.entries(o.devices)) {
60
66
  // An empty entry (`device: {}`) inherits defaults — represent as {}.
61
- const merged = ov == null ? {} : validateDefaults(ov, `devices.${name}`);
62
- // `config:` is the operator-config block (`agents devices config`) —
63
- // inert to the reconcile engine but part of the manifest shape.
64
- const cfg = ov != null ? ov.config : undefined;
65
- if (cfg !== undefined) {
66
- if (typeof cfg !== 'object' || cfg === null || Array.isArray(cfg)) {
67
- throw new Error(`fleet: devices.${name}.config must be a mapping of config keys to values.`);
68
- }
69
- merged.config = cfg;
70
- }
71
- map[name] = merged;
67
+ // (A per-device `config:` here is the LEGACY #2458 store — parsed through
68
+ // so reads stay lossless, folded into the per-device doc by the config
69
+ // migration, never written by current code.)
70
+ map[name] = ov == null ? {} : validateDefaults(ov, `devices.${name}`);
72
71
  }
73
72
  devices = map;
74
73
  }
@@ -76,6 +75,19 @@ export function parseFleetManifest(raw) {
76
75
  throw new Error(`fleet: devices must be the string 'all' or a mapping of device -> overrides (got ${JSON.stringify(o.devices)}).`);
77
76
  }
78
77
  const manifest = { defaults, devices };
78
+ if (o.discovery !== undefined) {
79
+ if (typeof o.discovery !== 'object' || o.discovery === null || Array.isArray(o.discovery)) {
80
+ throw new Error('fleet: discovery must be a mapping of device name to approved or ignored.');
81
+ }
82
+ const discovery = {};
83
+ for (const [name, status] of Object.entries(o.discovery)) {
84
+ if (status !== 'approved' && status !== 'ignored') {
85
+ throw new Error(`fleet: discovery.${name} must be approved or ignored.`);
86
+ }
87
+ discovery[name] = status;
88
+ }
89
+ manifest.discovery = discovery;
90
+ }
79
91
  // Additive, backward-compatible extras (captured by `agents fleet capture`).
80
92
  if (o.secrets !== undefined) {
81
93
  if (typeof o.secrets !== 'object' || o.secrets === null || Array.isArray(o.secrets)) {
@@ -27,6 +27,14 @@ export interface FleetDefaults {
27
27
  sync?: string[];
28
28
  /** Login propagation strategy. Default `'sync'`. */
29
29
  login?: FleetLoginMode;
30
+ /**
31
+ * Fleet-wide config defaults (`agents devices config --fleet <key> <value>`)
32
+ * — the middle layer of the device-config store: built-in default <
33
+ * `fleet.defaults.config` < per-device `devices/<name>/agents.yaml`
34
+ * `config:`. Inert to the reconcile engine (apply never pushes it; it takes
35
+ * effect through the config read path). Names and non-secret values only.
36
+ */
37
+ config?: Record<string, unknown>;
30
38
  }
31
39
  /** Per-device override; any omitted field inherits from `defaults`. */
32
40
  export interface FleetDeviceOverride {
@@ -34,12 +42,10 @@ export interface FleetDeviceOverride {
34
42
  sync?: string[];
35
43
  login?: FleetLoginMode;
36
44
  /**
37
- * Operator config for this device, written by `agents devices config <name>`
38
- * — the device-scope keys of the `lib/device-config.ts` registry (maxAgents,
39
- * schedulerEnabled, ssh*, autoLaunch*, notes, …). This is the ONE store for
40
- * per-device settings: central, synced, and backed up with agents.yaml.
41
- * LEAK-FREE like the rest of the manifest — names and non-secret values only
42
- * (a secrets-bundle NAME is fine; a credential value never is).
45
+ * LEGACY home of per-device operator config (#2458); the current store is the
46
+ * per-device doc `devices/<name>/agents.yaml` `config:` block. Existing
47
+ * values are folded into the device doc by lib/devices/config-migration.ts
48
+ * and stripped here current code never writes this field.
43
49
  */
44
50
  config?: Record<string, unknown>;
45
51
  }
@@ -68,6 +74,12 @@ export interface FleetManifest {
68
74
  };
69
75
  /** Routine NAMES that should be active on the fleet (files sync via the repo). */
70
76
  routines?: string[];
77
+ /**
78
+ * Portable user decisions for Tailscale discovery. A name maps to `approved`
79
+ * or `ignored`; absence means pending. Connection metadata remains in each
80
+ * machine's local device registry and is never committed.
81
+ */
82
+ discovery?: Record<string, 'approved' | 'ignored'>;
71
83
  }
72
84
  /**
73
85
  * A device's desired state after merging defaults with its override and
@@ -118,7 +130,7 @@ export interface DeviceProbe {
118
130
  note?: string;
119
131
  }
120
132
  /** One planned action against a device, in a single reconcile dimension. */
121
- export type FleetActionKind = 'install-cli' | 'upgrade-cli' | 'add-agent' | 'sync-config' | 'push-login' | 'needs-login'
133
+ export type FleetActionKind = 'install-cli' | 'upgrade-cli' | 'add-agent' | 'sync-config' | 'needs-login'
122
134
  /** Push a declared secrets bundle to the device over SSH. Opt-in only
123
135
  * (`--provision-secrets`) and gated on a pinned host key, because this moves
124
136
  * credential VALUES to another machine (RUSH-1968). */
@@ -12,7 +12,7 @@
12
12
  * `runFleetStatusPublish` for the fleet-status mirror); this module is the read
13
13
  * side only.
14
14
  */
15
- import { type UsageSnapshot } from './usage.js';
15
+ import { type UsageSnapshot } from './accounting/usage.js';
16
16
  import { type FleetStatusRow } from './fleet-status.js';
17
17
  /**
18
18
  * The fleet-status union the daemon publishes (own row) and the fleet-status
@@ -12,7 +12,7 @@
12
12
  * `runFleetStatusPublish` for the fleet-status mirror); this module is the read
13
13
  * side only.
14
14
  */
15
- import { readClaudeUsageCache } from './usage.js';
15
+ import { readClaudeUsageCache } from './accounting/usage.js';
16
16
  import { readHeadroomEntry } from './usage-refresh.js';
17
17
  import { readFleetStatus as readFleetStatusMirror } from './fleet-status.js';
18
18
  /**
@@ -50,6 +50,25 @@ export declare function truncate(s: string, max: number): string;
50
50
  export declare function relTime(iso: string): string;
51
51
  /** Format a millisecond duration as "45s", "3m", "2h 5m", "1d 3h". */
52
52
  export declare function humanDuration(ms: number): string;
53
+ /**
54
+ * Human-readable byte size. Previously copy-pasted into five files
55
+ * (`commands/prune.ts`, `commands/share.ts`, `commands/inspect.ts`,
56
+ * `commands/sessions.ts`, `lib/browser/sessions-list.ts`) — this is the
57
+ * canonical home.
58
+ */
59
+ export declare function formatBytes(n: number): string;
60
+ /**
61
+ * True when an error came from the user cancelling a prompt (Ctrl+C).
62
+ *
63
+ * Lives here rather than in `commands/utils.ts` so `lib/` callers
64
+ * (`drift-sync.ts`, `refresh.ts`) don't have to import upward out of `lib/`
65
+ * into the command layer. `commands/utils.ts` re-exports it.
66
+ */
67
+ export declare function isPromptCancelled(err: unknown): boolean;
68
+ /** True when stdin/stdout are attached to a real terminal. */
69
+ export declare function isInteractiveTerminal(): boolean;
70
+ /** Parse a comma-separated CLI list, trimming whitespace and dropping empties. */
71
+ export declare function parseCommaSeparatedList(value: string | undefined): string[];
53
72
  /**
54
73
  * Visible column width of `s`, ignoring ANSI SGR color codes (e.g. chalk
55
74
  * wrappers). Matches the full CSI sequence including the `\x1b` escape.
@@ -9,7 +9,7 @@
9
9
  */
10
10
  import chalk from 'chalk';
11
11
  import { readSync } from 'node:fs';
12
- import { emitFriction } from './events.js';
12
+ import { emitFriction } from './feed/events.js';
13
13
  /**
14
14
  * Render a fatal error to the right stream. Pure — no I/O, no `process.exit` — so
15
15
  * the human-vs-agent split is unit-testable. A `--json` caller gets
@@ -97,6 +97,49 @@ export function humanDuration(ms) {
97
97
  const hh = h % 24;
98
98
  return hh ? `${d}d ${hh}h` : `${d}d`;
99
99
  }
100
+ /**
101
+ * Human-readable byte size. Previously copy-pasted into five files
102
+ * (`commands/prune.ts`, `commands/share.ts`, `commands/inspect.ts`,
103
+ * `commands/sessions.ts`, `lib/browser/sessions-list.ts`) — this is the
104
+ * canonical home.
105
+ */
106
+ export function formatBytes(n) {
107
+ if (n < 1024)
108
+ return `${n} B`;
109
+ const units = ['KB', 'MB', 'GB', 'TB'];
110
+ let size = n / 1024;
111
+ let unit = 0;
112
+ while (size >= 1024 && unit < units.length - 1) {
113
+ size /= 1024;
114
+ unit++;
115
+ }
116
+ return `${size < 10 ? size.toFixed(1) : Math.round(size)} ${units[unit]}`;
117
+ }
118
+ /**
119
+ * True when an error came from the user cancelling a prompt (Ctrl+C).
120
+ *
121
+ * Lives here rather than in `commands/utils.ts` so `lib/` callers
122
+ * (`drift-sync.ts`, `refresh.ts`) don't have to import upward out of `lib/`
123
+ * into the command layer. `commands/utils.ts` re-exports it.
124
+ */
125
+ export function isPromptCancelled(err) {
126
+ return err instanceof Error && (err.name === 'ExitPromptError' ||
127
+ err.message.includes('force closed') ||
128
+ err.message.includes('User force closed'));
129
+ }
130
+ /** True when stdin/stdout are attached to a real terminal. */
131
+ export function isInteractiveTerminal() {
132
+ return Boolean(process.stdin.isTTY && process.stdout.isTTY);
133
+ }
134
+ /** Parse a comma-separated CLI list, trimming whitespace and dropping empties. */
135
+ export function parseCommaSeparatedList(value) {
136
+ if (!value)
137
+ return [];
138
+ return value
139
+ .split(',')
140
+ .map((item) => item.trim())
141
+ .filter(Boolean);
142
+ }
100
143
  /**
101
144
  * Visible column width of `s`, ignoring ANSI SGR color codes (e.g. chalk
102
145
  * wrappers). Matches the full CSI sequence including the `\x1b` escape.