@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
@@ -37,6 +37,7 @@ import { injectIntoTerminal } from '../lib/terminal/index.js';
37
37
  import { iLoginShell } from '../lib/terminal/shell.js';
38
38
  import { shellQuote as quoteArg } from '../lib/terminal/quote.js';
39
39
  import { killSession } from '../lib/tmux/session.js';
40
+ import { getDefaultSocketPath } from '../lib/tmux/paths.js';
40
41
  import { listAllHosts, resolveHost } from '../lib/hosts/registry.js';
41
42
  import { sshTargetFor } from '../lib/hosts/types.js';
42
43
  import { readyProbe, bootstrapAgentsCli, viewHasAgent } from '../lib/hosts/ready.js';
@@ -406,6 +407,44 @@ function prepareEphemeralCwd(sshTarget, source, branch) {
406
407
  }
407
408
  return dir;
408
409
  }
410
+ /**
411
+ * Pure. The remote shell commands that create the target's tmux session on the
412
+ * SAME socket its reaper queries, and that probe its liveness afterward.
413
+ *
414
+ * `homeRelSocketPath` is `getDefaultSocketPath()` expressed relative to the
415
+ * LOCAL home dir (`path.relative(os.homedir(), getDefaultSocketPath())`) — a
416
+ * portable suffix, not a resolved absolute path, because the local and remote
417
+ * HOME can differ (different user, different OS). It is spliced in after a
418
+ * literal, unquoted `$HOME/` so the REMOTE shell resolves it; `$HOME` MUST
419
+ * NEVER be resolved locally (see AGENTS.md's remote-path guidance).
420
+ *
421
+ * Extracted as a pure function so the "does the migrated session land on the
422
+ * agents socket, not tmux's bare default socket" invariant is unit-testable
423
+ * without an SSH round-trip (RUSH-2521 review — a bare `tmux` here made the
424
+ * migrated agent's helpers invisible to `readAllPaneOwners`, so the reaper's
425
+ * next tick killed the still-live, just-migrated agent as `tmux-session-gone`).
426
+ */
427
+ export function buildMigrateResumeCommands(opts) {
428
+ const socketDirRelToHome = path.dirname(opts.homeRelSocketPath);
429
+ const socketFlag = `-S "$HOME/${opts.homeRelSocketPath}"`;
430
+ const argv = ['set-option', '-g', 'remain-on-exit', 'on', ';', 'new-session', '-d', '-s', opts.sessionName];
431
+ if (opts.cwd && opts.cwd !== '~')
432
+ argv.push('-c', opts.cwd);
433
+ argv.push(opts.inner);
434
+ // Mirror createSession's second half: keep remain-on-exit on THIS pane (the
435
+ // liveness probe below reads `pane_dead`), then put the server-wide default
436
+ // back to off. Leaving `-g on` set made every later pane on the target — user
437
+ // splits included — retain a corpse when its command finished.
438
+ argv.push(';', 'set-option', '-t', opts.sessionName, '-p', 'remain-on-exit', 'on');
439
+ argv.push(';', 'set-option', '-g', 'remain-on-exit', 'off');
440
+ // Unlike tmux's own scratch dir (auto-created under /tmp), the agents socket's
441
+ // parent may not exist yet on a fresh worker or ephemeral box that never ran a
442
+ // tmux-backed `agents` command — `mkdir -p` it before tmux tries to bind there.
443
+ const launchCmd = `mkdir -p "$HOME/${socketDirRelToHome}" && tmux ${socketFlag} ` + argv.map(shellQuote).join(' ');
444
+ const q = shellQuote(opts.sessionName);
445
+ const probeCmd = `sleep 3; tmux ${socketFlag} has-session -t ${q} 2>/dev/null || exit 3; test "$(tmux ${socketFlag} list-panes -t ${q} -F '#{pane_dead}' 2>/dev/null | head -n1)" = 0 || exit 4`;
446
+ return { launchCmd, probeCmd, socketFlag };
447
+ }
409
448
  /**
410
449
  * Resume the session on the target through the SAME host path as
411
450
  * `sessions resume --host` (tmux backend). Returns true when the resume launched.
@@ -426,14 +465,18 @@ async function resumeOnTarget(sshTarget, source, remoteCwd, mode) {
426
465
  // carries spaces or backticks (the rehydrate prompt) reaches the agent as one
427
466
  // clean argument — an unquoted join would let the target shell split it and
428
467
  // run its backticks.
468
+ //
469
+ // The pane exports AGENT_TMUX_SESSION_NAME the way a local `createSession`
470
+ // pane does, so the target's reaper can attribute the helpers this agent
471
+ // spawns and collect them when it exits (RUSH-2521, `lib/tmux/orphan-reap.ts`)
472
+ // — see {@link buildMigrateResumeCommands} for why the session MUST land on
473
+ // the agents socket rather than tmux's bare default socket.
429
474
  const sessionName = `migrate-${source.shortId}`;
430
- const inner = iLoginShell(`exec ${command.map(quoteArg).join(' ')}`);
431
- const argv = ['tmux', 'set-option', '-g', 'remain-on-exit', 'on', ';', 'new-session', '-d', '-s', sessionName];
475
+ const homeRelSocketPath = path.relative(os.homedir(), getDefaultSocketPath());
476
+ const inner = iLoginShell(`export AGENT_TMUX_SESSION_NAME=${sessionName}; exec ${command.map(quoteArg).join(' ')}`);
432
477
  const cwd = remoteCwd ?? source.cwd;
433
- if (cwd && cwd !== '~')
434
- argv.push('-c', cwd);
435
- argv.push(inner);
436
- const launch = sshExec(sshTarget, argv.map(shellQuote).join(' '), { timeoutMs: 60000 });
478
+ const { launchCmd, probeCmd } = buildMigrateResumeCommands({ sessionName, homeRelSocketPath, inner, cwd });
479
+ const launch = sshExec(sshTarget, launchCmd, { timeoutMs: 60000 });
437
480
  if (launch.code !== 0) {
438
481
  console.log(chalk.red(` Resume on ${sshTarget} failed: ${launch.stderr.trim().split('\n').pop() || `tmux exited ${launch.code}`}`));
439
482
  return false;
@@ -441,9 +484,7 @@ async function resumeOnTarget(sshTarget, source, remoteCwd, mode) {
441
484
  // Liveness gate for the invariant: give the agent a moment to boot, then require
442
485
  // the pane to be ALIVE (not merely the session to exist) before the caller may
443
486
  // stop the source. An agent that dies on launch → we refuse to move.
444
- const q = shellQuote(sessionName);
445
- const probe = `sleep 3; tmux has-session -t ${q} 2>/dev/null || exit 3; test "$(tmux list-panes -t ${q} -F '#{pane_dead}' 2>/dev/null | head -n1)" = 0 || exit 4`;
446
- const check = sshExec(sshTarget, probe, { timeoutMs: 30000 });
487
+ const check = sshExec(sshTarget, probeCmd, { timeoutMs: 30000 });
447
488
  if (check.code !== 0) {
448
489
  const why = check.code === 4 ? 'the agent exited immediately on the target'
449
490
  : check.code === 3 ? 'the session did not start'
@@ -20,7 +20,7 @@ import { itemPicker } from '../lib/picker.js';
20
20
  import { createMemoryCache } from '../lib/memory-cache.js';
21
21
  import { classifyFileChanges, changeCounts, toolHistogram, detectTestResult } from '../lib/session/digest.js';
22
22
  import { extractArtifacts, extractHooks, extractLinks, extractRepos, extractSkills } from '../lib/session/highlights.js';
23
- import { getSessionPlugins, readSessionPreviewCache, writeSessionPreviewCache } from '../lib/session/db.js';
23
+ import { getSessionPlugins, readSessionPreviewCache, writeSessionPreviewCache, readSessionContent, readArchivedSessionPreview } from '../lib/session/db.js';
24
24
  /** A session whose transcript FILE is on another machine (folded in over the
25
25
  * live cross-machine fan-out): its `filePath` is on that peer's disk, so the
26
26
  * preview can't parse it locally — it shows metadata + a "resume there" note
@@ -130,8 +130,17 @@ export function clearPreviewMemoryCacheForTest() {
130
130
  previewCache.clear();
131
131
  }
132
132
  export function loadSessionPreviewDigest(session) {
133
- if (!session.filePath || !fs.existsSync(session.filePath))
133
+ if (!session.filePath || !fs.existsSync(session.filePath)) {
134
+ // File gone, but an archived session (RUSH-2436) keeps its last-computed
135
+ // digest in the DB — serve that so the picker preview still shows its turns
136
+ // instead of a bare "not indexed here" note. No events to replay.
137
+ const archived = readArchivedSessionPreview(session.id);
138
+ if (archived) {
139
+ archived.plugins = getSessionPlugins(session.id);
140
+ return { digest: archived, events: [] };
141
+ }
134
142
  return { events: [] };
143
+ }
135
144
  const safe = sanitizeMeta(session);
136
145
  let events = [];
137
146
  let sourceStamp;
@@ -182,9 +191,19 @@ export function buildPreview(session) {
182
191
  previewCache.set(cacheKey, output);
183
192
  return output;
184
193
  }
185
- // No transcript on disk — a live session not indexed locally, or a synthesized
186
- // entry (e.g. `sessions go`). Show the header + a clean note, not a parse error.
194
+ // No transcript on disk — either an archived session (file gone, user turns
195
+ // still in the DB — RUSH-2436), a live session not indexed locally, or a
196
+ // synthesized entry (e.g. `sessions go`). Show the header + a clean note.
187
197
  if (!session.filePath || !fs.existsSync(session.filePath)) {
198
+ const archivedContent = readSessionContent(session.id);
199
+ if (archivedContent && archivedContent.trim() !== '') {
200
+ const note = ' ' + chalk.yellow('archived — transcript file removed; served from the local DB');
201
+ const { digest } = loadSessionPreviewDigest(session);
202
+ const body = digest ? formatCompactPreview(digest, safe) : formatMetaOnlyBody(safe);
203
+ const output = [formatHeader(safe, []), '', note, body].filter(Boolean).join('\n');
204
+ previewCache.set(cacheKey, output);
205
+ return output;
206
+ }
188
207
  const note = ' ' + chalk.gray('Live session — full transcript not indexed here.');
189
208
  const metaBody = formatMetaOnlyBody(safe);
190
209
  const output = [formatHeader(safe, []), '', note, metaBody].filter(Boolean).join('\n');
@@ -1,5 +1,5 @@
1
1
  import type { Command } from 'commander';
2
- import type { SessionMeta } from '../lib/session/types.js';
2
+ import { type SessionMeta } from '../lib/session/types.js';
3
3
  import { type Backend, type EngineContext, type Packing } from '../lib/terminal/index.js';
4
4
  /** Opening more than this many live sessions at once asks for confirmation first. */
