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