@phnx-labs/agents-cli 1.22.39 → 1.22.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (554) hide show
  1. package/CHANGELOG.md +294 -0
  2. package/README.md +111 -70
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.js +45 -26
  5. package/dist/browser.js +2 -2
  6. package/dist/cli/command-registry.d.ts +135 -0
  7. package/dist/cli/command-registry.js +260 -0
  8. package/dist/commands/accounts.d.ts +20 -0
  9. package/dist/commands/accounts.js +186 -25
  10. package/dist/commands/apply.d.ts +3 -3
  11. package/dist/commands/apply.js +20 -63
  12. package/dist/commands/browser.js +206 -94
  13. package/dist/commands/budget.d.ts +7 -6
  14. package/dist/commands/budget.js +8 -7
  15. package/dist/commands/cloud.js +17 -20
  16. package/dist/commands/commands.js +1 -1
  17. package/dist/commands/computer-actions.d.ts +1 -35
  18. package/dist/commands/computer-actions.js +13 -181
  19. package/dist/commands/computer.d.ts +28 -3
  20. package/dist/commands/computer.js +93 -65
  21. package/dist/commands/config.js +16 -3
  22. package/dist/commands/cost.d.ts +2 -1
  23. package/dist/commands/cost.js +7 -6
  24. package/dist/commands/daemon.js +151 -4
  25. package/dist/commands/detach.js +1 -1
  26. package/dist/commands/doctor.js +19 -11
  27. package/dist/commands/events.js +1 -1
  28. package/dist/commands/exec.d.ts +2 -50
  29. package/dist/commands/exec.js +160 -215
  30. package/dist/commands/factory.js +1 -1
  31. package/dist/commands/feed.d.ts +2 -2
  32. package/dist/commands/feed.js +9 -12
  33. package/dist/commands/fleet-capture.js +25 -27
  34. package/dist/commands/focus.d.ts +2 -3
  35. package/dist/commands/focus.js +34 -9
  36. package/dist/commands/go.js +15 -5
  37. package/dist/commands/harness.d.ts +3 -3
  38. package/dist/commands/harness.js +53 -5
  39. package/dist/commands/hooks.js +1 -1
  40. package/dist/commands/import.js +2 -2
  41. package/dist/commands/insights.d.ts +5 -5
  42. package/dist/commands/insights.js +15 -9
  43. package/dist/commands/inspect.d.ts +2 -3
  44. package/dist/commands/inspect.js +4 -16
  45. package/dist/commands/logs.d.ts +2 -2
  46. package/dist/commands/logs.js +9 -9
  47. package/dist/commands/mcp.js +2 -2
  48. package/dist/commands/memory.js +1 -1
  49. package/dist/commands/message.d.ts +1 -1
  50. package/dist/commands/message.js +7 -7
  51. package/dist/commands/mine.d.ts +11 -8
  52. package/dist/commands/mine.js +11 -10
  53. package/dist/commands/models.js +1 -1
  54. package/dist/commands/modes.js +1 -1
  55. package/dist/commands/monitors.js +23 -6
  56. package/dist/commands/output.d.ts +7 -6
  57. package/dist/commands/output.js +11 -10
  58. package/dist/commands/packages.js +4 -4
  59. package/dist/commands/perf.js +1 -1
  60. package/dist/commands/permissions.js +49 -32
  61. package/dist/commands/plugins.d.ts +1 -1
  62. package/dist/commands/plugins.js +3 -3
  63. package/dist/commands/profiles.d.ts +6 -9
  64. package/dist/commands/profiles.js +8 -321
  65. package/dist/commands/projects.d.ts +9 -0
  66. package/dist/commands/projects.js +140 -8
  67. package/dist/commands/prune.js +5 -13
  68. package/dist/commands/refresh-rules.js +1 -1
  69. package/dist/commands/repo.d.ts +5 -7
  70. package/dist/commands/repo.js +34 -18
  71. package/dist/commands/resource-view.js +4 -0
  72. package/dist/commands/resume.d.ts +11 -7
  73. package/dist/commands/resume.js +82 -98
  74. package/dist/commands/route.d.ts +12 -0
  75. package/dist/commands/route.js +261 -0
  76. package/dist/commands/routines.d.ts +2 -3
  77. package/dist/commands/routines.js +120 -145
  78. package/dist/commands/rules.js +1 -1
  79. package/dist/commands/run-account-picker.d.ts +1 -1
  80. package/dist/commands/run-account-picker.js +2 -2
  81. package/dist/commands/run-broadcast.d.ts +21 -0
  82. package/dist/commands/run-broadcast.js +89 -0
  83. package/dist/commands/run-cloud.js +1 -1
  84. package/dist/commands/secrets-vault.d.ts +10 -0
  85. package/dist/commands/{login.js → secrets-vault.js} +34 -14
  86. package/dist/commands/secrets.d.ts +4 -4
  87. package/dist/commands/secrets.js +72 -63
  88. package/dist/commands/sessions-backfill.js +1 -1
  89. package/dist/commands/sessions-browser.d.ts +1 -1
  90. package/dist/commands/sessions-browser.js +9 -5
  91. package/dist/commands/sessions-export.js +2 -2
  92. package/dist/commands/sessions-inject.js +4 -5
  93. package/dist/commands/sessions-migrate.js +16 -27
  94. package/dist/commands/sessions-picker.d.ts +13 -0
  95. package/dist/commands/sessions-picker.js +182 -8
  96. package/dist/commands/sessions-resume.d.ts +7 -3
  97. package/dist/commands/sessions-resume.js +81 -33
  98. package/dist/commands/sessions-stats.js +2 -2
  99. package/dist/commands/sessions.d.ts +75 -68
  100. package/dist/commands/sessions.js +142 -180
  101. package/dist/commands/setup-computer.js +1 -1
  102. package/dist/commands/setup-fleet.js +3 -0
  103. package/dist/commands/setup-mine.d.ts +7 -3
  104. package/dist/commands/setup-mine.js +13 -8
  105. package/dist/commands/setup-secrets.js +2 -2
  106. package/dist/commands/setup-watchdog.js +2 -2
  107. package/dist/commands/setup.js +7 -2
  108. package/dist/commands/share.d.ts +65 -0
  109. package/dist/commands/share.js +253 -20
  110. package/dist/commands/skills.js +3 -3
  111. package/dist/commands/snapshot.d.ts +2 -2
  112. package/dist/commands/snapshot.js +9 -9
  113. package/dist/commands/ssh.d.ts +1 -1
  114. package/dist/commands/ssh.js +186 -64
  115. package/dist/commands/subagents.js +1 -1
  116. package/dist/commands/sync.js +24 -9
  117. package/dist/commands/teams.d.ts +2 -2
  118. package/dist/commands/teams.js +9 -18
  119. package/dist/commands/tmux.js +5 -1
  120. package/dist/commands/trash.js +1 -1
  121. package/dist/commands/usage.d.ts +1 -1
  122. package/dist/commands/usage.js +2 -2
  123. package/dist/commands/utils.d.ts +4 -14
  124. package/dist/commands/utils.js +6 -27
  125. package/dist/commands/versions.js +2 -2
  126. package/dist/commands/view.d.ts +9 -77
  127. package/dist/commands/view.js +23 -8
  128. package/dist/commands/watchdog.js +1 -1
  129. package/dist/commands/webhook.js +11 -25
  130. package/dist/commands/workflows.js +1 -1
  131. package/dist/index.js +1 -1
  132. package/dist/lib/account-capabilities.d.ts +39 -0
  133. package/dist/lib/account-capabilities.js +59 -0
  134. package/dist/lib/account-catalog.js +1 -1
  135. package/dist/lib/account-registry.d.ts +66 -0
  136. package/dist/lib/account-registry.js +151 -5
  137. package/dist/lib/{rotate.d.ts → accounting/rotate.d.ts} +4 -4
  138. package/dist/lib/{rotate.js → accounting/rotate.js} +8 -8
  139. package/dist/lib/{usage.d.ts → accounting/usage.d.ts} +4 -4
  140. package/dist/lib/{usage.js → accounting/usage.js} +11 -11
  141. package/dist/lib/agent-spec/provider.js +1 -1
  142. package/dist/lib/agents.d.ts +72 -4
  143. package/dist/lib/agents.js +231 -199
  144. package/dist/lib/answer-router.d.ts +2 -2
  145. package/dist/lib/ask-classifier.d.ts +1 -1
  146. package/dist/lib/ask-classifier.js +1 -1
  147. package/dist/lib/audit/log.js +1 -1
  148. package/dist/lib/auth-health.d.ts +1 -1
  149. package/dist/lib/auth-health.js +2 -2
  150. package/dist/lib/brand.js +1 -1
  151. package/dist/lib/browser/caller-identity.d.ts +28 -0
  152. package/dist/lib/browser/caller-identity.js +156 -0
  153. package/dist/lib/browser/cdp.js +1 -1
  154. package/dist/lib/browser/drivers/ssh.d.ts +1 -1
  155. package/dist/lib/browser/drivers/ssh.js +2 -2
  156. package/dist/lib/browser/hygiene.d.ts +10 -2
  157. package/dist/lib/browser/hygiene.js +7 -4
  158. package/dist/lib/browser/ipc.d.ts +22 -2
  159. package/dist/lib/browser/ipc.js +185 -21
  160. package/dist/lib/browser/profiles.d.ts +67 -3
  161. package/dist/lib/browser/profiles.js +129 -7
  162. package/dist/lib/browser/remote-control.d.ts +2 -2
  163. package/dist/lib/browser/remote-control.js +3 -3
  164. package/dist/lib/browser/runtime-state.d.ts +79 -0
  165. package/dist/lib/browser/runtime-state.js +119 -1
  166. package/dist/lib/browser/service.d.ts +113 -1
  167. package/dist/lib/browser/service.js +454 -40
  168. package/dist/lib/browser/sessions-list.d.ts +2 -1
  169. package/dist/lib/browser/sessions-list.js +4 -13
  170. package/dist/lib/browser/types.d.ts +18 -0
  171. package/dist/lib/budget/config.js +1 -1
  172. package/dist/lib/budget/ledger.js +1 -1
  173. package/dist/lib/byok-usage.js +1 -1
  174. package/dist/lib/capabilities.js +3 -15
  175. package/dist/lib/catchup.d.ts +1 -1
  176. package/dist/lib/catchup.js +1 -1
  177. package/dist/lib/cloud/dispatch.js +1 -1
  178. package/dist/lib/cloud/host.d.ts +3 -3
  179. package/dist/lib/cloud/host.js +5 -5
  180. package/dist/lib/cloud/rush.d.ts +9 -21
  181. package/dist/lib/cloud/rush.js +33 -120
  182. package/dist/lib/cloud/types.d.ts +2 -2
  183. package/dist/lib/commands.js +3 -13
  184. package/dist/lib/computer/actions.d.ts +36 -0
  185. package/dist/lib/computer/actions.js +162 -0
  186. package/dist/lib/computer/dispatch.d.ts +2 -2
  187. package/dist/lib/computer/dispatch.js +2 -2
  188. package/dist/lib/computer/sessions-list.d.ts +3 -3
  189. package/dist/lib/computer/sessions-list.js +2 -2
  190. package/dist/lib/config-keys.d.ts +2 -1
  191. package/dist/lib/config-keys.js +8 -4
  192. package/dist/lib/config-machine-keys.d.ts +4 -2
  193. package/dist/lib/config-machine-keys.js +5 -2
  194. package/dist/lib/crabbox/lease.js +9 -1
  195. package/dist/lib/crabbox/runtimes.d.ts +32 -7
  196. package/dist/lib/crabbox/runtimes.js +72 -30
  197. package/dist/lib/{daemon.d.ts → daemon/daemon.d.ts} +59 -1
  198. package/dist/lib/{daemon.js → daemon/daemon.js} +237 -49
  199. package/dist/lib/daemon-services.d.ts +1 -1
  200. package/dist/lib/daemon-services.js +5 -0
  201. package/dist/lib/daemon-ticks.d.ts +25 -0
  202. package/dist/lib/daemon-ticks.js +31 -1
  203. package/dist/lib/daemon-webhooks.d.ts +102 -0
  204. package/dist/lib/daemon-webhooks.js +210 -0
  205. package/dist/lib/device-config.d.ts +85 -75
  206. package/dist/lib/device-config.js +279 -141
  207. package/dist/lib/devices/config-migration.d.ts +29 -34
  208. package/dist/lib/devices/config-migration.js +209 -130
  209. package/dist/lib/devices/connect.d.ts +2 -2
  210. package/dist/lib/devices/connect.js +2 -2
  211. package/dist/lib/devices/discovery-policy.d.ts +30 -0
  212. package/dist/lib/devices/discovery-policy.js +101 -0
  213. package/dist/lib/devices/fleet-inventory.js +8 -3
  214. package/dist/lib/devices/harness-inventory.d.ts +1 -1
  215. package/dist/lib/devices/harness-inventory.js +12 -3
  216. package/dist/lib/devices/known-hosts.js +1 -1
  217. package/dist/lib/devices/pool.d.ts +10 -5
  218. package/dist/lib/devices/pool.js +5 -7
  219. package/dist/lib/devices/registry.d.ts +1 -1
  220. package/dist/lib/devices/registry.js +1 -1
  221. package/dist/lib/devices/resolve-profile.d.ts +2 -2
  222. package/dist/lib/devices/resolve-profile.js +2 -2
  223. package/dist/lib/devices/resolve-target.d.ts +1 -1
  224. package/dist/lib/devices/resolve-target.js +4 -4
  225. package/dist/lib/devices/self-host.d.ts +1 -1
  226. package/dist/lib/devices/self-host.js +3 -3
  227. package/dist/lib/devices/ssh-config.d.ts +1 -1
  228. package/dist/lib/devices/stats-cache.js +1 -1
  229. package/dist/lib/devices/sync.d.ts +3 -1
  230. package/dist/lib/devices/sync.js +3 -3
  231. package/dist/lib/doctor-diff.js +4 -4
  232. package/dist/lib/drift-sync.js +2 -2
  233. package/dist/lib/drift.js +2 -2
  234. package/dist/lib/event-families.d.ts +1 -1
  235. package/dist/lib/event-stream.d.ts +1 -1
  236. package/dist/lib/event-stream.js +2 -2
  237. package/dist/lib/events-ingest.js +2 -2
  238. package/dist/lib/exec.d.ts +4 -4
  239. package/dist/lib/exec.js +11 -11
  240. package/dist/lib/factory/snapshot.d.ts +1 -1
  241. package/dist/lib/factory/snapshot.js +1 -1
  242. package/dist/lib/{activity.d.ts → feed/activity.d.ts} +1 -1
  243. package/dist/lib/{activity.js → feed/activity.js} +7 -7
  244. package/dist/lib/{events.d.ts → feed/events.d.ts} +2 -2
  245. package/dist/lib/{events.js → feed/events.js} +5 -5
  246. package/dist/lib/{feed.js → feed/feed.js} +4 -4
  247. package/dist/lib/feed-outcome.d.ts +1 -1
  248. package/dist/lib/feed-policy.d.ts +1 -1
  249. package/dist/lib/feed-policy.js +1 -1
  250. package/dist/lib/feed-post.d.ts +1 -1
  251. package/dist/lib/feed-post.js +1 -1
  252. package/dist/lib/feed-ranking.d.ts +1 -1
  253. package/dist/lib/fleet/apply.d.ts +0 -6
  254. package/dist/lib/fleet/apply.js +18 -45
  255. package/dist/lib/fleet/auth-sync.d.ts +16 -35
  256. package/dist/lib/fleet/auth-sync.js +16 -75
  257. package/dist/lib/fleet/capture.js +8 -6
  258. package/dist/lib/fleet/manifest.js +23 -11
  259. package/dist/lib/fleet/types.d.ts +19 -7
  260. package/dist/lib/fleet-cache.d.ts +1 -1
  261. package/dist/lib/fleet-cache.js +1 -1
  262. package/dist/lib/format.d.ts +19 -0
  263. package/dist/lib/format.js +44 -1
  264. package/dist/lib/friction-heuristics.d.ts +1 -1
  265. package/dist/lib/git.d.ts +24 -1
  266. package/dist/lib/git.js +82 -38
  267. package/dist/lib/heal.js +3 -3
  268. package/dist/lib/hooks.d.ts +18 -0
  269. package/dist/lib/hooks.js +113 -1
  270. package/dist/lib/hosts/credentials.d.ts +30 -10
  271. package/dist/lib/hosts/credentials.js +38 -26
  272. package/dist/lib/hosts/dispatch.d.ts +3 -3
  273. package/dist/lib/hosts/dispatch.js +3 -3
  274. package/dist/lib/hosts/option.d.ts +3 -3
  275. package/dist/lib/hosts/option.js +7 -8
  276. package/dist/lib/hosts/passthrough.d.ts +17 -17
  277. package/dist/lib/hosts/passthrough.js +67 -50
  278. package/dist/lib/hosts/providers/devices.d.ts +1 -1
  279. package/dist/lib/hosts/providers/devices.js +1 -1
  280. package/dist/lib/hosts/reconcile.d.ts +1 -1
  281. package/dist/lib/hosts/reconcile.js +1 -1
  282. package/dist/lib/hosts/reconnect.d.ts +1 -1
  283. package/dist/lib/hosts/reconnect.js +2 -2
  284. package/dist/lib/hosts/registry.d.ts +5 -5
  285. package/dist/lib/hosts/registry.js +5 -5
  286. package/dist/lib/hosts/remote-cmd.d.ts +10 -10
  287. package/dist/lib/hosts/remote-cmd.js +25 -18
  288. package/dist/lib/hosts/remote-os.d.ts +4 -4
  289. package/dist/lib/hosts/remote-os.js +4 -4
  290. package/dist/lib/hosts/remote-session-id.d.ts +2 -2
  291. package/dist/lib/hosts/remote-session-id.js +2 -2
  292. package/dist/lib/hosts/routing-flag.d.ts +3 -3
  293. package/dist/lib/hosts/routing-flag.js +4 -5
  294. package/dist/lib/hosts/run-target.d.ts +4 -4
  295. package/dist/lib/hosts/run-target.js +4 -4
  296. package/dist/lib/hosts/session-index.d.ts +2 -2
  297. package/dist/lib/hosts/session-index.js +1 -1
  298. package/dist/lib/hosts/session-marker.d.ts +1 -1
  299. package/dist/lib/hosts/session-marker.js +1 -1
  300. package/dist/lib/hosts/types.d.ts +2 -2
  301. package/dist/lib/hosts/types.js +2 -2
  302. package/dist/lib/import.js +1 -1
  303. package/dist/lib/{migrate.d.ts → installations/migrate.d.ts} +13 -1
  304. package/dist/lib/{migrate.js → installations/migrate.js} +160 -40
  305. package/dist/lib/installations/resolve.js +1 -1
  306. package/dist/lib/installations/strategies.js +1 -1
  307. package/dist/lib/installations/update.js +2 -2
  308. package/dist/lib/{versions.d.ts → installations/versions.d.ts} +12 -3
  309. package/dist/lib/{versions.js → installations/versions.js} +51 -31
  310. package/dist/lib/isolation-boundary-report.js +1 -1
  311. package/dist/lib/linear-projects.d.ts +28 -0
  312. package/dist/lib/linear-projects.js +30 -0
  313. package/dist/lib/loop.js +1 -1
  314. package/dist/lib/mailbox-gc.js +1 -1
  315. package/dist/lib/mailbox.js +1 -1
  316. package/dist/lib/mcp-registry.d.ts +62 -0
  317. package/dist/lib/mcp-registry.js +177 -0
  318. package/dist/lib/mcp.d.ts +5 -0
  319. package/dist/lib/mcp.js +124 -307
  320. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  321. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  322. package/dist/lib/menubar/install-menubar.d.ts +7 -0
  323. package/dist/lib/menubar/install-menubar.js +24 -6
  324. package/dist/lib/menubar/snapshot.d.ts +7 -0
  325. package/dist/lib/menubar/snapshot.js +8 -6
  326. package/dist/lib/models.js +1 -1
  327. package/dist/lib/monitors/config.d.ts +12 -0
  328. package/dist/lib/monitors/config.js +3 -0
  329. package/dist/lib/monitors/dispatch.js +26 -5
  330. package/dist/lib/monitors/engine.js +10 -0
  331. package/dist/lib/monitors/sources/webhook.d.ts +1 -1
  332. package/dist/lib/monitors/state.d.ts +42 -0
  333. package/dist/lib/monitors/state.js +30 -0
  334. package/dist/lib/notify.d.ts +1 -1
  335. package/dist/lib/observe-aliases.d.ts +2 -2
  336. package/dist/lib/observe-aliases.js +2 -11
  337. package/dist/lib/output/git-output.js +2 -2
  338. package/dist/lib/overdue.d.ts +1 -1
  339. package/dist/lib/overdue.js +1 -1
  340. package/dist/lib/permissions-registry.d.ts +65 -0
  341. package/dist/lib/permissions-registry.js +599 -0
  342. package/dist/lib/permissions.d.ts +24 -13
  343. package/dist/lib/permissions.js +52 -271
  344. package/dist/lib/picker.d.ts +16 -0
  345. package/dist/lib/picker.js +33 -3
  346. package/dist/lib/placement.d.ts +1 -1
  347. package/dist/lib/placement.js +4 -4
  348. package/dist/lib/platform/paths.d.ts +8 -0
  349. package/dist/lib/platform/paths.js +11 -0
  350. package/dist/lib/platform/posixpath.js +3 -3
  351. package/dist/lib/{plugin-marketplace.d.ts → plugins/plugin-marketplace.d.ts} +1 -1
  352. package/dist/lib/{plugin-marketplace.js → plugins/plugin-marketplace.js} +2 -2
  353. package/dist/lib/{plugins.d.ts → plugins/plugins.d.ts} +1 -1
  354. package/dist/lib/{plugins.js → plugins/plugins.js} +7 -7
  355. package/dist/lib/{skills.d.ts → plugins/skills.d.ts} +1 -1
  356. package/dist/lib/{skills.js → plugins/skills.js} +7 -7
  357. package/dist/lib/pricing/cost.d.ts +1 -1
  358. package/dist/lib/pricing/cost.js +1 -1
  359. package/dist/lib/profiles-presets.d.ts +1 -1
  360. package/dist/lib/profiles-presets.js +1 -1
  361. package/dist/lib/profiles.js +2 -2
  362. package/dist/lib/project-import.js +4 -1
  363. package/dist/lib/project-launch.d.ts +1 -1
  364. package/dist/lib/project-launch.js +3 -3
  365. package/dist/lib/project-pull.d.ts +128 -0
  366. package/dist/lib/project-pull.js +384 -0
  367. package/dist/lib/project-root.d.ts +2 -2
  368. package/dist/lib/project-root.js +2 -2
  369. package/dist/lib/project-status.js +1 -1
  370. package/dist/lib/projects.d.ts +23 -0
  371. package/dist/lib/projects.js +29 -6
  372. package/dist/lib/refresh.d.ts +12 -1
  373. package/dist/lib/refresh.js +16 -9
  374. package/dist/lib/registry.d.ts +9 -2
  375. package/dist/lib/registry.js +11 -4
  376. package/dist/lib/resources.d.ts +2 -2
  377. package/dist/lib/resources.js +2 -2
  378. package/dist/lib/routers.d.ts +81 -0
  379. package/dist/lib/routers.js +153 -0
  380. package/dist/lib/routine-context.d.ts +1 -0
  381. package/dist/lib/routine-context.js +7 -2
  382. package/dist/lib/routine-notify-owner.d.ts +1 -1
  383. package/dist/lib/routine-notify.d.ts +1 -1
  384. package/dist/lib/routine-notify.js +1 -1
  385. package/dist/lib/routine-process-cleanup.d.ts +1 -1
  386. package/dist/lib/routine-readiness.d.ts +1 -1
  387. package/dist/lib/routine-readiness.js +11 -4
  388. package/dist/lib/routines-placement.d.ts +12 -2
  389. package/dist/lib/routines-placement.js +20 -3
  390. package/dist/lib/routines-project.d.ts +1 -1
  391. package/dist/lib/routines-project.js +1 -1
  392. package/dist/lib/rules/compile.d.ts +1 -0
  393. package/dist/lib/rules/compile.js +10 -2
  394. package/dist/lib/rules/rules.js +1 -1
  395. package/dist/lib/run-notify.js +1 -1
  396. package/dist/lib/runner.d.ts +80 -2
  397. package/dist/lib/runner.js +241 -62
  398. package/dist/lib/sandbox.d.ts +1 -1
  399. package/dist/lib/scheduler.d.ts +1 -1
  400. package/dist/lib/scheduler.js +1 -1
  401. package/dist/lib/{routines.d.ts → scheduling/routines.d.ts} +54 -9
  402. package/dist/lib/{routines.js → scheduling/routines.js} +173 -14
  403. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  404. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  405. package/dist/lib/secrets/agent.js +2 -2
  406. package/dist/lib/secrets/audit.js +1 -1
  407. package/dist/lib/secrets/bundles.d.ts +3 -3
  408. package/dist/lib/secrets/bundles.js +7 -7
  409. package/dist/lib/secrets/index.js +1 -1
  410. package/dist/lib/secrets/list-filter.d.ts +1 -1
  411. package/dist/lib/secrets/list-filter.js +2 -2
  412. package/dist/lib/secrets/push.d.ts +1 -1
  413. package/dist/lib/secrets/push.js +10 -12
  414. package/dist/lib/secrets/remote.d.ts +12 -10
  415. package/dist/lib/secrets/remote.js +21 -14
  416. package/dist/lib/secrets/vault.js +2 -2
  417. package/dist/lib/self-heal/checks/shadowing.js +1 -1
  418. package/dist/lib/self-heal/checks/shims.js +1 -1
  419. package/dist/lib/self-update.d.ts +39 -4
  420. package/dist/lib/self-update.js +78 -25
  421. package/dist/lib/serve/control.d.ts +1 -1
  422. package/dist/lib/serve/control.js +4 -4
  423. package/dist/lib/serve/data.d.ts +1 -1
  424. package/dist/lib/serve/data.js +1 -1
  425. package/dist/lib/serve/stream.js +1 -1
  426. package/dist/lib/service-manifest.d.ts +29 -0
  427. package/dist/lib/service-manifest.js +80 -0
  428. package/dist/lib/session/active.d.ts +59 -7
  429. package/dist/lib/session/active.js +158 -17
  430. package/dist/lib/session/bash-command.js +1 -1
  431. package/dist/lib/session/claude-accounts.d.ts +1 -1
  432. package/dist/lib/session/claude-accounts.js +1 -1
  433. package/dist/lib/session/db.d.ts +10 -2
  434. package/dist/lib/session/db.js +25 -6
  435. package/dist/lib/session/discover.d.ts +77 -0
  436. package/dist/lib/session/discover.js +130 -25
  437. package/dist/lib/session/fork.js +1 -1
  438. package/dist/lib/session/inject.d.ts +1 -1
  439. package/dist/lib/session/insights.d.ts +1 -1
  440. package/dist/lib/session/insights.js +1 -1
  441. package/dist/lib/session/live-metadata.d.ts +15 -0
  442. package/dist/lib/session/live-metadata.js +76 -0
  443. package/dist/lib/session/migrate-targets.d.ts +1 -1
  444. package/dist/lib/session/recovery.d.ts +1 -1
  445. package/dist/lib/session/recovery.js +2 -2
  446. package/dist/lib/session/remote-active.d.ts +10 -1
  447. package/dist/lib/session/remote-active.js +8 -3
  448. package/dist/lib/session/remote-bundle.d.ts +1 -1
  449. package/dist/lib/session/remote-bundle.js +2 -2
  450. package/dist/lib/session/remote-list.d.ts +15 -4
  451. package/dist/lib/session/remote-list.js +40 -3
  452. package/dist/lib/session/remote.d.ts +5 -5
  453. package/dist/lib/session/remote.js +13 -17
  454. package/dist/lib/session/resume-command.d.ts +3 -2
  455. package/dist/lib/session/resume-command.js +4 -3
  456. package/dist/lib/session/resume-owner.d.ts +3 -3
  457. package/dist/lib/session/resume-owner.js +3 -3
  458. package/dist/lib/session/session-cache.d.ts +12 -0
  459. package/dist/lib/session/session-cache.js +2 -0
  460. package/dist/lib/session/shell-programs.js +1 -1
  461. package/dist/lib/session/state.js +5 -5
  462. package/dist/lib/session/team-filter.d.ts +1 -1
  463. package/dist/lib/session/team-filter.js +1 -1
  464. package/dist/lib/session/types.d.ts +3 -3
  465. package/dist/lib/session/width.d.ts +2 -2
  466. package/dist/lib/session/width.js +2 -2
  467. package/dist/lib/share/delete.d.ts +21 -0
  468. package/dist/lib/share/delete.js +42 -0
  469. package/dist/lib/share/publish.d.ts +82 -0
  470. package/dist/lib/share/publish.js +170 -18
  471. package/dist/lib/share/worker-template.js +172 -9
  472. package/dist/lib/shims.js +35 -7
  473. package/dist/lib/smart-launch.d.ts +4 -4
  474. package/dist/lib/smart-launch.js +6 -4
  475. package/dist/lib/snapshot.d.ts +4 -4
  476. package/dist/lib/snapshot.js +2 -2
  477. package/dist/lib/ssh-exec.d.ts +1 -1
  478. package/dist/lib/ssh-exec.js +2 -2
  479. package/dist/lib/ssh-tunnel.d.ts +10 -10
  480. package/dist/lib/ssh-tunnel.js +12 -12
  481. package/dist/lib/staleness/checkers/hooks.d.ts +1 -1
  482. package/dist/lib/staleness/checkers/hooks.js +1 -1
  483. package/dist/lib/staleness/detectors/permissions.js +0 -23
  484. package/dist/lib/staleness/detectors/plugins.js +1 -1
  485. package/dist/lib/staleness/fingerprint.js +1 -1
  486. package/dist/lib/staleness/layers.d.ts +1 -1
  487. package/dist/lib/staleness/layers.js +1 -1
  488. package/dist/lib/staleness/writers/mcp.js +3 -1
  489. package/dist/lib/staleness/writers/plugins.js +1 -1
  490. package/dist/lib/staleness/writers/types.d.ts +8 -0
  491. package/dist/lib/startup/command-registry.d.ts +5 -147
  492. package/dist/lib/startup/command-registry.js +38 -303
  493. package/dist/lib/startup/dev-build.d.ts +0 -21
  494. package/dist/lib/startup/dev-build.js +29 -8
  495. package/dist/lib/state.d.ts +19 -1
  496. package/dist/lib/state.js +120 -51
  497. package/dist/lib/subagents.js +1 -1
  498. package/dist/lib/sync-status.js +1 -1
  499. package/dist/lib/sync-umbrella.d.ts +6 -1
  500. package/dist/lib/sync-umbrella.js +9 -4
  501. package/dist/lib/teams/agents.js +2 -2
  502. package/dist/lib/teams/registry.js +1 -1
  503. package/dist/lib/terminal/backends/vscodium-agent.js +1 -1
  504. package/dist/lib/terminal/engine.js +1 -1
  505. package/dist/lib/terminal/index.d.ts +4 -0
  506. package/dist/lib/terminal/index.js +3 -0
  507. package/dist/lib/terminal/inject.d.ts +2 -2
  508. package/dist/lib/terminal/inject.js +2 -2
  509. package/dist/lib/terminal/transport.js +1 -1
  510. package/dist/lib/tmux/index.d.ts +1 -1
  511. package/dist/lib/tmux/index.js +1 -1
  512. package/dist/lib/tmux/session.d.ts +21 -5
  513. package/dist/lib/tmux/session.js +76 -22
  514. package/dist/lib/triggers/handlers.d.ts +1 -1
  515. package/dist/lib/triggers/handlers.js +2 -2
  516. package/dist/lib/triggers/webhook.d.ts +36 -2
  517. package/dist/lib/triggers/webhook.js +97 -42
  518. package/dist/lib/types.d.ts +18 -6
  519. package/dist/lib/usage-fleet.d.ts +1 -1
  520. package/dist/lib/usage-fleet.js +1 -1
  521. package/dist/lib/usage-refresh.d.ts +1 -1
  522. package/dist/lib/usage-refresh.js +3 -3
  523. package/dist/lib/version-duplicates.js +2 -2
  524. package/dist/lib/view-types.d.ts +56 -0
  525. package/dist/lib/view-types.js +1 -0
  526. package/dist/lib/watchdog/rotate.d.ts +2 -2
  527. package/dist/lib/watchdog/rotate.js +3 -3
  528. package/dist/lib/watchdog/runner.d.ts +2 -3
  529. package/dist/lib/watchdog/runner.js +3 -4
  530. package/dist/lib/workflows.js +1 -1
  531. package/package.json +2 -1
  532. package/scripts/postinstall.js +2 -2
  533. package/dist/commands/bench.d.ts +0 -2
  534. package/dist/commands/bench.js +0 -101
  535. package/dist/commands/cp.d.ts +0 -84
  536. package/dist/commands/cp.js +0 -231
  537. package/dist/commands/login.d.ts +0 -2
  538. package/dist/lib/resources/commands.d.ts +0 -46
  539. package/dist/lib/resources/commands.js +0 -211
  540. package/dist/lib/resources/hooks.d.ts +0 -16
  541. package/dist/lib/resources/hooks.js +0 -153
  542. package/dist/lib/resources/mcp.d.ts +0 -34
  543. package/dist/lib/resources/mcp.js +0 -250
  544. package/dist/lib/resources/memory.d.ts +0 -15
  545. package/dist/lib/resources/memory.js +0 -46
  546. package/dist/lib/resources/permissions.d.ts +0 -13
  547. package/dist/lib/resources/permissions.js +0 -202
  548. package/dist/lib/resources/rules.d.ts +0 -46
  549. package/dist/lib/resources/rules.js +0 -179
  550. package/dist/lib/resources/skills.d.ts +0 -37
  551. package/dist/lib/resources/skills.js +0 -247
  552. package/dist/lib/resources/subagents.d.ts +0 -46
  553. package/dist/lib/resources/subagents.js +0 -202
  554. /package/dist/lib/{feed.d.ts → feed/feed.d.ts} +0 -0
