@phnx-labs/agents-cli 1.22.120 → 1.22.121

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 (1603) hide show
  1. package/CHANGELOG.md +227 -0
  2. package/README.md +19 -2
  3. package/dist/bootstrap.d.ts +0 -15
  4. package/dist/bootstrap.js +10 -409
  5. package/dist/cli/command-registry.d.ts +0 -58
  6. package/dist/cli/command-registry.js +2 -74
  7. package/dist/commands/accounts.d.ts +0 -17
  8. package/dist/commands/accounts.js +1 -52
  9. package/dist/commands/alias.d.ts +0 -12
  10. package/dist/commands/alias.js +0 -6
  11. package/dist/commands/apply.d.ts +0 -15
  12. package/dist/commands/apply.js +0 -63
  13. package/dist/commands/audit.d.ts +0 -12
  14. package/dist/commands/audit.js +0 -13
  15. package/dist/commands/auth.js +4 -12
  16. package/dist/commands/beta.d.ts +0 -6
  17. package/dist/commands/beta.js +2 -6
  18. package/dist/commands/browser-sessions-picker.d.ts +0 -8
  19. package/dist/commands/browser-sessions-picker.js +0 -26
  20. package/dist/commands/browser.d.ts +0 -57
  21. package/dist/commands/browser.js +0 -80
  22. package/dist/commands/budget.d.ts +0 -13
  23. package/dist/commands/budget.js +0 -2
  24. package/dist/commands/cli.d.ts +0 -12
  25. package/dist/commands/cli.js +0 -4
  26. package/dist/commands/cloud.d.ts +0 -9
  27. package/dist/commands/cloud.js +0 -43
  28. package/dist/commands/commands.d.ts +0 -9
  29. package/dist/commands/commands.js +0 -18
  30. package/dist/commands/computer-sessions-picker.d.ts +0 -11
  31. package/dist/commands/computer-sessions-picker.js +0 -29
  32. package/dist/commands/computer.d.ts +0 -62
  33. package/dist/commands/computer.js +3 -114
  34. package/dist/commands/config.d.ts +0 -14
  35. package/dist/commands/config.js +21 -60
  36. package/dist/commands/cost.d.ts +0 -11
  37. package/dist/commands/cost.js +1 -17
  38. package/dist/commands/daemon-test-harness.d.ts +0 -32
  39. package/dist/commands/daemon-test-harness.js +1 -36
  40. package/dist/commands/daemon.d.ts +0 -46
  41. package/dist/commands/daemon.js +8 -255
  42. package/dist/commands/detach-core.d.ts +0 -28
  43. package/dist/commands/detach-core.js +0 -30
  44. package/dist/commands/detach.d.ts +1 -12
  45. package/dist/commands/detach.js +16 -52
  46. package/dist/commands/device-config-test-harness.js +0 -12
  47. package/dist/commands/doctor.d.ts +0 -103
  48. package/dist/commands/doctor.js +3 -279
  49. package/dist/commands/events.d.ts +0 -29
  50. package/dist/commands/events.js +1 -55
  51. package/dist/commands/exec.d.ts +0 -163
  52. package/dist/commands/exec.js +15 -964
  53. package/dist/commands/factory.d.ts +0 -6
  54. package/dist/commands/factory.js +0 -2
  55. package/dist/commands/feed-watch.js +0 -20
  56. package/dist/commands/feed.d.ts +0 -38
  57. package/dist/commands/feed.js +1 -151
  58. package/dist/commands/feedback.d.ts +0 -5
  59. package/dist/commands/feedback.js +0 -5
  60. package/dist/commands/fleet-capture.d.ts +0 -12
  61. package/dist/commands/fleet-capture.js +1 -39
  62. package/dist/commands/focus.d.ts +6 -94
  63. package/dist/commands/focus.js +13 -183
  64. package/dist/commands/fork.d.ts +0 -21
  65. package/dist/commands/fork.js +0 -45
  66. package/dist/commands/funnel.d.ts +0 -3
  67. package/dist/commands/go.d.ts +2 -71
  68. package/dist/commands/go.js +5 -99
  69. package/dist/commands/harness-hooks.d.ts +0 -41
  70. package/dist/commands/harness-hooks.js +0 -48
  71. package/dist/commands/harness-wizard.d.ts +0 -137
  72. package/dist/commands/harness-wizard.js +0 -109
  73. package/dist/commands/harness.d.ts +0 -63
  74. package/dist/commands/harness.js +0 -103
  75. package/dist/commands/hooks.d.ts +0 -9
  76. package/dist/commands/hooks.js +0 -26
  77. package/dist/commands/humans.d.ts +0 -8
  78. package/dist/commands/humans.js +0 -8
  79. package/dist/commands/import.d.ts +0 -22
  80. package/dist/commands/import.js +0 -79
  81. package/dist/commands/insights.d.ts +0 -37
  82. package/dist/commands/insights.js +3 -115
  83. package/dist/commands/inspect.d.ts +0 -117
  84. package/dist/commands/inspect.js +2 -448
  85. package/dist/commands/lease.d.ts +0 -28
  86. package/dist/commands/lease.js +0 -43
  87. package/dist/commands/logs.d.ts +0 -23
  88. package/dist/commands/logs.js +0 -30
  89. package/dist/commands/mailboxes.d.ts +0 -18
  90. package/dist/commands/mailboxes.js +0 -29
  91. package/dist/commands/mcp.d.ts +0 -9
  92. package/dist/commands/mcp.js +0 -53
  93. package/dist/commands/memory.d.ts +0 -7
  94. package/dist/commands/memory.js +0 -7
  95. package/dist/commands/menubar.d.ts +0 -8
  96. package/dist/commands/menubar.js +0 -24
  97. package/dist/commands/message.d.ts +0 -23
  98. package/dist/commands/message.js +0 -50
  99. package/dist/commands/mine.d.ts +0 -22
  100. package/dist/commands/mine.js +0 -21
  101. package/dist/commands/models.d.ts +0 -8
  102. package/dist/commands/models.js +0 -33
  103. package/dist/commands/modes.d.ts +0 -10
  104. package/dist/commands/modes.js +0 -13
  105. package/dist/commands/monitors.d.ts +0 -9
  106. package/dist/commands/monitors.js +3 -160
  107. package/dist/commands/open.d.ts +0 -26
  108. package/dist/commands/open.js +0 -10
  109. package/dist/commands/output.d.ts +0 -18
  110. package/dist/commands/output.js +1 -34
  111. package/dist/commands/packages-materialize.d.ts +0 -11
  112. package/dist/commands/packages-materialize.js +0 -3
  113. package/dist/commands/packages.d.ts +0 -10
  114. package/dist/commands/packages.js +0 -50
  115. package/dist/commands/perf.d.ts +0 -41
  116. package/dist/commands/perf.js +0 -55
  117. package/dist/commands/permissions.d.ts +0 -9
  118. package/dist/commands/permissions.js +0 -43
  119. package/dist/commands/plugins.d.ts +0 -14
  120. package/dist/commands/plugins.js +2 -55
  121. package/dist/commands/profiles.d.ts +0 -25
  122. package/dist/commands/profiles.js +0 -27
  123. package/dist/commands/projects-todo.d.ts +2 -0
  124. package/dist/commands/projects-todo.js +132 -0
  125. package/dist/commands/projects.d.ts +0 -85
  126. package/dist/commands/projects.js +344 -291
  127. package/dist/commands/prune.js +0 -30
  128. package/dist/commands/ps-roster.d.ts +92 -0
  129. package/dist/commands/ps-roster.js +744 -0
  130. package/dist/commands/ps.d.ts +6 -0
  131. package/dist/commands/ps.js +98 -0
  132. package/dist/commands/refresh-rules.d.ts +0 -13
  133. package/dist/commands/refresh-rules.js +0 -14
  134. package/dist/commands/reminders.d.ts +0 -7
  135. package/dist/commands/repo.d.ts +0 -89
  136. package/dist/commands/repo.js +7 -205
  137. package/dist/commands/resource-view.d.ts +0 -33
  138. package/dist/commands/resource-view.js +0 -49
  139. package/dist/commands/resume.d.ts +1 -19
  140. package/dist/commands/resume.js +0 -50
  141. package/dist/commands/route.d.ts +0 -10
  142. package/dist/commands/route.js +0 -19
  143. package/dist/commands/routines.d.ts +0 -42
  144. package/dist/commands/routines.js +5 -290
  145. package/dist/commands/routines.test-fixture.d.ts +0 -34
  146. package/dist/commands/routines.test-fixture.js +4 -100
  147. package/dist/commands/rules.d.ts +0 -9
  148. package/dist/commands/rules.js +1 -6
  149. package/dist/commands/run-account-picker.d.ts +0 -59
  150. package/dist/commands/run-account-picker.js +0 -71
  151. package/dist/commands/run-broadcast.d.ts +0 -9
  152. package/dist/commands/run-broadcast.js +0 -7
  153. package/dist/commands/run-cloud.d.ts +0 -15
  154. package/dist/commands/run-cloud.js +0 -37
  155. package/dist/commands/run-device-picker.d.ts +0 -25
  156. package/dist/commands/run-device-picker.js +1 -53
  157. package/dist/commands/secrets-passthrough.d.ts +0 -31
  158. package/dist/commands/secrets-passthrough.js +0 -10
  159. package/dist/commands/send.d.ts +0 -20
  160. package/dist/commands/send.js +14 -18
  161. package/dist/commands/sessions-backfill.d.ts +0 -7
  162. package/dist/commands/sessions-backfill.js +1 -16
  163. package/dist/commands/sessions-backup-setup.js +0 -11
  164. package/dist/commands/sessions-bookmark.d.ts +0 -8
  165. package/dist/commands/sessions-bookmark.js +0 -28
  166. package/dist/commands/sessions-browser.d.ts +2 -117
  167. package/dist/commands/sessions-browser.js +5 -243
  168. package/dist/commands/sessions-export.d.ts +1 -26
  169. package/dist/commands/sessions-export.js +3 -81
  170. package/dist/commands/sessions-import.d.ts +0 -14
  171. package/dist/commands/sessions-import.js +0 -59
  172. package/dist/commands/sessions-inject.d.ts +0 -60
  173. package/dist/commands/sessions-inject.js +3 -96
  174. package/dist/commands/sessions-migrate.d.ts +2 -37
  175. package/dist/commands/sessions-migrate.js +7 -159
  176. package/dist/commands/sessions-optimize.d.ts +0 -12
  177. package/dist/commands/sessions-picker-factory.d.ts +0 -7
  178. package/dist/commands/sessions-picker-factory.js +0 -8
  179. package/dist/commands/sessions-picker.d.ts +4 -103
  180. package/dist/commands/sessions-picker.js +13 -352
  181. package/dist/commands/sessions-render.d.ts +1 -2
  182. package/dist/commands/sessions-render.js +3 -7
  183. package/dist/commands/sessions-resume.d.ts +1 -24
  184. package/dist/commands/sessions-resume.js +2 -65
  185. package/dist/commands/sessions-share.d.ts +1 -9
  186. package/dist/commands/sessions-share.js +1 -45
  187. package/dist/commands/sessions-stats.d.ts +0 -24
  188. package/dist/commands/sessions-stats.js +0 -49
  189. package/dist/commands/sessions-stop.d.ts +1 -20
  190. package/dist/commands/sessions-stop.js +4 -9
  191. package/dist/commands/sessions-tail.d.ts +1 -19
  192. package/dist/commands/sessions-tail.js +3 -36
  193. package/dist/commands/sessions-trace.d.ts +5 -36
  194. package/dist/commands/sessions-trace.js +7 -82
  195. package/dist/commands/sessions.d.ts +1 -666
  196. package/dist/commands/sessions.js +30 -2279
  197. package/dist/commands/sessions.test-fixture.d.ts +0 -9
  198. package/dist/commands/sessions.test-fixture.js +8 -23
  199. package/dist/commands/setup-accounts.d.ts +0 -6
  200. package/dist/commands/setup-browser.d.ts +0 -23
  201. package/dist/commands/setup-browser.js +0 -28
  202. package/dist/commands/setup-computer.d.ts +0 -16
  203. package/dist/commands/setup-computer.js +0 -28
  204. package/dist/commands/setup-fleet.d.ts +0 -8
  205. package/dist/commands/setup-fleet.js +0 -11
  206. package/dist/commands/setup-mine.d.ts +0 -14
  207. package/dist/commands/setup-mine.js +0 -25
  208. package/dist/commands/setup-preferences.d.ts +0 -47
  209. package/dist/commands/setup-preferences.js +0 -53
  210. package/dist/commands/setup-secrets.d.ts +2 -24
  211. package/dist/commands/setup-secrets.js +0 -24
  212. package/dist/commands/setup-term.d.ts +0 -21
  213. package/dist/commands/setup-term.js +0 -21
  214. package/dist/commands/setup-terminal.d.ts +0 -1
  215. package/dist/commands/setup-terminal.js +0 -1
  216. package/dist/commands/setup-tools.d.ts +2 -0
  217. package/dist/commands/setup-tools.js +73 -0
  218. package/dist/commands/setup.d.ts +0 -20
  219. package/dist/commands/setup.js +4 -57
  220. package/dist/commands/skills.d.ts +0 -9
  221. package/dist/commands/skills.js +1 -22
  222. package/dist/commands/snapshot.d.ts +0 -9
  223. package/dist/commands/snapshot.js +0 -10
  224. package/dist/commands/ssh.d.ts +0 -64
  225. package/dist/commands/ssh.js +9 -420
  226. package/dist/commands/status.d.ts +0 -12
  227. package/dist/commands/status.js +0 -26
  228. package/dist/commands/subagents.d.ts +0 -8
  229. package/dist/commands/subagents.js +0 -31
  230. package/dist/commands/sync.d.ts +0 -37
  231. package/dist/commands/sync.js +0 -256
  232. package/dist/commands/teams-picker.d.ts +0 -3
  233. package/dist/commands/teams-picker.js +0 -34
  234. package/dist/commands/teams.d.ts +1 -76
  235. package/dist/commands/teams.js +9 -477
  236. package/dist/commands/tmux.d.ts +0 -25
  237. package/dist/commands/tmux.js +0 -46
  238. package/dist/commands/traces.js +0 -19
  239. package/dist/commands/trash.d.ts +0 -17
  240. package/dist/commands/trash.js +1 -11
  241. package/dist/commands/uninstall.d.ts +0 -9
  242. package/dist/commands/uninstall.js +0 -6
  243. package/dist/commands/update.d.ts +0 -22
  244. package/dist/commands/update.js +0 -44
  245. package/dist/commands/upgrade.d.ts +0 -1
  246. package/dist/commands/upgrade.js +0 -1
  247. package/dist/commands/utils.d.ts +0 -85
  248. package/dist/commands/utils.js +1 -95
  249. package/dist/commands/versions.d.ts +0 -16
  250. package/dist/commands/versions.js +0 -134
  251. package/dist/commands/view.d.ts +0 -90
  252. package/dist/commands/view.js +4 -343
  253. package/dist/commands/watchdog.d.ts +0 -19
  254. package/dist/commands/watchdog.js +3 -43
  255. package/dist/commands/webhook.d.ts +0 -8
  256. package/dist/commands/webhook.js +0 -14
  257. package/dist/commands/workflows.d.ts +0 -8
  258. package/dist/commands/workflows.js +0 -6
  259. package/dist/index.d.ts +0 -25
  260. package/dist/index.js +5 -119
  261. package/dist/lib/account-capabilities.d.ts +0 -34
  262. package/dist/lib/account-capabilities.js +0 -32
  263. package/dist/lib/account-catalog.d.ts +0 -128
  264. package/dist/lib/account-catalog.js +8 -154
  265. package/dist/lib/account-provider-registry.d.ts +0 -14
  266. package/dist/lib/account-provider-registry.js +0 -8
  267. package/dist/lib/account-registry.d.ts +0 -74
  268. package/dist/lib/account-registry.js +14 -189
  269. package/dist/lib/account-schema.d.ts +0 -19
  270. package/dist/lib/account-schema.js +0 -43
  271. package/dist/lib/accounting/account-launch.d.ts +0 -15
  272. package/dist/lib/accounting/account-launch.js +1 -3
  273. package/dist/lib/accounting/account-pool-collect.d.ts +0 -26
  274. package/dist/lib/accounting/account-pool-collect.js +0 -42
  275. package/dist/lib/accounting/account-pool.d.ts +0 -41
  276. package/dist/lib/accounting/account-pool.js +0 -17
  277. package/dist/lib/accounting/capacity.d.ts +0 -32
  278. package/dist/lib/accounting/capacity.js +0 -32
  279. package/dist/lib/accounting/rotate.d.ts +0 -518
  280. package/dist/lib/accounting/rotate.js +4 -598
  281. package/dist/lib/accounting/usage-ingest.d.ts +0 -1
  282. package/dist/lib/accounting/usage-ingest.js +0 -44
  283. package/dist/lib/accounting/usage-sync.d.ts +0 -60
  284. package/dist/lib/accounting/usage-sync.js +4 -51
  285. package/dist/lib/accounting/usage.d.ts +0 -632
  286. package/dist/lib/accounting/usage.js +14 -1055
  287. package/dist/lib/accounts/add.d.ts +0 -60
  288. package/dist/lib/accounts/add.js +0 -127
  289. package/dist/lib/accounts/auth-operation-lock.d.ts +0 -1
  290. package/dist/lib/accounts/auth-operation-lock.js +0 -4
  291. package/dist/lib/accounts/migrate.d.ts +0 -9
  292. package/dist/lib/accounts/migrate.js +3 -42
  293. package/dist/lib/accounts/slots.d.ts +0 -25
  294. package/dist/lib/accounts/slots.js +1 -49
  295. package/dist/lib/acp/client.d.ts +0 -16
  296. package/dist/lib/acp/client.js +0 -29
  297. package/dist/lib/acp/harnesses.d.ts +0 -15
  298. package/dist/lib/acp/harnesses.js +0 -16
  299. package/dist/lib/acp/run.d.ts +0 -8
  300. package/dist/lib/acp/run.js +0 -8
  301. package/dist/lib/actor.d.ts +1 -71
  302. package/dist/lib/actor.js +1 -99
  303. package/dist/lib/add-dir.d.ts +0 -46
  304. package/dist/lib/add-dir.js +1 -70
  305. package/dist/lib/address.d.ts +0 -17
  306. package/dist/lib/address.js +0 -15
  307. package/dist/lib/agent-cli-commands.d.ts +0 -10
  308. package/dist/lib/agent-cli-commands.js +0 -10
  309. package/dist/lib/agent-modes.d.ts +0 -29
  310. package/dist/lib/agent-modes.js +0 -31
  311. package/dist/lib/agent-spec/agents.d.ts +0 -426
  312. package/dist/lib/agent-spec/agents.js +37 -924
  313. package/dist/lib/agent-spec/index.d.ts +0 -5
  314. package/dist/lib/agent-spec/index.js +0 -14
  315. package/dist/lib/agent-spec/materialize.d.ts +0 -10
  316. package/dist/lib/agent-spec/materialize.js +2 -139
  317. package/dist/lib/agent-spec/package-resolve.d.ts +0 -8
  318. package/dist/lib/agent-spec/package-resolve.js +1 -44
  319. package/dist/lib/agent-spec/package-schema.d.ts +0 -2
  320. package/dist/lib/agent-spec/package-schema.js +0 -11
  321. package/dist/lib/agent-spec/package-types.d.ts +0 -27
  322. package/dist/lib/agent-spec/package-types.js +0 -1
  323. package/dist/lib/agent-spec/primitives.d.ts +0 -18
  324. package/dist/lib/agent-spec/primitives.js +0 -27
  325. package/dist/lib/agent-spec/provider.js +0 -2
  326. package/dist/lib/agent-spec/resolve.d.ts +0 -23
  327. package/dist/lib/agent-spec/resolve.js +0 -41
  328. package/dist/lib/agent-spec/types.d.ts +0 -34
  329. package/dist/lib/agent-spec/types.js +0 -6
  330. package/dist/lib/agents.d.ts +0 -1
  331. package/dist/lib/agents.js +0 -1
  332. package/dist/lib/analytics/mix-commands.d.ts +0 -23
  333. package/dist/lib/analytics/mix-commands.js +0 -26
  334. package/dist/lib/analytics/recipes.d.ts +0 -1
  335. package/dist/lib/analytics/recipes.js +5 -10
  336. package/dist/lib/analytics/usage-db.js +4 -6
  337. package/dist/lib/answer-router.d.ts +0 -61
  338. package/dist/lib/answer-router.js +0 -57
  339. package/dist/lib/app-bundle-install.d.ts +0 -13
  340. package/dist/lib/app-bundle-install.js +0 -50
  341. package/dist/lib/artifact-actions.d.ts +0 -15
  342. package/dist/lib/artifact-actions.js +0 -18
  343. package/dist/lib/artifacts-client.d.ts +0 -10
  344. package/dist/lib/artifacts-client.js +0 -17
  345. package/dist/lib/ask-classifier.d.ts +0 -38
  346. package/dist/lib/ask-classifier.js +0 -27
  347. package/dist/lib/audit/log.d.ts +0 -47
  348. package/dist/lib/audit/log.js +1 -59
  349. package/dist/lib/auth-health.d.ts +0 -213
  350. package/dist/lib/auth-health.js +16 -266
  351. package/dist/lib/auth-mint.d.ts +0 -83
  352. package/dist/lib/auth-mint.js +8 -85
  353. package/dist/lib/auto-pull-worker.d.ts +0 -10
  354. package/dist/lib/auto-pull-worker.js +3 -48
  355. package/dist/lib/auto-pull.d.ts +0 -64
  356. package/dist/lib/auto-pull.js +0 -79
  357. package/dist/lib/beta.d.ts +0 -9
  358. package/dist/lib/beta.js +0 -9
  359. package/dist/lib/binary-shadow.d.ts +0 -22
  360. package/dist/lib/binary-shadow.js +4 -34
  361. package/dist/lib/boot-profile.d.ts +0 -10
  362. package/dist/lib/boot-profile.js +1 -31
  363. package/dist/lib/brand.d.ts +0 -20
  364. package/dist/lib/brand.js +0 -50
  365. package/dist/lib/browser/context.d.ts +0 -54
  366. package/dist/lib/browser/context.js +0 -49
  367. package/dist/lib/browser/paths.d.ts +0 -21
  368. package/dist/lib/browser/paths.js +0 -26
  369. package/dist/lib/browser/record.d.ts +0 -34
  370. package/dist/lib/browser/record.js +0 -38
  371. package/dist/lib/browser/sessions-list.d.ts +1 -79
  372. package/dist/lib/browser/sessions-list.js +2 -98
  373. package/dist/lib/browser-client.d.ts +0 -112
  374. package/dist/lib/browser-client.js +1 -90
  375. package/dist/lib/budget/config.d.ts +0 -6
  376. package/dist/lib/budget/config.js +0 -29
  377. package/dist/lib/budget/enforce.d.ts +0 -50
  378. package/dist/lib/budget/enforce.js +0 -27
  379. package/dist/lib/budget/ledger.d.ts +0 -23
  380. package/dist/lib/budget/ledger.js +0 -28
  381. package/dist/lib/budget/live-cloud.d.ts +0 -26
  382. package/dist/lib/budget/live-cloud.js +0 -12
  383. package/dist/lib/budget/live-team.d.ts +0 -17
  384. package/dist/lib/budget/live-team.js +1 -35
  385. package/dist/lib/budget/preflight.d.ts +0 -51
  386. package/dist/lib/budget/preflight.js +0 -36
  387. package/dist/lib/byok-usage.d.ts +0 -20
  388. package/dist/lib/byok-usage.js +1 -24
  389. package/dist/lib/capabilities.d.ts +0 -24
  390. package/dist/lib/capabilities.js +0 -29
  391. package/dist/lib/catchup.d.ts +0 -87
  392. package/dist/lib/catchup.js +1 -81
  393. package/dist/lib/channels/owner-forward.d.ts +0 -70
  394. package/dist/lib/channels/owner-forward.js +1 -43
  395. package/dist/lib/channels/owner-sink.js +0 -21
  396. package/dist/lib/channels/providers/desktop.d.ts +0 -37
  397. package/dist/lib/channels/providers/desktop.js +0 -72
  398. package/dist/lib/channels/providers/index.d.ts +0 -1
  399. package/dist/lib/channels/providers/index.js +2 -6
  400. package/dist/lib/channels/providers/mailbox.js +0 -7
  401. package/dist/lib/channels/providers/openclaw-telegram.js +0 -8
  402. package/dist/lib/channels/providers/rush.d.ts +0 -2
  403. package/dist/lib/channels/providers/rush.js +0 -26
  404. package/dist/lib/channels/providers/session.d.ts +2 -0
  405. package/dist/lib/channels/providers/session.js +26 -0
  406. package/dist/lib/channels/registry.d.ts +0 -27
  407. package/dist/lib/channels/registry.js +0 -10
  408. package/dist/lib/channels/resolve.d.ts +0 -19
  409. package/dist/lib/channels/resolve.js +0 -2
  410. package/dist/lib/channels/send.d.ts +0 -50
  411. package/dist/lib/channels/send.js +0 -25
  412. package/dist/lib/checkpoint.d.ts +0 -36
  413. package/dist/lib/checkpoint.js +0 -28
  414. package/dist/lib/claude-account-token.d.ts +0 -98
  415. package/dist/lib/claude-account-token.js +7 -169
  416. package/dist/lib/claude-statusline.d.ts +0 -41
  417. package/dist/lib/claude-statusline.js +0 -68
  418. package/dist/lib/cli-entry.d.ts +0 -26
  419. package/dist/lib/cli-entry.js +1 -61
  420. package/dist/lib/cli-resources.d.ts +31 -89
  421. package/dist/lib/cli-resources.js +116 -152
  422. package/dist/lib/cloud/antigravity.d.ts +0 -29
  423. package/dist/lib/cloud/antigravity.js +0 -36
  424. package/dist/lib/cloud/codex.d.ts +0 -8
  425. package/dist/lib/cloud/codex.js +0 -41
  426. package/dist/lib/cloud/cursor.d.ts +0 -5
  427. package/dist/lib/cloud/cursor.js +2 -7
  428. package/dist/lib/cloud/dispatch.d.ts +0 -13
  429. package/dist/lib/cloud/dispatch.js +1 -48
  430. package/dist/lib/cloud/factory.d.ts +0 -52
  431. package/dist/lib/cloud/factory.js +3 -67
  432. package/dist/lib/cloud/host.d.ts +0 -39
  433. package/dist/lib/cloud/host.js +5 -48
  434. package/dist/lib/cloud/registry.d.ts +0 -25
  435. package/dist/lib/cloud/registry.js +0 -29
  436. package/dist/lib/cloud/rush.d.ts +0 -47
  437. package/dist/lib/cloud/rush.js +1 -82
  438. package/dist/lib/cloud/session-index.d.ts +0 -27
  439. package/dist/lib/cloud/session-index.js +1 -32
  440. package/dist/lib/cloud/store.d.ts +0 -18
  441. package/dist/lib/cloud/store.js +0 -28
  442. package/dist/lib/cloud/stream.d.ts +0 -14
  443. package/dist/lib/cloud/stream.js +0 -25
  444. package/dist/lib/cloud/types.d.ts +0 -168
  445. package/dist/lib/cloud/types.js +0 -46
  446. package/dist/lib/cloudflare/creds.d.ts +0 -2
  447. package/dist/lib/cloudflare/creds.js +0 -14
  448. package/dist/lib/cloudflare/provision.d.ts +0 -8
  449. package/dist/lib/cloudflare/provision.js +1 -19
  450. package/dist/lib/codex-home.d.ts +0 -60
  451. package/dist/lib/codex-home.js +2 -72
  452. package/dist/lib/codex-policy.d.ts +0 -10
  453. package/dist/lib/codex-policy.js +0 -13
  454. package/dist/lib/command-skills.d.ts +0 -10
  455. package/dist/lib/command-skills.js +0 -10
  456. package/dist/lib/commands.d.ts +0 -74
  457. package/dist/lib/commands.js +0 -112
  458. package/dist/lib/comms-render.d.ts +0 -5
  459. package/dist/lib/comms-render.js +0 -5
  460. package/dist/lib/computer/context.d.ts +0 -23
  461. package/dist/lib/computer/context.js +0 -14
  462. package/dist/lib/computer/policy.d.ts +0 -20
  463. package/dist/lib/computer/policy.js +0 -53
  464. package/dist/lib/computer/record.d.ts +0 -33
  465. package/dist/lib/computer/record.js +1 -48
  466. package/dist/lib/computer/sessions-list.d.ts +1 -128
  467. package/dist/lib/computer/sessions-list.js +6 -165
  468. package/dist/lib/computer-client.d.ts +0 -106
  469. package/dist/lib/computer-client.js +5 -86
  470. package/dist/lib/concurrency.d.ts +0 -14
  471. package/dist/lib/concurrency.js +0 -3
  472. package/dist/lib/config-drift.d.ts +0 -31
  473. package/dist/lib/config-drift.js +0 -32
  474. package/dist/lib/config-keys.d.ts +1 -65
  475. package/dist/lib/config-keys.js +6 -52
  476. package/dist/lib/config-transfer.d.ts +0 -14
  477. package/dist/lib/config-transfer.js +0 -26
  478. package/dist/lib/convert.d.ts +0 -17
  479. package/dist/lib/convert.js +0 -18
  480. package/dist/lib/crabbox/cli.d.ts +0 -156
  481. package/dist/lib/crabbox/cli.js +1 -188
  482. package/dist/lib/crabbox/config.d.ts +0 -18
  483. package/dist/lib/crabbox/config.js +1 -19
  484. package/dist/lib/crabbox/lease.d.ts +0 -93
  485. package/dist/lib/crabbox/lease.js +4 -148
  486. package/dist/lib/crabbox/progress.d.ts +0 -56
  487. package/dist/lib/crabbox/progress.js +2 -49
  488. package/dist/lib/crabbox/runtimes.d.ts +0 -94
  489. package/dist/lib/crabbox/runtimes.js +1 -111
  490. package/dist/lib/crabbox/setup-copy.d.ts +0 -64
  491. package/dist/lib/crabbox/setup-copy.js +1 -53
  492. package/dist/lib/daemon/account-state-daemon-service.d.ts +0 -48
  493. package/dist/lib/daemon/account-state-daemon-service.js +2 -63
  494. package/dist/lib/daemon/attention-notify-service.d.ts +0 -12
  495. package/dist/lib/daemon/attention-notify-service.js +1 -24
  496. package/dist/lib/daemon/auth-sync-service.d.ts +0 -28
  497. package/dist/lib/daemon/auth-sync-service.js +0 -56
  498. package/dist/lib/daemon/catchup-service.d.ts +0 -34
  499. package/dist/lib/daemon/catchup-service.js +0 -30
  500. package/dist/lib/daemon/daemon.d.ts +0 -374
  501. package/dist/lib/daemon/daemon.js +44 -1049
  502. package/dist/lib/daemon/daemon.test-fixture.d.ts +0 -19
  503. package/dist/lib/daemon/daemon.test-fixture.js +1 -24
  504. package/dist/lib/daemon/device-probe-service.d.ts +0 -16
  505. package/dist/lib/daemon/device-probe-service.js +0 -20
  506. package/dist/lib/daemon/feed-stream-service.d.ts +0 -15
  507. package/dist/lib/daemon/feed-stream-service.js +0 -20
  508. package/dist/lib/daemon/harness-update-service.d.ts +2 -61
  509. package/dist/lib/daemon/harness-update-service.js +6 -86
  510. package/dist/lib/daemon/heartbeat-service.d.ts +0 -1
  511. package/dist/lib/daemon/heartbeat-service.js +0 -1
  512. package/dist/lib/daemon/leaked-daemons.d.ts +0 -46
  513. package/dist/lib/daemon/leaked-daemons.js +2 -78
  514. package/dist/lib/daemon/monitor-engine-service.d.ts +0 -13
  515. package/dist/lib/daemon/monitor-engine-service.js +3 -15
  516. package/dist/lib/daemon/runner.d.ts +0 -194
  517. package/dist/lib/daemon/runner.js +39 -760
  518. package/dist/lib/daemon/self-heal-service.d.ts +18 -17
  519. package/dist/lib/daemon/self-heal-service.js +83 -37
  520. package/dist/lib/daemon/self-update-service.d.ts +1 -131
  521. package/dist/lib/daemon/self-update-service.js +26 -189
  522. package/dist/lib/daemon/service.d.ts +0 -73
  523. package/dist/lib/daemon/service.js +0 -34
  524. package/dist/lib/daemon/session-index-service.d.ts +0 -12
  525. package/dist/lib/daemon/session-index-service.js +0 -23
  526. package/dist/lib/daemon/session-state-service.d.ts +0 -8
  527. package/dist/lib/daemon/session-state-service.js +0 -8
  528. package/dist/lib/daemon/session-summarizer-service.d.ts +0 -14
  529. package/dist/lib/daemon/session-summarizer-service.js +1 -19
  530. package/dist/lib/daemon/session-title-service.d.ts +0 -25
  531. package/dist/lib/daemon/session-title-service.js +0 -32
  532. package/dist/lib/daemon/state-dir-check-service.d.ts +0 -24
  533. package/dist/lib/daemon/state-dir-check-service.js +0 -29
  534. package/dist/lib/daemon/supervisor.d.ts +0 -112
  535. package/dist/lib/daemon/supervisor.js +4 -147
  536. package/dist/lib/daemon/testdata/process-view-daemon.js +0 -2
  537. package/dist/lib/daemon/testdata/process-view-start.js +0 -5
  538. package/dist/lib/daemon/tmux-reap-service.d.ts +0 -1
  539. package/dist/lib/daemon/tmux-reap-service.js +0 -1
  540. package/dist/lib/daemon/usage-sync-service.d.ts +0 -23
  541. package/dist/lib/daemon/usage-sync-service.js +0 -26
  542. package/dist/lib/daemon/watchdog-service.d.ts +0 -9
  543. package/dist/lib/daemon/watchdog-service.js +0 -13
  544. package/dist/lib/daemon/webhook-receiver-service.d.ts +0 -1
  545. package/dist/lib/daemon/webhook-receiver-service.js +0 -1
  546. package/dist/lib/daemon-health.d.ts +0 -55
  547. package/dist/lib/daemon-health.js +4 -77
  548. package/dist/lib/daemon-services.d.ts +0 -36
  549. package/dist/lib/daemon-services.js +0 -45
  550. package/dist/lib/daemon-ticks.d.ts +0 -126
  551. package/dist/lib/daemon-ticks.js +1 -156
  552. package/dist/lib/daemon-webhooks.d.ts +0 -57
  553. package/dist/lib/daemon-webhooks.js +2 -54
  554. package/dist/lib/deeplink/register.d.ts +0 -15
  555. package/dist/lib/deeplink/register.js +0 -60
  556. package/dist/lib/deeplink/url.d.ts +0 -24
  557. package/dist/lib/deeplink/url.js +1 -33
  558. package/dist/lib/device-config.d.ts +1 -192
  559. package/dist/lib/device-config.js +86 -240
  560. package/dist/lib/devices/config-migration.d.ts +0 -43
  561. package/dist/lib/devices/config-migration.js +7 -127
  562. package/dist/lib/devices/connect.d.ts +0 -168
  563. package/dist/lib/devices/connect.js +6 -254
  564. package/dist/lib/devices/device-docs.d.ts +0 -24
  565. package/dist/lib/devices/device-docs.js +0 -46
  566. package/dist/lib/devices/discovery-policy.d.ts +0 -30
  567. package/dist/lib/devices/discovery-policy.js +3 -34
  568. package/dist/lib/devices/doctor-findings.d.ts +0 -109
  569. package/dist/lib/devices/doctor-findings.js +30 -326
  570. package/dist/lib/devices/doctor-overview-cache.d.ts +0 -33
  571. package/dist/lib/devices/doctor-overview-cache.js +0 -81
  572. package/dist/lib/devices/fleet-divergence.d.ts +0 -89
  573. package/dist/lib/devices/fleet-divergence.js +1 -60
  574. package/dist/lib/devices/fleet-inventory.d.ts +0 -27
  575. package/dist/lib/devices/fleet-inventory.js +0 -38
  576. package/dist/lib/devices/fleet.d.ts +0 -95
  577. package/dist/lib/devices/fleet.js +0 -79
  578. package/dist/lib/devices/harness-inventory.d.ts +0 -75
  579. package/dist/lib/devices/harness-inventory.js +0 -101
  580. package/dist/lib/devices/health-report.d.ts +0 -37
  581. package/dist/lib/devices/health-report.js +0 -73
  582. package/dist/lib/devices/health.d.ts +0 -71
  583. package/dist/lib/devices/health.js +2 -82
  584. package/dist/lib/devices/interactive-host.d.ts +0 -10
  585. package/dist/lib/devices/interactive-host.js +0 -34
  586. package/dist/lib/devices/known-hosts.d.ts +0 -45
  587. package/dist/lib/devices/known-hosts.js +0 -77
  588. package/dist/lib/devices/pending.d.ts +0 -31
  589. package/dist/lib/devices/pending.js +7 -67
  590. package/dist/lib/devices/pool.d.ts +0 -36
  591. package/dist/lib/devices/pool.js +0 -30
  592. package/dist/lib/devices/reachability.d.ts +0 -25
  593. package/dist/lib/devices/reachability.js +0 -14
  594. package/dist/lib/devices/registry.d.ts +0 -141
  595. package/dist/lib/devices/registry.js +4 -151
  596. package/dist/lib/devices/resolve-profile.d.ts +0 -18
  597. package/dist/lib/devices/resolve-profile.js +0 -18
  598. package/dist/lib/devices/resolve-target.d.ts +0 -20
  599. package/dist/lib/devices/resolve-target.js +1 -51
  600. package/dist/lib/devices/rollout-verify.d.ts +1 -81
  601. package/dist/lib/devices/rollout-verify.js +0 -77
  602. package/dist/lib/devices/self-host.d.ts +0 -7
  603. package/dist/lib/devices/self-host.js +1 -29
  604. package/dist/lib/devices/ssh-config.d.ts +0 -18
  605. package/dist/lib/devices/ssh-config.js +0 -9
  606. package/dist/lib/devices/stats-cache.d.ts +0 -48
  607. package/dist/lib/devices/stats-cache.js +0 -80
  608. package/dist/lib/devices/sync.d.ts +0 -97
  609. package/dist/lib/devices/sync.js +0 -88
  610. package/dist/lib/devices/tailscale.d.ts +0 -18
  611. package/dist/lib/devices/tailscale.js +1 -38
  612. package/dist/lib/devices/terminfo.d.ts +0 -27
  613. package/dist/lib/devices/terminfo.js +2 -64
  614. package/dist/lib/devices/worker-pick.d.ts +0 -15
  615. package/dist/lib/devices/worker-pick.js +0 -48
  616. package/dist/lib/diff-text.d.ts +0 -18
  617. package/dist/lib/diff-text.js +0 -15
  618. package/dist/lib/doctor-diff.d.ts +0 -79
  619. package/dist/lib/doctor-diff.js +2 -181
  620. package/dist/lib/drift-sync.d.ts +0 -29
  621. package/dist/lib/drift-sync.js +0 -40
  622. package/dist/lib/drift.d.ts +0 -43
  623. package/dist/lib/drift.js +0 -31
  624. package/dist/lib/event-families.d.ts +0 -17
  625. package/dist/lib/event-families.js +0 -33
  626. package/dist/lib/event-provenance.d.ts +0 -4
  627. package/dist/lib/event-provenance.js +0 -5
  628. package/dist/lib/event-stream.d.ts +0 -29
  629. package/dist/lib/event-stream.js +0 -36
  630. package/dist/lib/events-ingest.d.ts +0 -27
  631. package/dist/lib/events-ingest.js +0 -54
  632. package/dist/lib/exec-account-home.d.ts +0 -24
  633. package/dist/lib/exec-account-home.js +0 -41
  634. package/dist/lib/exec-bounded.d.ts +1 -37
  635. package/dist/lib/exec-bounded.js +10 -46
  636. package/dist/lib/exec.d.ts +3 -583
  637. package/dist/lib/exec.js +18 -1025
  638. package/dist/lib/factory/snapshot.js +1 -15
  639. package/dist/lib/feed/activity-stream.d.ts +0 -27
  640. package/dist/lib/feed/activity-stream.js +4 -80
  641. package/dist/lib/feed/activity.d.ts +1 -243
  642. package/dist/lib/feed/activity.js +8 -273
  643. package/dist/lib/feed/answer.d.ts +0 -103
  644. package/dist/lib/feed/answer.js +0 -267
  645. package/dist/lib/feed/attention.d.ts +0 -56
  646. package/dist/lib/feed/attention.js +0 -161
  647. package/dist/lib/feed/envelope.d.ts +2 -17
  648. package/dist/lib/feed/envelope.js +0 -14
  649. package/dist/lib/feed/events.d.ts +0 -118
  650. package/dist/lib/feed/events.js +13 -213
  651. package/dist/lib/feed/feed.d.ts +1 -250
  652. package/dist/lib/feed/feed.js +24 -334
  653. package/dist/lib/feed/hub-server.d.ts +0 -100
  654. package/dist/lib/feed/hub-server.js +1 -191
  655. package/dist/lib/feed/hub.d.ts +0 -53
  656. package/dist/lib/feed/hub.js +0 -89
  657. package/dist/lib/feed/pr-status.d.ts +1 -19
  658. package/dist/lib/feed/pr-status.js +0 -18
  659. package/dist/lib/feed/tool-activity.d.ts +0 -59
  660. package/dist/lib/feed/tool-activity.js +1 -119
  661. package/dist/lib/feed/tools.d.ts +0 -100
  662. package/dist/lib/feed/tools.js +0 -89
  663. package/dist/lib/feed/watch.d.ts +0 -33
  664. package/dist/lib/feed/watch.js +2 -94
  665. package/dist/lib/feed-broadcast.d.ts +0 -148
  666. package/dist/lib/feed-broadcast.js +1 -283
  667. package/dist/lib/feed-outcome.d.ts +0 -50
  668. package/dist/lib/feed-outcome.js +1 -67
  669. package/dist/lib/feed-policy.d.ts +0 -6
  670. package/dist/lib/feed-policy.js +1 -27
  671. package/dist/lib/feed-post.d.ts +0 -61
  672. package/dist/lib/feed-post.js +4 -61
  673. package/dist/lib/feed-ranking.d.ts +1 -1
  674. package/dist/lib/fleet/apply.d.ts +0 -64
  675. package/dist/lib/fleet/apply.js +0 -125
  676. package/dist/lib/fleet/auth-sync.d.ts +0 -48
  677. package/dist/lib/fleet/auth-sync.js +4 -49
  678. package/dist/lib/fleet/capture.d.ts +0 -26
  679. package/dist/lib/fleet/capture.js +1 -36
  680. package/dist/lib/fleet/manifest.d.ts +0 -38
  681. package/dist/lib/fleet/manifest.js +0 -40
  682. package/dist/lib/fleet/types.d.ts +1 -138
  683. package/dist/lib/fleet/types.js +0 -12
  684. package/dist/lib/fleet-cache.d.ts +0 -12
  685. package/dist/lib/fleet-cache.js +0 -24
  686. package/dist/lib/fleet-shared-state.d.ts +6 -59
  687. package/dist/lib/fleet-shared-state.js +5 -51
  688. package/dist/lib/fleet-status.d.ts +0 -27
  689. package/dist/lib/fleet-status.js +0 -48
  690. package/dist/lib/format.d.ts +0 -74
  691. package/dist/lib/format.js +3 -77
  692. package/dist/lib/friction-heuristics.d.ts +0 -20
  693. package/dist/lib/friction-heuristics.js +0 -8
  694. package/dist/lib/fs-atomic.d.ts +0 -51
  695. package/dist/lib/fs-atomic.js +8 -66
  696. package/dist/lib/fs-walk.d.ts +0 -13
  697. package/dist/lib/fs-walk.js +0 -22
  698. package/dist/lib/fuzzy.d.ts +0 -29
  699. package/dist/lib/fuzzy.js +0 -31
  700. package/dist/lib/gemini-settings.js +0 -12
  701. package/dist/lib/git.d.ts +0 -366
  702. package/dist/lib/git.js +7 -574
  703. package/dist/lib/github/ci-failure.d.ts +30 -0
  704. package/dist/lib/github/ci-failure.js +95 -0
  705. package/dist/lib/github/gh-overload.d.ts +0 -38
  706. package/dist/lib/github/gh-overload.js +3 -55
  707. package/dist/lib/github/pr-mergeable.d.ts +3 -34
  708. package/dist/lib/github/pr-mergeable.js +2 -42
  709. package/dist/lib/github/pr-verdict.d.ts +0 -44
  710. package/dist/lib/github/pr-verdict.js +0 -36
  711. package/dist/lib/github/project-prs.d.ts +135 -105
  712. package/dist/lib/github/project-prs.js +530 -170
  713. package/dist/lib/github/release-drift.d.ts +45 -0
  714. package/dist/lib/github/release-drift.js +91 -0
  715. package/dist/lib/github/rest.d.ts +0 -50
  716. package/dist/lib/github/rest.js +0 -49
  717. package/dist/lib/github/viewer.d.ts +27 -0
  718. package/dist/lib/github/viewer.js +101 -0
  719. package/dist/lib/goose-commands.d.ts +0 -29
  720. package/dist/lib/goose-commands.js +3 -48
  721. package/dist/lib/harness/adapter.d.ts +0 -151
  722. package/dist/lib/harness/adapter.js +0 -41
  723. package/dist/lib/harness/adapters/claude.d.ts +0 -8
  724. package/dist/lib/harness/adapters/claude.js +0 -89
  725. package/dist/lib/harness/adapters/codex.js +0 -18
  726. package/dist/lib/harness/adapters/copilot.js +0 -3
  727. package/dist/lib/harness/adapters/cursor.js +0 -16
  728. package/dist/lib/harness/adapters/droid.js +0 -3
  729. package/dist/lib/harness/adapters/kimi.js +0 -19
  730. package/dist/lib/harness/adapters/muse.js +0 -9
  731. package/dist/lib/harness/adapters/opencode.js +0 -2
  732. package/dist/lib/harness/exec-config-version.d.ts +0 -2
  733. package/dist/lib/harness/exec-config-version.js +0 -13
  734. package/dist/lib/harness/index.js +0 -10
  735. package/dist/lib/harness-auth-capabilities.d.ts +0 -26
  736. package/dist/lib/harness-auth-capabilities.js +0 -18
  737. package/dist/lib/harness-connection-test.d.ts +0 -27
  738. package/dist/lib/harness-connection-test.js +2 -20
  739. package/dist/lib/heal.d.ts +0 -45
  740. package/dist/lib/heal.js +2 -82
  741. package/dist/lib/help.d.ts +0 -32
  742. package/dist/lib/help.js +0 -41
  743. package/dist/lib/helper-download.d.ts +0 -85
  744. package/dist/lib/helper-download.js +0 -95
  745. package/dist/lib/helper-versions.d.ts +0 -51
  746. package/dist/lib/helper-versions.js +1 -45
  747. package/dist/lib/hooks/cache.d.ts +0 -40
  748. package/dist/lib/hooks/cache.js +8 -122
  749. package/dist/lib/hooks/install.d.ts +0 -253
  750. package/dist/lib/hooks/install.js +49 -822
  751. package/dist/lib/hooks/match.d.ts +0 -24
  752. package/dist/lib/hooks/match.js +0 -31
  753. package/dist/lib/hooks/profile.d.ts +0 -21
  754. package/dist/lib/hooks/profile.js +0 -28
  755. package/dist/lib/hosts/credential-transport.d.ts +0 -6
  756. package/dist/lib/hosts/credential-transport.js +0 -17
  757. package/dist/lib/hosts/credentials.d.ts +0 -35
  758. package/dist/lib/hosts/credentials.js +0 -38
  759. package/dist/lib/hosts/dispatch.d.ts +0 -140
  760. package/dist/lib/hosts/dispatch.js +0 -176
  761. package/dist/lib/hosts/logs.d.ts +0 -25
  762. package/dist/lib/hosts/logs.js +1 -51
  763. package/dist/lib/hosts/option.d.ts +0 -12
  764. package/dist/lib/hosts/option.js +0 -12
  765. package/dist/lib/hosts/passthrough.d.ts +0 -129
  766. package/dist/lib/hosts/passthrough.js +12 -249
  767. package/dist/lib/hosts/progress.d.ts +0 -90
  768. package/dist/lib/hosts/progress.js +5 -115
  769. package/dist/lib/hosts/providers/devices.d.ts +0 -19
  770. package/dist/lib/hosts/providers/devices.js +1 -34
  771. package/dist/lib/hosts/providers/local.d.ts +0 -14
  772. package/dist/lib/hosts/providers/local.js +0 -22
  773. package/dist/lib/hosts/ready.d.ts +0 -99
  774. package/dist/lib/hosts/ready.js +0 -101
  775. package/dist/lib/hosts/reconcile.d.ts +0 -38
  776. package/dist/lib/hosts/reconcile.js +1 -50
  777. package/dist/lib/hosts/reconnect.d.ts +0 -75
  778. package/dist/lib/hosts/reconnect.js +0 -98
  779. package/dist/lib/hosts/registry.d.ts +0 -74
  780. package/dist/lib/hosts/registry.js +0 -110
  781. package/dist/lib/hosts/remote-cmd.d.ts +1 -228
  782. package/dist/lib/hosts/remote-cmd.js +19 -294
  783. package/dist/lib/hosts/remote-cmd.test-fixture.d.ts +0 -1
  784. package/dist/lib/hosts/remote-cmd.test-fixture.js +0 -12
  785. package/dist/lib/hosts/remote-os.d.ts +0 -19
  786. package/dist/lib/hosts/remote-os.js +0 -22
  787. package/dist/lib/hosts/remote-session-id.d.ts +0 -22
  788. package/dist/lib/hosts/remote-session-id.js +0 -24
  789. package/dist/lib/hosts/routing-flag.d.ts +0 -21
  790. package/dist/lib/hosts/routing-flag.js +0 -21
  791. package/dist/lib/hosts/run-target.d.ts +0 -53
  792. package/dist/lib/hosts/run-target.js +0 -56
  793. package/dist/lib/hosts/session-index.d.ts +1 -53
  794. package/dist/lib/hosts/session-index.js +2 -59
  795. package/dist/lib/hosts/session-marker.d.ts +0 -31
  796. package/dist/lib/hosts/session-marker.js +0 -32
  797. package/dist/lib/hosts/ssh-config.d.ts +0 -25
  798. package/dist/lib/hosts/ssh-config.js +1 -32
  799. package/dist/lib/hosts/tasks.d.ts +0 -54
  800. package/dist/lib/hosts/tasks.js +0 -35
  801. package/dist/lib/hosts/types.d.ts +0 -39
  802. package/dist/lib/hosts/types.js +0 -22
  803. package/dist/lib/humans.d.ts +0 -21
  804. package/dist/lib/humans.js +0 -30
  805. package/dist/lib/identity/client.d.ts +1 -35
  806. package/dist/lib/identity/client.js +3 -29
  807. package/dist/lib/identity/index.d.ts +3 -27
  808. package/dist/lib/identity/index.js +8 -24
  809. package/dist/lib/import.d.ts +0 -104
  810. package/dist/lib/import.js +1 -137
  811. package/dist/lib/installations/active-check.d.ts +0 -53
  812. package/dist/lib/installations/active-check.js +0 -49
  813. package/dist/lib/installations/index.d.ts +0 -9
  814. package/dist/lib/installations/index.js +0 -9
  815. package/dist/lib/installations/installation-lock.js +0 -8
  816. package/dist/lib/installations/launch-gate.d.ts +0 -56
  817. package/dist/lib/installations/launch-gate.js +0 -83
  818. package/dist/lib/installations/migrate.d.ts +0 -100
  819. package/dist/lib/installations/migrate.js +105 -572
  820. package/dist/lib/installations/native-command.d.ts +0 -1
  821. package/dist/lib/installations/native-command.js +0 -6
  822. package/dist/lib/installations/resolve.d.ts +0 -24
  823. package/dist/lib/installations/resolve.js +0 -24
  824. package/dist/lib/installations/shims.d.ts +0 -395
  825. package/dist/lib/installations/shims.js +30 -957
  826. package/dist/lib/installations/store.d.ts +0 -199
  827. package/dist/lib/installations/store.js +1 -297
  828. package/dist/lib/installations/strategies.d.ts +0 -44
  829. package/dist/lib/installations/strategies.js +0 -87
  830. package/dist/lib/installations/types.d.ts +1 -67
  831. package/dist/lib/installations/types.js +0 -6
  832. package/dist/lib/installations/update-cancellation.d.ts +0 -74
  833. package/dist/lib/installations/update-cancellation.js +0 -74
  834. package/dist/lib/installations/update-policy.d.ts +0 -57
  835. package/dist/lib/installations/update-policy.js +0 -62
  836. package/dist/lib/installations/update-runtime.d.ts +0 -88
  837. package/dist/lib/installations/update-runtime.js +1 -127
  838. package/dist/lib/installations/update.d.ts +0 -53
  839. package/dist/lib/installations/update.js +0 -95
  840. package/dist/lib/installations/versions.d.ts +0 -310
  841. package/dist/lib/installations/versions.js +14 -837
  842. package/dist/lib/isolation-boundary-report.d.ts +0 -7
  843. package/dist/lib/isolation-boundary-report.js +0 -7
  844. package/dist/lib/launch-identity.d.ts +0 -8
  845. package/dist/lib/launch-identity.js +0 -8
  846. package/dist/lib/linear-autoclose.d.ts +0 -25
  847. package/dist/lib/linear-autoclose.js +0 -19
  848. package/dist/lib/linear-cache.d.ts +0 -57
  849. package/dist/lib/linear-cache.js +1 -81
  850. package/dist/lib/linear-project-counts.d.ts +0 -83
  851. package/dist/lib/linear-project-counts.js +2 -64
  852. package/dist/lib/linear-projects.d.ts +0 -62
  853. package/dist/lib/linear-projects.js +0 -85
  854. package/dist/lib/linear-rate-limit.d.ts +0 -21
  855. package/dist/lib/linear-rate-limit.js +1 -93
  856. package/dist/lib/linux-userns.d.ts +1 -42
  857. package/dist/lib/linux-userns.js +0 -47
  858. package/dist/lib/lock-compromise.d.ts +0 -7
  859. package/dist/lib/lock-compromise.js +0 -7
  860. package/dist/lib/log-follow.d.ts +0 -2
  861. package/dist/lib/log-follow.js +5 -15
  862. package/dist/lib/loop.d.ts +0 -106
  863. package/dist/lib/loop.js +0 -135
  864. package/dist/lib/machine-id.d.ts +0 -19
  865. package/dist/lib/machine-id.js +0 -19
  866. package/dist/lib/mailbox-gc.d.ts +0 -7
  867. package/dist/lib/mailbox-gc.js +0 -25
  868. package/dist/lib/mailbox-target.d.ts +0 -31
  869. package/dist/lib/mailbox-target.js +0 -27
  870. package/dist/lib/mailbox.d.ts +0 -77
  871. package/dist/lib/mailbox.js +5 -105
  872. package/dist/lib/manifest.d.ts +0 -4
  873. package/dist/lib/manifest.js +0 -36
  874. package/dist/lib/markdown.d.ts +0 -3
  875. package/dist/lib/markdown.js +0 -9
  876. package/dist/lib/mcp-registry.d.ts +1 -50
  877. package/dist/lib/mcp-registry.js +0 -64
  878. package/dist/lib/mcp.d.ts +0 -115
  879. package/dist/lib/mcp.js +3 -199
  880. package/dist/lib/memory-cache.d.ts +0 -11
  881. package/dist/lib/memory-cache.js +0 -9
  882. package/dist/lib/memory.d.ts +0 -52
  883. package/dist/lib/memory.js +12 -74
  884. package/dist/lib/menubar/download-menubar.d.ts +0 -35
  885. package/dist/lib/menubar/download-menubar.js +0 -38
  886. package/dist/lib/menubar/install-menubar.d.ts +0 -405
  887. package/dist/lib/menubar/install-menubar.js +25 -667
  888. package/dist/lib/menubar/migrate-prefs.d.ts +0 -47
  889. package/dist/lib/menubar/migrate-prefs.js +1 -70
  890. package/dist/lib/menubar/notify-desktop.d.ts +0 -82
  891. package/dist/lib/menubar/notify-desktop.js +0 -68
  892. package/dist/lib/menubar/resolve-version.d.ts +0 -41
  893. package/dist/lib/menubar/resolve-version.js +2 -44
  894. package/dist/lib/menubar/snapshot.d.ts +13 -66
  895. package/dist/lib/menubar/snapshot.js +45 -39
  896. package/dist/lib/merged-resources.d.ts +0 -10
  897. package/dist/lib/merged-resources.js +0 -10
  898. package/dist/lib/migrate-fold.d.ts +0 -31
  899. package/dist/lib/migrate-fold.js +6 -38
  900. package/dist/lib/model-tier-overrides.d.ts +0 -30
  901. package/dist/lib/model-tier-overrides.js +0 -14
  902. package/dist/lib/model-tiers.d.ts +0 -43
  903. package/dist/lib/model-tiers.js +5 -78
  904. package/dist/lib/models.d.ts +0 -145
  905. package/dist/lib/models.js +3 -333
  906. package/dist/lib/monitors/config.d.ts +0 -187
  907. package/dist/lib/monitors/config.js +4 -101
  908. package/dist/lib/monitors/dispatch.d.ts +0 -22
  909. package/dist/lib/monitors/dispatch.js +0 -35
  910. package/dist/lib/monitors/engine.d.ts +1 -53
  911. package/dist/lib/monitors/engine.js +17 -106
  912. package/dist/lib/monitors/fingerprint.d.ts +0 -43
  913. package/dist/lib/monitors/fingerprint.js +0 -57
  914. package/dist/lib/monitors/pid-watch.d.ts +0 -31
  915. package/dist/lib/monitors/pid-watch.js +0 -31
  916. package/dist/lib/monitors/remote.d.ts +0 -52
  917. package/dist/lib/monitors/remote.js +0 -42
  918. package/dist/lib/monitors/sources/command.d.ts +2 -9
  919. package/dist/lib/monitors/sources/command.js +13 -34
  920. package/dist/lib/monitors/sources/device.d.ts +0 -10
  921. package/dist/lib/monitors/sources/device.js +0 -14
  922. package/dist/lib/monitors/sources/failure.d.ts +0 -27
  923. package/dist/lib/monitors/sources/failure.js +0 -27
  924. package/dist/lib/monitors/sources/file.d.ts +0 -10
  925. package/dist/lib/monitors/sources/file.js +0 -11
  926. package/dist/lib/monitors/sources/http.d.ts +0 -7
  927. package/dist/lib/monitors/sources/http.js +0 -9
  928. package/dist/lib/monitors/sources/index.d.ts +0 -9
  929. package/dist/lib/monitors/sources/index.js +0 -9
  930. package/dist/lib/monitors/sources/poll.d.ts +0 -8
  931. package/dist/lib/monitors/sources/poll.js +0 -8
  932. package/dist/lib/monitors/sources/types.d.ts +0 -18
  933. package/dist/lib/monitors/sources/types.js +0 -8
  934. package/dist/lib/monitors/sources/webhook.d.ts +0 -7
  935. package/dist/lib/monitors/sources/webhook.js +0 -7
  936. package/dist/lib/monitors/sources/ws.d.ts +0 -10
  937. package/dist/lib/monitors/sources/ws.js +3 -13
  938. package/dist/lib/monitors/state.d.ts +0 -132
  939. package/dist/lib/monitors/state.js +2 -86
  940. package/dist/lib/native-accounts.d.ts +0 -32
  941. package/dist/lib/native-accounts.js +0 -17
  942. package/dist/lib/net-close.d.ts +0 -9
  943. package/dist/lib/net-close.js +0 -5
  944. package/dist/lib/notify.d.ts +0 -47
  945. package/dist/lib/notify.js +0 -30
  946. package/dist/lib/onepassword.d.ts +0 -14
  947. package/dist/lib/onepassword.js +0 -12
  948. package/dist/lib/open-url.d.ts +0 -38
  949. package/dist/lib/open-url.js +1 -69
  950. package/dist/lib/openclaw-keychain.js +2 -7
  951. package/dist/lib/operator.d.ts +0 -9
  952. package/dist/lib/operator.js +0 -34
  953. package/dist/lib/origin-machine.d.ts +0 -16
  954. package/dist/lib/origin-machine.js +0 -16
  955. package/dist/lib/output/git-output.d.ts +0 -31
  956. package/dist/lib/output/git-output.js +4 -43
  957. package/dist/lib/overdue.d.ts +0 -35
  958. package/dist/lib/overdue.js +0 -60
  959. package/dist/lib/owner-message.d.ts +0 -20
  960. package/dist/lib/owner-message.js +1 -40
  961. package/dist/lib/packages/output-home.d.ts +0 -28
  962. package/dist/lib/packages/output-home.js +0 -114
  963. package/dist/lib/paths.d.ts +0 -26
  964. package/dist/lib/paths.js +1 -27
  965. package/dist/lib/percentile.d.ts +0 -11
  966. package/dist/lib/percentile.js +0 -11
  967. package/dist/lib/perf/db.d.ts +0 -16
  968. package/dist/lib/perf/db.js +3 -32
  969. package/dist/lib/perf/spool.d.ts +0 -12
  970. package/dist/lib/perf/spool.js +0 -13
  971. package/dist/lib/perf/types.d.ts +0 -26
  972. package/dist/lib/perf/types.js +0 -1
  973. package/dist/lib/permissions-registry.d.ts +0 -48
  974. package/dist/lib/permissions-registry.js +0 -108
  975. package/dist/lib/permissions.d.ts +0 -215
  976. package/dist/lib/permissions.js +4 -407
  977. package/dist/lib/picker.d.ts +0 -124
  978. package/dist/lib/picker.js +0 -140
  979. package/dist/lib/placement.d.ts +0 -57
  980. package/dist/lib/placement.js +0 -47
  981. package/dist/lib/platform/exec.d.ts +0 -73
  982. package/dist/lib/platform/exec.js +0 -80
  983. package/dist/lib/platform/index.d.ts +0 -14
  984. package/dist/lib/platform/index.js +0 -14
  985. package/dist/lib/platform/ipc.d.ts +0 -10
  986. package/dist/lib/platform/ipc.js +0 -13
  987. package/dist/lib/platform/links.d.ts +0 -14
  988. package/dist/lib/platform/links.js +0 -25
  989. package/dist/lib/platform/paths.d.ts +0 -48
  990. package/dist/lib/platform/paths.js +0 -52
  991. package/dist/lib/platform/posixpath.d.ts +0 -18
  992. package/dist/lib/platform/posixpath.js +0 -62
  993. package/dist/lib/platform/process.d.ts +0 -67
  994. package/dist/lib/platform/process.js +5 -99
  995. package/dist/lib/platform/winpath.d.ts +0 -50
  996. package/dist/lib/platform/winpath.js +0 -81
  997. package/dist/lib/plugins/plugin-marketplace.d.ts +0 -165
  998. package/dist/lib/plugins/plugin-marketplace.js +10 -238
  999. package/dist/lib/plugins/plugins.d.ts +0 -238
  1000. package/dist/lib/plugins/plugins.js +20 -454
  1001. package/dist/lib/plugins/skills.d.ts +0 -86
  1002. package/dist/lib/plugins/skills.js +1 -139
  1003. package/dist/lib/pr-land-detach.d.ts +0 -17
  1004. package/dist/lib/pr-land-detach.js +0 -30
  1005. package/dist/lib/pricing/cost.d.ts +0 -29
  1006. package/dist/lib/pricing/cost.js +0 -38
  1007. package/dist/lib/pricing/index.d.ts +0 -6
  1008. package/dist/lib/pricing/index.js +0 -6
  1009. package/dist/lib/pricing/table.d.ts +0 -8
  1010. package/dist/lib/pricing/table.js +3 -56
  1011. package/dist/lib/probe.d.ts +0 -5
  1012. package/dist/lib/probe.js +0 -40
  1013. package/dist/lib/profiles-presets.d.ts +0 -20
  1014. package/dist/lib/profiles-presets.js +1 -36
  1015. package/dist/lib/profiles.d.ts +0 -185
  1016. package/dist/lib/profiles.js +1 -158
  1017. package/dist/lib/project-doctor.d.ts +0 -29
  1018. package/dist/lib/project-doctor.js +0 -26
  1019. package/dist/lib/project-focus.d.ts +0 -41
  1020. package/dist/lib/project-focus.js +0 -49
  1021. package/dist/lib/project-import.d.ts +0 -41
  1022. package/dist/lib/project-import.js +0 -36
  1023. package/dist/lib/project-key.d.ts +0 -65
  1024. package/dist/lib/project-key.js +0 -70
  1025. package/dist/lib/project-launch.d.ts +0 -49
  1026. package/dist/lib/project-launch.js +2 -91
  1027. package/dist/lib/project-probe.d.ts +0 -86
  1028. package/dist/lib/project-probe.js +1 -88
  1029. package/dist/lib/project-pull.d.ts +0 -96
  1030. package/dist/lib/project-pull.js +0 -122
  1031. package/dist/lib/project-resources.d.ts +0 -44
  1032. package/dist/lib/project-resources.js +7 -171
  1033. package/dist/lib/project-root.d.ts +0 -95
  1034. package/dist/lib/project-root.js +0 -101
  1035. package/dist/lib/project-schedule.d.ts +0 -43
  1036. package/dist/lib/project-schedule.js +0 -52
  1037. package/dist/lib/project-status.d.ts +0 -108
  1038. package/dist/lib/project-status.js +0 -117
  1039. package/dist/lib/projects.d.ts +0 -197
  1040. package/dist/lib/projects.js +1 -213
  1041. package/dist/lib/pwsh.d.ts +0 -41
  1042. package/dist/lib/pwsh.js +0 -51
  1043. package/dist/lib/quick-todo.d.ts +84 -0
  1044. package/dist/lib/quick-todo.js +243 -0
  1045. package/dist/lib/reconcile-and-repair.d.ts +0 -78
  1046. package/dist/lib/reconcile-and-repair.js +3 -66
  1047. package/dist/lib/redact.d.ts +0 -29
  1048. package/dist/lib/redact.js +0 -54
  1049. package/dist/lib/refresh-coordinator.d.ts +0 -15
  1050. package/dist/lib/refresh-coordinator.js +0 -10
  1051. package/dist/lib/refresh.d.ts +0 -39
  1052. package/dist/lib/refresh.js +0 -45
  1053. package/dist/lib/registry.d.ts +0 -65
  1054. package/dist/lib/registry.js +0 -127
  1055. package/dist/lib/reminders.d.ts +0 -21
  1056. package/dist/lib/reminders.js +0 -30
  1057. package/dist/lib/remote-agents-json.d.ts +0 -44
  1058. package/dist/lib/remote-agents-json.js +1 -44
  1059. package/dist/lib/reserved-stores.d.ts +0 -28
  1060. package/dist/lib/reserved-stores.js +2 -28
  1061. package/dist/lib/resource-aliases.d.ts +0 -12
  1062. package/dist/lib/resource-aliases.js +0 -12
  1063. package/dist/lib/resource-content-diff.d.ts +0 -28
  1064. package/dist/lib/resource-content-diff.js +7 -34
  1065. package/dist/lib/resource-inventory.d.ts +0 -51
  1066. package/dist/lib/resource-inventory.js +0 -45
  1067. package/dist/lib/resource-patterns.d.ts +0 -32
  1068. package/dist/lib/resource-patterns.js +0 -34
  1069. package/dist/lib/resource-profiles.d.ts +0 -7
  1070. package/dist/lib/resource-profiles.js +0 -11
  1071. package/dist/lib/resources/types.d.ts +0 -50
  1072. package/dist/lib/resources/types.js +0 -7
  1073. package/dist/lib/resources/workflows.d.ts +0 -7
  1074. package/dist/lib/resources/workflows.js +0 -13
  1075. package/dist/lib/resources.d.ts +0 -65
  1076. package/dist/lib/resources.js +0 -78
  1077. package/dist/lib/routers.d.ts +0 -67
  1078. package/dist/lib/routers.js +0 -60
  1079. package/dist/lib/routine-activation.d.ts +0 -23
  1080. package/dist/lib/routine-activation.js +0 -24
  1081. package/dist/lib/routine-context.d.ts +1 -91
  1082. package/dist/lib/routine-context.js +0 -107
  1083. package/dist/lib/routine-notify-owner.d.ts +0 -79
  1084. package/dist/lib/routine-notify-owner.js +1 -103
  1085. package/dist/lib/routine-notify.d.ts +0 -70
  1086. package/dist/lib/routine-notify.js +1 -75
  1087. package/dist/lib/routine-process-cleanup.d.ts +0 -1
  1088. package/dist/lib/routine-process-cleanup.js +1 -4
  1089. package/dist/lib/routine-readiness.d.ts +0 -63
  1090. package/dist/lib/routine-readiness.js +4 -86
  1091. package/dist/lib/routines-format.d.ts +0 -40
  1092. package/dist/lib/routines-format.js +0 -67
  1093. package/dist/lib/routines-placement.d.ts +0 -33
  1094. package/dist/lib/routines-placement.js +0 -40
  1095. package/dist/lib/routines-project.d.ts +0 -57
  1096. package/dist/lib/routines-project.js +6 -80
  1097. package/dist/lib/rules/compile.d.ts +0 -66
  1098. package/dist/lib/rules/compile.js +6 -118
  1099. package/dist/lib/rules/compose.d.ts +0 -56
  1100. package/dist/lib/rules/compose.js +2 -83
  1101. package/dist/lib/rules/rules.d.ts +0 -23
  1102. package/dist/lib/rules/rules.js +0 -35
  1103. package/dist/lib/rules/run-sync.d.ts +0 -16
  1104. package/dist/lib/rules/run-sync.js +1 -44
  1105. package/dist/lib/run-config.d.ts +0 -7
  1106. package/dist/lib/run-config.js +0 -8
  1107. package/dist/lib/run-defaults.d.ts +0 -14
  1108. package/dist/lib/run-defaults.js +0 -14
  1109. package/dist/lib/run-notify.d.ts +0 -18
  1110. package/dist/lib/run-notify.js +0 -36
  1111. package/dist/lib/run-trace-sync.d.ts +0 -21
  1112. package/dist/lib/run-trace-sync.js +2 -66
  1113. package/dist/lib/rush-session.d.ts +0 -26
  1114. package/dist/lib/rush-session.js +0 -28
  1115. package/dist/lib/sandbox.d.ts +0 -45
  1116. package/dist/lib/sandbox.js +5 -93
  1117. package/dist/lib/scheduler.d.ts +0 -28
  1118. package/dist/lib/scheduler.js +0 -45
  1119. package/dist/lib/scheduling/routines.d.ts +0 -652
  1120. package/dist/lib/scheduling/routines.js +8 -475
  1121. package/dist/lib/secrets-cli.d.ts +3 -8
  1122. package/dist/lib/secrets-cli.js +1 -19
  1123. package/dist/lib/secrets-client.d.ts +0 -117
  1124. package/dist/lib/secrets-client.js +4 -275
  1125. package/dist/lib/secrets-policy.d.ts +0 -142
  1126. package/dist/lib/secrets-policy.js +4 -237
  1127. package/dist/lib/secrets-types.d.ts +0 -87
  1128. package/dist/lib/secrets-types.js +0 -13
  1129. package/dist/lib/self-heal/checks/hook-manifest.js +0 -25
  1130. package/dist/lib/self-heal/checks/hook-runtime.js +0 -5
  1131. package/dist/lib/self-heal/checks/install-staging.d.ts +0 -1
  1132. package/dist/lib/self-heal/checks/install-staging.js +1 -28
  1133. package/dist/lib/self-heal/checks/menubar-helper.js +0 -5
  1134. package/dist/lib/self-heal/checks/path.js +0 -9
  1135. package/dist/lib/self-heal/checks/resources.js +0 -5
  1136. package/dist/lib/self-heal/checks/shadowing.js +2 -16
  1137. package/dist/lib/self-heal/checks/shims.js +0 -14
  1138. package/dist/lib/self-heal/child.d.ts +12 -0
  1139. package/dist/lib/self-heal/child.js +23 -0
  1140. package/dist/lib/self-heal/registry.d.ts +0 -9
  1141. package/dist/lib/self-heal/registry.js +0 -16
  1142. package/dist/lib/self-heal/types.d.ts +0 -12
  1143. package/dist/lib/self-heal/types.js +0 -15
  1144. package/dist/lib/self-update.d.ts +0 -312
  1145. package/dist/lib/self-update.js +9 -360
  1146. package/dist/lib/service-manifest.d.ts +0 -39
  1147. package/dist/lib/service-manifest.js +0 -72
  1148. package/dist/lib/session/active.d.ts +13 -869
  1149. package/dist/lib/session/active.js +17 -976
  1150. package/dist/lib/session/actor-sidecar.d.ts +1 -32
  1151. package/dist/lib/session/actor-sidecar.js +1 -41
  1152. package/dist/lib/session/bookmarks.d.ts +0 -33
  1153. package/dist/lib/session/bookmarks.js +0 -37
  1154. package/dist/lib/session/bundle.d.ts +0 -86
  1155. package/dist/lib/session/bundle.js +0 -54
  1156. package/dist/lib/session/claude-accounts.d.ts +0 -40
  1157. package/dist/lib/session/claude-accounts.js +0 -49
  1158. package/dist/lib/session/cloud.d.ts +1 -23
  1159. package/dist/lib/session/cloud.js +0 -26
  1160. package/dist/lib/session/db.d.ts +5 -658
  1161. package/dist/lib/session/db.js +22 -1443
  1162. package/dist/lib/session/detached.d.ts +0 -21
  1163. package/dist/lib/session/detached.js +0 -29
  1164. package/dist/lib/session/discover.d.ts +3 -420
  1165. package/dist/lib/session/discover.js +30 -1123
  1166. package/dist/lib/session/fork.d.ts +1 -41
  1167. package/dist/lib/session/fork.js +0 -19
  1168. package/dist/lib/session/ghostty-tabs.d.ts +0 -24
  1169. package/dist/lib/session/ghostty-tabs.js +0 -37
  1170. package/dist/lib/session/glance-files.d.ts +19 -0
  1171. package/dist/lib/session/glance-files.js +258 -0
  1172. package/dist/lib/session/hook-sessions.d.ts +0 -33
  1173. package/dist/lib/session/hook-sessions.js +4 -99
  1174. package/dist/lib/session/host-link.d.ts +1 -94
  1175. package/dist/lib/session/host-link.js +1 -81
  1176. package/dist/lib/session/inject-target.d.ts +8 -0
  1177. package/dist/lib/session/inject-target.js +32 -0
  1178. package/dist/lib/session/inject.d.ts +0 -15
  1179. package/dist/lib/session/inject.js +0 -15
  1180. package/dist/lib/session/live-metadata.d.ts +1 -34
  1181. package/dist/lib/session/live-metadata.js +1 -73
  1182. package/dist/lib/session/local-tmux-attach.d.ts +0 -37
  1183. package/dist/lib/session/local-tmux-attach.js +1 -76
  1184. package/dist/lib/session/migrate-targets.d.ts +0 -46
  1185. package/dist/lib/session/migrate-targets.js +0 -24
  1186. package/dist/lib/session/migrations.d.ts +0 -12
  1187. package/dist/lib/session/migrations.js +1 -20
  1188. package/dist/lib/session/mirror.d.ts +0 -32
  1189. package/dist/lib/session/mirror.js +0 -77
  1190. package/dist/lib/session/origin-machine.js +0 -3
  1191. package/dist/lib/session/pid-registry.d.ts +0 -80
  1192. package/dist/lib/session/pid-registry.js +2 -81
  1193. package/dist/lib/session/presence.d.ts +0 -39
  1194. package/dist/lib/session/presence.js +2 -52
  1195. package/dist/lib/session/process-view.d.ts +0 -11
  1196. package/dist/lib/session/process-view.js +0 -25
  1197. package/dist/lib/session/projection.d.ts +0 -3
  1198. package/dist/lib/session/projection.js +0 -10
  1199. package/dist/lib/session/provenance.d.ts +1 -37
  1200. package/dist/lib/session/provenance.js +0 -69
  1201. package/dist/lib/session/recovery.d.ts +1 -40
  1202. package/dist/lib/session/recovery.js +2 -80
  1203. package/dist/lib/session/relative-time.js +0 -3
  1204. package/dist/lib/session/remote/peer-stream.d.ts +0 -42
  1205. package/dist/lib/session/remote/peer-stream.js +0 -64
  1206. package/dist/lib/session/remote/remote-bundle.d.ts +0 -6
  1207. package/dist/lib/session/remote/remote-bundle.js +0 -21
  1208. package/dist/lib/session/remote/remote-list.d.ts +1 -110
  1209. package/dist/lib/session/remote/remote-list.js +5 -139
  1210. package/dist/lib/session/remote/remote.d.ts +0 -98
  1211. package/dist/lib/session/remote/remote.js +3 -119
  1212. package/dist/lib/session/remote/watch.d.ts +1 -34
  1213. package/dist/lib/session/remote/watch.js +12 -72
  1214. package/dist/lib/session/remote-active.d.ts +0 -35
  1215. package/dist/lib/session/remote-active.js +0 -48
  1216. package/dist/lib/session/remote-bundle.js +0 -2
  1217. package/dist/lib/session/remote-list.js +0 -2
  1218. package/dist/lib/session/remote-preview-cache.d.ts +0 -7
  1219. package/dist/lib/session/remote-preview-cache.js +1 -76
  1220. package/dist/lib/session/remote.js +0 -2
  1221. package/dist/lib/session/resume-command.d.ts +0 -6
  1222. package/dist/lib/session/resume-command.js +0 -6
  1223. package/dist/lib/session/resume-owner.d.ts +1 -52
  1224. package/dist/lib/session/resume-owner.js +0 -56
  1225. package/dist/lib/session/run-names.d.ts +0 -24
  1226. package/dist/lib/session/run-names.js +0 -26
  1227. package/dist/lib/session/session-cache.d.ts +2 -146
  1228. package/dist/lib/session/session-cache.js +26 -203
  1229. package/dist/lib/session/short-id.js +0 -3
  1230. package/dist/lib/session/sync/agents.d.ts +0 -68
  1231. package/dist/lib/session/sync/agents.js +0 -0
  1232. package/dist/lib/session/sync/backend.d.ts +0 -39
  1233. package/dist/lib/session/sync/backend.js +0 -45
  1234. package/dist/lib/session/sync/config.d.ts +0 -27
  1235. package/dist/lib/session/sync/config.js +0 -56
  1236. package/dist/lib/session/sync/managed-config.d.ts +0 -17
  1237. package/dist/lib/session/sync/managed-config.js +0 -17
  1238. package/dist/lib/session/sync/managed-key.d.ts +0 -38
  1239. package/dist/lib/session/sync/managed-key.js +1 -42
  1240. package/dist/lib/session/sync/net-client.d.ts +0 -36
  1241. package/dist/lib/session/sync/net-client.js +0 -30
  1242. package/dist/lib/session/sync/provision.d.ts +0 -2
  1243. package/dist/lib/session/sync/provision.js +0 -13
  1244. package/dist/lib/session/sync/r2.d.ts +0 -20
  1245. package/dist/lib/session/sync/r2.js +0 -20
  1246. package/dist/lib/session/sync/transcript-crypto.d.ts +0 -37
  1247. package/dist/lib/session/sync/transcript-crypto.js +5 -37
  1248. package/dist/lib/session/sync/worker-template.d.ts +0 -5
  1249. package/dist/lib/session/sync/worker-template.js +0 -40
  1250. package/dist/lib/session/testdata/pid-registry-namespace.js +0 -2
  1251. package/dist/lib/session/testdata/process-view-private.js +0 -1
  1252. package/dist/lib/session/throughput.d.ts +0 -24
  1253. package/dist/lib/session/throughput.js +1 -25
  1254. package/dist/lib/session/timeline-pass.d.ts +1 -63
  1255. package/dist/lib/session/timeline-pass.js +161 -148
  1256. package/dist/lib/session/title.d.ts +0 -182
  1257. package/dist/lib/session/title.js +0 -139
  1258. package/dist/lib/session/tool-index.d.ts +2 -21
  1259. package/dist/lib/session/tool-index.js +3 -75
  1260. package/dist/lib/session/tool-store.d.ts +2 -48
  1261. package/dist/lib/session/tool-store.js +1 -33
  1262. package/dist/lib/session/viewing-in.d.ts +0 -67
  1263. package/dist/lib/session/viewing-in.js +1 -71
  1264. package/dist/lib/session/watch.js +0 -2
  1265. package/dist/lib/session/width.js +0 -3
  1266. package/dist/lib/sessions-client.d.ts +0 -46
  1267. package/dist/lib/sessions-client.js +36 -113
  1268. package/dist/lib/settings-manifest.d.ts +1 -17
  1269. package/dist/lib/settings-manifest.js +4 -57
  1270. package/dist/lib/setup-tool-install.d.ts +0 -1
  1271. package/dist/lib/setup-tool-install.js +2 -7
  1272. package/dist/lib/setup-tool-status.d.ts +0 -3
  1273. package/dist/lib/setup-tool-status.js +4 -14
  1274. package/dist/lib/sha256-asset.d.ts +0 -20
  1275. package/dist/lib/sha256-asset.js +0 -20
  1276. package/dist/lib/share-runtime.d.ts +0 -10
  1277. package/dist/lib/share-runtime.js +1 -27
  1278. package/dist/lib/shim-heal.d.ts +0 -15
  1279. package/dist/lib/shim-heal.js +3 -29
  1280. package/dist/lib/signin-badge.d.ts +0 -72
  1281. package/dist/lib/signin-badge.js +0 -86
  1282. package/dist/lib/sink-format.d.ts +0 -32
  1283. package/dist/lib/sink-format.js +0 -14
  1284. package/dist/lib/smart-launch.d.ts +0 -75
  1285. package/dist/lib/smart-launch.js +1 -83
  1286. package/dist/lib/snapshot.d.ts +0 -46
  1287. package/dist/lib/snapshot.js +5 -31
  1288. package/dist/lib/spinner.d.ts +0 -37
  1289. package/dist/lib/spinner.js +0 -37
  1290. package/dist/lib/sqlite.d.ts +0 -13
  1291. package/dist/lib/sqlite.js +3 -71
  1292. package/dist/lib/ssh-exec.d.ts +0 -209
  1293. package/dist/lib/ssh-exec.js +11 -248
  1294. package/dist/lib/ssh-tunnel.d.ts +0 -43
  1295. package/dist/lib/ssh-tunnel.js +2 -48
  1296. package/dist/lib/staleness/checkers/commands.d.ts +0 -4
  1297. package/dist/lib/staleness/checkers/commands.js +0 -4
  1298. package/dist/lib/staleness/checkers/hooks.d.ts +0 -10
  1299. package/dist/lib/staleness/checkers/hooks.js +0 -15
  1300. package/dist/lib/staleness/checkers/mcp.d.ts +0 -9
  1301. package/dist/lib/staleness/checkers/mcp.js +0 -9
  1302. package/dist/lib/staleness/checkers/permissions.d.ts +0 -12
  1303. package/dist/lib/staleness/checkers/permissions.js +0 -13
  1304. package/dist/lib/staleness/checkers/plugins.d.ts +0 -8
  1305. package/dist/lib/staleness/checkers/plugins.js +0 -8
  1306. package/dist/lib/staleness/checkers/rules.d.ts +0 -15
  1307. package/dist/lib/staleness/checkers/rules.js +0 -26
  1308. package/dist/lib/staleness/checkers/skills.d.ts +0 -4
  1309. package/dist/lib/staleness/checkers/skills.js +0 -4
  1310. package/dist/lib/staleness/checkers/subagents.d.ts +0 -9
  1311. package/dist/lib/staleness/checkers/subagents.js +0 -9
  1312. package/dist/lib/staleness/checkers/types.d.ts +0 -34
  1313. package/dist/lib/staleness/checkers/types.js +0 -19
  1314. package/dist/lib/staleness/checkers/workflows.d.ts +0 -7
  1315. package/dist/lib/staleness/checkers/workflows.js +0 -7
  1316. package/dist/lib/staleness/detectors/commands.js +0 -17
  1317. package/dist/lib/staleness/detectors/hooks.js +1 -6
  1318. package/dist/lib/staleness/detectors/mcp.js +0 -4
  1319. package/dist/lib/staleness/detectors/permissions.js +10 -23
  1320. package/dist/lib/staleness/detectors/rules.js +0 -6
  1321. package/dist/lib/staleness/detectors/skills.d.ts +0 -1
  1322. package/dist/lib/staleness/detectors/skills.js +1 -12
  1323. package/dist/lib/staleness/detectors/types.d.ts +0 -10
  1324. package/dist/lib/staleness/fingerprint.d.ts +0 -19
  1325. package/dist/lib/staleness/fingerprint.js +0 -35
  1326. package/dist/lib/staleness/index.d.ts +0 -28
  1327. package/dist/lib/staleness/index.js +1 -45
  1328. package/dist/lib/staleness/layers.d.ts +0 -23
  1329. package/dist/lib/staleness/layers.js +0 -34
  1330. package/dist/lib/staleness/prune.d.ts +0 -71
  1331. package/dist/lib/staleness/prune.js +2 -27
  1332. package/dist/lib/staleness/registry.d.ts +0 -10
  1333. package/dist/lib/staleness/registry.js +3 -33
  1334. package/dist/lib/staleness/types.d.ts +0 -36
  1335. package/dist/lib/staleness/types.js +0 -5
  1336. package/dist/lib/staleness/writers/commands.js +1 -48
  1337. package/dist/lib/staleness/writers/hooks.js +1 -18
  1338. package/dist/lib/staleness/writers/kinds.d.ts +0 -12
  1339. package/dist/lib/staleness/writers/kinds.js +0 -1
  1340. package/dist/lib/staleness/writers/lazy-map.d.ts +0 -11
  1341. package/dist/lib/staleness/writers/mcp.js +0 -13
  1342. package/dist/lib/staleness/writers/plugins.js +0 -4
  1343. package/dist/lib/staleness/writers/rules.d.ts +0 -1
  1344. package/dist/lib/staleness/writers/rules.js +1 -19
  1345. package/dist/lib/staleness/writers/skills.js +3 -14
  1346. package/dist/lib/staleness/writers/sources.d.ts +0 -11
  1347. package/dist/lib/staleness/writers/sources.js +0 -32
  1348. package/dist/lib/staleness/writers/subagents.js +0 -16
  1349. package/dist/lib/staleness/writers/types.d.ts +0 -58
  1350. package/dist/lib/staleness/writers/workflows.js +1 -1
  1351. package/dist/lib/standalone-tools.d.ts +24 -0
  1352. package/dist/lib/standalone-tools.js +58 -0
  1353. package/dist/lib/star-nudge.d.ts +0 -32
  1354. package/dist/lib/star-nudge.js +2 -36
  1355. package/dist/lib/startup/command-registry.d.ts +0 -45
  1356. package/dist/lib/startup/command-registry.js +1 -46
  1357. package/dist/lib/startup/dev-build.d.ts +0 -9
  1358. package/dist/lib/startup/dev-build.js +1 -42
  1359. package/dist/lib/startup/root-command.d.ts +0 -19
  1360. package/dist/lib/startup/root-command.js +0 -19
  1361. package/dist/lib/startup/spellcheck.d.ts +0 -13
  1362. package/dist/lib/startup/spellcheck.js +0 -13
  1363. package/dist/lib/state.d.ts +0 -376
  1364. package/dist/lib/state.js +19 -737
  1365. package/dist/lib/storage/selection.d.ts +0 -40
  1366. package/dist/lib/storage/selection.js +0 -29
  1367. package/dist/lib/subagents-registry.d.ts +0 -56
  1368. package/dist/lib/subagents-registry.js +0 -99
  1369. package/dist/lib/subagents.d.ts +0 -128
  1370. package/dist/lib/subagents.js +1 -158
  1371. package/dist/lib/summarizer/config.d.ts +0 -37
  1372. package/dist/lib/summarizer/config.js +0 -37
  1373. package/dist/lib/summarizer/pass.d.ts +0 -20
  1374. package/dist/lib/summarizer/pass.js +1 -34
  1375. package/dist/lib/summarizer/summarize.d.ts +1 -49
  1376. package/dist/lib/summarizer/summarize.js +0 -35
  1377. package/dist/lib/sync-passphrase.d.ts +0 -16
  1378. package/dist/lib/sync-passphrase.js +1 -18
  1379. package/dist/lib/sync-status.d.ts +0 -72
  1380. package/dist/lib/sync-status.js +0 -55
  1381. package/dist/lib/sync-umbrella.d.ts +0 -54
  1382. package/dist/lib/sync-umbrella.js +0 -48
  1383. package/dist/lib/system-run-sync.d.ts +0 -5
  1384. package/dist/lib/system-run-sync.js +1 -31
  1385. package/dist/lib/teams/agents.d.ts +1 -444
  1386. package/dist/lib/teams/agents.js +11 -871
  1387. package/dist/lib/teams/api.d.ts +2 -52
  1388. package/dist/lib/teams/api.js +4 -63
  1389. package/dist/lib/teams/debug.d.ts +0 -6
  1390. package/dist/lib/teams/debug.js +0 -6
  1391. package/dist/lib/teams/delivery.d.ts +0 -41
  1392. package/dist/lib/teams/delivery.js +0 -32
  1393. package/dist/lib/teams/file_ops.d.ts +0 -11
  1394. package/dist/lib/teams/file_ops.js +0 -11
  1395. package/dist/lib/teams/forEach.d.ts +0 -76
  1396. package/dist/lib/teams/forEach.js +1 -77
  1397. package/dist/lib/teams/index.d.ts +1 -7
  1398. package/dist/lib/teams/index.js +1 -7
  1399. package/dist/lib/teams/parsers.d.ts +0 -4
  1400. package/dist/lib/teams/parsers.js +0 -81
  1401. package/dist/lib/teams/persistence.d.ts +0 -2
  1402. package/dist/lib/teams/persistence.js +0 -12
  1403. package/dist/lib/teams/placement-probe.d.ts +0 -12
  1404. package/dist/lib/teams/placement-probe.js +1 -51
  1405. package/dist/lib/teams/pr-watch.d.ts +0 -107
  1406. package/dist/lib/teams/pr-watch.js +1 -107
  1407. package/dist/lib/teams/registry.d.ts +0 -36
  1408. package/dist/lib/teams/registry.js +0 -47
  1409. package/dist/lib/teams/remoteWorktree.d.ts +0 -50
  1410. package/dist/lib/teams/remoteWorktree.js +1 -96
  1411. package/dist/lib/teams/scheduler.d.ts +0 -111
  1412. package/dist/lib/teams/scheduler.js +2 -125
  1413. package/dist/lib/teams/summarizer.d.ts +0 -22
  1414. package/dist/lib/teams/summarizer.js +6 -50
  1415. package/dist/lib/teams/supervisor.d.ts +0 -38
  1416. package/dist/lib/teams/supervisor.js +0 -21
  1417. package/dist/lib/teams/worktree.d.ts +0 -95
  1418. package/dist/lib/teams/worktree.js +3 -110
  1419. package/dist/lib/template.d.ts +0 -21
  1420. package/dist/lib/template.js +0 -23
  1421. package/dist/lib/term-client.d.ts +0 -26
  1422. package/dist/lib/term-client.js +0 -48
  1423. package/dist/lib/term-driver.d.ts +0 -5
  1424. package/dist/lib/term-driver.js +0 -8
  1425. package/dist/lib/terminal/backends/ghostty.d.ts +0 -2
  1426. package/dist/lib/terminal/backends/ghostty.js +0 -12
  1427. package/dist/lib/terminal/backends/index.d.ts +0 -17
  1428. package/dist/lib/terminal/backends/index.js +0 -15
  1429. package/dist/lib/terminal/backends/iterm.d.ts +0 -2
  1430. package/dist/lib/terminal/backends/iterm.js +0 -10
  1431. package/dist/lib/terminal/backends/terminal-app.d.ts +0 -10
  1432. package/dist/lib/terminal/backends/terminal-app.js +0 -30
  1433. package/dist/lib/terminal/backends/tmux.d.ts +0 -10
  1434. package/dist/lib/terminal/backends/tmux.js +0 -2
  1435. package/dist/lib/terminal/backends/vscodium-agent.d.ts +0 -25
  1436. package/dist/lib/terminal/backends/vscodium-agent.js +0 -36
  1437. package/dist/lib/terminal/engine.d.ts +0 -17
  1438. package/dist/lib/terminal/engine.js +0 -10
  1439. package/dist/lib/terminal/index.d.ts +0 -8
  1440. package/dist/lib/terminal/inject.d.ts +1 -173
  1441. package/dist/lib/terminal/inject.js +0 -146
  1442. package/dist/lib/terminal/policy.d.ts +0 -8
  1443. package/dist/lib/terminal/policy.js +0 -1
  1444. package/dist/lib/terminal/preferred.d.ts +0 -66
  1445. package/dist/lib/terminal/preferred.js +0 -30
  1446. package/dist/lib/terminal/quote.d.ts +0 -8
  1447. package/dist/lib/terminal/quote.js +0 -8
  1448. package/dist/lib/terminal/resolve.d.ts +0 -46
  1449. package/dist/lib/terminal/resolve.js +0 -30
  1450. package/dist/lib/terminal/run-surface.d.ts +0 -56
  1451. package/dist/lib/terminal/run-surface.js +0 -46
  1452. package/dist/lib/terminal/shell.d.ts +0 -3
  1453. package/dist/lib/terminal/shell.js +0 -13
  1454. package/dist/lib/terminal/transport.d.ts +0 -14
  1455. package/dist/lib/terminal/transport.js +1 -30
  1456. package/dist/lib/terminal/types.d.ts +0 -40
  1457. package/dist/lib/terminal/types.js +0 -10
  1458. package/dist/lib/text/relative-time.d.ts +0 -36
  1459. package/dist/lib/text/relative-time.js +0 -43
  1460. package/dist/lib/text/short-id.d.ts +0 -16
  1461. package/dist/lib/text/short-id.js +0 -16
  1462. package/dist/lib/text/width.d.ts +0 -24
  1463. package/dist/lib/text/width.js +10 -52
  1464. package/dist/lib/tmux/binary.d.ts +0 -36
  1465. package/dist/lib/tmux/binary.js +0 -28
  1466. package/dist/lib/tmux/index.d.ts +0 -5
  1467. package/dist/lib/tmux/index.js +0 -5
  1468. package/dist/lib/tmux/orphan-reap.d.ts +0 -253
  1469. package/dist/lib/tmux/orphan-reap.js +3 -299
  1470. package/dist/lib/tmux/paths.d.ts +0 -14
  1471. package/dist/lib/tmux/paths.js +0 -14
  1472. package/dist/lib/tmux/session.d.ts +0 -263
  1473. package/dist/lib/tmux/session.js +6 -344
  1474. package/dist/lib/traces/backend.d.ts +0 -20
  1475. package/dist/lib/traces/backend.js +0 -23
  1476. package/dist/lib/traces/classify.d.ts +0 -20
  1477. package/dist/lib/traces/classify.js +0 -7
  1478. package/dist/lib/traces/insights.d.ts +1 -84
  1479. package/dist/lib/traces/insights.js +0 -126
  1480. package/dist/lib/traces/phenotype.d.ts +0 -69
  1481. package/dist/lib/traces/phenotype.js +0 -150
  1482. package/dist/lib/traces/provision.d.ts +0 -1
  1483. package/dist/lib/traces/provision.js +0 -5
  1484. package/dist/lib/traces/schema2-build.d.ts +3 -60
  1485. package/dist/lib/traces/schema2-build.js +8 -149
  1486. package/dist/lib/traces/schema2-danger.d.ts +0 -30
  1487. package/dist/lib/traces/schema2-danger.js +1 -63
  1488. package/dist/lib/traces/schema2.d.ts +0 -11
  1489. package/dist/lib/traces/segments.d.ts +0 -44
  1490. package/dist/lib/traces/segments.js +0 -65
  1491. package/dist/lib/traces/sync.d.ts +2 -239
  1492. package/dist/lib/traces/sync.js +15 -237
  1493. package/dist/lib/traces/worker-template.d.ts +0 -3
  1494. package/dist/lib/traces/worker-template.js +0 -29
  1495. package/dist/lib/triggers/handlers.d.ts +0 -82
  1496. package/dist/lib/triggers/handlers.js +0 -75
  1497. package/dist/lib/triggers/webhook.d.ts +0 -158
  1498. package/dist/lib/triggers/webhook.js +0 -143
  1499. package/dist/lib/types.d.ts +0 -736
  1500. package/dist/lib/types.js +0 -50
  1501. package/dist/lib/uninstall.d.ts +0 -17
  1502. package/dist/lib/uninstall.js +0 -75
  1503. package/dist/lib/usage-backoff.d.ts +0 -20
  1504. package/dist/lib/usage-backoff.js +3 -60
  1505. package/dist/lib/usage-refresh.d.ts +0 -154
  1506. package/dist/lib/usage-refresh.js +8 -212
  1507. package/dist/lib/verbs.d.ts +0 -12
  1508. package/dist/lib/verbs.js +0 -12
  1509. package/dist/lib/version-duplicates.d.ts +0 -6
  1510. package/dist/lib/version-duplicates.js +0 -6
  1511. package/dist/lib/version.d.ts +0 -55
  1512. package/dist/lib/version.js +1 -58
  1513. package/dist/lib/view-types.d.ts +0 -48
  1514. package/dist/lib/warn-unpushed.d.ts +0 -27
  1515. package/dist/lib/warn-unpushed.js +1 -45
  1516. package/dist/lib/watchdog/history.d.ts +0 -1
  1517. package/dist/lib/watchdog/history.js +0 -3
  1518. package/dist/lib/watchdog/index.js +0 -2
  1519. package/dist/lib/watchdog/log.d.ts +0 -19
  1520. package/dist/lib/watchdog/log.js +0 -34
  1521. package/dist/lib/watchdog/read.d.ts +0 -27
  1522. package/dist/lib/watchdog/read.js +3 -58
  1523. package/dist/lib/watchdog/rotate.d.ts +0 -139
  1524. package/dist/lib/watchdog/rotate.js +2 -151
  1525. package/dist/lib/watchdog/runner.d.ts +0 -125
  1526. package/dist/lib/watchdog/runner.js +3 -223
  1527. package/dist/lib/watchdog/service.d.ts +0 -1
  1528. package/dist/lib/watchdog/service.js +0 -2
  1529. package/dist/lib/watchdog/watchdog-agent.d.ts +0 -31
  1530. package/dist/lib/watchdog/watchdog-agent.js +0 -27
  1531. package/dist/lib/watchdog/watchdog.d.ts +0 -7
  1532. package/dist/lib/watchdog/watchdog.js +0 -10
  1533. package/dist/lib/watchdog/watchdogTail.js +0 -7
  1534. package/dist/lib/whats-new.d.ts +0 -10
  1535. package/dist/lib/whats-new.js +0 -21
  1536. package/dist/lib/workflows-registry.d.ts +0 -45
  1537. package/dist/lib/workflows-registry.js +0 -60
  1538. package/dist/lib/workflows.d.ts +0 -282
  1539. package/dist/lib/workflows.js +3 -213
  1540. package/dist/lib/worktree/held.d.ts +0 -89
  1541. package/dist/lib/worktree/held.js +1 -103
  1542. package/dist/lib/wrap.d.ts +0 -32
  1543. package/dist/lib/wrap.js +0 -32
  1544. package/dist/lib/yaml-io.d.ts +0 -45
  1545. package/dist/lib/yaml-io.js +0 -47
  1546. package/dist/session-tracker/dist/adapters/claude.js +0 -2
  1547. package/dist/session-tracker/dist/hook.sh +4 -37
  1548. package/dist/session-tracker/dist/index.d.ts +0 -7
  1549. package/dist/session-tracker/dist/index.js +0 -5
  1550. package/dist/session-tracker/dist/install-hook.d.ts +0 -5
  1551. package/dist/session-tracker/dist/install-hook.js +1 -15
  1552. package/dist/session-tracker/dist/prune-state.js +0 -4
  1553. package/dist/session-tracker/dist/reader.js +0 -4
  1554. package/dist/session-tracker/dist/state-file.d.ts +0 -3
  1555. package/dist/session-tracker/dist/state-file.js +3 -8
  1556. package/package.json +3 -4
  1557. package/scripts/postinstall.js +8 -116
  1558. package/dist/lib/session/artifacts.d.ts +0 -14
  1559. package/dist/lib/session/artifacts.js +0 -101
  1560. package/dist/lib/session/bash-command.d.ts +0 -63
  1561. package/dist/lib/session/bash-command.js +0 -490
  1562. package/dist/lib/session/digest.d.ts +0 -66
  1563. package/dist/lib/session/digest.js +0 -328
  1564. package/dist/lib/session/highlights.d.ts +0 -151
  1565. package/dist/lib/session/highlights.js +0 -391
  1566. package/dist/lib/session/insights.d.ts +0 -165
  1567. package/dist/lib/session/insights.js +0 -563
  1568. package/dist/lib/session/linear.d.ts +0 -19
  1569. package/dist/lib/session/linear.js +0 -99
  1570. package/dist/lib/session/parse.d.ts +0 -224
  1571. package/dist/lib/session/parse.js +0 -2408
  1572. package/dist/lib/session/prompt.d.ts +0 -213
  1573. package/dist/lib/session/prompt.js +0 -601
  1574. package/dist/lib/session/render.d.ts +0 -133
  1575. package/dist/lib/session/render.js +0 -1047
  1576. package/dist/lib/session/share-html.d.ts +0 -35
  1577. package/dist/lib/session/share-html.js +0 -319
  1578. package/dist/lib/session/shell-programs.d.ts +0 -33
  1579. package/dist/lib/session/shell-programs.js +0 -380
  1580. package/dist/lib/session/state.d.ts +0 -269
  1581. package/dist/lib/session/state.js +0 -777
  1582. package/dist/lib/session/stream-render.d.ts +0 -4
  1583. package/dist/lib/session/stream-render.js +0 -131
  1584. package/dist/lib/session/tail.d.ts +0 -88
  1585. package/dist/lib/session/tail.js +0 -294
  1586. package/dist/lib/session/team-filter.d.ts +0 -129
  1587. package/dist/lib/session/team-filter.js +0 -269
  1588. package/dist/lib/session/timeline.d.ts +0 -172
  1589. package/dist/lib/session/timeline.js +0 -636
  1590. package/dist/lib/session/tool-calls.d.ts +0 -132
  1591. package/dist/lib/session/tool-calls.js +0 -674
  1592. package/dist/lib/session/trajectory-compare.d.ts +0 -48
  1593. package/dist/lib/session/trajectory-compare.js +0 -116
  1594. package/dist/lib/session/trajectory-html.d.ts +0 -19
  1595. package/dist/lib/session/trajectory-html.js +0 -771
  1596. package/dist/lib/session/trajectory-lineage.d.ts +0 -93
  1597. package/dist/lib/session/trajectory-lineage.js +0 -195
  1598. package/dist/lib/session/trajectory-text.d.ts +0 -38
  1599. package/dist/lib/session/trajectory-text.js +0 -284
  1600. package/dist/lib/session/trajectory.d.ts +0 -145
  1601. package/dist/lib/session/trajectory.js +0 -394
  1602. package/dist/lib/session/types.d.ts +0 -627
  1603. package/dist/lib/session/types.js +0 -43
