@phnx-labs/agents-cli 1.22.39 → 1.22.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (569) hide show
  1. package/CHANGELOG.md +316 -0
  2. package/README.md +116 -70
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.js +45 -27
  5. package/dist/browser.js +2 -2
  6. package/dist/cli/command-registry.d.ts +135 -0
  7. package/dist/cli/command-registry.js +259 -0
  8. package/dist/commands/accounts.d.ts +20 -0
  9. package/dist/commands/accounts.js +186 -25
  10. package/dist/commands/apply.d.ts +3 -3
  11. package/dist/commands/apply.js +20 -63
  12. package/dist/commands/browser.d.ts +15 -0
  13. package/dist/commands/browser.js +318 -131
  14. package/dist/commands/budget.d.ts +7 -6
  15. package/dist/commands/budget.js +8 -7
  16. package/dist/commands/cloud.js +17 -20
  17. package/dist/commands/commands.js +1 -1
  18. package/dist/commands/computer-actions.d.ts +1 -35
  19. package/dist/commands/computer-actions.js +13 -181
  20. package/dist/commands/computer.d.ts +28 -3
  21. package/dist/commands/computer.js +93 -65
  22. package/dist/commands/config.js +16 -3
  23. package/dist/commands/cost.d.ts +2 -1
  24. package/dist/commands/cost.js +7 -6
  25. package/dist/commands/daemon.js +151 -4
  26. package/dist/commands/detach.js +1 -1
  27. package/dist/commands/doctor.js +19 -11
  28. package/dist/commands/events.js +1 -1
  29. package/dist/commands/exec.d.ts +2 -50
  30. package/dist/commands/exec.js +160 -215
  31. package/dist/commands/factory.js +1 -1
  32. package/dist/commands/feed.d.ts +2 -2
  33. package/dist/commands/feed.js +12 -23
  34. package/dist/commands/fleet-capture.js +25 -27
  35. package/dist/commands/focus.d.ts +2 -3
  36. package/dist/commands/focus.js +34 -9
  37. package/dist/commands/go.js +15 -5
  38. package/dist/commands/harness.d.ts +3 -3
  39. package/dist/commands/harness.js +53 -5
  40. package/dist/commands/hooks.js +1 -1
  41. package/dist/commands/import.js +2 -2
  42. package/dist/commands/insights.d.ts +5 -5
  43. package/dist/commands/insights.js +15 -9
  44. package/dist/commands/inspect.d.ts +2 -3
  45. package/dist/commands/inspect.js +4 -16
  46. package/dist/commands/logs.d.ts +2 -2
  47. package/dist/commands/logs.js +9 -9
  48. package/dist/commands/mcp.js +2 -2
  49. package/dist/commands/memory.js +1 -1
  50. package/dist/commands/message.d.ts +1 -1
  51. package/dist/commands/message.js +7 -7
  52. package/dist/commands/mine.d.ts +11 -8
  53. package/dist/commands/mine.js +11 -10
  54. package/dist/commands/models.js +1 -1
  55. package/dist/commands/modes.js +1 -1
  56. package/dist/commands/monitors.js +23 -6
  57. package/dist/commands/output.d.ts +7 -6
  58. package/dist/commands/output.js +11 -10
  59. package/dist/commands/packages.js +4 -4
  60. package/dist/commands/perf.js +1 -1
  61. package/dist/commands/permissions.js +49 -32
  62. package/dist/commands/plugins.d.ts +1 -1
  63. package/dist/commands/plugins.js +3 -3
  64. package/dist/commands/profiles.d.ts +6 -9
  65. package/dist/commands/profiles.js +8 -321
  66. package/dist/commands/projects.d.ts +9 -0
  67. package/dist/commands/projects.js +140 -8
  68. package/dist/commands/prune.js +5 -13
  69. package/dist/commands/refresh-rules.js +1 -1
  70. package/dist/commands/repo.d.ts +5 -7
  71. package/dist/commands/repo.js +34 -18
  72. package/dist/commands/resource-view.js +4 -0
  73. package/dist/commands/resume.d.ts +11 -7
  74. package/dist/commands/resume.js +82 -98
  75. package/dist/commands/route.d.ts +12 -0
  76. package/dist/commands/route.js +261 -0
  77. package/dist/commands/routines.d.ts +2 -3
  78. package/dist/commands/routines.js +120 -145
  79. package/dist/commands/rules.js +1 -1
  80. package/dist/commands/run-account-picker.d.ts +1 -1
  81. package/dist/commands/run-account-picker.js +2 -2
  82. package/dist/commands/run-broadcast.d.ts +21 -0
  83. package/dist/commands/run-broadcast.js +89 -0
  84. package/dist/commands/run-cloud.js +1 -1
  85. package/dist/commands/secrets-vault.d.ts +10 -0
  86. package/dist/commands/{login.js → secrets-vault.js} +34 -14
  87. package/dist/commands/secrets.d.ts +4 -4
  88. package/dist/commands/secrets.js +158 -159
  89. package/dist/commands/sessions-backfill.js +1 -1
  90. package/dist/commands/sessions-browser.d.ts +1 -1
  91. package/dist/commands/sessions-browser.js +9 -5
  92. package/dist/commands/sessions-export.js +2 -2
  93. package/dist/commands/sessions-inject.js +4 -5
  94. package/dist/commands/sessions-migrate.js +16 -27
  95. package/dist/commands/sessions-picker.d.ts +14 -0
  96. package/dist/commands/sessions-picker.js +209 -13
  97. package/dist/commands/sessions-resume.d.ts +7 -3
  98. package/dist/commands/sessions-resume.js +81 -33
  99. package/dist/commands/sessions-share.d.ts +25 -0
  100. package/dist/commands/sessions-share.js +166 -0
  101. package/dist/commands/sessions-stats.js +2 -2
  102. package/dist/commands/sessions.d.ts +75 -68
  103. package/dist/commands/sessions.js +144 -180
  104. package/dist/commands/setup-browser.js +1 -1
  105. package/dist/commands/setup-computer.js +1 -1
  106. package/dist/commands/setup-fleet.js +3 -0
  107. package/dist/commands/setup-mine.d.ts +7 -3
  108. package/dist/commands/setup-mine.js +13 -8
  109. package/dist/commands/setup-preferences.js +2 -2
  110. package/dist/commands/setup-secrets.js +2 -2
  111. package/dist/commands/setup-watchdog.js +2 -2
  112. package/dist/commands/setup.js +7 -2
  113. package/dist/commands/share.d.ts +65 -0
  114. package/dist/commands/share.js +253 -20
  115. package/dist/commands/skills.js +3 -3
  116. package/dist/commands/snapshot.d.ts +2 -2
  117. package/dist/commands/snapshot.js +9 -9
  118. package/dist/commands/ssh.d.ts +1 -1
  119. package/dist/commands/ssh.js +186 -64
  120. package/dist/commands/subagents.js +1 -1
  121. package/dist/commands/sync.js +24 -9
  122. package/dist/commands/teams.d.ts +2 -2
  123. package/dist/commands/teams.js +9 -18
  124. package/dist/commands/tmux.js +5 -1
  125. package/dist/commands/trash.js +1 -1
  126. package/dist/commands/usage.d.ts +1 -1
  127. package/dist/commands/usage.js +2 -2
  128. package/dist/commands/utils.d.ts +4 -14
  129. package/dist/commands/utils.js +6 -27
  130. package/dist/commands/versions.js +2 -2
  131. package/dist/commands/view.d.ts +9 -77
  132. package/dist/commands/view.js +23 -8
  133. package/dist/commands/watchdog.js +1 -1
  134. package/dist/commands/webhook.js +25 -34
  135. package/dist/commands/workflows.js +1 -1
  136. package/dist/index.js +1 -1
  137. package/dist/lib/account-capabilities.d.ts +39 -0
  138. package/dist/lib/account-capabilities.js +59 -0
  139. package/dist/lib/account-catalog.js +1 -1
  140. package/dist/lib/account-registry.d.ts +66 -0
  141. package/dist/lib/account-registry.js +151 -5
  142. package/dist/lib/{rotate.d.ts → accounting/rotate.d.ts} +4 -4
  143. package/dist/lib/{rotate.js → accounting/rotate.js} +8 -8
  144. package/dist/lib/{usage.d.ts → accounting/usage.d.ts} +4 -4
  145. package/dist/lib/{usage.js → accounting/usage.js} +11 -11
  146. package/dist/lib/agent-spec/provider.js +1 -1
  147. package/dist/lib/agents.d.ts +72 -4
  148. package/dist/lib/agents.js +231 -199
  149. package/dist/lib/answer-router.d.ts +2 -2
  150. package/dist/lib/ask-classifier.d.ts +1 -1
  151. package/dist/lib/ask-classifier.js +1 -1
  152. package/dist/lib/audit/log.js +1 -1
  153. package/dist/lib/auth-health.d.ts +1 -1
  154. package/dist/lib/auth-health.js +2 -2
  155. package/dist/lib/brand.js +1 -1
  156. package/dist/lib/browser/caller-identity.d.ts +28 -0
  157. package/dist/lib/browser/caller-identity.js +156 -0
  158. package/dist/lib/browser/cdp.js +5 -1
  159. package/dist/lib/browser/chrome.js +12 -1
  160. package/dist/lib/browser/drivers/ssh.d.ts +1 -1
  161. package/dist/lib/browser/drivers/ssh.js +3 -2
  162. package/dist/lib/browser/hygiene.d.ts +10 -2
  163. package/dist/lib/browser/hygiene.js +7 -4
  164. package/dist/lib/browser/ipc.d.ts +22 -2
  165. package/dist/lib/browser/ipc.js +185 -21
  166. package/dist/lib/browser/profiles.d.ts +69 -5
  167. package/dist/lib/browser/profiles.js +135 -13
  168. package/dist/lib/browser/remote-control.d.ts +2 -2
  169. package/dist/lib/browser/remote-control.js +3 -3
  170. package/dist/lib/browser/runtime-state.d.ts +79 -0
  171. package/dist/lib/browser/runtime-state.js +119 -1
  172. package/dist/lib/browser/service.d.ts +137 -2
  173. package/dist/lib/browser/service.js +492 -54
  174. package/dist/lib/browser/sessions-list.d.ts +2 -1
  175. package/dist/lib/browser/sessions-list.js +4 -13
  176. package/dist/lib/browser/types.d.ts +19 -1
  177. package/dist/lib/budget/config.js +1 -1
  178. package/dist/lib/budget/ledger.js +1 -1
  179. package/dist/lib/byok-usage.js +1 -1
  180. package/dist/lib/capabilities.js +3 -15
  181. package/dist/lib/catchup.d.ts +1 -1
  182. package/dist/lib/catchup.js +1 -1
  183. package/dist/lib/cloud/dispatch.js +1 -1
  184. package/dist/lib/cloud/host.d.ts +3 -3
  185. package/dist/lib/cloud/host.js +5 -5
  186. package/dist/lib/cloud/rush.d.ts +9 -21
  187. package/dist/lib/cloud/rush.js +33 -120
  188. package/dist/lib/cloud/types.d.ts +2 -2
  189. package/dist/lib/commands.js +3 -13
  190. package/dist/lib/computer/actions.d.ts +36 -0
  191. package/dist/lib/computer/actions.js +162 -0
  192. package/dist/lib/computer/dispatch.d.ts +2 -2
  193. package/dist/lib/computer/dispatch.js +2 -2
  194. package/dist/lib/computer/sessions-list.d.ts +3 -3
  195. package/dist/lib/computer/sessions-list.js +2 -2
  196. package/dist/lib/config-keys.d.ts +2 -1
  197. package/dist/lib/config-keys.js +8 -4
  198. package/dist/lib/config-machine-keys.d.ts +4 -2
  199. package/dist/lib/config-machine-keys.js +5 -2
  200. package/dist/lib/crabbox/lease.js +9 -1
  201. package/dist/lib/crabbox/runtimes.d.ts +32 -7
  202. package/dist/lib/crabbox/runtimes.js +72 -30
  203. package/dist/lib/{daemon.d.ts → daemon/daemon.d.ts} +59 -1
  204. package/dist/lib/{daemon.js → daemon/daemon.js} +237 -49
  205. package/dist/lib/daemon-services.d.ts +1 -1
  206. package/dist/lib/daemon-services.js +5 -0
  207. package/dist/lib/daemon-ticks.d.ts +25 -0
  208. package/dist/lib/daemon-ticks.js +31 -1
  209. package/dist/lib/daemon-webhooks.d.ts +104 -0
  210. package/dist/lib/daemon-webhooks.js +215 -0
  211. package/dist/lib/device-config.d.ts +85 -75
  212. package/dist/lib/device-config.js +280 -142
  213. package/dist/lib/devices/config-migration.d.ts +29 -34
  214. package/dist/lib/devices/config-migration.js +209 -130
  215. package/dist/lib/devices/connect.d.ts +2 -2
  216. package/dist/lib/devices/connect.js +2 -2
  217. package/dist/lib/devices/discovery-policy.d.ts +30 -0
  218. package/dist/lib/devices/discovery-policy.js +101 -0
  219. package/dist/lib/devices/fleet-inventory.js +8 -3
  220. package/dist/lib/devices/harness-inventory.d.ts +1 -1
  221. package/dist/lib/devices/harness-inventory.js +12 -3
  222. package/dist/lib/devices/known-hosts.js +1 -1
  223. package/dist/lib/devices/pool.d.ts +10 -5
  224. package/dist/lib/devices/pool.js +5 -7
  225. package/dist/lib/devices/registry.d.ts +1 -1
  226. package/dist/lib/devices/registry.js +1 -1
  227. package/dist/lib/devices/resolve-profile.d.ts +2 -2
  228. package/dist/lib/devices/resolve-profile.js +2 -2
  229. package/dist/lib/devices/resolve-target.d.ts +1 -1
  230. package/dist/lib/devices/resolve-target.js +4 -4
  231. package/dist/lib/devices/self-host.d.ts +1 -1
  232. package/dist/lib/devices/self-host.js +3 -3
  233. package/dist/lib/devices/ssh-config.d.ts +1 -1
  234. package/dist/lib/devices/stats-cache.js +1 -1
  235. package/dist/lib/devices/sync.d.ts +3 -1
  236. package/dist/lib/devices/sync.js +3 -3
  237. package/dist/lib/doctor-diff.js +4 -4
  238. package/dist/lib/drift-sync.js +2 -2
  239. package/dist/lib/drift.js +2 -2
  240. package/dist/lib/event-families.d.ts +1 -1
  241. package/dist/lib/event-stream.d.ts +1 -1
  242. package/dist/lib/event-stream.js +2 -2
  243. package/dist/lib/events-ingest.js +2 -2
  244. package/dist/lib/exec.d.ts +4 -4
  245. package/dist/lib/exec.js +11 -11
  246. package/dist/lib/factory/snapshot.d.ts +1 -1
  247. package/dist/lib/factory/snapshot.js +1 -1
  248. package/dist/lib/{activity.d.ts → feed/activity.d.ts} +1 -1
  249. package/dist/lib/{activity.js → feed/activity.js} +7 -7
  250. package/dist/lib/{events.d.ts → feed/events.d.ts} +2 -2
  251. package/dist/lib/{events.js → feed/events.js} +5 -5
  252. package/dist/lib/{feed.js → feed/feed.js} +4 -4
  253. package/dist/lib/feed-outcome.d.ts +1 -1
  254. package/dist/lib/feed-policy.d.ts +1 -1
  255. package/dist/lib/feed-policy.js +1 -1
  256. package/dist/lib/feed-post.d.ts +1 -1
  257. package/dist/lib/feed-post.js +1 -1
  258. package/dist/lib/feed-ranking.d.ts +1 -1
  259. package/dist/lib/fleet/apply.d.ts +0 -6
  260. package/dist/lib/fleet/apply.js +18 -45
  261. package/dist/lib/fleet/auth-sync.d.ts +16 -35
  262. package/dist/lib/fleet/auth-sync.js +16 -75
  263. package/dist/lib/fleet/capture.js +8 -6
  264. package/dist/lib/fleet/manifest.js +23 -11
  265. package/dist/lib/fleet/types.d.ts +19 -7
  266. package/dist/lib/fleet-cache.d.ts +1 -1
  267. package/dist/lib/fleet-cache.js +1 -1
  268. package/dist/lib/format.d.ts +19 -0
  269. package/dist/lib/format.js +44 -1
  270. package/dist/lib/friction-heuristics.d.ts +1 -1
  271. package/dist/lib/git.d.ts +24 -1
  272. package/dist/lib/git.js +82 -38
  273. package/dist/lib/heal.js +3 -3
  274. package/dist/lib/hooks.d.ts +18 -0
  275. package/dist/lib/hooks.js +113 -1
  276. package/dist/lib/hosts/credentials.d.ts +30 -10
  277. package/dist/lib/hosts/credentials.js +38 -26
  278. package/dist/lib/hosts/dispatch.d.ts +3 -3
  279. package/dist/lib/hosts/dispatch.js +3 -3
  280. package/dist/lib/hosts/option.d.ts +3 -3
  281. package/dist/lib/hosts/option.js +7 -8
  282. package/dist/lib/hosts/passthrough.d.ts +17 -17
  283. package/dist/lib/hosts/passthrough.js +67 -50
  284. package/dist/lib/hosts/providers/devices.d.ts +1 -1
  285. package/dist/lib/hosts/providers/devices.js +1 -1
  286. package/dist/lib/hosts/reconcile.d.ts +1 -1
  287. package/dist/lib/hosts/reconcile.js +1 -1
  288. package/dist/lib/hosts/reconnect.d.ts +1 -1
  289. package/dist/lib/hosts/reconnect.js +2 -2
  290. package/dist/lib/hosts/registry.d.ts +5 -5
  291. package/dist/lib/hosts/registry.js +5 -5
  292. package/dist/lib/hosts/remote-cmd.d.ts +10 -10
  293. package/dist/lib/hosts/remote-cmd.js +25 -18
  294. package/dist/lib/hosts/remote-os.d.ts +4 -4
  295. package/dist/lib/hosts/remote-os.js +4 -4
  296. package/dist/lib/hosts/remote-session-id.d.ts +2 -2
  297. package/dist/lib/hosts/remote-session-id.js +2 -2
  298. package/dist/lib/hosts/routing-flag.d.ts +3 -3
  299. package/dist/lib/hosts/routing-flag.js +4 -5
  300. package/dist/lib/hosts/run-target.d.ts +4 -4
  301. package/dist/lib/hosts/run-target.js +4 -4
  302. package/dist/lib/hosts/session-index.d.ts +2 -2
  303. package/dist/lib/hosts/session-index.js +1 -1
  304. package/dist/lib/hosts/session-marker.d.ts +1 -1
  305. package/dist/lib/hosts/session-marker.js +1 -1
  306. package/dist/lib/hosts/types.d.ts +2 -2
  307. package/dist/lib/hosts/types.js +2 -2
  308. package/dist/lib/import.js +1 -1
  309. package/dist/lib/{migrate.d.ts → installations/migrate.d.ts} +13 -1
  310. package/dist/lib/{migrate.js → installations/migrate.js} +160 -40
  311. package/dist/lib/installations/resolve.js +1 -1
  312. package/dist/lib/installations/strategies.js +1 -1
  313. package/dist/lib/installations/update.js +2 -2
  314. package/dist/lib/{versions.d.ts → installations/versions.d.ts} +12 -3
  315. package/dist/lib/{versions.js → installations/versions.js} +51 -31
  316. package/dist/lib/isolation-boundary-report.js +1 -1
  317. package/dist/lib/linear-projects.d.ts +28 -0
  318. package/dist/lib/linear-projects.js +30 -0
  319. package/dist/lib/loop.js +1 -1
  320. package/dist/lib/mailbox-gc.js +1 -1
  321. package/dist/lib/mailbox.js +1 -1
  322. package/dist/lib/mcp-registry.d.ts +62 -0
  323. package/dist/lib/mcp-registry.js +177 -0
  324. package/dist/lib/mcp.d.ts +5 -0
  325. package/dist/lib/mcp.js +124 -307
  326. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  327. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  328. package/dist/lib/menubar/install-menubar.d.ts +7 -0
  329. package/dist/lib/menubar/install-menubar.js +24 -6
  330. package/dist/lib/menubar/snapshot.d.ts +7 -0
  331. package/dist/lib/menubar/snapshot.js +8 -6
  332. package/dist/lib/models.js +1 -1
  333. package/dist/lib/monitors/config.d.ts +12 -0
  334. package/dist/lib/monitors/config.js +3 -0
  335. package/dist/lib/monitors/dispatch.js +26 -5
  336. package/dist/lib/monitors/engine.js +10 -0
  337. package/dist/lib/monitors/sources/webhook.d.ts +1 -1
  338. package/dist/lib/monitors/state.d.ts +42 -0
  339. package/dist/lib/monitors/state.js +30 -0
  340. package/dist/lib/notify.d.ts +1 -1
  341. package/dist/lib/observe-aliases.d.ts +3 -3
  342. package/dist/lib/observe-aliases.js +3 -21
  343. package/dist/lib/output/git-output.js +2 -2
  344. package/dist/lib/overdue.d.ts +1 -1
  345. package/dist/lib/overdue.js +1 -1
  346. package/dist/lib/permissions-registry.d.ts +65 -0
  347. package/dist/lib/permissions-registry.js +599 -0
  348. package/dist/lib/permissions.d.ts +24 -13
  349. package/dist/lib/permissions.js +52 -271
  350. package/dist/lib/picker.d.ts +16 -0
  351. package/dist/lib/picker.js +33 -3
  352. package/dist/lib/placement.d.ts +1 -1
  353. package/dist/lib/placement.js +4 -4
  354. package/dist/lib/platform/paths.d.ts +8 -0
  355. package/dist/lib/platform/paths.js +11 -0
  356. package/dist/lib/platform/posixpath.js +3 -3
  357. package/dist/lib/{plugin-marketplace.d.ts → plugins/plugin-marketplace.d.ts} +1 -1
  358. package/dist/lib/{plugin-marketplace.js → plugins/plugin-marketplace.js} +2 -2
  359. package/dist/lib/{plugins.d.ts → plugins/plugins.d.ts} +1 -1
  360. package/dist/lib/{plugins.js → plugins/plugins.js} +7 -7
  361. package/dist/lib/{skills.d.ts → plugins/skills.d.ts} +1 -1
  362. package/dist/lib/{skills.js → plugins/skills.js} +7 -7
  363. package/dist/lib/pricing/cost.d.ts +1 -1
  364. package/dist/lib/pricing/cost.js +1 -1
  365. package/dist/lib/profiles-presets.d.ts +1 -1
  366. package/dist/lib/profiles-presets.js +1 -1
  367. package/dist/lib/profiles.js +2 -2
  368. package/dist/lib/project-import.js +4 -1
  369. package/dist/lib/project-key.js +7 -0
  370. package/dist/lib/project-launch.d.ts +1 -1
  371. package/dist/lib/project-launch.js +3 -3
  372. package/dist/lib/project-pull.d.ts +128 -0
  373. package/dist/lib/project-pull.js +384 -0
  374. package/dist/lib/project-root.d.ts +2 -2
  375. package/dist/lib/project-root.js +2 -2
  376. package/dist/lib/project-status.js +1 -1
  377. package/dist/lib/projects.d.ts +23 -0
  378. package/dist/lib/projects.js +29 -6
  379. package/dist/lib/refresh.d.ts +12 -1
  380. package/dist/lib/refresh.js +16 -9
  381. package/dist/lib/registry.d.ts +9 -2
  382. package/dist/lib/registry.js +11 -4
  383. package/dist/lib/resources.d.ts +2 -2
  384. package/dist/lib/resources.js +2 -2
  385. package/dist/lib/routers.d.ts +81 -0
  386. package/dist/lib/routers.js +153 -0
  387. package/dist/lib/routine-context.d.ts +1 -0
  388. package/dist/lib/routine-context.js +7 -2
  389. package/dist/lib/routine-notify-owner.d.ts +1 -1
  390. package/dist/lib/routine-notify.d.ts +1 -1
  391. package/dist/lib/routine-notify.js +1 -1
  392. package/dist/lib/routine-process-cleanup.d.ts +1 -1
  393. package/dist/lib/routine-readiness.d.ts +1 -1
  394. package/dist/lib/routine-readiness.js +11 -4
  395. package/dist/lib/routines-placement.d.ts +12 -2
  396. package/dist/lib/routines-placement.js +20 -3
  397. package/dist/lib/routines-project.d.ts +1 -1
  398. package/dist/lib/routines-project.js +1 -1
  399. package/dist/lib/rules/compile.d.ts +1 -0
  400. package/dist/lib/rules/compile.js +10 -2
  401. package/dist/lib/rules/rules.js +1 -1
  402. package/dist/lib/run-notify.js +1 -1
  403. package/dist/lib/runner.d.ts +80 -2
  404. package/dist/lib/runner.js +261 -67
  405. package/dist/lib/sandbox.d.ts +1 -1
  406. package/dist/lib/scheduler.d.ts +1 -1
  407. package/dist/lib/scheduler.js +1 -1
  408. package/dist/lib/{routines.d.ts → scheduling/routines.d.ts} +54 -9
  409. package/dist/lib/{routines.js → scheduling/routines.js} +173 -14
  410. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  411. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  412. package/dist/lib/secrets/agent.js +2 -2
  413. package/dist/lib/secrets/audit.js +1 -1
  414. package/dist/lib/secrets/bundles.d.ts +4 -4
  415. package/dist/lib/secrets/bundles.js +8 -8
  416. package/dist/lib/secrets/headless.d.ts +16 -0
  417. package/dist/lib/secrets/headless.js +21 -0
  418. package/dist/lib/secrets/index.js +1 -1
  419. package/dist/lib/secrets/list-filter.d.ts +1 -1
  420. package/dist/lib/secrets/list-filter.js +2 -2
  421. package/dist/lib/secrets/push.d.ts +1 -1
  422. package/dist/lib/secrets/push.js +10 -12
  423. package/dist/lib/secrets/remote.d.ts +21 -17
  424. package/dist/lib/secrets/remote.js +39 -23
  425. package/dist/lib/secrets/vault.js +2 -2
  426. package/dist/lib/self-heal/checks/shadowing.js +1 -1
  427. package/dist/lib/self-heal/checks/shims.js +1 -1
  428. package/dist/lib/self-update.d.ts +39 -4
  429. package/dist/lib/self-update.js +78 -25
  430. package/dist/lib/serve/control.d.ts +1 -1
  431. package/dist/lib/serve/control.js +4 -4
  432. package/dist/lib/serve/data.d.ts +1 -1
  433. package/dist/lib/serve/data.js +1 -1
  434. package/dist/lib/serve/stream.js +1 -1
  435. package/dist/lib/service-manifest.d.ts +29 -0
  436. package/dist/lib/service-manifest.js +80 -0
  437. package/dist/lib/session/active.d.ts +59 -7
  438. package/dist/lib/session/active.js +158 -17
  439. package/dist/lib/session/bash-command.js +1 -1
  440. package/dist/lib/session/claude-accounts.d.ts +1 -1
  441. package/dist/lib/session/claude-accounts.js +1 -1
  442. package/dist/lib/session/db.d.ts +10 -2
  443. package/dist/lib/session/db.js +25 -6
  444. package/dist/lib/session/discover.d.ts +77 -0
  445. package/dist/lib/session/discover.js +130 -25
  446. package/dist/lib/session/fork.js +1 -1
  447. package/dist/lib/session/inject.d.ts +1 -1
  448. package/dist/lib/session/insights.d.ts +1 -1
  449. package/dist/lib/session/insights.js +1 -1
  450. package/dist/lib/session/live-metadata.d.ts +15 -0
  451. package/dist/lib/session/live-metadata.js +76 -0
  452. package/dist/lib/session/migrate-targets.d.ts +1 -1
  453. package/dist/lib/session/recovery.d.ts +1 -1
  454. package/dist/lib/session/recovery.js +2 -2
  455. package/dist/lib/session/remote-active.d.ts +10 -1
  456. package/dist/lib/session/remote-active.js +8 -3
  457. package/dist/lib/session/remote-bundle.d.ts +1 -1
  458. package/dist/lib/session/remote-bundle.js +2 -2
  459. package/dist/lib/session/remote-list.d.ts +15 -4
  460. package/dist/lib/session/remote-list.js +40 -3
  461. package/dist/lib/session/remote.d.ts +5 -5
  462. package/dist/lib/session/remote.js +13 -17
  463. package/dist/lib/session/resume-command.d.ts +3 -2
  464. package/dist/lib/session/resume-command.js +4 -3
  465. package/dist/lib/session/resume-owner.d.ts +3 -3
  466. package/dist/lib/session/resume-owner.js +3 -3
  467. package/dist/lib/session/session-cache.d.ts +12 -0
  468. package/dist/lib/session/session-cache.js +2 -0
  469. package/dist/lib/session/share-html.d.ts +55 -0
  470. package/dist/lib/session/share-html.js +319 -0
  471. package/dist/lib/session/shell-programs.js +1 -1
  472. package/dist/lib/session/state.js +5 -5
  473. package/dist/lib/session/team-filter.d.ts +1 -1
  474. package/dist/lib/session/team-filter.js +1 -1
  475. package/dist/lib/session/types.d.ts +3 -3
  476. package/dist/lib/session/width.d.ts +2 -2
  477. package/dist/lib/session/width.js +2 -2
  478. package/dist/lib/settings-manifest.d.ts +2 -0
  479. package/dist/lib/settings-manifest.js +81 -3
  480. package/dist/lib/share/delete.d.ts +21 -0
  481. package/dist/lib/share/delete.js +42 -0
  482. package/dist/lib/share/publish.d.ts +120 -0
  483. package/dist/lib/share/publish.js +243 -18
  484. package/dist/lib/share/worker-template.js +172 -9
  485. package/dist/lib/shims.js +35 -7
  486. package/dist/lib/smart-launch.d.ts +4 -4
  487. package/dist/lib/smart-launch.js +6 -4
  488. package/dist/lib/snapshot.d.ts +4 -4
  489. package/dist/lib/snapshot.js +2 -2
  490. package/dist/lib/ssh-exec.d.ts +1 -1
  491. package/dist/lib/ssh-exec.js +2 -2
  492. package/dist/lib/ssh-tunnel.d.ts +10 -10
  493. package/dist/lib/ssh-tunnel.js +12 -12
  494. package/dist/lib/staleness/checkers/hooks.d.ts +1 -1
  495. package/dist/lib/staleness/checkers/hooks.js +1 -1
  496. package/dist/lib/staleness/detectors/permissions.js +0 -23
  497. package/dist/lib/staleness/detectors/plugins.js +1 -1
  498. package/dist/lib/staleness/fingerprint.js +1 -1
  499. package/dist/lib/staleness/layers.d.ts +1 -1
  500. package/dist/lib/staleness/layers.js +1 -1
  501. package/dist/lib/staleness/writers/mcp.js +3 -1
  502. package/dist/lib/staleness/writers/plugins.js +1 -1
  503. package/dist/lib/staleness/writers/types.d.ts +8 -0
  504. package/dist/lib/startup/command-registry.d.ts +6 -147
  505. package/dist/lib/startup/command-registry.js +40 -303
  506. package/dist/lib/startup/dev-build.d.ts +0 -21
  507. package/dist/lib/startup/dev-build.js +29 -8
  508. package/dist/lib/state.d.ts +19 -1
  509. package/dist/lib/state.js +120 -51
  510. package/dist/lib/subagents.js +1 -1
  511. package/dist/lib/sync-status.js +1 -1
  512. package/dist/lib/sync-umbrella.d.ts +6 -1
  513. package/dist/lib/sync-umbrella.js +9 -4
  514. package/dist/lib/teams/agents.js +2 -2
  515. package/dist/lib/teams/registry.js +1 -1
  516. package/dist/lib/terminal/backends/vscodium-agent.js +1 -1
  517. package/dist/lib/terminal/engine.js +1 -1
  518. package/dist/lib/terminal/index.d.ts +4 -0
  519. package/dist/lib/terminal/index.js +3 -0
  520. package/dist/lib/terminal/inject.d.ts +2 -2
  521. package/dist/lib/terminal/inject.js +2 -2
  522. package/dist/lib/terminal/transport.js +1 -1
  523. package/dist/lib/tmux/index.d.ts +1 -1
  524. package/dist/lib/tmux/index.js +1 -1
  525. package/dist/lib/tmux/session.d.ts +21 -5
  526. package/dist/lib/tmux/session.js +76 -22
  527. package/dist/lib/triggers/handlers.d.ts +38 -3
  528. package/dist/lib/triggers/handlers.js +58 -7
  529. package/dist/lib/triggers/webhook.d.ts +113 -5
  530. package/dist/lib/triggers/webhook.js +223 -44
  531. package/dist/lib/types.d.ts +19 -7
  532. package/dist/lib/usage-fleet.d.ts +1 -1
  533. package/dist/lib/usage-fleet.js +1 -1
  534. package/dist/lib/usage-refresh.d.ts +1 -1
  535. package/dist/lib/usage-refresh.js +3 -3
  536. package/dist/lib/version-duplicates.js +2 -2
  537. package/dist/lib/view-types.d.ts +56 -0
  538. package/dist/lib/view-types.js +1 -0
  539. package/dist/lib/watchdog/rotate.d.ts +2 -2
  540. package/dist/lib/watchdog/rotate.js +3 -3
  541. package/dist/lib/watchdog/runner.d.ts +2 -3
  542. package/dist/lib/watchdog/runner.js +3 -4
  543. package/dist/lib/workflows.js +1 -1
  544. package/dist/lib/wrap.d.ts +33 -0
  545. package/dist/lib/wrap.js +70 -0
  546. package/package.json +2 -1
  547. package/scripts/postinstall.js +2 -2
  548. package/dist/commands/bench.d.ts +0 -2
  549. package/dist/commands/bench.js +0 -101
  550. package/dist/commands/cp.d.ts +0 -84
  551. package/dist/commands/cp.js +0 -231
  552. package/dist/commands/login.d.ts +0 -2
  553. package/dist/lib/resources/commands.d.ts +0 -46
  554. package/dist/lib/resources/commands.js +0 -211
  555. package/dist/lib/resources/hooks.d.ts +0 -16
  556. package/dist/lib/resources/hooks.js +0 -153
  557. package/dist/lib/resources/mcp.d.ts +0 -34
  558. package/dist/lib/resources/mcp.js +0 -250
  559. package/dist/lib/resources/memory.d.ts +0 -15
  560. package/dist/lib/resources/memory.js +0 -46
  561. package/dist/lib/resources/permissions.d.ts +0 -13
  562. package/dist/lib/resources/permissions.js +0 -202
  563. package/dist/lib/resources/rules.d.ts +0 -46
  564. package/dist/lib/resources/rules.js +0 -179
  565. package/dist/lib/resources/skills.d.ts +0 -37
  566. package/dist/lib/resources/skills.js +0 -247
  567. package/dist/lib/resources/subagents.d.ts +0 -46
  568. package/dist/lib/resources/subagents.js +0 -202
  569. /package/dist/lib/{feed.d.ts → feed/feed.d.ts} +0 -0
