@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
|
@@ -26,7 +26,22 @@ export function captureFleet(prev, inputs) {
|
|
|
26
26
|
// Roster: explicit map of the captured names. A hand-authored override for a
|
|
27
27
|
// device that still exists is preserved; a captured agent list only fills in
|
|
28
28
|
// when the manifest didn't already pin one for that device.
|
|
29
|
+
//
|
|
30
|
+
// A device absent from `inputs.devices` drops OUT of the roster — that is the
|
|
31
|
+
// intended "live state is the source of truth for WHICH devices exist". But
|
|
32
|
+
// `fleet.devices.<name>.config` is also the operator-config store, and a
|
|
33
|
+
// capture run from a box whose registry has not seen a peer would silently
|
|
34
|
+
// erase that peer's settings. Observed for real: capturing on yosemite-s0
|
|
35
|
+
// deleted zion's whole config block from the shared agents.yaml. So carry a
|
|
36
|
+
// dropped device's `config:` forward — config only, never its roster fields.
|
|
29
37
|
const devices = {};
|
|
38
|
+
for (const [name, prevOverride] of Object.entries(prevDevices)) {
|
|
39
|
+
if (inputs.devices.includes(name))
|
|
40
|
+
continue; // handled by the roster loop below
|
|
41
|
+
const config = prevOverride?.config;
|
|
42
|
+
if (config && Object.keys(config).length > 0)
|
|
43
|
+
devices[name] = { config };
|
|
44
|
+
}
|
|
30
45
|
for (const name of inputs.devices) {
|
|
31
46
|
const prevOverride = prevDevices[name] ?? {};
|
|
32
47
|
const override = { ...prevOverride };
|
|
@@ -59,6 +59,15 @@ export function parseFleetManifest(raw) {
|
|
|
59
59
|
for (const [name, ov] of Object.entries(o.devices)) {
|
|
60
60
|
// An empty entry (`device: {}`) inherits defaults — represent as {}.
|
|
61
61
|
const merged = ov == null ? {} : validateDefaults(ov, `devices.${name}`);
|
|
62
|
+
// `config:` is the operator-config block (`agents devices config`) —
|
|
63
|
+
// inert to the reconcile engine but part of the manifest shape.
|
|
64
|
+
const cfg = ov != null ? ov.config : undefined;
|
|
65
|
+
if (cfg !== undefined) {
|
|
66
|
+
if (typeof cfg !== 'object' || cfg === null || Array.isArray(cfg)) {
|
|
67
|
+
throw new Error(`fleet: devices.${name}.config must be a mapping of config keys to values.`);
|
|
68
|
+
}
|
|
69
|
+
merged.config = cfg;
|
|
70
|
+
}
|
|
62
71
|
map[name] = merged;
|
|
63
72
|
}
|
|
64
73
|
devices = map;
|
|
@@ -33,6 +33,15 @@ export interface FleetDeviceOverride {
|
|
|
33
33
|
agents?: string[];
|
|
34
34
|
sync?: string[];
|
|
35
35
|
login?: FleetLoginMode;
|
|
36
|
+
/**
|
|
37
|
+
* Operator config for this device, written by `agents devices config <name>`
|
|
38
|
+
* — the device-scope keys of the `lib/device-config.ts` registry (maxAgents,
|
|
39
|
+
* schedulerEnabled, ssh*, autoLaunch*, notes, …). This is the ONE store for
|
|
40
|
+
* per-device settings: central, synced, and backed up with agents.yaml.
|
|
41
|
+
* LEAK-FREE like the rest of the manifest — names and non-secret values only
|
|
42
|
+
* (a secrets-bundle NAME is fine; a credential value never is).
|
|
43
|
+
*/
|
|
44
|
+
config?: Record<string, unknown>;
|
|
36
45
|
}
|
|
37
46
|
/**
|
|
38
47
|
* The `fleet:` block as it appears in `agents.yaml` (or any `-f` file). `devices`
|
package/dist/lib/fleet-status.js
CHANGED
|
@@ -30,6 +30,7 @@ import * as path from 'path';
|
|
|
30
30
|
import { getCacheDir } from './state.js';
|
|
31
31
|
import { probeLocalStats } from './devices/health.js';
|
|
32
32
|
import { getActiveSessions } from './session/active.js';
|
|
33
|
+
import { atomicWriteFileSync, ensureLockTarget, withFileLock } from './fs-atomic.js';
|
|
33
34
|
/**
|
|
34
35
|
* Tally running-agent workload from a host's live sessions. "running" is the
|
|
35
36
|
* actively-working set (`status === 'running'`); `live` is every session the
|
|
@@ -95,14 +96,15 @@ export function readFleetStatus() {
|
|
|
95
96
|
/** Merge rows into the mirror (best-effort; preserves other hosts' rows). */
|
|
96
97
|
export function writeFleetStatusRows(entries) {
|
|
97
98
|
try {
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
99
|
+
const target = mirrorPath();
|
|
100
|
+
ensureLockTarget(target, JSON.stringify({ version: 1, entries: {} }));
|
|
101
|
+
withFileLock(target, () => {
|
|
102
|
+
const merged = {
|
|
103
|
+
version: 1,
|
|
104
|
+
entries: { ...readFleetStatus(), ...entries },
|
|
105
|
+
};
|
|
106
|
+
atomicWriteFileSync(target, JSON.stringify(merged, null, 2));
|
|
107
|
+
});
|
|
106
108
|
}
|
|
107
109
|
catch {
|
|
108
110
|
// best-effort; a failed write just means the reader sees an older union
|
package/dist/lib/git.d.ts
CHANGED
|
@@ -123,7 +123,7 @@ export declare function _resetSnapshotShaCacheForTest(): void;
|
|
|
123
123
|
*/
|
|
124
124
|
export declare function getGitHubUsername(): Promise<string | null>;
|
|
125
125
|
/**
|
|
126
|
-
* Resolve the GitHub username synchronously for `agents share`. Order:
|
|
126
|
+
* Resolve the GitHub username synchronously for `agents artifacts share`. Order:
|
|
127
127
|
* 1. `AGENTS_SHARE_GITHUB_USER` env override
|
|
128
128
|
* 2. `git config --global github.user`
|
|
129
129
|
* Falls back to null so callers can decide whether to require auth or proceed
|
|
@@ -267,7 +267,9 @@ export declare function hasLocalChanges(dir: string): Promise<boolean>;
|
|
|
267
267
|
export declare function displayHomePath(dir: string): string;
|
|
268
268
|
/**
|
|
269
269
|
* Pull changes in an existing repo.
|
|
270
|
-
*
|
|
270
|
+
* A dirty working tree no longer refuses outright: a fast-forward that touches
|
|
271
|
+
* no uncommitted path still runs (see `dirtyTreeRefusal`). It refuses when the
|
|
272
|
+
* branch has local commits to rebase, or when an incoming path is also dirty.
|
|
271
273
|
*
|
|
272
274
|
* Strategy (RUSH-2282):
|
|
273
275
|
* 1. Fetch, then compare HEAD to the resolved tracking ref.
|
|
@@ -289,15 +291,27 @@ export declare function pullRepo(dir: string): Promise<{
|
|
|
289
291
|
* Rebase a repo onto its remote, optionally pushing local commits back up.
|
|
290
292
|
*
|
|
291
293
|
* The one-repo counterpart to `pullRepo` used by `agents sync <repo>`:
|
|
292
|
-
* 1.
|
|
293
|
-
* 2.
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
294
|
+
* 1. `git fetch origin`.
|
|
295
|
+
* 2. Clean tree → `git pull --rebase origin <branch>`: rebase, not merge, so a
|
|
296
|
+
* local commit lands cleanly on top of upstream with no merge bubble.
|
|
297
|
+
* 3. Dirty tree → fast-forward instead, but only when that is provably safe:
|
|
298
|
+
* no local commits ahead of upstream, and no incoming path collides with a
|
|
299
|
+
* dirty one. Otherwise refuse, naming the paths that collided.
|
|
300
|
+
* 4. When `push` is set, `git push origin <branch>` to send local commits up.
|
|
297
301
|
*
|
|
298
302
|
* The branch is read from the repo's current HEAD (falls back to `main`) rather
|
|
299
303
|
* than hardcoded. System repos pass `push: false` — they are pull-only mirrors
|
|
300
304
|
* of the npm-shipped upstream.
|
|
305
|
+
*
|
|
306
|
+
* Why step 3 exists: refusing on *any* dirt strands merged changes indefinitely.
|
|
307
|
+
* A DotAgents repo accumulates unrelated local state — a modified `agents.yaml`,
|
|
308
|
+
* a session's scratch file, a machine-local dotfile — and under the old rule one
|
|
309
|
+
* such file froze that box's layer forever, silently. Measured 2026-08-10: a
|
|
310
|
+
* merged fix could not reach three of three boxes, each blocked by files the
|
|
311
|
+
* incoming commits never touched. A `--ff-only` merge is the safe primitive
|
|
312
|
+
* here: it cannot rewrite local commits, and git itself aborts rather than
|
|
313
|
+
* overwrite a modified file, so the path check is belt-and-braces, not the only
|
|
314
|
+
* guard.
|
|
301
315
|
*/
|
|
302
316
|
export declare function syncRepoGit(dir: string, opts: {
|
|
303
317
|
push: boolean;
|
package/dist/lib/git.js
CHANGED
|
@@ -437,7 +437,7 @@ function readGitConfigUser() {
|
|
|
437
437
|
}
|
|
438
438
|
}
|
|
439
439
|
/**
|
|
440
|
-
* Resolve the GitHub username synchronously for `agents share`. Order:
|
|
440
|
+
* Resolve the GitHub username synchronously for `agents artifacts share`. Order:
|
|
441
441
|
* 1. `AGENTS_SHARE_GITHUB_USER` env override
|
|
442
442
|
* 2. `git config --global github.user`
|
|
443
443
|
* Falls back to null so callers can decide whether to require auth or proceed
|
|
@@ -865,7 +865,9 @@ export function displayHomePath(dir) {
|
|
|
865
865
|
}
|
|
866
866
|
/**
|
|
867
867
|
* Pull changes in an existing repo.
|
|
868
|
-
*
|
|
868
|
+
* A dirty working tree no longer refuses outright: a fast-forward that touches
|
|
869
|
+
* no uncommitted path still runs (see `dirtyTreeRefusal`). It refuses when the
|
|
870
|
+
* branch has local commits to rebase, or when an incoming path is also dirty.
|
|
869
871
|
*
|
|
870
872
|
* Strategy (RUSH-2282):
|
|
871
873
|
* 1. Fetch, then compare HEAD to the resolved tracking ref.
|
|
@@ -914,11 +916,18 @@ export async function pullRepo(dir) {
|
|
|
914
916
|
};
|
|
915
917
|
}
|
|
916
918
|
const status = await git.status();
|
|
917
|
-
|
|
919
|
+
// A dirty tree is not decided here: whether a fast-forward is safe depends
|
|
920
|
+
// on what is actually incoming, and that needs a fetched upstream ref. The
|
|
921
|
+
// gate therefore sits just before the integrate step below. The exception is
|
|
922
|
+
// a repo with no remote at all — there is nothing to fast-forward from, so
|
|
923
|
+
// the dirt is the whole answer and the resolution below would only fail
|
|
924
|
+
// with a less useful message.
|
|
925
|
+
const isDirty = !status.isClean();
|
|
926
|
+
if (isDirty && (await git.getRemotes()).length === 0) {
|
|
918
927
|
return {
|
|
919
928
|
success: false,
|
|
920
929
|
commit: '',
|
|
921
|
-
error: `Blocked by local changes. Commit or discard them before pulling.\n\n cd ${displayHomePath(dir)} && git status`,
|
|
930
|
+
error: `Blocked by local changes: the repo has no remote to pull from. Commit or discard them before pulling.\n\n cd ${displayHomePath(dir)} && git status`,
|
|
922
931
|
};
|
|
923
932
|
}
|
|
924
933
|
const branch = status.current || 'main';
|
|
@@ -978,6 +987,20 @@ export async function pullRepo(dir) {
|
|
|
978
987
|
Number.isFinite(behindCount) &&
|
|
979
988
|
aheadCount === 0 &&
|
|
980
989
|
behindCount > 0;
|
|
990
|
+
// Dirty tree: same rule `syncRepoGit` applies, from the same function — a
|
|
991
|
+
// fast-forward that touches nothing the author is holding may proceed; a
|
|
992
|
+
// rebase or a colliding path may not. Refusing on any dirt at all is what
|
|
993
|
+
// used to strand merged changes on every box that had an unrelated edit.
|
|
994
|
+
if (isDirty) {
|
|
995
|
+
const refusal = await dirtyTreeRefusal(git, status, tracking);
|
|
996
|
+
if (refusal) {
|
|
997
|
+
return {
|
|
998
|
+
success: false,
|
|
999
|
+
commit: '',
|
|
1000
|
+
error: `Blocked by local changes: ${refusal}. Commit or discard them before pulling.\n\n cd ${displayHomePath(dir)} && git status`,
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
981
1004
|
try {
|
|
982
1005
|
if (canFastForward) {
|
|
983
1006
|
// Integrate the already-fetched tracking ref. No network, no FETCH_HEAD.
|
|
@@ -1017,19 +1040,92 @@ export async function pullRepo(dir) {
|
|
|
1017
1040
|
return { success: false, commit: '', error: err.message };
|
|
1018
1041
|
}
|
|
1019
1042
|
}
|
|
1043
|
+
/**
|
|
1044
|
+
* Every repo-relative path a status reports as locally touched, in one set.
|
|
1045
|
+
*
|
|
1046
|
+
* Reads `status.files`, which `simple-git` documents as "all files" and which is
|
|
1047
|
+
* the same source `isClean()` is computed from — so this set and the decision to
|
|
1048
|
+
* treat the tree as dirty can never disagree. The per-category arrays
|
|
1049
|
+
* (`modified`, `staged`, `not_added`, …) are projections of that list; unioning
|
|
1050
|
+
* them by hand means a category nobody thought of contributes nothing. `from`
|
|
1051
|
+
* carries a rename's original path, and the incoming side may collide with
|
|
1052
|
+
* either end.
|
|
1053
|
+
*/
|
|
1054
|
+
function dirtyPathSet(status) {
|
|
1055
|
+
const out = new Set();
|
|
1056
|
+
for (const f of status.files || []) {
|
|
1057
|
+
if (f?.path)
|
|
1058
|
+
out.add(f.path);
|
|
1059
|
+
if (f?.from)
|
|
1060
|
+
out.add(f.from);
|
|
1061
|
+
}
|
|
1062
|
+
return out;
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* Why a dirty working tree must NOT fast-forward to `upstreamRef` — or `null`
|
|
1066
|
+
* when it safely can.
|
|
1067
|
+
*
|
|
1068
|
+
* The single home for that decision: `syncRepoGit` and `pullRepo` both integrate
|
|
1069
|
+
* upstream and both meet dirty trees, and two copies of this rule would drift
|
|
1070
|
+
* into two different answers for one question. Refusing outright is the thing
|
|
1071
|
+
* being replaced — it strands merged changes behind unrelated local files —
|
|
1072
|
+
* so the rule is narrow and stated once:
|
|
1073
|
+
*
|
|
1074
|
+
* - local commits ahead of upstream → refuse (they need a rebase, which
|
|
1075
|
+
* requires a clean tree);
|
|
1076
|
+
* - an incoming path that is also dirty → refuse, and name it;
|
|
1077
|
+
* - otherwise the fast-forward touches nothing the author is holding.
|
|
1078
|
+
*
|
|
1079
|
+
* `-z` on the diff because `git diff --name-only` C-quotes paths containing
|
|
1080
|
+
* unicode or control characters — `café.txt` comes back as `"caf\303\251.txt"`,
|
|
1081
|
+
* while `status.files` reports it raw. Without `-z` the two sides are in
|
|
1082
|
+
* different encodings and a collision on such a path silently misses. (A plain
|
|
1083
|
+
* space does NOT trigger quoting; `my file.txt` is emitted as-is either way.)
|
|
1084
|
+
*/
|
|
1085
|
+
async function dirtyTreeRefusal(git, status, upstreamRef) {
|
|
1086
|
+
const ahead = parseInt((await git.raw(['rev-list', '--count', `${upstreamRef}..HEAD`])).trim(), 10);
|
|
1087
|
+
if (Number.isNaN(ahead))
|
|
1088
|
+
return 'the upstream ref could not be compared with HEAD';
|
|
1089
|
+
if (ahead > 0) {
|
|
1090
|
+
return `the branch has ${ahead} local commit(s) to rebase, which needs a clean tree`;
|
|
1091
|
+
}
|
|
1092
|
+
const dirty = dirtyPathSet(status);
|
|
1093
|
+
const incoming = (await git.raw(['diff', '--name-only', '-z', `HEAD..${upstreamRef}`]))
|
|
1094
|
+
.split('\0')
|
|
1095
|
+
.filter(Boolean);
|
|
1096
|
+
const collisions = incoming.filter((p) => dirty.has(p));
|
|
1097
|
+
if (collisions.length > 0) {
|
|
1098
|
+
const shown = collisions.slice(0, 5).join(', ');
|
|
1099
|
+
const more = collisions.length > 5 ? ` (+${collisions.length - 5} more)` : '';
|
|
1100
|
+
return `incoming changes touch uncommitted paths: ${shown}${more}`;
|
|
1101
|
+
}
|
|
1102
|
+
return null;
|
|
1103
|
+
}
|
|
1020
1104
|
/**
|
|
1021
1105
|
* Rebase a repo onto its remote, optionally pushing local commits back up.
|
|
1022
1106
|
*
|
|
1023
1107
|
* The one-repo counterpart to `pullRepo` used by `agents sync <repo>`:
|
|
1024
|
-
* 1.
|
|
1025
|
-
* 2.
|
|
1026
|
-
*
|
|
1027
|
-
*
|
|
1028
|
-
*
|
|
1108
|
+
* 1. `git fetch origin`.
|
|
1109
|
+
* 2. Clean tree → `git pull --rebase origin <branch>`: rebase, not merge, so a
|
|
1110
|
+
* local commit lands cleanly on top of upstream with no merge bubble.
|
|
1111
|
+
* 3. Dirty tree → fast-forward instead, but only when that is provably safe:
|
|
1112
|
+
* no local commits ahead of upstream, and no incoming path collides with a
|
|
1113
|
+
* dirty one. Otherwise refuse, naming the paths that collided.
|
|
1114
|
+
* 4. When `push` is set, `git push origin <branch>` to send local commits up.
|
|
1029
1115
|
*
|
|
1030
1116
|
* The branch is read from the repo's current HEAD (falls back to `main`) rather
|
|
1031
1117
|
* than hardcoded. System repos pass `push: false` — they are pull-only mirrors
|
|
1032
1118
|
* of the npm-shipped upstream.
|
|
1119
|
+
*
|
|
1120
|
+
* Why step 3 exists: refusing on *any* dirt strands merged changes indefinitely.
|
|
1121
|
+
* A DotAgents repo accumulates unrelated local state — a modified `agents.yaml`,
|
|
1122
|
+
* a session's scratch file, a machine-local dotfile — and under the old rule one
|
|
1123
|
+
* such file froze that box's layer forever, silently. Measured 2026-08-10: a
|
|
1124
|
+
* merged fix could not reach three of three boxes, each blocked by files the
|
|
1125
|
+
* incoming commits never touched. A `--ff-only` merge is the safe primitive
|
|
1126
|
+
* here: it cannot rewrite local commits, and git itself aborts rather than
|
|
1127
|
+
* overwrite a modified file, so the path check is belt-and-braces, not the only
|
|
1128
|
+
* guard.
|
|
1033
1129
|
*/
|
|
1034
1130
|
export async function syncRepoGit(dir, opts) {
|
|
1035
1131
|
try {
|
|
@@ -1038,18 +1134,26 @@ export async function syncRepoGit(dir, opts) {
|
|
|
1038
1134
|
}
|
|
1039
1135
|
const git = simpleGit(dir);
|
|
1040
1136
|
const status = await git.status();
|
|
1041
|
-
if (!status.isClean()) {
|
|
1042
|
-
return {
|
|
1043
|
-
success: false,
|
|
1044
|
-
commit: '',
|
|
1045
|
-
pushed: false,
|
|
1046
|
-
error: `Working tree has uncommitted changes. Commit or discard them first.\n\n cd ${dir} && git status`,
|
|
1047
|
-
};
|
|
1048
|
-
}
|
|
1049
1137
|
const branch = status.current || 'main';
|
|
1050
1138
|
assertValidBranchName(branch);
|
|
1051
1139
|
await git.fetch('origin');
|
|
1052
|
-
|
|
1140
|
+
if (status.isClean()) {
|
|
1141
|
+
await git.pull('origin', branch, { '--rebase': 'true' });
|
|
1142
|
+
}
|
|
1143
|
+
else {
|
|
1144
|
+
// Dirty tree: a rebase would refuse outright, so fast-forward instead —
|
|
1145
|
+
// but only when nothing local can be lost. One shared rule, see above.
|
|
1146
|
+
const refusal = await dirtyTreeRefusal(git, status, `origin/${branch}`);
|
|
1147
|
+
if (refusal) {
|
|
1148
|
+
return {
|
|
1149
|
+
success: false,
|
|
1150
|
+
commit: '',
|
|
1151
|
+
pushed: false,
|
|
1152
|
+
error: `Working tree has uncommitted changes and ${refusal}. Commit or discard them first.\n\n cd ${dir} && git status`,
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
await git.raw(['merge', '--ff-only', `origin/${branch}`]);
|
|
1156
|
+
}
|
|
1053
1157
|
installGithooksSymlinks(dir);
|
|
1054
1158
|
let pushed = false;
|
|
1055
1159
|
if (opts.push) {
|
|
@@ -13,6 +13,11 @@ import { type HostTask } from './tasks.js';
|
|
|
13
13
|
import { type HostCredentials } from './credentials.js';
|
|
14
14
|
import { deriveMirroredCwd, homeRemainder, remoteCdPrefix } from '../project-root.js';
|
|
15
15
|
export { deriveMirroredCwd, homeRemainder, remoteCdPrefix };
|
|
16
|
+
/**
|
|
17
|
+
* Diagnostic helper for RUSH-2441: log the requested agent and initial remote
|
|
18
|
+
* `agents run` argv without changing normal command output.
|
|
19
|
+
*/
|
|
20
|
+
export declare function logForwardedArgs(kind: string, agent: string, version: string | undefined, args: string[], hasPrompt: boolean): void;
|
|
16
21
|
/**
|
|
17
22
|
* Merge the resolved actor's provenance env UNDER a caller-supplied env, so every
|
|
18
23
|
* remote `agents …` invocation forwards `AGENTS_ACTOR*` / `GIT_*` across the SSH
|
|
@@ -73,10 +78,10 @@ export declare function terminateDispatchedTask(task: HostTask): void;
|
|
|
73
78
|
export declare function buildStopRemoteCommand(pid: number, remoteExit: string): string;
|
|
74
79
|
export declare function buildWindowsStopRemoteCommand(pid: number, remoteExit: string): string;
|
|
75
80
|
/**
|
|
76
|
-
* Stop a running host task from the origin machine (`agents
|
|
81
|
+
* Stop a running host task from the origin machine (`agents devices stop <id>`).
|
|
77
82
|
*
|
|
78
83
|
* Unlike {@link terminateDispatchedTask} (rollback cleanup after a failed
|
|
79
|
-
* persist), this keeps the remote log so `agents
|
|
84
|
+
* persist), this keeps the remote log so `agents logs <id>` still works,
|
|
80
85
|
* writes a terminal `.exit` marker only when we actually stopped a live group
|
|
81
86
|
* (or no code existed), and never clobbers a real completed-run exit code.
|
|
82
87
|
*/
|
|
@@ -130,7 +135,7 @@ export interface DispatchOptions {
|
|
|
130
135
|
sessionId?: string;
|
|
131
136
|
/**
|
|
132
137
|
* Durable `--name <slug>` handle, forwarded to the remote `agents run` and
|
|
133
|
-
* recorded on the local task so `agents
|
|
138
|
+
* recorded on the local task so `agents logs <name>` / `agents devices ps` resolve it.
|
|
134
139
|
*/
|
|
135
140
|
name?: string;
|
|
136
141
|
/** Resume an existing session on the host by id (via `agents run --resume`). */
|
|
@@ -26,6 +26,30 @@ import { RUN_AUTO_KEYWORD, RUN_AUTO_HOST_RESOLVED_ENV } from '../types.js';
|
|
|
26
26
|
// shell builder (devices/connect.ts) as well as this dispatch layer. Re-exported
|
|
27
27
|
// here so existing `hosts/dispatch.js` importers and tests keep resolving them.
|
|
28
28
|
export { deriveMirroredCwd, homeRemainder, remoteCdPrefix };
|
|
29
|
+
/**
|
|
30
|
+
* Diagnostic helper for RUSH-2441: log the requested agent and initial remote
|
|
31
|
+
* `agents run` argv without changing normal command output.
|
|
32
|
+
*/
|
|
33
|
+
export function logForwardedArgs(kind, agent, version, args, hasPrompt) {
|
|
34
|
+
if (!process.env.AGENTS_DISPATCH_DEBUG)
|
|
35
|
+
return;
|
|
36
|
+
const safeArgs = [...args];
|
|
37
|
+
if (safeArgs[0] === 'run' && safeArgs[2] && hasPrompt) {
|
|
38
|
+
safeArgs[2] = '<prompt>';
|
|
39
|
+
}
|
|
40
|
+
for (let i = 0; i < safeArgs.length; i++) {
|
|
41
|
+
if (safeArgs[i] === '--env' && safeArgs[i + 1]) {
|
|
42
|
+
const key = safeArgs[i + 1].split('=', 1)[0];
|
|
43
|
+
safeArgs[i + 1] = `${key}=<redacted>`;
|
|
44
|
+
i++;
|
|
45
|
+
}
|
|
46
|
+
else if (safeArgs[i] === '--') {
|
|
47
|
+
safeArgs.splice(i + 1, safeArgs.length - i - 1, '<passthrough redacted>');
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
process.stderr.write(`[dispatch:${kind}] agent=${agent}${version ? `@${version}` : ''} args=${JSON.stringify(safeArgs)}\n`);
|
|
52
|
+
}
|
|
29
53
|
// Use $HOME (not ~) so the path is correct whether or not it's quoted and
|
|
30
54
|
// regardless of the run's cwd. Task ids are 8 hex chars, so these paths are
|
|
31
55
|
// injection-safe to interpolate unquoted into remote commands.
|
|
@@ -189,10 +213,10 @@ export function buildWindowsStopRemoteCommand(pid, remoteExit) {
|
|
|
189
213
|
return `powershell -NoProfile -EncodedCommand ${encodePowershell(script)}`;
|
|
190
214
|
}
|
|
191
215
|
/**
|
|
192
|
-
* Stop a running host task from the origin machine (`agents
|
|
216
|
+
* Stop a running host task from the origin machine (`agents devices stop <id>`).
|
|
193
217
|
*
|
|
194
218
|
* Unlike {@link terminateDispatchedTask} (rollback cleanup after a failed
|
|
195
|
-
* persist), this keeps the remote log so `agents
|
|
219
|
+
* persist), this keeps the remote log so `agents logs <id>` still works,
|
|
196
220
|
* writes a terminal `.exit` marker only when we actually stopped a live group
|
|
197
221
|
* (or no code existed), and never clobbers a real completed-run exit code.
|
|
198
222
|
*/
|
|
@@ -313,7 +337,7 @@ async function launchDetached(host, target, opts) {
|
|
|
313
337
|
remoteShell,
|
|
314
338
|
});
|
|
315
339
|
// -1 = the follow window closed while the run continues on the host. Leave the
|
|
316
|
-
// record 'running' (do NOT freeze it terminal) so a later `
|
|
340
|
+
// record 'running' (do NOT freeze it terminal) so a later `agents devices ps` / `agents logs`
|
|
317
341
|
// reconcile against the remote `.exit` resolves the true final status.
|
|
318
342
|
const finished = exitCode === -1 ? task : (updateTask(id, terminalPatch(exitCode)) ?? task);
|
|
319
343
|
return { task: finished, exitCode };
|
|
@@ -382,6 +406,7 @@ export function buildRunForwardedArgs(opts) {
|
|
|
382
406
|
args.push('--emit-session-id');
|
|
383
407
|
if (opts.passthroughArgs && opts.passthroughArgs.length > 0)
|
|
384
408
|
args.push('--', ...opts.passthroughArgs);
|
|
409
|
+
logForwardedArgs('headless', opts.agent, opts.version, args, true);
|
|
385
410
|
return args;
|
|
386
411
|
}
|
|
387
412
|
/**
|
|
@@ -438,6 +463,7 @@ export function buildInteractiveRunForwardedArgs(opts) {
|
|
|
438
463
|
if (opts.passthroughArgs && opts.passthroughArgs.length > 0) {
|
|
439
464
|
args.push('--', ...opts.passthroughArgs);
|
|
440
465
|
}
|
|
466
|
+
logForwardedArgs('interactive', opts.agent, opts.version, args, Boolean(opts.prompt && opts.forceInteractive));
|
|
441
467
|
return args;
|
|
442
468
|
}
|
|
443
469
|
/**
|
package/dist/lib/hosts/logs.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Shared host-task log viewer — the show-or-follow core behind
|
|
3
|
-
*
|
|
2
|
+
* Shared host-task log viewer — the show-or-follow core behind the
|
|
3
|
+
* top-level `agents logs <id>`.
|
|
4
4
|
*
|
|
5
5
|
* A running task with follow re-enters the offset-tail (`followHostTask`).
|
|
6
6
|
* Otherwise the view is **concise by default**: a bounded tail of the captured
|
package/dist/lib/hosts/logs.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Shared host-task log viewer — the show-or-follow core behind
|
|
3
|
-
*
|
|
2
|
+
* Shared host-task log viewer — the show-or-follow core behind the
|
|
3
|
+
* top-level `agents logs <id>`.
|
|
4
4
|
*
|
|
5
5
|
* A running task with follow re-enters the offset-tail (`followHostTask`).
|
|
6
6
|
* Otherwise the view is **concise by default**: a bounded tail of the captured
|
package/dist/lib/hosts/option.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
/** Attach the standard `--host` flag family to a command and return it (chainable). */
|
|
13
13
|
export function addHostOption(cmd) {
|
|
14
14
|
return cmd
|
|
15
|
-
.option('-H, --host <name>', 'Run this command on another machine over SSH instead of locally — a device,
|
|
15
|
+
.option('-H, --host <name>', 'Run this command on another machine over SSH instead of locally — a device, an ssh-config host, user@host, or `all` to fan out across every registered device. See `agents devices`.')
|
|
16
16
|
.option('--device <name>', 'Alias of --host: run this command on a registered device (from `agents devices`), or `all` to run it across the whole fleet.')
|
|
17
17
|
.option('--remote-cwd <dir>', "Working directory on the host for --host runs. Resolves on the REMOTE host — pass a '$HOME'-relative path (single-quoted so your local shell doesn't expand it) or a valid remote absolute path; a local ~ expands here and won't exist there (/Users/you vs /home/you). No effect on 'teams add'.")
|
|
18
18
|
.option('--no-tty', 'Force non-interactive output for --host runs even from a terminal.')
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
import { type Host } from './types.js';
|
|
20
20
|
import { type DeviceProfile, type DeviceRegistry } from '../devices/registry.js';
|
|
21
21
|
import { runLocalCommand, runOnDevice } from '../devices/fleet.js';
|
|
22
|
+
/** Re-export for callers that historically imported flagValue from this module. */
|
|
23
|
+
export { flagValue, hasHostRoutingFlag } from './routing-flag.js';
|
|
22
24
|
/** Per-command remote behaviour. Absence from this map = not host-routable here. */
|
|
23
25
|
interface RemoteSpec {
|
|
24
26
|
/** Flags appended when running non-interactively (no local TTY / `--no-tty`). */
|
|
@@ -46,8 +48,6 @@ export declare const REMOTE_PASSTHROUGH: Record<string, RemoteSpec>;
|
|
|
46
48
|
* these to {@link REMOTE_PASSTHROUGH}.
|
|
47
49
|
*/
|
|
48
50
|
export declare const OWN_HOST_COMMANDS: Set<string>;
|
|
49
|
-
/** Pull the value of `--host`/`-H`/`--remote-cwd` (any form) out of an argv. */
|
|
50
|
-
export declare function flagValue(args: string[], long: string, short?: string): string | undefined;
|
|
51
51
|
/** Injectable dependencies for {@link runFleetPassthrough} — used by tests. */
|
|
52
52
|
export interface FleetPassthroughOptions {
|
|
53
53
|
/** Override the device registry loader (tests). */
|
|
@@ -131,4 +131,3 @@ export declare function passthroughSshOptions(host: Host, interactive: boolean):
|
|
|
131
131
|
multiplex: true;
|
|
132
132
|
extraSshArgs: string[];
|
|
133
133
|
};
|
|
134
|
-
export {};
|
|
@@ -23,13 +23,19 @@ import { sshTargetFor, hostIdentityArgs } from './types.js';
|
|
|
23
23
|
import { dispatchAgentsCommand, withActorEnv } from './dispatch.js';
|
|
24
24
|
import { stripRoutingFlags, buildRemoteAgentsInvocation, stripClixml, HOST_ROUTING_SPECS, } from './remote-cmd.js';
|
|
25
25
|
import { resolveRemoteOsSync } from './remote-os.js';
|
|
26
|
-
|
|
26
|
+
// Leaf import: `session/sync/config.js` re-exports machineId from machine-id.js
|
|
27
|
+
// but pulling the re-export path drags secrets/bundles (~140ms cold). Same value,
|
|
28
|
+
// 6–7× cheaper graph (RUSH-2374 proposal 2).
|
|
29
|
+
import { machineId } from '../machine-id.js';
|
|
27
30
|
import { isDeviceAuto, resolveDeviceAffinity } from '../smart-launch.js';
|
|
31
|
+
import { flagValue, hasHostRoutingFlag } from './routing-flag.js';
|
|
28
32
|
import { loadDevices } from '../devices/registry.js';
|
|
29
33
|
import { isSelfHost } from '../devices/self-host.js';
|
|
30
34
|
import { fanOutDevices, planFleetTargets, runLocalCommand, runOnDevice, } from '../devices/fleet.js';
|
|
31
35
|
import { platformGroupLabel } from '../devices/health-report.js';
|
|
32
36
|
import { isKnownTopLevelCommand } from '../startup/command-registry.js';
|
|
37
|
+
/** Re-export for callers that historically imported flagValue from this module. */
|
|
38
|
+
export { flagValue, hasHostRoutingFlag } from './routing-flag.js';
|
|
33
39
|
/**
|
|
34
40
|
* First-class groups that run transparently on a remote via SSH when
|
|
35
41
|
* `--host`/`--device` is present. Keep both canonical names and aliases
|
|
@@ -95,9 +101,7 @@ export const REMOTE_PASSTHROUGH = {
|
|
|
95
101
|
worktree: {},
|
|
96
102
|
events: {},
|
|
97
103
|
audit: {},
|
|
98
|
-
lock: {},
|
|
99
104
|
feedback: {},
|
|
100
|
-
wallet: {},
|
|
101
105
|
pty: {},
|
|
102
106
|
tmux: {},
|
|
103
107
|
watchdog: {},
|
|
@@ -118,6 +122,7 @@ export const OWN_HOST_COMMANDS = new Set([
|
|
|
118
122
|
'feed',
|
|
119
123
|
'computer',
|
|
120
124
|
'secrets',
|
|
125
|
+
'accounts', // `accounts sync --device` names the destination, not remote routing
|
|
121
126
|
'logs',
|
|
122
127
|
'hosts',
|
|
123
128
|
'ssh',
|
|
@@ -135,21 +140,6 @@ const STRIP_SPECS = [
|
|
|
135
140
|
{ long: 'hosts', takesValue: true },
|
|
136
141
|
{ long: 'devices', takesValue: true },
|
|
137
142
|
];
|
|
138
|
-
/** Pull the value of `--host`/`-H`/`--remote-cwd` (any form) out of an argv. */
|
|
139
|
-
export function flagValue(args, long, short) {
|
|
140
|
-
for (let i = 0; i < args.length; i++) {
|
|
141
|
-
const a = args[i];
|
|
142
|
-
if (a === `--${long}` || (short && a === `-${short}`))
|
|
143
|
-
return args[i + 1];
|
|
144
|
-
if (a.startsWith(`--${long}=`))
|
|
145
|
-
return a.slice(long.length + 3);
|
|
146
|
-
if (short && a.startsWith(`-${short}=`))
|
|
147
|
-
return a.slice(short.length + 2);
|
|
148
|
-
if (short && new RegExp(`^-${short}(.+)`).test(a))
|
|
149
|
-
return a.slice(2);
|
|
150
|
-
}
|
|
151
|
-
return undefined;
|
|
152
|
-
}
|
|
153
143
|
/** Synthesize a `Host` for a raw `user@host` / bare-alias target (not enrolled). */
|
|
154
144
|
function syntheticHost(target) {
|
|
155
145
|
const at = target.indexOf('@');
|
|
@@ -584,13 +574,9 @@ export async function maybeRunOnHost(command, allArgs, opts) {
|
|
|
584
574
|
*/
|
|
585
575
|
export async function maybeRunStandaloneOnHost(command, opts) {
|
|
586
576
|
const rawArgs = process.argv.slice(2);
|
|
587
|
-
const hasRoutingFlag = flagValue(rawArgs, 'host', 'H') !== undefined ||
|
|
588
|
-
flagValue(rawArgs, 'device') !== undefined ||
|
|
589
|
-
flagValue(rawArgs, 'hosts') !== undefined ||
|
|
590
|
-
flagValue(rawArgs, 'devices') !== undefined;
|
|
591
577
|
// No routing flag → nothing to route or strip. Leave argv alone so a purely
|
|
592
578
|
// local run keeps every flag it passed.
|
|
593
|
-
if (!
|
|
579
|
+
if (!hasHostRoutingFlag(rawArgs))
|
|
594
580
|
return false;
|
|
595
581
|
// Keep --help/--version local (docs must work without a reachable host), mirroring
|
|
596
582
|
// index.ts's `helpOrVersionRequested` guard, but still strip the routing flags
|
|
@@ -626,7 +612,7 @@ export function streamAgentsOnHost(host, forwardedArgs, opts = {}) {
|
|
|
626
612
|
const code = sshStream(target, remoteCmd, passthroughSshOptions(host, !!opts.interactive));
|
|
627
613
|
if (code === 255) {
|
|
628
614
|
console.error(chalk.red(`${host.name}: unreachable over SSH (asleep, offline, or host key changed?).`) +
|
|
629
|
-
chalk.gray(' Check: agents
|
|
615
|
+
chalk.gray(' Check: agents devices status'));
|
|
630
616
|
}
|
|
631
617
|
return code;
|
|
632
618
|
}
|
|
@@ -243,7 +243,7 @@ export async function followHostTask(target, opts) {
|
|
|
243
243
|
for (;;) {
|
|
244
244
|
const remaining = deadline - Date.now();
|
|
245
245
|
if (remaining <= 0) {
|
|
246
|
-
process.stderr.write('\n[hosts] follow timed out; the run continues on the host. Reattach with: agents
|
|
246
|
+
process.stderr.write('\n[hosts] follow timed out; the run continues on the host. Reattach with: agents logs ' + opts.taskId + ' -f\n');
|
|
247
247
|
return -1;
|
|
248
248
|
}
|
|
249
249
|
const abort = new AbortController();
|
|
@@ -271,7 +271,7 @@ export async function followHostTask(target, opts) {
|
|
|
271
271
|
// chunks were flushed as they arrived, so reconnect from the advanced offset.
|
|
272
272
|
// If no bytes arrived, back off like the old idle poll.
|
|
273
273
|
if (Date.now() > deadline) {
|
|
274
|
-
process.stderr.write('\n[hosts] follow timed out; the run continues on the host. Reattach with: agents
|
|
274
|
+
process.stderr.write('\n[hosts] follow timed out; the run continues on the host. Reattach with: agents logs ' + opts.taskId + ' -f\n');
|
|
275
275
|
return -1;
|
|
276
276
|
}
|
|
277
277
|
// Reconnect quickly while output flows; ease toward maxMs when the stream
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Bridges the devices registry (`agents devices`, ~/.agents/.history/devices/
|
|
5
5
|
* registry.json) into the host pool behind the same `HostProvider` seam as
|
|
6
6
|
* `local` — the "tailscale provider" fast-follow named in docs/hosts.md. With
|
|
7
|
-
* it, a machine registered once via `agents devices sync`
|
|
8
|
-
* `
|
|
9
|
-
* by target pickers — not just resolvable by exact name.
|
|
7
|
+
* it, a machine registered once via `agents devices sync` becomes a resolvable
|
|
8
|
+
* `--host`/`--device` dispatch target, participates in capability routing, and
|
|
9
|
+
* is enumerable by target pickers — not just resolvable by exact name.
|
|
10
10
|
*
|
|
11
11
|
* Password-auth devices are listed (the pool stays honest about what exists)
|
|
12
12
|
* but marked `dispatchable: false`; resolving one for dispatch throws the same
|