@@ -1,14 +1,3 @@
1
- /**
2
- * Usage and rate-limit tracking for Claude, Codex, Kimi, Droid, Grok, Cursor,
3
- * and Antigravity agents.
4
- *
5
- * Fetches live usage data from each agent's usage API (Anthropic OAuth for
6
- * Claude, Kimi Code /usages, Factory billing limits for Droid, Google Code
7
- * Assist :retrieveUserQuota for Antigravity) or parses rate-limit events from
8
- * Codex session logs. Results are normalized into a common UsageSnapshot
9
- * shape, cached to disk, and rendered as terminal progress bars for the
10
- * `agents view` command.
11
- */
12
1
  import { execFile } from 'child_process';
13
2
  import { createHash } from 'crypto';
14
3
  import * as fs from 'fs';
@@ -33,37 +22,12 @@ const CLAUDE_TOKEN_URL = 'https://platform.claude.com/v1/oauth/token';
33
22
  const CLAUDE_CLIENT_ID = '9d1c250a-e61b-44d9-88ed-5944d1962f5e';
34
23
  const CLAUDE_OAUTH_BETA_HEADER = 'oauth-2025-04-20';
35
24
  const CLAUDE_REFRESH_LEEWAY_MS = 5 * 60 * 1000;
36
- /**
37
- * Why a usage read produced no snapshot, when the cause is the credential or the
38
- * server rather than the payload. Every provider used to return `error: null`
39
- * for all three, which made an account nobody can read indistinguishable from a
40
- * healthy one: the caller fell back to whatever was in the SWR cache and
41
- * rendered its bars as fact. On `yosemite-s1` that hid five Claude accounts
42
- * whose stored access token had expired — one of them eleven days earlier —
43
- * behind a cache frozen for 26h, and balanced routing launched into an account
44
- * that was actually at its weekly cap.
45
- *
46
- * No usage read ever refreshes a token (RUSH-1822 for Claude; the same rule for
47
- * Kimi/Droid/Cursor, whose own CLIs rotate on their next launch), so an expired
48
- * credential cannot heal on its own — the account stays unreadable until that
49
- * agent actually runs, or a long-lived token is provisioned for it.
50
- *
51
- * Shared across all four networked providers on purpose: the failure shape is
52
- * identical, and wiring only Claude would leave `agents view --refresh`
53
- * reporting Claude accounts while silently presenting stale Kimi, Droid, and
54
- * Cursor readings as confirmed.
55
- */
56
25
  export function usageNoCredentialError(agent) {
57
26
  return `No readable ${agent} credential — sign in, or provision a long-lived token for this account.`;
58
27
  }