@@ -16,7 +16,7 @@
16
16
  import { AgentManager } from '../teams/agents.js';
17
17
  import { handleTasks, handleStatus, toTaskStatusSummary } from '../teams/api.js';
18
18
  import { gitDiff } from '../teams/worktree.js';
19
- import { listJobs } from '../routines.js';
19
+ import { listJobs } from '../scheduling/routines.js';
20
20
  import { listTasks as listCloudTasks } from '../cloud/store.js';
21
21
  /**
22
22
  * Build the per-worktree diffs for a set of teammates. Only teammates with a
@@ -9,7 +9,7 @@
9
9
  * phone that drops mid-run reconnects with `?offset=<bytes>` (or the standard
10
10
  * `Last-Event-ID` header) and never loses or double-counts an event.
11
11
  *
12
- * Scope: this streams runs whose executor is the anchor itself (no `--host`).
12
+ * Scope: this streams runs whose executor is the anchor itself (no `--device`).
13
13
  * Streaming a run offloaded to another box reuses `pullRemoteLogDelta` and is a
14
14
  * follow-up; see the changelog fragment.
15
15
  */
@@ -0,0 +1,29 @@
1
+ /**
2
+ * A short, stable hash of this process's HOME when — and only when — HOME has
3
+ * been redirected away from the account's real home.
4
+ *
5
+ * `os.userInfo().homedir` reads the OS/passwd record directly and ignores
6
+ * `$HOME` (unlike `os.homedir()`, which honors it), so comparing the two
7
+ * detects exactly that redirection: true for every hermetic test process, false
8
+ * for every real interactive or production invocation. A real user's services
9
+ * therefore keep registering under their unchanged production identifiers.
10
+ */
11
+ export declare function isolatedHomeSuffix(): string | null;
12
+ /**
13
+ * Namespace a service identifier under a redirected HOME. Returns `base`
14
+ * unchanged for a real production invocation.
15
+ */
16
+ export declare function namespacedServiceLabel(base: string): string;
17
+ /**
18
+ * The home-resolution environment every generated service manifest must carry,
19
+ * so the service-manager-started child resolves the SAME home the caller did.
20
+ *
21
+ * `AGENTS_REAL_HOME` is the canonical seam that distinguishes an agent's
22
+ * isolated version home from the active installation home; pinning it alongside
23
+ * HOME keeps a child that a login shell or service manager re-homes pointed at
24
+ * the installation the caller meant.
25
+ */
26
+ export declare function serviceManifestHomeEnv(): {
27
+ HOME: string;
28
+ AGENTS_REAL_HOME: string;
29
+ };
@@ -0,0 +1,80 @@
1
+ /**
2
+ * One rule for every service manifest this CLI writes — the launchd plists and
3
+ * the systemd unit that a service manager, not this process, will later start.
4
+ *
5
+ * RUSH-2639. A service manager does NOT inherit the environment of whoever
6
+ * called `launchctl bootstrap` / `systemctl --user start`. The started child
7
+ * sees the login session's own environment plus whatever the manifest declares,
8
+ * so a manifest that omits HOME hands its child the ACCOUNT home no matter what
9
+ * HOME the process that generated and loaded it was running under. In
10
+ * production that is a no-op — the login session's HOME already is the account
11
+ * home — but under the hermetic test harness (`tests/setup.ts` redirects HOME to
12
+ * a fork-private sandbox) it means a service-manager-started process silently
13
+ * escapes the sandbox and bootstraps the developer's or the CI runner's REAL
14
+ * `~/.agents` (`ensureAgentsDir`, `state.ts`, creates `.system`, `.history`,
15
+ * `.cache`, `routines`).
16
+ *
17
+ * The same asymmetry applies to the service IDENTIFIER. `launchctl` and
18
+ * `systemctl` route `bootout`/`bootstrap`/`unload`/`load`/`list` by identifier
19
+ * alone, never by the manifest file's path, so a sandboxed instance's own
20
+ * teardown of its own never-loaded manifest tears down whatever job the OS
21
+ * already has registered under that same label — on a developer's machine, the
22
+ * real always-on service; in CI, another concurrent test fork's.
23
+ *
24
+ * Both were fixed once for the daemon and left unfixed for the menu-bar helper
25
+ * (`lib/menubar/install-menubar.ts`) and the computer helper
26
+ * (`commands/computer.ts`), which is why the leak survived the daemon fix. This
27
+ * module is the single place both rules live, so a new manifest has one obvious
28
+ * thing to call.
29
+ *
30
+ * It is not yet the only consumer of the identifier rule: `lib/secrets/agent.ts`
31
+ * keeps a literal `SERVICE_LABEL` for its `bootout`. That path is retire-only —
32
+ * it detects and removes a plist an older version installed and generates none
33
+ * of its own — so it has no HOME to bake and was deliberately left alone.
34
+ */
35
+ import * as crypto from 'crypto';
36
+ import * as os from 'os';
37
+ import * as path from 'path';
38
+ /**
39
+ * A short, stable hash of this process's HOME when — and only when — HOME has
40
+ * been redirected away from the account's real home.
41
+ *
42
+ * `os.userInfo().homedir` reads the OS/passwd record directly and ignores
43
+ * `$HOME` (unlike `os.homedir()`, which honors it), so comparing the two
44
+ * detects exactly that redirection: true for every hermetic test process, false
45
+ * for every real interactive or production invocation. A real user's services
46
+ * therefore keep registering under their unchanged production identifiers.
47
+ */
48
+ export function isolatedHomeSuffix() {
49
+ try {
50
+ const effective = path.resolve(process.env.HOME || os.homedir());
51
+ const real = path.resolve(os.userInfo().homedir);
52
+ if (effective === real)
53
+ return null;
54
+ return crypto.createHash('sha256').update(effective).digest('hex').slice(0, 12);
55
+ }
56
+ catch {
57
+ return null;
58
+ }
59
+ }
60
+ /**
61
+ * Namespace a service identifier under a redirected HOME. Returns `base`
62
+ * unchanged for a real production invocation.
63
+ */
64
+ export function namespacedServiceLabel(base) {
65
+ const suffix = isolatedHomeSuffix();
66
+ return suffix ? `${base}.sandbox-${suffix}` : base;
67
+ }
68
+ /**
69
+ * The home-resolution environment every generated service manifest must carry,
70
+ * so the service-manager-started child resolves the SAME home the caller did.
71
+ *
72
+ * `AGENTS_REAL_HOME` is the canonical seam that distinguishes an agent's
73
+ * isolated version home from the active installation home; pinning it alongside
74
+ * HOME keeps a child that a login shell or service manager re-homes pointed at
75
+ * the installation the caller meant.
76
+ */
77
+ export function serviceManifestHomeEnv() {
78
+ const home = process.env.HOME || os.homedir();
79
+ return { HOME: home, AGENTS_REAL_HOME: process.env.AGENTS_REAL_HOME || home };
80
+ }
@@ -2,7 +2,7 @@ import type { CloudTaskStatus } from '../cloud/types.js';
2
2
  import { type PidSessionEntry } from './pid-registry.js';