5
5
  export declare const CONFIRM_THRESHOLD = 5;
@@ -17,6 +17,8 @@ export interface ResumeOptions {
17
17
  /** --terminal-app: force macOS Terminal.app. Named to avoid reading as `run --terminal`. */
18
18
  terminalApp?: boolean;
19
19
  splits?: boolean;
20
+ attachOnly?: boolean;
21
+ local?: boolean;
20
22
  }
21
23
  export declare function registerSessionsResumeCommand(sessionsCmd: Command): void;
22
24
  /** IDs and tmux aliases are actions, not picker search text. Human phrases keep
@@ -28,8 +30,8 @@ export declare function resumeSelectorInPlace(selector: string): Promise<void>;
28
30
  /** Direct identities use focus as the lifecycle dispatcher: it rechecks the
29
31
  * live fleet, attaches a healthy pane, and falls through to `agents resume`
30
32
  * only when the process is no longer attachable. */
31
- export declare function dispatchSessionLifecycleInPlace(selector: string, hosts?: string[]): Promise<void>;
32
- export declare function buildSessionLifecycleArgs(selector: string, hosts?: string[]): string[];
33
+ export declare function dispatchSessionLifecycleInPlace(selector: string, hosts?: string[], attachOnly?: boolean, local?: boolean): Promise<void>;
34
+ export declare function buildSessionLifecycleArgs(selector: string, hosts?: string[], attachOnly?: boolean, local?: boolean): string[];
33
35
  export declare function resolveResumePacking(options: Pick<ResumeOptions, 'splits'>): Packing;