59
28
  export function usageExpiredCredentialError(agent) {
60
29
  return `${agent} credential expired — re-auth this account (a usage read never refreshes it).`;
61
30
  }
62
- /**
63
- * Kimi-specific expired-credential wording. A normal Kimi launch refreshes its
64
- * own OAuth access token, so the recovery action for an expired Kimi credential
65
- * is to run Kimi once — not to re-auth through agents-cli (RUSH-3198).
66
- */
67
31
  export function usageExpiredKimiCredentialError() {
68
32
  return `Kimi credential expired — run Kimi once to refresh it (a usage read never refreshes it).`;
69
33
  }
@@ -72,31 +36,13 @@ export function usageRejectedError(agent, status) {
72
36
  ? `${agent} is rate-limiting the usage endpoint for this machine (HTTP 429).`
73
37
  : `${agent} rejected the usage read (HTTP ${status}).`;
74
38
  }
75
- /**
76
- * Canonical phrase for the Anthropic setup-token scope gap (RUSH-2392).
77
- * `claude setup-token` mints `user:inference` only; the usage endpoint requires
78
- * `user:profile`. The account can still run; usage bars cannot populate via
79
- * that token. Callers detect this string with {@link isUsageHeadlessScopeError}
80
- * so the UI can render it distinctly from a generic "unverified" failure.
81
- */
82
39
  export const USAGE_HEADLESS_SCOPE_MARKER = 'usage unavailable (headless)';
