@phnx-labs/agents-cli 1.22.34 → 1.22.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (493) hide show
  1. package/CHANGELOG.md +672 -2
  2. package/README.md +82 -35
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.d.ts +15 -0
  5. package/dist/bootstrap.js +1211 -0
  6. package/dist/commands/accounts.d.ts +4 -11
  7. package/dist/commands/accounts.js +159 -27
  8. package/dist/commands/attach.js +17 -4
  9. package/dist/commands/audit.d.ts +8 -8
  10. package/dist/commands/audit.js +57 -47
  11. package/dist/commands/browser.js +15 -11
  12. package/dist/commands/cloud.js +1 -1
  13. package/dist/commands/commands.js +0 -11
  14. package/dist/commands/computer-actions.js +33 -0
  15. package/dist/commands/computer-sessions-picker.d.ts +21 -0
  16. package/dist/commands/computer-sessions-picker.js +141 -0
  17. package/dist/commands/computer.d.ts +16 -0
  18. package/dist/commands/computer.js +37 -0
  19. package/dist/commands/config.d.ts +17 -0
  20. package/dist/commands/config.js +401 -0
  21. package/dist/commands/cp.d.ts +84 -0
  22. package/dist/commands/cp.js +231 -0
  23. package/dist/commands/daemon.js +243 -14
  24. package/dist/commands/detach-core.d.ts +1 -1
  25. package/dist/commands/detach-core.js +12 -2
  26. package/dist/commands/detach.js +1 -1
  27. package/dist/commands/doctor.js +64 -5
  28. package/dist/commands/events.d.ts +24 -12
  29. package/dist/commands/events.js +144 -28
  30. package/dist/commands/exec.js +85 -41
  31. package/dist/commands/feed.d.ts +1 -1
  32. package/dist/commands/feed.js +16 -8
  33. package/dist/commands/focus.d.ts +33 -1
  34. package/dist/commands/focus.js +177 -17
  35. package/dist/commands/funnel.d.ts +1 -1
  36. package/dist/commands/go.js +9 -8
  37. package/dist/commands/harness-wizard.d.ts +1 -0
  38. package/dist/commands/harness-wizard.js +18 -20
  39. package/dist/commands/harness.d.ts +2 -0
  40. package/dist/commands/harness.js +59 -26
  41. package/dist/commands/hooks.js +0 -11
  42. package/dist/commands/inspect.d.ts +94 -1
  43. package/dist/commands/inspect.js +866 -40
  44. package/dist/commands/lease.d.ts +4 -4
  45. package/dist/commands/lease.js +6 -6
  46. package/dist/commands/login.js +0 -13
  47. package/dist/commands/logs.d.ts +2 -2
  48. package/dist/commands/logs.js +2 -2
  49. package/dist/commands/mcp.js +7 -2
  50. package/dist/commands/memory.js +7 -2
  51. package/dist/commands/message.d.ts +1 -1
  52. package/dist/commands/message.js +37 -6
  53. package/dist/commands/models.js +4 -0
  54. package/dist/commands/monitors.d.ts +0 -1
  55. package/dist/commands/monitors.js +199 -16
  56. package/dist/commands/open.d.ts +18 -0
  57. package/dist/commands/open.js +57 -0
  58. package/dist/commands/packages.js +2 -107
  59. package/dist/commands/plugins.js +6 -3
  60. package/dist/commands/profiles.d.ts +1 -0
  61. package/dist/commands/profiles.js +16 -160
  62. package/dist/commands/projects.d.ts +28 -0
  63. package/dist/commands/projects.js +125 -5
  64. package/dist/commands/reconnect.js +9 -3
  65. package/dist/commands/repo.js +42 -1
  66. package/dist/commands/resource-view.d.ts +17 -0
  67. package/dist/commands/resource-view.js +36 -14
  68. package/dist/commands/resume.js +9 -2
  69. package/dist/commands/routines.d.ts +0 -2
  70. package/dist/commands/routines.js +473 -289
  71. package/dist/commands/secrets.js +52 -9
  72. package/dist/commands/sessions-export.d.ts +47 -0
  73. package/dist/commands/sessions-export.js +116 -6
  74. package/dist/commands/sessions-import.d.ts +17 -0
  75. package/dist/commands/sessions-import.js +114 -6
  76. package/dist/commands/sessions-migrate.d.ts +27 -0
  77. package/dist/commands/sessions-migrate.js +50 -9
  78. package/dist/commands/sessions-picker.js +23 -4
  79. package/dist/commands/sessions-resume.d.ts +5 -3
  80. package/dist/commands/sessions-resume.js +30 -8
  81. package/dist/commands/sessions-watch.d.ts +2 -0
  82. package/dist/commands/sessions-watch.js +53 -0
  83. package/dist/commands/sessions.d.ts +66 -3
  84. package/dist/commands/sessions.js +298 -47
  85. package/dist/commands/set.d.ts +1 -1
  86. package/dist/commands/set.js +2 -2
  87. package/dist/commands/setup-browser.js +2 -2
  88. package/dist/commands/setup-mine.js +0 -1
  89. package/dist/commands/setup-preferences.js +1 -1
  90. package/dist/commands/setup-share.js +34 -4
  91. package/dist/commands/setup.d.ts +5 -0
  92. package/dist/commands/setup.js +26 -0
  93. package/dist/commands/share.d.ts +85 -0
  94. package/dist/commands/share.js +379 -8
  95. package/dist/commands/skills.js +0 -11
  96. package/dist/commands/snapshot.js +1 -1
  97. package/dist/commands/ssh.d.ts +18 -0
  98. package/dist/commands/ssh.js +549 -210
  99. package/dist/commands/sync.d.ts +5 -0
  100. package/dist/commands/sync.js +212 -32
  101. package/dist/commands/teams.d.ts +13 -0
  102. package/dist/commands/teams.js +187 -30
  103. package/dist/commands/tickets.d.ts +2 -0
  104. package/dist/commands/tickets.js +43 -0
  105. package/dist/commands/update.js +2 -4
  106. package/dist/commands/usage.js +5 -3
  107. package/dist/commands/versions.js +11 -5
  108. package/dist/commands/view.js +15 -7
  109. package/dist/commands/webhook.d.ts +2 -2
  110. package/dist/commands/webhook.js +7 -7
  111. package/dist/index.d.ts +18 -2
  112. package/dist/index.js +53 -1264
  113. package/dist/lib/account-catalog.d.ts +18 -0
  114. package/dist/lib/account-catalog.js +38 -0
  115. package/dist/lib/account-provider-registry.d.ts +18 -0
  116. package/dist/lib/account-provider-registry.js +59 -0
  117. package/dist/lib/account-registry.d.ts +40 -0
  118. package/dist/lib/account-registry.js +239 -0
  119. package/dist/lib/account-schema.d.ts +44 -0
  120. package/dist/lib/account-schema.js +91 -0
  121. package/dist/lib/account-state-service.d.ts +21 -0
  122. package/dist/lib/account-state-service.js +60 -0
  123. package/dist/lib/activity.d.ts +1 -1
  124. package/dist/lib/activity.js +8 -1
  125. package/dist/lib/add-dir.d.ts +80 -0
  126. package/dist/lib/add-dir.js +241 -0
  127. package/dist/lib/agent-cli-commands.d.ts +11 -0
  128. package/dist/lib/agent-cli-commands.js +30 -0
  129. package/dist/lib/agents.js +44 -36
  130. package/dist/lib/answer-router.js +1 -1
  131. package/dist/lib/audit/log.d.ts +10 -27
  132. package/dist/lib/audit/log.js +20 -33
  133. package/dist/lib/auth-health.d.ts +9 -2
  134. package/dist/lib/auth-health.js +42 -9
  135. package/dist/lib/auto-pull-worker.js +7 -3
  136. package/dist/lib/auto-pull.d.ts +44 -3
  137. package/dist/lib/auto-pull.js +88 -5
  138. package/dist/lib/binary-shadow.d.ts +28 -0
  139. package/dist/lib/binary-shadow.js +121 -0
  140. package/dist/lib/brand.js +9 -3
  141. package/dist/lib/browser/ipc.d.ts +30 -0
  142. package/dist/lib/browser/ipc.js +81 -4
  143. package/dist/lib/browser/profiles.d.ts +3 -2
  144. package/dist/lib/browser/profiles.js +65 -22
  145. package/dist/lib/browser/service.d.ts +4 -0
  146. package/dist/lib/browser/service.js +30 -3
  147. package/dist/lib/browser/sessions-list.d.ts +22 -2
  148. package/dist/lib/browser/sessions-list.js +54 -6
  149. package/dist/lib/browser/stream.d.ts +2 -0
  150. package/dist/lib/browser/stream.js +1 -0
  151. package/dist/lib/browser/types.d.ts +19 -0
  152. package/dist/lib/byok-usage.d.ts +9 -2
  153. package/dist/lib/byok-usage.js +133 -31
  154. package/dist/lib/cli-entry.d.ts +11 -0
  155. package/dist/lib/cli-entry.js +46 -0
  156. package/dist/lib/cloud/host.d.ts +1 -1
  157. package/dist/lib/cloud/host.js +2 -2
  158. package/dist/lib/cloud/registry.js +1 -1
  159. package/dist/lib/cloud/types.d.ts +1 -1
  160. package/dist/lib/codex-policy.d.ts +9 -1
  161. package/dist/lib/codex-policy.js +17 -2
  162. package/dist/lib/commands.d.ts +2 -0
  163. package/dist/lib/commands.js +2 -0
  164. package/dist/lib/computer/sessions-list.d.ts +150 -0
  165. package/dist/lib/computer/sessions-list.js +363 -0
  166. package/dist/lib/config-keys.d.ts +86 -0
  167. package/dist/lib/config-keys.js +193 -0
  168. package/dist/lib/config-machine-keys.d.ts +12 -0
  169. package/dist/lib/config-machine-keys.js +17 -0
  170. package/dist/lib/config-transfer.js +3 -4
  171. package/dist/lib/crabbox/cli.d.ts +2 -2
  172. package/dist/lib/crabbox/cli.js +3 -3
  173. package/dist/lib/daemon-health.d.ts +22 -0
  174. package/dist/lib/daemon-health.js +33 -3
  175. package/dist/lib/daemon-services.d.ts +50 -0
  176. package/dist/lib/daemon-services.js +147 -0
  177. package/dist/lib/daemon-ticks.d.ts +35 -66
  178. package/dist/lib/daemon-ticks.js +77 -159
  179. package/dist/lib/daemon.d.ts +72 -4
  180. package/dist/lib/daemon.js +792 -202
  181. package/dist/lib/deeplink/register.d.ts +49 -0
  182. package/dist/lib/deeplink/register.js +253 -0
  183. package/dist/lib/deeplink/url.d.ts +34 -0
  184. package/dist/lib/deeplink/url.js +78 -0
  185. package/dist/lib/device-config.d.ts +124 -29
  186. package/dist/lib/device-config.js +346 -141
  187. package/dist/lib/devices/config-migration.d.ts +42 -0
  188. package/dist/lib/devices/config-migration.js +203 -0
  189. package/dist/lib/devices/connect.js +14 -7
  190. package/dist/lib/devices/doctor-findings.d.ts +4 -1
  191. package/dist/lib/devices/doctor-findings.js +20 -1
  192. package/dist/lib/devices/harness-inventory.d.ts +11 -2
  193. package/dist/lib/devices/harness-inventory.js +0 -0
  194. package/dist/lib/devices/health.d.ts +1 -1
  195. package/dist/lib/devices/health.js +1 -1
  196. package/dist/lib/devices/pending.d.ts +22 -1
  197. package/dist/lib/devices/pending.js +67 -2
  198. package/dist/lib/devices/registry.d.ts +0 -25
  199. package/dist/lib/devices/registry.js +2 -83
  200. package/dist/lib/devices/resolve-profile.d.ts +20 -0
  201. package/dist/lib/devices/resolve-profile.js +44 -0
  202. package/dist/lib/devices/rollout-verify.d.ts +101 -0
  203. package/dist/lib/devices/rollout-verify.js +193 -0
  204. package/dist/lib/devices/ssh-config.js +10 -6
  205. package/dist/lib/event-families.d.ts +28 -0
  206. package/dist/lib/event-families.js +159 -0
  207. package/dist/lib/event-stream.d.ts +9 -1
  208. package/dist/lib/event-stream.js +26 -9
  209. package/dist/lib/events.d.ts +9 -1
  210. package/dist/lib/events.js +21 -6
  211. package/dist/lib/exec.d.ts +30 -0
  212. package/dist/lib/exec.js +220 -122
  213. package/dist/lib/feed-broadcast.d.ts +25 -0
  214. package/dist/lib/feed-broadcast.js +33 -0
  215. package/dist/lib/feed.d.ts +1 -1
  216. package/dist/lib/feed.js +12 -2
  217. package/dist/lib/fleet/capture.js +15 -0
  218. package/dist/lib/fleet/manifest.js +9 -0
  219. package/dist/lib/fleet/types.d.ts +9 -0
  220. package/dist/lib/fleet-status.js +10 -8
  221. package/dist/lib/git.d.ts +20 -6
  222. package/dist/lib/git.js +121 -17
  223. package/dist/lib/hosts/dispatch.d.ts +8 -3
  224. package/dist/lib/hosts/dispatch.js +29 -3
  225. package/dist/lib/hosts/logs.d.ts +2 -2
  226. package/dist/lib/hosts/logs.js +2 -2
  227. package/dist/lib/hosts/option.js +1 -1
  228. package/dist/lib/hosts/passthrough.d.ts +2 -3
  229. package/dist/lib/hosts/passthrough.js +10 -24
  230. package/dist/lib/hosts/progress.js +2 -2
  231. package/dist/lib/hosts/providers/devices.d.ts +3 -3
  232. package/dist/lib/hosts/providers/devices.js +18 -12
  233. package/dist/lib/hosts/ready.d.ts +5 -1
  234. package/dist/lib/hosts/ready.js +9 -3
  235. package/dist/lib/hosts/reconcile.d.ts +2 -2
  236. package/dist/lib/hosts/reconcile.js +2 -2
  237. package/dist/lib/hosts/registry.js +14 -9
  238. package/dist/lib/hosts/remote-cmd.js +1 -1
  239. package/dist/lib/hosts/remote-os.d.ts +9 -6
  240. package/dist/lib/hosts/remote-os.js +13 -6
  241. package/dist/lib/hosts/routing-flag.d.ts +23 -0
  242. package/dist/lib/hosts/routing-flag.js +41 -0
  243. package/dist/lib/hosts/run-target.js +1 -1
  244. package/dist/lib/hosts/session-index.js +1 -1
  245. package/dist/lib/hosts/tasks.d.ts +6 -6
  246. package/dist/lib/hosts/tasks.js +4 -4
  247. package/dist/lib/hosts/types.js +1 -2
  248. package/dist/lib/installations/resolve.js +2 -8
  249. package/dist/lib/isolation-boundary-report.js +0 -1
  250. package/dist/lib/linear-cache.d.ts +7 -0
  251. package/dist/lib/linear-cache.js +31 -4
  252. package/dist/lib/linear-project-counts.d.ts +1 -1
  253. package/dist/lib/linear-project-counts.js +2 -3
  254. package/dist/lib/linear-projects.js +1 -1
  255. package/dist/lib/loop.d.ts +2 -2
  256. package/dist/lib/loop.js +1 -1
  257. package/dist/lib/mailbox-target.d.ts +1 -1
  258. package/dist/lib/mailbox-target.js +1 -1
  259. package/dist/lib/manifest.js +7 -4
  260. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  261. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  262. package/dist/lib/menubar/snapshot.d.ts +3 -2
  263. package/dist/lib/menubar/snapshot.js +6 -2
  264. package/dist/lib/migrate-fold.d.ts +33 -0
  265. package/dist/lib/migrate-fold.js +130 -0
  266. package/dist/lib/migrate.d.ts +34 -34
  267. package/dist/lib/migrate.js +106 -128
  268. package/dist/lib/model-tier-overrides.d.ts +1 -1
  269. package/dist/lib/model-tier-overrides.js +15 -2
  270. package/dist/lib/monitors/config.d.ts +17 -3
  271. package/dist/lib/monitors/config.js +52 -18
  272. package/dist/lib/monitors/engine.d.ts +32 -1
  273. package/dist/lib/monitors/engine.js +94 -11
  274. package/dist/lib/monitors/fingerprint.d.ts +46 -0
  275. package/dist/lib/monitors/fingerprint.js +100 -0
  276. package/dist/lib/monitors/remote.d.ts +47 -0
  277. package/dist/lib/monitors/remote.js +81 -0
  278. package/dist/lib/monitors/state.d.ts +39 -0
  279. package/dist/lib/monitors/state.js +56 -0
  280. package/dist/lib/onepassword.d.ts +17 -0
  281. package/dist/lib/onepassword.js +52 -22
  282. package/dist/lib/open-url.js +1 -1
  283. package/dist/lib/picker.d.ts +14 -2
  284. package/dist/lib/picker.js +35 -13
  285. package/dist/lib/placement.d.ts +1 -1
  286. package/dist/lib/placement.js +1 -1
  287. package/dist/lib/pr-land-detach.d.ts +32 -0
  288. package/dist/lib/pr-land-detach.js +79 -0
  289. package/dist/lib/profiles-presets.js +13 -0
  290. package/dist/lib/profiles.d.ts +2 -0
  291. package/dist/lib/profiles.js +44 -1
  292. package/dist/lib/project-focus.d.ts +1 -1
  293. package/dist/lib/project-focus.js +1 -1
  294. package/dist/lib/project-key.d.ts +17 -0
  295. package/dist/lib/project-key.js +26 -0
  296. package/dist/lib/project-probe.d.ts +4 -1
  297. package/dist/lib/project-probe.js +5 -4
  298. package/dist/lib/project-resources.js +2 -18
  299. package/dist/lib/project-root.d.ts +16 -0
  300. package/dist/lib/project-root.js +20 -2
  301. package/dist/lib/projects.d.ts +20 -1
  302. package/dist/lib/projects.js +78 -1
  303. package/dist/lib/refresh-coordinator.d.ts +24 -0
  304. package/dist/lib/refresh-coordinator.js +52 -0
  305. package/dist/lib/registry.d.ts +2 -2
  306. package/dist/lib/registry.js +1 -1
  307. package/dist/lib/resource-aliases.d.ts +13 -0
  308. package/dist/lib/resource-aliases.js +26 -0
  309. package/dist/lib/resources/types.d.ts +1 -1
  310. package/dist/lib/resources.d.ts +16 -0
  311. package/dist/lib/resources.js +66 -10
  312. package/dist/lib/rotate.d.ts +3 -4
  313. package/dist/lib/rotate.js +4 -5
  314. package/dist/lib/routine-activation.d.ts +22 -2
  315. package/dist/lib/routine-activation.js +63 -16
  316. package/dist/lib/routine-context.d.ts +9 -2
  317. package/dist/lib/routine-context.js +21 -6
  318. package/dist/lib/routines-project.d.ts +58 -48
  319. package/dist/lib/routines-project.js +190 -159
  320. package/dist/lib/routines.d.ts +41 -6
  321. package/dist/lib/routines.js +92 -34
  322. package/dist/lib/run-defaults.d.ts +5 -0
  323. package/dist/lib/run-defaults.js +11 -1
  324. package/dist/lib/runner.d.ts +10 -8
  325. package/dist/lib/runner.js +122 -39
  326. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  327. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  328. package/dist/lib/secrets/agent.d.ts +10 -3
  329. package/dist/lib/secrets/agent.js +43 -8
  330. package/dist/lib/secrets/bundles.d.ts +1 -0
  331. package/dist/lib/secrets/bundles.js +92 -80
  332. package/dist/lib/secrets/index.js +32 -9
  333. package/dist/lib/secrets/install-helper.d.ts +4 -4
  334. package/dist/lib/secrets/install-helper.js +4 -4
  335. package/dist/lib/secrets/push.d.ts +40 -6
  336. package/dist/lib/secrets/push.js +58 -11
  337. package/dist/lib/secrets/read-backoff.d.ts +1 -1
  338. package/dist/lib/secrets/read-backoff.js +1 -1
  339. package/dist/lib/secrets/remote.d.ts +24 -0
  340. package/dist/lib/secrets/remote.js +54 -4
  341. package/dist/lib/self-update.d.ts +108 -0
  342. package/dist/lib/self-update.js +276 -1
  343. package/dist/lib/session/active.d.ts +89 -5
  344. package/dist/lib/session/active.js +165 -10
  345. package/dist/lib/session/actor-sidecar.d.ts +1 -1
  346. package/dist/lib/session/actor-sidecar.js +2 -1
  347. package/dist/lib/session/db.d.ts +176 -2
  348. package/dist/lib/session/db.js +484 -17
  349. package/dist/lib/session/discover.js +27 -4
  350. package/dist/lib/session/hook-sessions.js +2 -2
  351. package/dist/lib/session/host-link.d.ts +2 -2
  352. package/dist/lib/session/host-link.js +2 -2
  353. package/dist/lib/session/pid-registry.d.ts +21 -0
  354. package/dist/lib/session/pid-registry.js +57 -0
  355. package/dist/lib/session/remote-active.js +15 -1
  356. package/dist/lib/session/remote.js +2 -2
  357. package/dist/lib/session/session-cache.d.ts +14 -7
  358. package/dist/lib/session/session-cache.js +51 -9
  359. package/dist/lib/session/state.d.ts +2 -2
  360. package/dist/lib/session/state.js +1 -1
  361. package/dist/lib/session/sync/config.d.ts +10 -10
  362. package/dist/lib/session/sync/config.js +10 -10
  363. package/dist/lib/session/sync/r2.d.ts +34 -0
  364. package/dist/lib/session/sync/r2.js +123 -0
  365. package/dist/lib/session/throughput.d.ts +1 -1
  366. package/dist/lib/session/throughput.js +1 -1
  367. package/dist/lib/session/types.d.ts +23 -1
  368. package/dist/lib/session/types.js +15 -0
  369. package/dist/lib/session/viewing-in.d.ts +1 -1
  370. package/dist/lib/session/viewing-in.js +1 -1
  371. package/dist/lib/session/watch.d.ts +101 -0
  372. package/dist/lib/session/watch.js +242 -0
  373. package/dist/lib/share/config.d.ts +4 -0
  374. package/dist/lib/share/config.js +1 -0
  375. package/dist/lib/share/delete.d.ts +93 -0
  376. package/dist/lib/share/delete.js +127 -0
  377. package/dist/lib/share/provision.d.ts +38 -0
  378. package/dist/lib/share/provision.js +50 -0
  379. package/dist/lib/share/publish.d.ts +40 -1
  380. package/dist/lib/share/publish.js +116 -3
  381. package/dist/lib/share/worker-template.js +71 -6
  382. package/dist/lib/shims.d.ts +17 -3
  383. package/dist/lib/shims.js +136 -27
  384. package/dist/lib/signin-badge.js +3 -2
  385. package/dist/lib/skills.js +2 -0
  386. package/dist/lib/smart-launch.d.ts +8 -8
  387. package/dist/lib/smart-launch.js +80 -59
  388. package/dist/lib/ssh-exec.d.ts +1 -1
  389. package/dist/lib/ssh-exec.js +1 -1
  390. package/dist/lib/staleness/prune.d.ts +88 -0
  391. package/dist/lib/staleness/prune.js +69 -0
  392. package/dist/lib/staleness/registry.d.ts +1 -1
  393. package/dist/lib/staleness/writers/commands.js +34 -2
  394. package/dist/lib/staleness/writers/hooks.js +16 -0
  395. package/dist/lib/staleness/writers/kinds.d.ts +6 -0
  396. package/dist/lib/staleness/writers/skills.js +19 -0
  397. package/dist/lib/staleness/writers/subagents.d.ts +2 -3
  398. package/dist/lib/staleness/writers/subagents.js +0 -4
  399. package/dist/lib/staleness/writers/types.d.ts +32 -0
  400. package/dist/lib/startup/command-registry.d.ts +6 -12
  401. package/dist/lib/startup/command-registry.js +14 -31
  402. package/dist/lib/startup/dev-build.d.ts +10 -0
  403. package/dist/lib/startup/dev-build.js +13 -1
  404. package/dist/lib/startup/spellcheck.d.ts +18 -0
  405. package/dist/lib/startup/spellcheck.js +45 -0
  406. package/dist/lib/state.d.ts +36 -9
  407. package/dist/lib/state.js +96 -46
  408. package/dist/lib/subagents-registry.d.ts +0 -7
  409. package/dist/lib/subagents-registry.js +38 -65
  410. package/dist/lib/subagents.d.ts +0 -33
  411. package/dist/lib/subagents.js +0 -75
  412. package/dist/lib/sync-umbrella.js +1 -1
  413. package/dist/lib/teams/agents.d.ts +41 -1
  414. package/dist/lib/teams/agents.js +187 -9
  415. package/dist/lib/teams/api.d.ts +11 -1
  416. package/dist/lib/teams/api.js +11 -2
  417. package/dist/lib/teams/delivery.d.ts +41 -0
  418. package/dist/lib/teams/delivery.js +60 -0
  419. package/dist/lib/teams/registry.d.ts +14 -0
  420. package/dist/lib/teams/registry.js +51 -1
  421. package/dist/lib/teams/remoteWorktree.d.ts +19 -0
  422. package/dist/lib/teams/remoteWorktree.js +29 -0
  423. package/dist/lib/teams/scheduler.d.ts +1 -1
  424. package/dist/lib/teams/scheduler.js +1 -1
  425. package/dist/lib/teams/worktree.d.ts +24 -0
  426. package/dist/lib/teams/worktree.js +42 -0
  427. package/dist/lib/terminal/backends/vscodium-agent.d.ts +10 -1
  428. package/dist/lib/terminal/backends/vscodium-agent.js +16 -5
  429. package/dist/lib/terminal/engine.d.ts +4 -0
  430. package/dist/lib/terminal/engine.js +8 -2
  431. package/dist/lib/terminal/types.d.ts +21 -2
  432. package/dist/lib/testdata/refresh-coordinator-worker.d.ts +1 -0
  433. package/dist/lib/testdata/refresh-coordinator-worker.js +23 -0
  434. package/dist/lib/tickets/list.d.ts +53 -0
  435. package/dist/lib/tickets/list.js +153 -0
  436. package/dist/lib/tmux/orphan-reap.d.ts +320 -0
  437. package/dist/lib/tmux/orphan-reap.js +644 -0
  438. package/dist/lib/tmux/session.d.ts +68 -3
  439. package/dist/lib/tmux/session.js +95 -5
  440. package/dist/lib/triggers/handlers.d.ts +20 -0
  441. package/dist/lib/triggers/handlers.js +6 -1
  442. package/dist/lib/types.d.ts +46 -34
  443. package/dist/lib/usage-fleet.d.ts +32 -0
  444. package/dist/lib/usage-fleet.js +125 -0
  445. package/dist/lib/usage-refresh.d.ts +3 -3
  446. package/dist/lib/usage-refresh.js +19 -16
  447. package/dist/lib/usage.d.ts +51 -47
  448. package/dist/lib/usage.js +145 -153
  449. package/dist/lib/version-duplicates.js +2 -2
  450. package/dist/lib/versions.d.ts +56 -13
  451. package/dist/lib/versions.js +195 -45
  452. package/dist/lib/watchdog/log.d.ts +1 -1
  453. package/dist/lib/watchdog/log.js +3 -3
  454. package/dist/lib/watchdog/rotate.d.ts +6 -6
  455. package/dist/lib/watchdog/rotate.js +6 -6
  456. package/dist/lib/workflows.d.ts +1 -1
  457. package/dist/lib/yaml-io.d.ts +47 -0
  458. package/dist/lib/yaml-io.js +55 -0
  459. package/package.json +2 -1
  460. package/scripts/install-helper.js +2 -2
  461. package/scripts/postinstall.js +23 -20
  462. package/dist/commands/defaults.d.ts +0 -7
  463. package/dist/commands/defaults.js +0 -107
  464. package/dist/commands/export.d.ts +0 -11
  465. package/dist/commands/export.js +0 -215
  466. package/dist/commands/helper.d.ts +0 -12
  467. package/dist/commands/helper.js +0 -87
  468. package/dist/commands/hosts.d.ts +0 -11
  469. package/dist/commands/hosts.js +0 -330
  470. package/dist/commands/lock.d.ts +0 -12
  471. package/dist/commands/lock.js +0 -70
  472. package/dist/commands/pull.d.ts +0 -17
  473. package/dist/commands/pull.js +0 -39
  474. package/dist/commands/push.d.ts +0 -14
  475. package/dist/commands/push.js +0 -30
  476. package/dist/commands/wallet.d.ts +0 -20
  477. package/dist/commands/wallet.js +0 -216
  478. package/dist/commands/worktree.d.ts +0 -19
  479. package/dist/commands/worktree.js +0 -272
  480. package/dist/lib/account-labels.d.ts +0 -24
  481. package/dist/lib/account-labels.js +0 -72
  482. package/dist/lib/auto-dispatch-linear.d.ts +0 -18
  483. package/dist/lib/auto-dispatch-linear.js +0 -107
  484. package/dist/lib/auto-dispatch-provider.d.ts +0 -10
  485. package/dist/lib/auto-dispatch-provider.js +0 -30
  486. package/dist/lib/auto-dispatch.d.ts +0 -93
  487. package/dist/lib/auto-dispatch.js +0 -128
  488. package/dist/lib/export.d.ts +0 -72
  489. package/dist/lib/export.js +0 -269
  490. package/dist/lib/lock.d.ts +0 -93
  491. package/dist/lib/lock.js +0 -207
  492. package/dist/lib/wallet/index.d.ts +0 -78
  493. package/dist/lib/wallet/index.js +0 -253