34
36
  export declare function resumeHostMismatch(session: Pick<SessionMeta, 'shortId' | 'machine'>, requestedHost: string, self?: string): string | null;
35
37
  /**
@@ -10,6 +10,7 @@
10
10
  */
11
11
  import * as fs from 'fs';
12
12
  import chalk from 'chalk';
13
+ import { isAgentTmuxAlias } from '../lib/session/types.js';
13
14
  import { discoverSessions } from '../lib/session/discover.js';
14
15
  import { filterTeamSessions } from '../lib/session/team-filter.js';
15
16
  import { multiItemPicker, itemPicker } from '../lib/picker.js';
@@ -42,6 +43,8 @@ export function registerSessionsResumeCommand(sessionsCmd) {
42
43
  .option('--tmux', 'Force the tmux backend')
43
44
  .option('--vscodium', 'Force the VSCodium agent-terminal backend (swarm-ext)')
44
45
  .option('--terminal-app', 'Force macOS Terminal.app (no split support — panes become tabs)')
46
+ .option('--local', 'Only this machine (skip the cross-host sweep)')
47
+ .option('--attach-only', 'With an id/alias: attach a living pane only — never resume a copy')
45
48
  .option('--splits', 'Pack two sessions side by side per tab (default: one tab per session)');
46
49
  setHelpSections(cmd, {
47
50
  examples: `
@@ -55,6 +58,9 @@ export function registerSessionsResumeCommand(sessionsCmd) {
55
58
  agents sessions resume 019fd114
56
59
  agents sessions resume ag-codex-c1f3d813
57
60
 
61
+ # Attach a living pane only — never resume a copy (the old go)
62
+ agents sessions resume 019fd114 --attach-only
63
+
58
64
  # Force a backend / side-by-side splits / a remote host
59
65
  agents sessions resume --ghostty
60
66
  agents sessions resume --vscodium
@@ -62,7 +68,10 @@ export function registerSessionsResumeCommand(sessionsCmd) {
62
68
  agents sessions resume --host zion --tmux
63
69
  `,
64
70
  notes: `
65
- - A UUID/prefix or ag-<agent>-<suffix> alias bypasses the picker: a live pane is attached; an inactive session resumes on its owning device.
71
+ - This is the ONE verb for getting back in. It detects the state: a live tmux pane is attached, a headless session comes to the foreground, an ended one recovers on its owning device.
72
+ - A UUID/prefix or ag-<agent>-<suffix> alias bypasses the picker. A live alias attaches by name even when the session index cannot attribute it.
73
+ - Retired spellings still work for one release and print the replacement: sessions attach, sessions go, reconnect.
74
+ - Going the other way (foreground -> background) is 'agents sessions detach <id>'.
66
75
  - With no identity selector, space toggles a session, enter confirms, and tab toggles the preview pane.
67
76
  - Layout: one tab per session by default. --splits packs session pairs side by side in each tab.
68
77
  - Backend: auto-detected from the terminal you're in (iTerm / Ghostty / tmux); override with --iterm/--ghostty/--tmux/--vscodium.
@@ -82,7 +91,7 @@ async function sessionsResumeAction(query, options) {
82
91
  return;
83
92
  }
84
93
  if (query && isDirectResumeSelector(query)) {
85
- await dispatchSessionLifecycleInPlace(query.trim(), options.host ? [options.host] : []);
94
+ await dispatchSessionLifecycleInPlace(query.trim(), options.host ? [options.host] : [], options.attachOnly === true, options.local === true);
86
95
  return;
87
96
  }
88
97
  const { agent, version } = parseAgentFilter(options.agent);
@@ -182,7 +191,15 @@ async function sessionsResumeAction(query, options) {
182
191
  console.log(chalk.yellow('Terminal.app cannot split panes — opening one tab per session instead.'));
183
192
  }
184
193
  console.log(chalk.gray(`Opening ${items.length} session${items.length === 1 ? '' : 's'} in ${where} (${packing})…`));
185
- const results = await openSurfaces(items.map((it) => ({ cwd: it.cwd, command: it.command })), { backend, host: options.host, packing });
194
+ // agent + sessionId ride the SurfaceItem into the vscodium-agent spawn URI
195
+ // so the extension can set the tab chip without process-tree sniffing (#2478).
196
+ const results = await openSurfaces(items.map((it) => ({
197
+ cwd: it.cwd,
198
+ command: it.command,
199
+ agent: it.session.agent || undefined,
200
+ sessionId: it.session.id || undefined,
201
+ title: it.session.label || it.session.topic || undefined,
202
+ })), { backend, host: options.host, packing });
186
203
  let opened = 0;
187
204
  results.forEach((r, i) => {
188
205
  const s = items[i].session;
@@ -201,7 +218,7 @@ async function sessionsResumeAction(query, options) {
201
218
  * the existing pre-filtered picker, while an explicit identity resumes directly. */
202
219
  export function isDirectResumeSelector(query) {
203
220
  const selector = query.trim();
204
- return looksLikeSessionId(selector) || /^ag-[a-z][a-z0-9-]*-[0-9a-f]{8}$/i.test(selector);
221
+ return looksLikeSessionId(selector) || isAgentTmuxAlias(selector);
205
222
  }
206
223
  /** Re-enter through the top-level command so fleet routing and harness policy
207
224
  * stay centralized. The child inherits this terminal for a real interactive resume. */
@@ -211,11 +228,16 @@ export async function resumeSelectorInPlace(selector) {
211
228
  /** Direct identities use focus as the lifecycle dispatcher: it rechecks the
212
229
  * live fleet, attaches a healthy pane, and falls through to `agents resume`
213
230
  * only when the process is no longer attachable. */
214
- export async function dispatchSessionLifecycleInPlace(selector, hosts = []) {
215
- await spawnCliInPlace(buildSessionLifecycleArgs(selector, hosts));
231
+ export async function dispatchSessionLifecycleInPlace(selector, hosts = [], attachOnly = false, local = false) {
232
+ await spawnCliInPlace(buildSessionLifecycleArgs(selector, hosts, attachOnly, local));
216
233
  }
217
- export function buildSessionLifecycleArgs(selector, hosts = []) {
218
- return ['sessions', 'focus', selector, ...hosts.flatMap(host => ['--host', host])];
234
+ export function buildSessionLifecycleArgs(selector, hosts = [], attachOnly = false, local = false) {
235
+ return [
236
+ 'sessions', 'focus', selector,
237
+ ...hosts.flatMap(host => ['--host', host]),
238
+ ...(attachOnly ? ['--attach-only'] : []),
239
+ ...(local ? ['--local'] : []),
240
+ ];
219
241
  }
220
242
  function asyncExitCode(child) {
221
243
  return new Promise((resolve) => {
@@ -0,0 +1,2 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerSessionsWatchCommand(parent: Command): void;
@@ -0,0 +1,53 @@
1
+ import { machineId } from '../lib/machine-id.js';
2
+ import { setHelpSections } from '../lib/help.js';
3
+ import { watchFleetSessions, watchLocalSessions } from '../lib/session/watch.js';
4
+ export function registerSessionsWatchCommand(parent) {
5
+ const command = parent.command('watch')
6
+ .description('Stream canonical live and recoverable session row changes as NDJSON')
7
+ .option('--json', 'Emit versioned NDJSON envelopes')
8
+ .option('--local', 'Watch only this machine');
9
+ setHelpSections(command, {
10
+ examples: `
11
+ # Subscribe to session changes for a long-lived UI consumer
12
+ agents sessions watch --json
13
+
14
+ # Subscribe only to this machine
15
+ agents sessions watch --json --local
16
+ `,
17
+ notes: `
18
+ - Each line is one versioned reset, upsert, remove, scope, or heartbeat envelope.
19
+ - rowKey is opaque. Order changes by streamId + sequence.
20
+ - An unavailable scope retains its last rows until that scope reconnects.
21
+ `,
22
+ });
23
+ command.action(async (_options, invoked) => {
24
+ const options = invoked.optsWithGlobals();
25
+ if (!options.json)
26
+ invoked.error('error: required option \'--json\' not specified');
27
+ const controller = new AbortController();
28
+ const stop = () => controller.abort();
29
+ const stopOnClosedConsumer = (error) => {
30
+ if (error.code === 'EPIPE')
31
+ controller.abort();
32
+ else {
33
+ process.exitCode = 1;
34
+ controller.abort(error);
35
+ }
36
+ };
37
+ process.once('SIGINT', stop);
38
+ process.once('SIGTERM', stop);
39
+ process.stdout.on('error', stopOnClosedConsumer);
40
+ try {
41
+ const emit = (event) => process.stdout.write(`${JSON.stringify(event)}\n`);
42
+ if (options.local)
43
+ await watchLocalSessions({ scope: machineId(), signal: controller.signal, emit });
44
+ else
45
+ await watchFleetSessions({ signal: controller.signal, emit });
46
+ }
47
+ finally {
48
+ process.off('SIGINT', stop);
49
+ process.off('SIGTERM', stop);
50
+ process.stdout.off('error', stopOnClosedConsumer);
51
+ }
52
+ });
53
+ }
@@ -3,8 +3,10 @@ import { type ProjectDef } from '../lib/projects.js';
3
3
  import type { SessionAgentId, SessionMeta, ViewMode } from '../lib/session/types.js';
4
4
  import { type ActiveSession } from '../lib/session/active.js';
5
5
  import { gatherRemoteList, runOnPeer } from '../lib/session/remote-list.js';
6
+ import { type RemoteAgentsJsonParseResult } from '../lib/remote-agents-json.js';
6
7
  import { type RunMeta } from '../lib/routines.js';
7
8
  import { type PickedSession } from './sessions-picker.js';
9
+ import { type ComputerRunRow } from '../lib/computer/sessions-list.js';
8
10
  import { type ToolSearchEnvelope, type ToolProgramCountEnvelope } from '../lib/session/tool-index.js';
9
11
  interface SessionFilterOptions {
10
12
  agent?: string;
@@ -254,6 +256,22 @@ export declare function serializeActiveSessionsForJson(sessions: ActiveSession[]
254
256
  prLink: string | null;
255
257
  viewingIn: string | null;
256
258
  }>;
259
+ export interface SessionPickerJsonRow extends SessionMeta {
260
+ state: ActiveSession['status'] | 'inactive';
261
+ resumable: boolean;
262
+ unwatched: boolean;
263
+ viewingIn: string | null;
264
+ sourceDevice: string;
265
+ lastActivityMs: number;
266
+ pid: number | null;
267
+ recovery: {
268
+ command: 'agents';
269
+ args: string[];
270
+ cwd?: string;
271
+ } | null;
272
+ }
273
+ /** Canonical JSON row consumed by resume pickers and other session UIs. */
274
+ export declare function serializeSessionPickerRows(sessions: SessionMeta[], liveSessions: ActiveSession[], self?: string): SessionPickerJsonRow[];
257
275
  /**
258
276
  * Build the (one or two) rendered lines for a single active-session row.
259
277
  * Indent is the leading whitespace (2 spaces for flat groups, 4 inside a window
@@ -332,6 +350,15 @@ export declare function groupSessionsByMachine(sessions: ActiveSession[], localM
332
350
  * correlated, so they're all kept.
333
351
  */
334
352
  export declare function dedupeByMachineSession(sessions: ActiveSession[]): ActiveSession[];
353
+ /**
354
+ * Narrow a gathered live set to the machines an explicit `--host`/`--device`
355
+ * scope named. The gather picks which boxes to ASK; this asserts what the answer
356
+ * may contain, and the two are not the same question: a host-dispatched run is
357
+ * reported by the box that dispatched it while executing somewhere else, so
358
+ * `--device <dispatcher>` used to list sessions that were not running there at
359
+ * all (RUSH-2479). No scope → unchanged. Pure; exported for unit testing.
360
+ */
361
+ export declare function filterActiveSessionsByHostScope(sessions: ActiveSession[], hosts: string[] | undefined, self: string): ActiveSession[];
335
362
  /**
336
363
  * Order a merged listing so the local machine's sessions come first, then each
337
364
  * remote machine as a contiguous block (more sessions first, then name), with
@@ -356,6 +383,14 @@ export declare function serializeSessionsJson(sessions: SessionMeta[]): string;
356
383
  * It includes only launch identity needed to route/resume. Transcript paths,
357
384
  * extracted plans, costs, and content stay on the machine that owns them. */
358
385
  export declare function serializeResolvedSessionsJson(sessions: SessionMeta[]): string;
386
+ /** Parse one peer's computer-run array without accepting banners or partial
387
+ * JSON. The fan-out boundary supplies the machine name when an older peer row
388
+ * omitted it. */
389
+ export declare function parseRemoteComputerSessionRows(stdout: string, machine: string): RemoteAgentsJsonParseResult<ComputerRunRow>;
390
+ /** Collect computer history from named peers, or every automatic peer when
391
+ * hosts is omitted. Every peer is forced to JSON and receives the recursion
392
+ * guard through the shared fleet transport. */
393
+ export declare function gatherRemoteComputerSessionRows(hosts?: string[]): Promise<ComputerRunRow[]>;
359
394
  /**
360
395
  * Whether the local machine's sessions belong in an `--active` view. Local is
361
396
  * included by default; an explicit `--host`/`--device` list scopes the view to
@@ -829,6 +864,11 @@ export type MetadataResolveOutcome = {
829
864
  * the wrong session (whichever peer replied first). Labels therefore stay
830
865
  * all-settle so a cross-machine label conflict surfaces as an ambiguity, and a
831
866
  * short-id PREFIX stays all-settle for the same reason (RUSH-2203).
867
+ *
868
+ * This is about cancelling a sweep that is still IN FLIGHT, where a peer that
869
+ * has not answered yet is still expected to. It is deliberately stricter than
870
+ * `isUniqueEnoughSelector`, which decides what to do once the sweep is OVER and
871
+ * a peer has definitively not answered — see SES-9a.
832
872
  */
833
873
  export declare function isDefinitiveMatch(session: SessionMeta, selector: string): boolean;
834
874
  /**
@@ -849,9 +889,20 @@ export declare function fleetCandidatesByQuery(rows: SessionMeta[], query: strin
849
889
  export declare function metadataResolveForwardedArgs(selector: string, scope: Pick<SessionFilterOptions, 'agent' | 'project'>): string[];
850
890
  /** Build the local-only peer argv for a distributed tool search. */
851
891
  export declare function toolSearchForwardedArgs(argv: string[], hosts: string[]): string[];
852
- /** Resolution fails closed for prefixes/keywords when a peer did not answer.
853
- * A full UUID is globally unique, so one exact hit is sufficient even when an
854
- * unrelated registered device is offline. */
892
+ /**
893
+ * Whether a selector names ONE session precisely enough to resolve from the
894
+ * reachable fleet alone when some peer did not answer (SES-9a).
895
+ *
896
+ * Deliberately stricter than `looksLikeSessionId`, which accepts any 6+ char
897
+ * `[0-9a-f-]` run and so matches ordinary words (`facade`, `decade`, `beaded`).
898
+ * Those are keywords a user typed as a search, not identifiers, and they must
899
+ * keep waiting for every peer.
900
+ */
901
+ export declare function isUniqueEnoughSelector(selector: string): boolean;
902
+ /** Resolution fails closed for keywords and labels when a peer did not answer.
903
+ * An id-shaped selector at least `SHORT_SESSION_ID_WIDTH` hex chars wide (or a
904
+ * complete id) resolves from a single reachable hit even when an unrelated
905
+ * registered device is offline — see SES-9a for the accepted collision risk. */
855
906
  export declare function metadataResolveOutcome(localMatches: SessionMeta[], remote: {
856
907
  sessions: SessionMeta[];
857
908
  unreachable: string[];
@@ -864,6 +915,18 @@ export declare function resolveSessionMetadataValue(selector: string, scope?: {
864
915
  local?: boolean;
865
916
  hosts?: string[];
866
917
  }, deps?: Pick<FleetResolveDeps, 'gatherRemoteList'>): Promise<MetadataResolveOutcome>;
918
+ /** Resolve one selector to indexed metadata across the fleet without reading or
919
+ * rendering transcript events. A peer answering the parent sweep returns every
920
+ * local candidate; the parent performs the one logical-session uniqueness gate.
921
+ * Backs `agents sessions --resolve <selector> --json`. Exported (deps already
922
+ * injectable) so tests can drive this real call site against a fake fan-out
923
+ * instead of only the pure resolver it wraps. */
924
+ export declare function resolveSessionMetadata(selector: string, scope: {
925
+ agent?: string;
926
+ project?: string;
927
+ local?: boolean;
928
+ hosts?: string[];
929
+ }, deps?: Pick<FleetResolveDeps, 'gatherRemoteList'>): Promise<void>;
867
930
  /**
868
931
  * Locate a full session id or short id prefix across the online fleet and render it from the machine
869
932
  * that holds it. The local disk already missed; this fans `sessions <id> --json