3
3
  import { type HookSessionIndex } from './hook-sessions.js';
4
4
  import { type SessionState, type SessionActivity, type AwaitingReason, type StructuredQuestion, type TodoProgress, type DetectedPr, type DetectedWorktree, type DetectedTicket } from './state.js';
5
- import { type SessionAgentId, type SessionAttachment } from './types.js';
5
+ import { type SessionAgentId, type SessionAttachment, type SessionMeta } from './types.js';
6
6
  import { type SessionProvenance } from './provenance.js';
7
7
  import { type DeviceRegistry } from '../devices/registry.js';
8
8
  import { type Presence } from './detached.js';
@@ -60,6 +60,19 @@ export declare function attributedSetLostPids(prev: Set<number>, next: Set<numbe
60
60
  */
61
61
  export declare function filterCachedUnattributed(sessions: ActiveSession[], attributed: Set<number>, alive: (pid: number, startedAtMs?: number) => boolean): ActiveSession[];
62
62
  export type ActiveContext = 'terminal' | 'teams' | 'cloud' | 'headless';
63
+ /** The SessionMeta fields the live-row backfill reads — the enrichment a running process cannot report. */
64
+ export type BackfillMeta = Pick<SessionMeta, 'version' | 'timestamp' | 'label' | 'ticketId' | 'prUrl' | 'prNumber' | 'origin' | 'routineName'>;
65
+ export declare function backfillActiveRowsFromMeta(sessions: ActiveSession[], metaById: Map<string, BackfillMeta>): void;
66
+ export declare function backfillActiveRowsFromIndex(sessions: ActiveSession[]): void;
67
+ export declare function isRunningLiveSession(s: ActiveSession): boolean;
68
+ export declare function activeSessionProjectKey(s: Pick<ActiveSession, 'cwd' | 'context'>): string;
69
+ export declare function serializeActiveSessionsForJson(sessions: ActiveSession[]): Array<Omit<ActiveSession, 'viewingIn'> & {
70
+ ticketId: string | null;
71
+ project: string;
72
+ prLink: string | null;
73
+ viewingIn: string | null;
74
+ }>;
75
+ export declare function serializeSessionsJson(sessions: SessionMeta[]): string;
63
76
  /**
64
77
  * Every status here is COMPUTED by the framework from observable signals — PID
65
78
  * liveness and transcript last-write (mtime) — never self-reported by the agent.
@@ -307,7 +320,7 @@ export interface ActiveSession {
307
320
  * registry. This is the one identifier that survives an SSH hop AND a session
308
321
  * rotation: a Factory tab offloaded to a device has no local process to inspect,
309
322
  * and its spawn-time session id goes stale the moment the agent moves to another
310
- * session (`/clear`, exit-and-rerun), so `--active --host <device>` joined on
323
+ * session (`/clear`, exit-and-rerun), so `--active --device <device>` joined on
311
324
  * this is how that tab re-identifies its own session. Absent for any launch that
312
325
  * did not inherit a terminal id.
313
326
  */
@@ -334,6 +347,18 @@ export interface ActiveQueryOptions {
334
347
  */
335
348
  localOnly?: boolean;
336
349
  }
350
+ /**
351
+ * Thrown by {@link listTmuxAgentSessions} when the socket exists (a server has
352
+ * run) but tmux could not be asked for its truth — spawn failure, timeout, or a
353
+ * nonzero exit. Distinct from a missing socket, which means no server ever ran
354
+ * and is genuinely empty, not degraded. `getActiveSessions` still swallows this
355
+ * to `[]` so its return type stays a plain session array, but
356
+ * {@link describeActiveDiscoveryHealth} re-probes and surfaces it so the empty
357
+ * case a real fleet sweep found (RUSH-2507) reads differently from a clean one.
358
+ */
359
+ export declare class TmuxDiscoveryDegradedError extends Error {
360
+ constructor(message: string);
361
+ }
337
362
  /**
338
363
  * A live process can only borrow an indexed session file if that transcript
339
364
  * has been touched recently enough to plausibly belong to the process. This is
@@ -465,12 +490,24 @@ export declare function resolveFallbackStatus(sessionFile: string | undefined, p
465
490
  * (+ optional session uuid), so they resolve straight off disk. Every OTHER
466
491
  * tracked harness — Codex (date-partitioned), plus grok / droid / rush / gemini /
467
492
  * kimi / hermes / opencode / antigravity / cursor (per-session dirs, SQLite, single-JSON)
468
- * — is resolved through the session index by cwd: the newest indexed transcript
469
- * for that cwd, bounded by ACTIVE_SESSION_STALE_MS so a live pid never borrows a
470
- * weeks-old transcript. This is what lets a live NON-claude/codex agent get a real
471
- * status instead of falling through to `unknown` (the file feeds
493
+ * — is resolved through the session index. When the session id is KNOWN, that id
494
+ * selects the transcript. Only an id-less process falls back to the newest indexed
495
+ * transcript for that cwd, bounded by ACTIVE_SESSION_STALE_MS so a live pid never
496
+ * borrows a weeks-old transcript. This is what lets a live NON-claude/codex agent
497
+ * get a real status instead of falling through to `unknown` (the file feeds
472
498
  * {@link computeLiveSignals}). An opaque kind we don't track still yields undefined
473
499
  * here and degrades honestly to a live `running`.
500
+ *
501
+ * The id branch exists because the cwd fallback is only safe when there is nothing
502
+ * better: it answers `WHERE agent = ? AND cwd = ? ORDER BY last_activity DESC LIMIT 1`
503
+ * (`latestSessionFileForCwd`), so with two same-harness agents in ONE cwd — routine on
504
+ * this fleet — every one of them resolves to whichever transcript was touched last.
505
+ * That is the same "one stranger's transcript" hazard the id-less tmux pane already
506
+ * refuses to guess at (see `listTmuxAgentSessions`), and since RUSH-2682 it reaches
507
+ * further than a status badge: the live row now backs `sessions preview <id>`, so the
508
+ * guess renders session B's digest under session A's header and caches it against A.
509
+ * An id we cannot resolve yields undefined — the honest "not indexed here" render —
510
+ * rather than a neighbour's transcript (RUSH-2691).
474
511
  */
475
512
  export declare function findSessionFileForKind(kind: string, cwd?: string, sessionId?: string): string | undefined;
476
513
  /** Live per-session signals derived from one transcript-tail read. */
@@ -641,6 +678,21 @@ export declare function listTmuxAgentSessions(): Promise<ActiveSession[]>;
641
678
  * terminal/headless row for the same session id.
642
679
  */
643
680
  export declare function getActiveSessions(opts?: ActiveQueryOptions): Promise<ActiveSession[]>;
681
+ /** Local discovery sources probed by {@link describeActiveDiscoveryHealth}. */
682
+ export interface ActiveDiscoveryHealth {
683
+ /** Sources that failed on the probe (currently only `'tmux'`). Empty = nothing degraded locally. */
684
+ degradedSources: string[];
685
+ }
686
+ /**
687
+ * Cheap post-hoc health probe for the local discovery sources. `getActiveSessions`
688
+ * always swallows a source failure to `[]` so its return type stays a plain
689
+ * session array — this re-probes the same sources and reports which ones threw,
690
+ * so a caller that got an empty list back can tell "genuinely nothing running"
691
+ * apart from "a source errored and got silently folded into empty" (RUSH-2507).
692
+ * Intended for the empty-result branch only, not the hot path — it repeats a
693
+ * `list-panes` call `getActiveSessions` already made.
694
+ */
695
+ export declare function describeActiveDiscoveryHealth(): Promise<ActiveDiscoveryHealth>;
644
696
  /**
645
697
  * True when a live agent process on this host carries `--session-id <id>` in
646
698
  * its argv. RUSH-2384 last-resort for `agents message`: getActiveSessions can
@@ -707,7 +759,7 @@ export declare function foldTmuxClients(rows: ActiveSession[]): Promise<void>;
707
759
  * `registerInteractiveHostSession` write the index row with
708
760
  * `machine: normalizeHost(task.host)` (`lib/hosts/session-index.ts:55,134`), so
709
761
  * this folds that recorded machine back onto the live row. Every consumer then
710
- * agrees on one owner: the `--host`/`--device` scope, the browser's device
762
+ * agrees on one owner: the `--device`/`--device` scope, the browser's device
711
763
  * filter, `_remote`/preview routing (`liveSessionToMeta`), and the id resolver.
712
764
  *
713
765
  * Two rows are deliberately left alone:
@@ -29,7 +29,7 @@ import { readSessionActorRecord, writeSessionAliasRecord } from './actor-sidecar
29
29
  import { loadHookSessionIndex, resolveHookSessionRecord, readStateSessionRecord } from './hook-sessions.js';
30
30
  import { buildClaudeLabelMap, getAgentSessionDirs } from './discover.js';
31
31
  import { buildRunNameMap } from './run-names.js';
32
- import { latestSessionFileForCwd, findSessionsByShortIds, findSessionMachinesByIds } from './db.js';
32
+ import { latestSessionFileForCwd, findSessionsByShortIds, findSessionMachinesByIds, getSessionById } from './db.js';
33
33
  import { extractSessionTopic } from './prompt.js';
34
34
  import { readSessionTailWithRaw } from './tail.js';
35
35
  import { parseSession } from './parse.js';
@@ -43,6 +43,8 @@ import { machineId, normalizeHost } from '../machine-id.js';
43
43
  import { presenceFromStore } from './detached.js';
44
44
  import { classifyHostLink, HOST_HEARTBEAT_STALE_MS } from './host-link.js';
45
45
  import { mapBounded } from '../concurrency.js';
46
+ import { linearIssueUrl } from './linear.js';
47
+ import { viewingInLabel } from './viewing-in.js';
46
48
  const execFileAsync = promisify(execFile);
47
49
  /**
48
50
  * The owner (actor id) to show for a session in `--active`. Prefers the actor
@@ -140,6 +142,79 @@ export function filterCachedUnattributed(sessions, attributed, alive) {
140
142
  return alive(s.pid, s.startedAtMs);
141
143
  });
142
144
  }
145
+ export function backfillActiveRowsFromMeta(sessions, metaById) {
146
+ for (const s of sessions) {
147
+ if (!s.sessionId)
148
+ continue;
149
+ const m = metaById.get(s.sessionId);
150
+ if (!m)
151
+ continue;
152
+ if (!s.version && m.version)
153
+ s.version = m.version;
154
+ if (!s.label && m.label)
155
+ s.label = m.label;
156
+ if (!s.ticket && m.ticketId)
157
+ s.ticket = { id: m.ticketId, url: linearIssueUrl(m.ticketId) };
158
+ if (!s.pr && m.prUrl)
159
+ s.pr = { url: m.prUrl, number: m.prNumber };
160
+ if (!s.startedAtMs && m.timestamp) {
161
+ const ts = new Date(m.timestamp).getTime();
162
+ if (!Number.isNaN(ts))
163
+ s.startedAtMs = ts;
164
+ }
165
+ if (!s.origin && m.origin)
166
+ s.origin = m.origin;
167
+ if (!s.routineName && m.routineName)
168
+ s.routineName = m.routineName;
169
+ }
170
+ }
171
+ function loadBackfillMetaFor(sessions) {
172
+ const byId = new Map();
173
+ try {
174
+ for (const s of sessions) {
175
+ if (!s.sessionId || byId.has(s.sessionId))
176
+ continue;
177
+ const m = getSessionById(s.sessionId);
178
+ if (m)
179
+ byId.set(s.sessionId, m);
180
+ }
181
+ }
182
+ catch {
183
+ /* enrichment is best-effort — an unavailable DB leaves rows un-backfilled */
184
+ }
185
+ return byId;
186
+ }
187
+ export function backfillActiveRowsFromIndex(sessions) {
188
+ backfillActiveRowsFromMeta(sessions, loadBackfillMetaFor(sessions));
189
+ }
190
+ export function isRunningLiveSession(s) {
191
+ if (s.status === 'queued' || s.status === 'closed' || s.status === 'crashed')
192
+ return false;
193
+ if (s.context === 'cloud')
194
+ return Boolean(s.cloudProvider) && Boolean(s.cloudTaskId);
195
+ return Boolean(s.machine) && typeof s.pid === 'number' && s.pid > 0 && s.pidAlive === true;
196
+ }
197
+ export function activeSessionProjectKey(s) {
198
+ if (s.cwd)
199
+ return path.basename(s.cwd);
200
+ return s.context === 'cloud' ? 'cloud' : 'other';
201
+ }
202
+ export function serializeActiveSessionsForJson(sessions) {
203
+ return sessions.map((s) => ({
204
+ ...s,
205
+ ticketId: s.ticket?.id ?? null,
206
+ project: activeSessionProjectKey(s),
207
+ prLink: s.pr?.url ?? null,
208
+ viewingIn: viewingInLabel(s) ?? null,
209
+ }));
210
+ }
211
+ export function serializeSessionsJson(sessions) {
212
+ const serializable = sessions.map((s) => {
213
+ const { _matchedTerms, _bm25Score, _remote, ...rest } = s;
214
+ return rest;
215
+ });
216
+ return JSON.stringify(serializable, null, 2) + '\n';
217
+ }
143
218
  export function activeStatusFromCloudStatus(status) {
144
219
  switch (status) {
145
220
  case 'running':
@@ -162,9 +237,24 @@ const ACTIVE_MTIME_WINDOW_MS = 2 * 60_000;
162
237
  /**
163
238
  * Bound on the tmux `list-panes` call in {@link listTmuxAgentSessions}. A wedged
164
239
  * tmux server would otherwise hang the whole `--active` scan (the other sources
165
- * can't run past it); on timeout the tmux source degrades to empty.
240
+ * can't run past it); on timeout the tmux source throws {@link TmuxDiscoveryDegradedError}.
166
241
  */
167
242
  const TMUX_LIST_PANES_TIMEOUT_MS = 5_000;
243
+ /**
244
+ * Thrown by {@link listTmuxAgentSessions} when the socket exists (a server has
245
+ * run) but tmux could not be asked for its truth — spawn failure, timeout, or a
246
+ * nonzero exit. Distinct from a missing socket, which means no server ever ran
247
+ * and is genuinely empty, not degraded. `getActiveSessions` still swallows this
248
+ * to `[]` so its return type stays a plain session array, but
249
+ * {@link describeActiveDiscoveryHealth} re-probes and surfaces it so the empty
250
+ * case a real fleet sweep found (RUSH-2507) reads differently from a clean one.
251
+ */
252
+ export class TmuxDiscoveryDegradedError extends Error {
253
+ constructor(message) {
254
+ super(message);
255
+ this.name = 'TmuxDiscoveryDegradedError';
256
+ }
257
+ }
168
258
  /**
169
259
  * A live process can only borrow an indexed session file if that transcript
170
260
  * has been touched recently enough to plausibly belong to the process. This is
@@ -621,22 +711,47 @@ export function resolveFallbackStatus(sessionFile, pidAlive, nowMs = Date.now())
621
711
  * (+ optional session uuid), so they resolve straight off disk. Every OTHER
622
712
  * tracked harness — Codex (date-partitioned), plus grok / droid / rush / gemini /
623
713
  * kimi / hermes / opencode / antigravity / cursor (per-session dirs, SQLite, single-JSON)
624
- * — is resolved through the session index by cwd: the newest indexed transcript
625
- * for that cwd, bounded by ACTIVE_SESSION_STALE_MS so a live pid never borrows a
626
- * weeks-old transcript. This is what lets a live NON-claude/codex agent get a real
627
- * status instead of falling through to `unknown` (the file feeds
714
+ * — is resolved through the session index. When the session id is KNOWN, that id
715
+ * selects the transcript. Only an id-less process falls back to the newest indexed
716
+ * transcript for that cwd, bounded by ACTIVE_SESSION_STALE_MS so a live pid never
717
+ * borrows a weeks-old transcript. This is what lets a live NON-claude/codex agent
718
+ * get a real status instead of falling through to `unknown` (the file feeds
628
719
  * {@link computeLiveSignals}). An opaque kind we don't track still yields undefined
629
720
  * here and degrades honestly to a live `running`.
721
+ *
722
+ * The id branch exists because the cwd fallback is only safe when there is nothing
723
+ * better: it answers `WHERE agent = ? AND cwd = ? ORDER BY last_activity DESC LIMIT 1`
724
+ * (`latestSessionFileForCwd`), so with two same-harness agents in ONE cwd — routine on
725
+ * this fleet — every one of them resolves to whichever transcript was touched last.
726
+ * That is the same "one stranger's transcript" hazard the id-less tmux pane already
727
+ * refuses to guess at (see `listTmuxAgentSessions`), and since RUSH-2682 it reaches
728
+ * further than a status badge: the live row now backs `sessions preview <id>`, so the
729
+ * guess renders session B's digest under session A's header and caches it against A.
730
+ * An id we cannot resolve yields undefined — the honest "not indexed here" render —
731
+ * rather than a neighbour's transcript (RUSH-2691).
630
732
  */
631
733
  export function findSessionFileForKind(kind, cwd, sessionId) {
632
734
  if (!cwd)
633
735
  return undefined;
634
736
  if (kind === 'claude')
635
737
  return findClaudeSessionFile(cwd, sessionId);
636
- if (isSessionTrackedAgent(kind)) {
637
- return latestSessionFileForCwd(kind, cwd, { maxAgeMs: ACTIVE_SESSION_STALE_MS });
638
- }
639
- return undefined;
738
+ if (!isSessionTrackedAgent(kind))
739
+ return undefined;
740
+ if (sessionId)
741
+ return indexedSessionFileForId(kind, sessionId);
742
+ return latestSessionFileForCwd(kind, cwd, { maxAgeMs: ACTIVE_SESSION_STALE_MS });
743
+ }
744
+ /**
745
+ * The indexed transcript for one exact session id, or undefined when the index has
746
+ * not reached it yet. The `agent` guard rejects a row that belongs to a different
747
+ * harness than the live process claims: those cannot be the same conversation, and
748
+ * returning it would reintroduce the misattribution this function exists to avoid.
749
+ */
750
+ function indexedSessionFileForId(kind, sessionId) {
751
+ const row = getSessionById(sessionId);
752
+ if (!row || row.agent !== kind)
753
+ return undefined;
754
+ return row.filePath || undefined;
640
755
  }
641
756
  /** Recover the session UUID from a transcript filename (Claude `<uuid>.jsonl`, Codex `rollout-…-<uuid>.jsonl`). */
642
757
  const UUID_RE = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
@@ -1540,6 +1655,9 @@ export async function listTmuxAgentSessions() {
1540
1655
  const { readSessionMeta } = await import('../tmux/session.js');
1541
1656
  const { runTmux } = await import('../tmux/binary.js');
1542
1657
  const socket = getDefaultSocketPath();
1658
+ // No server has ever run on this socket — genuinely nothing to report, not
1659
+ // a degraded read. Distinct from the throws below, which mean tmux truth
1660
+ // exists but could not be read (RUSH-2507).
1543
1661
  if (!fs.existsSync(socket))
1544
1662
  return [];
1545
1663
  let res;
@@ -1549,16 +1667,19 @@ export async function listTmuxAgentSessions() {
1549
1667
  args: ['list-panes', '-a', '-F', ['#{pane_id}', '#{session_name}', '#{pane_pid}', '#{pane_dead}', '#{pane_current_path}'].join(TMUX_FIELD_SEP)],
1550
1668
  throwOnError: false,
1551
1669
  // A wedged tmux server must not hang the whole active-session scan. The
1552
- // catch below turns a timeout into an empty tmux source (the other sources
1553
- // still report) rather than a frozen `agents sessions --active`.
1670
+ // catch below turns a timeout into a DEGRADED-tmux-source signal (the
1671
+ // other sources still report) rather than a frozen `agents sessions
1672
+ // --active` — and, crucially, no longer collapses into the same silent
1673
+ // `[]` a genuinely-idle socket returns (RUSH-2507).
1554
1674
  timeoutMs: TMUX_LIST_PANES_TIMEOUT_MS,
1555
1675
  });
1556
1676
  }
1557
- catch {
1558
- return [];
1677
+ catch (err) {
1678
+ throw new TmuxDiscoveryDegradedError(`tmux list-panes on ${socket} did not answer: ${err instanceof Error ? err.message : String(err)}`);
1679
+ }
1680
+ if (res.code !== 0) {
1681
+ throw new TmuxDiscoveryDegradedError(`tmux list-panes on ${socket} exited ${res.code}: ${res.stderr.trim() || res.stdout.trim()}`);
1559
1682
  }
1560
- if (res.code !== 0)
1561
- return [];
1562
1683
  // Index live launches by the pane they target, so a pane we did NOT wrap (a
1563
1684
  // split) resolves to its own agent. Newest launch wins a pane (pid reuse), and
1564
1685
  // only live pids count — a dead agent's stale entry can't light up its old pane.
@@ -1716,6 +1837,26 @@ export async function getActiveSessions(opts = {}) {
1716
1837
  annotateOrchestratorLabels(merged);
1717
1838
  return merged;
1718
1839
  }
1840
+ /**
1841
+ * Cheap post-hoc health probe for the local discovery sources. `getActiveSessions`
1842
+ * always swallows a source failure to `[]` so its return type stays a plain
1843
+ * session array — this re-probes the same sources and reports which ones threw,
1844
+ * so a caller that got an empty list back can tell "genuinely nothing running"
1845
+ * apart from "a source errored and got silently folded into empty" (RUSH-2507).
1846
+ * Intended for the empty-result branch only, not the hot path — it repeats a
1847
+ * `list-panes` call `getActiveSessions` already made.
1848
+ */
1849
+ export async function describeActiveDiscoveryHealth() {
1850
+ const degradedSources = [];
1851
+ try {
1852
+ await listTmuxAgentSessions();
1853
+ }
1854
+ catch (err) {
1855
+ if (err instanceof TmuxDiscoveryDegradedError)
1856
+ degradedSources.push('tmux');
1857
+ }
1858
+ return { degradedSources };
1859
+ }
1719
1860
  /**
1720
1861
  * True when a live agent process on this host carries `--session-id <id>` in
1721
1862
  * its argv. RUSH-2384 last-resort for `agents message`: getActiveSessions can
@@ -1826,7 +1967,7 @@ export async function foldTmuxClients(rows) {
1826
1967
  * `registerInteractiveHostSession` write the index row with
1827
1968
  * `machine: normalizeHost(task.host)` (`lib/hosts/session-index.ts:55,134`), so
1828
1969
  * this folds that recorded machine back onto the live row. Every consumer then
1829
- * agrees on one owner: the `--host`/`--device` scope, the browser's device
1970
+ * agrees on one owner: the `--device`/`--device` scope, the browser's device
1830
1971
  * filter, `_remote`/preview routing (`liveSessionToMeta`), and the id resolver.
1831
1972
  *
1832
1973
  * Two rows are deliberately left alone:
@@ -140,7 +140,7 @@ const VALUE_FLAGS = {
140
140
  // (`agents sessions`, `linear list`) instead of one flat `other` pile (#1830).
141
141
  // `ag` is deliberately NOT here — it is the silver searcher in TOOL_REGISTRY,
142
142
  // not the agents alias, in this classifier's world.
143
- agents: new Set(['-H', '--host', '--device']),
143
+ agents: new Set(['-D', '--device']),
144
144
  linear: new Set(),
145
145
  };
146
146
  /**
@@ -55,7 +55,7 @@
55
55
  *
56
56
  * Until that lands, a non-Claude session has a NULL `account_key` and rolls up under
57
57
  * `unattributed:<agent>` — named after its harness rather than implying we tried and
58
- * failed. `--by account` on `agents cost` / `agents output` therefore reports Claude
58
+ * failed. `--by account` on `agents insights cost` / `agents insights output` therefore reports Claude
59
59
  * accounts plus one bucket per other harness.
60
60
  */
61
61
  /** The account a transcript is attributed to. */
@@ -55,7 +55,7 @@
55
55
  *
56
56
  * Until that lands, a non-Claude session has a NULL `account_key` and rolls up under
57
57
  * `unattributed:<agent>` — named after its harness rather than implying we tried and
58
- * failed. `--by account` on `agents cost` / `agents output` therefore reports Claude
58
+ * failed. `--by account` on `agents insights cost` / `agents insights output` therefore reports Claude
59
59
  * accounts plus one bucket per other harness.
60
60
  */
61
61
  import * as os from 'os';
@@ -192,6 +192,14 @@ export declare function maintainSessionSearchIndex(db?: Database.Database, optio
192
192
  * mode can return SQLITE_BUSY_SNAPSHOT which bypasses the busy handler.
193
193
  */
194
194
  export declare function tryClaimScan(pid: number): boolean;
195
+ /**
196
+ * Read-only probe: is a scan in progress right now, held by a LIVE process
197
+ * within the TTL? (RUSH-2682). Unlike {@link tryClaimScan} it never writes, so a
198
+ * caller that lost the claim can wait for the in-flight scan to finish rather
199
+ * than returning the pre-scan DB snapshot as if it were the answer. Returns
200
+ * false for a dead-PID or expired claim — that scan is not actually running.
201
+ */
202
+ export declare function scanInProgressByLivePid(): boolean;
195
203
  /**
196
204
  * Release the scan claim written by tryClaimScan. Only deletes the entry
197
205
  * if it still belongs to this process (guards against TTL takeovers).
@@ -354,7 +362,7 @@ export interface UsageRollupRow {
354
362
  costUsd: number;
355
363
  /**
356
364
  * USD cost priced as if caching were off (cache read/write at the input rate),
357
- * summed from `cost_usd_nocache`. Backs `agents output --pricing no-cache`.
365
+ * summed from `cost_usd_nocache`. Backs `agents insights output --pricing no-cache`.
358
366
  * Equals `costUsd` for rows whose sessions record no cache split (RUSH-2287).
359
367
  */
360
368
  costUsdNoCache: number;
@@ -472,7 +480,7 @@ export declare function queryAffinityRollup(options: {
472
480
  /**
473
481
  * Aggregate cost / duration / tokens across sessions, grouped by agent,
474
482
  * project, or calendar day. Honors the same filter shape as querySessions
475
- * (agent, since/until, team-origin) so `agents cost --since 7d --by day`
483
+ * (agent, since/until, team-origin) so `agents insights cost --since 7d --by day`
476
484
  * lines up with what `agents sessions` would list. Ordered by cost desc.
477
485
  */
478
486
  export declare function queryUsageRollup(options: QueryOptions & {
@@ -12,7 +12,7 @@ import Database from '../sqlite.js';
12
12
  import { parseSession, sessionFilePathContainer } from './parse.js';
13
13
  import { extractRecentDirectoriesTouched, extractTodoProgressFromEvents } from './state.js';
14
14
  import { getSessionsDir, getSessionsDbPath } from '../state.js';
15
- import { query as queryEvents, queryToolUsageForSessions } from '../events.js';
15
+ import { query as queryEvents, queryToolUsageForSessions } from '../feed/events.js';
16
16
  import { machineForSessionFile } from './origin-machine.js';
17
17
  import { loadSessionActorIndex, readSessionActorRecord } from './actor-sidecar.js';
18
18
  import { toolCallsFromEvents } from './tool-calls.js';
@@ -20,7 +20,7 @@ import { persistToolCalls, toolEvidenceSourcePath } from './tool-store.js';
20
20
  import { buildClaudeAccountIndex, resolveClaudeAccount } from './claude-accounts.js';
21
21
  import { extractSkills, extractSlashCommands } from './highlights.js';
22
22
  import { resolveResource } from '../resources.js';
23
- import { discoverPlugins } from '../plugins.js';
23
+ import { discoverPlugins } from '../plugins/plugins.js';
24
24
  import { machineId } from '../machine-id.js';
25
25
  const SESSIONS_DIR = getSessionsDir();
26
26
  const DB_PATH = getSessionsDbPath();
@@ -528,7 +528,7 @@ function migrateSchema(db, fromVersion) {
528
528
  // v11 → v12: `output_tokens` — the real generated-token count, kept separate
529
529
  // from `token_count` (which sums cache-read/-write and so is dominated by
530
530
  // cheap re-counted context). This is the honest "output" metric powering
531
- // `agents output`. Additive column; rescan to backfill from transcripts.
531
+ // `agents insights output`. Additive column; rescan to backfill from transcripts.
532
532
  const cols = db.prepare(`PRAGMA table_info(sessions)`).all();
533
533
  if (!cols.some(c => c.name === 'output_tokens'))
534
534
  db.exec(`ALTER TABLE sessions ADD COLUMN output_tokens INTEGER`);
@@ -966,12 +966,12 @@ function migrateSchema(db, fromVersion) {
966
966
  }
967
967
  if (fromVersion < 37) {
968
968
  // v36 -> v37: persist the burn SPLIT (uncached input / cache-read /
969
- // cache-write) and a second "no-cache" cost per session, so `agents output`
969
+ // cache-write) and a second "no-cache" cost per session, so `agents insights output`
970
970
  // can report the token split and a --pricing no-cache scenario (RUSH-2287).
971
971
  // These are new nullable columns — do NOT flush scan_ledger (adding a column
972
972
  // must keep warm session ledgers warm, the contract the v33->v34 note above
973
973
  // states). Pre-upgrade rows stay NULL for the split until their transcript is
974
- // re-scanned; `agents output` reports the split only where it is present, so
974
+ // re-scanned; `agents insights output` reports the split only where it is present, so
975
975
  // an absent split reads as "not available for this session", never as zero.
976
976
  const cols = new Set(db.prepare(`PRAGMA table_info(sessions)`).all().map((c) => c.name));
977
977
  if (!cols.has('input_tokens'))
@@ -1309,6 +1309,25 @@ export function tryClaimScan(pid) {
1309
1309
  });
1310
1310
  return txn();
1311
1311
  }
1312
+ /**
1313
+ * Read-only probe: is a scan in progress right now, held by a LIVE process
1314
+ * within the TTL? (RUSH-2682). Unlike {@link tryClaimScan} it never writes, so a
1315
+ * caller that lost the claim can wait for the in-flight scan to finish rather
1316
+ * than returning the pre-scan DB snapshot as if it were the answer. Returns
1317
+ * false for a dead-PID or expired claim — that scan is not actually running.
1318
+ */
1319
+ export function scanInProgressByLivePid() {
1320
+ const db = getDB();
1321
+ const existing = db
1322
+ .prepare(`SELECT value FROM meta WHERE key = 'scan_in_progress'`)
1323
+ .get();
1324
+ if (!existing)
1325
+ return false;
1326
+ const parts = existing.value.split(':');
1327
+ const pid = parseInt(parts[0], 10);
1328
+ const ts = parseInt(parts[1], 10);
1329
+ return isProcessAlive(pid) && Date.now() - ts < SCAN_CLAIM_TTL_MS;
1330
+ }
1312
1331
  /**
1313
1332
  * Release the scan claim written by tryClaimScan. Only deletes the entry
1314
1333
  * if it still belongs to this process (guards against TTL takeovers).
@@ -2807,7 +2826,7 @@ export function queryAffinityRollup(options) {
2807
2826
  /**
2808
2827
  * Aggregate cost / duration / tokens across sessions, grouped by agent,
2809
2828
  * project, or calendar day. Honors the same filter shape as querySessions
2810
- * (agent, since/until, team-origin) so `agents cost --since 7d --by day`
2829
+ * (agent, since/until, team-origin) so `agents insights cost --since 7d --by day`
2811
2830
  * lines up with what `agents sessions` would list. Ordered by cost desc.
2812
2831
  */
2813
2832
  export function queryUsageRollup(options) {