83
- /**
84
- * Distinct error when Claude's usage API returns 403 because the setup-token
85
- * lacks `user:profile` (RUSH-2392). Not a revocation, not a missing mint —
86
- * a permanent tradeoff of the headless credential.
87
- */
88
40
  export function usageHeadlessScopeError(agent = 'Claude') {
89
41
  return `${agent} ${USAGE_HEADLESS_SCOPE_MARKER} — setup-token lacks user:profile; account can still run.`;
90
42
  }
91
- /** True when an error string is the setup-token scope gap (RUSH-2392). */
92
43
  export function isUsageHeadlessScopeError(error) {
93
44
  return typeof error === 'string' && error.includes(USAGE_HEADLESS_SCOPE_MARKER);
94
45
  }
95
- /**
96
- * Canonical phrase for a Claude account the usage reader holds no usable
97
- * credential for. Distinct from {@link USAGE_HEADLESS_SCOPE_MARKER}, which
98
- * means a setup-token WAS read and the endpoint refused its scope.
99
- */
100
46
  export const USAGE_NO_USAGE_CREDENTIAL_MARKER = 'usage unavailable (no usage credential)';
101
47
  /**
102
48
  * Claude's own no-credential message. The shared
@@ -113,16 +59,9 @@ export function usageNoClaudeUsageCredentialError() {
113
59
  return (`Claude ${USAGE_NO_USAGE_CREDENTIAL_MARKER} — a usage read never uses your login ` +
114
60
  '(RUSH-1822); a setup-token cannot read usage (RUSH-2392). The account still runs.');
115
61
  }
116
- /** True when an error string is the Claude no-usage-credential state (#2987). */
117
62
  function isUsageNoUsageCredentialError(error) {
118
63
  return typeof error === 'string' && error.includes(USAGE_NO_USAGE_CREDENTIAL_MARKER);
119
64
  }