package/dist/lib/usage.js CHANGED
@@ -25,6 +25,7 @@ import { formatBackoffRemaining, noteUsageRateLimited, usageRateLimitedUntil, }
25
25
  import { getCacheDir } from './state.js';
26
26
  import { mapBounded } from './concurrency.js';
27
27
  import { atomicWriteFileSync, ensureLockTarget, withFileLock } from './fs-atomic.js';
28
+ import { withRefreshLease } from './refresh-coordinator.js';
28
29
  const execFileAsync = promisify(execFile);
29
30
  const CLAUDE_USAGE_URL = 'https://api.anthropic.com/api/oauth/usage';
30
31
  const CLAUDE_TOKEN_URL = 'https://platform.claude.com/v1/oauth/token';
@@ -62,6 +63,40 @@ export function usageRejectedError(agent, status) {
62
63
  ? `${agent} is rate-limiting the usage endpoint for this machine (HTTP 429).`
63
64
  : `${agent} rejected the usage read (HTTP ${status}).`;
64
65
  }
66
+ /**
67
+ * Canonical phrase for the Anthropic setup-token scope gap (RUSH-2392).
68
+ * `claude setup-token` mints `user:inference` only; the usage endpoint requires
69
+ * `user:profile`. The account can still run; usage bars cannot populate via
70
+ * that token. Callers detect this string with {@link isUsageHeadlessScopeError}
71
+ * so the UI can render it distinctly from a generic "unverified" failure.
72
+ */
73
+ export const USAGE_HEADLESS_SCOPE_MARKER = 'usage unavailable (headless)';
74
+ /**
75
+ * Distinct error when Claude's usage API returns 403 because the setup-token
76
+ * lacks `user:profile` (RUSH-2392). Not a revocation, not a missing mint —
77
+ * a permanent tradeoff of the headless credential.
78
+ */
79
+ export function usageHeadlessScopeError(agent = 'Claude') {
80
+ return `${agent} ${USAGE_HEADLESS_SCOPE_MARKER} — setup-token lacks user:profile; account can still run.`;
81
+ }
82
+ /** True when an error string is the setup-token scope gap (RUSH-2392). */
83
+ export function isUsageHeadlessScopeError(error) {
84
+ return typeof error === 'string' && error.includes(USAGE_HEADLESS_SCOPE_MARKER);
85
+ }
86
+ /**
87
+ * Detect Anthropic's usage-endpoint scope denial: HTTP 403 whose body names
88
+ * `user:profile` (or "scope requirement"). A bare 403 without that body stays
89
+ * classified as a real rejection — only the known setup-token shape is special
90
+ * (RUSH-2392).
91
+ */
92
+ export function isClaudeUsageScopeDenied(status, bodyText) {
93
+ if (status !== 403)
94
+ return false;
95
+ if (!bodyText)
96
+ return false;
97
+ const lower = bodyText.toLowerCase();
98
+ return lower.includes('user:profile') || lower.includes('scope requirement');
99
+ }
65
100
  /**
66
101
  * The read threw rather than answering — a timeout, DNS/TLS failure, a payload
67
102
  * that would not parse, a credential that would not decrypt. Every provider
@@ -193,9 +228,9 @@ export function agentReportsUsage(agentId) {
193
228
  }
194
229
  /**
195
230
  * Whether an agent's usage source makes a live NETWORK call (Claude/Kimi/Droid/
196
- * Cursor/Antigravity) versus reading local session logs (Codex/Grok). Only the
197
- * networked ones go through the on-disk cache, and only they need the daemon's
198
- * background refresher to keep that cache warm for the routing hot path.
231
+ * Cursor/Antigravity) versus reading local session logs (Codex/Grok). Both
232
+ * kinds publish through the shared cache; callers use this only to distinguish
233
+ * provider I/O from local collection.
199
234
  */
