@phnx-labs/agents-cli 1.22.35 → 1.22.37

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 (487) hide show
  1. package/CHANGELOG.md +666 -2
  2. package/README.md +75 -35
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.d.ts +15 -0
  5. package/dist/bootstrap.js +1211 -0
  6. package/dist/commands/accounts.d.ts +4 -11
  7. package/dist/commands/accounts.js +159 -27
  8. package/dist/commands/attach.js +17 -4
  9. package/dist/commands/audit.d.ts +8 -8
  10. package/dist/commands/audit.js +57 -47
  11. package/dist/commands/browser.js +15 -11
  12. package/dist/commands/cloud.js +1 -1
  13. package/dist/commands/commands.js +0 -11
  14. package/dist/commands/computer-actions.js +33 -0
  15. package/dist/commands/computer-sessions-picker.d.ts +21 -0
  16. package/dist/commands/computer-sessions-picker.js +141 -0
  17. package/dist/commands/computer.d.ts +16 -0
  18. package/dist/commands/computer.js +37 -0
  19. package/dist/commands/config.d.ts +17 -0
  20. package/dist/commands/config.js +401 -0
  21. package/dist/commands/cp.d.ts +84 -0
  22. package/dist/commands/cp.js +231 -0
  23. package/dist/commands/daemon.js +243 -14
  24. package/dist/commands/detach-core.d.ts +1 -1
  25. package/dist/commands/detach-core.js +12 -2
  26. package/dist/commands/detach.js +1 -1
  27. package/dist/commands/doctor.js +64 -5
  28. package/dist/commands/events.d.ts +24 -12
  29. package/dist/commands/events.js +144 -28
  30. package/dist/commands/exec.js +85 -41
  31. package/dist/commands/feed.d.ts +1 -1
  32. package/dist/commands/feed.js +16 -8
  33. package/dist/commands/focus.d.ts +33 -1
  34. package/dist/commands/focus.js +177 -17
  35. package/dist/commands/funnel.d.ts +1 -1
  36. package/dist/commands/go.js +9 -8
  37. package/dist/commands/harness-wizard.d.ts +1 -0
  38. package/dist/commands/harness-wizard.js +18 -20
  39. package/dist/commands/harness.d.ts +2 -0
  40. package/dist/commands/harness.js +59 -26
  41. package/dist/commands/hooks.js +0 -11
  42. package/dist/commands/inspect.d.ts +94 -1
  43. package/dist/commands/inspect.js +866 -40
  44. package/dist/commands/lease.d.ts +4 -4
  45. package/dist/commands/lease.js +6 -6
  46. package/dist/commands/login.js +0 -13
  47. package/dist/commands/logs.d.ts +2 -2
  48. package/dist/commands/logs.js +2 -2
  49. package/dist/commands/mcp.js +7 -2
  50. package/dist/commands/memory.js +7 -2
  51. package/dist/commands/message.d.ts +1 -1
  52. package/dist/commands/message.js +37 -6
  53. package/dist/commands/models.js +4 -0
  54. package/dist/commands/monitors.d.ts +0 -1
  55. package/dist/commands/monitors.js +199 -16
  56. package/dist/commands/open.d.ts +18 -0
  57. package/dist/commands/open.js +57 -0
  58. package/dist/commands/packages.js +2 -107
  59. package/dist/commands/plugins.js +6 -3
  60. package/dist/commands/profiles.d.ts +1 -0
  61. package/dist/commands/profiles.js +16 -160
  62. package/dist/commands/projects.d.ts +28 -0
  63. package/dist/commands/projects.js +125 -5
  64. package/dist/commands/reconnect.js +9 -3
  65. package/dist/commands/repo.js +42 -1
  66. package/dist/commands/resource-view.d.ts +17 -0
  67. package/dist/commands/resource-view.js +36 -14
  68. package/dist/commands/resume.js +9 -2
  69. package/dist/commands/routines.d.ts +0 -2
  70. package/dist/commands/routines.js +473 -289
  71. package/dist/commands/secrets.js +52 -9
  72. package/dist/commands/sessions-export.d.ts +47 -0
  73. package/dist/commands/sessions-export.js +116 -6
  74. package/dist/commands/sessions-import.d.ts +17 -0
  75. package/dist/commands/sessions-import.js +114 -6
  76. package/dist/commands/sessions-migrate.d.ts +27 -0
  77. package/dist/commands/sessions-migrate.js +50 -9
  78. package/dist/commands/sessions-picker.js +23 -4
  79. package/dist/commands/sessions-resume.d.ts +5 -3
  80. package/dist/commands/sessions-resume.js +30 -8
  81. package/dist/commands/sessions-watch.d.ts +2 -0
  82. package/dist/commands/sessions-watch.js +53 -0
  83. package/dist/commands/sessions.d.ts +66 -3
  84. package/dist/commands/sessions.js +298 -47
  85. package/dist/commands/set.d.ts +1 -1
  86. package/dist/commands/set.js +2 -2
  87. package/dist/commands/setup-browser.js +2 -2
  88. package/dist/commands/setup-mine.js +0 -1
  89. package/dist/commands/setup-preferences.js +1 -1
  90. package/dist/commands/setup-share.js +34 -4
  91. package/dist/commands/setup.d.ts +5 -0
  92. package/dist/commands/setup.js +26 -0
  93. package/dist/commands/share.d.ts +67 -0
  94. package/dist/commands/share.js +275 -12
  95. package/dist/commands/skills.js +0 -11
  96. package/dist/commands/snapshot.js +1 -1
  97. package/dist/commands/ssh.d.ts +18 -0
  98. package/dist/commands/ssh.js +549 -210
  99. package/dist/commands/sync.d.ts +5 -0
  100. package/dist/commands/sync.js +212 -32
  101. package/dist/commands/teams.d.ts +13 -0
  102. package/dist/commands/teams.js +187 -30
  103. package/dist/commands/tickets.d.ts +2 -0
  104. package/dist/commands/tickets.js +43 -0
  105. package/dist/commands/update.js +2 -4
  106. package/dist/commands/usage.js +5 -3
  107. package/dist/commands/versions.js +11 -5
  108. package/dist/commands/view.js +15 -7
  109. package/dist/commands/webhook.d.ts +2 -2
  110. package/dist/commands/webhook.js +7 -7
  111. package/dist/index.d.ts +18 -2
  112. package/dist/index.js +53 -1264
  113. package/dist/lib/account-catalog.d.ts +18 -0
  114. package/dist/lib/account-catalog.js +38 -0
  115. package/dist/lib/account-provider-registry.d.ts +18 -0
  116. package/dist/lib/account-provider-registry.js +59 -0
  117. package/dist/lib/account-registry.d.ts +40 -0
  118. package/dist/lib/account-registry.js +239 -0
  119. package/dist/lib/account-schema.d.ts +44 -0
  120. package/dist/lib/account-schema.js +91 -0
  121. package/dist/lib/account-state-service.d.ts +21 -0
  122. package/dist/lib/account-state-service.js +60 -0
  123. package/dist/lib/activity.d.ts +1 -1
  124. package/dist/lib/activity.js +8 -1
  125. package/dist/lib/add-dir.d.ts +80 -0
  126. package/dist/lib/add-dir.js +241 -0
  127. package/dist/lib/agent-cli-commands.d.ts +11 -0
  128. package/dist/lib/agent-cli-commands.js +30 -0
  129. package/dist/lib/agents.js +44 -36
  130. package/dist/lib/answer-router.js +1 -1
  131. package/dist/lib/audit/log.d.ts +10 -27
  132. package/dist/lib/audit/log.js +20 -33
  133. package/dist/lib/auth-health.d.ts +9 -2
  134. package/dist/lib/auth-health.js +42 -9
  135. package/dist/lib/auto-pull-worker.js +7 -3
  136. package/dist/lib/auto-pull.d.ts +44 -3
  137. package/dist/lib/auto-pull.js +88 -5
  138. package/dist/lib/binary-shadow.d.ts +28 -0
  139. package/dist/lib/binary-shadow.js +121 -0
  140. package/dist/lib/brand.js +9 -3
  141. package/dist/lib/browser/ipc.d.ts +30 -0
  142. package/dist/lib/browser/ipc.js +81 -4
  143. package/dist/lib/browser/profiles.d.ts +3 -2
  144. package/dist/lib/browser/profiles.js +65 -22
  145. package/dist/lib/browser/service.d.ts +4 -0
  146. package/dist/lib/browser/service.js +30 -3
  147. package/dist/lib/browser/sessions-list.d.ts +22 -2
  148. package/dist/lib/browser/sessions-list.js +54 -6
  149. package/dist/lib/browser/stream.d.ts +2 -0
  150. package/dist/lib/browser/stream.js +1 -0
  151. package/dist/lib/browser/types.d.ts +19 -0
  152. package/dist/lib/byok-usage.d.ts +9 -2
  153. package/dist/lib/byok-usage.js +133 -31
  154. package/dist/lib/cli-entry.d.ts +11 -0
  155. package/dist/lib/cli-entry.js +46 -0
  156. package/dist/lib/cloud/host.d.ts +1 -1
  157. package/dist/lib/cloud/host.js +2 -2
  158. package/dist/lib/cloud/registry.js +1 -1
  159. package/dist/lib/cloud/types.d.ts +1 -1
  160. package/dist/lib/commands.d.ts +2 -0
  161. package/dist/lib/commands.js +2 -0
  162. package/dist/lib/computer/sessions-list.d.ts +150 -0
  163. package/dist/lib/computer/sessions-list.js +363 -0
  164. package/dist/lib/config-keys.d.ts +86 -0
  165. package/dist/lib/config-keys.js +193 -0
  166. package/dist/lib/config-machine-keys.d.ts +12 -0
  167. package/dist/lib/config-machine-keys.js +17 -0
  168. package/dist/lib/config-transfer.js +3 -4
  169. package/dist/lib/crabbox/cli.d.ts +2 -2
  170. package/dist/lib/crabbox/cli.js +3 -3
  171. package/dist/lib/daemon-health.d.ts +22 -0
  172. package/dist/lib/daemon-health.js +33 -3
  173. package/dist/lib/daemon-services.d.ts +50 -0
  174. package/dist/lib/daemon-services.js +147 -0
  175. package/dist/lib/daemon-ticks.d.ts +35 -66
  176. package/dist/lib/daemon-ticks.js +77 -159
  177. package/dist/lib/daemon.d.ts +72 -4
  178. package/dist/lib/daemon.js +792 -202
  179. package/dist/lib/deeplink/register.d.ts +49 -0
  180. package/dist/lib/deeplink/register.js +253 -0
  181. package/dist/lib/deeplink/url.d.ts +34 -0
  182. package/dist/lib/deeplink/url.js +78 -0
  183. package/dist/lib/device-config.d.ts +124 -29
  184. package/dist/lib/device-config.js +346 -141
  185. package/dist/lib/devices/config-migration.d.ts +42 -0
  186. package/dist/lib/devices/config-migration.js +203 -0
  187. package/dist/lib/devices/connect.js +14 -7
  188. package/dist/lib/devices/doctor-findings.d.ts +4 -1
  189. package/dist/lib/devices/doctor-findings.js +20 -1
  190. package/dist/lib/devices/harness-inventory.d.ts +11 -2
  191. package/dist/lib/devices/harness-inventory.js +0 -0
  192. package/dist/lib/devices/health.d.ts +1 -1
  193. package/dist/lib/devices/health.js +1 -1
  194. package/dist/lib/devices/pending.d.ts +22 -1
  195. package/dist/lib/devices/pending.js +67 -2
  196. package/dist/lib/devices/registry.d.ts +0 -25
  197. package/dist/lib/devices/registry.js +2 -83
  198. package/dist/lib/devices/resolve-profile.d.ts +20 -0
  199. package/dist/lib/devices/resolve-profile.js +44 -0
  200. package/dist/lib/devices/rollout-verify.d.ts +101 -0
  201. package/dist/lib/devices/rollout-verify.js +193 -0
  202. package/dist/lib/devices/ssh-config.js +10 -6
  203. package/dist/lib/event-families.d.ts +28 -0
  204. package/dist/lib/event-families.js +159 -0
  205. package/dist/lib/event-stream.d.ts +9 -1
  206. package/dist/lib/event-stream.js +26 -9
  207. package/dist/lib/events.d.ts +9 -1
  208. package/dist/lib/events.js +21 -6
  209. package/dist/lib/exec.d.ts +30 -0
  210. package/dist/lib/exec.js +219 -121
  211. package/dist/lib/feed-broadcast.d.ts +25 -0
  212. package/dist/lib/feed-broadcast.js +33 -0
  213. package/dist/lib/feed.d.ts +1 -1
  214. package/dist/lib/feed.js +12 -2
  215. package/dist/lib/fleet/capture.js +15 -0
  216. package/dist/lib/fleet/manifest.js +9 -0
  217. package/dist/lib/fleet/types.d.ts +9 -0
  218. package/dist/lib/fleet-status.js +10 -8
  219. package/dist/lib/git.d.ts +20 -6
  220. package/dist/lib/git.js +121 -17
  221. package/dist/lib/hosts/dispatch.d.ts +8 -3
  222. package/dist/lib/hosts/dispatch.js +29 -3
  223. package/dist/lib/hosts/logs.d.ts +2 -2
  224. package/dist/lib/hosts/logs.js +2 -2
  225. package/dist/lib/hosts/option.js +1 -1
  226. package/dist/lib/hosts/passthrough.d.ts +2 -3
  227. package/dist/lib/hosts/passthrough.js +10 -24
  228. package/dist/lib/hosts/progress.js +2 -2
  229. package/dist/lib/hosts/providers/devices.d.ts +3 -3
  230. package/dist/lib/hosts/providers/devices.js +18 -12
  231. package/dist/lib/hosts/ready.d.ts +5 -1
  232. package/dist/lib/hosts/ready.js +9 -3
  233. package/dist/lib/hosts/reconcile.d.ts +2 -2
  234. package/dist/lib/hosts/reconcile.js +2 -2
  235. package/dist/lib/hosts/registry.js +14 -9
  236. package/dist/lib/hosts/remote-cmd.js +1 -1
  237. package/dist/lib/hosts/remote-os.d.ts +9 -6
  238. package/dist/lib/hosts/remote-os.js +13 -6
  239. package/dist/lib/hosts/routing-flag.d.ts +23 -0
  240. package/dist/lib/hosts/routing-flag.js +41 -0
  241. package/dist/lib/hosts/run-target.js +1 -1
  242. package/dist/lib/hosts/session-index.js +1 -1
  243. package/dist/lib/hosts/tasks.d.ts +6 -6
  244. package/dist/lib/hosts/tasks.js +4 -4
  245. package/dist/lib/hosts/types.js +1 -2
  246. package/dist/lib/installations/resolve.js +2 -8
  247. package/dist/lib/isolation-boundary-report.js +0 -1
  248. package/dist/lib/linear-cache.d.ts +7 -0
  249. package/dist/lib/linear-cache.js +31 -4
  250. package/dist/lib/linear-project-counts.d.ts +1 -1
  251. package/dist/lib/linear-project-counts.js +2 -3
  252. package/dist/lib/linear-projects.js +1 -1
  253. package/dist/lib/loop.d.ts +2 -2
  254. package/dist/lib/loop.js +1 -1
  255. package/dist/lib/mailbox-target.d.ts +1 -1
  256. package/dist/lib/mailbox-target.js +1 -1
  257. package/dist/lib/manifest.js +7 -4
  258. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  259. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  260. package/dist/lib/menubar/snapshot.d.ts +3 -2
  261. package/dist/lib/menubar/snapshot.js +6 -2
  262. package/dist/lib/migrate-fold.d.ts +33 -0
  263. package/dist/lib/migrate-fold.js +130 -0
  264. package/dist/lib/migrate.d.ts +34 -34
  265. package/dist/lib/migrate.js +106 -128
  266. package/dist/lib/model-tier-overrides.d.ts +1 -1
  267. package/dist/lib/model-tier-overrides.js +15 -2
  268. package/dist/lib/monitors/config.d.ts +17 -3
  269. package/dist/lib/monitors/config.js +52 -18
  270. package/dist/lib/monitors/engine.d.ts +32 -1
  271. package/dist/lib/monitors/engine.js +94 -11
  272. package/dist/lib/monitors/fingerprint.d.ts +46 -0
  273. package/dist/lib/monitors/fingerprint.js +100 -0
  274. package/dist/lib/monitors/remote.d.ts +47 -0
  275. package/dist/lib/monitors/remote.js +81 -0
  276. package/dist/lib/monitors/state.d.ts +39 -0
  277. package/dist/lib/monitors/state.js +56 -0
  278. package/dist/lib/onepassword.d.ts +17 -0
  279. package/dist/lib/onepassword.js +52 -22
  280. package/dist/lib/open-url.js +1 -1
  281. package/dist/lib/picker.d.ts +14 -2
  282. package/dist/lib/picker.js +35 -13
  283. package/dist/lib/placement.d.ts +1 -1
  284. package/dist/lib/placement.js +1 -1
  285. package/dist/lib/pr-land-detach.d.ts +32 -0
  286. package/dist/lib/pr-land-detach.js +79 -0
  287. package/dist/lib/profiles-presets.js +13 -0
  288. package/dist/lib/profiles.d.ts +2 -0
  289. package/dist/lib/profiles.js +44 -1
  290. package/dist/lib/project-focus.d.ts +1 -1
  291. package/dist/lib/project-focus.js +1 -1
  292. package/dist/lib/project-probe.d.ts +4 -1
  293. package/dist/lib/project-probe.js +5 -4
  294. package/dist/lib/project-resources.js +2 -18
  295. package/dist/lib/project-root.d.ts +16 -0
  296. package/dist/lib/project-root.js +20 -2
  297. package/dist/lib/projects.d.ts +20 -1
  298. package/dist/lib/projects.js +78 -1
  299. package/dist/lib/refresh-coordinator.d.ts +24 -0
  300. package/dist/lib/refresh-coordinator.js +52 -0
  301. package/dist/lib/registry.d.ts +2 -2
  302. package/dist/lib/registry.js +1 -1
  303. package/dist/lib/resource-aliases.d.ts +13 -0
  304. package/dist/lib/resource-aliases.js +26 -0
  305. package/dist/lib/resources/types.d.ts +1 -1
  306. package/dist/lib/resources.d.ts +16 -0
  307. package/dist/lib/resources.js +66 -10
  308. package/dist/lib/rotate.d.ts +3 -4
  309. package/dist/lib/rotate.js +4 -5
  310. package/dist/lib/routine-activation.d.ts +22 -2
  311. package/dist/lib/routine-activation.js +63 -16
  312. package/dist/lib/routine-context.d.ts +9 -2
  313. package/dist/lib/routine-context.js +21 -6
  314. package/dist/lib/routines-project.d.ts +58 -48
  315. package/dist/lib/routines-project.js +190 -159
  316. package/dist/lib/routines.d.ts +41 -6
  317. package/dist/lib/routines.js +92 -34
  318. package/dist/lib/run-defaults.d.ts +5 -0
  319. package/dist/lib/run-defaults.js +11 -1
  320. package/dist/lib/runner.d.ts +10 -8
  321. package/dist/lib/runner.js +122 -39
  322. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  323. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  324. package/dist/lib/secrets/agent.d.ts +10 -3
  325. package/dist/lib/secrets/agent.js +43 -8
  326. package/dist/lib/secrets/bundles.d.ts +1 -0
  327. package/dist/lib/secrets/bundles.js +92 -80
  328. package/dist/lib/secrets/index.js +32 -9
  329. package/dist/lib/secrets/install-helper.d.ts +4 -4
  330. package/dist/lib/secrets/install-helper.js +4 -4
  331. package/dist/lib/secrets/push.d.ts +40 -6
  332. package/dist/lib/secrets/push.js +58 -11
  333. package/dist/lib/secrets/read-backoff.d.ts +1 -1
  334. package/dist/lib/secrets/read-backoff.js +1 -1
  335. package/dist/lib/secrets/remote.d.ts +24 -0
  336. package/dist/lib/secrets/remote.js +54 -4
  337. package/dist/lib/self-update.d.ts +108 -0
  338. package/dist/lib/self-update.js +276 -1
  339. package/dist/lib/session/active.d.ts +89 -5
  340. package/dist/lib/session/active.js +165 -10
  341. package/dist/lib/session/actor-sidecar.d.ts +1 -1
  342. package/dist/lib/session/actor-sidecar.js +2 -1
  343. package/dist/lib/session/db.d.ts +176 -2
  344. package/dist/lib/session/db.js +484 -17
  345. package/dist/lib/session/discover.js +27 -4
  346. package/dist/lib/session/hook-sessions.js +2 -2
  347. package/dist/lib/session/host-link.d.ts +2 -2
  348. package/dist/lib/session/host-link.js +2 -2
  349. package/dist/lib/session/pid-registry.d.ts +21 -0
  350. package/dist/lib/session/pid-registry.js +57 -0
  351. package/dist/lib/session/remote-active.js +15 -1
  352. package/dist/lib/session/remote.js +2 -2
  353. package/dist/lib/session/session-cache.d.ts +14 -7
  354. package/dist/lib/session/session-cache.js +51 -9
  355. package/dist/lib/session/state.d.ts +2 -2
  356. package/dist/lib/session/state.js +1 -1
  357. package/dist/lib/session/sync/config.d.ts +10 -10
  358. package/dist/lib/session/sync/config.js +10 -10
  359. package/dist/lib/session/sync/r2.d.ts +34 -0
  360. package/dist/lib/session/sync/r2.js +123 -0
  361. package/dist/lib/session/throughput.d.ts +1 -1
  362. package/dist/lib/session/throughput.js +1 -1
  363. package/dist/lib/session/types.d.ts +23 -1
  364. package/dist/lib/session/types.js +15 -0
  365. package/dist/lib/session/viewing-in.d.ts +1 -1
  366. package/dist/lib/session/viewing-in.js +1 -1
  367. package/dist/lib/session/watch.d.ts +101 -0
  368. package/dist/lib/session/watch.js +242 -0
  369. package/dist/lib/share/config.d.ts +4 -0
  370. package/dist/lib/share/config.js +1 -0
  371. package/dist/lib/share/provision.d.ts +38 -0
  372. package/dist/lib/share/provision.js +50 -0
  373. package/dist/lib/share/publish.d.ts +40 -1
  374. package/dist/lib/share/publish.js +116 -3
  375. package/dist/lib/share/worker-template.js +71 -6
  376. package/dist/lib/shims.d.ts +17 -3
  377. package/dist/lib/shims.js +98 -26
  378. package/dist/lib/signin-badge.js +3 -2
  379. package/dist/lib/skills.js +2 -0
  380. package/dist/lib/smart-launch.d.ts +8 -8
  381. package/dist/lib/smart-launch.js +80 -59
  382. package/dist/lib/ssh-exec.d.ts +1 -1
  383. package/dist/lib/ssh-exec.js +1 -1
  384. package/dist/lib/staleness/prune.d.ts +88 -0
  385. package/dist/lib/staleness/prune.js +69 -0
  386. package/dist/lib/staleness/registry.d.ts +1 -1
  387. package/dist/lib/staleness/writers/commands.js +34 -2
  388. package/dist/lib/staleness/writers/hooks.js +16 -0
  389. package/dist/lib/staleness/writers/kinds.d.ts +6 -0
  390. package/dist/lib/staleness/writers/skills.js +19 -0
  391. package/dist/lib/staleness/writers/subagents.d.ts +2 -3
  392. package/dist/lib/staleness/writers/subagents.js +0 -4
  393. package/dist/lib/staleness/writers/types.d.ts +32 -0
  394. package/dist/lib/startup/command-registry.d.ts +6 -12
  395. package/dist/lib/startup/command-registry.js +11 -31
  396. package/dist/lib/startup/dev-build.d.ts +10 -0
  397. package/dist/lib/startup/dev-build.js +13 -1
  398. package/dist/lib/startup/spellcheck.d.ts +18 -0
  399. package/dist/lib/startup/spellcheck.js +45 -0
  400. package/dist/lib/state.d.ts +36 -9
  401. package/dist/lib/state.js +96 -46
  402. package/dist/lib/subagents-registry.d.ts +0 -7
  403. package/dist/lib/subagents-registry.js +38 -65
  404. package/dist/lib/subagents.d.ts +0 -33
  405. package/dist/lib/subagents.js +0 -75
  406. package/dist/lib/sync-umbrella.js +1 -1
  407. package/dist/lib/teams/agents.d.ts +41 -1
  408. package/dist/lib/teams/agents.js +187 -9
  409. package/dist/lib/teams/api.d.ts +11 -1
  410. package/dist/lib/teams/api.js +11 -2
  411. package/dist/lib/teams/delivery.d.ts +41 -0
  412. package/dist/lib/teams/delivery.js +60 -0
  413. package/dist/lib/teams/registry.d.ts +14 -0
  414. package/dist/lib/teams/registry.js +51 -1
  415. package/dist/lib/teams/remoteWorktree.d.ts +19 -0
  416. package/dist/lib/teams/remoteWorktree.js +29 -0
  417. package/dist/lib/teams/scheduler.d.ts +1 -1
  418. package/dist/lib/teams/scheduler.js +1 -1
  419. package/dist/lib/teams/worktree.d.ts +24 -0
  420. package/dist/lib/teams/worktree.js +42 -0
  421. package/dist/lib/terminal/backends/vscodium-agent.d.ts +10 -1
  422. package/dist/lib/terminal/backends/vscodium-agent.js +16 -5
  423. package/dist/lib/terminal/engine.d.ts +4 -0
  424. package/dist/lib/terminal/engine.js +8 -2
  425. package/dist/lib/terminal/types.d.ts +21 -2
  426. package/dist/lib/testdata/refresh-coordinator-worker.d.ts +1 -0
  427. package/dist/lib/testdata/refresh-coordinator-worker.js +23 -0
  428. package/dist/lib/tickets/list.d.ts +53 -0
  429. package/dist/lib/tickets/list.js +153 -0
  430. package/dist/lib/tmux/orphan-reap.d.ts +320 -0
  431. package/dist/lib/tmux/orphan-reap.js +644 -0
  432. package/dist/lib/tmux/session.d.ts +68 -3
  433. package/dist/lib/tmux/session.js +95 -5
  434. package/dist/lib/triggers/handlers.d.ts +20 -0
  435. package/dist/lib/triggers/handlers.js +6 -1
  436. package/dist/lib/types.d.ts +46 -34
  437. package/dist/lib/usage-fleet.d.ts +32 -0
  438. package/dist/lib/usage-fleet.js +125 -0
  439. package/dist/lib/usage-refresh.d.ts +3 -3
  440. package/dist/lib/usage-refresh.js +19 -16
  441. package/dist/lib/usage.d.ts +51 -47
  442. package/dist/lib/usage.js +145 -153
  443. package/dist/lib/version-duplicates.js +2 -2
  444. package/dist/lib/versions.d.ts +56 -13
  445. package/dist/lib/versions.js +195 -45
  446. package/dist/lib/watchdog/log.d.ts +1 -1
  447. package/dist/lib/watchdog/log.js +3 -3
  448. package/dist/lib/watchdog/rotate.d.ts +6 -6
  449. package/dist/lib/watchdog/rotate.js +6 -6
  450. package/dist/lib/workflows.d.ts +1 -1
  451. package/dist/lib/yaml-io.d.ts +47 -0
  452. package/dist/lib/yaml-io.js +55 -0
  453. package/package.json +2 -1
  454. package/scripts/install-helper.js +2 -2
  455. package/scripts/postinstall.js +23 -20
  456. package/dist/commands/defaults.d.ts +0 -7
  457. package/dist/commands/defaults.js +0 -107
  458. package/dist/commands/export.d.ts +0 -11
  459. package/dist/commands/export.js +0 -215
  460. package/dist/commands/helper.d.ts +0 -12
  461. package/dist/commands/helper.js +0 -87
  462. package/dist/commands/hosts.d.ts +0 -11
  463. package/dist/commands/hosts.js +0 -330
  464. package/dist/commands/lock.d.ts +0 -12
  465. package/dist/commands/lock.js +0 -70
  466. package/dist/commands/pull.d.ts +0 -17
  467. package/dist/commands/pull.js +0 -39
  468. package/dist/commands/push.d.ts +0 -14
  469. package/dist/commands/push.js +0 -30
  470. package/dist/commands/wallet.d.ts +0 -20
  471. package/dist/commands/wallet.js +0 -216
  472. package/dist/commands/worktree.d.ts +0 -19
  473. package/dist/commands/worktree.js +0 -272
  474. package/dist/lib/account-labels.d.ts +0 -24
  475. package/dist/lib/account-labels.js +0 -72
  476. package/dist/lib/auto-dispatch-linear.d.ts +0 -18
  477. package/dist/lib/auto-dispatch-linear.js +0 -107
  478. package/dist/lib/auto-dispatch-provider.d.ts +0 -10
  479. package/dist/lib/auto-dispatch-provider.js +0 -30
  480. package/dist/lib/auto-dispatch.d.ts +0 -93
  481. package/dist/lib/auto-dispatch.js +0 -128
  482. package/dist/lib/export.d.ts +0 -72
  483. package/dist/lib/export.js +0 -269
  484. package/dist/lib/lock.d.ts +0 -93
  485. package/dist/lib/lock.js +0 -207
  486. package/dist/lib/wallet/index.d.ts +0 -78
  487. package/dist/lib/wallet/index.js +0 -253
