@phnx-labs/agents-cli 1.22.34 → 1.22.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +672 -2
- package/README.md +82 -35
- package/dist/bin/agents +0 -0
- package/dist/bootstrap.d.ts +15 -0
- package/dist/bootstrap.js +1211 -0
- package/dist/commands/accounts.d.ts +4 -11
- package/dist/commands/accounts.js +159 -27
- 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 +15 -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 +85 -41
- 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 +4 -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/set.d.ts +1 -1
- package/dist/commands/set.js +2 -2
- 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-share.js +34 -4
- package/dist/commands/setup.d.ts +5 -0
- package/dist/commands/setup.js +26 -0
- package/dist/commands/share.d.ts +85 -0
- package/dist/commands/share.js +379 -8
- 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/ipc.d.ts +30 -0
- package/dist/lib/browser/ipc.js +81 -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 +4 -0
- package/dist/lib/browser/service.js +30 -3
- 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 +19 -0
- 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/codex-policy.d.ts +9 -1
- package/dist/lib/codex-policy.js +17 -2
- 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 +220 -122
- 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 +20 -6
- package/dist/lib/git.js +121 -17
- 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-key.d.ts +17 -0
- package/dist/lib/project-key.js +26 -0
- 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 +41 -6
- 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/config.d.ts +4 -0
- package/dist/lib/share/config.js +1 -0
- package/dist/lib/share/delete.d.ts +93 -0
- package/dist/lib/share/delete.js +127 -0
- package/dist/lib/share/provision.d.ts +38 -0
- package/dist/lib/share/provision.js +50 -0
- package/dist/lib/share/publish.d.ts +40 -1
- package/dist/lib/share/publish.js +116 -3
- package/dist/lib/share/worker-template.js +71 -6
- package/dist/lib/shims.d.ts +17 -3
- package/dist/lib/shims.js +136 -27
- 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 +6 -12
- package/dist/lib/startup/command-registry.js +14 -31
- 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 +320 -0
- package/dist/lib/tmux/orphan-reap.js +644 -0
- package/dist/lib/tmux/session.d.ts +68 -3
- package/dist/lib/tmux/session.js +95 -5
- package/dist/lib/triggers/handlers.d.ts +20 -0
- package/dist/lib/triggers/handlers.js +6 -1
- package/dist/lib/types.d.ts +46 -34
- 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/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
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only task/run history over the `computer.action` event ledger
|
|
3
|
+
* (`~/.agents/.history/events/YYYY-MM-DD/events.jsonl`, see `../events.ts`) —
|
|
4
|
+
* the durable, already-existing audit log every `agents computer <verb>`
|
|
5
|
+
* invocation (the explicit CLI verbs in `commands/computer-actions.ts`, and
|
|
6
|
+
* the embedded `computer run` loop in `computer/dispatch.ts`) writes through
|
|
7
|
+
* `emitComputerAction()`. Backs both `agents computer sessions` and the
|
|
8
|
+
* `agents sessions --computer` alias.
|
|
9
|
+
*
|
|
10
|
+
* There is no separate capture directory the way browser tasks have
|
|
11
|
+
* `.cache/browser/<profile>/sessions/<task>/` — a computer action drives a
|
|
12
|
+
* live GUI in place and leaves no artifact of its own, so the event ledger
|
|
13
|
+
* IS the canonical execution source for this history (RUSH-2432, the
|
|
14
|
+
* computer counterpart of `../browser/sessions-list.ts`'s RUSH-2407
|
|
15
|
+
* task-first grouping).
|
|
16
|
+
*
|
|
17
|
+
* Retention/privacy: `events.ts` bounds and prunes the LEDGER
|
|
18
|
+
* (`DEFAULT_RETENTION_DAYS` / `DEFAULT_MAX_STORAGE_BYTES` — 7 days / 50 MiB
|
|
19
|
+
* by default, gzip-rotated at 10 MiB) and nothing here changes that policy or
|
|
20
|
+
* re-prunes that log. The durable `computer_sessions` table added in RUSH-2549
|
|
21
|
+
* is a SECOND store with its OWN, much longer bound
|
|
22
|
+
* (`TOOL_SESSION_MAX_AGE_DAYS`, swept by `pruneToolSessions` from the listing
|
|
23
|
+
* path below) — that is deliberate, since the table exists precisely to outlive
|
|
24
|
+
* the ledger's 7 days, and one row per CLI process would otherwise grow without
|
|
25
|
+
* limit. It is metadata only. Nothing sensitive is persisted: `type` /
|
|
26
|
+
* `type-text` events already carry only `textLength`, never the typed text
|
|
27
|
+
* (see `commands/computer-actions.ts` `emitComputerAction` call sites) — the
|
|
28
|
+
* mission this module fulfils changes NONE of that. A `run --task`
|
|
29
|
+
* description is the agent's OWN instruction, not typed-into-a-target-app
|
|
30
|
+
* content (the same class of thing `agents sessions` already stores
|
|
31
|
+
* unredacted as a session prompt) — it is kept, but bounded to
|
|
32
|
+
* {@link TASK_PREVIEW_MAX_CHARS} via `events.ts`'s `truncate()` before it is
|
|
33
|
+
* ever written (see `computer.ts` `registerRunCommand`), never the full
|
|
34
|
+
* unbounded text, and it is not the wire-shape `prompt` field so it is a
|
|
35
|
+
* deliberate exception to (not a bypass of) the automatic prompt-redaction
|
|
36
|
+
* path in `events.ts` `sanitizePayload`.
|
|
37
|
+
*
|
|
38
|
+
* Grouping key: `emitComputerAction()` stamps one random `invocationId` for
|
|
39
|
+
* the lifetime of the emitting CLI process. The event's own `pid` field is the emitting
|
|
40
|
+
* CLI PROCESS's pid, never the target app's (that's `targetPid` — see
|
|
41
|
+
* `computer-actions.ts` `emitComputerAction`, and its `#11` test guarding
|
|
42
|
+
* this). One `agents computer <verb>` invocation is one process, and
|
|
43
|
+
* `computer run`'s whole embedded observe/act/verify loop is ALSO one
|
|
44
|
+
* process. Grouping by `invocationId` gives exactly one row per CLI invocation without
|
|
45
|
+
* conflating unrelated processes when the OS later reuses a pid: a
|
|
46
|
+
* single explicit verb collapses to a one-action row, and a `run --task`
|
|
47
|
+
* loop collapses to one row holding every verb the model drove. That row is
|
|
48
|
+
* the "run" a task-first view groups by.
|
|
49
|
+
*
|
|
50
|
+
* Session identity: unlike a browser task (which only ever learns its
|
|
51
|
+
* `launchId`, requiring the join `buildLaunchSessionIndex`/
|
|
52
|
+
* `resolveLaunchSession` perform), a `computer.action` event is emitted
|
|
53
|
+
* IN-PROCESS by the CLI invocation itself, so `stampProvenance()`
|
|
54
|
+
* (`../event-provenance.ts`) already stamps its own `sessionId` directly
|
|
55
|
+
* onto the record — no join needed for the common case. This module still
|
|
56
|
+
* falls back to the shared launchId join — imported from
|
|
57
|
+
* `../browser/sessions-list.ts`, never duplicated — for the case where
|
|
58
|
+
* `sessionId` doesn't resolve (a rotated/unindexed session) but `launchId`
|
|
59
|
+
* still does via the more authoritative pid registry.
|
|
60
|
+
*/
|
|
61
|
+
import { query, truncate } from '../events.js';
|
|
62
|
+
import { formatRelativeTime } from '../session/relative-time.js';
|
|
63
|
+
import { getSessionById, listComputerSessionRecords, pruneToolSessions } from '../session/db.js';
|
|
64
|
+
import { buildLaunchSessionIndex, resolveLaunchSession, } from '../browser/sessions-list.js';
|
|
65
|
+
/** Max chars of a `run --task` description persisted to the ledger — see the
|
|
66
|
+
* module docblock's retention/privacy note. */
|
|
67
|
+
export const TASK_PREVIEW_MAX_CHARS = 200;
|
|
68
|
+
/** Cap on how many raw ledger rows a single read scans/returns. `query()`
|
|
69
|
+
* already reads newest-first and stops at this cutoff mid-scan, so raising
|
|
70
|
+
* it only ever costs as much as the history actually holds. */
|
|
71
|
+
const DEFAULT_ACTION_LIMIT = 5000;
|
|
72
|
+
function recordToAction(r) {
|
|
73
|
+
if (typeof r.command !== 'string' || typeof r.pid !== 'number')
|
|
74
|
+
return null;
|
|
75
|
+
const tsMs = Date.parse(r.ts);
|
|
76
|
+
if (Number.isNaN(tsMs))
|
|
77
|
+
return null;
|
|
78
|
+
return {
|
|
79
|
+
verb: r.command,
|
|
80
|
+
ts: r.ts,
|
|
81
|
+
tsMs,
|
|
82
|
+
pid: r.pid,
|
|
83
|
+
invocationId: typeof r.invocationId === 'string' ? r.invocationId : undefined,
|
|
84
|
+
targetPid: typeof r.targetPid === 'number' ? r.targetPid : undefined,
|
|
85
|
+
bundle: typeof r.bundle === 'string' ? r.bundle : undefined,
|
|
86
|
+
host: typeof r.host === 'string' ? r.host : undefined,
|
|
87
|
+
task: typeof r.task === 'string' ? r.task : undefined,
|
|
88
|
+
sessionId: typeof r.sessionId === 'string' ? r.sessionId : undefined,
|
|
89
|
+
launchId: typeof r.launchId === 'string' ? r.launchId : undefined,
|
|
90
|
+
agent: typeof r.agent === 'string' ? r.agent : undefined,
|
|
91
|
+
machineId: typeof r.machineId === 'string' ? r.machineId : undefined,
|
|
92
|
+
hostname: typeof r.hostname === 'string' ? r.hostname : undefined,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/** Read `computer.action` events straight from the durable event ledger,
|
|
96
|
+
* newest first, bounded by `limit`. Malformed/legacy records (missing
|
|
97
|
+
* `command` or `pid`, or an unparseable `ts`) are skipped, never thrown —
|
|
98
|
+
* the ledger is a plain rotated JSONL file another process can be mid-write
|
|
99
|
+
* or mid-rotate against. */
|
|
100
|
+
export function listComputerActions(opts = {}) {
|
|
101
|
+
const records = query({ eventTypes: ['computer.action'], limit: opts.limit ?? DEFAULT_ACTION_LIMIT });
|
|
102
|
+
const out = [];
|
|
103
|
+
for (const r of records) {
|
|
104
|
+
const a = recordToAction(r);
|
|
105
|
+
if (a)
|
|
106
|
+
out.push(a);
|
|
107
|
+
}
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Group flat ledger actions into task-first rows, newest first. Pure:
|
|
112
|
+
* session resolvers are passed in, so this has no filesystem/session-index
|
|
113
|
+
* dependency and is unit-testable with synthetic data (see
|
|
114
|
+
* {@link buildComputerSessionRows} for the impure disk/index-reading caller).
|
|
115
|
+
*/
|
|
116
|
+
export function groupIntoComputerRuns(actions, resolveSession, resolveLaunch) {
|
|
117
|
+
const byInvocation = new Map();
|
|
118
|
+
for (const [index, a] of actions.entries()) {
|
|
119
|
+
// Legacy rows have no trustworthy process identity. Pids are recyclable,
|
|
120
|
+
// so preserve each event separately instead of inventing a relationship.
|
|
121
|
+
const key = a.invocationId ?? `legacy:${a.pid}:${a.tsMs}:${index}`;
|
|
122
|
+
const list = byInvocation.get(key) ?? [];
|
|
123
|
+
list.push(a);
|
|
124
|
+
byInvocation.set(key, list);
|
|
125
|
+
}
|
|
126
|
+
const rows = [];
|
|
127
|
+
for (const group of byInvocation.values()) {
|
|
128
|
+
const pid = group[0].pid;
|
|
129
|
+
group.sort((a, b) => b.tsMs - a.tsMs); // newest first
|
|
130
|
+
const marker = group.find((a) => a.verb === 'run');
|
|
131
|
+
const driving = group.filter((a) => a.verb !== 'run');
|
|
132
|
+
const counts = {};
|
|
133
|
+
for (const a of driving)
|
|
134
|
+
counts[a.verb] = (counts[a.verb] ?? 0) + 1;
|
|
135
|
+
const bundle = group.find((a) => a.bundle)?.bundle;
|
|
136
|
+
const remoteHost = group.find((a) => a.host)?.host;
|
|
137
|
+
const identity = group.find((a) => a.sessionId || a.launchId) ?? group[0];
|
|
138
|
+
const machine = group.find((a) => a.hostname)?.hostname ?? 'unknown';
|
|
139
|
+
const machineId = group.find((a) => a.machineId)?.machineId;
|
|
140
|
+
let linkedSession = null;
|
|
141
|
+
if (identity.sessionId)
|
|
142
|
+
linkedSession = resolveSession?.(identity.sessionId) ?? null;
|
|
143
|
+
if (!linkedSession && identity.launchId)
|
|
144
|
+
linkedSession = resolveLaunch?.(identity.launchId) ?? null;
|
|
145
|
+
const times = group.map((a) => a.tsMs);
|
|
146
|
+
rows.push({
|
|
147
|
+
pid,
|
|
148
|
+
invocationId: group[0].invocationId,
|
|
149
|
+
task: marker?.task,
|
|
150
|
+
machine,
|
|
151
|
+
machineId,
|
|
152
|
+
remoteHost,
|
|
153
|
+
bundle,
|
|
154
|
+
agent: identity.agent,
|
|
155
|
+
sessionId: identity.sessionId,
|
|
156
|
+
launchId: identity.launchId,
|
|
157
|
+
linkStatus: linkedSession ? 'linked' : (identity.sessionId || identity.launchId) ? 'unresolved' : 'unlinked',
|
|
158
|
+
linkedSession: linkedSession ?? undefined,
|
|
159
|
+
actions: driving,
|
|
160
|
+
counts,
|
|
161
|
+
startMs: Math.min(...times),
|
|
162
|
+
endMs: Math.max(...times),
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
rows.sort((a, b) => b.endMs - a.endMs);
|
|
166
|
+
return rows;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Add runs the event ledger no longer holds, from the durable
|
|
170
|
+
* `computer_sessions` table (RUSH-2549).
|
|
171
|
+
*
|
|
172
|
+
* The ledger is deliberately bounded — it prunes at 7 days / 50 MiB — so before
|
|
173
|
+
* this, a run simply disappeared from `agents sessions --computer` on day 8 even
|
|
174
|
+
* though it had happened and its identity was known. The DB row is metadata
|
|
175
|
+
* only, so a recovered row carries its identity, timing and action COUNT but no
|
|
176
|
+
* per-verb breakdown: those individual actions lived in the pruned ledger and
|
|
177
|
+
* are genuinely gone. It is listed as a real run with an empty `actions` list
|
|
178
|
+
* rather than silently omitted, and never fabricated back.
|
|
179
|
+
*
|
|
180
|
+
* Ledger rows win on collision: while both exist the ledger is richer.
|
|
181
|
+
*/
|
|
182
|
+
function appendPrunedRunsFromDb(rows, limit) {
|
|
183
|
+
const seen = new Set(rows.map((r) => r.invocationId));
|
|
184
|
+
// Ask the DB for what the ledger CANNOT still hold — everything older than
|
|
185
|
+
// the oldest action the ledger returned. Reading the newest N instead is
|
|
186
|
+
// self-defeating: those are precisely the rows `seen` discards, so once the
|
|
187
|
+
// table exceeds the read limit the recovery returns nothing and history
|
|
188
|
+
// disappears past the ledger window again — the exact bug this recovery
|
|
189
|
+
// exists to prevent. With no ledger rows at all there is nothing to exclude,
|
|
190
|
+
// so every stored row is recoverable.
|
|
191
|
+
const startedBeforeMs = rows.length > 0
|
|
192
|
+
? Math.min(...rows.map((r) => r.startMs))
|
|
193
|
+
: undefined;
|
|
194
|
+
for (const record of listComputerSessionRecords({ limit, startedBeforeMs })) {
|
|
195
|
+
// The dedup is LOAD-BEARING — do not delete it as redundant with the WHERE
|
|
196
|
+
// clause above. A run's DB `started_at` is its TRUE start and is never
|
|
197
|
+
// updated, while the ledger row's `startMs` is only its oldest RETAINED
|
|
198
|
+
// action. So a long `computer run` that began before the ledger window but
|
|
199
|
+
// kept acting inside it sits below the cutoff, is selected by the SQL, and
|
|
200
|
+
// is already present as a ledger row. This is what drops the duplicate.
|
|
201
|
+
if (seen.has(record.invocationId))
|
|
202
|
+
continue;
|
|
203
|
+
const linked = record.sessionId ? getSessionById(record.sessionId) : null;
|
|
204
|
+
rows.push({
|
|
205
|
+
// No pid: the process is long gone and the ledger entry that knew it has
|
|
206
|
+
// been pruned. Fabricating `0` rendered rows labelled "pid 0" (see the
|
|
207
|
+
// label fallbacks in this file and computer-sessions-picker.ts).
|
|
208
|
+
pid: undefined,
|
|
209
|
+
invocationId: record.invocationId,
|
|
210
|
+
task: record.taskPreview,
|
|
211
|
+
// machineId() form ("zion"), the same normalized id the DB stored; the
|
|
212
|
+
// ledger path records the raw os.hostname() ("Zion.local") in `machine`.
|
|
213
|
+
// Setting BOTH from the one value we have keeps `--machine` substring
|
|
214
|
+
// filtering working on either spelling instead of silently missing
|
|
215
|
+
// recovered rows (events.ts documents the hostname/machineId split).
|
|
216
|
+
machine: record.machine,
|
|
217
|
+
machineId: record.machine,
|
|
218
|
+
bundle: undefined,
|
|
219
|
+
remoteHost: undefined,
|
|
220
|
+
agent: undefined,
|
|
221
|
+
sessionId: record.sessionId,
|
|
222
|
+
launchId: record.launchId,
|
|
223
|
+
linkStatus: linked ? 'linked' : (record.sessionId || record.launchId) ? 'unresolved' : 'unlinked',
|
|
224
|
+
linkedSession: linked ?? undefined,
|
|
225
|
+
// The per-verb breakdown lived in the pruned ledger and is genuinely gone
|
|
226
|
+
// — it is never reconstructed. The TOTAL survives in the row, so report
|
|
227
|
+
// it as an explicit total rather than dropping it: a 40-action run must
|
|
228
|
+
// not render identically to one that did nothing.
|
|
229
|
+
actions: [],
|
|
230
|
+
counts: {},
|
|
231
|
+
recoveredActionCount: record.actionCount,
|
|
232
|
+
startMs: record.startedAt,
|
|
233
|
+
endMs: record.lastActivity ?? record.startedAt,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/** Build task-first rows from the real ledger, resolving each row's owning
|
|
238
|
+
* session against the live indexes. The interactive picker's (and the
|
|
239
|
+
* flat/`--json` printer's) data source. `machine` narrows to rows whose
|
|
240
|
+
* invoking hostname, machineId, or `--host` target contains the substring. */
|
|
241
|
+
export function buildComputerSessionRows(opts = {}) {
|
|
242
|
+
const actions = listComputerActions({ limit: opts.limit });
|
|
243
|
+
const index = buildLaunchSessionIndex();
|
|
244
|
+
const rows = groupIntoComputerRuns(actions, (sessionId) => getSessionById(sessionId), (launchId) => resolveLaunchSession(index, launchId));
|
|
245
|
+
// Retention runs here, on the listing path, never on the action hot path:
|
|
246
|
+
// one row per `agents computer` CLI process means the table would otherwise
|
|
247
|
+
// grow without bound. Best-effort — a read-only DB must not break a listing.
|
|
248
|
+
try {
|
|
249
|
+
pruneToolSessions();
|
|
250
|
+
}
|
|
251
|
+
catch { /* listing must not fail on retention */ }
|
|
252
|
+
appendPrunedRunsFromDb(rows, opts.limit);
|
|
253
|
+
rows.sort((a, b) => b.endMs - a.endMs);
|
|
254
|
+
if (!opts.machine)
|
|
255
|
+
return rows;
|
|
256
|
+
const q = opts.machine.toLowerCase();
|
|
257
|
+
return rows.filter((r) => r.machine.toLowerCase().includes(q) ||
|
|
258
|
+
r.remoteHost?.toLowerCase().includes(q) ||
|
|
259
|
+
r.machineId?.toLowerCase().includes(q));
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Search predicate for the interactive picker: task text, machine/remote
|
|
263
|
+
* host, target bundle, the linked session's agent/topic/label, or any
|
|
264
|
+
* driven verb in the row.
|
|
265
|
+
*/
|
|
266
|
+
export function matchesComputerSessionRow(row, queryText) {
|
|
267
|
+
const q = queryText.trim().toLowerCase();
|
|
268
|
+
if (!q)
|
|
269
|
+
return true;
|
|
270
|
+
if (row.task?.toLowerCase().includes(q))
|
|
271
|
+
return true;
|
|
272
|
+
if (row.machine.toLowerCase().includes(q))
|
|
273
|
+
return true;
|
|
274
|
+
if (row.remoteHost?.toLowerCase().includes(q))
|
|
275
|
+
return true;
|
|
276
|
+
if (row.bundle?.toLowerCase().includes(q))
|
|
277
|
+
return true;
|
|
278
|
+
const s = row.linkedSession;
|
|
279
|
+
if (s && (s.agent.toLowerCase().includes(q) || s.topic?.toLowerCase().includes(q) || s.label?.toLowerCase().includes(q))) {
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
return row.actions.some((a) => a.verb.toLowerCase().includes(q));
|
|
283
|
+
}
|
|
284
|
+
/** Human one-line summary of a row's per-verb action counts, most frequent
|
|
285
|
+
* first — shared by the flat table and the interactive picker's label. */
|
|
286
|
+
/**
|
|
287
|
+
* One row's action summary — the single renderer every surface should use.
|
|
288
|
+
*
|
|
289
|
+
* A run recovered from the DB after the ledger pruned has no per-verb detail,
|
|
290
|
+
* only a total. Rendering it through the per-verb formatter printed
|
|
291
|
+
* "(no actions)", which is indistinguishable from a run that did nothing — so a
|
|
292
|
+
* 40-action run read as empty. Report the surviving total, and say plainly that
|
|
293
|
+
* the breakdown is gone rather than implying we still have it.
|
|
294
|
+
*/
|
|
295
|
+
export function formatRowActions(row) {
|
|
296
|
+
if (row.recoveredActionCount !== undefined) {
|
|
297
|
+
const n = row.recoveredActionCount;
|
|
298
|
+
return `${n} action${n === 1 ? '' : 's'} (per-verb detail pruned from the event log)`;
|
|
299
|
+
}
|
|
300
|
+
return formatActionCounts(row.counts);
|
|
301
|
+
}
|
|
302
|
+
export function formatActionCounts(counts) {
|
|
303
|
+
const parts = Object.entries(counts)
|
|
304
|
+
.sort((a, b) => b[1] - a[1])
|
|
305
|
+
.map(([verb, n]) => `${verb} ${n}`);
|
|
306
|
+
return parts.join(', ') || '(no actions)';
|
|
307
|
+
}
|
|
308
|
+
/** Human table for the CLI. Returns lines (no trailing newline). */
|
|
309
|
+
export function renderComputerSessionRows(rows) {
|
|
310
|
+
if (rows.length === 0)
|
|
311
|
+
return 'No computer actions recorded.';
|
|
312
|
+
const lines = [];
|
|
313
|
+
for (const r of rows) {
|
|
314
|
+
const when = formatRelativeTime(new Date(r.endMs).toISOString());
|
|
315
|
+
const where = r.remoteHost ? `${r.machine} -> ${r.remoteHost}` : r.machine;
|
|
316
|
+
const label = r.task ? truncate(r.task, 60) : (r.bundle ?? `pid ${r.pid}`);
|
|
317
|
+
const link = r.linkStatus === 'linked' && r.linkedSession
|
|
318
|
+
? `${r.linkedSession.agent} — ${r.linkedSession.label || r.linkedSession.topic || r.linkedSession.shortId}`
|
|
319
|
+
: r.linkStatus === 'unresolved'
|
|
320
|
+
? 'unresolved (session not indexed here)'
|
|
321
|
+
: 'unlinked';
|
|
322
|
+
lines.push(`${when.padEnd(12)} ${where.padEnd(24)} ${String(label ?? '').padEnd(40)} ${link}`);
|
|
323
|
+
lines.push(` ${formatRowActions(r)}`);
|
|
324
|
+
}
|
|
325
|
+
return lines.join('\n');
|
|
326
|
+
}
|
|
327
|
+
/** Default row cap for the flat/non-interactive table. A computer row is
|
|
328
|
+
* much finer-grained than a browser task — real usage is mostly one
|
|
329
|
+
* standalone verb per CLI invocation, not a `run --task` loop, so an
|
|
330
|
+
* unbounded flat dump against real history reads as hundreds of one-action
|
|
331
|
+
* rows (confirmed against a real machine's history while building this).
|
|
332
|
+
* The interactive picker has no such cap (it's searchable); only the
|
|
333
|
+
* static table needs one. `--limit` overrides. */
|
|
334
|
+
export const DEFAULT_ROW_DISPLAY_LIMIT = 50;
|
|
335
|
+
/** Slice `rows` to at most `limit` (newest first, rows are already sorted),
|
|
336
|
+
* and report how many were dropped — pure, so the cap arithmetic and the
|
|
337
|
+
* trailer condition are unit-testable without a console spy. */
|
|
338
|
+
export function applyRowDisplayLimit(rows, limit = DEFAULT_ROW_DISPLAY_LIMIT) {
|
|
339
|
+
const shown = rows.slice(0, limit);
|
|
340
|
+
return { shown, more: rows.length - shown.length };
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Shared CLI action for `agents computer sessions` and `agents sessions
|
|
344
|
+
* --computer`. Non-interactive by design (the interactive routing decision
|
|
345
|
+
* lives in `commands/computer-sessions-picker.ts`, mirroring
|
|
346
|
+
* `runBrowserSessions`/`runBrowserSessionsCommand`'s split).
|
|
347
|
+
*/
|
|
348
|
+
export function runComputerSessions(opts) {
|
|
349
|
+
const rows = buildComputerSessionRows({ machine: opts.machine });
|
|
350
|
+
printComputerSessionRows(rows, opts);
|
|
351
|
+
}
|
|
352
|
+
/** Print already-collected rows. Fleet callers use this after merging local and
|
|
353
|
+
* remote JSON so text, limits, and JSON keep exactly one renderer. */
|
|
354
|
+
export function printComputerSessionRows(rows, opts) {
|
|
355
|
+
if (opts.json) {
|
|
356
|
+
console.log(JSON.stringify(rows, null, 2));
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
const { shown, more } = applyRowDisplayLimit(rows, opts.limit ?? DEFAULT_ROW_DISPLAY_LIMIT);
|
|
360
|
+
console.log(renderComputerSessionRows(shown));
|
|
361
|
+
if (more > 0)
|
|
362
|
+
console.log(`\n… (${more} more; --limit ${rows.length} or --json to see all, --machine to narrow)`);
|
|
363
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified config key grammar for `agents config`.
|
|
3
|
+
*
|
|
4
|
+
* Translates user-facing dotted keys like `run.claude@*.tier.best` into the
|
|
5
|
+
* existing storage locations (run.defaults, model.tiers, config.*,
|
|
6
|
+
* defaultBrowserProfile, deviceConfig.*) so the new command barrel can sit on
|
|
7
|
+
* top of the current YAML schema without a migration.
|
|
8
|
+
*/
|
|
9
|
+
import type { AgentId } from './types.js';
|
|
10
|
+
import { type ModelTier } from './model-tiers.js';
|
|
11
|
+
/** The top-level scope of a unified config key. */
|
|
12
|
+
export type ConfigScope = 'run' | 'interactive' | 'usage' | 'browser' | 'project' | 'device';
|
|
13
|
+
/** A run-time default key: model, mode, effort, or tier override. */
|
|
14
|
+
export interface ParsedRunConfigKey {
|
|
15
|
+
scope: 'run';
|
|
16
|
+
agent: AgentId;
|
|
17
|
+
version: string;
|
|
18
|
+
property: 'model' | 'mode' | 'effort' | 'tier';
|
|
19
|
+
tier?: ModelTier;
|
|
20
|
+
}
|
|
21
|
+
/** The interactive host pin. */
|
|
22
|
+
export interface ParsedInteractiveConfigKey {
|
|
23
|
+
scope: 'interactive';
|
|
24
|
+
property: 'host';
|
|
25
|
+
}
|
|
26
|
+
/** The host whose usage snapshots are authoritative for fleet-wide reporting. */
|
|
27
|
+
export interface ParsedUsageConfigKey {
|
|
28
|
+
scope: 'usage';
|
|
29
|
+
property: 'primary-host';
|
|
30
|
+
}
|
|
31
|
+
/** The default browser profile (device-scope, self or peer). */
|
|
32
|
+
export interface ParsedBrowserConfigKey {
|
|
33
|
+
scope: 'browser';
|
|
34
|
+
property: 'profile';
|
|
35
|
+
device?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface ParsedProjectConfigKey {
|
|
38
|
+
scope: 'project';
|
|
39
|
+
property: 'root';
|
|
40
|
+
}
|
|
41
|
+
/** A per-device configuration key. */
|
|
42
|
+
export interface ParsedDeviceConfigKey {
|
|
43
|
+
scope: 'device';
|
|
44
|
+
device: string;
|
|
45
|
+
property: DeviceConfigProperty;
|
|
46
|
+
}
|
|
47
|
+
export type ParsedConfigKey = ParsedRunConfigKey | ParsedInteractiveConfigKey | ParsedUsageConfigKey | ParsedBrowserConfigKey | ParsedProjectConfigKey | ParsedDeviceConfigKey;
|
|
48
|
+
export type DeviceConfigProperty = 'max-agents' | 'scheduler' | 'daemon' | 'watchdog' | 'browser.remote-control' | 'notes' | 'browser.profile';
|
|
49
|
+
/** Normalize agent@version to use `@` consistently. */
|
|
50
|
+
export declare function formatAgentVersion(agent: AgentId, version: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* Parse a unified config key into its structured representation.
|
|
53
|
+
*
|
|
54
|
+
* Supported forms:
|
|
55
|
+
* run.<agent@version>.model
|
|
56
|
+
* run.<agent@version>.mode
|
|
57
|
+
* run.<agent@version>.effort
|
|
58
|
+
* run.<agent@version>.tier.<cheap|default|best|ultra>
|
|
59
|
+
* interactive.host
|
|
60
|
+
* usage.primary-host
|
|
61
|
+
* browser.profile
|
|
62
|
+
* project.root
|
|
63
|
+
* devices.<name>.max-agents
|
|
64
|
+
* devices.<name>.scheduler
|
|
65
|
+
* devices.<name>.daemon
|
|
66
|
+
* devices.<name>.watchdog
|
|
67
|
+
* devices.<name>.browser.remote-control
|
|
68
|
+
* devices.<name>.notes
|
|
69
|
+
* devices.<name>.browser.profile
|
|
70
|
+
*/
|
|
71
|
+
export declare function parseConfigKey(key: string): ParsedConfigKey;
|
|
72
|
+
/** Render a parsed key back to its canonical dotted string. */
|
|
73
|
+
export declare function formatConfigKey(parsed: ParsedConfigKey): string;
|
|
74
|
+
/** List every canonical key the command documents, with wildcards expanded to a concrete example. */
|
|
75
|
+
export declare function listKnownConfigKeys(): string[];
|
|
76
|
+
/**
|
|
77
|
+
* Map a parsed device property to the internal device-config key name.
|
|
78
|
+
* This is the bridge between the friendly `agents config` surface and the
|
|
79
|
+
* existing CONFIG_KEYS registry in lib/device-config.ts.
|
|
80
|
+
*/
|
|
81
|
+
export declare function devicePropertyToConfigName(property: DeviceConfigProperty): string;
|
|
82
|
+
/**
|
|
83
|
+
* Map a parsed key to the human-readable "where is this stored" note.
|
|
84
|
+
* Useful for `agents config list --source` output.
|
|
85
|
+
*/
|
|
86
|
+
export declare function configKeyStorageHint(parsed: ParsedConfigKey): string;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified config key grammar for `agents config`.
|
|
3
|
+
*
|
|
4
|
+
* Translates user-facing dotted keys like `run.claude@*.tier.best` into the
|
|
5
|
+
* existing storage locations (run.defaults, model.tiers, config.*,
|
|
6
|
+
* defaultBrowserProfile, deviceConfig.*) so the new command barrel can sit on
|
|
7
|
+
* top of the current YAML schema without a migration.
|
|
8
|
+
*/
|
|
9
|
+
import { AGENTS } from './agents.js';
|
|
10
|
+
import { MODEL_TIERS } from './model-tiers.js';
|
|
11
|
+
import { VERSION_RE } from './run-defaults.js';
|
|
12
|
+
const DEVICE_CONFIG_PROPERTIES = [
|
|
13
|
+
'max-agents',
|
|
14
|
+
'scheduler',
|
|
15
|
+
'daemon',
|
|
16
|
+
'watchdog',
|
|
17
|
+
'browser.remote-control',
|
|
18
|
+
'notes',
|
|
19
|
+
'browser.profile',
|
|
20
|
+
];
|
|
21
|
+
/** Split an agent@version token into its parts. Accepts both `@` and `:`. */
|
|
22
|
+
function parseAgentVersion(token) {
|
|
23
|
+
const sep = token.includes('@') ? '@' : ':';
|
|
24
|
+
const [agentPart, versionPart = '*'] = token.split(sep);
|
|
25
|
+
const agent = agentPart.toLowerCase();
|
|
26
|
+
if (!(agent in AGENTS)) {
|
|
27
|
+
throw new Error(`Unknown agent '${agentPart}'. Known agents: ${Object.keys(AGENTS).join(', ')}.`);
|
|
28
|
+
}
|
|
29
|
+
if (!VERSION_RE.test(versionPart)) {
|
|
30
|
+
throw new Error(`Invalid version '${versionPart}' in '${token}'. Use *, latest, or [A-Za-z0-9._+-]{1,64}.`);
|
|
31
|
+
}
|
|
32
|
+
return { agent: agent, version: versionPart };
|
|
33
|
+
}
|
|
34
|
+
/** Normalize agent@version to use `@` consistently. */
|
|
35
|
+
export function formatAgentVersion(agent, version) {
|
|
36
|
+
return `${agent}@${version}`;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Parse a unified config key into its structured representation.
|
|
40
|
+
*
|
|
41
|
+
* Supported forms:
|
|
42
|
+
* run.<agent@version>.model
|
|
43
|
+
* run.<agent@version>.mode
|
|
44
|
+
* run.<agent@version>.effort
|
|
45
|
+
* run.<agent@version>.tier.<cheap|default|best|ultra>
|
|
46
|
+
* interactive.host
|
|
47
|
+
* usage.primary-host
|
|
48
|
+
* browser.profile
|
|
49
|
+
* project.root
|
|
50
|
+
* devices.<name>.max-agents
|
|
51
|
+
* devices.<name>.scheduler
|
|
52
|
+
* devices.<name>.daemon
|
|
53
|
+
* devices.<name>.watchdog
|
|
54
|
+
* devices.<name>.browser.remote-control
|
|
55
|
+
* devices.<name>.notes
|
|
56
|
+
* devices.<name>.browser.profile
|
|
57
|
+
*/
|
|
58
|
+
export function parseConfigKey(key) {
|
|
59
|
+
const raw = key.trim();
|
|
60
|
+
if (!raw)
|
|
61
|
+
throw new Error('Config key is required.');
|
|
62
|
+
const runMatch = raw.match(/^run\.(.+)\.(model|mode|effort)$/);
|
|
63
|
+
if (runMatch) {
|
|
64
|
+
const { agent, version } = parseAgentVersion(runMatch[1]);
|
|
65
|
+
return { scope: 'run', agent, version, property: runMatch[2] };
|
|
66
|
+
}
|
|
67
|
+
const tierMatch = raw.match(/^run\.(.+)\.tier\.(cheap|default|best|ultra)$/i);
|
|
68
|
+
if (tierMatch) {
|
|
69
|
+
const { agent, version } = parseAgentVersion(tierMatch[1]);
|
|
70
|
+
return { scope: 'run', agent, version, property: 'tier', tier: tierMatch[2].toLowerCase() };
|
|
71
|
+
}
|
|
72
|
+
if (raw === 'interactive.host') {
|
|
73
|
+
return { scope: 'interactive', property: 'host' };
|
|
74
|
+
}
|
|
75
|
+
if (raw === 'usage.primary-host') {
|
|
76
|
+
return { scope: 'usage', property: 'primary-host' };
|
|
77
|
+
}
|
|
78
|
+
if (raw === 'browser.profile') {
|
|
79
|
+
return { scope: 'browser', property: 'profile' };
|
|
80
|
+
}
|
|
81
|
+
if (raw === 'project.root') {
|
|
82
|
+
return { scope: 'project', property: 'root' };
|
|
83
|
+
}
|
|
84
|
+
const deviceMatch = raw.match(/^devices\.(.+)\.(max-agents|scheduler|daemon|watchdog|notes|browser\.remote-control|browser\.profile)$/);
|
|
85
|
+
if (deviceMatch) {
|
|
86
|
+
return {
|
|
87
|
+
scope: 'device',
|
|
88
|
+
device: deviceMatch[1],
|
|
89
|
+
property: deviceMatch[2],
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Provide helpful errors for common mistakes.
|
|
93
|
+
if (raw.startsWith('run.')) {
|
|
94
|
+
throw new Error(`Invalid run config key '${key}'. Expected run.<agent@version>.<model|mode|effort> or run.<agent@version>.tier.<cheap|default|best|ultra>.`);
|
|
95
|
+
}
|
|
96
|
+
if (raw.startsWith('interactive.')) {
|
|
97
|
+
throw new Error(`Invalid interactive config key '${key}'. Use interactive.host.`);
|
|
98
|
+
}
|
|
99
|
+
if (raw.startsWith('usage.')) {
|
|
100
|
+
throw new Error(`Invalid usage config key '${key}'. Use usage.primary-host.`);
|
|
101
|
+
}
|
|
102
|
+
if (raw.startsWith('browser.')) {
|
|
103
|
+
throw new Error(`Invalid browser config key '${key}'. Use browser.profile.`);
|
|
104
|
+
}
|
|
105
|
+
if (raw.startsWith('project.')) {
|
|
106
|
+
throw new Error(`Invalid project config key '${key}'. Use project.root.`);
|
|
107
|
+
}
|
|
108
|
+
if (raw.startsWith('devices.')) {
|
|
109
|
+
throw new Error(`Invalid device config key '${key}'. Expected devices.<name>.<${DEVICE_CONFIG_PROPERTIES.join('|')}>.`);
|
|
110
|
+
}
|
|
111
|
+
throw new Error(`Unknown config scope in '${key}'. Use one of: run, interactive, usage, browser, project, devices.`);
|
|
112
|
+
}
|
|
113
|
+
/** Render a parsed key back to its canonical dotted string. */
|
|
114
|
+
export function formatConfigKey(parsed) {
|
|
115
|
+
switch (parsed.scope) {
|
|
116
|
+
case 'run':
|
|
117
|
+
if (parsed.property === 'tier') {
|
|
118
|
+
return `run.${formatAgentVersion(parsed.agent, parsed.version)}.tier.${parsed.tier}`;
|
|
119
|
+
}
|
|
120
|
+
return `run.${formatAgentVersion(parsed.agent, parsed.version)}.${parsed.property}`;
|
|
121
|
+
case 'interactive':
|
|
122
|
+
return 'interactive.host';
|
|
123
|
+
case 'usage':
|
|
124
|
+
return 'usage.primary-host';
|
|
125
|
+
case 'browser':
|
|
126
|
+
return parsed.device ? `devices.${parsed.device}.browser.profile` : 'browser.profile';
|
|
127
|
+
case 'project':
|
|
128
|
+
return 'project.root';
|
|
129
|
+
case 'device':
|
|
130
|
+
return `devices.${parsed.device}.${parsed.property}`;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** List every canonical key the command documents, with wildcards expanded to a concrete example. */
|
|
134
|
+
export function listKnownConfigKeys() {
|
|
135
|
+
const keys = [];
|
|
136
|
+
keys.push('run.<agent@version>.model', 'run.<agent@version>.mode', 'run.<agent@version>.effort');
|
|
137
|
+
for (const tier of MODEL_TIERS) {
|
|
138
|
+
keys.push(`run.<agent@version>.tier.${tier}`);
|
|
139
|
+
}
|
|
140
|
+
keys.push('interactive.host', 'usage.primary-host', 'browser.profile', 'project.root');
|
|
141
|
+
for (const prop of DEVICE_CONFIG_PROPERTIES) {
|
|
142
|
+
keys.push(`devices.<name>.${prop}`);
|
|
143
|
+
}
|
|
144
|
+
return keys;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Map a parsed device property to the internal device-config key name.
|
|
148
|
+
* This is the bridge between the friendly `agents config` surface and the
|
|
149
|
+
* existing CONFIG_KEYS registry in lib/device-config.ts.
|
|
150
|
+
*/
|
|
151
|
+
export function devicePropertyToConfigName(property) {
|
|
152
|
+
switch (property) {
|
|
153
|
+
case 'max-agents':
|
|
154
|
+
return 'agents.max-concurrent';
|
|
155
|
+
case 'scheduler':
|
|
156
|
+
return 'scheduler.enabled';
|
|
157
|
+
case 'daemon':
|
|
158
|
+
return 'daemon.enabled';
|
|
159
|
+
case 'watchdog':
|
|
160
|
+
return 'watchdog.enabled';
|
|
161
|
+
case 'browser.remote-control':
|
|
162
|
+
return 'browser.remote-control';
|
|
163
|
+
case 'notes':
|
|
164
|
+
return 'notes';
|
|
165
|
+
case 'browser.profile':
|
|
166
|
+
return 'browser.profile';
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Map a parsed key to the human-readable "where is this stored" note.
|
|
171
|
+
* Useful for `agents config list --source` output.
|
|
172
|
+
*/
|
|
173
|
+
export function configKeyStorageHint(parsed) {
|
|
174
|
+
switch (parsed.scope) {
|
|
175
|
+
case 'run':
|
|
176
|
+
if (parsed.property === 'tier') {
|
|
177
|
+
return `model.tiers.${parsed.agent}:${parsed.version}.${parsed.tier}`;
|
|
178
|
+
}
|
|
179
|
+
return `run.defaults.${parsed.agent}:${parsed.version}.${parsed.property}`;
|
|
180
|
+
case 'interactive':
|
|
181
|
+
return 'config.interactiveHost';
|
|
182
|
+
case 'usage':
|
|
183
|
+
return 'config.usagePrimaryHost';
|
|
184
|
+
case 'browser':
|
|
185
|
+
return parsed.device
|
|
186
|
+
? `fleet.devices.${parsed.device}.config.defaultBrowserProfile`
|
|
187
|
+
: 'fleet.devices.<self>.config.defaultBrowserProfile';
|
|
188
|
+
case 'project':
|
|
189
|
+
return 'devices.<self>.projectRoot';
|
|
190
|
+
case 'device':
|
|
191
|
+
return `fleet.devices.${parsed.device}.config ${devicePropertyToConfigName(parsed.property)}`;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The YAML keys of every machine-visibility config key — the ones that live in
|
|
3
|
+
* the owning box's own `devices/<machine>/agents.yaml` and must never reach the
|
|
4
|
+
* fleet-shared `agents.yaml`.
|
|
5
|
+
*
|
|
6
|
+
* This is a ZERO-DEPENDENCY leaf on purpose. The authority is `CONFIG_KEYS` in
|
|
7
|
+
* `lib/device-config.ts`, but that module imports `devices/config-migration.ts`,
|
|
8
|
+
* so the migration cannot import it back without a cycle. Same shape as the
|
|
9
|
+
* `agent-cli-commands` leaf: duplicated here, pinned equal to the registry by a
|
|
10
|
+
* test (`device-config.test.ts`), so the two cannot drift silently.
|
|
11
|
+
*/
|
|
12
|
+
export declare const MACHINE_LOCAL_YAML_KEYS: ReadonlySet<string>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The YAML keys of every machine-visibility config key — the ones that live in
|
|
3
|
+
* the owning box's own `devices/<machine>/agents.yaml` and must never reach the
|
|
4
|
+
* fleet-shared `agents.yaml`.
|
|
5
|
+
*
|
|
6
|
+
* This is a ZERO-DEPENDENCY leaf on purpose. The authority is `CONFIG_KEYS` in
|
|
7
|
+
* `lib/device-config.ts`, but that module imports `devices/config-migration.ts`,
|
|
8
|
+
* so the migration cannot import it back without a cycle. Same shape as the
|
|
9
|
+
* `agent-cli-commands` leaf: duplicated here, pinned equal to the registry by a
|
|
10
|
+
* test (`device-config.test.ts`), so the two cannot drift silently.
|
|
11
|
+
*/
|
|
12
|
+
export const MACHINE_LOCAL_YAML_KEYS = new Set([
|
|
13
|
+
'defaultBrowserProfile', // browser.profile
|
|
14
|
+
'browserRemoteControl', // browser.remote-control — a consent flag; syncing it is a leak
|
|
15
|
+
'schedulerEnabled', // scheduler.enabled
|
|
16
|
+
'daemonEnabled', // daemon.enabled
|
|
17
|
+
]);
|