@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/audit/log.js
CHANGED
|
@@ -1,29 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Run-dispatch recording (issue #347) — now a thin write into the unified
|
|
3
|
+
* event stream (`emit('run.dispatched', …)`). The historical hash-chained file
|
|
4
|
+
* at `~/.agents/.history/audit/log.jsonl` is still readable via
|
|
5
|
+
* `readAuditLog` / `verifyAuditChain` for pre-unification history; new runs do
|
|
6
|
+
* NOT append there. Operators list run outcomes with:
|
|
3
7
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* each record embeds the previous record's `hash` as `prevHash`, and its own
|
|
7
|
-
* `hash` is `sha256(canonicalJSON(record-without-hash))`. Because `prevHash`
|
|
8
|
-
* is part of the hashed payload, rewriting or reordering any record breaks the
|
|
9
|
-
* chain from that point forward — `verifyAuditChain()` reports the first index
|
|
10
|
-
* that fails to reproduce.
|
|
11
|
-
*
|
|
12
|
-
* Storage is append-only JSONL under the durable-runtime bucket
|
|
13
|
-
* (`~/.agents/.history/audit/log.jsonl`), one record per line. `.history/` is
|
|
14
|
-
* machine-local, gitignored, and NEVER synced by `agents repo push/pull` — so
|
|
15
|
-
* the `repo` field (a git remote url that can embed an access token) never
|
|
16
|
-
* lands in a version-controlled DotAgents repo, and a cross-machine pull can't
|
|
17
|
-
* splice a foreign chain into this one. The write path is deliberately cheap
|
|
18
|
-
* and non-fatal: a logging failure must never crash a run (see
|
|
19
|
-
* `recordDispatchedRun`). Concurrent writers (parallel teams/routines dispatch)
|
|
20
|
-
* are serialized by an advisory lock file so the chain never forks — see
|
|
21
|
-
* `appendAuditRecord`.
|
|
22
|
-
*
|
|
23
|
-
* Governance context: this is the evidence trail an operator needs to answer
|
|
24
|
-
* "which agent, at which version, ran against which repo, and did it succeed?"
|
|
25
|
-
* — the kind of automated-decision logging the EU AI Act (Art. 12) expects of
|
|
26
|
-
* high-risk systems, kept tamper-evident so the log itself can be trusted.
|
|
8
|
+
* agents events --include runs
|
|
9
|
+
* agents audit # alias of the above
|
|
27
10
|
*/
|
|
28
11
|
import * as fs from 'fs';
|
|
29
12
|
import * as path from 'path';
|
|
@@ -31,6 +14,7 @@ import { spawnSync } from 'child_process';
|
|
|
31
14
|
import { sha256 } from '../staleness/fingerprint.js';
|
|
32
15
|
import { getHistoryDir } from '../state.js';
|
|
33
16
|
import { ensureLockTarget, withFileLock } from '../fs-atomic.js';
|
|
17
|
+
import { emit } from '../events.js';
|
|
34
18
|
/** First record's `prevHash` — a fixed anchor so the chain has a root. */
|
|
35
19
|
export const GENESIS_HASH = 'GENESIS';
|
|
36
20
|
/**
|
|
@@ -155,23 +139,26 @@ function repoLabel(cwd) {
|
|
|
155
139
|
}
|
|
156
140
|
}
|
|
157
141
|
/**
|
|
158
|
-
* Record ONE dispatched run at the single exec chokepoint
|
|
159
|
-
* contract: any failure is caught and warned, never
|
|
160
|
-
* hiccup must not crash a run that already finished.
|
|
142
|
+
* Record ONE dispatched run at the single exec chokepoint into the unified
|
|
143
|
+
* event stream. Non-fatal by contract: any failure is caught and warned, never
|
|
144
|
+
* thrown — a log hiccup must not crash a run that already finished.
|
|
161
145
|
*/
|
|
162
146
|
export function recordDispatchedRun(run) {
|
|
163
147
|
try {
|
|
164
|
-
|
|
165
|
-
|
|
148
|
+
const outcome = run.exitCode === 0 ? 'ok' : 'fail';
|
|
149
|
+
emit('run.dispatched', {
|
|
150
|
+
module: 'run',
|
|
166
151
|
agent: run.agent,
|
|
167
152
|
version: run.version,
|
|
168
|
-
repo: repoLabel(run.cwd),
|
|
169
153
|
mode: run.mode,
|
|
170
|
-
|
|
171
|
-
|
|
154
|
+
repo: repoLabel(run.cwd),
|
|
155
|
+
cwd: run.cwd,
|
|
156
|
+
outcome,
|
|
157
|
+
exitCode: run.exitCode,
|
|
158
|
+
status: outcome,
|
|
172
159
|
});
|
|
173
160
|
}
|
|
174
161
|
catch (err) {
|
|
175
|
-
process.stderr.write(`[agents]
|
|
162
|
+
process.stderr.write(`[agents] run.dispatched emit failed: ${err.message}\n`);
|
|
176
163
|
}
|
|
177
164
|
}
|
|
@@ -3,10 +3,15 @@ import type { AgentId } from './types.js';
|
|
|
3
3
|
import { type ProviderProbe } from './usage.js';
|
|
4
4
|
/**
|
|
5
5
|
* - `live` — completed an authenticated request (200).
|
|
6
|
-
* - `revoked` — the server rejected the token (401/403)
|
|
6
|
+
* - `revoked` — the server rejected the token (401/403), except Claude
|
|
7
|
+
* setup-token `user:profile` scope denials (those are
|
|
8
|
+
* `unverified` via `reason: 'usage_scope'` — RUSH-2392).
|
|
7
9
|
* - `expired` — locally-detected expiry; not network-verified (no refresh on the read path).
|
|
8
10
|
* - `rate_limited`— token works but is throttled right now (429).
|
|
9
|
-
* - `unverified` — credential present, not locally expired, but this agent has
|
|
11
|
+
* - `unverified` — credential present, not locally expired, but this agent has
|
|
12
|
+
* no in-repo probe endpoint (codex/grok), OR the probe
|
|
13
|
+
* endpoint cannot prove live for a known non-revocation
|
|
14
|
+
* reason (Claude setup-token usage-scope gap — RUSH-2392).
|
|
10
15
|
* - `unconfigured`— no usable credential on disk.
|
|
11
16
|
* - `error` — network/other failure; verdict indeterminate (keep the last known one).
|
|
12
17
|
*/
|
|
@@ -129,6 +134,8 @@ export declare function authCacheKey(host: string, agent: AgentId | string, vers
|
|
|
129
134
|
export declare function readAuthHealthCache(): Record<string, AuthHealth>;
|
|
130
135
|
/** Read one entry, or null. */
|
|
131
136
|
export declare function readAuthHealth(host: string, agent: AgentId | string, version: string): AuthHealth | null;
|
|
137
|
+
/** Reconstruct one host's published probe rows for a lease waiter/CLI reader. */
|
|
138
|
+
export declare function readFleetAuthRows(host: string): AuthProbeRow[];
|
|
132
139
|
/**
|
|
133
140
|
* Merge entries into the cache. An incoming `error` verdict (a network blip,
|
|
134
141
|
* not a server rejection) is indeterminate, so it must NOT clobber a prior
|
package/dist/lib/auth-health.js
CHANGED
|
@@ -20,8 +20,9 @@ import * as fs from 'fs';
|
|
|
20
20
|
import * as path from 'path';
|
|
21
21
|
import { ALL_AGENT_IDS, getAccountInfo } from './agents.js';
|
|
22
22
|
import { getCacheDir } from './state.js';
|
|
23
|
-
import { probeClaudeStatus, probeDroidStatus, probeKimiStatus, } from './usage.js';
|
|
23
|
+
import { probeClaudeStatus, probeDroidStatus, probeKimiStatus, USAGE_HEADLESS_SCOPE_MARKER, } from './usage.js';
|
|
24
24
|
import { getVersionHomePath, listInstalledVersions } from './versions.js';
|
|
25
|
+
import { atomicWriteFileSync, ensureLockTarget, withFileLock } from './fs-atomic.js';
|
|
25
26
|
/** Agents with a live network probe wired up today. The rest are best-effort. */
|
|
26
27
|
export const LIVE_PROBE_AGENTS = new Set(['claude', 'kimi', 'droid']);
|
|
27
28
|
// ---------------------------------------------------------------------------
|
|
@@ -43,12 +44,20 @@ export function verdictFromProbe(probe) {
|
|
|
43
44
|
return 'unconfigured';
|
|
44
45
|
if (probe.token === 'expired')
|
|
45
46
|
return 'expired';
|
|
47
|
+
// Setup-token can run inference but cannot read usage (RUSH-2392). That 403
|
|
48
|
+
// is NOT a revocation — classifying it as revoked made the best-provisioned
|
|
49
|
+
// headless accounts look the least healthy on `agents view` / fleet ping.
|
|
50
|
+
if (probe.reason === 'usage_scope')
|
|
51
|
+
return 'unverified';
|
|
46
52
|
if (probe.status == null)
|
|
47
53
|
return 'error';
|
|
48
54
|
return classifyHttpStatus(probe.status);
|
|
49
55
|
}
|
|
50
56
|
/** A short human detail line for a probe result (rendered under --verbose). */
|
|
51
57
|
export function probeDetail(probe) {
|
|
58
|
+
if (probe.reason === 'usage_scope') {
|
|
59
|
+
return probe.error ?? USAGE_HEADLESS_SCOPE_MARKER;
|
|
60
|
+
}
|
|
52
61
|
if (probe.status != null && (probe.status < 200 || probe.status >= 300))
|
|
53
62
|
return `HTTP ${probe.status}`;
|
|
54
63
|
if (probe.error)
|
|
@@ -226,6 +235,29 @@ export function readAuthHealthCache() {
|
|
|
226
235
|
export function readAuthHealth(host, agent, version) {
|
|
227
236
|
return readAuthHealthCache()[authCacheKey(host, agent, version)] ?? null;
|
|
228
237
|
}
|
|
238
|
+
/** Reconstruct one host's published probe rows for a lease waiter/CLI reader. */
|
|
239
|
+
export function readFleetAuthRows(host) {
|
|
240
|
+
const prefix = `${host}:`;
|
|
241
|
+
const rows = [];
|
|
242
|
+
for (const [key, health] of Object.entries(readAuthHealthCache())) {
|
|
243
|
+
if (!key.startsWith(prefix))
|
|
244
|
+
continue;
|
|
245
|
+
const identity = key.slice(prefix.length);
|
|
246
|
+
const separator = identity.indexOf(':');
|
|
247
|
+
if (separator <= 0)
|
|
248
|
+
continue;
|
|
249
|
+
const agent = identity.slice(0, separator);
|
|
250
|
+
if (!ALL_AGENT_IDS.includes(agent))
|
|
251
|
+
continue;
|
|
252
|
+
rows.push({
|
|
253
|
+
agent: agent,
|
|
254
|
+
version: identity.slice(separator + 1),
|
|
255
|
+
account: health.account,
|
|
256
|
+
health,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
return rows;
|
|
260
|
+
}
|
|
229
261
|
/**
|
|
230
262
|
* Merge entries into the cache. An incoming `error` verdict (a network blip,
|
|
231
263
|
* not a server rejection) is indeterminate, so it must NOT clobber a prior
|
|
@@ -245,14 +277,15 @@ export function mergeAuthHealthEntries(current, incoming) {
|
|
|
245
277
|
/** Merge one or more entries into the cache (best-effort write). */
|
|
246
278
|
export function writeAuthHealthEntries(entries) {
|
|
247
279
|
try {
|
|
248
|
-
const
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
280
|
+
const target = cacheFilePath();
|
|
281
|
+
ensureLockTarget(target, JSON.stringify({ version: 1, entries: {} }));
|
|
282
|
+
withFileLock(target, () => {
|
|
283
|
+
const merged = {
|
|
284
|
+
version: 1,
|
|
285
|
+
entries: mergeAuthHealthEntries(readAuthHealthCache(), entries),
|
|
286
|
+
};
|
|
287
|
+
atomicWriteFileSync(target, JSON.stringify(merged, null, 2));
|
|
288
|
+
});
|
|
256
289
|
}
|
|
257
290
|
catch {
|
|
258
291
|
// best-effort; a failed write just means the next reader falls back to heuristics
|
|
@@ -12,8 +12,7 @@ import * as fs from 'fs';
|
|
|
12
12
|
import { simpleGit } from 'simple-git';
|
|
13
13
|
import { tryAutoPull, isGitRepo } from './git.js';
|
|
14
14
|
import { getSystemAgentsDir, getUserAgentsDir, getEnabledExtraRepos, getFetchCacheDir, } from './state.js';
|
|
15
|
-
import { lockFilePath, statusFilePath } from './auto-pull.js';
|
|
16
|
-
const LOCK_TTL_MS = 5 * 60 * 1000;
|
|
15
|
+
import { lockFilePath, statusFilePath, markDetachedSyncComplete, SYNC_LOCK_TTL_MS, } from './auto-pull.js';
|
|
17
16
|
/**
|
|
18
17
|
* Background auto-pull of ~/.agents/.system/ is off by default. When enabled it
|
|
19
18
|
* silently fast-forwards a tracked source tree that the CLI then reads as a
|
|
@@ -38,7 +37,7 @@ function tryAcquireLock(alias) {
|
|
|
38
37
|
const lock = lockFilePath(alias);
|
|
39
38
|
try {
|
|
40
39
|
const stat = fs.statSync(lock);
|
|
41
|
-
if (Date.now() - stat.mtimeMs <
|
|
40
|
+
if (Date.now() - stat.mtimeMs < SYNC_LOCK_TTL_MS)
|
|
42
41
|
return false;
|
|
43
42
|
}
|
|
44
43
|
catch {
|
|
@@ -130,6 +129,11 @@ async function main() {
|
|
|
130
129
|
}
|
|
131
130
|
}
|
|
132
131
|
await Promise.all(targets.map(processTarget));
|
|
132
|
+
// Stamp the cycle so the next foreground CLI invocation can skip the ~7ms
|
|
133
|
+
// detached spawn for SYNC_LOCK_TTL_MS (RUSH-2324). Written even when every
|
|
134
|
+
// target was lock-skipped or the target list was empty — "nothing to do"
|
|
135
|
+
// is still a completed cycle.
|
|
136
|
+
markDetachedSyncComplete();
|
|
133
137
|
}
|
|
134
138
|
main().catch(() => {
|
|
135
139
|
/* swallow — detached worker must never crash the parent's terminal */
|
package/dist/lib/auto-pull.d.ts
CHANGED
|
@@ -9,11 +9,26 @@
|
|
|
9
9
|
* Public API:
|
|
10
10
|
* spawnDetachedSync() — fire-and-forget; never blocks the foreground command.
|
|
11
11
|
* readRepoBehindMarkers() — synchronous; reads markers without consuming them.
|
|
12
|
+
* shouldSkipDetachedSync() — parent-side recency gate (RUSH-2324).
|
|
13
|
+
* markDetachedSyncComplete() — worker stamps a completed cycle for the parent gate.
|
|
12
14
|
*/
|
|
15
|
+
/**
|
|
16
|
+
* Shared 5-minute recency window for per-repo locks (worker) and the parent
|
|
17
|
+
* spawn gate (RUSH-2324). Worker skips a repo when its lock mtime is younger
|
|
18
|
+
* than this; the parent skips the entire detached spawn when a recent cycle
|
|
19
|
+
* completed or every existing lock is still within the window.
|
|
20
|
+
*/
|
|
21
|
+
export declare const SYNC_LOCK_TTL_MS: number;
|
|
13
22
|
/** Per-repo lock file path. mtime acts as a recency check. */
|
|
14
|
-
export declare function lockFilePath(alias: string): string;
|
|
23
|
+
export declare function lockFilePath(alias: string, fetchDir?: string): string;
|
|
15
24
|
/** Per-repo status marker path (for user/extras only). */
|
|
16
|
-
export declare function statusFilePath(alias: string): string;
|
|
25
|
+
export declare function statusFilePath(alias: string, fetchDir?: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Stamp written at the end of every detached-worker cycle (including the
|
|
28
|
+
* no-target / all-locks-skipped path). Parent `spawnDetachedSync` stats this
|
|
29
|
+
* one file instead of forking a child on every ordinary CLI invocation.
|
|
30
|
+
*/
|
|
31
|
+
export declare function lastSyncStampPath(fetchDir?: string): string;
|
|
17
32
|
export interface FetchStatusMarker {
|
|
18
33
|
alias: string;
|
|
19
34
|
dir: string;
|
|
@@ -22,8 +37,34 @@ export interface FetchStatusMarker {
|
|
|
22
37
|
branch: string;
|
|
23
38
|
fetchedAt: number;
|
|
24
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Whether the parent should skip forking the detached auto-pull worker.
|
|
42
|
+
*
|
|
43
|
+
* True when either:
|
|
44
|
+
* 1. `.last-sync` exists and its mtime is within {@link SYNC_LOCK_TTL_MS}
|
|
45
|
+
* (a prior cycle completed recently — the common warm path), or
|
|
46
|
+
* 2. the fetch dir has at least one `*.lock` and every lock is still within
|
|
47
|
+
* the same window (a worker is mid-flight, or a cycle left locks that
|
|
48
|
+
* still count as fresh).
|
|
49
|
+
*
|
|
50
|
+
* False (spawn) when the stamp is missing/stale and there are no fresh locks
|
|
51
|
+
* — including a missing fetch dir and an empty one. Cheap: one `stat` or one
|
|
52
|
+
* `readdir` + a few `stat`s; never spawns and never reads git.
|
|
53
|
+
*
|
|
54
|
+
* @param fetchDir - Override the fetch state dir (for tests). Defaults to the
|
|
55
|
+
* production getFetchCacheDir() path.
|
|
56
|
+
* @param now - Override the clock (for tests).
|
|
57
|
+
* @param ttlMs - Override the recency window (for tests).
|
|
58
|
+
*/
|
|
59
|
+
export declare function shouldSkipDetachedSync(fetchDir?: string, now?: number, ttlMs?: number): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Record that a detached-worker cycle finished (success, empty targets, or
|
|
62
|
+
* every repo skipped by its lock). Best-effort; a failed write just means the
|
|
63
|
+
* next foreground invocation will re-spawn the worker.
|
|
64
|
+
*/
|
|
65
|
+
export declare function markDetachedSyncComplete(fetchDir?: string): void;
|
|
25
66
|
/** Spawn the detached worker. No-op when AGENTS_NO_AUTOPULL=1 is set. */
|
|
26
|
-
export declare function spawnDetachedSync(): void;
|
|
67
|
+
export declare function spawnDetachedSync(fetchDir?: string): void;
|
|
27
68
|
/**
|
|
28
69
|
* Read all current status markers and return those where the local repo is
|
|
29
70
|
* behind upstream. Markers are NOT deleted — they persist until the next
|
package/dist/lib/auto-pull.js
CHANGED
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* Public API:
|
|
10
10
|
* spawnDetachedSync() — fire-and-forget; never blocks the foreground command.
|
|
11
11
|
* readRepoBehindMarkers() — synchronous; reads markers without consuming them.
|
|
12
|
+
* shouldSkipDetachedSync() — parent-side recency gate (RUSH-2324).
|
|
13
|
+
* markDetachedSyncComplete() — worker stamps a completed cycle for the parent gate.
|
|
12
14
|
*/
|
|
13
15
|
import * as fs from 'fs';
|
|
14
16
|
import * as path from 'path';
|
|
@@ -16,22 +18,103 @@ import { spawn } from 'child_process';
|
|
|
16
18
|
import { fileURLToPath } from 'url';
|
|
17
19
|
import { getFetchCacheDir } from './state.js';
|
|
18
20
|
import { backgroundSpawnOptions } from './platform/process.js';
|
|
21
|
+
/**
|
|
22
|
+
* Shared 5-minute recency window for per-repo locks (worker) and the parent
|
|
23
|
+
* spawn gate (RUSH-2324). Worker skips a repo when its lock mtime is younger
|
|
24
|
+
* than this; the parent skips the entire detached spawn when a recent cycle
|
|
25
|
+
* completed or every existing lock is still within the window.
|
|
26
|
+
*/
|
|
27
|
+
export const SYNC_LOCK_TTL_MS = 5 * 60 * 1000;
|
|
19
28
|
/** Where lock files and per-repo status markers live. */
|
|
20
29
|
function fetchStateDir() {
|
|
21
30
|
return getFetchCacheDir();
|
|
22
31
|
}
|
|
23
32
|
/** Per-repo lock file path. mtime acts as a recency check. */
|
|
24
|
-
export function lockFilePath(alias) {
|
|
25
|
-
return path.join(fetchStateDir(), `${alias}.lock`);
|
|
33
|
+
export function lockFilePath(alias, fetchDir) {
|
|
34
|
+
return path.join(fetchDir ?? fetchStateDir(), `${alias}.lock`);
|
|
26
35
|
}
|
|
27
36
|
/** Per-repo status marker path (for user/extras only). */
|
|
28
|
-
export function statusFilePath(alias) {
|
|
29
|
-
return path.join(fetchStateDir(), `${alias}.status.json`);
|
|
37
|
+
export function statusFilePath(alias, fetchDir) {
|
|
38
|
+
return path.join(fetchDir ?? fetchStateDir(), `${alias}.status.json`);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Stamp written at the end of every detached-worker cycle (including the
|
|
42
|
+
* no-target / all-locks-skipped path). Parent `spawnDetachedSync` stats this
|
|
43
|
+
* one file instead of forking a child on every ordinary CLI invocation.
|
|
44
|
+
*/
|
|
45
|
+
export function lastSyncStampPath(fetchDir) {
|
|
46
|
+
return path.join(fetchDir ?? fetchStateDir(), '.last-sync');
|
|
47
|
+
}
|
|
48
|
+
function isMtimeFresh(filePath, now, ttlMs) {
|
|
49
|
+
try {
|
|
50
|
+
return now - fs.statSync(filePath).mtimeMs < ttlMs;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Whether the parent should skip forking the detached auto-pull worker.
|
|
58
|
+
*
|
|
59
|
+
* True when either:
|
|
60
|
+
* 1. `.last-sync` exists and its mtime is within {@link SYNC_LOCK_TTL_MS}
|
|
61
|
+
* (a prior cycle completed recently — the common warm path), or
|
|
62
|
+
* 2. the fetch dir has at least one `*.lock` and every lock is still within
|
|
63
|
+
* the same window (a worker is mid-flight, or a cycle left locks that
|
|
64
|
+
* still count as fresh).
|
|
65
|
+
*
|
|
66
|
+
* False (spawn) when the stamp is missing/stale and there are no fresh locks
|
|
67
|
+
* — including a missing fetch dir and an empty one. Cheap: one `stat` or one
|
|
68
|
+
* `readdir` + a few `stat`s; never spawns and never reads git.
|
|
69
|
+
*
|
|
70
|
+
* @param fetchDir - Override the fetch state dir (for tests). Defaults to the
|
|
71
|
+
* production getFetchCacheDir() path.
|
|
72
|
+
* @param now - Override the clock (for tests).
|
|
73
|
+
* @param ttlMs - Override the recency window (for tests).
|
|
74
|
+
*/
|
|
75
|
+
export function shouldSkipDetachedSync(fetchDir, now = Date.now(), ttlMs = SYNC_LOCK_TTL_MS) {
|
|
76
|
+
const dir = fetchDir ?? fetchStateDir();
|
|
77
|
+
if (isMtimeFresh(lastSyncStampPath(dir), now, ttlMs))
|
|
78
|
+
return true;
|
|
79
|
+
let entries;
|
|
80
|
+
try {
|
|
81
|
+
entries = fs.readdirSync(dir);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
const locks = entries.filter((name) => name.endsWith('.lock'));
|
|
87
|
+
if (locks.length === 0)
|
|
88
|
+
return false;
|
|
89
|
+
return locks.every((name) => isMtimeFresh(path.join(dir, name), now, ttlMs));
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Record that a detached-worker cycle finished (success, empty targets, or
|
|
93
|
+
* every repo skipped by its lock). Best-effort; a failed write just means the
|
|
94
|
+
* next foreground invocation will re-spawn the worker.
|
|
95
|
+
*/
|
|
96
|
+
export function markDetachedSyncComplete(fetchDir) {
|
|
97
|
+
const dir = fetchDir ?? fetchStateDir();
|
|
98
|
+
const stamp = lastSyncStampPath(dir);
|
|
99
|
+
try {
|
|
100
|
+
if (!fs.existsSync(dir))
|
|
101
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
102
|
+
fs.writeFileSync(stamp, String(Date.now()));
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
/* best-effort */
|
|
106
|
+
}
|
|
30
107
|
}
|
|
31
108
|
/** Spawn the detached worker. No-op when AGENTS_NO_AUTOPULL=1 is set. */
|
|
32
|
-
export function spawnDetachedSync() {
|
|
109
|
+
export function spawnDetachedSync(fetchDir) {
|
|
33
110
|
if (process.env.AGENTS_NO_AUTOPULL === '1')
|
|
34
111
|
return;
|
|
112
|
+
// RUSH-2324: the spawn itself costs ~7ms mean on a warm box, and the worker
|
|
113
|
+
// almost always no-ops when a cycle ran in the last five minutes. Inspect
|
|
114
|
+
// the last-sync stamp + lock mtimes in the parent and skip the fork when
|
|
115
|
+
// everything is still fresh.
|
|
116
|
+
if (shouldSkipDetachedSync(fetchDir))
|
|
117
|
+
return;
|
|
35
118
|
// Resolve the worker path relative to the compiled location of this module.
|
|
36
119
|
// After `tsc`, both files land in the same directory under dist/lib/.
|
|
37
120
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface AgentsBinaryShadow {
|
|
2
|
+
/** Path of the shadowing binary as it appears to the caller. */
|
|
3
|
+
path: string;
|
|
4
|
+
/** Its self-reported version, if we can run it. */
|
|
5
|
+
version?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Whether two path spellings identify the same file.
|
|
9
|
+
*
|
|
10
|
+
* Two spellings of one file rarely compare equal on Windows: `realpathSync` does
|
|
11
|
+
* not expand 8.3 short names, so a path rooted at `os.tmpdir()`
|
|
12
|
+
* (`C:\Users\RUNNER~1\...` on a GitHub runner) never matches the long form
|
|
13
|
+
* (`C:\Users\runneradmin\...`) that `where` reports. Compare by device+inode
|
|
14
|
+
* first and fall back to case-insensitive resolved spellings.
|
|
15
|
+
*/
|
|
16
|
+
export declare function sameFile(a: string, b: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Find `agents` installs that are NOT the currently running binary.
|
|
19
|
+
*
|
|
20
|
+
* Checks two sources:
|
|
21
|
+
* 1. The current PATH: if `which agents` / `where agents` resolves to a
|
|
22
|
+
* different real binary than the one executing this code, it is an active
|
|
23
|
+
* shadow.
|
|
24
|
+
* 2. Well-known install directories: any executable `agents` whose realpath
|
|
25
|
+
* differs from the current entry is a latent shadow — it may win under a
|
|
26
|
+
* different PATH (e.g. the daemon's service-managed PATH).
|
|
27
|
+
*/
|
|
28
|
+
export declare function detectAgentsBinaryShadows(currentBin?: string, extraDirs?: readonly string[]): AgentsBinaryShadow[];
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect `agents` binaries that could shadow the currently running CLI.
|
|
3
|
+
*
|
|
4
|
+
* Scheduled command routines invoke the bare name `agents`. When an older install
|
|
5
|
+
* appears earlier on PATH than the current binary, routines silently run stale
|
|
6
|
+
* code (RUSH-2431). This module finds those shadows so `agents doctor` can warn.
|
|
7
|
+
*/
|
|
8
|
+
import { execFileSync } from 'child_process';
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import * as os from 'os';
|
|
11
|
+
import * as path from 'path';
|
|
12
|
+
import { getAgentsBinPath } from './cli-entry.js';
|
|
13
|
+
/** Realpath of `p`, or `p` itself if it cannot be resolved. */
|
|
14
|
+
function safeRealpath(p) {
|
|
15
|
+
try {
|
|
16
|
+
return fs.realpathSync(p);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return p;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Whether two path spellings identify the same file.
|
|
24
|
+
*
|
|
25
|
+
* Two spellings of one file rarely compare equal on Windows: `realpathSync` does
|
|
26
|
+
* not expand 8.3 short names, so a path rooted at `os.tmpdir()`
|
|
27
|
+
* (`C:\Users\RUNNER~1\...` on a GitHub runner) never matches the long form
|
|
28
|
+
* (`C:\Users\runneradmin\...`) that `where` reports. Compare by device+inode
|
|
29
|
+
* first and fall back to case-insensitive resolved spellings.
|
|
30
|
+
*/
|
|
31
|
+
export function sameFile(a, b) {
|
|
32
|
+
try {
|
|
33
|
+
const aStat = fs.statSync(a);
|
|
34
|
+
const bStat = fs.statSync(b);
|
|
35
|
+
if (aStat.dev === bStat.dev && aStat.ino === bStat.ino)
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
catch { /* compare their resolved path spellings below */ }
|
|
39
|
+
const aReal = safeRealpath(a);
|
|
40
|
+
const bReal = safeRealpath(b);
|
|
41
|
+
return process.platform === 'win32'
|
|
42
|
+
? aReal.toLowerCase() === bReal.toLowerCase()
|
|
43
|
+
: aReal === bReal;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Find `agents` installs that are NOT the currently running binary.
|
|
47
|
+
*
|
|
48
|
+
* Checks two sources:
|
|
49
|
+
* 1. The current PATH: if `which agents` / `where agents` resolves to a
|
|
50
|
+
* different real binary than the one executing this code, it is an active
|
|
51
|
+
* shadow.
|
|
52
|
+
* 2. Well-known install directories: any executable `agents` whose realpath
|
|
53
|
+
* differs from the current entry is a latent shadow — it may win under a
|
|
54
|
+
* different PATH (e.g. the daemon's service-managed PATH).
|
|
55
|
+
*/
|
|
56
|
+
export function detectAgentsBinaryShadows(currentBin = getAgentsBinPath(), extraDirs = defaultWellKnownDirs()) {
|
|
57
|
+
const currentReal = safeRealpath(currentBin);
|
|
58
|
+
const seen = new Set();
|
|
59
|
+
const shadows = [];
|
|
60
|
+
function addIfShadow(candidate) {
|
|
61
|
+
if (seen.has(candidate))
|
|
62
|
+
return;
|
|
63
|
+
seen.add(candidate);
|
|
64
|
+
if (sameFile(candidate, currentReal))
|
|
65
|
+
return;
|
|
66
|
+
let version;
|
|
67
|
+
try {
|
|
68
|
+
version = execFileSync(candidate, ['--version'], { encoding: 'utf-8', env: process.env })
|
|
69
|
+
.trim()
|
|
70
|
+
.split('\n')[0];
|
|
71
|
+
}
|
|
72
|
+
catch { /* binary may be unreadable/unrunnable — still report it */ }
|
|
73
|
+
shadows.push({ path: candidate, version });
|
|
74
|
+
}
|
|
75
|
+
// Active shadow under the current environment's PATH.
|
|
76
|
+
try {
|
|
77
|
+
const resolver = process.platform === 'win32' ? 'where' : 'which';
|
|
78
|
+
const pathAgents = execFileSync(resolver, ['agents'], { encoding: 'utf-8', env: process.env })
|
|
79
|
+
.split(/\r?\n/)
|
|
80
|
+
.map((s) => s.trim())
|
|
81
|
+
.filter(Boolean)[0];
|
|
82
|
+
if (pathAgents && !sameFile(pathAgents, currentReal)) {
|
|
83
|
+
addIfShadow(pathAgents);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch { /* no `agents` resolved on PATH */ }
|
|
87
|
+
// Latent shadows in well-known install locations.
|
|
88
|
+
for (const dir of extraDirs) {
|
|
89
|
+
for (const name of agentBinaryNames()) {
|
|
90
|
+
const candidate = path.join(dir, name);
|
|
91
|
+
try {
|
|
92
|
+
fs.accessSync(candidate, fs.constants.X_OK);
|
|
93
|
+
addIfShadow(candidate);
|
|
94
|
+
}
|
|
95
|
+
catch { /* ignore */ }
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return shadows;
|
|
99
|
+
}
|
|
100
|
+
function agentBinaryNames() {
|
|
101
|
+
return process.platform === 'win32' ? ['agents.exe', 'agents.cmd', 'agents'] : ['agents'];
|
|
102
|
+
}
|
|
103
|
+
function defaultWellKnownDirs() {
|
|
104
|
+
const home = os.homedir();
|
|
105
|
+
if (process.platform === 'win32') {
|
|
106
|
+
const programFiles = process.env.ProgramFiles ?? 'C:\\Program Files';
|
|
107
|
+
return [
|
|
108
|
+
path.join(home, 'AppData', 'Roaming', 'npm'),
|
|
109
|
+
path.join(programFiles, 'nodejs'),
|
|
110
|
+
path.dirname(process.execPath),
|
|
111
|
+
];
|
|
112
|
+
}
|
|
113
|
+
return [
|
|
114
|
+
path.join(home, '.local', 'bin'),
|
|
115
|
+
'/usr/local/bin',
|
|
116
|
+
'/opt/homebrew/bin',
|
|
117
|
+
path.join(home, '.npm-global', 'bin'),
|
|
118
|
+
path.join(home, '.bun', 'bin'),
|
|
119
|
+
path.dirname(process.execPath),
|
|
120
|
+
];
|
|
121
|
+
}
|
package/dist/lib/brand.js
CHANGED
|
@@ -17,7 +17,13 @@
|
|
|
17
17
|
* where the active profile is resolved brand-first.
|
|
18
18
|
*/
|
|
19
19
|
import { readMeta, updateMeta } from './state.js';
|
|
20
|
-
|
|
20
|
+
// Leaf list only — do NOT import agents.js here. index.ts imports brand on
|
|
21
|
+
// every invocation (resolveBrandName / disabledCommandsForActiveBrand); a
|
|
22
|
+
// static agents import pulls the full agents.ts → versions.ts graph (~90ms)
|
|
23
|
+
// into --version/--help and the secrets-broker hot path (RUSH-2331).
|
|
24
|
+
// reservedBrandNames is only called when minting a brand; AGENT_CLI_COMMANDS
|
|
25
|
+
// is pinned equal to AGENTS[*].cliCommand by agent-cli-commands.test.ts.
|
|
26
|
+
import { AGENT_CLI_COMMANDS } from './agent-cli-commands.js';
|
|
21
27
|
/** The default (unbranded) program name. */
|
|
22
28
|
export const DEFAULT_CLI_NAME = 'agents';
|
|
23
29
|
/** Valid brand names: a letter, then letters/digits/_/- (matches alias rules). */
|
|
@@ -45,8 +51,8 @@ export function isBranded() {
|
|
|
45
51
|
/** Names that would clobber an agent CLI shim or the `agents`/`ag` binary. */
|
|
46
52
|
export function reservedBrandNames() {
|
|
47
53
|
const reserved = new Set([DEFAULT_CLI_NAME, 'ag']);
|
|
48
|
-
for (const
|
|
49
|
-
reserved.add(
|
|
54
|
+
for (const cmd of AGENT_CLI_COMMANDS)
|
|
55
|
+
reserved.add(cmd);
|
|
50
56
|
return reserved;
|
|
51
57
|
}
|
|
52
58
|
/** Validate a proposed brand name; returns an error string or null when ok. */
|