200
235
  export function agentUsesNetworkUsage(agentId) {
201
236
  return getUsageSource(agentId)?.network === true;
@@ -207,27 +242,6 @@ export function agentUsesNetworkUsage(agentId) {
207
242
  * (and cannot stack behind delayed responses until the process is pegged).
208
243
  */
209
244
  export const USAGE_FETCH_CONCURRENCY = 3;
210
- /**
211
- * Concurrent background SWR refreshes. Kept below the blocking concurrency so
212
- * a display path that returns cached data immediately does not still flood the
213
- * network with N silent refreshes that finish long after the command exits and
214
- * pile onto the next invocation.
215
- */
216
- const USAGE_BG_REFRESH_CONCURRENCY = 2;
217
- /**
218
- * How long a cached snapshot is treated as fresh enough that we skip the network
219
- * entirely. Five minutes balances "still accurate enough to glance at" against
220
- * "don't re-hit every account on every `agents view` in a tight loop". Was 2
221
- * minutes; that re-fired too often when delayed responses stacked.
222
- */
223
- export const USAGE_CACHE_FRESH_MS = 5 * 60 * 1000;
224
- export const USAGE_CACHE_SWR_MS = 24 * 60 * 60 * 1000; // 24 hours — beyond this, block on live fetch.
225
- /**
226
- * Unified entry for every multi-account usage lookup (`agents view`, rotation,
227
- * JSON export). Deduplicates by usage identity, then fans out through the
228
- * shared SWR + timeout path with a hard concurrency cap so delayed calls
229
- * cannot pile up.
230
- */
231
245
  export async function getUsageInfoByIdentity(inputs, opts) {
232
246
  const { canonicalByUsageKey, usageFetchInputs } = buildCanonicalUsageContext(inputs);
233
247
  const entries = [...usageFetchInputs.entries()];
@@ -246,63 +260,36 @@ export async function getUsageInfoByIdentity(inputs, opts) {
246
260
  };
247
261
  }
248
262
  /**
249
- * How stale a cached snapshot may be before the read stops serving it and blocks
250
- * on the network. Defaults to the full 24h stale-while-revalidate window; a
251
- * caller that is about to ROUTE on the number passes a shorter `maxAgeMs` and
252
- * gets a live read instead of a day-old one. Never widens past 24h — a caller
253
- * cannot opt into more staleness than the cache policy allows.
254
- */
255
- export function swrWindowMsFor(maxAgeMs) {
256
- if (maxAgeMs === undefined || !Number.isFinite(maxAgeMs))
257
- return USAGE_CACHE_SWR_MS;
258
- return Math.min(USAGE_CACHE_SWR_MS, Math.max(0, maxAgeMs));
259
- }
260
- /**
261
- * In-process dedup for live + background usage work on the same identity.
262
- * Covers both the blocking cold-cache path and SWR background refreshes so a
263
- * delayed HTTP response cannot be stacked under a second request for the same
264
- * key (the pile-up that made consecutive `agents view` runs peg CPU/network).
263
+ * In-process dedup complements the device-wide lease. It avoids lock contention
264
+ * when several callers in one process explicitly request the same refresh.
265
265
  */
266
266
  const inFlightLiveFetches = new Map();
267
- const inFlightBgKeys = new Set();
268
- const bgRefreshQueue = [];
269
- let bgRefreshActive = 0;
270
267
  /**
271
- * Fetch usage for a single identity using stale-while-revalidate.
272
- *
273
- * - Cache fresh (< 5 min): return cached snapshot, NO network.
274
- * - Cache stale but < 24h: return cached snapshot instantly, enqueue a
275
- * concurrency-capped background refresh.
276
- * - Cache too stale or absent: block on live fetch (shared in-flight promise),
277
- * fall back to cache on error.
278
- *
279
- * This keeps `agents run` / `agents view` off the network on the hot path. The
280
- * first invocation after a cold install or 24h gap still blocks once to seed
281
- * the cache; every run after that returns instantly while the cache silently
282
- * refreshes in the background — never more than {@link USAGE_BG_REFRESH_CONCURRENCY}
283
- * at a time.
268
+ * Fetch usage for one identity. Ordinary callers always read the shared cache;
269
+ * the daemon and explicit `--refresh` calls collect through one device lease.
284
270
  */
285
271
  export async function getUsageInfoForIdentity(input, opts) {
286
272
  const usageKey = getUsageLookupKey(input.info);
287
273
  const forceRefresh = opts?.forceRefresh === true;
288
- const readOnly = opts?.readOnly === true;
289
- // Agents whose registered usage source makes a live network call go
290
- // through the stale-while-revalidate cache below so `agents run`/`agents view`
291
- // stay off the network on the hot path. Everything else (Codex reads local
292
- // session logs) takes the legacy blocking path. The on-disk cache is shared and
274
+ // Reading is the default. Only an explicit forceRefresh is authorized to
275
+ // collect provider/local-log state; callers cannot accidentally turn a
276
+ // display or routing path into a collector by omitting an option.
277
+ const readOnly = !forceRefresh;
278
+ // The on-disk cache is shared for both provider and local-log sources and is
293
279
  // keyed by usageKey, which is namespaced per agent (`claude:org=…`,
294
280
  // `kimi:user=…`, `droid:org=…`, `cursor:user=…`, `antigravity:sub=…`), so one
295
281
  // cache file holds every account without collision.
296
- const usesNetworkUsage = getUsageSource(input.agentId)?.network === true;
297
- if (!usesNetworkUsage || !usageKey) {
282
+ if (!usageKey) {
283
+ if (readOnly)
284
+ return { snapshot: null, error: 'stale' };
298
285
  return getUsageInfo(input.agentId, {
299
286
  home: input.home,
300
287
  cliVersion: input.cliVersion,
301
288
  organizationId: input.info.organizationId,
289
+ fileOnly: opts?.fileOnly,
302
290
  });
303
291
  }
304
292
  const cached = readClaudeUsageCache(usageKey);
305
- const ageMs = cached?.capturedAt ? Date.now() - cached.capturedAt.getTime() : Infinity;
306
293
  // `readOnly` (the `agents run` routing hot path): serve the cache and NEVER
307
294
  // touch the network — not even a background refresh. `collectRunCandidates`
308
295
  // used to pass a 5-minute `maxAgeMs`, which made a snapshot older than that
@@ -319,58 +306,48 @@ export async function getUsageInfoForIdentity(input, opts) {
319
306
  return { snapshot: cached, error: null };
320
307
  return { snapshot: null, error: 'stale' };
321
308
  }
322
- // `--refresh` (forceRefresh) skips both cache short-circuits and blocks on a
323
- // live fetch below, so `agents view --refresh` repopulates every account we can
324
- // actually reach a token for.
325
- if (!forceRefresh) {
326
- // Fresh: cache is recent enough, skip network entirely.
327
- if (cached && ageMs < USAGE_CACHE_FRESH_MS) {
328
- return { snapshot: cached, error: null };
329
- }
330
- // Stale-while-revalidate: cache exists and isn't ancient, return it now and
331
- // refresh in the background so the next invocation has fresh data.
332
- //
333
- // `maxAgeMs` shortens that window for callers that are about to make a
334
- // DECISION on the number rather than display it. Serving a day-old snapshot
335
- // to the account router is how a launch lands on an already-exhausted
336
- // account: the box picks from its own cache, the background refresh lands
337
- // after the choice is made, and nothing reconciles. Display callers keep the
338
- // full 24h window and stay off the hot path.
339
- const swrWindowMs = swrWindowMsFor(opts?.maxAgeMs);
340
- if (cached && ageMs < swrWindowMs) {
341
- enqueueBackgroundUsageRefresh(input, usageKey);
342
- return { snapshot: cached, error: null };
343
- }
344
- }
345
- // Cold cache or > 24h old (or forceRefresh): block on a shared live fetch so
346
- // concurrent callers for the same identity share one in-flight HTTP call.
347
- return fetchLiveUsageDeduped(input, usageKey, cached);
309
+ // Explicit refresh: block on the shared device collector.
310
+ return fetchLiveUsageDeduped(input, usageKey, cached, opts?.fileOnly === true);
348
311
  }
349
312
  /**
350
313
  * Single-flight live usage fetch per usage key. Concurrent callers (view +
351
314
  * rotation, or two rows sharing an account) await the same promise rather than
352
315
  * opening duplicate HTTP requests that then time out and pile up.
353
316
  */
354
- async function fetchLiveUsageDeduped(input, usageKey, cached) {
317
+ async function fetchLiveUsageDeduped(input, usageKey, cached, fileOnly) {
355
318
  const existing = inFlightLiveFetches.get(usageKey);
356
319
  if (existing)
357
320
  return existing;
358
- const promise = (async () => {
359
- const usage = await getUsageInfo(input.agentId, {
360
- home: input.home,
361
- cliVersion: input.cliVersion,
362
- organizationId: input.info.organizationId,
363
- });
364
- if (usage.snapshot?.source === 'live') {
365
- writeClaudeUsageCache(usageKey, usage.snapshot);
321
+ const previousCapturedAt = cached?.capturedAt?.getTime() ?? 0;
322
+ const promise = withRefreshLease({
323
+ scope: 'usage',
324
+ key: usageKey,
325
+ readCompleted: () => {
326
+ const snapshot = readClaudeUsageCache(usageKey);
327
+ return snapshot ? { snapshot, error: null } : null;
328
+ },
329
+ isCompleted: (value) => (value.snapshot?.capturedAt?.getTime() ?? 0) > previousCapturedAt,
330
+ refresh: async () => {
331
+ const latestCached = readClaudeUsageCache(usageKey) ?? cached;
332
+ const usage = await getUsageInfo(input.agentId, {
333
+ home: input.home,
334
+ cliVersion: input.cliVersion,
335
+ organizationId: input.info.organizationId,
336
+ fileOnly,
337
+ });
338
+ if (usage.snapshot) {
339
+ if (!usage.snapshot.capturedAt || usage.snapshot.capturedAt.getTime() <= previousCapturedAt) {
340
+ usage.snapshot.capturedAt = new Date(previousCapturedAt + 1);
341
+ }
342
+ writeClaudeUsageCache(usageKey, usage.snapshot);
343
+ return usage;
344
+ }
345
+ // Live fetch failed — last-resort fallback to whatever cache we had.
346
+ if (latestCached)
347
+ return { snapshot: latestCached, error: usage.error };
366
348
  return usage;
367
- }
368
- // Live fetch failed — last-resort fallback to whatever cache we had.
369
- if (cached) {
370
- return { snapshot: cached, error: usage.error };
371
- }
372
- return usage;
373
- })();
349
+ },
350
+ });
374
351
  inFlightLiveFetches.set(usageKey, promise);
375
352
  try {
376
353
  return await promise;
@@ -379,46 +356,6 @@ async function fetchLiveUsageDeduped(input, usageKey, cached) {
379
356
  inFlightLiveFetches.delete(usageKey);
380
357
  }
381
358
  }
382
- /**
383
- * Enqueue a background refresh of the usage cache. Errors are swallowed — a
384
- * failed refresh leaves the existing cache in place. Work is deferred via
385
- * `setImmediate` (keychain reads do sync I/O) and drained with a hard
386
- * concurrency cap so N stale accounts do not open N HTTP calls at once.
387
- */
388
- function enqueueBackgroundUsageRefresh(input, usageKey) {
389
- if (inFlightBgKeys.has(usageKey) || inFlightLiveFetches.has(usageKey))
390
- return;
391
- inFlightBgKeys.add(usageKey);
392
- bgRefreshQueue.push(async () => {
393
- try {
394
- // Reuse the single-flight live path so a blocking caller that arrives
395
- // mid-refresh shares the same HTTP call instead of racing it.
396
- const cached = readClaudeUsageCache(usageKey);
397
- await fetchLiveUsageDeduped(input, usageKey, cached);
398
- }
399
- catch {
400
- /* background refresh failed — leave existing cache in place */
401
- }
402
- finally {
403
- inFlightBgKeys.delete(usageKey);
404
- }
405
- });
406
- pumpBackgroundUsageRefreshes();
407
- }
408
- function pumpBackgroundUsageRefreshes() {
409
- while (bgRefreshActive < USAGE_BG_REFRESH_CONCURRENCY && bgRefreshQueue.length > 0) {
410
- const work = bgRefreshQueue.shift();
411
- bgRefreshActive++;
412
- // setImmediate so the SWR caller returns the cached snapshot before any
413
- // keychain/network work starts on this tick.
414
- setImmediate(() => {
415
- work().finally(() => {
416
- bgRefreshActive--;
417
- pumpBackgroundUsageRefreshes();
418
- });
419
- });
420
- }
421
- }
422
359
  /**
423
360
  * Pick which usage windows to render in a compact one-line summary.
424
361
  *
@@ -488,10 +425,20 @@ export function formatUsageSummary(plan, snapshot, planWidth = 3, opts) {
488
425
  // The bars came from the cache and the live read that should have confirmed
489
426
  // them failed, so they are the last thing we saw — not the current state.
490
427
  // Drawing them unmarked is what let a 26h-old "48% used" read as fact.
491
- if (opts?.unverified) {
428
+ // Headless-scope (RUSH-2392) is a known permanent gap, not a flaky cache:
429
+ // prefer that label over the generic "unverified" so operators do not re-mint.
430
+ if (opts?.headless) {
431
+ parts.push(chalk.dim(USAGE_HEADLESS_SCOPE_MARKER));
432
+ }
433
+ else if (opts?.unverified) {
492
434
  parts.push(chalk.yellow('unverified'));
493
435
  }
494
436
  }
437
+ else if (opts?.headless) {
438
+ // No bars at all: still name the scope gap so "usage pending" is not
439
+ // mistaken for a missing setup-token or seeding failure (RUSH-2392).
440
+ parts.push(chalk.dim(USAGE_HEADLESS_SCOPE_MARKER));
441
+ }
495
442
  else if (opts?.unavailable) {
496
443
  // Signed-in account we could NOT fetch usage for (no live token in a reachable
497
444
  // home / org mismatch / fetch error). Say so explicitly instead of drawing a
@@ -725,6 +672,21 @@ async function getClaudeUsageInfo(options) {
725
672
  if (response.status === 429) {
726
673
  noteUsageRateLimited('claude', response.headers.get('retry-after'));
727
674
  }
675
+ // Setup-token is user:inference only; usage needs user:profile → 403
676
+ // with a scope-requirement body. Distinct from a real rejection so the
677
+ // UI does not say "unverified" / re-mint (RUSH-2392).
678
+ if (response.status === 403) {
679
+ let bodyText = '';
680
+ try {
681
+ bodyText = await response.text();
682
+ }
683
+ catch {
684
+ // ignore — fall through to generic rejection
685
+ }
686
+ if (isClaudeUsageScopeDenied(response.status, bodyText)) {
687
+ return { snapshot: null, error: usageHeadlessScopeError('Claude') };
688
+ }
689
+ }
728
690
  return { snapshot: null, error: usageRejectedError('Claude', response.status) };
729
691
  }
730
692
  const data = await response.json();
@@ -908,7 +870,7 @@ export function formatKimiPlan(data) {
908
870
  return tail.charAt(0).toUpperCase() + tail.slice(1).toLowerCase();
909
871
  }
910
872
  /**
911
- * Fetch Droid usage via Factory's billing limits API — the same endpoint the
873
+ * Fetch Droid usage via Factory.ai's billing limits API — the same endpoint the
912
874
  * droid CLI polls for its token-limit banner. The WorkOS access token comes
913
875
  * from the locally decrypted ~/.factory/auth.v2.file (the same credential
914
876
  * account identity in agents.ts reads).
@@ -1018,6 +980,25 @@ export async function probeClaudeStatus(home, cliVersion) {
1018
980
  if (response.status === 429) {
1019
981
  noteUsageRateLimited('claude', response.headers.get('retry-after'));
1020
982
  }
983
+ // Setup-token is user:inference only; usage needs user:profile → 403.
984
+ // That is NOT a revocation — the account still runs (RUSH-2392).
985
+ if (response.status === 403) {
986
+ let bodyText = '';
987
+ try {
988
+ bodyText = await response.text();
989
+ }
990
+ catch {
991
+ // Body unreadable: fall through to a bare 403 (classified as revoked).
992
+ }
993
+ if (isClaudeUsageScopeDenied(response.status, bodyText)) {
994
+ return {
995
+ status: 403,
996
+ token: 'present',
997
+ reason: 'usage_scope',
998
+ error: USAGE_HEADLESS_SCOPE_MARKER,
999
+ };
1000
+ }
1001
+ }
1021
1002
  return { status: response.status, token: 'present' };
1022
1003
  }
1023
1004
  catch (err) {
@@ -1316,7 +1297,7 @@ function deleteCachedClaudeOauth(service) {
1316
1297
  * a file-based setup-token and, when none is provisioned, gets `null` — it never
1317
1298
  * reads Claude Code's interactive login (transmitting that ACL-bound OAuth token
1318
1299
  * to Anthropic's API is what gets it revoked; see the branch body and
1319
- * docs/design/credential-management.md). It is OFF by default so full-credential
1300
+ * docs/credential-management.md). It is OFF by default so full-credential
1320
1301
  * callers that refresh (`isClaudeAuthValid` -> `getClaudeAccessToken`) or export
1321
1302
  * the full blob (`readClaudeCredentialsBlob` for Rush Cloud dispatch) still read
1322
1303
  * the interactive login.
@@ -1348,7 +1329,7 @@ export async function loadClaudeOauth(home, opts) {
1348
1329
  // interactive credential used programmatically, which Anthropic flags and
1349
1330
  // revokes (the fleet-wide-logout class, RUSH-1822), and which violates the
1350
1331
  // invariant that the interactive/rotating login is untouchable
1351
- // (docs/design/credential-management.md). Report unprovisioned (-> probe
1332
+ // (docs/credential-management.md). Report unprovisioned (-> probe
1352
1333
  // token 'missing' -> auth-health 'unconfigured', benign for rotation); seed a
1353
1334
  // setup-token via the mint-auth path to restore usage/probe for the account.
1354
1335
  return null;
@@ -1786,12 +1767,20 @@ async function getGrokUsageInfo(options) {
1786
1767
  const match = await readLatestGrokBilling(logPath);
1787
1768
  if (!match)
1788
1769
  return { snapshot: null, error: null };
1770
+ // Grok has no live usage API (`network: false`) — bars are last-seen from
1771
+ // this machine's unified.jsonl only. Drop windows whose billing period has
1772
+ // already ended so a stale 100% does not paint "rate-limited" after reset,
1773
+ // and so an expired 92% on one box cannot disagree with a fresh reading on
1774
+ // another. Missing `creditUsagePercent` never reaches here as a 0% bar
1775
+ // (see readLatestGrokBilling).
1776
+ const now = new Date();
1777
+ const windows = match.windows.filter((window) => isCachedUsageWindowFresh(window, match.capturedAt, now));
1789
1778
  return {
1790
1779
  snapshot: {
1791
1780
  source: 'last_seen',
1792
1781
  sourceLabel: 'last seen in Grok logs',
1793
1782
  capturedAt: match.capturedAt,
1794
- windows: match.windows,
1783
+ windows,
1795
1784
  plan: match.subscriptionTier,
1796
1785
  },
1797
1786
  error: null,
@@ -2028,10 +2017,13 @@ async function readLatestGrokBilling(filePath) {
2028
2017
  if (parsed.msg === 'billing: fetched credits config' && parsed.ctx?.config) {
2029
2018
  const config = parsed.ctx.config;
2030
2019
  const windows = [];
2031
- if (config.currentPeriod?.end) {
2020
+ if (config.currentPeriod?.end && typeof config.creditUsagePercent === 'number') {
2032
2021
  // `creditUsagePercent` is Grok's weekly credit consumption (0-100);
2033
2022
  // the billing period's `end` is when that window resets.
2034
- const rawPercent = typeof config.creditUsagePercent === 'number' ? config.creditUsagePercent : 0;
2023
+ // Do NOT coerce a missing percent to 0 a new period often lands a
2024
+ // billing line before the gauge is populated, and inventing 0% makes
2025
+ // `agents view` disagree across devices (and looks like a fresh week).
2026
+ const rawPercent = config.creditUsagePercent;
2035
2027
  windows.push({
2036
2028
  key: 'week',
2037
2029
  label: 'Current week',
@@ -1,7 +1,7 @@
1
1
  import chalk from 'chalk';
2
2
  import { getAccountInfo, agentLabel } from './agents.js';
3
3
  import { compareVersions, getVersionHomePath, listInstalledVersions, } from './versions.js';
4
- import { getUsageInfoByIdentity, getUsageLookupKey, } from './usage.js';
4
+ import { buildCanonicalUsageContext, getUsageLookupKey, } from './usage.js';
5
5
  function duplicateIdentity(info) {
6
6
  if (!info)
7
7
  return null;
@@ -38,7 +38,7 @@ export async function getNewerDuplicateVersions(agentId, selectedVersion) {
38
38
  const info = await getAccountInfo(agentId, home);
39
39
  return { version, home, info };
40
40
  }));
41
- const { canonicalByUsageKey } = await getUsageInfoByIdentity(rows.map(({ version, home, info }) => ({
41
+ const { canonicalByUsageKey } = buildCanonicalUsageContext(rows.map(({ version, home, info }) => ({
42
42
  agentId,
43
43
  home,
44
44
  cliVersion: version,
@@ -1,5 +1,6 @@
1
1
  import type { AgentId } from './types.js';
2
2
  import { compareVersions } from './agent-spec/primitives.js';
3
+ import { type PrunableKind } from './staleness/prune.js';
3
4
  /**
4
5
  * Resource selection for syncing to a version.
5
6
  * Each field can be:
@@ -110,6 +111,24 @@ export declare function parseAgentSpec(spec: string): AgentSpec | null;
110
111
  * Get the directory where a specific version is installed.
111
112
  */
112
113
  export declare function getVersionDir(agent: AgentId, version: string): string;
114
+ /**
115
+ * Pick the real grok binary among `grok-*` entries in `downloadsDir` when NO
116
+ * filename carries the pinned version string. Grok self-updates its binary in
117
+ * place while running under the shim, so a version-home's downloads dir can
118
+ * accumulate several `grok-*` files whose names have drifted away from that
119
+ * version-home's pinned version (RUSH-2459: on yosemite-s0, version-home
120
+ * `0.2.82` held `grok-1.0.0-linux-aarch64` after grok self-updated, plus a
121
+ * stale, unrelated 99-byte `grok-0.2.118-linux-aarch64` wrapper script that
122
+ * happened to sort alphabetically first).
123
+ *
124
+ * Never blindly take whatever `fs.readdirSync` returns first — that is exactly
125
+ * the bug this replaces. Instead: exclude anything under
126
+ * {@link MIN_GROK_BINARY_BYTES} (rejects wrapper/alias artifacts on size
127
+ * alone, no content sniffing needed) and, among the survivors, prefer the most
128
+ * recently modified — the file grok's self-updater actually wrote last.
129
+ * Returns null (fail loud, never guess) when nothing survives the size filter.
130
+ */
131
+ export declare function resolveGrokFallbackBinary(downloadsDir: string): string | null;
113
132
  /**
114
133
  * Get the binary path for a specific agent version.
115
134
  */
@@ -494,6 +513,12 @@ export interface SyncResult {
494
513
  * sync — never one line per file from down here.
495
514
  */
496
515
  projectSkipped: string[];
516
+ /**
517
+ * Resources removed from the version home because they were deleted from
518
+ * source since the last sync (RUSH-2438), per kind. Populated only on a
519
+ * repo-scope reconcile that ran the prune pass; empty otherwise.
520
+ */
521
+ pruned: Record<PrunableKind, string[]>;
497
522
  }
498
523
  /**
499
524
  * Enumerate the DotAgent repo names that resources can be scoped to:
@@ -501,21 +526,37 @@ export interface SyncResult {
501
526
  * repo alias. Used to validate `agents sync <agent> --repo <name>`.
502
527
  */
503
528
  export declare function listRepoNames(): string[];
529
+ /**
530
+ * Build a ResourceSelection from source-pattern expansion and an optional
531
+ * per-kind name filter. Both dimensions are optional and compose:
532
+ *
533
+ * patterns only → resources from those source layers (all matching names)
534
+ * kindFilter only → only those specific kinds / names, no source restriction
535
+ * both combined → patterns scope the source layer; kindFilter further
536
+ * limits which names within each kind are included
537
+ *
538
+ * Typical callers:
539
+ * `--repo system` → buildSelection(['system:*'])
540
+ * `--plugin` → buildSelection([], { plugins: 'all' })
541
+ * `--plugin fleet` → buildSelection([], { plugins: ['fleet'] })
542
+ * no flags → buildSelection([]) → full selection
543
+ *
544
+ * Memory (`kindFilter.memory`):
545
+ * - Always `'all'` when patterns are active (repo scope must recompile the
546
+ * composed file from all layers, RUSH-1354).
547
+ * - `'all'` when `kindFilter.memory` is set (--rule / --memory flag).
548
+ * - Absent (skipped) when kindFilter is given but does not include memory,
549
+ * so `--plugin fleet` does NOT trigger a memory recompile.
550
+ * - `'all'` when no kindFilter is given (full sync includes everything).
551
+ */
552
+ export declare function buildSelection(patterns: string[], kindFilter?: ResourceSelection, cwd?: string): ResourceSelection;
504
553
  /**
505
554
  * Build a ResourceSelection scoped to a single DotAgent repo (`system`,
506
- * `user`, `project`, or an extra-repo alias). Every resource kind is filtered
507
- * to the entries whose source layer matches `repo`, reusing the same
508
- * name→source maps and `source:*` pattern expansion the persisted-pattern
509
- * sync path uses. Passing the result as an explicit `selection` means the sync
510
- * touches only that repo's resources no orphan-sweep of the other layers.
511
- *
512
- * `memory` is set to `'all'`, NOT `[]`: the composed rules-memory file is a
513
- * merge of ALL layers, so scoping the sync to a single repo must still
514
- * recompile it in the same pass (RUSH-1354). Leaving it out — or using the
515
- * `[]` skip-sentinel — silently strands the memory file at its old content
516
- * whenever a repo-scoped sync runs after a rules change. `'all'` makes
517
- * `syncResourcesToVersion` recompose from every layer via the active preset,
518
- * exactly as an unscoped full reconcile does.
555
+ * `user`, `project`, or an extra-repo alias). Delegates to `buildSelection`
556
+ * so the source-map and pattern-expansion logic stays in one place.
557
+ *
558
+ * `memory` is always `'all'`: the composed rules-memory file spans all layers
559
+ * and must be recompiled in the same pass (RUSH-1354).
519
560
  */
520
561
  export declare function buildRepoScopedSelection(repo: string, cwd?: string): ResourceSelection;
521
562
  /**
@@ -550,6 +591,8 @@ export declare function syncResourcesToVersion(agent: AgentId, version: string,
550
591
  cwd?: string;
551
592
  force?: boolean;
552
593
  available?: AvailableResources;
594
+ prune?: boolean;
595
+ allowExecSurfaces?: boolean;
553
596
  }): SyncResult;
554
597
  /**
555
598
  * Get the effective HOME directory for an agent.