@@ -15,7 +15,7 @@
15
15
  * - ship the transcript with the SAME bundle pipeline as
16
16
  * `sessions export --stdout | sessions import -`, over `sshExec`;
17
17
  * - resume on the target through the SAME `openSurfaces({ backend:'tmux', host })`
18
- * path `sessions resume --host` uses;
18
+ * path `sessions resume --device` uses;
19
19
  * - only AFTER the target's prompt is confirmed live, kill the source tmux
20
20
  * session (`killSession`). --keep skips the kill (copy, not move).
21
21
  *
@@ -33,9 +33,7 @@ import { getActiveSessions } from '../lib/session/active.js';
33
33
  import { discoverSessions, resolveSessionById } from '../lib/session/discover.js';
34
34
  import { buildResumeCommand } from './sessions.js';
35
35
  import { injectTargetFromReplyRail } from '../lib/session/inject.js';
36
- import { injectIntoTerminal } from '../lib/terminal/index.js';
37
- import { iLoginShell } from '../lib/terminal/shell.js';
38
- import { shellQuote as quoteArg } from '../lib/terminal/quote.js';
36
+ import { injectIntoTerminal, iLoginShell, shellQuote as quoteArg } from '../lib/terminal/index.js';
39
37
  import { killSession } from '../lib/tmux/session.js';