@@ -26,7 +26,22 @@ export function captureFleet(prev, inputs) {
26
26
  // Roster: explicit map of the captured names. A hand-authored override for a
27
27
  // device that still exists is preserved; a captured agent list only fills in
28
28
  // when the manifest didn't already pin one for that device.
29
+ //
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.
29
37
  const devices = {};
38
+ for (const [name, prevOverride] of Object.entries(prevDevices)) {
39
+ if (inputs.devices.includes(name))
40
+ continue; // handled by the roster loop below
41
+ const config = prevOverride?.config;
42
+ if (config && Object.keys(config).length > 0)
43
+ devices[name] = { config };
44
+ }
30
45
  for (const name of inputs.devices) {
31
46
  const prevOverride = prevDevices[name] ?? {};
32
47
  const override = { ...prevOverride };
@@ -59,6 +59,15 @@ export function parseFleetManifest(raw) {
59
59
  for (const [name, ov] of Object.entries(o.devices)) {
60
60
  // An empty entry (`device: {}`) inherits defaults — represent as {}.
61
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
+ }
62
71
  map[name] = merged;
63
72
  }
64
73
  devices = map;
@@ -33,6 +33,15 @@ export interface FleetDeviceOverride {
33
33
  agents?: string[];
34
34
  sync?: string[];
35
35
  login?: FleetLoginMode;
36
+ /**
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).
43
+ */
44
+ config?: Record<string, unknown>;
36
45
  }
37
46
  /**
38
47
  * The `fleet:` block as it appears in `agents.yaml` (or any `-f` file). `devices`
@@ -30,6 +30,7 @@ import * as path from 'path';
30
30
  import { getCacheDir } from './state.js';
31
31
  import { probeLocalStats } from './devices/health.js';
32
32
  import { getActiveSessions } from './session/active.js';
33
+ import { atomicWriteFileSync, ensureLockTarget, withFileLock } from './fs-atomic.js';
33
34
  /**
34
35
  * Tally running-agent workload from a host's live sessions. "running" is the
35
36
  * actively-working set (`status === 'running'`); `live` is every session the
@@ -95,14 +96,15 @@ export function readFleetStatus() {
95
96
  /** Merge rows into the mirror (best-effort; preserves other hosts' rows). */
96
97
  export function writeFleetStatusRows(entries) {
97
98
  try {
98
- const dir = getCacheDir();
99
- if (!fs.existsSync(dir))
100
- fs.mkdirSync(dir, { recursive: true });
101
- const merged = {
102
- version: 1,
103
- entries: { ...readFleetStatus(), ...entries },
104
- };
105
- fs.writeFileSync(mirrorPath(), JSON.stringify(merged, null, 2));
99
+ const target = mirrorPath();
100
+ ensureLockTarget(target, JSON.stringify({ version: 1, entries: {} }));
101
+ withFileLock(target, () => {
102
+ const merged = {
103
+ version: 1,
104
+ entries: { ...readFleetStatus(), ...entries },
105
+ };
106
+ atomicWriteFileSync(target, JSON.stringify(merged, null, 2));
107
+ });
106
108
  }
107
109
  catch {
108
110
  // best-effort; a failed write just means the reader sees an older union
package/dist/lib/git.d.ts CHANGED
@@ -267,7 +267,9 @@ export declare function hasLocalChanges(dir: string): Promise<boolean>;
267
267
  export declare function displayHomePath(dir: string): string;
268
268
  /**
269
269
  * Pull changes in an existing repo.
270
- * Refuses to pull if the working tree is dirty -- user must commit or discard changes first.
270
+ * A dirty working tree no longer refuses outright: a fast-forward that touches
271
+ * no uncommitted path still runs (see `dirtyTreeRefusal`). It refuses when the
272
+ * branch has local commits to rebase, or when an incoming path is also dirty.
271
273
  *
272
274
  * Strategy (RUSH-2282):
273
275
  * 1. Fetch, then compare HEAD to the resolved tracking ref.
@@ -289,15 +291,27 @@ export declare function pullRepo(dir: string): Promise<{
289
291
  * Rebase a repo onto its remote, optionally pushing local commits back up.
290
292
  *
291
293
  * The one-repo counterpart to `pullRepo` used by `agents sync <repo>`:
292
- * 1. Refuse if the working tree is dirty (commit or discard first).
293
- * 2. `git fetch origin` then `git pull --rebase origin <branch>` rebase, not
294
- * merge, so a local commit lands cleanly on top of upstream with no merge
295
- * bubble.
296
- * 3. When `push` is set, `git push origin <branch>` to send local commits up.
294
+ * 1. `git fetch origin`.
295
+ * 2. Clean tree `git pull --rebase origin <branch>`: rebase, not merge, so a
296
+ * local commit lands cleanly on top of upstream with no merge bubble.
297
+ * 3. Dirty tree → fast-forward instead, but only when that is provably safe:
298
+ * no local commits ahead of upstream, and no incoming path collides with a
299
+ * dirty one. Otherwise refuse, naming the paths that collided.
300
+ * 4. When `push` is set, `git push origin <branch>` to send local commits up.
297
301
  *
298
302
  * The branch is read from the repo's current HEAD (falls back to `main`) rather
299
303
  * than hardcoded. System repos pass `push: false` — they are pull-only mirrors
300
304
  * of the npm-shipped upstream.
305
+ *
306
+ * Why step 3 exists: refusing on *any* dirt strands merged changes indefinitely.
307
+ * A DotAgents repo accumulates unrelated local state — a modified `agents.yaml`,
308
+ * a session's scratch file, a machine-local dotfile — and under the old rule one
309
+ * such file froze that box's layer forever, silently. Measured 2026-08-10: a
310
+ * merged fix could not reach three of three boxes, each blocked by files the
311
+ * incoming commits never touched. A `--ff-only` merge is the safe primitive
312
+ * here: it cannot rewrite local commits, and git itself aborts rather than
313
+ * overwrite a modified file, so the path check is belt-and-braces, not the only
314
+ * guard.
301
315
  */
302
316
  export declare function syncRepoGit(dir: string, opts: {
303
317
  push: boolean;
package/dist/lib/git.js CHANGED
@@ -865,7 +865,9 @@ export function displayHomePath(dir) {
865
865
  }
866
866
  /**
867
867
  * Pull changes in an existing repo.
868
- * Refuses to pull if the working tree is dirty -- user must commit or discard changes first.
868
+ * A dirty working tree no longer refuses outright: a fast-forward that touches
869
+ * no uncommitted path still runs (see `dirtyTreeRefusal`). It refuses when the
870
+ * branch has local commits to rebase, or when an incoming path is also dirty.
869
871
  *
870
872
  * Strategy (RUSH-2282):
871
873
  * 1. Fetch, then compare HEAD to the resolved tracking ref.
@@ -914,11 +916,18 @@ export async function pullRepo(dir) {
914
916
  };
915
917
  }
916
918
  const status = await git.status();
917
- if (!status.isClean()) {
919
+ // A dirty tree is not decided here: whether a fast-forward is safe depends
920
+ // on what is actually incoming, and that needs a fetched upstream ref. The
921
+ // gate therefore sits just before the integrate step below. The exception is
922
+ // a repo with no remote at all — there is nothing to fast-forward from, so
923
+ // the dirt is the whole answer and the resolution below would only fail
924
+ // with a less useful message.
925
+ const isDirty = !status.isClean();
926
+ if (isDirty && (await git.getRemotes()).length === 0) {
918
927
  return {
919
928
  success: false,
920
929
  commit: '',
921
- error: `Blocked by local changes. Commit or discard them before pulling.\n\n cd ${displayHomePath(dir)} && git status`,
930
+ error: `Blocked by local changes: the repo has no remote to pull from. Commit or discard them before pulling.\n\n cd ${displayHomePath(dir)} && git status`,
922
931
  };
923
932
  }
924
933
  const branch = status.current || 'main';
@@ -978,6 +987,20 @@ export async function pullRepo(dir) {
978
987
  Number.isFinite(behindCount) &&
979
988
  aheadCount === 0 &&
980
989
  behindCount > 0;
990
+ // Dirty tree: same rule `syncRepoGit` applies, from the same function — a
991
+ // fast-forward that touches nothing the author is holding may proceed; a
992
+ // rebase or a colliding path may not. Refusing on any dirt at all is what
993
+ // used to strand merged changes on every box that had an unrelated edit.
994
+ if (isDirty) {
995
+ const refusal = await dirtyTreeRefusal(git, status, tracking);
996
+ if (refusal) {
997
+ return {
998
+ success: false,
999
+ commit: '',
1000
+ error: `Blocked by local changes: ${refusal}. Commit or discard them before pulling.\n\n cd ${displayHomePath(dir)} && git status`,
1001
+ };
1002
+ }
1003
+ }
981
1004
  try {
982
1005
  if (canFastForward) {
983
1006
  // Integrate the already-fetched tracking ref. No network, no FETCH_HEAD.
@@ -1017,19 +1040,92 @@ export async function pullRepo(dir) {
1017
1040
  return { success: false, commit: '', error: err.message };
1018
1041
  }
1019
1042
  }
1043
+ /**
1044
+ * Every repo-relative path a status reports as locally touched, in one set.
1045
+ *
1046
+ * Reads `status.files`, which `simple-git` documents as "all files" and which is
1047
+ * the same source `isClean()` is computed from — so this set and the decision to
1048
+ * treat the tree as dirty can never disagree. The per-category arrays
1049
+ * (`modified`, `staged`, `not_added`, …) are projections of that list; unioning
1050
+ * them by hand means a category nobody thought of contributes nothing. `from`
1051
+ * carries a rename's original path, and the incoming side may collide with
1052
+ * either end.
1053
+ */
1054
+ function dirtyPathSet(status) {
1055
+ const out = new Set();
1056
+ for (const f of status.files || []) {
1057
+ if (f?.path)
1058
+ out.add(f.path);
1059
+ if (f?.from)
1060
+ out.add(f.from);
1061
+ }
1062
+ return out;
1063
+ }
1064
+ /**
1065
+ * Why a dirty working tree must NOT fast-forward to `upstreamRef` — or `null`
1066
+ * when it safely can.
1067
+ *
1068
+ * The single home for that decision: `syncRepoGit` and `pullRepo` both integrate
1069
+ * upstream and both meet dirty trees, and two copies of this rule would drift
1070
+ * into two different answers for one question. Refusing outright is the thing
1071
+ * being replaced — it strands merged changes behind unrelated local files —
1072
+ * so the rule is narrow and stated once:
1073
+ *
1074
+ * - local commits ahead of upstream → refuse (they need a rebase, which
1075
+ * requires a clean tree);
1076
+ * - an incoming path that is also dirty → refuse, and name it;
1077
+ * - otherwise the fast-forward touches nothing the author is holding.
1078
+ *
1079
+ * `-z` on the diff because `git diff --name-only` C-quotes paths containing
1080
+ * unicode or control characters — `café.txt` comes back as `"caf\303\251.txt"`,
1081
+ * while `status.files` reports it raw. Without `-z` the two sides are in
1082
+ * different encodings and a collision on such a path silently misses. (A plain
1083
+ * space does NOT trigger quoting; `my file.txt` is emitted as-is either way.)
1084
+ */
1085
+ async function dirtyTreeRefusal(git, status, upstreamRef) {
1086
+ const ahead = parseInt((await git.raw(['rev-list', '--count', `${upstreamRef}..HEAD`])).trim(), 10);
1087
+ if (Number.isNaN(ahead))
1088
+ return 'the upstream ref could not be compared with HEAD';
1089
+ if (ahead > 0) {
1090
+ return `the branch has ${ahead} local commit(s) to rebase, which needs a clean tree`;
1091
+ }
1092
+ const dirty = dirtyPathSet(status);
1093
+ const incoming = (await git.raw(['diff', '--name-only', '-z', `HEAD..${upstreamRef}`]))
1094
+ .split('\0')
1095
+ .filter(Boolean);
1096
+ const collisions = incoming.filter((p) => dirty.has(p));
1097
+ if (collisions.length > 0) {
1098
+ const shown = collisions.slice(0, 5).join(', ');
1099
+ const more = collisions.length > 5 ? ` (+${collisions.length - 5} more)` : '';
1100
+ return `incoming changes touch uncommitted paths: ${shown}${more}`;
1101
+ }
1102
+ return null;
1103
+ }
1020
1104
  /**
1021
1105
  * Rebase a repo onto its remote, optionally pushing local commits back up.
1022
1106
  *
1023
1107
  * The one-repo counterpart to `pullRepo` used by `agents sync <repo>`:
1024
- * 1. Refuse if the working tree is dirty (commit or discard first).
1025
- * 2. `git fetch origin` then `git pull --rebase origin <branch>` rebase, not
1026
- * merge, so a local commit lands cleanly on top of upstream with no merge
1027
- * bubble.
1028
- * 3. When `push` is set, `git push origin <branch>` to send local commits up.
1108
+ * 1. `git fetch origin`.
1109
+ * 2. Clean tree `git pull --rebase origin <branch>`: rebase, not merge, so a
1110
+ * local commit lands cleanly on top of upstream with no merge bubble.
1111
+ * 3. Dirty tree → fast-forward instead, but only when that is provably safe:
1112
+ * no local commits ahead of upstream, and no incoming path collides with a
1113
+ * dirty one. Otherwise refuse, naming the paths that collided.
1114
+ * 4. When `push` is set, `git push origin <branch>` to send local commits up.
1029
1115
  *
1030
1116
  * The branch is read from the repo's current HEAD (falls back to `main`) rather
1031
1117
  * than hardcoded. System repos pass `push: false` — they are pull-only mirrors
1032
1118
  * of the npm-shipped upstream.
1119
+ *
1120
+ * Why step 3 exists: refusing on *any* dirt strands merged changes indefinitely.
1121
+ * A DotAgents repo accumulates unrelated local state — a modified `agents.yaml`,
1122
+ * a session's scratch file, a machine-local dotfile — and under the old rule one
1123
+ * such file froze that box's layer forever, silently. Measured 2026-08-10: a
1124
+ * merged fix could not reach three of three boxes, each blocked by files the
1125
+ * incoming commits never touched. A `--ff-only` merge is the safe primitive
1126
+ * here: it cannot rewrite local commits, and git itself aborts rather than
1127
+ * overwrite a modified file, so the path check is belt-and-braces, not the only
1128
+ * guard.
1033
1129
  */
1034
1130
  export async function syncRepoGit(dir, opts) {
1035
1131
  try {
@@ -1038,18 +1134,26 @@ export async function syncRepoGit(dir, opts) {
1038
1134
  }
1039
1135
  const git = simpleGit(dir);
1040
1136
  const status = await git.status();
1041
- if (!status.isClean()) {
1042
- return {
1043
- success: false,
1044
- commit: '',
1045
- pushed: false,
1046
- error: `Working tree has uncommitted changes. Commit or discard them first.\n\n cd ${dir} && git status`,
1047
- };
1048
- }
1049
1137
  const branch = status.current || 'main';
1050
1138
  assertValidBranchName(branch);
1051
1139
  await git.fetch('origin');
1052
- await git.pull('origin', branch, { '--rebase': 'true' });
1140
+ if (status.isClean()) {
1141
+ await git.pull('origin', branch, { '--rebase': 'true' });
1142
+ }
1143
+ else {
1144
+ // Dirty tree: a rebase would refuse outright, so fast-forward instead —
1145
+ // but only when nothing local can be lost. One shared rule, see above.
1146
+ const refusal = await dirtyTreeRefusal(git, status, `origin/${branch}`);
1147
+ if (refusal) {
1148
+ return {
1149
+ success: false,
1150
+ commit: '',
1151
+ pushed: false,
1152
+ error: `Working tree has uncommitted changes and ${refusal}. Commit or discard them first.\n\n cd ${dir} && git status`,
1153
+ };
1154
+ }
1155
+ await git.raw(['merge', '--ff-only', `origin/${branch}`]);
1156
+ }
1053
1157
  installGithooksSymlinks(dir);
1054
1158
  let pushed = false;
1055
1159
  if (opts.push) {
@@ -13,6 +13,11 @@ import { type HostTask } from './tasks.js';
13
13
  import { type HostCredentials } from './credentials.js';
14
14
  import { deriveMirroredCwd, homeRemainder, remoteCdPrefix } from '../project-root.js';
15
15
  export { deriveMirroredCwd, homeRemainder, remoteCdPrefix };
16
+ /**
17
+ * Diagnostic helper for RUSH-2441: log the requested agent and initial remote
18
+ * `agents run` argv without changing normal command output.
19
+ */
20
+ export declare function logForwardedArgs(kind: string, agent: string, version: string | undefined, args: string[], hasPrompt: boolean): void;
16
21
  /**
17
22
  * Merge the resolved actor's provenance env UNDER a caller-supplied env, so every
18
23
  * remote `agents …` invocation forwards `AGENTS_ACTOR*` / `GIT_*` across the SSH
@@ -73,10 +78,10 @@ export declare function terminateDispatchedTask(task: HostTask): void;
73
78
  export declare function buildStopRemoteCommand(pid: number, remoteExit: string): string;
74
79
  export declare function buildWindowsStopRemoteCommand(pid: number, remoteExit: string): string;
75
80
  /**
76
- * Stop a running host task from the origin machine (`agents hosts stop <id>`).
81
+ * Stop a running host task from the origin machine (`agents devices stop <id>`).
77
82
  *
78
83
  * Unlike {@link terminateDispatchedTask} (rollback cleanup after a failed
79
- * persist), this keeps the remote log so `agents hosts logs <id>` still works,
84
+ * persist), this keeps the remote log so `agents logs <id>` still works,
80
85
  * writes a terminal `.exit` marker only when we actually stopped a live group
81
86
  * (or no code existed), and never clobbers a real completed-run exit code.
82
87
  */
@@ -130,7 +135,7 @@ export interface DispatchOptions {
130
135
  sessionId?: string;
131
136
  /**
132
137
  * Durable `--name <slug>` handle, forwarded to the remote `agents run` and
133
- * recorded on the local task so `agents hosts logs/ps <name>` resolve it.
138
+ * recorded on the local task so `agents logs <name>` / `agents devices ps` resolve it.
134
139
  */
135
140
  name?: string;
136
141
  /** Resume an existing session on the host by id (via `agents run --resume`). */
@@ -26,6 +26,30 @@ import { RUN_AUTO_KEYWORD, RUN_AUTO_HOST_RESOLVED_ENV } from '../types.js';
26
26
  // shell builder (devices/connect.ts) as well as this dispatch layer. Re-exported
27
27
  // here so existing `hosts/dispatch.js` importers and tests keep resolving them.
28
28
  export { deriveMirroredCwd, homeRemainder, remoteCdPrefix };
29
+ /**
30
+ * Diagnostic helper for RUSH-2441: log the requested agent and initial remote
31
+ * `agents run` argv without changing normal command output.
32
+ */
33
+ export function logForwardedArgs(kind, agent, version, args, hasPrompt) {
34
+ if (!process.env.AGENTS_DISPATCH_DEBUG)
35
+ return;
36
+ const safeArgs = [...args];
37
+ if (safeArgs[0] === 'run' && safeArgs[2] && hasPrompt) {
38
+ safeArgs[2] = '<prompt>';
39
+ }
40
+ for (let i = 0; i < safeArgs.length; i++) {
41
+ if (safeArgs[i] === '--env' && safeArgs[i + 1]) {
42
+ const key = safeArgs[i + 1].split('=', 1)[0];
43
+ safeArgs[i + 1] = `${key}=<redacted>`;
44
+ i++;
45
+ }
46
+ else if (safeArgs[i] === '--') {
47
+ safeArgs.splice(i + 1, safeArgs.length - i - 1, '<passthrough redacted>');
48
+ break;
49
+ }
50
+ }
51
+ process.stderr.write(`[dispatch:${kind}] agent=${agent}${version ? `@${version}` : ''} args=${JSON.stringify(safeArgs)}\n`);
52
+ }
29
53
  // Use $HOME (not ~) so the path is correct whether or not it's quoted and
30
54
  // regardless of the run's cwd. Task ids are 8 hex chars, so these paths are
31
55
  // injection-safe to interpolate unquoted into remote commands.
@@ -189,10 +213,10 @@ export function buildWindowsStopRemoteCommand(pid, remoteExit) {
189
213
  return `powershell -NoProfile -EncodedCommand ${encodePowershell(script)}`;
190
214
  }
191
215
  /**
192
- * Stop a running host task from the origin machine (`agents hosts stop <id>`).
216
+ * Stop a running host task from the origin machine (`agents devices stop <id>`).
193
217
  *
194
218
  * Unlike {@link terminateDispatchedTask} (rollback cleanup after a failed
195
- * persist), this keeps the remote log so `agents hosts logs <id>` still works,
219
+ * persist), this keeps the remote log so `agents logs <id>` still works,
196
220
  * writes a terminal `.exit` marker only when we actually stopped a live group
197
221
  * (or no code existed), and never clobbers a real completed-run exit code.
198
222
  */
@@ -313,7 +337,7 @@ async function launchDetached(host, target, opts) {
313
337
  remoteShell,
314
338
  });
315
339
  // -1 = the follow window closed while the run continues on the host. Leave the
316
- // record 'running' (do NOT freeze it terminal) so a later `hosts ps`/`logs`
340
+ // record 'running' (do NOT freeze it terminal) so a later `agents devices ps` / `agents logs`
317
341
  // reconcile against the remote `.exit` resolves the true final status.
318
342
  const finished = exitCode === -1 ? task : (updateTask(id, terminalPatch(exitCode)) ?? task);
319
343
  return { task: finished, exitCode };
@@ -382,6 +406,7 @@ export function buildRunForwardedArgs(opts) {
382
406
  args.push('--emit-session-id');
383
407
  if (opts.passthroughArgs && opts.passthroughArgs.length > 0)
384
408
  args.push('--', ...opts.passthroughArgs);
409
+ logForwardedArgs('headless', opts.agent, opts.version, args, true);
385
410
  return args;
386
411
  }
387
412
  /**
@@ -438,6 +463,7 @@ export function buildInteractiveRunForwardedArgs(opts) {
438
463
  if (opts.passthroughArgs && opts.passthroughArgs.length > 0) {
439
464
  args.push('--', ...opts.passthroughArgs);
440
465
  }
466
+ logForwardedArgs('interactive', opts.agent, opts.version, args, Boolean(opts.prompt && opts.forceInteractive));
441
467
  return args;
442
468
  }
443
469
  /**
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Shared host-task log viewer — the show-or-follow core behind both
3
- * `agents hosts logs <id>` and the top-level `agents logs <id>`.
2
+ * Shared host-task log viewer — the show-or-follow core behind the
3
+ * top-level `agents logs <id>`.
4
4
  *
5
5
  * A running task with follow re-enters the offset-tail (`followHostTask`).
6
6
  * Otherwise the view is **concise by default**: a bounded tail of the captured
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Shared host-task log viewer — the show-or-follow core behind both
3
- * `agents hosts logs <id>` and the top-level `agents logs <id>`.
2
+ * Shared host-task log viewer — the show-or-follow core behind the
3
+ * top-level `agents logs <id>`.
4
4
  *
5
5
  * A running task with follow re-enters the offset-tail (`followHostTask`).
6
6
  * Otherwise the view is **concise by default**: a bounded tail of the captured
@@ -12,7 +12,7 @@
12
12
  /** Attach the standard `--host` flag family to a command and return it (chainable). */
13
13
  export function addHostOption(cmd) {
14
14
  return cmd
15
- .option('-H, --host <name>', 'Run this command on another machine over SSH instead of locally — a device, a registered host, user@host, or `all` to fan out across every registered device. See `agents devices` / `agents hosts`.')
15
+ .option('-H, --host <name>', 'Run this command on another machine over SSH instead of locally — a device, an ssh-config host, user@host, or `all` to fan out across every registered device. See `agents devices`.')
16
16
  .option('--device <name>', 'Alias of --host: run this command on a registered device (from `agents devices`), or `all` to run it across the whole fleet.')
17
17
  .option('--remote-cwd <dir>', "Working directory on the host for --host runs. Resolves on the REMOTE host — pass a '$HOME'-relative path (single-quoted so your local shell doesn't expand it) or a valid remote absolute path; a local ~ expands here and won't exist there (/Users/you vs /home/you). No effect on 'teams add'.")
18
18
  .option('--no-tty', 'Force non-interactive output for --host runs even from a terminal.')
@@ -19,6 +19,8 @@
19
19
  import { type Host } from './types.js';
20
20
  import { type DeviceProfile, type DeviceRegistry } from '../devices/registry.js';
21
21
  import { runLocalCommand, runOnDevice } from '../devices/fleet.js';
22
+ /** Re-export for callers that historically imported flagValue from this module. */
23
+ export { flagValue, hasHostRoutingFlag } from './routing-flag.js';
22
24
  /** Per-command remote behaviour. Absence from this map = not host-routable here. */
23
25
  interface RemoteSpec {
24
26
  /** Flags appended when running non-interactively (no local TTY / `--no-tty`). */
@@ -46,8 +48,6 @@ export declare const REMOTE_PASSTHROUGH: Record<string, RemoteSpec>;
46
48
  * these to {@link REMOTE_PASSTHROUGH}.
47
49
  */
48
50
  export declare const OWN_HOST_COMMANDS: Set<string>;
49
- /** Pull the value of `--host`/`-H`/`--remote-cwd` (any form) out of an argv. */
50
- export declare function flagValue(args: string[], long: string, short?: string): string | undefined;
51
51
  /** Injectable dependencies for {@link runFleetPassthrough} — used by tests. */
52
52
  export interface FleetPassthroughOptions {
53
53
  /** Override the device registry loader (tests). */
@@ -131,4 +131,3 @@ export declare function passthroughSshOptions(host: Host, interactive: boolean):
131
131
  multiplex: true;
132
132
  extraSshArgs: string[];
133
133
  };
134
- export {};
@@ -23,13 +23,19 @@ import { sshTargetFor, hostIdentityArgs } from './types.js';
23
23
  import { dispatchAgentsCommand, withActorEnv } from './dispatch.js';
24
24
  import { stripRoutingFlags, buildRemoteAgentsInvocation, stripClixml, HOST_ROUTING_SPECS, } from './remote-cmd.js';
25
25
  import { resolveRemoteOsSync } from './remote-os.js';
26
- import { machineId } from '../session/sync/config.js';
26
+ // Leaf import: `session/sync/config.js` re-exports machineId from machine-id.js
27
+ // but pulling the re-export path drags secrets/bundles (~140ms cold). Same value,
28
+ // 6–7× cheaper graph (RUSH-2374 proposal 2).
29
+ import { machineId } from '../machine-id.js';
27
30
  import { isDeviceAuto, resolveDeviceAffinity } from '../smart-launch.js';
31
+ import { flagValue, hasHostRoutingFlag } from './routing-flag.js';
28
32
  import { loadDevices } from '../devices/registry.js';
29
33
  import { isSelfHost } from '../devices/self-host.js';
30
34
  import { fanOutDevices, planFleetTargets, runLocalCommand, runOnDevice, } from '../devices/fleet.js';
31
35
  import { platformGroupLabel } from '../devices/health-report.js';
32
36
  import { isKnownTopLevelCommand } from '../startup/command-registry.js';
37
+ /** Re-export for callers that historically imported flagValue from this module. */
38
+ export { flagValue, hasHostRoutingFlag } from './routing-flag.js';
33
39
  /**
34
40
  * First-class groups that run transparently on a remote via SSH when
35
41
  * `--host`/`--device` is present. Keep both canonical names and aliases
@@ -95,9 +101,7 @@ export const REMOTE_PASSTHROUGH = {
95
101
  worktree: {},
96
102
  events: {},
97
103
  audit: {},
98
- lock: {},
99
104
  feedback: {},
100
- wallet: {},
101
105
  pty: {},
102
106
  tmux: {},
103
107
  watchdog: {},
@@ -118,6 +122,7 @@ export const OWN_HOST_COMMANDS = new Set([
118
122
  'feed',
119
123
  'computer',
120
124
  'secrets',
125
+ 'accounts', // `accounts sync --device` names the destination, not remote routing
121
126
  'logs',
122
127
  'hosts',
123
128
  'ssh',
@@ -135,21 +140,6 @@ const STRIP_SPECS = [
135
140
  { long: 'hosts', takesValue: true },
136
141
  { long: 'devices', takesValue: true },
137
142
  ];
138
- /** Pull the value of `--host`/`-H`/`--remote-cwd` (any form) out of an argv. */
139
- export function flagValue(args, long, short) {
140
- for (let i = 0; i < args.length; i++) {
141
- const a = args[i];
142
- if (a === `--${long}` || (short && a === `-${short}`))
143
- return args[i + 1];
144
- if (a.startsWith(`--${long}=`))
145
- return a.slice(long.length + 3);
146
- if (short && a.startsWith(`-${short}=`))
147
- return a.slice(short.length + 2);
148
- if (short && new RegExp(`^-${short}(.+)`).test(a))
149
- return a.slice(2);
150
- }
151
- return undefined;
152
- }
153
143
  /** Synthesize a `Host` for a raw `user@host` / bare-alias target (not enrolled). */
154
144
  function syntheticHost(target) {
155
145
  const at = target.indexOf('@');
@@ -584,13 +574,9 @@ export async function maybeRunOnHost(command, allArgs, opts) {
584
574
  */
585
575
  export async function maybeRunStandaloneOnHost(command, opts) {
586
576
  const rawArgs = process.argv.slice(2);
587
- const hasRoutingFlag = flagValue(rawArgs, 'host', 'H') !== undefined ||
588
- flagValue(rawArgs, 'device') !== undefined ||
589
- flagValue(rawArgs, 'hosts') !== undefined ||
590
- flagValue(rawArgs, 'devices') !== undefined;
591
577
  // No routing flag → nothing to route or strip. Leave argv alone so a purely
592
578
  // local run keeps every flag it passed.
593
- if (!hasRoutingFlag)
579
+ if (!hasHostRoutingFlag(rawArgs))
594
580
  return false;
595
581
  // Keep --help/--version local (docs must work without a reachable host), mirroring
596
582
  // index.ts's `helpOrVersionRequested` guard, but still strip the routing flags
@@ -626,7 +612,7 @@ export function streamAgentsOnHost(host, forwardedArgs, opts = {}) {
626
612
  const code = sshStream(target, remoteCmd, passthroughSshOptions(host, !!opts.interactive));
627
613
  if (code === 255) {
628
614
  console.error(chalk.red(`${host.name}: unreachable over SSH (asleep, offline, or host key changed?).`) +
629
- chalk.gray(' Check: agents hosts check ' + host.name));
615
+ chalk.gray(' Check: agents devices status'));
630
616
  }
631
617
  return code;
632
618
  }
@@ -243,7 +243,7 @@ export async function followHostTask(target, opts) {
243
243
  for (;;) {
244
244
  const remaining = deadline - Date.now();
245
245
  if (remaining <= 0) {
246
- process.stderr.write('\n[hosts] follow timed out; the run continues on the host. Reattach with: agents hosts logs ' + opts.taskId + ' -f\n');
246
+ process.stderr.write('\n[hosts] follow timed out; the run continues on the host. Reattach with: agents logs ' + opts.taskId + ' -f\n');
247
247
  return -1;
248
248
  }
249
249
  const abort = new AbortController();
@@ -271,7 +271,7 @@ export async function followHostTask(target, opts) {
271
271
  // chunks were flushed as they arrived, so reconnect from the advanced offset.
272
272
  // If no bytes arrived, back off like the old idle poll.
273
273
  if (Date.now() > deadline) {
274
- process.stderr.write('\n[hosts] follow timed out; the run continues on the host. Reattach with: agents hosts logs ' + opts.taskId + ' -f\n');
274
+ process.stderr.write('\n[hosts] follow timed out; the run continues on the host. Reattach with: agents logs ' + opts.taskId + ' -f\n');
275
275
  return -1;
276
276
  }
277
277
  // Reconnect quickly while output flows; ease toward maxMs when the stream
@@ -4,9 +4,9 @@
4
4
  * Bridges the devices registry (`agents devices`, ~/.agents/.history/devices/
5
5
  * registry.json) into the host pool behind the same `HostProvider` seam as
6
6
  * `local` — the "tailscale provider" fast-follow named in docs/hosts.md. With
7
- * it, a machine registered once via `agents devices sync` shows up in
8
- * `agents hosts list`, participates in capability routing, and is enumerable
9
- * by target pickers — not just resolvable by exact name.
7
+ * it, a machine registered once via `agents devices sync` becomes a resolvable
8
+ * `--host`/`--device` dispatch target, participates in capability routing, and
9
+ * is enumerable by target pickers — not just resolvable by exact name.
10
10
  *
11
11
  * Password-auth devices are listed (the pool stays honest about what exists)
12
12
  * but marked `dispatchable: false`; resolving one for dispatch throws the same