120
- /**
121
- * Detect Anthropic's usage-endpoint scope denial: HTTP 403 whose body names
122
- * `user:profile` (or "scope requirement"). A bare 403 without that body stays
123
- * classified as a real rejection — only the known setup-token shape is special
124
- * (RUSH-2392).
125
- */
126
65
  export function isClaudeUsageScopeDenied(status, bodyText) {
127
66
  if (status !== 403)
128
67
  return false;
@@ -131,18 +70,6 @@ export function isClaudeUsageScopeDenied(status, bodyText) {
131
70
  const lower = bodyText.toLowerCase();
132
71
  return lower.includes('user:profile') || lower.includes('scope requirement');
133
72
  }
134
- /**
135
- * The read threw rather than answering — a timeout, DNS/TLS failure, a payload
136
- * that would not parse, a credential that would not decrypt. Every provider
137
- * swallowed these into `error: null`, which is the same silence as an expired
138
- * token: the caller renders a stale snapshot as confirmed. The cause is carried
139
- * verbatim because these are the failures a user cannot otherwise see.
140
- */
141
- /**
142
- * The provider told us to back off and we are still inside that window, so this
143
- * read made no request at all. Distinct from `usageRejectedError(agent, 429)`,
144
- * which is the 429 itself: this one says we are *honouring* it.
145
- */
146
73
  export function usageThrottledError(agent, untilMs) {
147
74
  return `${agent} rate-limited this machine — not retrying for ${formatBackoffRemaining(untilMs)}.`;
148
75
  }
@@ -152,38 +79,9 @@ export function usageUnreachableError(agent, cause) {
152
79
  ? `${agent} usage read failed: ${detail}`
153
80
  : `${agent} usage read failed.`;
154
81
  }
155
- /**
156
- * Marker for a log-based (`network: false`) provider — Codex, Grok — that has
157
- * simply never recorded a rate-limit event on this machine yet: no session
158
- * log exists, or no session in it carries usage data. Distinct on purpose from
159
- * `usageUnreachableError`: that one means the local log COULDN'T be read (a
160
- * real failure worth surfacing distinctly); this one means there is nothing to
161
- * read because the account has not run here, which is expected for a fresh
162
- * install and should render as a benign state, not an error (RUSH-3040).
163
- */
164
82
  const USAGE_NO_RECENT_USAGE_MARKER = 'no usage recorded yet';
165
83
  export const USAGE_BENIGN_STATE = Symbol('usageBenignState');
166
- /**
167
- * Sentinel `UsageInfo.error` for a read-only lookup whose cache held nothing
168
- * (`getUsageInfoForIdentity`). No request was made and nothing failed — the
169
- * daemon simply has not collected this account yet. It was an unclassified
170
- * literal, so `classifyUsageErrorKind` fell through to `'rejected'` and
171
- * `agents view` printed the generic "usage unavailable" for a cold cache,
172
- * which reads as a failure the operator should chase (#2987). The string value
173
- * is unchanged; callers that already compare against `'stale'` keep working.
174
- */
175
84
  export const USAGE_NOT_COLLECTED_MARKER = 'stale';
176
- /**
177
- * Human-facing form of a `UsageInfo.error` for a machine/JSON consumer
178
- * (`agents view --json`'s `usageError`). Every error string this module
179
- * constructs is already a full human sentence EXCEPT the internal
180
- * {@link USAGE_NOT_COLLECTED_MARKER} (`'stale'`) sentinel, which a read-only
181
- * lookup returns for a never-cached account when `--refresh` was not passed. That
182
- * value is an internal cache signal, not an error message, and leaking it verbatim
183
- * contradicts the field's "human-readable" contract (PHNX-3348). Map it to a
184
- * plain-language, actionable string and pass every genuine error through
185
- * unchanged. Returns `null` when there is no error.
186
- */
187
85
  export function usageErrorForDisplay(error) {
188
86
  if (!error)
189
87
  return null;
@@ -192,18 +90,6 @@ export function usageErrorForDisplay(error) {
192
90
  }
193
91
  return error;
194
92
  }
195
- /**
196
- * Shared error-classification + 429 backoff for a networked usage fetch whose
197
- * only signal is an HTTP status (or none at all, on a network failure) —
198
- * Antigravity's :retrieveUserQuota and Muse's Meta Model API probe are both
199
- * this shape. They were added to `USAGE_SOURCES` after the four original
200
- * `usageXError` constructors and did not get their own scheme (usage.ts's
201
- * error handling was written for "four networked providers"; RUSH-3040).
202
- * Route every no-snapshot outcome for either through this one function so a
203
- * future entry cannot be added second-class again — it owns noting the 429
204
- * backoff, so callers must NOT also call {@link noteUsageRateLimited} for the
205
- * same response.
206
- */
207
93
  export function classifyUsageFetchFailure(agent, agentId, status, retryAfterHeader, usageScope) {
208
94
  if (status === 429) {
209
95
  noteUsageRateLimited(agentId, retryAfterHeader ?? null, { account: usageScope });
@@ -213,7 +99,6 @@ export function classifyUsageFetchFailure(agent, agentId, status, retryAfterHead
213
99
  return usageRejectedError(agent, status);
214
100
  return usageUnreachableError(agent);
215
101
  }
216
- /** Classify a `UsageInfo.error` string into its {@link UsageErrorKind}, or null when there is no error. */
217
102
  export function classifyUsageErrorKind(error) {
218
103
  if (!error)
219
104
  return null;
@@ -236,17 +121,6 @@ export function classifyUsageErrorKind(error) {
236
121
  return 'unreachable';
237
122
  return 'rejected';
238
123
  }
239
- /**
240
- * True when a Claude OAuth access token is within the refresh leeway of expiry
241
- * (or already expired) — i.e. it "would need a refresh" before the next use.
242
- *
243
- * Single source of truth for the expiry gate, shared by the two callers that
244
- * must agree on it but act differently: the run/usage hot path
245
- * (`getClaudeAccessToken`) refreshes when this is true; the health probe
246
- * (`probeClaudeStatus`) must NOT refresh and instead reports the non-fatal
247
- * `expired` state (RUSH-1822). A missing `expiresAt` is treated as "still
248
- * fresh" (never force a refresh on a token with no known expiry).
249
- */
250
124
  export function claudeAccessTokenNeedsRefresh(expiresAt, nowMs = Date.now()) {
251
125
  if (expiresAt == null)
252
126
  return false;
@@ -260,12 +134,6 @@ const CLAUDE_SCOPES = [
260
134
  'user:file_upload',
261
135
  ];
262
136
  const CLAUDE_KEYCHAIN_SERVICE = 'Claude Code-credentials';
263
- /**
264
- * Test seam for the usage cache path, mirroring `setUsageBackoffDirForTest`.
265
- * `getCacheDir()` resolves from a module-level constant captured at import, so
266
- * overriding `HOME` in a test does NOT redirect this cache — it would write into
267
- * the developer's real `~/.agents/.cache/`. Point it at a tmpdir instead.
268
- */
269
137
  let claudeUsageCachePathOverride = null;
270
138
  export function setClaudeUsageCachePathForTest(cachePath) {
271
139
  const prev = claudeUsageCachePathOverride;
@@ -284,21 +152,13 @@ const USAGE_BAR_LEN = 10;
284
152
  const FULL = '\u2588';
285
153
  const EMPTY = '\u2591';
286
154
  const PARTIAL_BLOCKS = ['', '\u258F', '\u258E', '\u258D', '\u258C', '\u258B', '\u258A', '\u2589'];
287
- // A window we EXPECTED but have no reading for \u2014 e.g. Claude's 5h "session"
288
- // window when the account has no usage in the current rolling window, so the
289
- // usage API returns five_hour.utilization = null and no session bar is written.
290
- // It must read as neither 0% (EMPTY '\u2591') nor 100% (FULL '\u2588') \u2014 a full block was
291
- // alarming and looked maxed-out \u2014 so use a dashed row that says "no data".
292
155
  const NO_DATA = '\u2504';
293
- /** Construct the benign no-local-log result without overloading `error`. */
294
156
  function usageNoRecentUsageInfo() {
295
157
  return { snapshot: null, error: null, [USAGE_BENIGN_STATE]: 'no-recent-usage' };
296
158
  }
297
- /** Read a benign state for the human renderer; symbols are omitted by JSON serialization. */
298
159
  export function getUsageBenignState(info) {
299
160
  return info[USAGE_BENIGN_STATE] ?? null;
300
161
  }
301
- /** The single registry of agent usage sources and their transport. */
302
162
  const USAGE_SOURCES = {
303
163
  claude: { fetch: getClaudeUsageInfo, network: true },
304
164
  codex: { fetch: getCodexUsageInfo, network: false },
@@ -313,29 +173,17 @@ export const USAGE_SOURCE_AGENT_IDS = Object.keys(USAGE_SOURCES);
313
173
  function getUsageSource(agentId) {
314
174
  return USAGE_SOURCES[agentId];
315
175
  }
316
- /** Fetch usage info for a given agent through the canonical source registry. */
317
176
  export async function getUsageInfo(agentId, options) {
318
177
  const source = getUsageSource(agentId);
319
178
  return source ? source.fetch(options) : { snapshot: null, error: null };
320
179
  }
321
- /**
322
- * Combine a caller-supplied abort signal (the daemon tick deadline) with a
323
- * per-fetch timeout, so a provider fetch is bounded by whichever fires first
324
- * (PHNX-3608). With no caller signal it degrades to the timeout alone —
325
- * byte-identical to the previous `AbortSignal.timeout(ms)` behaviour.
326
- */
327
180
  function usageFetchSignal(signal, timeoutMs) {
328
181
  const timeout = AbortSignal.timeout(timeoutMs);
329
182
  return signal ? AbortSignal.any([signal, timeout]) : timeout;
330
183
  }
331
- /** Derive a stable lookup key from account info for usage deduplication. */
332
184
  export function getUsageLookupKey(info) {
333
185
  return info?.usageKey || info?.accountKey || null;
334
186
  }
335
- /**
336
- * Deduplicate identity inputs into canonical (most-recently-active) accounts
337
- * and build the corresponding fetch inputs for each unique usage key.
338
- */
339
187
  export function buildCanonicalUsageContext(inputs) {
340
188
  const canonicalByUsageKey = new Map();
341
189
  const usageFetchInputs = new Map();
@@ -359,31 +207,12 @@ export function buildCanonicalUsageContext(inputs) {
359
207
  }
360
208
  return { canonicalByUsageKey, usageFetchInputs };
361
209
  }
362
- /**
363
- * Whether an agent exposes usage/limit data we can render — Claude/Kimi/Droid/
364
- * Cursor/Antigravity via a live API, Codex/Grok via local session logs.
365
- * Everything else has no usage concept, so callers use this to decide whether
366
- * a missing snapshot is worth flagging as "usage unavailable" (a signed-in
367
- * Claude account with no data) versus simply not applicable (OpenCode).
368
- */
369
210
  export function agentReportsUsage(agentId) {
370
211
  return getUsageSource(agentId) !== undefined;
371
212
  }
372
- /**
373
- * Whether an agent's usage source makes a live NETWORK call (Claude/Kimi/Droid/
374
- * Cursor/Antigravity) versus reading local session logs (Codex/Grok). Both
375
- * kinds publish through the shared cache; callers use this only to distinguish
376
- * provider I/O from local collection.
377
- */
378
213
  export function agentUsesNetworkUsage(agentId) {
379
214
  return getUsageSource(agentId)?.network === true;
380
215
  }
381
- /**
382
- * Concurrent live usage fetches for a single `agents view` / rotation pass.
383
- * High enough to finish a multi-account refresh in one round-trip window; low
384
- * enough that a cold cache of 10+ accounts cannot open 10+ HTTP calls at once
385
- * (and cannot stack behind delayed responses until the process is pegged).
386
- */
387
216
  export const USAGE_FETCH_CONCURRENCY = 3;
388
217
  export async function getUsageInfoByIdentity(inputs, opts) {
389
218
  const { canonicalByUsageKey, usageFetchInputs } = buildCanonicalUsageContext(inputs);
@@ -402,26 +231,11 @@ export async function getUsageInfoByIdentity(inputs, opts) {
402
231
  usageByKey: new Map(usageResults.map(({ key, usage }) => [key, usage])),
403
232
  };
404
233
  }
405
- /**
406
- * In-process dedup complements the device-wide lease. It avoids lock contention
407
- * when several callers in one process explicitly request the same refresh.
408
- */
409
234
  const inFlightLiveFetches = new Map();
410
- /**
411
- * Fetch usage for one identity. Ordinary callers always read the shared cache;
412
- * the daemon and explicit `--refresh` calls collect through one device lease.
413
- */
414
235
  export async function getUsageInfoForIdentity(input, opts) {
415
236
  const usageKey = getUsageLookupKey(input.info);
416
237
  const forceRefresh = opts?.forceRefresh === true;
417
- // Reading is the default. Only an explicit forceRefresh is authorized to
418
- // collect provider/local-log state; callers cannot accidentally turn a
419
- // display or routing path into a collector by omitting an option.
420
238
  const readOnly = !forceRefresh;
421
- // The on-disk cache is shared for both provider and local-log sources and is
422
- // keyed by usageKey, which is namespaced per agent (`claude:org=…`,
423
- // `kimi:user=…`, `droid:org=…`, `cursor:user=…`, `antigravity:sub=…`), so one
424
- // cache file holds every account without collision.
425
239
  if (!usageKey) {
426
240
  if (readOnly)
427
241
  return { snapshot: null, error: USAGE_NOT_COLLECTED_MARKER };
@@ -436,49 +250,20 @@ export async function getUsageInfoForIdentity(input, opts) {
436
250
  });
437
251
  }
438
252
  const cached = readClaudeUsageCache(usageKey);
439
- // `readOnly` (the `agents run` routing hot path): serve the cache and NEVER
440
- // touch the network — not even a background refresh. `collectRunCandidates`
441
- // used to pass a 5-minute `maxAgeMs`, which made a snapshot older than that
442
- // fall through to the blocking live fetch below (getUsageInfo → provider HTTP),
443
- // adding one round trip per account to `agents run` cold-start on a box whose
444
- // cache had gone stale. The daemon now owns keeping this cache fresh
445
- // (`runUsageRefresh`, adaptive + rate-capped), so the router only ever reads
446
- // it. A stale-or-absent snapshot is handled downstream by the router's own
447
- // freshness guard (`isUsageVerified` in rotate.ts), which routes around a
448
- // number it can't confirm rather than trusting an old one — so returning a
449
- // stale snapshot here is safe, and an absent one reports
450
- // {@link USAGE_NOT_COLLECTED_MARKER}.
451
253
  if (readOnly) {
452
- // A row carries a CONFIRMED reading when it has a fresh window, a
453
- // subscription plan (meterless-healthy, e.g. Grok's tier), or a live refusal
454
- // (out_of_credits / session_limit). Those report `usageError: null`.
455
254
  if (cached && (cached.windows.length > 0 || cached.plan || cached.unavailable)) {
456
255
  return { snapshot: cached, error: null };
457
256
  }
458
- // A row whose ONLY content is last-known stale readings — the all-expired
459
- // Claude case, its windows moved to `staleWindows` (view-only) so the
460
- // TERMINAL view still renders the number with its age — must NOT read as a
461
- // healthy account. `staleWindows` is deliberately excluded from `--json`
462
- // (which projects only `windows`), so keep `usageError` non-null: a consumer
463
- // polling `agents view --json` must still see the staleness signal, the exact
464
- // RUSH-2858 weeks-stale case this marker exists for. The snapshot is still
465
- // returned, so the human view is unaffected.
466
257
  if (cached)
467
258
  return { snapshot: cached, error: USAGE_NOT_COLLECTED_MARKER };
468
259
  return { snapshot: null, error: USAGE_NOT_COLLECTED_MARKER };
469
260
  }
470
- // Explicit refresh: block on the shared device collector.
471
261
  return fetchLiveUsageDeduped(input, usageKey, cached, opts?.fileOnly === true, {
472
262
  allowInteractiveLogin: opts?.allowInteractiveLogin === true,
473
263
  nativeFileLogin: opts?.nativeFileLogin === true,
474
264
  signal: opts?.signal,
475
265
  });
476
266
  }
477
- /**
478
- * Single-flight live usage fetch per usage key. Concurrent callers (view +
479
- * rotation, or two rows sharing an account) await the same promise rather than
480
- * opening duplicate HTTP requests that then time out and pile up.
481
- */
482
267
  async function fetchLiveUsageDeduped(input, usageKey, cached, fileOnly, opts) {
483
268
  const existing = inFlightLiveFetches.get(usageKey);
484
269
  if (existing)
@@ -498,8 +283,6 @@ async function fetchLiveUsageDeduped(input, usageKey, cached, fileOnly, opts) {
498
283
  home: input.home,
499
284
  cliVersion: input.cliVersion,
500
285
  organizationId: input.info.organizationId,
501
- // Scope this fetch's 429 backoff to the account being fetched, so one
502
- // throttled account cannot park the whole provider (RUSH-3036).
503
286
  usageScope: usageKey,
504
287
  fileOnly,
505
288
  allowInteractiveLogin: opts?.allowInteractiveLogin === true,
@@ -513,7 +296,6 @@ async function fetchLiveUsageDeduped(input, usageKey, cached, fileOnly, opts) {
513
296
  writeClaudeUsageCache(usageKey, usage.snapshot);
514
297
  return usage;
515
298
  }
516
- // Live fetch failed — last-resort fallback to whatever cache we had.
517
299
  if (latestCached)
518
300
  return { snapshot: latestCached, error: usage.error };
519
301
  return usage;
@@ -527,23 +309,11 @@ async function fetchLiveUsageDeduped(input, usageKey, cached, fileOnly, opts) {
527
309
  inFlightLiveFetches.delete(usageKey);
528
310
  }
529
311
  }
530
- /**
531
- * Pick which usage windows to render in a compact one-line summary.
532
- *
533
- * Overview rows (`agents view` all agents) must stay narrow enough that one
534
- * multi-window agent (Antigravity's four model quotas, Droid's three buckets)
535
- * does not force every other row to pad to ~200 columns and wrap. Prefer the
536
- * canonical session + week windows when present; otherwise take the highest
537
- * utilization remaining. Returns the full set when `maxWindows` is unset.
538
- */
539
312
  export function pickCompactUsageWindows(windows, maxWindows) {
540
313
  const filtered = windows.filter((window) => window.key !== 'sonnet_week');
541
314
  if (maxWindows === undefined || maxWindows <= 0 || filtered.length <= maxWindows) {
542
315
  return filtered;
543
316
  }
544
- // Pick by object identity, not by key. Antigravity normalizes every model
545
- // quota as key: 'session', so a key-set filter would keep only the first and
546
- // drop the rest even when maxWindows > 1.
547
317
  const chosen = [];
548
318
  const take = (w) => {
549
319
  if (!w || chosen.includes(w) || chosen.length >= maxWindows)
@@ -562,12 +332,6 @@ export function pickCompactUsageWindows(windows, maxWindows) {
562
332
  }
563
333
  return chosen;
564
334
  }
565
- /**
566
- * Shared builder for {@link formatUsageSummary} options in `agents view` and
567
- * account-catalog rows. One builder, no copy — captures `headless`,
568
- * `unverified`, `expectedWindows`, `errorKind`, `benignState`, and the grok
569
- * `noRecentUsageLabel` consistently.
570
- */
571
335
  export function viewUsageSummaryOptions(agentId, signedIn, usageInfo, maxWindows, version) {
572
336
  const headless = isUsageHeadlessScopeError(usageInfo?.error);
573
337
  const benignState = usageInfo ? getUsageBenignState(usageInfo) : null;
@@ -587,22 +351,15 @@ export function viewUsageSummaryOptions(agentId, signedIn, usageInfo, maxWindows
587
351
  : null,
588
352
  };
589
353
  }
590
- /** Human label for a classified usage error, for the no-bars branch of {@link formatUsageSummary}. */
591
354
  function formatUsageErrorKindLabel(kind, detail) {
592
355
  switch (kind) {
593
356
  case 'no-credential':
594
357
  return 'sign in / provision token';
595
- // Both of these are permanent for the account as configured, and both used
596
- // to render as the generic bucket — which reads as a transient failure and
597
- // sends operators back to `claude setup-token` for a remedy that cannot
598
- // work (#2987). Name the state instead.
599
358
  case 'no-usage-credential':
600
359
  return USAGE_NO_USAGE_CREDENTIAL_MARKER;
601
360
  case 'headless-scope':
602
361
  return USAGE_HEADLESS_SCOPE_MARKER;
603
362
  case 'expired-credential':
604
- // Kimi refreshes its own credential on a normal launch; the recovery hint
605
- // is embedded in the error string so the label matches the exact action.
606
363
  if (detail?.includes('run Kimi once'))
607
364
  return 'run Kimi once';
608
365
  return 're-auth for usage';
@@ -620,35 +377,19 @@ function formatUsageErrorKindLabel(kind, detail) {
620
377
  return 'usage unavailable';
621
378
  }
622
379
  }
623
- /** Format a one-line usage summary with compact bars for inline display. */
624
380
  export function formatUsageSummary(plan, snapshot, planWidth = 3, opts) {
625
381
  const parts = [];
626
382
  if (plan) {
627
383
  parts.push(chalk.gray(plan.padEnd(planWidth)));
628
384
  }
629
385
  if (snapshot) {
630
- // A blocking marker renders AFTER the bars: leading it pushed every gauge
631
- // out of its column, so one throttled account misaligned the whole table.
632
386
  const blocked = snapshot.unavailable?.reason === 'out_of_credits'
633
387
  ? chalk.red('out of credits')
634
388
  : snapshot.unavailable?.reason === 'session_limit' && snapshot.unavailable.resetsAt
635
389
  ? chalk.yellow(`session-limited (${formatResetHint(snapshot.unavailable.resetsAt)})`)
636
390
  : null;
637
- // Compact rows show BLOCKING windows — the same set
638
- // deriveUsageStatusFromSnapshot uses for the rate-limited badge — so an
639
- // account throttled by its month window (Droid meters on 5h/week/month)
640
- // shows the bar that explains why. Claude's Sonnet week is a per-model
641
- // sub-limit, not a blocking window; it renders only in the full
642
- // per-version usage section. Each window reads "S: ███░░ 58% (3d)" — the
643
- // gauge, the exact percentage, and a compact hint of when it resets.
644
- //
645
- // Overview caps the window count (see pickCompactUsageWindows) so one
646
- // multi-meter agent cannot force the whole table to wrap.
647
391
  const selected = pickCompactUsageWindows(snapshot.windows, opts?.maxWindows);
648
392
  const hidden = Math.max(0, snapshot.windows.filter((w) => w.key !== 'sonnet_week').length - selected.length);
649
- // Last-known windows the freshness gate dropped (see UsageSnapshot.staleWindows).
650
- // Rendered with an age suffix so a stale reading stays visible instead of a
651
- // bare "unavailable"; never in `snapshot.windows`, so routing never sees them.
652
393
  const now = new Date();
653
394
  const staleWindows = snapshot.staleWindows ?? [];
654
395
  const staleByKey = new Map(staleWindows.map((w) => [w.key, w]));
@@ -658,8 +399,6 @@ export function formatUsageSummary(plan, snapshot, planWidth = 3, opts) {
658
399
  : selected.map((window) => ({ key: window.key, window, shortLabel: window.shortLabel }));
659
400
  const windowParts = windowsToRender.map(({ key, window, shortLabel }, index) => {
660
401
  if (!window) {
661
- // A window we expected but have no fresh reading for: render the
662
- // last-known value with its age if we still have it, else "unavailable".
663
402
  const stale = staleByKey.get(key);
664
403
  const rendered = stale
665
404
  ? renderStaleUsageWindow(stale, snapshot.capturedAt, shortLabel, now)
@@ -679,9 +418,6 @@ export function formatUsageSummary(plan, snapshot, planWidth = 3, opts) {
679
418
  parts.push(windowParts.join(' '));
680
419
  }
681
420
  else if (staleWindows.length > 0) {
682
- // No fresh bars, but we have last-known readings (e.g. Grok's weekly bar
683
- // from an ended billing period): show them with an age suffix rather than
684
- // the "run once to refresh" hint, which hid a number we actually had.
685
421
  const cap = opts?.maxWindows ?? staleWindows.length;
686
422
  const rendered = staleWindows
687
423
  .slice(0, cap)
@@ -691,11 +427,6 @@ export function formatUsageSummary(plan, snapshot, planWidth = 3, opts) {
691
427
  else if (snapshot.refreshHint) {
692
428
  parts.push(chalk.dim(snapshot.refreshHint));
693
429
  }
694
- // The bars came from the cache and the live read that should have confirmed
695
- // them failed, so they are the last thing we saw — not the current state.
696
- // Drawing them unmarked is what let a 26h-old "48% used" read as fact.
697
- // Headless-scope (RUSH-2392) is a known permanent gap, not a flaky cache:
698
- // prefer that label over the generic "unverified" so operators do not re-mint.
699
430
  if (opts?.headless) {
700
431
  parts.push(chalk.dim(USAGE_HEADLESS_SCOPE_MARKER));
701
432
  }
@@ -706,61 +437,23 @@ export function formatUsageSummary(plan, snapshot, planWidth = 3, opts) {
706
437
  parts.push(blocked);
707
438
  }
708
439
  else if (opts?.headless) {
709
- // No bars at all: still name the scope gap so "usage pending" is not
710
- // mistaken for a missing setup-token or seeding failure (RUSH-2392).
711
440
  parts.push(chalk.dim(USAGE_HEADLESS_SCOPE_MARKER));
712
441
  }
713
442
  else if (opts?.benignState === 'no-recent-usage') {
714
443
  parts.push(chalk.dim(opts.noRecentUsageLabel || USAGE_NO_RECENT_USAGE_MARKER));
715
444
  }
716
445
  else if (opts?.unavailable) {
717
- // Signed-in account we could NOT fetch usage for (no live token in a reachable
718
- // home / org mismatch / fetch error). Say so explicitly instead of drawing a
719
- // blank gauge that reads like "0% used" — and name the SPECIFIC cause when
720
- // the caller passed one, rather than the generic bucket that used to cover
721
- // ~6 different failures (RUSH-3040).
722
446
  parts.push(chalk.dim(formatUsageErrorKindLabel(opts.errorKind, opts.errorDetail)));
723
447
  }
724
448
  return parts.join(' ');
725
449
  }
726
- /**
727
- * The snapshot's windows that are still LIVE — reset time not yet passed. A
728
- * window past its `resetsAt` has rolled over: its `usedPercent` is a reading of
729
- * the PREVIOUS period, not a live throttle (PHNX-4116). Both the throttle
730
- * verdict ({@link deriveUsageStatusFromSnapshot}) and the displayed
731
- * `usedPercent` (`devices/harness-inventory.ts`) MUST select from this SAME set,
732
- * or a maxed-then-reset account reads `available` yet shows a stale 99% next to
733
- * its "ready" verdict (#3705). Callers still narrow further (dropping
734
- * `sonnet_week`, the model sub-limit); this is only the reset-rollover cut.
735
- */
736
450
  export function liveUsageWindows(snapshot, now = Date.now()) {
737
451
  return snapshot.windows.filter((window) => !(window.resetsAt && window.resetsAt.getTime() <= now));
738
452
  }
739
- /**
740
- * Derive an account's real throttle state from its live usage windows — the
741
- * single signal both the `agents view` badge and run-rotation eligibility share
742
- * (`hasUsageAvailable` in rotate.ts treats a `rate_limited` verdict here as
743
- * ineligible). A window at 100% utilization means the account is throttled until
744
- * that window resets. Rotation *weighting* still ranks eligible accounts by
745
- * weekly headroom (`getRoutingUsedPercent`); this function is the yes/no gate.
746
- *
747
- * Returns `null` when there is no snapshot, so callers render no badge rather
748
- * than a misleading one. This deliberately never consults
749
- * `cachedExtraUsageDisabledReason`: that field describes why pay-as-you-go
750
- * overage is disabled (`out_of_credits` = no overage credits purchased,
751
- * `org_level_disabled` = an admin turned overage off), NOT whether the account
752
- * can do work right now. A Pro account at 5% weekly usage with overage disabled
753
- * is fully usable, yet that flag would mislabel it "out of credits".
754
- *
755
- * The model-specific `sonnet_week` sub-limit is excluded: hitting it throttles
756
- * one model, not the account, so it shouldn't flip the whole row to throttled.
757
- */
758
453
  export function deriveUsageStatusFromSnapshot(snapshot, now = Date.now()) {
759
454
  if (!snapshot)
760
455
  return null;
761
456
  if (snapshot.unavailable) {
762
- // out_of_credits has no clock — it stays blocking until a successful run
763
- // clears it. session_limit blocks only until its reset time.
764
457
  if (snapshot.unavailable.reason === 'out_of_credits')
765
458
  return 'rate_limited';
766
459
  if (snapshot.unavailable.resetsAt && snapshot.unavailable.resetsAt.getTime() > now) {
@@ -790,30 +483,12 @@ export function deriveUsageHeadroom(snapshot, prev) {
790
483
  }
791
484
  const deltaPercent = session.usedPercent - prev.usedPercent;
792
485
  const deltaMinutes = (capturedAt - prev.capturedAt) / 60_000;
793
- // Flat, falling (a window reset), or a zero/negative time delta: no live burn
794
- // to project from, so this account is not "projected to cap".
795
486
  if (deltaPercent <= 0 || deltaMinutes <= 0)
796
487
  return { status, minutesToLimit: null };
797
488
  const burnPerMinute = deltaPercent / deltaMinutes;
798
489
  const remaining = Math.max(0, 100 - session.usedPercent);
799
490
  return { status, minutesToLimit: remaining / burnPerMinute };
800
491
  }
801
- /**
802
- * Compact colored badge for the account's overall usage status. Renders only
803
- * when the account is throttled — `available` and `null` return ''.
804
- *
805
- * - `out_of_credits` → red "out of credits" (terminal account, all buckets dry)
806
- * - `rate_limited` → yellow "rate-limited" (transient throttling)
807
- *
808
- * The badge sits between the usage bars and `lastActive` in `agents view`, so
809
- * a glance at the row tells the user whether the version can do useful work.
810
- * The same signal is exposed as `usageStatus` in `agents view --json` for
811
- * programmatic consumers (e.g. the swarmify panel's "resume in healthy agent").
812
- *
813
- * The switch is exhaustive on purpose — adding a new `AccountInfo.usageStatus`
814
- * value without updating the cases here is a build error at `_exhaustive`,
815
- * which is exactly the bug class this PR is fixing.
816
- */
817
492
  export function formatUsageStatusBadge(usageStatus) {
818
493
  if (usageStatus === null || usageStatus === undefined)
819
494
  return '';
@@ -828,7 +503,6 @@ export function formatUsageStatusBadge(usageStatus) {
828
503
  }
829
504
  }
830
505
  }
831
- /** Format a multi-line usage section for detailed agent views. */
832
506
  export function formatUsageSection(usage) {
833
507
  if (!usage.snapshot && !usage.error) {
834
508
  return [];
@@ -853,25 +527,8 @@ export function formatUsageSection(usage) {
853
527
  lines.push(` ${chalk.dim(`Source: ${usage.snapshot.sourceLabel}`)}`);
854
528
  return lines;
855
529
  }
856
- /** Fetch Codex usage by scanning the most recent session files for rate-limit events. */
857
530
  async function getCodexUsageInfo(options) {
858
531
  try {
859
- // Codex usage is read from on-disk session transcripts, which carry no
860
- // account identity and are not removed on logout. To keep the bar scoped to
861
- // the account signed in NOW, floor the scan at the current login time: the
862
- // id_token's `auth_time` claim — the OIDC time-of-authentication. A session
863
- // written before that login belongs to whoever was signed in before (e.g.
864
- // after `codex logout` + login into a different account), and showing its
865
- // rate_limits is the "wrong usage after switch" bug.
866
- //
867
- // `auth_time` — not the auth.json file mtime — is the correct floor: Codex
868
- // rewrites auth.json on every token refresh (advancing its mtime), but a
869
- // refresh_token grant does not re-authenticate the user, so `auth_time`
870
- // stays at the real login. Flooring on mtime would blank the bar after each
871
- // background refresh; flooring on `auth_time` does not. No readable
872
- // credential means the version is signed out — report no usage. A credential
873
- // that carries no `auth_time` falls back to no floor (prior behavior) rather
874
- // than hide a signed-in account's usage.
875
532
  const base = options?.home || os.homedir();
876
533
  let sinceMs;
877
534
  try {
@@ -889,11 +546,6 @@ async function getCodexUsageInfo(options) {
889
546
  const match = await readLatestCodexRateLimits(filePath);
890
547
  if (!match)
891
548
  continue;
892
- // Same freshness filter Grok already applies (RUSH-3040): a window whose
893
- // reset time or windowMinutes-derived expiry has passed is a STALE read,
894
- // not a current one — rendering it as-is is how a codex bar kept showing
895
- // "100% used" past its own reset. Try the next-older session file rather
896
- // than surfacing a stale bar.
897
549
  const windows = normalizeCodexWindows(match.rateLimits).filter((window) => isCachedUsageWindowFresh(window, match.capturedAt, now));
898
550
  if (windows.length === 0)
899
551
  continue;
@@ -907,52 +559,21 @@ async function getCodexUsageInfo(options) {
907
559
  error: null,
908
560
  };
909
561
  }
910
- // No session ever recorded a rate-limit event on this machine (or none of
911
- // the ones found were still fresh) — a benign "nothing to show yet", not a
912
- // failure (RUSH-3040). Distinct from the outer catch below, which is a
913
- // genuine read/parse failure.
914
562
  return usageNoRecentUsageInfo();
915
563
  }
916
564
  catch (err) {
917
565
  return { snapshot: null, error: usageUnreachableError('Codex', err) };
918
566
  }
919
567
  }
920
- /**
921
- * The access token to use for a READ-ONLY Claude usage fetch, or null when the
922
- * stored token is within the refresh leeway.
923
- *
924
- * Returns null instead of refreshing on purpose. Claude's refresh token is
925
- * single-use and rotates server-side on every refresh; with one account signed
926
- * into several machines, refreshing here would stampede that one token and
927
- * silently invalidate every other holder — the RUSH-1822 failure, except in the
928
- * usage path (fired in the background by the SWR cache and by `agents run`'s
929
- * default "balanced" rotation on every unpinned run) rather than the health
930
- * probe. So a usage read must never rotate: a near-expiry token yields "no usage
931
- * right now" instead of a fleet-wide logout. Mirrors {@link probeClaudeStatus};
932
- * the single legitimate refresh belongs to the actual claude run, never a read.
933
- * Pure — unit-tested.
934
- */
568
+ // Usage probes never refresh credentials or fall into interactive OAuth; foreground headed reads must opt in explicitly.
935
569
  export function claudeUsageAccessTokenNoRefresh(oauth) {
936
570
  if (claudeAccessTokenNeedsRefresh(oauth.expiresAt ?? null))
937
571
  return null;
938
572
  const token = oauth.accessToken?.trim();
939
573
  return token ? token : null;
940
574
  }
941
- /** Fetch Claude usage via the Anthropic OAuth usage API. */
942
575
  async function getClaudeUsageInfo(options) {
943
576
  try {
944
- // accessTokenCache: this is the every-60s watchdog hot path and usage needs
945
- // only the access token, so it reads ONLY the file-based setup-token and never
946
- // the interactive login (reading that ACL-bound token and firing it at the
947
- // usage API is what got it revoked — RUSH-1822). No setup-token => null =>
948
- // "usage pending". fileOnly additionally forbids the ACL keychain path.
949
- //
950
- // allowInteractiveLogin is the one sanctioned exception (USAGE-READ-1/2): a
951
- // foreground human `agents view` on a `personal` device MAY fall through to
952
- // the interactive login when no setup-token exists, because that login is the
953
- // only credential carrying the `user:profile` scope the usage endpoint
954
- // requires (the setup-token is user:inference → 403, RUSH-2392). It is unset
955
- // for every background caller, so the RUSH-1822 guarantee is untouched there.
956
577
  const oauth = await loadClaudeOauth(options?.home, {
957
578
  accessTokenCache: options?.nativeFileLogin !== true,
958
579
  fileOnly: options?.fileOnly === true || options?.nativeFileLogin === true,
@@ -960,26 +581,17 @@ async function getClaudeUsageInfo(options) {
960
581
  nativeFileLogin: options?.nativeFileLogin === true,
961
582
  });
962
583
  if (!oauth?.accessToken) {
963
- // NOT the shared no-credential message: "sign in" is not a remedy here.
964
- // The account this reads for is usually signed in already — the reader is
965
- // forbidden from touching that login (RUSH-1822) — so the shared wording
966
- // asked the operator to redo the one thing they had already done (#2987).
967
584
  return { snapshot: null, error: usageNoClaudeUsageCredentialError() };
968
585
  }
969
586
  const requestedOrgId = normalizeString(options?.organizationId);
970
587
  const liveOrgId = normalizeString(oauth.organizationUuid);
971
588
  if (!isClaudeUsageOrgMatch(requestedOrgId, liveOrgId)) {
972
- // Not a fault: this home is signed into a different org than the identity
973
- // being read, so there is nothing to report for it.
974
589
  return { snapshot: null, error: null };
975
590
  }
976
- // Read-only: never refresh a single-use token just to read usage (RUSH-1822).
977
591
  const accessToken = claudeUsageAccessTokenNoRefresh(oauth);
978
592
  if (!accessToken) {
979
593
  return { snapshot: null, error: usageExpiredCredentialError('Claude') };
980
594
  }
981
- // Honour a live Retry-After rather than re-arming the penalty (see
982
- // usage-backoff.ts). No request at all while the window is open.
983
595
  const throttledUntil = usageRateLimitedUntil('claude', Date.now(), options?.usageScope);
984
596
  if (throttledUntil) {
985
597
  return { snapshot: null, error: usageThrottledError('Claude', throttledUntil) };
@@ -998,16 +610,12 @@ async function getClaudeUsageInfo(options) {
998
610
  if (response.status === 429) {
999
611
  noteUsageRateLimited('claude', response.headers.get('retry-after'), { account: options?.usageScope });
1000
612
  }
1001
- // Setup-token is user:inference only; usage needs user:profile → 403
1002
- // with a scope-requirement body. Distinct from a real rejection so the
1003
- // UI does not say "unverified" / re-mint (RUSH-2392).
1004
613
  if (response.status === 403) {
1005
614
  let bodyText = '';
1006
615
  try {
1007
616
  bodyText = await response.text();
1008
617
  }
1009
618
  catch {
1010
- // ignore — fall through to generic rejection
1011
619
  }
1012
620
  if (isClaudeUsageScopeDenied(response.status, bodyText)) {
1013
621
  return { snapshot: null, error: usageHeadlessScopeError('Claude') };
@@ -1031,19 +639,9 @@ async function getClaudeUsageInfo(options) {
1031
639
  };
1032
640
  }
1033
641
  catch (err) {
1034
- // A thrown request (timeout, DNS, TLS, a malformed payload) is a failed
1035
- // read like any other — staying silent here would hand the caller a stale
1036
- // snapshot to render as confirmed, which is the bug this file just closed.
1037
642
  return { snapshot: null, error: usageUnreachableError('Claude', err) };
1038
643
  }
1039
644
  }
1040
- /**
1041
- * Resolve Kimi's OAuth credential file. Sign-in is account-global but each
1042
- * installed version has an isolated home; the file physically lives only in the
1043
- * home the user logged in under. Check the per-version home first, then the
1044
- * active location under the real HOME — mirrors resolveAccountCredentialPath in
1045
- * agents.ts so every version reflects the true account state.
1046
- */
1047
645
  function resolveKimiCredentialPath(home) {
1048
646
  const rel = ['.kimi-code', 'credentials', 'kimi-code.json'];
1049
647
  const perVersion = path.join(home || os.homedir(), ...rel);
@@ -1051,14 +649,14 @@ function resolveKimiCredentialPath(home) {
1051
649
  if (fs.existsSync(perVersion))
1052
650
  return perVersion;
1053
651
  }
1054
- catch { /* unreadable */ }
652
+ catch { }
1055
653
  const active = path.join(process.env.AGENTS_REAL_HOME || os.homedir(), ...rel);
1056
654
  if (active !== perVersion) {
1057
655
  try {
1058
656
  if (fs.existsSync(active))
1059
657
  return active;
1060
658
  }
1061
- catch { /* unreadable */ }
659
+ catch { }
1062
660
  }
1063
661
  return null;
1064
662
  }
@@ -1087,8 +685,6 @@ async function getKimiUsageInfo(options) {
1087
685
  if (expiresAt !== null && Date.now() / 1000 >= expiresAt) {
1088
686
  return { snapshot: null, error: usageExpiredKimiCredentialError() };
1089
687
  }
1090
- // Honour a live Retry-After rather than re-arming the penalty (see
1091
- // usage-backoff.ts). No request at all while the window is open.
1092
688
  const throttledUntil = usageRateLimitedUntil('kimi', Date.now(), options?.usageScope);
1093
689
  if (throttledUntil) {
1094
690
  return { snapshot: null, error: usageThrottledError('Kimi', throttledUntil) };
@@ -1101,8 +697,6 @@ async function getKimiUsageInfo(options) {
1101
697
  },
1102
698
  signal: usageFetchSignal(options?.signal, 5000),
1103
699
  });
1104
- // 401/403 => expired token, 404 => no Kimi For Coding subscription. Either
1105
- // way there are no bars to draw, and the status is what tells them apart.
1106
700
  if (!response.ok) {
1107
701
  if (response.status === 429) {
1108
702
  noteUsageRateLimited('kimi', response.headers.get('retry-after'), { account: options?.usageScope });
@@ -1126,29 +720,22 @@ async function getKimiUsageInfo(options) {
1126
720
  };
1127
721
  }
1128
722
  catch (err) {
1129
- // A thrown request (timeout, DNS, TLS, a malformed payload) is a failed
1130
- // read like any other — staying silent here would hand the caller a stale
1131
- // snapshot to render as confirmed, which is the bug this file just closed.
1132
723
  return { snapshot: null, error: usageUnreachableError('Kimi', err) };
1133
724
  }
1134
725
  }
1135
- /** Normalize the Kimi /usages payload into the common UsageWindow shape. */
1136
726
  export function normalizeKimiWindows(data) {
1137
727
  const windows = [];
1138
- // Per-window rate limit (e.g. a 300-minute bucket) -> "session".
1139
728
  const shortLimit = Array.isArray(data.limits)
1140
729
  ? data.limits.find((entry) => entry?.detail)
1141
730
  : null;
1142
731
  const session = normalizeKimiWindow(shortLimit?.detail, 'session', 'Current session', 'S', kimiWindowMinutes(shortLimit?.window));
1143
732
  if (session)
1144
733
  windows.push(session);
1145
- // Rolling account quota -> "week".
1146
734
  const period = normalizeKimiWindow(data.usage, 'week', 'Current period', 'W', null);
1147
735
  if (period)
1148
736
  windows.push(period);
1149
737
  return windows;
1150
738
  }
1151
- /** Normalize a single Kimi quota bucket (used/limit strings) into a UsageWindow. */
1152
739
  function normalizeKimiWindow(quota, key, label, shortLabel, windowMinutes) {
1153
740
  const limit = kimiNumber(quota?.limit);
1154
741
  const used = kimiNumber(quota?.used);
@@ -1166,7 +753,6 @@ function normalizeKimiWindow(quota, key, label, shortLabel, windowMinutes) {
1166
753
  windowMinutes: windowMinutes ?? inferWindowMinutes(key),
1167
754
  };
1168
755
  }
1169
- /** Parse a numeric field that Kimi serializes as a string (e.g. "100"). */
1170
756
  function kimiNumber(value) {
1171
757
  if (typeof value === 'number' && Number.isFinite(value))
1172
758
  return value;
@@ -1175,7 +761,6 @@ function kimiNumber(value) {
1175
761
  }
1176
762
  return null;
1177
763
  }
1178
- /** Convert a Kimi limit window (duration + timeUnit enum) to minutes. */
1179
764
  function kimiWindowMinutes(window) {
1180
765
  const duration = typeof window?.duration === 'number' ? window.duration : null;
1181
766
  if (duration === null || duration <= 0)
@@ -1183,14 +768,13 @@ function kimiWindowMinutes(window) {
1183
768
  switch (window?.timeUnit) {
1184
769
  case 'TIME_UNIT_HOUR': return duration * 60;
1185
770
  case 'TIME_UNIT_SECOND': return duration / 60;
1186
- default: return duration; // TIME_UNIT_MINUTE or unknown -> minutes
771
+ default: return duration;
1187
772
  }
1188
773
  }
1189
- /** Derive a display plan label from Kimi's membership tier or subscription type. */
1190
774
  export function formatKimiPlan(data) {
1191
775
  const level = data.user?.membership?.level;
1192
776
  const raw = (typeof level === 'string' && level) || (typeof data.subType === 'string' && data.subType) || '';
1193
- const tail = raw.split('_').pop() || ''; // LEVEL_INTERMEDIATE -> INTERMEDIATE
777
+ const tail = raw.split('_').pop() || '';
1194
778
  if (!tail)
1195
779
  return null;
1196
780
  return tail.charAt(0).toUpperCase() + tail.slice(1).toLowerCase();
@@ -1221,8 +805,6 @@ async function getDroidUsageInfo(options) {
1221
805
  if (typeof exp === 'number' && Date.now() / 1000 >= exp) {
1222
806
  return { snapshot: null, error: usageExpiredCredentialError('Droid') };
1223
807
  }
1224
- // Honour a live Retry-After rather than re-arming the penalty (see
1225
- // usage-backoff.ts). No request at all while the window is open.
1226
808
  const throttledUntil = usageRateLimitedUntil('droid', Date.now(), options?.usageScope);
1227
809
  if (throttledUntil) {
1228
810
  return { snapshot: null, error: usageThrottledError('Droid', throttledUntil) };
@@ -1235,7 +817,6 @@ async function getDroidUsageInfo(options) {
1235
817
  },
1236
818
  signal: usageFetchSignal(options?.signal, 5000),
1237
819
  });
1238
- // 401 => revoked/expired token. No bars to draw, and the status says why.
1239
820
  if (!response.ok) {
1240
821
  if (response.status === 429) {
1241
822
  noteUsageRateLimited('droid', response.headers.get('retry-after'), { account: options?.usageScope });
@@ -1258,38 +839,17 @@ async function getDroidUsageInfo(options) {
1258
839
  };
1259
840
  }
1260
841
  catch (err) {
1261
- // A thrown request (timeout, DNS, TLS, a malformed payload) is a failed
1262
- // read like any other — staying silent here would hand the caller a stale
1263
- // snapshot to render as confirmed, which is the bug this file just closed.
1264
842
  return { snapshot: null, error: usageUnreachableError('Droid', err) };
1265
843
  }
1266
844
  }
1267
- /** Probe Claude's OAuth token against the usage endpoint. Never refreshes — reports `expired` for a near-expiry token; see the comment below (RUSH-1822). */
1268
845
  export async function probeClaudeStatus(home, cliVersion, usageScope, signal) {
1269
- // accessTokenCache: the daemon warms this probe every ~3 min per account, so it
1270
- // reads ONLY the file-based setup-token and never the interactive login —
1271
- // transmitting that ACL-bound token to the usage API from a background loop is
1272
- // what got it revoked (RUSH-1822). No setup-token => token 'missing' below.
1273
846
  const oauth = await loadClaudeOauth(home, { accessTokenCache: true });
1274
847
  const accessToken = oauth?.accessToken?.trim();
1275
848
  if (!accessToken)
1276
849
  return { status: null, token: 'missing' };
1277
- // Never refresh from a health probe. Claude's refresh token is single-use and
1278
- // rotates on every refresh; with one account signed into several machines the
1279
- // daemon's every-3-min fleet-cache warm (probeLocalFleetAuth -> here) would
1280
- // stampede that one rotating token and silently invalidate every other
1281
- // holder, dropping the fleet to "run /login" (RUSH-1822). Mirror the sibling
1282
- // Kimi/Droid probes, which never refresh: if the stored token is within the
1283
- // refresh leeway of expiry, report the non-fatal `expired` state ("would need
1284
- // a refresh") instead of rotating it, and leave the single legitimate refresh
1285
- // to the run/usage hot path (getClaudeAccessToken).
1286
850
  if (claudeAccessTokenNeedsRefresh(oauth?.expiresAt ?? null)) {
1287
851
  return { status: null, token: 'expired' };
1288
852
  }
1289
- // A probe is a request like any other: while the provider's Retry-After
1290
- // window is open, report the throttle from the recorded state instead of
1291
- // firing again and re-arming it (usage-backoff.ts). This 3-min-cadence
1292
- // probe is what created the loop it now respects.
1293
853
  if (usageRateLimitedUntil('claude', Date.now(), usageScope))
1294
854
  return { status: 429, token: 'present' };
1295
855
  try {
@@ -1306,15 +866,12 @@ export async function probeClaudeStatus(home, cliVersion, usageScope, signal) {
1306
866
  if (response.status === 429) {
1307
867
  noteUsageRateLimited('claude', response.headers.get('retry-after'), { account: usageScope });
1308
868
  }
1309
- // Setup-token is user:inference only; usage needs user:profile → 403.
1310
- // That is NOT a revocation — the account still runs (RUSH-2392).
1311
869
  if (response.status === 403) {
1312
870
  let bodyText = '';
1313
871
  try {
1314
872
  bodyText = await response.text();
1315
873
  }
1316
874
  catch {
1317
- // Body unreadable: fall through to a bare 403 (classified as revoked).
1318
875
  }
1319
876
  if (isClaudeUsageScopeDenied(response.status, bodyText)) {
1320
877
  return {
@@ -1331,7 +888,6 @@ export async function probeClaudeStatus(home, cliVersion, usageScope, signal) {
1331
888
  return { status: null, token: 'present', error: err instanceof Error ? err.message : String(err) };
1332
889
  }
1333
890
  }
1334
- /** Probe Kimi's OAuth token against the /usages endpoint. Never refreshes (single-use rotation — see getKimiUsageInfo). */
1335
891
  export async function probeKimiStatus(home, usageScope, signal) {
1336
892
  const credPath = resolveKimiCredentialPath(home);
1337
893
  if (!credPath)
@@ -1350,12 +906,6 @@ export async function probeKimiStatus(home, usageScope, signal) {
1350
906
  return { status: null, token: 'missing' };
1351
907
  if (expiresAt !== null && Date.now() / 1000 >= expiresAt)
1352
908
  return { status: null, token: 'expired' };
1353
- // A probe is a request like any other: while the provider's Retry-After
1354
- // window is open, report the throttle from the recorded state instead of
1355
- // firing again and re-arming it (usage-backoff.ts). This 3-min-cadence probe
1356
- // is what created the loop it now respects. It sits AFTER the local
1357
- // missing/expired checks — as in probeClaudeStatus and probeDroidStatus — so
1358
- // a genuinely broken credential is never misreported as merely throttled.
1359
909
  if (usageRateLimitedUntil('kimi', Date.now(), usageScope))
1360
910
  return { status: 429, token: 'present' };
1361
911
  try {
@@ -1373,7 +923,6 @@ export async function probeKimiStatus(home, usageScope, signal) {
1373
923
  return { status: null, token: 'present', error: err instanceof Error ? err.message : String(err) };
1374
924
  }
1375
925
  }
1376
- /** Probe Droid's WorkOS token against the billing-limits endpoint. Never refreshes (single-use rotation — see getDroidUsageInfo). */
1377
926
  export async function probeDroidStatus(home, usageScope, signal) {
1378
927
  const cred = decryptDroidAuthPayload(home || os.homedir());
1379
928
  const accessToken = cred?.access_token;
@@ -1382,10 +931,6 @@ export async function probeDroidStatus(home, usageScope, signal) {
1382
931
  const exp = decodeJwtPayload(accessToken)?.exp;
1383
932
  if (typeof exp === 'number' && Date.now() / 1000 >= exp)
1384
933
  return { status: null, token: 'expired' };
1385
- // A probe is a request like any other: while the provider's Retry-After
1386
- // window is open, report the throttle from the recorded state instead of
1387
- // firing again and re-arming it (usage-backoff.ts). This 3-min-cadence
1388
- // probe is what created the loop it now respects.
1389
934
  if (usageRateLimitedUntil('droid', Date.now(), usageScope))
1390
935
  return { status: 429, token: 'present' };
1391
936
  try {
@@ -1403,12 +948,6 @@ export async function probeDroidStatus(home, usageScope, signal) {
1403
948
  return { status: null, token: 'present', error: err instanceof Error ? err.message : String(err) };
1404
949
  }
1405
950
  }
1406
- /**
1407
- * Normalize the Factory billing-limits payload into the common UsageWindow
1408
- * shape. Orgs on the legacy (non token-rate-limit) billing model have no
1409
- * meaningful windows, so they render nothing — mirrors droid's own gate on
1410
- * `usesTokenRateLimitsBilling` before it reads `limits.standard`.
1411
- */
1412
951
  export function normalizeDroidWindows(data) {
1413
952
  if (data.usesTokenRateLimitsBilling !== true)
1414
953
  return [];
@@ -1422,7 +961,6 @@ export function normalizeDroidWindows(data) {
1422
961
  ];
1423
962
  return windows.filter((window) => window !== null);
1424
963
  }
1425
- /** Normalize a single Droid billing-limits window. */
1426
964
  function normalizeDroidWindow(window, key, label, shortLabel) {
1427
965
  const usedPercent = normalizePercent(window?.usedPercent);
1428
966
  if (usedPercent === null)
@@ -1436,14 +974,6 @@ function normalizeDroidWindow(window, key, label, shortLabel) {
1436
974
  windowMinutes: inferWindowMinutes(key),
1437
975
  };
1438
976
  }
1439
- /**
1440
- * Collect Codex JSONL session files sorted newest-first.
1441
- *
1442
- * `sinceMs` drops files modified before it. Codex session transcripts are not
1443
- * tagged with the account that wrote them, so this mtime floor is how usage is
1444
- * kept account-scoped: a session older than the current login belongs to a
1445
- * prior account (see {@link getCodexUsageInfo}).
1446
- */
1447
977
  function collectCodexSessionFiles(home, sinceMs) {
1448
978
  const base = home || os.homedir();
1449
979
  const dir = path.join(base, '.codex', 'sessions');
@@ -1466,7 +996,6 @@ function collectCodexSessionFiles(home, sinceMs) {
1466
996
  files.sort((a, b) => b.mtime - a.mtime);
1467
997
  return files.map((file) => file.path);
1468
998
  }
1469
- /** Stream a Codex JSONL file and return the last rate_limits payload found. */
1470
999
  async function readLatestCodexRateLimits(filePath) {
1471
1000
  return new Promise((resolve) => {
1472
1001
  let latest = null;
@@ -1486,21 +1015,18 @@ async function readLatestCodexRateLimits(filePath) {
1486
1015
  };
1487
1016
  }
1488
1017
  catch {
1489
- /* malformed session line */
1490
1018
  }
1491
1019
  });
1492
1020
  rl.on('close', () => resolve(latest));
1493
1021
  rl.on('error', () => resolve(latest));
1494
1022
  });
1495
1023
  }
1496
- /** Normalize Codex rate-limit windows into the common UsageWindow shape. */
1497
1024
  function normalizeCodexWindows(rateLimits) {
1498
1025
  return [rateLimits.primary, rateLimits.secondary]
1499
1026
  .map(normalizeCodexWindow)
1500
1027
  .filter((window) => window !== null)
1501
1028
  .sort((a, b) => (a.windowMinutes ?? 0) - (b.windowMinutes ?? 0));
1502
1029
  }
1503
- /** Normalize a single Codex rate-limit window. */
1504
1030
  function normalizeCodexWindow(window) {
1505
1031
  const usedPercent = normalizePercent(window?.used_percent);
1506
1032
  if (usedPercent === null)
@@ -1516,7 +1042,6 @@ function normalizeCodexWindow(window) {
1516
1042
  windowMinutes,
1517
1043
  };
1518
1044
  }
1519
- /** Codex assigns quota windows to primary/secondary by plan, so duration carries their meaning. */
1520
1045
  function classifyCodexWindow(windowMinutes) {
1521
1046
  if (windowMinutes !== null && windowMinutes >= 28 * 24 * 60) {
1522
1047
  return { key: 'month', label: 'Current month', shortLabel: 'M' };
@@ -1526,7 +1051,6 @@ function classifyCodexWindow(windowMinutes) {
1526
1051
  }
1527
1052
  return { key: 'session', label: 'Current session', shortLabel: 'S' };
1528
1053
  }
1529
- /** Normalize Claude API usage windows into the common UsageWindow shape. */
1530
1054
  function normalizeClaudeWindows(data) {
1531
1055
  const windows = [
1532
1056
  normalizeClaudeWindow(data.five_hour, 'session', 'Current session', 'S'),
@@ -1535,7 +1059,6 @@ function normalizeClaudeWindows(data) {
1535
1059
  ];
1536
1060
  return windows.filter((window) => window !== null);
1537
1061
  }
1538
- /** Normalize a single Claude API usage window. */
1539
1062
  function normalizeClaudeWindow(window, key, label, shortLabel) {
1540
1063
  const usedPercent = normalizePercent(window?.utilization);
1541
1064
  if (usedPercent === null)
@@ -1549,12 +1072,6 @@ function normalizeClaudeWindow(window, key, label, shortLabel) {
1549
1072
  windowMinutes: inferWindowMinutes(key),
1550
1073
  };
1551
1074
  }
1552
- /**
1553
- * Parse a wrapped Claude OAuth payload — the `{ claudeAiOauth, organizationUuid }`
1554
- * shape written by BOTH the macOS Keychain item and the Linux `.credentials.json`
1555
- * file — into our credential struct. Returns null when there is no usable access
1556
- * token. Never throws (malformed JSON => null).
1557
- */
1558
1075
  function parseClaudeOauthPayload(raw) {
1559
1076
  try {
1560
1077
  const payload = JSON.parse(raw.trim());
@@ -1570,69 +1087,18 @@ function parseClaudeOauthPayload(raw) {
1570
1087
  return null;
1571
1088
  }
1572
1089
  }
1573
- // ── Stale no-ACL Claude OAuth cache eviction (retired subsystem) ──
1574
- //
1575
- // Earlier versions cached Claude's OAuth ACCESS token in a device-local no-ACL
1576
- // keychain item so a read-only usage/probe read wouldn't pop the macOS Touch ID
1577
- // prompt that the ACL-bound source item (`Claude Code-credentials-<hash>`) forces.
1578
- // That cache is retired: read-only probes now authenticate ONLY with a file-based
1579
- // setup-token and never read the interactive login (see loadClaudeOauth), so
1580
- // nothing populates the cache anymore. deleteCachedClaudeOauth remains — a
1581
- // credential rotation still evicts a stale item an earlier version may have
1582
- // written, so an old no-ACL copy of the interactive token can't linger.
1583
1090
  const CLAUDE_OAUTH_CACHE_PREFIX = 'agents-cli.claude-oauth-cache.';
1584
- /** The no-ACL cache item name for a Claude keychain service (hashed to stay tidy). */
1585
1091
  function claudeOauthCacheItem(service) {
1586
1092
  const hash = createHash('sha256').update(service).digest('hex').slice(0, 16);
1587
1093
  return `${CLAUDE_OAUTH_CACHE_PREFIX}${hash}`;
1588
1094
  }
1589
- /**
1590
- * Evict any no-ACL access-token cache item so a source rotation or sign-out is
1591
- * reflected immediately. The cache itself is retired — read-only probes no longer
1592
- * read or write it (loadClaudeOauth returns a file-based setup-token or nothing) —
1593
- * but this eviction remains so a credential rotation still clears a stale cache
1594
- * item that an earlier agents-cli version may have written no-ACL.
1595
- */
1596
1095
  function deleteCachedClaudeOauth(service) {
1597
1096
  try {
1598
1097
  deleteKeychainTokenSync(claudeOauthCacheItem(service));
1599
1098
  }
1600
1099
  catch {
1601
- /* best-effort — cache is an optimization */
1602
1100
  }
1603
1101
  }
1604
- /**
1605
- * Load a version home's Claude OAuth credential from the two stores Claude Code
1606
- * uses, tried in order:
1607
- *
1608
- * 1. The OS keychain (`getKeychainToken`). Canonical on macOS — Claude Code
1609
- * writes the token to the login keychain and we read it via `/usr/bin/security`.
1610
- * 2. `<home>/.claude/.credentials.json`. On a headless Linux box (the
1611
- * `agents view --device <linux>` case) there is no reachable Secret Service, so
1612
- * the Claude CLI stores its OAuth token in this plaintext file instead. The
1613
- * keychain read above finds nothing on that platform, so we fall back to the
1614
- * file. Same wrapped `{ claudeAiOauth }` shape, so one parser handles both.
1615
- *
1616
- * Without step 2 the live usage fetch got no token on Linux, so `agents view`
1617
- * (run remotely over SSH by `--device`) rendered no usage bars even though the
1618
- * account + plan — read from the plaintext `.claude.json` — showed fine.
1619
- *
1620
- * `opts.accessTokenCache` marks a read-only, access-token-only consumer (the
1621
- * usage fetch and the auth-health probe). Such a caller authenticates ONLY with
1622
- * a file-based setup-token and, when none is provisioned, gets `null` — it never
1623
- * reads Claude Code's interactive login (transmitting that ACL-bound OAuth token
1624
- * to Anthropic's API is what gets it revoked; see the branch body and
1625
- * docs/secrets.md). It is OFF by default so full-credential
1626
- * callers that refresh (`isClaudeAuthValid` -> `getClaudeAccessToken`) still
1627
- * read the interactive login. Rush Cloud dispatch does not call this helper
1628
- * at all (SING-1b: the account manifest is email-only; RUSH-2359 removed the
1629
- * leftover blob reader that used to send the interactive login).
1630
- *
1631
- * `opts.fileOnly` skips the ACL keychain read entirely — setup-token and
1632
- * `.credentials.json` only. Used by the daemon usage refresher so a background
1633
- * tick can never pop Touch ID.
1634
- */
1635
- /** True when `<home>/.claude/.credentials.json` is a native rotating OAuth blob. */
1636
1102
  export function claudeHomeHasNativeOauthFile(home) {
1637
1103
  return readClaudeNativeCredentialsFile(home) !== null;
1638
1104
  }
@@ -1642,8 +1108,6 @@ function readClaudeNativeCredentialsFile(home) {
1642
1108
  if (!fs.existsSync(credsPath))
1643
1109
  return null;
1644
1110
  const parsed = parseClaudeOauthPayload(fs.readFileSync(credsPath, 'utf-8'));
1645
- // A native rotating blob has a refresh token. A setup-token-shaped file
1646
- // (access only) is not a native login and must not be polled as one.
1647
1111
  if (!parsed?.accessToken?.trim() || !parsed.refreshToken?.trim())
1648
1112
  return null;
1649
1113
  return parsed;
@@ -1653,55 +1117,18 @@ function readClaudeNativeCredentialsFile(home) {
1653
1117
  }
1654
1118
  }
1655
1119
  export async function loadClaudeOauth(home, opts) {
1656
- // Headed usage poller: the native rotating blob in `.credentials.json` is
1657
- // the only credential that carries `user:profile` without opening the ACL
1658
- // keychain (Touch ID) or firing a setup-token that 403s on /oauth/usage.
1659
1120
  if (opts?.nativeFileLogin === true) {
1660
1121
  return readClaudeNativeCredentialsFile(home);
1661
1122
  }
1662
- // Read-only usage/probe callers (accessTokenCache) authenticate ONLY with a
1663
- // file-based setup-token from the `auth` bundle — never Claude Code's
1664
- // interactive login. The usage endpoint accepts any sk-ant-oat01 bearer, and
1665
- // the file-based token never pops Touch ID. When no setup-token is provisioned
1666
- // the probe reports unprovisioned rather than reading the interactive
1667
- // credential (see below) — that is the whole point of this branch.
1668
1123
  if (opts?.accessTokenCache === true) {
1669
1124
  const setupToken = resolveClaudeSetupToken(home);
1670
1125
  if (setupToken) {
1671
- // No expiresAt: a setup-token is long-lived and non-rotating, and a null
1672
- // expiry reads as "still fresh" (claudeAccessTokenNeedsRefresh) so the
1673
- // probe never reports it expired or tries to refresh it. The endpoint is
1674
- // the source of truth if it has actually been revoked.
1675
1126
  return { accessToken: setupToken };
1676
1127
  }
1677
- // No provisioned setup-token. A read-only usage/health probe MUST NOT fall
1678
- // through to Claude Code's interactive login credential. The daemon's usage
1679
- // (~60s) and auth-health (~3min) warms would otherwise read the ACL-bound
1680
- // OAuth token and transmit it to api.anthropic.com/api/oauth/usage — an
1681
- // interactive credential used programmatically, which Anthropic flags and
1682
- // revokes (the fleet-wide-logout class, RUSH-1822), and which violates the
1683
- // invariant that the interactive/rotating login is untouchable
1684
- // (docs/secrets.md). Report unprovisioned (-> probe
1685
- // token 'missing' -> auth-health 'unconfigured', benign for rotation); seed a
1686
- // setup-token via the mint-auth path to restore usage/probe for the account.
1687
- //
1688
- // The single sanctioned exception (USAGE-READ-1/2): a foreground human
1689
- // `agents view` on a headed device (personal or desktop) sets allowInteractiveLogin, and only
1690
- // then do we fall through to the interactive-login read below — the one
1691
- // credential carrying `user:profile`, which the usage endpoint requires. This
1692
- // is a human running one command, not an unattended loop, so it is not the
1693
- // revocation risk RUSH-1822 fixed. Every background caller leaves the flag
1694
- // unset and still returns null here.
1695
1128
  if (opts?.allowInteractiveLogin !== true) {
1696
1129
  return null;
1697
1130
  }
1698
1131
  }
1699
- // Full-credential callers (isClaudeAuthValid -> getClaudeAccessToken)
1700
- // legitimately read the interactive login to run/refresh Claude. Rush Cloud
1701
- // dispatch does not (SING-1b / RUSH-2359). The OS keychain/keyring step is
1702
- // macOS/Linux-only; Windows and any
1703
- // fileOnly caller skip to the .credentials.json read below (the Claude CLI
1704
- // stores its OAuth token in that file too).
1705
1132
  if (!opts?.fileOnly && (process.platform === 'darwin' || process.platform === 'linux')) {
1706
1133
  const service = getClaudeKeychainService(home);
1707
1134
  try {
@@ -1710,7 +1137,6 @@ export async function loadClaudeOauth(home, opts) {
1710
1137
  return fromKeychain;
1711
1138
  }
1712
1139
  catch {
1713
- // No keychain item, or no reachable keyring (headless Linux) — fall through.
1714
1140
  }
1715
1141
  }
1716
1142
  const credsPath = path.join(home ?? os.homedir(), '.claude', '.credentials.json');
@@ -1720,33 +1146,22 @@ export async function loadClaudeOauth(home, opts) {
1720
1146
  }
1721
1147
  }
1722
1148
  catch {
1723
- // Unreadable file — treat as not signed in.
1724
1149
  }
1725
1150
  return null;
1726
1151
  }
1727
- /**
1728
- * Save Claude OAuth credentials to the system keychain/keyring.
1729
- * Reads the existing payload, merges the new OAuth fields, and writes back.
1730
- * Exported for regression tests; not part of the public command surface.
1731
- */
1732
1152
  async function saveClaudeOauth(home, credentials) {
1733
- // Windows not yet supported: Claude Code keeps its credential in the file
1734
- // there, so the rotated credential is written by the harness, not here.
1735
1153
  if (process.platform !== 'darwin' && process.platform !== 'linux') {
1736
1154
  return false;
1737
1155
  }
1738
1156
  try {
1739
1157
  const service = getClaudeKeychainService(home);
1740
- // Read existing payload to preserve other fields
1741
1158
  let existingPayload = {};
1742
1159
  try {
1743
1160
  const stdout = getKeychainTokenSync(service);
1744
1161
  existingPayload = JSON.parse(stdout.trim());
1745
1162
  }
1746
1163
  catch {
1747
- // No existing entry, start fresh
1748
1164
  }
1749
- // Merge new credentials into existing payload
1750
1165
  const newPayload = {
1751
1166
  ...existingPayload,
1752
1167
  claudeAiOauth: {
@@ -1758,15 +1173,12 @@ async function saveClaudeOauth(home, credentials) {
1758
1173
  },
1759
1174
  };
1760
1175
  const payloadJson = JSON.stringify(newPayload);
1761
- // Delete existing entry first, then add updated entry
1762
1176
  try {
1763
1177
  await deleteKeychainToken(service);
1764
1178
  }
1765
1179
  catch {
1766
- // Entry might not exist, ignore
1767
1180
  }
1768
1181
  await setKeychainToken(service, payloadJson);
1769
- // A new credential rotation means any cached access token is stale.
1770
1182
  deleteCachedClaudeOauth(service);
1771
1183
  return true;
1772
1184
  }
@@ -1774,10 +1186,6 @@ async function saveClaudeOauth(home, credentials) {
1774
1186
  return false;
1775
1187
  }
1776
1188
  }
1777
- /**
1778
- * Derive the Keychain service name for a Claude home directory.
1779
- * Managed (non-default) homes get a hash suffix for isolation.
1780
- */
1781
1189
  export function getClaudeKeychainService(home) {
1782
1190
  if (!home) {
1783
1191
  return CLAUDE_KEYCHAIN_SERVICE;
@@ -1786,16 +1194,12 @@ export function getClaudeKeychainService(home) {
1786
1194
  const hash = createHash('sha256').update(configDir).digest('hex').slice(0, 8);
1787
1195
  return `${CLAUDE_KEYCHAIN_SERVICE}-${hash}`;
1788
1196
  }
1789
- /**
1790
- * Check whether a requested org ID matches the live OAuth org ID.
1791
- * Returns true when either is absent (no filtering) or when they match.
1792
- */
1197
+ // Organization identity guards attribution because different accounts can share email and home labels.
1793
1198
  export function isClaudeUsageOrgMatch(requestedOrgId, liveOrgId) {
1794
1199
  const requested = normalizeString(requestedOrgId);
1795
1200
  const live = normalizeString(liveOrgId);
1796
1201
  return !requested || !live || requested === live;
1797
1202
  }
1798
- /** Read a cached usage snapshot for a given usage key. Returns null if absent or stale. */
1799
1203
  export function readClaudeUsageCache(usageKey, cachePath = getClaudeUsageCachePath(), now = new Date()) {
1800
1204
  const cache = readClaudeUsageCacheFile(cachePath);
1801
1205
  const cached = cache[usageKey];
@@ -1808,13 +1212,10 @@ export function readClaudeUsageCache(usageKey, cachePath = getClaudeUsageCachePa
1808
1212
  }
1809
1213
  return snapshot;
1810
1214
  }
1811
- /** Delete an expired cache row only if it is still expired under the write lock. */
1812
1215
  export function pruneExpiredClaudeUsageCacheEntry(usageKey, cachePath = getClaudeUsageCachePath(), now = new Date()) {
1813
1216
  try {
1814
1217
  ensureLockTarget(cachePath, '{}');
1815
1218
  withFileLock(cachePath, () => {
1816
- // The row may have been refreshed after readClaudeUsageCache observed it.
1817
- // Re-read under the lock so stale cleanup cannot erase that newer write.
1818
1219
  const latest = readClaudeUsageCacheFile(cachePath);
1819
1220
  const current = latest[usageKey];
1820
1221
  if (!current || deserializeClaudeUsageSnapshot(current, now))
@@ -1824,16 +1225,12 @@ export function pruneExpiredClaudeUsageCacheEntry(usageKey, cachePath = getClaud
1824
1225
  });
1825
1226
  }
1826
1227
  catch {
1827
- /* best-effort cache cleanup — lock busy or disk full */
1828
1228
  }
1829
1229
  }
1830
- /** Write a usage snapshot to the on-disk cache. */
1831
1230
  export function writeClaudeUsageCache(usageKey, snapshot, cachePath = getClaudeUsageCachePath()) {
1832
1231
  try {
1833
1232
  ensureLockTarget(cachePath, '{}');
1834
1233
  withFileLock(cachePath, () => {
1835
- // Re-read under the lock so a concurrent daemon tick / agents view
1836
- // refresh cannot drop another account's row (lost update).
1837
1234
  const cache = readClaudeUsageCacheFile(cachePath);
1838
1235
  const prior = cache[usageKey];
1839
1236
  cache[usageKey] = {
@@ -1841,20 +1238,14 @@ export function writeClaudeUsageCache(usageKey, snapshot, cachePath = getClaudeU
1841
1238
  ...snapshot,
1842
1239
  unavailable: carryForwardUnavailable(prior?.unavailable, snapshot.unavailable),
1843
1240
  }),
1844
- // A per-model refusal has its own independent lifecycle (see
1845
- // noteClaudeModelRefusal / clearClaudeModelRefusal) — a global usage
1846
- // write must never drop it, the same reason `unavailable` is carried
1847
- // forward above rather than overwritten.
1848
1241
  modelRefusals: prior?.modelRefusals,
1849
1242
  };
1850
1243
  atomicWriteFileSync(cachePath, JSON.stringify(cache, null, 2), 'utf-8');
1851
1244
  });
1852
1245
  }
1853
1246
  catch {
1854
- /* best-effort cache write — lock busy or disk full */
1855
1247
  }
1856
1248
  }
1857
- /** Atomically merge partial native Claude windows into the current fresh row. */
1858
1249
  export function mergeClaudeUsageCacheWindows(usageKey, snapshot, cachePath = getClaudeUsageCachePath()) {
1859
1250
  try {
1860
1251
  ensureLockTarget(cachePath, '{}');
@@ -1874,22 +1265,14 @@ export function mergeClaudeUsageCacheWindows(usageKey, snapshot, cachePath = get
1874
1265
  plan: snapshot.plan ?? priorSnapshot?.plan ?? null,
1875
1266
  unavailable: carryForwardUnavailable(prior?.unavailable, snapshot.unavailable),
1876
1267
  }),
1877
- // See writeClaudeUsageCache: a per-model refusal survives a windows-only merge too.
1878
1268
  modelRefusals: prior?.modelRefusals,
1879
1269
  };
1880
1270
  atomicWriteFileSync(cachePath, JSON.stringify(cache, null, 2), 'utf-8');
1881
1271
  });
1882
1272
  }
1883
1273
  catch {
1884
- /* best-effort cache write — lock busy or disk full */
1885
1274
  }
1886
1275
  }
1887
- /**
1888
- * Export the local usage cache rows worth publishing to fleet peers (PHNX-3392
1889
- * usage-sync). Returns the raw serialized rows keyed by usage identity, filtered
1890
- * to those carrying at least one window — an empty row has nothing to teach a
1891
- * worker. The transport is the on-disk cache form, so there is no Date round-trip.
1892
- */
1893
1276
  export function exportClaudeUsageCacheRows(cachePath = getClaudeUsageCachePath()) {
1894
1277
  const cache = readClaudeUsageCacheFile(cachePath);
1895
1278
  const out = {};
@@ -1905,26 +1288,6 @@ function parseCapturedAtMs(capturedAt) {
1905
1288
  const ms = Date.parse(capturedAt);
1906
1289
  return Number.isFinite(ms) ? ms : null;
1907
1290
  }
1908
- /**
1909
- * Merge usage rows received from a fleet peer into the local cache, NEWEST-WINS
1910
- * per identity by `capturedAt` (PHNX-3392 usage-sync). A worker has no local
1911
- * usage writer, so an incoming row is almost always the freshest it will get; the
1912
- * timestamp guard exists so a stale push from one headed peer can never overwrite
1913
- * a fresher row another peer (or, on a headed receiver, the local status-line)
1914
- * already wrote. An incoming row with no `capturedAt` cannot prove it is newer, so
1915
- * it never displaces an existing timestamped row. Returns the count updated.
1916
- * Locked + atomic like every other cache writer, but through the ASYNC lock: it
1917
- * runs on the daemon's usage-sync tick once per peer reply (PHNX-4116), where
1918
- * the sync lock's `sleepSync` would freeze every other service under contention.
1919
- *
1920
- * Deliberately NOT role-gated on the receiver. "Consume only on worker/unmarked"
1921
- * is a SENDER-side optimization (don't waste a push on a headed peer that reads
1922
- * its own usage), not a safety invariant — the actual safety property is this
1923
- * newest-wins guard. Receiving on a headed box is harmless (its fresher local
1924
- * status-line row survives) or helpful (an account it is signed into but never
1925
- * runs now shows a usage bar), so gating here on the receiver's own — laggier —
1926
- * view of its role would only reject legitimate data.
1927
- */
1928
1291
  export async function ingestPeerClaudeUsageRows(rows, cachePath = getClaudeUsageCachePath()) {
1929
1292
  const incoming = Object.entries(rows).filter(([, row]) => row && Array.isArray(row.windows) && row.windows.length > 0);
1930
1293
  if (incoming.length === 0)
@@ -1939,7 +1302,6 @@ export async function ingestPeerClaudeUsageRows(rows, cachePath = getClaudeUsage
1939
1302
  if (prior) {
1940
1303
  const priorMs = parseCapturedAtMs(prior.capturedAt);
1941
1304
  const incomingMs = parseCapturedAtMs(row.capturedAt);
1942
- // Keep local unless the incoming row PROVES it is strictly newer.
1943
1305
  if (incomingMs === null)
1944
1306
  continue;
1945
1307
  if (priorMs !== null && priorMs >= incomingMs)
@@ -1953,11 +1315,9 @@ export async function ingestPeerClaudeUsageRows(rows, cachePath = getClaudeUsage
1953
1315
  });
1954
1316
  }
1955
1317
  catch {
1956
- /* best-effort cache write — lock busy or disk full */
1957
1318
  }
1958
1319
  return merged;
1959
1320
  }
1960
- /** Read the entire usage cache file from disk. */
1961
1321
  function readClaudeUsageCacheFile(cachePath) {
1962
1322
  if (!fs.existsSync(cachePath)) {
1963
1323
  return {};
@@ -1970,28 +1330,15 @@ function readClaudeUsageCacheFile(cachePath) {
1970
1330
  return {};
1971
1331
  }
1972
1332
  }
1973
- /** Write the entire usage cache to disk. Best-effort; failures are silent. */
1974
1333
  function writeClaudeUsageCacheFile(cache, cachePath) {
1975
1334
  try {
1976
1335
  fs.mkdirSync(path.dirname(cachePath), { recursive: true });
1977
1336
  atomicWriteFileSync(cachePath, JSON.stringify(cache, null, 2), 'utf-8');
1978
1337
  }
1979
1338
  catch {
1980
- /* best-effort cache write */
1981
1339
  }
1982
1340
  }
1983
- /** Convert a live UsageSnapshot to its JSON-serializable cached form. */
1984
1341
  function serializeClaudeUsageSnapshot(snapshot) {
1985
- // Persist the union of fresh `windows` and last-known `staleWindows`.
1986
- // `deserializeClaudeUsageSnapshot` re-runs the freshness gate on read and
1987
- // re-partitions the serialized windows into fresh vs. stale, so what matters
1988
- // is that every last-known reading reaches disk. Claude's collector returns
1989
- // raw windows (no `staleWindows`) and relies on that read-side partition. But
1990
- // Grok's collector pre-partitions in the fetch, moving an ended-period reading
1991
- // onto `staleWindows` — serializing only `windows` dropped it, so the very
1992
- // number a daemon `--refresh` just captured was gone from the next cached
1993
- // `agents view grok`, which rendered the plan alone (no bar). Include the
1994
- // stale windows here so the round-trip preserves them for any collector.
1995
1342
  const persistedWindows = [...snapshot.windows, ...(snapshot.staleWindows ?? [])];
1996
1343
  return {
1997
1344
  capturedAt: snapshot.capturedAt?.toISOString() || null,
@@ -2015,24 +1362,6 @@ function serializeClaudeUsageSnapshot(snapshot) {
2015
1362
  pollerDevice: snapshot.freshness?.poller,
2016
1363
  };
2017
1364
  }
2018
- /**
2019
- * Deserialize a cached snapshot, dropping windows whose reset time has passed.
2020
- *
2021
- * An expired window is UNKNOWN, not 0%: the counter reset, and anything may
2022
- * have burned since. Zeroing-but-keeping it (the previous behavior) rendered a
2023
- * weeks-frozen cache as "S: 0% (now)" with `deriveUsageStatusFromSnapshot` →
2024
- * 'available', so a genuinely rate-limited account read as an idle dispatch
2025
- * candidate (RUSH-2858). Dropping keeps them out of `windows` (routing stays
2026
- * blind), but they are preserved on `staleWindows` so the view can render the
2027
- * last-known number with its age instead of a bare "unavailable" — a row that
2028
- * carries only stale windows therefore survives (it is worth showing), and only
2029
- * a row with NOTHING to show — no fresh window, no stale window, no plan, no
2030
- * refusal — deserializes to null so `readClaudeUsageCache` deletes it.
2031
- *
2032
- * A row that carries a plan survives even with no fresh windows: the plan is a
2033
- * truthful reading in its own right, and losing it is what made the cached view
2034
- * contradict the refreshed one for meterless harnesses. See the guard below.
2035
- */
2036
1365
  function deserializeClaudeUsageSnapshot(snapshot, now) {
2037
1366
  const capturedAt = parseDateValue(snapshot.capturedAt);
2038
1367
  const deserialized = snapshot.windows.map((window) => ({
@@ -2044,23 +1373,9 @@ function deserializeClaudeUsageSnapshot(snapshot, now) {
2044
1373
  windowMinutes: window.windowMinutes,
2045
1374
  }));
2046
1375
  const windows = deserialized.filter((window) => isCachedUsageWindowFresh(window, capturedAt, now));
2047
- // The dropped windows are still the LAST reading we saw for those meters —
2048
- // routing must not trust them (they stay out of `windows`), but the view
2049
- // renders them with an age suffix rather than a bare "unavailable" (see
2050
- // UsageSnapshot.staleWindows). Skip any meter that already has a fresh row.
2051
1376
  const freshKeys = new Set(windows.map((window) => window.key));
2052
1377
  const staleWindows = deserialized.filter((window) => !freshKeys.has(window.key) && !isCachedUsageWindowFresh(window, capturedAt, now));
2053
1378
  const unavailable = deserializeUnavailable(snapshot.unavailable, now);
2054
- // A windowless row is not automatically worthless. Grok's collector reports
2055
- // the subscription tier and no meters at all, so treating "no fresh windows"
2056
- // as "nothing cached" deleted the only truthful thing we knew about the
2057
- // account: `--refresh` wrote {plan: 'SuperGrok Heavy', windows: []}, the very
2058
- // next plain `agents view` deserialized it to null, `readClaudeUsageCache`
2059
- // pruned the row, and the row rendered "usage unavailable" one read after a
2060
- // successful refresh. Keep a plan-bearing row — it renders as the plan alone,
2061
- // and `deriveUsageStatusFromSnapshot` still returns null for zero windows, so
2062
- // it can never read as a 0% bar or an "available" badge (the RUSH-2858
2063
- // property that made expired windows drop in the first place).
2064
1379
  if (windows.length === 0 &&
2065
1380
  staleWindows.length === 0 &&
2066
1381
  !unavailable &&
@@ -2083,13 +1398,6 @@ function deserializeClaudeUsageSnapshot(snapshot, now) {
2083
1398
  : undefined,
2084
1399
  };
2085
1400
  }
2086
- /**
2087
- * Carry a prior refusal marker forward across a daemon usage refresh, and drop
2088
- * an expired one. A live `snapshot.unavailable` (a refusal just observed) wins.
2089
- * `out_of_credits` survives refreshes with no reset — only a successful run
2090
- * clears it (clearClaudeAccountRefusal). A `session_limit` survives only while
2091
- * its reset time is still in the future.
2092
- */
2093
1401
  function carryForwardUnavailable(prior, live) {
2094
1402
  if (live)
2095
1403
  return live;
@@ -2102,10 +1410,6 @@ function carryForwardUnavailable(prior, live) {
2102
1410
  ? { reason: 'session_limit', resetsAt: reset }
2103
1411
  : undefined;
2104
1412
  }
2105
- /**
2106
- * Deserialize a cached `unavailable` marker, dropping an expired session_limit
2107
- * but keeping a clock-less out_of_credits.
2108
- */
2109
1413
  function deserializeUnavailable(cached, now) {
2110
1414
  if (!cached)
2111
1415
  return undefined;
@@ -2116,23 +1420,16 @@ function deserializeUnavailable(cached, now) {
2116
1420
  ? { reason: 'session_limit', resetsAt: reset }
2117
1421
  : undefined;
2118
1422
  }
2119
- /** Whether any per-model refusal in the row is still live (not clock-expired). */
2120
1423
  function hasLiveModelRefusal(modelRefusals, now) {
2121
1424
  if (!modelRefusals)
2122
1425
  return false;
2123
1426
  return Object.values(modelRefusals).some((entry) => {
2124
1427
  if (!entry.resetsAt)
2125
- return true; // no clock given — sticky until cleared
1428
+ return true;
2126
1429
  const reset = parseDateValue(entry.resetsAt);
2127
1430
  return !reset || reset.getTime() > now.getTime();
2128
1431
  });
2129
1432
  }
2130
- /**
2131
- * Persist a Claude tokens/credits exhaustion (`out of usage credits` / `monthly
2132
- * spend limit`) from a real run. Unlike a rate/session limit this does NOT reset
2133
- * on a clock, so no reset time is stored — rotation excludes the account until a
2134
- * later successful run clears it via {@link clearClaudeAccountRefusal}.
2135
- */
2136
1433
  export function noteClaudeOutOfCredits(usageKey, cachePath = getClaudeUsageCachePath()) {
2137
1434
  try {
2138
1435
  ensureLockTarget(cachePath, '{}');
@@ -2144,14 +1441,8 @@ export function noteClaudeOutOfCredits(usageKey, cachePath = getClaudeUsageCache
2144
1441
  });
2145
1442
  }
2146
1443
  catch {
2147
- /* best-effort cache write — lock busy or disk full */
2148
1444
  }
2149
1445
  }
2150
- /**
2151
- * Clear any persisted refusal marker for an account after a run SUCCEEDS on it.
2152
- * This is the recovery path for `out_of_credits` (which has no clock) and also
2153
- * proactively clears a stale `session_limit` the moment the account serves again.
2154
- */
2155
1446
  export function clearClaudeAccountRefusal(usageKey, cachePath = getClaudeUsageCachePath()) {
2156
1447
  try {
2157
1448
  if (!fs.existsSync(cachePath))
@@ -2167,13 +1458,8 @@ export function clearClaudeAccountRefusal(usageKey, cachePath = getClaudeUsageCa
2167
1458
  });
2168
1459
  }
2169
1460
  catch {
2170
- /* best-effort cache write */
2171
1461
  }
2172
1462
  }
2173
- /**
2174
- * Persist a Claude session-limit refusal from a real run until its stated reset.
2175
- * This quota is not part of Anthropic's five-hour/weekly usage response.
2176
- */
2177
1463
  export function noteClaudeSessionLimit(usageKey, resetsAt, cachePath = getClaudeUsageCachePath()) {
2178
1464
  try {
2179
1465
  ensureLockTarget(cachePath, '{}');
@@ -2188,23 +1474,8 @@ export function noteClaudeSessionLimit(usageKey, resetsAt, cachePath = getClaude
2188
1474
  });
2189
1475
  }
2190
1476
  catch {
2191
- /* best-effort cache write — lock busy or disk full */
2192
1477
  }
2193
1478
  }
2194
- /**
2195
- * Persist a Claude MODEL-specific refusal — "You've reached your Fable limit.
2196
- * Run /usage-credits to continue or switch models with /model." — a distinct
2197
- * class from {@link noteClaudeOutOfCredits} / {@link noteClaudeSessionLimit}:
2198
- * those exclude the whole account, this excludes only ONE model on it (an
2199
- * organization quota group can meter models separately). `accountKey` MUST be
2200
- * the candidate's stable native-account key (see `candidateAccountKey` in
2201
- * rotate.ts), never the org-shared `usageKey` — using the org key here would
2202
- * poison every sibling account under that org for a limit that named one
2203
- * model on one login. No invented reset: `resetsAt` is written only when the
2204
- * refusal text carried one; otherwise the marker is sticky until a later
2205
- * successful run on this exact (account, model) clears it via
2206
- * {@link clearClaudeModelRefusal}.
2207
- */
2208
1479
  export function claudeModelRefusalKey(accountId, home) {
2209
1480
  if (accountId)
2210
1481
  return `account:${accountId}`;
@@ -2237,16 +1508,8 @@ export function noteClaudeModelRefusal(accountKey, model, refusal, cachePath = g
2237
1508
  });
2238
1509
  }
2239
1510
  catch {
2240
- /* best-effort cache write — lock busy or disk full */
2241
1511
  }
2242
1512
  }
2243
- /**
2244
- * Clear a persisted model-refusal marker for exactly ONE (account, model)
2245
- * pair after a run SUCCEEDS on that same account+model. Never clears a
2246
- * sibling model on the same account, and never fires for an interactive
2247
- * detach or an unknown outcome — the caller must have demonstrated an actual
2248
- * completed success on this exact model before calling this.
2249
- */
2250
1513
  export function clearClaudeModelRefusal(accountKey, model, cachePath = getClaudeUsageCachePath()) {
2251
1514
  model = modelFamily(model);
2252
1515
  try {
@@ -2267,15 +1530,8 @@ export function clearClaudeModelRefusal(accountKey, model, cachePath = getClaude
2267
1530
  });
2268
1531
  }
2269
1532
  catch {
2270
- /* best-effort cache write */
2271
1533
  }
2272
1534
  }
2273
- /**
2274
- * Read a live (non-expired) model-refusal marker for (accountKey, model), or
2275
- * null when none is recorded or the recorded one has passed its clock. A
2276
- * marker with no `resetsAt` never expires here — it is sticky until
2277
- * {@link clearClaudeModelRefusal} observes a real success.
2278
- */
2279
1535
  export function getClaudeModelRefusal(accountKey, model, nowMs = Date.now(), cachePath = getClaudeUsageCachePath()) {
2280
1536
  const cache = readClaudeUsageCacheFile(cachePath);
2281
1537
  const entry = cache[accountKey]?.modelRefusals?.[modelFamily(model)];
@@ -2289,14 +1545,6 @@ export function getClaudeModelRefusal(accountKey, model, nowMs = Date.now(), cac
2289
1545
  }
2290
1546
  return { family: entry.family, resetsAt: null };
2291
1547
  }
2292
- /**
2293
- * Parse Claude's model-specific refusal — the CLI's own phrasing when ONE
2294
- * model's quota is exhausted while the account otherwise keeps serving:
2295
- * "You've reached your Fable limit. Run /usage-credits to continue or switch
2296
- * models with /model." Deliberately narrow (unlike the broad RATE_LIMIT_PATTERNS
2297
- * scan) so a session that merely discusses `/usage-credits` cannot false-positive.
2298
- * Tolerates both a straight and curly apostrophe.
2299
- */
2300
1548
  export function parseClaudeModelRefusal(text) {
2301
1549
  const candidates = [text];
2302
1550
  for (const line of text.split('\n')) {
@@ -2308,7 +1556,7 @@ export function parseClaudeModelRefusal(text) {
2308
1556
  candidates.push(row.message.content.filter((block) => block.type === 'text').map((block) => block.text ?? '').join('\n'));
2309
1557
  }
2310
1558
  }
2311
- catch { /* Plain terminal output is checked directly. */ }
1559
+ catch { }
2312
1560
  }
2313
1561
  for (const candidate of candidates) {
2314
1562
  const match = /(?:^|\n)\s*You['’]ve reached your ([^\n.]+) limit\.\s*Run \/usage-credits to continue or switch models with \/model\./i.exec(candidate);
@@ -2317,7 +1565,6 @@ export function parseClaudeModelRefusal(text) {
2317
1565
  }
2318
1566
  return null;
2319
1567
  }
2320
- /** Parse Claude's `hit your session limit · resets …` refusal. */
2321
1568
  export function parseClaudeSessionLimitReset(text, nowMs = Date.now()) {
2322
1569
  if (!/hit your session limit/i.test(text))
2323
1570
  return null;
@@ -2360,7 +1607,6 @@ export function parseClaudeSessionLimitReset(text, nowMs = Date.now()) {
2360
1607
  return null;
2361
1608
  }
2362
1609
  }
2363
- /** Check whether a cached usage window is still relevant (not expired or reset). */
2364
1610
  function isCachedUsageWindowFresh(window, capturedAt, now) {
2365
1611
  if (window.resetsAt && window.resetsAt.getTime() <= now.getTime()) {
2366
1612
  return false;
@@ -2373,7 +1619,6 @@ function isCachedUsageWindowFresh(window, capturedAt, now) {
2373
1619
  }
2374
1620
  return true;
2375
1621
  }
2376
- /** Obtain a valid access token, refreshing if expired. Saves refreshed tokens to Keychain. */
2377
1622
  async function getClaudeAccessToken(oauth, home) {
2378
1623
  const accessToken = oauth.accessToken?.trim();
2379
1624
  if (!accessToken) {
@@ -2389,11 +1634,9 @@ async function getClaudeAccessToken(oauth, home) {
2389
1634
  if (!refreshed?.accessToken) {
2390
1635
  return null;
2391
1636
  }
2392
- // Persist refreshed credentials to Keychain so they survive across runs
2393
1637
  await saveClaudeOauth(home, refreshed);
2394
1638
  return refreshed.accessToken.trim();
2395
1639
  }
2396
- /** Refresh an expired Claude OAuth access token using the refresh token. */
2397
1640
  async function refreshClaudeToken(oauth) {
2398
1641
  const response = await fetch(CLAUDE_TOKEN_URL, {
2399
1642
  method: 'POST',
@@ -2422,11 +1665,6 @@ async function refreshClaudeToken(oauth) {
2422
1665
  scopes: data.scope ? data.scope.split(/\s+/).filter(Boolean) : (oauth.scopes || CLAUDE_SCOPES),
2423
1666
  };
2424
1667
  }
2425
- /**
2426
- * Check whether the Claude OAuth credentials for a given home are usable.
2427
- * Attempts a token refresh if the access token is expired.
2428
- * Returns true only when a valid access token can be obtained.
2429
- */
2430
1668
  export async function isClaudeAuthValid(home) {
2431
1669
  const oauth = await loadClaudeOauth(home);
2432
1670
  if (!oauth)
@@ -2434,25 +1672,21 @@ export async function isClaudeAuthValid(home) {
2434
1672
  const token = await getClaudeAccessToken(oauth, home);
2435
1673
  return token !== null;
2436
1674
  }
2437
- /** Build a User-Agent string for Claude API requests. */
2438
1675
  function getClaudeUserAgent(cliVersion) {
2439
1676
  return cliVersion ? `claude-code/${cliVersion}` : 'claude-code';
2440
1677
  }
2441
- /** Clamp a numeric value to 0..100, returning null for non-finite values. */
2442
1678
  function normalizePercent(value) {
2443
1679
  if (typeof value !== 'number' || !Number.isFinite(value)) {
2444
1680
  return null;
2445
1681
  }
2446
1682
  return Math.max(0, Math.min(100, value));
2447
1683
  }
2448
- /** Validate and return a positive window duration, or null. */
2449
1684
  function normalizeWindowMinutes(value) {
2450
1685
  if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
2451
1686
  return null;
2452
1687
  }
2453
1688
  return value;
2454
1689
  }
2455
- /** Infer the window duration in minutes from a well-known window key. */
2456
1690
  function inferWindowMinutes(key) {
2457
1691
  switch (key) {
2458
1692
  case 'session':
@@ -2464,7 +1698,6 @@ function inferWindowMinutes(key) {
2464
1698
  return 43200;
2465
1699
  }
2466
1700
  }
2467
- /** Parse a date value from a number (epoch seconds or ms) or ISO string. */
2468
1701
  function parseDateValue(value) {
2469
1702
  if (value === null || value === undefined || value === '') {
2470
1703
  return null;
@@ -2482,22 +1715,18 @@ function parseDateValue(value) {
2482
1715
  }
2483
1716
  return null;
2484
1717
  }
2485
- /** Trim and return a string, or null if empty/non-string. */
2486
1718
  function normalizeString(value) {
2487
1719
  if (typeof value !== 'string')
2488
1720
  return null;
2489
1721
  const trimmed = value.trim();
2490
1722
  return trimmed || null;
2491
1723
  }
2492
- /** Render a full-width usage bar for detailed views. */
2493
1724
  function renderUsageBar(usedPercent) {
2494
1725
  return renderBar(usedPercent, USAGE_BAR_LEN);
2495
1726
  }
2496
- /** Render a compact usage bar for inline summaries. */
2497
1727
  function renderCompactUsageBar(usedPercent) {
2498
1728
  return renderBar(usedPercent, COMPACT_BAR_LEN);
2499
1729
  }
2500
- /** Render a proportional colored progress bar at one-eighth-cell resolution. */
2501
1730
  export function renderBar(usedPercent, length) {
2502
1731
  const clamped = Math.max(0, Math.min(100, usedPercent));
2503
1732
  const eighths = Math.round((clamped / 100) * length * 8);
@@ -2507,11 +1736,9 @@ export function renderBar(usedPercent, length) {
2507
1736
  const gauge = FULL.repeat(filled) + PARTIAL_BLOCKS[partial];
2508
1737
  return color(gauge) + chalk.dim(EMPTY.repeat(length - filled - (partial > 0 ? 1 : 0)));
2509
1738
  }
2510
- /** Apply the appropriate color to a text string based on usage percentage. */
2511
1739
  function colorUsage(text, usedPercent) {
2512
1740
  return getUsageColor(usedPercent)(text);
2513
1741
  }
2514
- /** Return a chalk color function based on the usage percentage threshold. */
2515
1742
  export function getUsageColor(usedPercent) {
2516
1743
  if (usedPercent >= 100)
2517
1744
  return chalk.red;
@@ -2519,17 +1746,10 @@ export function getUsageColor(usedPercent) {
2519
1746
  return chalk.yellow;
2520
1747
  return chalk.cyan;
2521
1748
  }
2522
- /** Format a percentage value with at most one decimal place. */
2523
1749
  function formatPercent(value) {
2524
1750
  const rounded = Math.round(value * 10) / 10;
2525
1751
  return Number.isInteger(rounded) ? String(rounded) : rounded.toFixed(1);
2526
1752
  }
2527
- /**
2528
- * Compact "time until reset" hint for the inline usage bars: "5m", "2h", "3d",
2529
- * or "now" once elapsed. Deliberately coarse (single unit, whole numbers) so it
2530
- * fits after a bar without wrapping the row — the detailed section
2531
- * (`formatResetAt`) carries the precise clock time.
2532
- */
2533
1753
  function formatResetHint(date) {
2534
1754
  const diffMs = date.getTime() - Date.now();
2535
1755
  if (diffMs <= 0)
@@ -2543,11 +1763,6 @@ function formatResetHint(date) {
2543
1763
  const days = Math.round(hours / 24);
2544
1764
  return `${days}d`;
2545
1765
  }
2546
- /**
2547
- * Compact elapsed-time label for a stale reading's age: "30m", "6h", "2d".
2548
- * Coarse single-unit like {@link formatResetHint}, floored at "1m" so a
2549
- * just-expired window never reads "0m".
2550
- */
2551
1766
  function formatAgeShort(diffMs) {
2552
1767
  const mins = Math.max(1, Math.round(diffMs / 60000));
2553
1768
  if (mins < 60)
@@ -2558,15 +1773,6 @@ function formatAgeShort(diffMs) {
2558
1773
  const days = Math.round(hours / 24);
2559
1774
  return `${days}d`;
2560
1775
  }
2561
- /**
2562
- * Staleness suffix for a last-known window the freshness gate dropped. A window
2563
- * whose reset/period boundary passed while the sample itself is still inside its
2564
- * `windowMinutes` rolled OVER — the number describes a period that is done, so
2565
- * name it ("period ended 1h", e.g. Grok's weekly billing period). A window
2566
- * that aged past its own `windowMinutes` (Claude's 5h session read never
2567
- * refreshed in time) is a stale sample of a still-rolling window, so report the
2568
- * capture age ("6h old"). Falls back to the reset age, then a bare "stale".
2569
- */
2570
1776
  function formatStaleWindowSuffix(window, capturedAt, now) {
2571
1777
  const resetPassed = !!window.resetsAt && window.resetsAt.getTime() <= now.getTime();
2572
1778
  const captureExpired = !!capturedAt &&
@@ -2581,20 +1787,12 @@ function formatStaleWindowSuffix(window, capturedAt, now) {
2581
1787
  return `period ended ${formatAgeShort(now.getTime() - window.resetsAt.getTime())}`;
2582
1788
  return 'stale';
2583
1789
  }
2584
- /**
2585
- * Render a dropped-but-last-known window as "S: ▍░░░░ 30%* (6h old)": the gauge
2586
- * and percentage exactly as a live bar, then the `*` stale marker the listing
2587
- * legend explains and a dim age, so the number is always visible and
2588
- * unmistakably not current. VIEW-ONLY — these windows are never in
2589
- * `snapshot.windows`, so routing never sees them.
2590
- */
2591
1790
  function renderStaleUsageWindow(window, capturedAt, shortLabel, now) {
2592
1791
  const bar = renderCompactUsageBar(window.usedPercent);
2593
1792
  const pct = colorUsage(`${Math.round(window.usedPercent)}%`, window.usedPercent);
2594
1793
  const suffix = formatStaleWindowSuffix(window, capturedAt, now);
2595
1794
  return `${chalk.gray(`${shortLabel}:`)} ${bar} ${pct}${chalk.dim('*')} ${chalk.dim(`(${suffix})`)}`;
2596
1795
  }
2597
- /** Format a reset timestamp as a human-readable relative or absolute time. */
2598
1796
  function formatResetAt(date) {
2599
1797
  const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
2600
1798
  const now = new Date();
@@ -2619,7 +1817,6 @@ function formatResetAt(date) {
2619
1817
  }
2620
1818
  return `${date.toLocaleString('en-US', options)} (${timezone})`;
2621
1819
  }
2622
- /** Safe wrapper around fs.realpathSync that returns null on error. */
2623
1820
  function safeRealpathSync(filePath) {
2624
1821
  try {
2625
1822
  return fs.realpathSync(filePath);
@@ -2628,7 +1825,6 @@ function safeRealpathSync(filePath) {
2628
1825
  return null;
2629
1826
  }
2630
1827
  }
2631
- /** Safe wrapper around fs.statSync that returns null on error. */
2632
1828
  function safeStatSync(filePath) {
2633
1829
  try {
2634
1830
  return fs.statSync(filePath);
@@ -2637,19 +1833,6 @@ function safeStatSync(filePath) {
2637
1833
  return null;
2638
1834
  }
2639
1835
  }
2640
- /**
2641
- * Resolve the Grok billing log to read usage from.
2642
- *
2643
- * `agents view grok` reads usage per INSTALLED VERSION, passing each version's
2644
- * isolated home (`~/.agents/.history/versions/grok/<ver>`). Grok writes
2645
- * `unified.jsonl` only to the shared real home `~/.grok/logs/unified.jsonl`
2646
- * even though GROK_HOME isolates auth/config/models per version. A per-version
2647
- * log, if one ever appears, still wins; otherwise we return the shared path
2648
- * marked `shared: true` so the caller can attribute it to at most one identity.
2649
- * Grok accounts are version-scoped (`NATIVE_ACCOUNT_CAPABILITIES.grok.scope ===
2650
- * 'version'`) — the shared file has no owner, so it must not be stamped onto
2651
- * every version home.
2652
- */
2653
1836
  function resolveGrokBillingLogPath(home) {
2654
1837
  const rel = ['.grok', 'logs', 'unified.jsonl'];
2655
1838
  const perVersion = path.join(home || os.homedir(), ...rel);
@@ -2657,21 +1840,17 @@ function resolveGrokBillingLogPath(home) {
2657
1840
  if (fs.existsSync(perVersion))
2658
1841
  return { logPath: perVersion, shared: false };
2659
1842
  }
2660
- catch { /* unreadable */ }
2661
- // `AGENTS_REAL_HOME` is the seam every version-home consumer honors: a
2662
- // daemon/service-manager child's HOME can be baked to something other than
2663
- // the account's real home, so os.homedir() alone is not a reliable stand-in.
1843
+ catch { }
2664
1844
  const shared = path.join(process.env.AGENTS_REAL_HOME || os.homedir(), ...rel);
2665
1845
  if (shared !== perVersion) {
2666
1846
  try {
2667
1847
  if (fs.existsSync(shared))
2668
1848
  return { logPath: shared, shared: true };
2669
1849
  }
2670
- catch { /* unreadable */ }
1850
+ catch { }
2671
1851
  }
2672
1852
  return null;
2673
1853
  }
2674
- /** This home's own `.grok/auth.json` only — never the shared-home fallback. */
2675
1854
  function readGrokAuthIdentity(home) {
2676
1855
  const authPath = path.join(home, '.grok', 'auth.json');
2677
1856
  try {
@@ -2730,11 +1909,7 @@ function grokIdentityFromBillingPayload(parsed) {
2730
1909
  function sameHomePath(a, b) {
2731
1910
  return (safeRealpathSync(a) ?? path.resolve(a)) === (safeRealpathSync(b) ?? path.resolve(b));
2732
1911
  }
2733
- /**
2734
- * Whether the shared `~/.grok` billing log may be attached to this home.
2735
- * Grok logins are per version home; the shared last line is one account's
2736
- * meter. Fail loud: never copy it onto every installed identity.
2737
- */
1912
+ // A real-HOME Grok billing log serves a version home only when payload/auth identities match; unknown identity belongs only to real HOME.
2738
1913
  function sharedGrokLogAppliesToHome(home, match) {
2739
1914
  const realHome = process.env.AGENTS_REAL_HOME || os.homedir();
2740
1915
  const requestedHome = home || os.homedir();
@@ -2742,18 +1917,13 @@ function sharedGrokLogAppliesToHome(home, match) {
2742
1917
  if (match.identity) {
2743
1918
  return grokIdentitiesMatch(match.identity, thisId);
2744
1919
  }
2745
- // No identity on the line (the live Grok shape). Attribute the reading to
2746
- // exactly one canonical identity: the real home itself, or the version home
2747
- // whose own auth.json matches the shared `~/.grok/auth.json`.
2748
1920
  if (sameHomePath(requestedHome, realHome))
2749
1921
  return true;
2750
1922
  return grokIdentitiesMatch(thisId, readGrokAuthIdentity(realHome));
2751
1923
  }
2752
- /** Parse the latest billing info from Grok's unified log. */
2753
1924
  async function getGrokUsageInfo(options) {
2754
1925
  try {
2755
1926
  const resolved = resolveGrokBillingLogPath(options?.home);
2756
- // No log yet: a benign "nothing recorded here", not a failure (RUSH-3040).
2757
1927
  if (!resolved)
2758
1928
  return usageNoRecentUsageInfo();
2759
1929
  const match = await readLatestGrokBilling(resolved.logPath);
@@ -2762,18 +1932,8 @@ async function getGrokUsageInfo(options) {
2762
1932
  if (resolved.shared && !sharedGrokLogAppliesToHome(options?.home, match)) {
2763
1933
  return usageNoRecentUsageInfo();
2764
1934
  }
2765
- // Grok has no live usage API (`network: false`) — bars are last-seen from
2766
- // this machine's unified.jsonl only. Drop windows whose billing period has
2767
- // already ended so a stale 100% does not paint "rate-limited" after reset,
2768
- // and so an expired 92% on one box cannot disagree with a fresh reading on
2769
- // another. Missing `creditUsagePercent` never reaches here as a 0% bar
2770
- // (see readLatestGrokBilling).
2771
1935
  const now = new Date();
2772
1936
  const windows = match.windows.filter((window) => isCachedUsageWindowFresh(window, match.capturedAt, now));
2773
- // A window from an ended billing period is the LAST reading we saw — routing
2774
- // must not trust it (kept out of `windows`), but the view renders it with a
2775
- // "period ended Xh ago" suffix instead of the bare refresh hint. Only when
2776
- // there is nothing at all to show does the refresh hint stand alone.
2777
1937
  const staleWindows = match.windows.filter((window) => !isCachedUsageWindowFresh(window, match.capturedAt, now));
2778
1938
  const version = options?.cliVersion;
2779
1939
  const refreshHint = windows.length === 0 && staleWindows.length === 0
@@ -2796,21 +1956,9 @@ async function getGrokUsageInfo(options) {
2796
1956
  return { snapshot: null, error: usageUnreachableError('Grok', err) };
2797
1957
  }
2798
1958
  }
2799
- /**
2800
- * Muse Code usage.
2801
- *
2802
- * Prefer live Meta Model API rate-limit headers when a key is available
2803
- * (META_API_KEY / MODEL_API_KEY / ~/.config/muse/auth.json). Fall back to
2804
- * aggregating `model_completed.usage` from local session.jsonl logs under
2805
- * ~/.local/share/muse/sessions for a last-7-days token window.
2806
- */
2807
1959
  async function getMuseUsageInfo(options) {
2808
1960
  try {
2809
1961
  const base = options?.home || os.homedir();
2810
- // Honour a live Retry-After rather than re-arming the penalty (see
2811
- // usage-backoff.ts). The local log fallback still works while the live
2812
- // probe is throttled — only report the throttle when there is truly
2813
- // nothing else to show.
2814
1962
  const throttledUntil = usageRateLimitedUntil('muse', Date.now(), options?.usageScope);
2815
1963
  if (throttledUntil) {
2816
1964
  const local = await readMuseLocalSessionUsage(base);
@@ -2824,9 +1972,6 @@ async function getMuseUsageInfo(options) {
2824
1972
  const local = await readMuseLocalSessionUsage(base);
2825
1973
  if (local)
2826
1974
  return { snapshot: local, error: null };
2827
- // No live snapshot and no local log — every source came up empty. Only
2828
- // now does the probe's own outcome become the reported error, mirroring
2829
- // Cursor's "surface the last resort's failure" pattern above.
2830
1975
  if (!probe.hasKey)
2831
1976
  return { snapshot: null, error: usageNoCredentialError('Muse') };
2832
1977
  if (probe.noHeaders)
@@ -2837,13 +1982,9 @@ async function getMuseUsageInfo(options) {
2837
1982
  };
2838
1983
  }
2839
1984
  catch (err) {
2840
- // A thrown request (timeout, DNS, TLS, a malformed payload) is a failed
2841
- // read like any other — staying silent here would hand the caller a stale
2842
- // snapshot to render as confirmed (RUSH-3040).
2843
1985
  return { snapshot: null, error: usageUnreachableError('Muse', err) };
2844
1986
  }
2845
1987
  }
2846
- /** Resolve a Muse API key from env or auth.json without logging the value. */
2847
1988
  function resolveMuseApiKey(base) {
2848
1989
  const envKey = process.env.META_API_KEY?.trim() || process.env.MODEL_API_KEY?.trim();
2849
1990
  if (envKey)
@@ -2868,16 +2009,9 @@ function resolveMuseApiKey(base) {
2868
2009
  }
2869
2010
  }
2870
2011
  catch {
2871
- /* unreadable auth */
2872
2012
  }
2873
2013
  return null;
2874
2014
  }
2875
- /**
2876
- * Probe Meta Model API for rate-limit headers. Uses GET /v1/models (no token
2877
- * spend). The 429 backoff is noted by the CALLER via
2878
- * {@link classifyUsageFetchFailure}, not here, so a throttled read is recorded
2879
- * exactly once regardless of which branch of `getMuseUsageInfo` observes it.
2880
- */
2881
2015
  async function probeMuseRateLimits(base) {
2882
2016
  const key = resolveMuseApiKey(base);
2883
2017
  if (!key)
@@ -2951,11 +2085,6 @@ function headerNumber(headers, name) {
2951
2085
  const n = Number(raw);
2952
2086
  return Number.isFinite(n) ? n : null;
2953
2087
  }
2954
- /**
2955
- * Aggregate Muse session token usage from local session.jsonl files for the
2956
- * last 7 days. Scales the bar against 10M tokens (soft visibility scale — Meta
2957
- * is pay-as-you-go with no hard local cap).
2958
- */
2959
2088
  async function readMuseLocalSessionUsage(base) {
2960
2089
  const root = path.join(base, '.local', 'share', 'muse', 'sessions');
2961
2090
  if (!fs.existsSync(root))
@@ -3015,7 +2144,6 @@ async function readMuseLocalSessionUsage(base) {
3015
2144
  }
3016
2145
  }
3017
2146
  catch {
3018
- /* skip unreadable session */
3019
2147
  }
3020
2148
  }
3021
2149
  };
@@ -3023,7 +2151,6 @@ async function readMuseLocalSessionUsage(base) {
3023
2151
  const total = inputTokens + outputTokens + cachedTokens;
3024
2152
  if (total === 0 && files === 0)
3025
2153
  return null;
3026
- // Soft 10M-token scale for the bar (pay-as-you-go has no hard local cap).
3027
2154
  const softCap = 10_000_000;
3028
2155
  const usedPercent = Math.max(0, Math.min(100, (total / softCap) * 100));
3029
2156
  const formatK = (n) => n >= 1_000_000 ? `${(n / 1_000_000).toFixed(1)}M` : n >= 1000 ? `${(n / 1000).toFixed(1)}k` : String(n);
@@ -3064,11 +2191,6 @@ async function readLatestGrokBilling(filePath) {
3064
2191
  ? config.currentPeriod
3065
2192
  : null;
3066
2193
  if (currentPeriod?.end && typeof config.creditUsagePercent === 'number') {
3067
- // `creditUsagePercent` is Grok's weekly credit consumption (0-100);
3068
- // the billing period's `end` is when that window resets.
3069
- // Do NOT coerce a missing percent to 0 — a new period often lands a
3070
- // billing line before the gauge is populated, and inventing 0% makes
3071
- // `agents view` disagree across devices (and looks like a fresh week).
3072
2194
  const rawPercent = config.creditUsagePercent;
3073
2195
  windows.push({
3074
2196
  key: 'week',
@@ -3088,22 +2210,12 @@ async function readLatestGrokBilling(filePath) {
3088
2210
  }
3089
2211
  }
3090
2212
  catch {
3091
- /* malformed session line */
3092
2213
  }
3093
2214
  });
3094
2215
  rl.on('close', () => resolve(latest));
3095
2216
  rl.on('error', () => resolve(latest));
3096
2217
  });
3097
2218
  }
3098
- /**
3099
- * Normalize Cursor's /api/usage payload into the common UsageWindow shape.
3100
- *
3101
- * Only free / legacy request-capped plans carry a `maxRequestUsage` on the
3102
- * premium ("gpt-4") bucket — that's the fast-request cap the plan meters, and it
3103
- * maps cleanly to a monthly window. Usage-based plans report `maxRequestUsage:
3104
- * null` (no request cap — spend is metered in dollars instead), so they have no
3105
- * bar to draw here and return no windows rather than a misleading empty gauge.
3106
- */
3107
2219
  export function normalizeCursorUsage(data) {
3108
2220
  const premium = data['gpt-4'];
3109
2221
  if (!premium || typeof premium !== 'object')
@@ -3113,10 +2225,6 @@ export function normalizeCursorUsage(data) {
3113
2225
  return [];
3114
2226
  const used = typeof premium.numRequests === 'number' ? premium.numRequests : 0;
3115
2227
  const startOfMonth = typeof data.startOfMonth === 'string' ? parseDateValue(data.startOfMonth) : null;
3116
- // The request quota resets one calendar month after the period start. Guard the
3117
- // month-end overflow: setMonth on a day the target month lacks (Jan 31 -> Feb 31)
3118
- // rolls forward into the month after (Mar 3), so clamp back to the intended
3119
- // month's last day.
3120
2228
  let resetsAt = null;
3121
2229
  if (startOfMonth) {
3122
2230
  resetsAt = new Date(startOfMonth);
@@ -3136,25 +2244,12 @@ export function normalizeCursorUsage(data) {
3136
2244
  },
3137
2245
  ];
3138
2246
  }
3139
- /**
3140
- * Normalize a single Cursor percent-based window (auto/api/total), or null when
3141
- * the percent is not a finite number — the "no empty gauges" rule.
3142
- * `windowMinutes` stays null: every window shares one billing-cycle reset
3143
- * (`resetsAt`, from the explicit `billingCycleEnd`), not an inferred cadence, so
3144
- * inferring one from the (repurposed) `session`/`week`/`month` key would let the
3145
- * SWR cache zero the bar out long before the real reset.
3146
- */
3147
2247
  function normalizeCursorPercentWindow(percent, key, label, shortLabel, resetsAt) {
3148
2248
  const usedPercent = normalizePercent(percent);
3149
2249
  if (usedPercent === null)
3150
2250
  return null;
3151
2251
  return { key, label, shortLabel, usedPercent, resetsAt, windowMinutes: null };
3152
2252
  }
3153
- /**
3154
- * Normalize Cursor's dashboard `get-current-period-usage` payload — the
3155
- * primary usage source, giving the same Auto+Composer / API / Total breakdown
3156
- * the web dashboard shows.
3157
- */
3158
2253
  export function normalizeCursorPeriodUsage(data) {
3159
2254
  const resetsAt = parseDateValue(data.billingCycleEnd);
3160
2255
  const plan = data.planUsage;
@@ -3165,14 +2260,6 @@ export function normalizeCursorPeriodUsage(data) {
3165
2260
  ];
3166
2261
  return windows.filter((window) => window !== null);
3167
2262
  }
3168
- /**
3169
- * Normalize Cursor's `usage-summary` fallback payload — the same Auto/API/Total
3170
- * breakdown nested under `individualUsage.plan`, used when the primary
3171
- * dashboard endpoint returns no usable `planUsage` (seen on some
3172
- * enterprise/team accounts). An unlimited plan (`isUnlimited: true`) with no
3173
- * usable percent has nothing to draw and returns no windows, rather than a
3174
- * misleading empty gauge.
3175
- */
3176
2263
  export function normalizeCursorUsageSummary(data) {
3177
2264
  const resetsAt = parseDateValue(data.billingCycleEnd);
3178
2265
  const plan = data.individualUsage?.plan;
@@ -3183,7 +2270,6 @@ export function normalizeCursorUsageSummary(data) {
3183
2270
  ];
3184
2271
  return windows.filter((window) => window !== null);
3185
2272
  }
3186
- /** Read Cursor's OAuth access token + config-file subject from the local CLI config/auth files. */
3187
2273
  function readCursorCredentials(base) {
3188
2274
  try {
3189
2275
  const cfgPath = path.join(base, '.cursor', 'cli-config.json');
@@ -3202,22 +2288,10 @@ function readCursorCredentials(base) {
3202
2288
  return null;
3203
2289
  }
3204
2290
  }
3205
- /**
3206
- * Resolve the OAuth subject Cursor expects in the `WorkosCursorSessionToken`
3207
- * cookie: the access token's own JWT `sub` claim first (the subject that
3208
- * actually signed the token in hand), falling back to the subject
3209
- * `cli-config.json` recorded at login when the token carries no usable `sub`.
3210
- */
3211
2291
  function resolveCursorSubject(accessToken, cfgSub) {
3212
2292
  const jwtSub = normalizeString(decodeJwtPayload(accessToken)?.sub);
3213
2293
  return jwtSub || cfgSub;
3214
2294
  }
3215
- /**
3216
- * POST the dashboard current-period-usage endpoint and normalize its windows.
3217
- * Returns null on any network/auth failure so the caller falls through to the
3218
- * next source — only a genuine empty-windows response distinguishes "no usage
3219
- * to report" from "couldn't reach this source".
3220
- */
3221
2295
  async function fetchCursorPeriodWindows(cookie) {
3222
2296
  try {
3223
2297
  const response = await fetch(CURSOR_PERIOD_USAGE_URL, {
@@ -3244,10 +2318,6 @@ async function fetchCursorPeriodWindows(cookie) {
3244
2318
  return null;
3245
2319
  }
3246
2320
  }
3247
- /**
3248
- * GET the usage-summary fallback endpoint and normalize its windows. Same
3249
- * null-on-failure contract as {@link fetchCursorPeriodWindows}.
3250
- */
3251
2321
  async function fetchCursorUsageSummaryWindows(cookie) {
3252
2322
  try {
3253
2323
  const response = await fetch(CURSOR_USAGE_SUMMARY_URL, {
@@ -3271,30 +2341,6 @@ async function fetchCursorUsageSummaryWindows(cookie) {
3271
2341
  return null;
3272
2342
  }
3273
2343
  }
3274
- /**
3275
- * Fetch Cursor usage. Cursor authenticates every one of these requests with a
3276
- * `WorkosCursorSessionToken` cookie of the form `<oauth-subject>::<access-token>`
3277
- * (the same pair the web dashboard sends), not a bearer header, so all three
3278
- * sources below share one resolved cookie.
3279
- *
3280
- * Three sources, tried in order, because no single endpoint carries usable data
3281
- * for every plan shape:
3282
- *
3283
- * 1. `get-current-period-usage` — the primary source, and the richest: the
3284
- * Auto+Composer / API / Total percent breakdown the dashboard itself shows.
3285
- * 2. `usage-summary` — some enterprise/team accounts return no usable
3286
- * `planUsage` from (1); this nests the same three percentages under
3287
- * `individualUsage.plan` instead.
3288
- * 3. The legacy `/api/usage` request-cap endpoint — the original source,
3289
- * kept as the final fallback for free/legacy plans that predate the
3290
- * percent-based breakdown above and only ever exposed a monthly request cap.
3291
- *
3292
- * The first source to yield a non-empty window list wins; a source that errors
3293
- * or returns no usable numbers falls through to the next rather than surfacing
3294
- * an error — only the last resort's own response/error is surfaced when every
3295
- * source comes up empty, so a plan enrolled in exactly one billing model still
3296
- * renders instead of reporting three swallowed failures.
3297
- */
3298
2344
  async function getCursorUsageInfo(options) {
3299
2345
  try {
3300
2346
  const base = options?.home || os.homedir();
@@ -3336,8 +2382,6 @@ async function getCursorUsageInfo(options) {
3336
2382
  },
3337
2383
  signal: usageFetchSignal(options?.signal, 5000),
3338
2384
  });
3339
- // 401/redirect => revoked/expired session. No bars to draw, and the status
3340
- // says why.
3341
2385
  if (!response.ok) {
3342
2386
  if (response.status === 429) {
3343
2387
  noteUsageRateLimited('cursor', response.headers.get('retry-after'));
@@ -3356,38 +2400,17 @@ async function getCursorUsageInfo(options) {
3356
2400
  };
3357
2401
  }
3358
2402
  catch (err) {
3359
- // A thrown request (timeout, DNS, TLS, a malformed payload) is a failed
3360
- // read like any other — staying silent here would hand the caller a stale
3361
- // snapshot to render as confirmed, which is the bug this file just closed.
3362
2403
  return { snapshot: null, error: usageUnreachableError('Cursor', err) };
3363
2404
  }
3364
2405
  }
3365
- // ---------------------------------------------------------------------------
3366
- // Antigravity (`agy`) usage — Google Code Assist per-model quota buckets
3367
- // ---------------------------------------------------------------------------
3368
2406
  const ANTIGRAVITY_TOKEN_URL = 'https://oauth2.googleapis.com/token';
3369
- // Production Code Assist endpoint first; the daily track is where `agy` itself
3370
- // points when the account is enrolled in the daily channel (its log shows
3371
- // daily-cloudcode-pa), so fall back to it when prod rejects the call.
3372
2407
  const ANTIGRAVITY_QUOTA_URLS = [
3373
2408
  'https://cloudcode-pa.googleapis.com/v1internal:retrieveUserQuota',
3374
2409
  'https://daily-cloudcode-pa.googleapis.com/v1internal:retrieveUserQuota',
3375
2410
  ];
3376
- // The public installed-app OAuth client the released `agy` binary itself
3377
- // ships (Google installed-app clients are non-confidential by design — the
3378
- // same client community tooling uses). Needed because a Google token refresh
3379
- // requires the client id/secret pair the login was minted under.
3380
2411
  const ANTIGRAVITY_CLIENT_ID = '1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com';
3381
2412
  const ANTIGRAVITY_CLIENT_SECRET = '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';
3382
- /** Refresh leeway — treat an access token expiring within a minute as expired. */
3383
2413
  const ANTIGRAVITY_REFRESH_LEEWAY_MS = 60 * 1000;
3384
- /**
3385
- * Parse a stored `agy` OAuth payload into its token. Handles both on-disk
3386
- * shapes: the raw `{ token: {…} }` JSON (Linux file fallback) and the
3387
- * `go-keyring-base64:<base64>` wrapper zalando/go-keyring writes into the
3388
- * macOS Keychain item (service `gemini`, account `antigravity`). Never throws
3389
- * (malformed input => null).
3390
- */
3391
2414
  export function parseAntigravityOauthPayload(raw) {
3392
2415
  try {
3393
2416
  let text = raw.trim();
@@ -3406,12 +2429,6 @@ export function parseAntigravityOauthPayload(raw) {
3406
2429
  return null;
3407
2430
  }
3408
2431
  }
3409
- /**
3410
- * True when the stored access token is expired (or inside the refresh leeway).
3411
- * A missing/unparseable expiry is treated as still-fresh — the quota call
3412
- * below is the source of truth if the token is actually dead (401 => render
3413
- * nothing), and we never want to force a refresh without evidence.
3414
- */
3415
2432
  export function antigravityTokenNeedsRefresh(expiry, nowMs = Date.now()) {
3416
2433
  if (!expiry)
3417
2434
  return false;
@@ -3420,13 +2437,6 @@ export function antigravityTokenNeedsRefresh(expiry, nowMs = Date.now()) {
3420
2437
  return false;
3421
2438
  return nowMs + ANTIGRAVITY_REFRESH_LEEWAY_MS >= ms;
3422
2439
  }
3423
- /**
3424
- * Resolve the `agy` OAuth credential file. agy is a self-updating global
3425
- * install (no per-version homes), but check the passed home first and then the
3426
- * active location under the real HOME — mirrors resolveKimiCredentialPath.
3427
- * Present only on Linux without a Secret Service daemon; macOS logins live in
3428
- * the Keychain instead.
3429
- */
3430
2440
  function resolveAntigravityCredentialPath(home) {
3431
2441
  const rel = ['.gemini', 'antigravity-cli', 'antigravity-oauth-token'];
3432
2442
  const perHome = path.join(home || os.homedir(), ...rel);
@@ -3434,25 +2444,17 @@ function resolveAntigravityCredentialPath(home) {
3434
2444
  if (fs.existsSync(perHome))
3435
2445
  return perHome;
3436
2446
  }
3437
- catch { /* unreadable */ }
2447
+ catch { }
3438
2448
  const active = path.join(process.env.AGENTS_REAL_HOME || os.homedir(), ...rel);
3439
2449
  if (active !== perHome) {
3440
2450
  try {
3441
2451
  if (fs.existsSync(active))
3442
2452
  return active;
3443
2453
  }
3444
- catch { /* unreadable */ }
2454
+ catch { }
3445
2455
  }
3446
2456
  return null;
3447
2457
  }
3448
- /**
3449
- * Load the stored `agy` OAuth token: the file fallback first, then the OS
3450
- * keyring (macOS Keychain / Linux Secret Service — go-keyring's two stores;
3451
- * the probe command pair mirrors antigravityOsKeyringProbe in agents.ts, with
3452
- * `-w` on macOS to read the secret value, not just metadata). Returns null on
3453
- * Windows or when no readable credential exists. Honors the
3454
- * AGENTS_NO_KEYCHAIN_PROBE=1 test guard.
3455
- */
3456
2458
  async function loadAntigravityOauth(home) {
3457
2459
  const credPath = resolveAntigravityCredentialPath(home);
3458
2460
  if (credPath) {
@@ -3461,7 +2463,7 @@ async function loadAntigravityOauth(home) {
3461
2463
  if (parsed)
3462
2464
  return parsed;
3463
2465
  }
3464
- catch { /* unreadable file — fall through to the keyring */ }
2466
+ catch { }
3465
2467
  }
3466
2468
  if (process.env.AGENTS_NO_KEYCHAIN_PROBE === '1')
3467
2469
  return null;
@@ -3480,16 +2482,6 @@ async function loadAntigravityOauth(home) {
3480
2482
  return null;
3481
2483
  }
3482
2484
  }
3483
- /**
3484
- * Refresh an `agy` access token against Google's token endpoint. This is safe
3485
- * from a read path in a way Claude/WorkOS refreshes are NOT: Google's OAuth
3486
- * refresh tokens are stable and non-rotating — a refresh mints a new access
3487
- * token and leaves the refresh token (and every other live access token)
3488
- * valid, so refreshing here cannot invalidate a concurrently running `agy`.
3489
- * We still never write the refreshed token back: `agy` rewrites its own
3490
- * keychain item on launch, and a read-only usage fetch must not mutate the
3491
- * user's credential.
3492
- */
3493
2485
  async function refreshAntigravityAccessToken(refreshToken) {
3494
2486
  try {
3495
2487
  const response = await fetch(ANTIGRAVITY_TOKEN_URL, {
@@ -3512,13 +2504,6 @@ async function refreshAntigravityAccessToken(refreshToken) {
3512
2504
  return null;
3513
2505
  }
3514
2506
  }
3515
- /**
3516
- * POST :retrieveUserQuota against the Code Assist endpoints in order, returning
3517
- * the first successful bucket list. `buckets: null` when every endpoint rejects
3518
- * (expired token, no quota API for the account) or the network fails — `status`
3519
- * carries the LAST rejection's HTTP status (or null when every attempt threw)
3520
- * so the caller can classify the failure instead of it reading as silence.
3521
- */
3522
2507
  async function fetchAntigravityQuota(accessToken) {
3523
2508
  let lastStatus = null;
3524
2509
  let lastRetryAfter = null;
@@ -3548,7 +2533,6 @@ async function fetchAntigravityQuota(accessToken) {
3548
2533
  }
3549
2534
  return { buckets: null, status: lastStatus, retryAfter: lastRetryAfter };
3550
2535
  }
3551
- /** Compact model tag for the inline bar — 'gemini-2.5-flash-lite' => '2.5FL'. */
3552
2536
  export function antigravityModelShortLabel(modelId) {
3553
2537
  const stripped = modelId.replace(/^gemini-/i, '');
3554
2538
  const parts = stripped.split('-').filter(Boolean);
@@ -3557,16 +2541,6 @@ export function antigravityModelShortLabel(modelId) {
3557
2541
  const [version, ...rest] = parts;
3558
2542
  return version + rest.map((part) => (part[0] ? part[0].toUpperCase() : '')).join('');
3559
2543
  }
3560
- /**
3561
- * Normalize the per-model quota buckets into the common UsageWindow shape —
3562
- * one window per model (`gemini-3.1-pro`, `gemini-2.5-flash`, …), keyed
3563
- * `session` since each bucket is a short-cycle quota with its own reset time.
3564
- * Duplicate buckets for one model keep the LOWEST remaining fraction (the
3565
- * most conservative read). Sorted most-used first so the bar closest to
3566
- * throttling leads the row. `windowMinutes` stays null: the API reports only
3567
- * the reset timestamp, not the window length, and an inferred 5h session
3568
- * length would wrongly zero the SWR cache between resets.
3569
- */
3570
2544
  export function normalizeAntigravityWindows(buckets) {
3571
2545
  const byModel = new Map();
3572
2546
  for (const bucket of buckets) {
@@ -3596,14 +2570,6 @@ export function normalizeAntigravityWindows(buckets) {
3596
2570
  windows.sort((a, b) => b.usedPercent - a.usedPercent);
3597
2571
  return windows;
3598
2572
  }
3599
- /**
3600
- * Fetch Antigravity usage via Google Code Assist's :retrieveUserQuota — the
3601
- * quota API `agy` itself talks to (its log shows the sibling :loadCodeAssist
3602
- * and :fetchAvailableModels calls on the same host). Auth is the stored `agy`
3603
- * OAuth token (OS keyring on macOS, file fallback on Linux), refreshed
3604
- * in-memory when expired — safe because Google's refresh tokens are
3605
- * non-rotating (see refreshAntigravityAccessToken).
3606
- */
3607
2573
  async function getAntigravityUsageInfo(options) {
3608
2574
  try {
3609
2575
  const token = await loadAntigravityOauth(options?.home);
@@ -3615,10 +2581,6 @@ async function getAntigravityUsageInfo(options) {
3615
2581
  }
3616
2582
  if (!accessToken)
3617
2583
  return { snapshot: null, error: usageExpiredCredentialError('Antigravity') };
3618
- // Honour a live Retry-After rather than re-arming the penalty (see
3619
- // usage-backoff.ts). No request at all while the window is open. Antigravity
3620
- // previously had NO rate-limit backoff at all (RUSH-3040) — every refresh
3621
- // re-hit a throttled endpoint.
3622
2584
  const throttledUntil = usageRateLimitedUntil('antigravity', Date.now(), options?.usageScope);
3623
2585
  if (throttledUntil) {
3624
2586
  return { snapshot: null, error: usageThrottledError('Antigravity', throttledUntil) };
@@ -3644,9 +2606,6 @@ async function getAntigravityUsageInfo(options) {
3644
2606
  };
3645
2607
  }
3646
2608
  catch (err) {
3647
- // A thrown request (timeout, DNS, TLS, a malformed payload) is a failed
3648
- // read like any other — staying silent here would hand the caller a stale
3649
- // snapshot to render as confirmed (RUSH-3040).
3650
2609
  return { snapshot: null, error: usageUnreachableError('Antigravity', err) };
3651
2610
  }
3652
2611
  }