40
38
  import { getDefaultSocketPath } from '../lib/tmux/paths.js';
41
39
  import { listAllHosts, resolveHost } from '../lib/hosts/registry.js';
@@ -57,7 +55,7 @@ export function registerSessionsMigrateCommand(sessionsCmd) {
57
55
  .alias('relocate')
58
56
  .description('Relocate a running session onto another machine (fleet worker, device, or ephemeral box), then stop the source here.')
59
57
  .option('--auto', 'Pick the best target host automatically (idle fleet worker preferred)')
60
- .option('--host <name>', 'Explicit target: an enrolled host, a device, or a warm ephemeral box slug')
58
+ .option('--device <name>', 'Explicit target: an enrolled host, device, or a warm ephemeral box slug')
61
59
  .option('--lease', 'Provision a fresh ephemeral crabbox box as the target')
62
60
  .option('--mode <mode>', 'rehydrate (default: the target agent reads the transported transcript) or resume (best-effort native --resume)', 'rehydrate')
63
61
  .option('--keep', 'Copy, not move — do NOT stop the source after resuming on the target')
@@ -68,13 +66,13 @@ export function registerSessionsMigrateCommand(sessionsCmd) {
68
66
  agents sessions migrate --auto
69
67
 
70
68
  # Move a specific session onto a named host
71
- agents sessions migrate a1b2c3d4 --host yosemite-s1
69
+ agents sessions migrate a1b2c3d4 --device yosemite-s1
72
70
 
73
71
  # Spin up a fresh ephemeral box and move onto it
74
72
  agents sessions migrate --lease
75
73
 
76
74
  # Copy (don't stop the source), letting the agent wrap up its own dirty tree
77
- agents sessions migrate --host box-a --keep --agent-wrapup
75
+ agents sessions migrate --device box-a --keep --agent-wrapup
78
76
  `,
79
77
  notes: `
80
78
  - Without a [session-id], migrate resolves the session running in THIS tmux pane ($TMUX_PANE).
@@ -87,17 +85,8 @@ export function registerSessionsMigrateCommand(sessionsCmd) {
87
85
  - Every migrate appends to the ledger — see 'agents sessions migrations' for where each session went.
88
86
  `,
89
87
  });
90
- cmd.action(async (sessionId, options, command) => {
91
- // commander 15: the parent `sessions` command owns a global `-H, --host` (the
92
- // listing fan-out), which shadows this subcommand's own --host — the value
93
- // lands in the merged globals, not `options.host`. Read it from there so
94
- // `agents sessions migrate --host <name>` binds.
95
- const globals = command.optsWithGlobals();
96
- const hosts = Array.isArray(globals.host) ? globals.host : globals.host ? [globals.host] : [];
97
- if (hosts.length > 1) {
98
- console.error(chalk.yellow(`Multiple --host values given; migrating to the first (${hosts[0]}).`));
99
- }
100
- await sessionsMigrateAction(sessionId, { ...options, host: hosts[0] });
88
+ cmd.action(async (sessionId, options) => {
89
+ await sessionsMigrateAction(sessionId, options);
101
90
  });
102
91
  }
103
92
  function fail(message) {
@@ -141,7 +130,7 @@ function statsByName() {
141
130
  const cache = readStatsCache();
142
131
  return new Map(Object.entries(cache));
143
132
  }
144
- /** Enumerate + rank targets, honoring --host / --auto / --lease. */
133
+ /** Enumerate + rank targets, honoring --device / --auto / --lease. */
145
134
  async function resolveTarget(options, source) {
146
135
  const selfHostname = os.hostname();
147
136
  const ctx = {
@@ -162,17 +151,17 @@ async function resolveTarget(options, source) {
162
151
  warm = []; // crabbox not configured — fleet-only targets
163
152
  }
164
153
  const stats = statsByName();
165
- if (options.host) {
154
+ if (options.device) {
166
155
  // Explicit target: a fleet host/device, or a warm box slug.
167
- const box = warm.find((b) => b.slug === options.host);
156
+ const box = warm.find((b) => b.slug === options.device);
168
157
  if (box) {
169
158
  return { name: box.slug, kind: 'ephemeral', os: 'linux', headroom: 'unknown', box };
170
159
  }
171
- const host = await resolveHost(options.host);
160
+ const host = await resolveHost(options.device);
172
161
  if (!host)
173
- fail(`No host, device, or warm box named "${options.host}".`);
162
+ fail(`No host, device, or warm box named "${options.device}".`);
174
163
  if (host.name.toLowerCase() === selfHostname.toLowerCase()) {
175
- fail(`"${options.host}" is this machine — migrate needs a different target.`);
164
+ fail(`"${options.device}" is this machine — migrate needs a different target.`);
176
165
  }
177
166
  return { name: host.name, kind: 'fleet', os: host.os, headroom: 'unknown', host };
178
167
  }
@@ -186,7 +175,7 @@ async function resolveTarget(options, source) {
186
175
  }
187
176
  // Interactive: rank the candidates and let the user pick.
188
177
  if (!isInteractiveTerminal()) {
189
- fail('Pass --auto, --host <name>, or --lease to choose a target (no interactive picker without a tty).');
178
+ fail('Pass --auto, --device <name>, or --lease to choose a target (no interactive picker without a tty).');
190
179
  }
191
180
  const ranked = rankTargets(enumerateTargets(hosts, warm, stats, ctx), ctx);
192
181
  if (ranked.length === 0) {
@@ -447,7 +436,7 @@ export function buildMigrateResumeCommands(opts) {
447
436
  }
448
437
  /**
449
438
  * Resume the session on the target through the SAME host path as
450
- * `sessions resume --host` (tmux backend). Returns true when the resume launched.
439
+ * `sessions resume --device` (tmux backend). Returns true when the resume launched.
451
440
  */
452
441
  async function resumeOnTarget(sshTarget, source, remoteCwd, mode) {
453
442
  const command = mode === 'resume' ? buildResumeCommand(source) : rehydrateCommand(source);
@@ -459,7 +448,7 @@ async function resumeOnTarget(sshTarget, source, remoteCwd, mode) {
459
448
  // box has none ("no server running"), so we create the session (and thus the
460
449
  // server) directly with `new-session -d`, mirroring the local `createSession`
461
450
  // helper (remain-on-exit keeps the pane inspectable if the agent exits), over
462
- // the same SSH transport as `sessions resume --host`.
451
+ // the same SSH transport as `sessions resume --device`.
463
452
  //
464
453
  // Each argv element is quoted BEFORE the zsh -ilc wrapper so a command that
465
454
  // carries spaces or backticks (the rehydrate prompt) reaches the agent as one
@@ -1,4 +1,5 @@
1
1
  import type { SessionEvent, SessionMeta, TodoProgress } from '../lib/session/types.js';
2
+ import { fetchPeerPreviewDigest } from '../lib/session/remote-list.js';
2
3
  import { classifyFileChanges, changeCounts, toolHistogram, detectTestResult } from '../lib/session/digest.js';
3
4
  import { extractArtifacts, extractHooks, extractLinks, extractSkills } from '../lib/session/highlights.js';
4
5
  /**
@@ -32,6 +33,18 @@ export interface SessionPickerConfig {
32
33
  /** Lines the caller printed above the prompt (hidden-session footer). */
33
34
  linesAbovePrompt?: number;
34
35
  }
36
+ export declare function setRemotePreviewRepaint(repaint?: () => void): void;
37
+ export declare function setPeerDigestFetcherForTest(fetcher?: typeof fetchPeerPreviewDigest): void;
38
+ export declare function clearRemoteDigestCacheForTest(): void;
39
+ /**
40
+ * Validate + scrub a peer-supplied preview digest before any of it reaches this
41
+ * terminal. Peer JSON is untrusted at this boundary — the same rule
42
+ * `sanitizeMeta` applies to fan-out rows — so every string is stripped of
43
+ * terminal escapes and every list re-shaped field by field. Anything that
44
+ * doesn't look like the v1 digest is rejected, so a version-skewed peer
45
+ * degrades to the metadata card instead of a corrupted pane.
46
+ */
47
+ export declare function sanitizeRemoteDigest(raw: unknown): SessionPreviewDigest | undefined;
35
48
  export declare function clearPreviewMemoryCacheForTest(): void;
36
49
  export declare function loadSessionPreviewDigest(session: SessionMeta): {
37
50
  digest?: SessionPreviewDigest;
@@ -9,6 +9,7 @@ import fs from 'node:fs';
9
9
  import path from 'node:path';
10
10
  import chalk from 'chalk';
11
11
  import { truncate, humanDuration } from '../lib/format.js';
12
+ import { fetchPeerPreviewDigest } from '../lib/session/remote-list.js';
12
13
  import { parseSession, sanitizeForTerminal, SNAPSHOT_TODO_TOOLS } from '../lib/session/parse.js';
13
14
  import { safeTeamText } from '../lib/session/team-filter.js';
14
15
  import { cleanSessionPrompt, extractSessionTopic, isSyntheticUserMessage } from '../lib/session/prompt.js';
@@ -23,9 +24,10 @@ import { extractArtifacts, extractHooks, extractLinks, extractRepos, extractSkil
23
24
  import { getSessionPlugins, readSessionPreviewCache, writeSessionPreviewCache, readSessionContent, readArchivedSessionPreview } from '../lib/session/db.js';
24
25
  /** A session whose transcript FILE is on another machine (folded in over the
25
26
  * live cross-machine fan-out): its `filePath` is on that peer's disk, so the
26
- * preview can't parse it locally — it shows metadata + a "resume there" note
27
- * instead. Keys off `_remote`, not the machine tag, so locally-readable synced
28
- * mirrors still parse their file normally.
27
+ * preview can't parse it locally — it fetches the peer's digest over SSH and
28
+ * shows metadata + a "resume there" note until that lands. Keys off `_remote`,
29
+ * not the machine tag, so locally-readable synced mirrors still parse their
30
+ * file normally.
29
31
  *
30
32
  * This is the READ rule and only the read rule. Whether a session may be
31
33
  * RESUMED here is a different question with a different answer — a mirror is
@@ -106,6 +108,155 @@ const previewCache = createMemoryCache({
106
108
  max: 256,
107
109
  ttlMs: 5 * 60_000,
108
110
  });
111
+ const remoteDigestCache = createMemoryCache({
112
+ max: 256,
113
+ ttlMs: 5 * 60_000,
114
+ });
115
+ function remoteDigestKey(sessionId, machine) {
116
+ return `${machine}:${sessionId}`;
117
+ }
118
+ /**
119
+ * The open picker's repaint trigger. The peer fetch resolves while the pane is
120
+ * already painted, so completion has to nudge the picker into re-rendering —
121
+ * pickers register their trigger here (via `registerPreviewRepaint`) and clear
122
+ * it when they close, making a late fetch after close a no-op.
123
+ */
124
+ let remotePreviewRepaint;
125
+ export function setRemotePreviewRepaint(repaint) {
126
+ remotePreviewRepaint = repaint;
127
+ }
128
+ /** Seam for tests: the real fetcher opens an SSH connection to the peer. */
129
+ let peerDigestFetcher = fetchPeerPreviewDigest;
130
+ export function setPeerDigestFetcherForTest(fetcher) {
131
+ peerDigestFetcher = fetcher ?? fetchPeerPreviewDigest;
132
+ }
133
+ export function clearRemoteDigestCacheForTest() {
134
+ remoteDigestCache.clear();
135
+ }
136
+ /**
137
+ * Look up (or start fetching) the peer digest for a remote row. Returns the
138
+ * current entry synchronously — `buildPreview` renders whatever state exists
139
+ * now, and the fetch's completion repaints the pane through the registered
140
+ * trigger.
141
+ */
142
+ function remoteDigestForPreview(session, machine) {
143
+ const key = remoteDigestKey(session.id, machine);
144
+ const existing = remoteDigestCache.get(key);
145
+ if (existing)
146
+ return existing;
147
+ const pending = { state: 'pending' };
148
+ remoteDigestCache.set(key, pending);
149
+ void peerDigestFetcher(session.id, machine)
150
+ .then((raw) => {
151
+ const digest = sanitizeRemoteDigest(raw);
152
+ remoteDigestCache.set(key, digest ? { state: 'ready', digest } : { state: 'failed' });
153
+ })
154
+ .catch(() => {
155
+ remoteDigestCache.set(key, { state: 'failed' });
156
+ })
157
+ .then(() => remotePreviewRepaint?.());
158
+ return pending;
159
+ }
160
+ /**
161
+ * Validate + scrub a peer-supplied preview digest before any of it reaches this
162
+ * terminal. Peer JSON is untrusted at this boundary — the same rule
163
+ * `sanitizeMeta` applies to fan-out rows — so every string is stripped of
164
+ * terminal escapes and every list re-shaped field by field. Anything that
165
+ * doesn't look like the v1 digest is rejected, so a version-skewed peer
166
+ * degrades to the metadata card instead of a corrupted pane.
167
+ */
168
+ export function sanitizeRemoteDigest(raw) {
169
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw))
170
+ return undefined;
171
+ const d = raw;
172
+ if (d.schemaVersion !== 1)
173
+ return undefined;
174
+ const str = (v) => (typeof v === 'string' ? sanitizeForTerminal(v) : '');
175
+ const optStr = (v) => (typeof v === 'string' ? sanitizeForTerminal(v) : undefined);
176
+ const num = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : 0);
177
+ const optNum = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : undefined);
178
+ const strList = (v) => Array.isArray(v) ? v.filter((x) => typeof x === 'string').map(sanitizeForTerminal) : [];
179
+ const objList = (v, map) => Array.isArray(v)
180
+ ? v.flatMap((x) => {
181
+ if (!x || typeof x !== 'object' || Array.isArray(x))
182
+ return [];
183
+ const mapped = map(x);
184
+ return mapped === undefined ? [] : [mapped];
185
+ })
186
+ : [];
187
+ let todos;
188
+ if (d.todos && typeof d.todos === 'object' && !Array.isArray(d.todos)) {
189
+ const t = d.todos;
190
+ const items = objList(t.items, (it) => {
191
+ const content = str(it.content ?? it.text);
192
+ if (!content)
193
+ return undefined;
194
+ const status = it.status === 'completed' || it.status === 'in_progress' ? it.status : 'pending';
195
+ return { content, status, activeForm: optStr(it.activeForm) };
196
+ });
197
+ todos = { items, done: num(t.done), total: num(t.total), activeForm: optStr(t.activeForm) };
198
+ }
199
+ const changes = d.changes && typeof d.changes === 'object' && !Array.isArray(d.changes)
200
+ ? {
201
+ created: num(d.changes.created),
202
+ modified: num(d.changes.modified),
203
+ deleted: num(d.changes.deleted),
204
+ }
205
+ : { created: 0, modified: 0, deleted: 0 };
206
+ let test;
207
+ if (d.test && typeof d.test === 'object' && !Array.isArray(d.test)) {
208
+ const t = d.test;
209
+ const runner = str(t.runner);
210
+ if (runner) {
211
+ test = { runner, ok: t.ok === true, ts: num(t.ts), passed: optNum(t.passed), failed: optNum(t.failed) };
212
+ }
213
+ }
214
+ return {
215
+ schemaVersion: 1,
216
+ firstUser: str(d.firstUser),
217
+ lastAssistant: str(d.lastAssistant),
218
+ filesRead: num(d.filesRead),
219
+ toolCalls: num(d.toolCalls),
220
+ planFile: str(d.planFile),
221
+ todos,
222
+ subAgentCount: num(d.subAgentCount),
223
+ toolTags: strList(d.toolTags),
224
+ changes,
225
+ dirs: strList(d.dirs),
226
+ repos: strList(d.repos),
227
+ artifacts: objList(d.artifacts, (a) => {
228
+ const p = str(a.path);
229
+ const basename = str(a.basename);
230
+ if (!p || !basename)
231
+ return undefined;
232
+ const bucket = a.bucket === 'artifacts' || a.bucket === 'plans' || a.bucket === 'reports' ? a.bucket : 'docs';
233
+ return { path: p, basename, bucket };
234
+ }),
235
+ skills: objList(d.skills, (s) => {
236
+ const name = str(s.name);
237
+ return name ? { name, count: num(s.count) } : undefined;
238
+ }),
239
+ plugins: strList(d.plugins),
240
+ hooks: objList(d.hooks, (h) => {
241
+ const name = str(h.name);
242
+ return name ? { name, event: optStr(h.event), count: num(h.count), failed: num(h.failed) } : undefined;
243
+ }),
244
+ links: objList(d.links, (l) => {
245
+ const url = str(l.url);
246
+ const label = str(l.label);
247
+ // Only http(s) URLs render as OSC 8 hyperlinks — anything else a peer
248
+ // sends (file:, a bare payload) is dropped rather than linkified.
249
+ return /^https?:\/\//.test(url) && label ? { kind: 'other', url, label } : undefined;
250
+ }),
251
+ errorCount: num(d.errorCount),
252
+ firstError: optStr(d.firstError),
253
+ toolHistogram: objList(d.toolHistogram, (h) => {
254
+ const tool = str(h.tool);
255
+ return tool ? { tool, count: num(h.count) } : undefined;
256
+ }),
257
+ test,
258
+ };
259
+ }
109
260
  function previewCacheKey(session, remote) {
110
261
  let fileStamp = '';
111
262
  if (!remote && session.filePath) {
@@ -117,10 +268,16 @@ function previewCacheKey(session, remote) {
117
268
  fileStamp = 'missing';
118
269
  }
119
270
  }
271
+ // A remote row's rendered pane depends on the fetched digest's state
272
+ // (none → pending → ready/failed), so the state rides the key — otherwise the
273
+ // memoized metadata-only card would keep serving after the digest arrived.
274
+ const remoteDigestState = remote
275
+ ? remoteDigestCache.get(remoteDigestKey(session.id, remote))?.state ?? 'none'
276
+ : '';
120
277
  // The transcript stamp invalidates derived activity. Metadata that can change
121
278
  // independently (label/ticket/PR/live scanner enrichment) also rides the key.
122
279
  return JSON.stringify([
123
- remote ?? '', session.id, fileStamp, session.lastActivity, session.label,
280
+ remote ?? '', remoteDigestState, session.id, fileStamp, session.lastActivity, session.label,
124
281
  session.topic, session.ticketId, session.prUrl, session.messageCount,
125
282
  session.tokenCount, session.model, session.todos, session.plan,
126
283
  session.recentDirectoriesTouched, session.skillsUsed,
@@ -181,13 +338,26 @@ export function buildPreview(session) {
181
338
  return cached;
182
339
  const safe = sanitizeMeta(session);
183
340
  // Remote session: the transcript is on the peer's disk, so there is nothing to
184
- // parse here. Show the metadata header (agent, cwd, msgs, tokens all carried
185
- // over in the fan-out) plus where it lives and how to open it.
341
+ // parse here. Fetch the peer's already-computed digest over SSH (kicked off on
342
+ // first render; the pane repaints when it lands) and render the same compact
343
+ // preview a local row gets. Until it arrives — or when the peer can't answer —
344
+ // show the metadata header (agent, cwd, msgs, tokens — all carried over in the
345
+ // fan-out) plus where it lives and how to open it.
186
346
  if (remote) {
187
347
  const note = ' ' + chalk.gray(`on `) + chalk.bold.white(remote)
188
348
  + chalk.gray(` — enter to resume there, or space then enter to read it over SSH`);
349
+ const entry = remoteDigestForPreview(session, remote);
350
+ if (entry.state === 'ready') {
351
+ const body = formatCompactPreview(entry.digest, safe);
352
+ const output = [formatHeader(safe, []), '', note, body].filter(Boolean).join('\n');
353
+ previewCache.set(cacheKey, output);
354
+ return output;
355
+ }
356
+ const fetching = entry.state === 'pending'
357
+ ? ' ' + chalk.gray(`fetching preview from ${remote} over SSH…`)
358
+ : '';
189
359
  const metaBody = formatMetaOnlyBody(safe);
190
- const output = [formatHeader(safe, []), '', note, metaBody].filter(Boolean).join('\n');
360
+ const output = [formatHeader(safe, []), '', note, fetching, metaBody].filter(Boolean).join('\n');
191
361
  previewCache.set(cacheKey, output);
192
362
  return output;
193
363
  }
@@ -895,13 +1065,17 @@ export async function sessionPicker(config) {
895
1065
  filter: config.filter,
896
1066
  labelFor: config.labelFor,
897
1067
  buildPreview,
1068
+ // A remote row's digest arrives over SSH after the pane painted — this is
1069
+ // what lets its completion swap the metadata card for the full preview.
1070
+ registerPreviewRepaint: setRemotePreviewRepaint,
898
1071
  shortIdFor: (s) => s.shortId,
899
1072
  pageSize: config.pageSize,
900
1073
  initialSearch: config.initialSearch,
901
1074
  emptyMessage: 'No sessions match.',
902
1075
  enterHint: config.enterHint ?? 'resume',
903
1076
  linesAbovePrompt: config.linesAbovePrompt,
904
- });
1077
+ // A late digest fetch must not poke a closed prompt.
1078
+ }).finally(() => setRemotePreviewRepaint(undefined));
905
1079
  if (!picked)
906
1080
  return null;
907
1081
  return { session: picked.item, action: 'resume' };
@@ -1,15 +1,16 @@
1
1
  import type { Command } from 'commander';
2
2
  import { type SessionMeta } from '../lib/session/types.js';
3
3
  import { type Backend, type EngineContext, type Packing } from '../lib/terminal/index.js';
4
+ import { type StrictResumeOptions } from './resume.js';
4
5
  /** Opening more than this many live sessions at once asks for confirmation first. */
5
6
  export declare const CONFIRM_THRESHOLD = 5;
6
- export interface ResumeOptions {
7
+ export interface ResumeOptions extends StrictResumeOptions {
7
8
  agent?: string;
8
9
  all?: boolean;
9
10
  teams?: boolean;
10
11
  since?: string;
11
12
  limit?: string;
12
- host?: string;
13
+ device?: string;
13
14
  iterm?: boolean;
14
15
  ghostty?: boolean;
15
16
  tmux?: boolean;
@@ -24,12 +25,15 @@ export declare function registerSessionsResumeCommand(sessionsCmd: Command): voi
24
25
  /** IDs and tmux aliases are actions, not picker search text. Human phrases keep
25
26
  * the existing pre-filtered picker, while an explicit identity resumes directly. */
26
27
  export declare function isDirectResumeSelector(query: string): boolean;
27
- /** Re-enter through the top-level command so fleet routing and harness policy
28
+ /** Re-enter through sessions resume so fleet routing and harness policy
28
29
  * stay centralized. The child inherits this terminal for a real interactive resume. */
29
30
  export declare function resumeSelectorInPlace(selector: string): Promise<void>;
30
31
  /** Direct identities use focus as the lifecycle dispatcher: it rechecks the
31
32
  * live fleet, attaches a healthy pane, and falls through to `agents resume`
32
33
  * only when the process is no longer attachable. */
34
+ /** True when `sessions resume <id> --attach-only|--local` must go through
35
+ * `sessions focus` instead of `runStrictResume` (which can fork a copy). */
36
+ export declare function resumeUsesLifecycleDispatch(query: string | undefined, prompt: string | undefined, options: Pick<ResumeOptions, 'attachOnly' | 'local' | 'mode' | 'interactive' | 'headless' | 'here'>): boolean;
33
37
  export declare function dispatchSessionLifecycleInPlace(selector: string, hosts?: string[], attachOnly?: boolean, local?: boolean): Promise<void>;
34
38
  export declare function buildSessionLifecycleArgs(selector: string, hosts?: string[], attachOnly?: boolean, local?: boolean): string[];
35
39
  export declare function resolveResumePacking(options: Pick<ResumeOptions, 'splits'>): Packing;