@phnx-labs/agents-cli 1.22.38 → 1.22.40
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 +302 -0
- package/README.md +111 -70
- package/dist/bin/agents +0 -0
- package/dist/bootstrap.js +46 -27
- package/dist/browser.js +2 -2
- package/dist/cli/command-registry.d.ts +135 -0
- package/dist/cli/command-registry.js +260 -0
- package/dist/commands/accounts.d.ts +20 -0
- package/dist/commands/accounts.js +186 -25
- package/dist/commands/apply.d.ts +3 -3
- package/dist/commands/apply.js +20 -63
- package/dist/commands/browser.js +206 -94
- package/dist/commands/budget.d.ts +7 -6
- package/dist/commands/budget.js +8 -7
- package/dist/commands/cloud.js +17 -20
- package/dist/commands/commands.js +1 -1
- package/dist/commands/computer-actions.d.ts +1 -35
- package/dist/commands/computer-actions.js +13 -181
- package/dist/commands/computer.d.ts +28 -3
- package/dist/commands/computer.js +93 -65
- package/dist/commands/config.js +47 -4
- package/dist/commands/cost.d.ts +2 -1
- package/dist/commands/cost.js +7 -6
- package/dist/commands/daemon.js +151 -4
- package/dist/commands/detach.js +1 -1
- package/dist/commands/doctor.js +19 -11
- package/dist/commands/events.js +1 -1
- package/dist/commands/exec.d.ts +2 -50
- package/dist/commands/exec.js +161 -216
- package/dist/commands/factory.js +1 -1
- package/dist/commands/feed.d.ts +2 -2
- package/dist/commands/feed.js +9 -12
- package/dist/commands/fleet-capture.js +25 -27
- package/dist/commands/focus.d.ts +2 -3
- package/dist/commands/focus.js +34 -9
- package/dist/commands/go.js +15 -5
- package/dist/commands/harness.d.ts +3 -3
- package/dist/commands/harness.js +53 -5
- package/dist/commands/hooks.js +1 -1
- package/dist/commands/import.js +2 -2
- package/dist/commands/insights.d.ts +5 -5
- package/dist/commands/insights.js +15 -9
- package/dist/commands/inspect.d.ts +2 -3
- package/dist/commands/inspect.js +4 -16
- package/dist/commands/logs.d.ts +2 -2
- package/dist/commands/logs.js +9 -9
- package/dist/commands/mcp.js +2 -2
- package/dist/commands/memory.js +1 -1
- package/dist/commands/message.d.ts +1 -1
- package/dist/commands/message.js +7 -7
- package/dist/commands/mine.d.ts +11 -8
- package/dist/commands/mine.js +11 -10
- package/dist/commands/models.js +1 -1
- package/dist/commands/modes.js +1 -1
- package/dist/commands/monitors.js +23 -6
- package/dist/commands/output.d.ts +7 -6
- package/dist/commands/output.js +11 -10
- package/dist/commands/packages.js +4 -4
- package/dist/commands/perf.js +1 -1
- package/dist/commands/permissions.js +49 -32
- package/dist/commands/plugins.d.ts +1 -1
- package/dist/commands/plugins.js +3 -3
- package/dist/commands/profiles.d.ts +6 -9
- package/dist/commands/profiles.js +8 -321
- package/dist/commands/projects.d.ts +9 -0
- package/dist/commands/projects.js +140 -8
- package/dist/commands/prune.js +5 -13
- package/dist/commands/refresh-rules.js +1 -1
- package/dist/commands/repo.d.ts +5 -7
- package/dist/commands/repo.js +34 -18
- package/dist/commands/resource-view.js +4 -0
- package/dist/commands/resume.d.ts +11 -7
- package/dist/commands/resume.js +82 -98
- package/dist/commands/route.d.ts +12 -0
- package/dist/commands/route.js +261 -0
- package/dist/commands/routines.d.ts +2 -3
- package/dist/commands/routines.js +120 -145
- package/dist/commands/rules.js +1 -1
- package/dist/commands/run-account-picker.d.ts +1 -1
- package/dist/commands/run-account-picker.js +2 -2
- package/dist/commands/run-broadcast.d.ts +21 -0
- package/dist/commands/run-broadcast.js +89 -0
- package/dist/commands/run-cloud.js +1 -1
- package/dist/commands/secrets-vault.d.ts +10 -0
- package/dist/commands/{login.js → secrets-vault.js} +34 -14
- package/dist/commands/secrets.d.ts +4 -4
- package/dist/commands/secrets.js +72 -63
- package/dist/commands/sessions-backfill.js +1 -1
- package/dist/commands/sessions-browser.d.ts +1 -1
- package/dist/commands/sessions-browser.js +9 -5
- package/dist/commands/sessions-export.js +2 -2
- package/dist/commands/sessions-inject.js +4 -5
- package/dist/commands/sessions-migrate.js +16 -27
- package/dist/commands/sessions-picker.d.ts +13 -0
- package/dist/commands/sessions-picker.js +182 -8
- package/dist/commands/sessions-resume.d.ts +7 -3
- package/dist/commands/sessions-resume.js +81 -33
- package/dist/commands/sessions-stats.js +2 -2
- package/dist/commands/sessions.d.ts +75 -68
- package/dist/commands/sessions.js +142 -180
- package/dist/commands/setup-computer.js +1 -1
- package/dist/commands/setup-fleet.js +3 -0
- package/dist/commands/setup-mine.d.ts +7 -3
- package/dist/commands/setup-mine.js +13 -8
- package/dist/commands/setup-secrets.js +2 -2
- package/dist/commands/setup-watchdog.js +2 -2
- package/dist/commands/setup.js +7 -2
- package/dist/commands/share.d.ts +65 -0
- package/dist/commands/share.js +253 -20
- package/dist/commands/skills.js +3 -3
- package/dist/commands/snapshot.d.ts +2 -2
- package/dist/commands/snapshot.js +9 -9
- package/dist/commands/ssh.d.ts +1 -1
- package/dist/commands/ssh.js +318 -48
- package/dist/commands/subagents.js +1 -1
- package/dist/commands/sync.js +24 -9
- package/dist/commands/teams.d.ts +2 -2
- package/dist/commands/teams.js +9 -18
- package/dist/commands/tmux.js +5 -1
- package/dist/commands/trash.js +1 -1
- package/dist/commands/usage.d.ts +1 -1
- package/dist/commands/usage.js +2 -2
- package/dist/commands/utils.d.ts +4 -14
- package/dist/commands/utils.js +6 -27
- package/dist/commands/versions.js +2 -2
- package/dist/commands/view.d.ts +9 -77
- package/dist/commands/view.js +23 -8
- package/dist/commands/watchdog.js +1 -1
- package/dist/commands/webhook.js +11 -25
- package/dist/commands/workflows.js +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/account-capabilities.d.ts +39 -0
- package/dist/lib/account-capabilities.js +59 -0
- package/dist/lib/account-catalog.js +1 -1
- package/dist/lib/account-registry.d.ts +66 -0
- package/dist/lib/account-registry.js +151 -5
- package/dist/lib/{rotate.d.ts → accounting/rotate.d.ts} +4 -4
- package/dist/lib/{rotate.js → accounting/rotate.js} +8 -8
- package/dist/lib/{usage.d.ts → accounting/usage.d.ts} +4 -4
- package/dist/lib/{usage.js → accounting/usage.js} +11 -11
- package/dist/lib/agent-spec/provider.js +1 -1
- package/dist/lib/agents.d.ts +72 -4
- package/dist/lib/agents.js +231 -199
- package/dist/lib/answer-router.d.ts +2 -2
- package/dist/lib/ask-classifier.d.ts +1 -1
- package/dist/lib/ask-classifier.js +1 -1
- package/dist/lib/audit/log.js +1 -1
- package/dist/lib/auth-health.d.ts +1 -1
- package/dist/lib/auth-health.js +2 -2
- package/dist/lib/brand.js +1 -1
- package/dist/lib/browser/caller-identity.d.ts +28 -0
- package/dist/lib/browser/caller-identity.js +156 -0
- package/dist/lib/browser/cdp.js +1 -1
- package/dist/lib/browser/drivers/ssh.d.ts +1 -1
- package/dist/lib/browser/drivers/ssh.js +2 -2
- package/dist/lib/browser/hygiene.d.ts +10 -2
- package/dist/lib/browser/hygiene.js +7 -4
- package/dist/lib/browser/ipc.d.ts +22 -2
- package/dist/lib/browser/ipc.js +185 -21
- package/dist/lib/browser/profiles.d.ts +67 -3
- package/dist/lib/browser/profiles.js +129 -7
- package/dist/lib/browser/remote-control.d.ts +2 -2
- package/dist/lib/browser/remote-control.js +3 -3
- package/dist/lib/browser/runtime-state.d.ts +79 -0
- package/dist/lib/browser/runtime-state.js +119 -1
- package/dist/lib/browser/service.d.ts +113 -1
- package/dist/lib/browser/service.js +454 -40
- package/dist/lib/browser/sessions-list.d.ts +2 -1
- package/dist/lib/browser/sessions-list.js +4 -13
- package/dist/lib/browser/types.d.ts +18 -0
- package/dist/lib/budget/config.js +1 -1
- package/dist/lib/budget/ledger.js +1 -1
- package/dist/lib/byok-usage.js +1 -1
- package/dist/lib/capabilities.js +3 -15
- package/dist/lib/catchup.d.ts +1 -1
- package/dist/lib/catchup.js +1 -1
- package/dist/lib/cloud/dispatch.js +1 -1
- package/dist/lib/cloud/host.d.ts +3 -3
- package/dist/lib/cloud/host.js +5 -5
- package/dist/lib/cloud/rush.d.ts +9 -21
- package/dist/lib/cloud/rush.js +33 -120
- package/dist/lib/cloud/types.d.ts +2 -2
- package/dist/lib/commands.js +3 -13
- package/dist/lib/computer/actions.d.ts +36 -0
- package/dist/lib/computer/actions.js +162 -0
- package/dist/lib/computer/dispatch.d.ts +2 -2
- package/dist/lib/computer/dispatch.js +2 -2
- package/dist/lib/computer/sessions-list.d.ts +3 -3
- package/dist/lib/computer/sessions-list.js +2 -2
- package/dist/lib/config-keys.d.ts +12 -3
- package/dist/lib/config-keys.js +29 -6
- package/dist/lib/config-machine-keys.d.ts +4 -2
- package/dist/lib/config-machine-keys.js +6 -2
- package/dist/lib/crabbox/lease.js +9 -1
- package/dist/lib/crabbox/runtimes.d.ts +32 -7
- package/dist/lib/crabbox/runtimes.js +72 -30
- package/dist/lib/{daemon.d.ts → daemon/daemon.d.ts} +59 -1
- package/dist/lib/{daemon.js → daemon/daemon.js} +237 -49
- package/dist/lib/daemon-services.d.ts +1 -1
- package/dist/lib/daemon-services.js +5 -0
- package/dist/lib/daemon-ticks.d.ts +25 -0
- package/dist/lib/daemon-ticks.js +31 -1
- package/dist/lib/daemon-webhooks.d.ts +102 -0
- package/dist/lib/daemon-webhooks.js +210 -0
- package/dist/lib/device-config.d.ts +116 -72
- package/dist/lib/device-config.js +366 -132
- package/dist/lib/devices/config-migration.d.ts +29 -34
- package/dist/lib/devices/config-migration.js +209 -130
- package/dist/lib/devices/connect.d.ts +2 -2
- package/dist/lib/devices/connect.js +2 -2
- package/dist/lib/devices/discovery-policy.d.ts +30 -0
- package/dist/lib/devices/discovery-policy.js +101 -0
- package/dist/lib/devices/fleet-inventory.js +8 -3
- package/dist/lib/devices/harness-inventory.d.ts +1 -1
- package/dist/lib/devices/harness-inventory.js +12 -3
- package/dist/lib/devices/known-hosts.js +1 -1
- package/dist/lib/devices/pool.d.ts +61 -0
- package/dist/lib/devices/pool.js +83 -0
- package/dist/lib/devices/registry.d.ts +1 -1
- package/dist/lib/devices/registry.js +1 -1
- package/dist/lib/devices/resolve-profile.d.ts +2 -2
- package/dist/lib/devices/resolve-profile.js +2 -2
- package/dist/lib/devices/resolve-target.d.ts +1 -1
- package/dist/lib/devices/resolve-target.js +4 -4
- package/dist/lib/devices/self-host.d.ts +1 -1
- package/dist/lib/devices/self-host.js +3 -3
- package/dist/lib/devices/ssh-config.d.ts +1 -1
- package/dist/lib/devices/stats-cache.js +1 -1
- package/dist/lib/devices/sync.d.ts +3 -1
- package/dist/lib/devices/sync.js +3 -3
- package/dist/lib/doctor-diff.js +4 -4
- package/dist/lib/drift-sync.js +2 -2
- package/dist/lib/drift.js +2 -2
- package/dist/lib/event-families.d.ts +1 -1
- package/dist/lib/event-stream.d.ts +1 -1
- package/dist/lib/event-stream.js +2 -2
- package/dist/lib/events-ingest.js +2 -2
- package/dist/lib/exec.d.ts +8 -5
- package/dist/lib/exec.js +19 -13
- package/dist/lib/factory/snapshot.d.ts +1 -1
- package/dist/lib/factory/snapshot.js +1 -1
- package/dist/lib/{activity.d.ts → feed/activity.d.ts} +1 -1
- package/dist/lib/{activity.js → feed/activity.js} +7 -7
- package/dist/lib/{events.d.ts → feed/events.d.ts} +2 -2
- package/dist/lib/{events.js → feed/events.js} +5 -5
- package/dist/lib/{feed.js → feed/feed.js} +4 -4
- package/dist/lib/feed-outcome.d.ts +1 -1
- package/dist/lib/feed-policy.d.ts +1 -1
- package/dist/lib/feed-policy.js +1 -1
- package/dist/lib/feed-post.d.ts +1 -1
- package/dist/lib/feed-post.js +1 -1
- package/dist/lib/feed-ranking.d.ts +1 -1
- package/dist/lib/fleet/apply.d.ts +0 -6
- package/dist/lib/fleet/apply.js +18 -45
- package/dist/lib/fleet/auth-sync.d.ts +16 -35
- package/dist/lib/fleet/auth-sync.js +16 -75
- package/dist/lib/fleet/capture.js +8 -6
- package/dist/lib/fleet/manifest.js +23 -11
- package/dist/lib/fleet/types.d.ts +19 -7
- package/dist/lib/fleet-cache.d.ts +1 -1
- package/dist/lib/fleet-cache.js +1 -1
- package/dist/lib/format.d.ts +19 -0
- package/dist/lib/format.js +44 -1
- package/dist/lib/friction-heuristics.d.ts +1 -1
- package/dist/lib/git.d.ts +24 -1
- package/dist/lib/git.js +82 -38
- package/dist/lib/heal.js +3 -3
- package/dist/lib/hooks.d.ts +18 -0
- package/dist/lib/hooks.js +113 -1
- package/dist/lib/hosts/credentials.d.ts +30 -10
- package/dist/lib/hosts/credentials.js +38 -26
- package/dist/lib/hosts/dispatch.d.ts +3 -3
- package/dist/lib/hosts/dispatch.js +3 -3
- package/dist/lib/hosts/option.d.ts +3 -3
- package/dist/lib/hosts/option.js +7 -8
- package/dist/lib/hosts/passthrough.d.ts +17 -17
- package/dist/lib/hosts/passthrough.js +67 -50
- package/dist/lib/hosts/providers/devices.d.ts +1 -1
- package/dist/lib/hosts/providers/devices.js +1 -1
- package/dist/lib/hosts/reconcile.d.ts +1 -1
- package/dist/lib/hosts/reconcile.js +1 -1
- package/dist/lib/hosts/reconnect.d.ts +1 -1
- package/dist/lib/hosts/reconnect.js +2 -2
- package/dist/lib/hosts/registry.d.ts +5 -5
- package/dist/lib/hosts/registry.js +5 -5
- package/dist/lib/hosts/remote-cmd.d.ts +10 -10
- package/dist/lib/hosts/remote-cmd.js +25 -18
- package/dist/lib/hosts/remote-os.d.ts +4 -4
- package/dist/lib/hosts/remote-os.js +4 -4
- package/dist/lib/hosts/remote-session-id.d.ts +2 -2
- package/dist/lib/hosts/remote-session-id.js +2 -2
- package/dist/lib/hosts/routing-flag.d.ts +3 -3
- package/dist/lib/hosts/routing-flag.js +4 -5
- package/dist/lib/hosts/run-target.d.ts +4 -4
- package/dist/lib/hosts/run-target.js +4 -4
- package/dist/lib/hosts/session-index.d.ts +2 -2
- package/dist/lib/hosts/session-index.js +1 -1
- package/dist/lib/hosts/session-marker.d.ts +1 -1
- package/dist/lib/hosts/session-marker.js +1 -1
- package/dist/lib/hosts/types.d.ts +2 -2
- package/dist/lib/hosts/types.js +2 -2
- package/dist/lib/import.js +1 -1
- package/dist/lib/{migrate.d.ts → installations/migrate.d.ts} +49 -1
- package/dist/lib/{migrate.js → installations/migrate.js} +265 -38
- package/dist/lib/installations/resolve.js +1 -1
- package/dist/lib/installations/strategies.js +1 -1
- package/dist/lib/installations/update.js +2 -2
- package/dist/lib/{versions.d.ts → installations/versions.d.ts} +12 -3
- package/dist/lib/{versions.js → installations/versions.js} +51 -31
- package/dist/lib/isolation-boundary-report.js +1 -1
- package/dist/lib/linear-projects.d.ts +28 -0
- package/dist/lib/linear-projects.js +30 -0
- package/dist/lib/loop.js +1 -1
- package/dist/lib/mailbox-gc.js +1 -1
- package/dist/lib/mailbox.js +1 -1
- package/dist/lib/mcp-registry.d.ts +62 -0
- package/dist/lib/mcp-registry.js +177 -0
- package/dist/lib/mcp.d.ts +5 -0
- package/dist/lib/mcp.js +124 -307
- 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/install-menubar.d.ts +7 -0
- package/dist/lib/menubar/install-menubar.js +24 -6
- package/dist/lib/menubar/snapshot.d.ts +7 -0
- package/dist/lib/menubar/snapshot.js +8 -6
- package/dist/lib/models.js +1 -1
- package/dist/lib/monitors/config.d.ts +12 -0
- package/dist/lib/monitors/config.js +3 -0
- package/dist/lib/monitors/dispatch.js +26 -5
- package/dist/lib/monitors/engine.js +10 -0
- package/dist/lib/monitors/sources/webhook.d.ts +1 -1
- package/dist/lib/monitors/state.d.ts +42 -0
- package/dist/lib/monitors/state.js +30 -0
- package/dist/lib/notify.d.ts +1 -1
- package/dist/lib/observe-aliases.d.ts +2 -2
- package/dist/lib/observe-aliases.js +2 -11
- package/dist/lib/output/git-output.js +2 -2
- package/dist/lib/overdue.d.ts +1 -1
- package/dist/lib/overdue.js +1 -1
- package/dist/lib/permissions-registry.d.ts +65 -0
- package/dist/lib/permissions-registry.js +599 -0
- package/dist/lib/permissions.d.ts +24 -13
- package/dist/lib/permissions.js +52 -271
- package/dist/lib/picker.d.ts +16 -0
- package/dist/lib/picker.js +33 -3
- package/dist/lib/placement.d.ts +1 -1
- package/dist/lib/placement.js +4 -4
- package/dist/lib/platform/paths.d.ts +8 -0
- package/dist/lib/platform/paths.js +11 -0
- package/dist/lib/platform/posixpath.js +3 -3
- package/dist/lib/{plugin-marketplace.d.ts → plugins/plugin-marketplace.d.ts} +1 -1
- package/dist/lib/{plugin-marketplace.js → plugins/plugin-marketplace.js} +2 -2
- package/dist/lib/{plugins.d.ts → plugins/plugins.d.ts} +1 -1
- package/dist/lib/{plugins.js → plugins/plugins.js} +7 -7
- package/dist/lib/{skills.d.ts → plugins/skills.d.ts} +1 -1
- package/dist/lib/{skills.js → plugins/skills.js} +7 -7
- package/dist/lib/pricing/cost.d.ts +1 -1
- package/dist/lib/pricing/cost.js +1 -1
- package/dist/lib/profiles-presets.d.ts +1 -1
- package/dist/lib/profiles-presets.js +1 -1
- package/dist/lib/profiles.js +2 -2
- package/dist/lib/project-import.js +4 -1
- package/dist/lib/project-launch.d.ts +1 -1
- package/dist/lib/project-launch.js +3 -3
- package/dist/lib/project-pull.d.ts +128 -0
- package/dist/lib/project-pull.js +384 -0
- package/dist/lib/project-root.d.ts +2 -2
- package/dist/lib/project-root.js +2 -2
- package/dist/lib/project-status.js +1 -1
- package/dist/lib/projects.d.ts +23 -0
- package/dist/lib/projects.js +29 -6
- package/dist/lib/refresh.d.ts +12 -1
- package/dist/lib/refresh.js +16 -9
- package/dist/lib/registry.d.ts +9 -2
- package/dist/lib/registry.js +11 -4
- package/dist/lib/resources.d.ts +2 -2
- package/dist/lib/resources.js +2 -2
- package/dist/lib/routers.d.ts +81 -0
- package/dist/lib/routers.js +153 -0
- package/dist/lib/routine-context.d.ts +1 -0
- package/dist/lib/routine-context.js +7 -2
- package/dist/lib/routine-notify-owner.d.ts +1 -1
- package/dist/lib/routine-notify.d.ts +1 -1
- package/dist/lib/routine-notify.js +1 -1
- package/dist/lib/routine-process-cleanup.d.ts +1 -1
- package/dist/lib/routine-readiness.d.ts +1 -1
- package/dist/lib/routine-readiness.js +11 -4
- package/dist/lib/routines-placement.d.ts +12 -2
- package/dist/lib/routines-placement.js +20 -3
- package/dist/lib/routines-project.d.ts +1 -1
- package/dist/lib/routines-project.js +1 -1
- package/dist/lib/rules/compile.d.ts +1 -0
- package/dist/lib/rules/compile.js +10 -2
- package/dist/lib/rules/rules.js +1 -1
- package/dist/lib/run-notify.js +1 -1
- package/dist/lib/runner.d.ts +80 -2
- package/dist/lib/runner.js +241 -62
- package/dist/lib/sandbox.d.ts +1 -1
- package/dist/lib/scheduler.d.ts +1 -1
- package/dist/lib/scheduler.js +1 -1
- package/dist/lib/{routines.d.ts → scheduling/routines.d.ts} +54 -9
- package/dist/lib/{routines.js → scheduling/routines.js} +173 -14
- 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.js +2 -2
- package/dist/lib/secrets/audit.js +1 -1
- package/dist/lib/secrets/bundles.d.ts +3 -3
- package/dist/lib/secrets/bundles.js +7 -7
- package/dist/lib/secrets/index.js +1 -1
- package/dist/lib/secrets/list-filter.d.ts +1 -1
- package/dist/lib/secrets/list-filter.js +2 -2
- package/dist/lib/secrets/push.d.ts +1 -1
- package/dist/lib/secrets/push.js +10 -12
- package/dist/lib/secrets/remote.d.ts +12 -10
- package/dist/lib/secrets/remote.js +21 -14
- package/dist/lib/secrets/vault.js +2 -2
- package/dist/lib/self-heal/checks/shadowing.js +1 -1
- package/dist/lib/self-heal/checks/shims.js +1 -1
- package/dist/lib/self-update.d.ts +39 -4
- package/dist/lib/self-update.js +78 -25
- package/dist/lib/serve/control.d.ts +1 -1
- package/dist/lib/serve/control.js +4 -4
- package/dist/lib/serve/data.d.ts +1 -1
- package/dist/lib/serve/data.js +1 -1
- package/dist/lib/serve/stream.js +1 -1
- package/dist/lib/service-manifest.d.ts +29 -0
- package/dist/lib/service-manifest.js +80 -0
- package/dist/lib/session/active.d.ts +59 -7
- package/dist/lib/session/active.js +158 -17
- package/dist/lib/session/bash-command.js +1 -1
- package/dist/lib/session/claude-accounts.d.ts +1 -1
- package/dist/lib/session/claude-accounts.js +1 -1
- package/dist/lib/session/db.d.ts +10 -2
- package/dist/lib/session/db.js +25 -6
- package/dist/lib/session/discover.d.ts +77 -0
- package/dist/lib/session/discover.js +130 -25
- package/dist/lib/session/fork.js +1 -1
- package/dist/lib/session/inject.d.ts +1 -1
- package/dist/lib/session/insights.d.ts +1 -1
- package/dist/lib/session/insights.js +1 -1
- package/dist/lib/session/live-metadata.d.ts +15 -0
- package/dist/lib/session/live-metadata.js +76 -0
- package/dist/lib/session/migrate-targets.d.ts +1 -1
- package/dist/lib/session/recovery.d.ts +1 -1
- package/dist/lib/session/recovery.js +2 -2
- package/dist/lib/session/remote-active.d.ts +10 -1
- package/dist/lib/session/remote-active.js +8 -3
- package/dist/lib/session/remote-bundle.d.ts +1 -1
- package/dist/lib/session/remote-bundle.js +2 -2
- package/dist/lib/session/remote-list.d.ts +15 -4
- package/dist/lib/session/remote-list.js +40 -3
- package/dist/lib/session/remote.d.ts +5 -5
- package/dist/lib/session/remote.js +13 -17
- package/dist/lib/session/resume-command.d.ts +3 -2
- package/dist/lib/session/resume-command.js +4 -3
- package/dist/lib/session/resume-owner.d.ts +3 -3
- package/dist/lib/session/resume-owner.js +3 -3
- package/dist/lib/session/session-cache.d.ts +12 -0
- package/dist/lib/session/session-cache.js +2 -0
- package/dist/lib/session/shell-programs.js +1 -1
- package/dist/lib/session/state.js +5 -5
- package/dist/lib/session/team-filter.d.ts +1 -1
- package/dist/lib/session/team-filter.js +1 -1
- package/dist/lib/session/types.d.ts +3 -3
- package/dist/lib/session/width.d.ts +2 -2
- package/dist/lib/session/width.js +2 -2
- package/dist/lib/share/delete.d.ts +21 -0
- package/dist/lib/share/delete.js +42 -0
- package/dist/lib/share/publish.d.ts +82 -0
- package/dist/lib/share/publish.js +170 -18
- package/dist/lib/share/worker-template.js +172 -9
- package/dist/lib/shims.js +35 -7
- package/dist/lib/smart-launch.d.ts +36 -6
- package/dist/lib/smart-launch.js +65 -8
- package/dist/lib/snapshot.d.ts +4 -4
- package/dist/lib/snapshot.js +2 -2
- package/dist/lib/ssh-exec.d.ts +1 -1
- package/dist/lib/ssh-exec.js +2 -2
- package/dist/lib/ssh-tunnel.d.ts +10 -10
- package/dist/lib/ssh-tunnel.js +12 -12
- package/dist/lib/staleness/checkers/hooks.d.ts +1 -1
- package/dist/lib/staleness/checkers/hooks.js +1 -1
- package/dist/lib/staleness/detectors/permissions.js +0 -23
- package/dist/lib/staleness/detectors/plugins.js +1 -1
- package/dist/lib/staleness/fingerprint.js +1 -1
- package/dist/lib/staleness/layers.d.ts +1 -1
- package/dist/lib/staleness/layers.js +1 -1
- package/dist/lib/staleness/writers/mcp.js +3 -1
- package/dist/lib/staleness/writers/plugins.js +1 -1
- package/dist/lib/staleness/writers/types.d.ts +8 -0
- package/dist/lib/startup/command-registry.d.ts +5 -147
- package/dist/lib/startup/command-registry.js +38 -303
- package/dist/lib/startup/dev-build.d.ts +0 -21
- package/dist/lib/startup/dev-build.js +29 -8
- package/dist/lib/state.d.ts +19 -1
- package/dist/lib/state.js +120 -51
- package/dist/lib/subagents.js +1 -1
- package/dist/lib/sync-status.js +1 -1
- package/dist/lib/sync-umbrella.d.ts +6 -1
- package/dist/lib/sync-umbrella.js +9 -4
- package/dist/lib/teams/agents.js +2 -2
- package/dist/lib/teams/registry.js +1 -1
- package/dist/lib/terminal/backends/vscodium-agent.js +1 -1
- package/dist/lib/terminal/engine.js +1 -1
- package/dist/lib/terminal/index.d.ts +4 -0
- package/dist/lib/terminal/index.js +3 -0
- package/dist/lib/terminal/inject.d.ts +2 -2
- package/dist/lib/terminal/inject.js +2 -2
- package/dist/lib/terminal/transport.js +1 -1
- package/dist/lib/tmux/index.d.ts +1 -1
- package/dist/lib/tmux/index.js +1 -1
- package/dist/lib/tmux/session.d.ts +21 -5
- package/dist/lib/tmux/session.js +76 -22
- package/dist/lib/triggers/handlers.d.ts +1 -1
- package/dist/lib/triggers/handlers.js +2 -2
- package/dist/lib/triggers/webhook.d.ts +36 -2
- package/dist/lib/triggers/webhook.js +97 -42
- package/dist/lib/types.d.ts +18 -6
- package/dist/lib/usage-fleet.d.ts +1 -1
- package/dist/lib/usage-fleet.js +1 -1
- package/dist/lib/usage-refresh.d.ts +1 -1
- package/dist/lib/usage-refresh.js +3 -3
- package/dist/lib/version-duplicates.js +2 -2
- package/dist/lib/view-types.d.ts +56 -0
- package/dist/lib/view-types.js +1 -0
- package/dist/lib/watchdog/rotate.d.ts +2 -2
- package/dist/lib/watchdog/rotate.js +3 -3
- package/dist/lib/watchdog/runner.d.ts +2 -3
- package/dist/lib/watchdog/runner.js +3 -4
- package/dist/lib/workflows.js +1 -1
- package/package.json +2 -1
- package/scripts/postinstall.js +2 -2
- package/dist/commands/bench.d.ts +0 -2
- package/dist/commands/bench.js +0 -101
- package/dist/commands/cp.d.ts +0 -84
- package/dist/commands/cp.js +0 -231
- package/dist/commands/login.d.ts +0 -2
- package/dist/lib/resources/commands.d.ts +0 -46
- package/dist/lib/resources/commands.js +0 -211
- package/dist/lib/resources/hooks.d.ts +0 -16
- package/dist/lib/resources/hooks.js +0 -153
- package/dist/lib/resources/mcp.d.ts +0 -34
- package/dist/lib/resources/mcp.js +0 -250
- package/dist/lib/resources/memory.d.ts +0 -15
- package/dist/lib/resources/memory.js +0 -46
- package/dist/lib/resources/permissions.d.ts +0 -13
- package/dist/lib/resources/permissions.js +0 -202
- package/dist/lib/resources/rules.d.ts +0 -46
- package/dist/lib/resources/rules.js +0 -179
- package/dist/lib/resources/skills.d.ts +0 -37
- package/dist/lib/resources/skills.js +0 -247
- package/dist/lib/resources/subagents.d.ts +0 -46
- package/dist/lib/resources/subagents.js +0 -202
- /package/dist/lib/{feed.d.ts → feed/feed.d.ts} +0 -0
|
@@ -34,7 +34,7 @@ import { costOfUsage, costOfUsageNoCache } from '../pricing/index.js';
|
|
|
34
34
|
import { machineForSessionFile } from './origin-machine.js';
|
|
35
35
|
export { machineForSessionFile } from './origin-machine.js';
|
|
36
36
|
import { mapBounded } from '../concurrency.js';
|
|
37
|
-
import { getDB, getScanStampByPath, getScanStampsForPaths, getParserStatesForPaths, getDirLedgerForPaths, recordDirScans, recordScans, syncLabels, seedLabelsFromNames, syncTopics, upsertSessionsBatch, querySessions, countSessions, ftsSearch, tryClaimScan, releaseScan, cacheLinearProject, } from './db.js';
|
|
37
|
+
import { getDB, getScanStampByPath, getScanStampsForPaths, getParserStatesForPaths, getDirLedgerForPaths, recordDirScans, recordScans, syncLabels, seedLabelsFromNames, syncTopics, upsertSessionsBatch, querySessions, countSessions, ftsSearch, tryClaimScan, releaseScan, scanInProgressByLivePid, cacheLinearProject, } from './db.js';
|
|
38
38
|
import { buildRunNameMap } from './run-names.js';
|
|
39
39
|
import { resolveLinearApiKey } from '../linear-cache.js';
|
|
40
40
|
import { ToolCallCollector, collectClaudeToolCalls, collectCodexToolCalls, } from './tool-calls.js';
|
|
@@ -142,6 +142,12 @@ function dirLedgerDisabled() {
|
|
|
142
142
|
return v === '1' || v === 'true';
|
|
143
143
|
}
|
|
144
144
|
let cachedOpenClawWorkspaces = null;
|
|
145
|
+
/** Max time a `waitForScan` repair waits for a concurrent scan to settle. */
|
|
146
|
+
const WAIT_FOR_SCAN_TIMEOUT_MS = 2_000;
|
|
147
|
+
const WAIT_FOR_SCAN_POLL_MS = 100;
|
|
148
|
+
function sleep(ms) {
|
|
149
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
150
|
+
}
|
|
145
151
|
const cachedAgentVersions = new Map();
|
|
146
152
|
/**
|
|
147
153
|
* Discover sessions. Scans only files whose (mtime, size) have changed since
|
|
@@ -154,31 +160,81 @@ const cachedAgentVersions = new Map();
|
|
|
154
160
|
* TTL, no external lock files needed.
|
|
155
161
|
*/
|
|
156
162
|
export async function discoverSessions(options) {
|
|
163
|
+
const { claimed } = await scanSessionsIncremental({
|
|
164
|
+
agent: options?.agent,
|
|
165
|
+
onProgress: options?.onProgress,
|
|
166
|
+
});
|
|
167
|
+
if (!claimed && options?.waitForScan) {
|
|
168
|
+
// Lost the single-flight claim to another live process (a foreground
|
|
169
|
+
// `agents sessions*` or the daemon's index warm). Rather than return the
|
|
170
|
+
// pre-scan snapshot that just missed, wait (bounded) for that scan to finish
|
|
171
|
+
// so the read below reflects what it wrote (RUSH-2682 cold-miss repair).
|
|
172
|
+
await waitForScanToSettle();
|
|
173
|
+
}
|
|
174
|
+
return queryIndexedSessions(options, {
|
|
175
|
+
skipExistenceCheck: options?.skipExistenceCheck ?? false,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* The write half of {@link discoverSessions}: claim the single-flight scan slot,
|
|
180
|
+
* incrementally index this host's transcript dirs, and report what was parsed.
|
|
181
|
+
*
|
|
182
|
+
* Split out so a caller that only wants the index refreshed — the daemon's warm
|
|
183
|
+
* tick — can run it WITHOUT the listing query `discoverSessions` ends with. That
|
|
184
|
+
* query is not free: it applies a cwd filter, runs the `archived_at`-writing
|
|
185
|
+
* existence check, and can issue a Linear fetch, none of which index anything
|
|
186
|
+
* (RUSH-2691). Keeping one implementation here is also what stops the tick and
|
|
187
|
+
* the foreground path from drifting apart.
|
|
188
|
+
*/
|
|
189
|
+
export async function scanSessionsIncremental(options) {
|
|
157
190
|
// Touch the DB so the schema is ready and connection is cached for this run.
|
|
158
191
|
getDB();
|
|
159
192
|
const agents = options?.agent ? [options.agent] : SESSION_AGENTS;
|
|
160
193
|
const onProgress = options?.onProgress;
|
|
161
|
-
if (tryClaimScan(process.pid))
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
194
|
+
if (!tryClaimScan(process.pid))
|
|
195
|
+
return { claimed: false, scanned: 0 };
|
|
196
|
+
// `parsed` climbs monotonically within one scanner run, so the last value per
|
|
197
|
+
// (phase, agent) is that scanner's total. Phase-keyed because the dotfile scan
|
|
198
|
+
// and the routine-archive scan both report under the same agent id.
|
|
199
|
+
const parsedByPhaseAgent = new Map();
|
|
200
|
+
const track = (phase) => (p) => {
|
|
201
|
+
parsedByPhaseAgent.set(`${phase}\0${p.agent}`, p.parsed);
|
|
202
|
+
onProgress?.(p);
|
|
203
|
+
};
|
|
204
|
+
try {
|
|
205
|
+
// Bounded + staggered instead of a single Promise.all: scanning every
|
|
206
|
+
// agent's dotfile dir (~/.claude, ~/.codex, ~/.gemini, …) simultaneously
|
|
207
|
+
// reads to behavioral EDR (CrowdStrike Falcon) as a ransomware-style bulk
|
|
208
|
+
// file-enumeration sweep. Same dirs, same results — just not all at once.
|
|
209
|
+
await scanAgentsBounded(agents, agent => dispatchAgentScan(agent, track('dotfiles')));
|
|
210
|
+
await scanAgentsBounded(agents, agent => scanRoutineArchivesIncremental(agent, track('routines')));
|
|
211
|
+
// Seed labels from `agents run --name` handles onto the freshly-scanned
|
|
212
|
+
// rows by id. Runs AFTER the per-agent scans (which applied agent-generated
|
|
213
|
+
// titles via syncLabels), so a real title always wins and the seed only
|
|
214
|
+
// backfills sessions that would otherwise be unnamed.
|
|
215
|
+
seedLabelsFromNames(buildRunNameMap());
|
|
178
216
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
217
|
+
finally {
|
|
218
|
+
releaseScan(process.pid);
|
|
219
|
+
}
|
|
220
|
+
let scanned = 0;
|
|
221
|
+
for (const n of parsedByPhaseAgent.values())
|
|
222
|
+
scanned += n;
|
|
223
|
+
return { claimed: true, scanned };
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Poll until no live process holds the scan claim, or the bound elapses
|
|
227
|
+
* (RUSH-2682). Bounded so a wedged/slow scan can never hang a foreground preview.
|
|
228
|
+
* Exported for the cold-miss repair test.
|
|
229
|
+
*/
|
|
230
|
+
export async function waitForScanToSettle(timeoutMs = WAIT_FOR_SCAN_TIMEOUT_MS, pollMs = WAIT_FOR_SCAN_POLL_MS) {
|
|
231
|
+
const deadline = Date.now() + timeoutMs;
|
|
232
|
+
while (scanInProgressByLivePid()) {
|
|
233
|
+
if (Date.now() >= deadline)
|
|
234
|
+
return false;
|
|
235
|
+
await sleep(pollMs);
|
|
236
|
+
}
|
|
237
|
+
return true;
|
|
182
238
|
}
|
|
183
239
|
/** Read the current SQLite snapshot without scanning or parsing transcript files. */
|
|
184
240
|
export async function queryIndexedSessions(options, indexedOptions = {}) {
|
|
@@ -202,6 +258,38 @@ export async function queryIndexedSessions(options, indexedOptions = {}) {
|
|
|
202
258
|
}
|
|
203
259
|
return scopeToManaged(sessions, agents, options);
|
|
204
260
|
}
|
|
261
|
+
/**
|
|
262
|
+
* Resolve a full-or-partial session id against the LOCAL SQLite index only.
|
|
263
|
+
*
|
|
264
|
+
* A plain WAL read through `queryIndexedSessions` — same origin-machine
|
|
265
|
+
* attribution and managed scoping every indexed read gets — with NO incremental
|
|
266
|
+
* discovery scan (so none of `tryClaimScan`/`releaseScan`'s `BEGIN IMMEDIATE`
|
|
267
|
+
* writer lock) and NO fleet SSH fan-out. This is the crash-restart storm path
|
|
268
|
+
* (RUSH-2477): dozens of `sessions resume <id>` at once for a known local id must
|
|
269
|
+
* each be a cheap read, never a writer-lock contender or a dial into the
|
|
270
|
+
* not-yet-up tailnet. Exact id first, then prefix (matching `findSessionsById`),
|
|
271
|
+
* so a complete id never also drags in its prefix siblings. Returns `[]` on a
|
|
272
|
+
* genuine local miss, leaving the caller to fall back to the fleet resolver.
|
|
273
|
+
*
|
|
274
|
+
* The existence check is left ON (`skipExistenceCheck: false`), exactly as the old
|
|
275
|
+
* `discoverSessions` path and `findSessionsById` do (RUSH-2436): it KEEPS a
|
|
276
|
+
* file-gone session whose user turns still live in `session_text` (flagged
|
|
277
|
+
* archived) and SUPPRESSES a contentless phantom — so a phantom id misses here and
|
|
278
|
+
* falls through to the fleet resolver, instead of resolving to a row with no real
|
|
279
|
+
* transcript to resume. For a present transcript — the storm's actual case, since
|
|
280
|
+
* the crashed tabs' files are on disk — the check does no writes, so the lock-free
|
|
281
|
+
* guarantee holds; it only writes to (un)archive a genuinely missing or resurrected
|
|
282
|
+
* file, which is not the 20-at-once resume path.
|
|
283
|
+
*/
|
|
284
|
+
export async function resolveIndexedSessionById(idQuery) {
|
|
285
|
+
const q = idQuery.trim();
|
|
286
|
+
if (!q)
|
|
287
|
+
return [];
|
|
288
|
+
const exact = await queryIndexedSessions({ all: true, unbounded: true, idExact: q }, { resolveLinear: false, skipExistenceCheck: false });
|
|
289
|
+
if (exact.length > 0)
|
|
290
|
+
return exact;
|
|
291
|
+
return queryIndexedSessions({ all: true, unbounded: true, idPrefix: q }, { resolveLinear: false, skipExistenceCheck: false });
|
|
292
|
+
}
|
|
205
293
|
const linearProjectCache = new Map();
|
|
206
294
|
async function resolveLinearProjects(sessions) {
|
|
207
295
|
const apiKey = resolveLinearApiKey();
|
|
@@ -310,8 +398,8 @@ function dispatchAgentScan(agent, onProgress) {
|
|
|
310
398
|
case 'codex': return scanCodexIncremental(onProgress);
|
|
311
399
|
case 'gemini': return scanGeminiIncremental(onProgress);
|
|
312
400
|
case 'antigravity': return scanAntigravityIncremental(onProgress);
|
|
313
|
-
case 'opencode': return scanOpenCodeIncremental();
|
|
314
|
-
case 'openclaw': return scanOpenClawIncremental();
|
|
401
|
+
case 'opencode': return scanOpenCodeIncremental(onProgress);
|
|
402
|
+
case 'openclaw': return scanOpenClawIncremental(onProgress);
|
|
315
403
|
case 'rush': return scanRushIncremental(onProgress);
|
|
316
404
|
case 'hermes': return scanHermesIncremental(onProgress);
|
|
317
405
|
case 'kimi': return scanKimiIncremental(onProgress);
|
|
@@ -418,6 +506,8 @@ function buildQueryOptions(options, agents, opts) {
|
|
|
418
506
|
skipExistenceCheck: options?.skipExistenceCheck,
|
|
419
507
|
skill: options?.skill,
|
|
420
508
|
plugin: options?.plugin,
|
|
509
|
+
idExact: options?.idExact,
|
|
510
|
+
idPrefix: options?.idPrefix,
|
|
421
511
|
};
|
|
422
512
|
}
|
|
423
513
|
/**
|
|
@@ -1940,7 +2030,7 @@ function openCodeSessionStamp(times, bytes, dbScan) {
|
|
|
1940
2030
|
return { fileMtimeMs: known.length === 0 ? 0 : Math.floor(Math.max(...known)), fileSize: size };
|
|
1941
2031
|
}
|
|
1942
2032
|
/** Scan OpenCode sessions from its SQLite database when the DB file has changed. */
|
|
1943
|
-
async function scanOpenCodeIncremental() {
|
|
2033
|
+
async function scanOpenCodeIncremental(onProgress) {
|
|
1944
2034
|
if (!fs.existsSync(OPENCODE_DB))
|
|
1945
2035
|
return;
|
|
1946
2036
|
const stat = safeStatSync(OPENCODE_DB);
|
|
@@ -2135,6 +2225,12 @@ async function scanOpenCodeIncremental() {
|
|
|
2135
2225
|
entries.push({ meta, content: topic || '', scan });
|
|
2136
2226
|
}
|
|
2137
2227
|
upsertSessionsBatch(entries);
|
|
2228
|
+
// Report what this scan indexed. OpenCode is one SQLite DB rather than N
|
|
2229
|
+
// transcript files, so the whole batch lands as a single progress emit —
|
|
2230
|
+
// enough for the daemon's warm tick to count it (RUSH-2691); without it a
|
|
2231
|
+
// tick whose only changed sessions were OpenCode's reported 0 and logged
|
|
2232
|
+
// nothing, the same silent-success class this tick exists to remove.
|
|
2233
|
+
onProgress?.({ agent: 'opencode', parsed: entries.length, total: entries.length });
|
|
2138
2234
|
// Stamp the OpenCode DB itself so we can short-circuit on the next run.
|
|
2139
2235
|
recordScans([{ filePath: OPENCODE_DB, scan: currentScan }]);
|
|
2140
2236
|
}
|
|
@@ -2154,7 +2250,7 @@ async function scanOpenCodeIncremental() {
|
|
|
2154
2250
|
// OpenClaw
|
|
2155
2251
|
// ---------------------------------------------------------------------------
|
|
2156
2252
|
/** Scan active OpenClaw channels and cron jobs via the openclaw CLI. */
|
|
2157
|
-
async function scanOpenClawIncremental() {
|
|
2253
|
+
async function scanOpenClawIncremental(onProgress) {
|
|
2158
2254
|
// Check if openclaw is installed — silently skip if not. `which` is POSIX-only
|
|
2159
2255
|
// (Windows resolves PATH with `where`), so a bare `which` throws ENOENT on every
|
|
2160
2256
|
// Windows run and silently disabled the entire OpenClaw scan there — its sessions
|
|
@@ -2247,6 +2343,15 @@ async function scanOpenClawIncremental() {
|
|
|
2247
2343
|
/* cron command failed */
|
|
2248
2344
|
}
|
|
2249
2345
|
upsertSessionsBatch(entries);
|
|
2346
|
+
// Deliberately NO onProgress emit, unlike every other scanner (RUSH-2691).
|
|
2347
|
+
// This one cannot report a delta: its gate is a 60s TTL (not a store stamp),
|
|
2348
|
+
// `scan` above stamps a fresh `now` on every entry every run, and `entries` is
|
|
2349
|
+
// the CURRENT INVENTORY — running channels plus cron jobs — rebuilt from
|
|
2350
|
+
// scratch each pass. Emitting entries.length would report "how many openclaw
|
|
2351
|
+
// things exist", re-counted every 60s forever, which is a worse lie than
|
|
2352
|
+
// silence: the warm tick's number means "transcripts parsed this scan". Giving
|
|
2353
|
+
// OpenClaw a real per-entry stamp is tracked separately; until then it
|
|
2354
|
+
// contributes 0 and the docblock on IncrementalScanResult says so.
|
|
2250
2355
|
db.prepare(`INSERT OR REPLACE INTO meta (key, value) VALUES ('openclaw_last_scan_ms', ?)`).run(String(Date.now()));
|
|
2251
2356
|
}
|
|
2252
2357
|
/** Incrementally re-scan changed Rush session files and upsert into the DB. */
|
package/dist/lib/session/fork.js
CHANGED
|
@@ -80,7 +80,7 @@ export function forkSession(source, opts = {}) {
|
|
|
80
80
|
// Label sidecar (seeds the DB label; survives rescans until an agent title
|
|
81
81
|
// supersedes it), mirroring `agents run --name`.
|
|
82
82
|
recordRunName({ sessionId: newId, name: label, agent: source.agent, cwd: source.cwd });
|
|
83
|
-
// Register the new session so it resolves immediately (by `agents resume`,
|
|
83
|
+
// Register the new session so it resolves immediately (by `agents sessions resume`,
|
|
84
84
|
// `agents sessions`, etc.) without waiting for the next scan.
|
|
85
85
|
const stamp = opts.now ?? new Date().toISOString();
|
|
86
86
|
const meta = {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* engine stays agnostic of how a target was discovered.
|
|
10
10
|
*/
|
|
11
11
|
import type { ReplyRail } from './provenance.js';
|
|
12
|
-
import type { InjectTarget } from '../terminal/
|
|
12
|
+
import type { InjectTarget } from '../terminal/index.js';
|
|
13
13
|
/**
|
|
14
14
|
* Map a session's `ReplyRail` to an engine `InjectTarget`. Today only tmux rails
|
|
15
15
|
* are externally addressable (provenance.ts:143-149); a null rail yields null and
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Behavioural facets of a coding session, and the cross-session rollup built from them.
|
|
3
3
|
*
|
|
4
4
|
* This is the engine behind `agents insights`. It answers "how do you work" rather than
|
|
5
|
-
* "what did you spend" (`agents cost`) or "what shipped" (`agents output`), and it is
|
|
5
|
+
* "what did you spend" (`agents insights cost`) or "what shipped" (`agents insights output`), and it is
|
|
6
6
|
* the only surface that splits any of it by the account that produced the work.
|
|
7
7
|
*
|
|
8
8
|
* Everything here is a pure function of a parsed `SessionEvent[]`, so it is testable
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Behavioural facets of a coding session, and the cross-session rollup built from them.
|
|
3
3
|
*
|
|
4
4
|
* This is the engine behind `agents insights`. It answers "how do you work" rather than
|
|
5
|
-
* "what did you spend" (`agents cost`) or "what shipped" (`agents output`), and it is
|
|
5
|
+
* "what did you spend" (`agents insights cost`) or "what shipped" (`agents insights output`), and it is
|
|
6
6
|
* the only surface that splits any of it by the account that produced the work.
|
|
7
7
|
*
|
|
8
8
|
* Everything here is a pure function of a parsed `SessionEvent[]`, so it is testable
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type SessionMeta } from './types.js';
|
|
2
|
+
import type { ActiveSession } from './active.js';
|
|
3
|
+
/**
|
|
4
|
+
* Reshape one live `ActiveSession` into a `SessionMeta` candidate for the id
|
|
5
|
+
* resolver. Returns `null` for a row that cannot back a durable session — no
|
|
6
|
+
* `sessionId`, or a `kind` that is not a session-tracked harness (cloud/team
|
|
7
|
+
* rows without a real agent transcript). Pure: the caller supplies `self` (the
|
|
8
|
+
* local machine id) and `nowMs` so the row is deterministic and testable.
|
|
9
|
+
*/
|
|
10
|
+
export declare function activeSessionToSessionMeta(active: ActiveSession, self: string, nowMs: number): SessionMeta | null;
|
|
11
|
+
/**
|
|
12
|
+
* Map every eligible live session to a `SessionMeta` candidate. Ineligible rows
|
|
13
|
+
* (no id, non-agent kind) are dropped. Order follows the input.
|
|
14
|
+
*/
|
|
15
|
+
export declare function liveSessionMetas(active: ActiveSession[], self: string, nowMs: number): SessionMeta[];
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Live-registry → SessionMeta bridge (RUSH-2682)
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
//
|
|
5
|
+
// A session the live registry (`getActiveSessions`) already knows about can be
|
|
6
|
+
// minutes ahead of the transcript index on the SAME box: indexing is lazy and
|
|
7
|
+
// only runs inside `discoverSessions`, so a session this machine JUST started is
|
|
8
|
+
// "running" in `agents sessions --active` while `agents sessions preview <id>`
|
|
9
|
+
// answers "No session matching" until an unrelated `agents sessions*` call
|
|
10
|
+
// happens to scan (measured 7.6 min blind on zion, agents-cli 1.22.39).
|
|
11
|
+
//
|
|
12
|
+
// This module converts a running `ActiveSession` into a `SessionMeta` candidate
|
|
13
|
+
// so the id resolver behind `preview` / `resume` / `focus` can resolve and render
|
|
14
|
+
// a running session with no transcript row yet, instead of claiming it does not
|
|
15
|
+
// exist. It parses no transcript and renders nothing — it only reshapes process
|
|
16
|
+
// state the live registry already computed. When the transcript IS on disk, the
|
|
17
|
+
// synthesized row carries its path, so the downstream `buildPreview` renders the
|
|
18
|
+
// real digest; otherwise it renders the header + a "not indexed here" note.
|
|
19
|
+
import { deriveShortId } from './short-id.js';
|
|
20
|
+
import { isSessionTrackedAgent } from './types.js';
|
|
21
|
+
/**
|
|
22
|
+
* Reshape one live `ActiveSession` into a `SessionMeta` candidate for the id
|
|
23
|
+
* resolver. Returns `null` for a row that cannot back a durable session — no
|
|
24
|
+
* `sessionId`, or a `kind` that is not a session-tracked harness (cloud/team
|
|
25
|
+
* rows without a real agent transcript). Pure: the caller supplies `self` (the
|
|
26
|
+
* local machine id) and `nowMs` so the row is deterministic and testable.
|
|
27
|
+
*/
|
|
28
|
+
export function activeSessionToSessionMeta(active, self, nowMs) {
|
|
29
|
+
const id = active.sessionId;
|
|
30
|
+
if (!id)
|
|
31
|
+
return null;
|
|
32
|
+
if (!isSessionTrackedAgent(active.kind))
|
|
33
|
+
return null;
|
|
34
|
+
const startedMs = active.startedAtMs ?? nowMs;
|
|
35
|
+
const lastMs = active.lastActivityMs ?? startedMs;
|
|
36
|
+
return {
|
|
37
|
+
id,
|
|
38
|
+
shortId: deriveShortId(id),
|
|
39
|
+
agent: active.kind,
|
|
40
|
+
timestamp: new Date(startedMs).toISOString(),
|
|
41
|
+
lastActivity: new Date(lastMs).toISOString(),
|
|
42
|
+
// An empty file path is honest — a just-created session may have no
|
|
43
|
+
// transcript on disk yet, and `buildPreview` renders the header + a live
|
|
44
|
+
// note for that case rather than trying to parse a missing file.
|
|
45
|
+
filePath: active.sessionFile ?? '',
|
|
46
|
+
cwd: active.cwd,
|
|
47
|
+
project: active.project ?? undefined,
|
|
48
|
+
label: active.label,
|
|
49
|
+
topic: active.topic,
|
|
50
|
+
version: active.version,
|
|
51
|
+
messageCount: undefined,
|
|
52
|
+
// The row runs HERE — the local live registry is machine-local, so a match
|
|
53
|
+
// resolves without an SSH hop back to a peer.
|
|
54
|
+
machine: active.machine ?? self,
|
|
55
|
+
ticketId: active.ticket?.id,
|
|
56
|
+
prUrl: active.pr?.url,
|
|
57
|
+
prNumber: active.pr?.number,
|
|
58
|
+
worktreeSlug: active.worktree?.slug,
|
|
59
|
+
gitBranch: active.worktree?.branch,
|
|
60
|
+
origin: active.origin,
|
|
61
|
+
routineName: active.routineName,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Map every eligible live session to a `SessionMeta` candidate. Ineligible rows
|
|
66
|
+
* (no id, non-agent kind) are dropped. Order follows the input.
|
|
67
|
+
*/
|
|
68
|
+
export function liveSessionMetas(active, self, nowMs) {
|
|
69
|
+
const out = [];
|
|
70
|
+
for (const a of active) {
|
|
71
|
+
const meta = activeSessionToSessionMeta(a, self, nowMs);
|
|
72
|
+
if (meta)
|
|
73
|
+
out.push(meta);
|
|
74
|
+
}
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
@@ -18,7 +18,7 @@ import type { DeviceStats, Headroom } from '../devices/health.js';
|
|
|
18
18
|
import type { CrabboxBox } from '../crabbox/cli.js';
|
|
19
19
|
/** A machine the current session could be relocated onto. */
|
|
20
20
|
export interface MigrateTarget {
|
|
21
|
-
/** The `--
|
|
21
|
+
/** The `--device` value: a host/device name, or a warm box slug for ephemeral. */
|
|
22
22
|
name: string;
|
|
23
23
|
/** Where the target comes from — a fleet host/device, or a warm crabbox box. */
|
|
24
24
|
kind: 'fleet' | 'ephemeral';
|
|
@@ -4,8 +4,8 @@ import { AGENTS, agentConfigDirName } from '../agents.js';
|
|
|
4
4
|
import { isSelfHost } from '../devices/self-host.js';
|
|
5
5
|
import { nativeResume } from '../exec.js';
|
|
6
6
|
import { machineId, normalizeHost } from '../machine-id.js';
|
|
7
|
-
import { collectRunCandidates, formatNoHealthyAccountError, pickBalancedCandidate, readinessFromCandidate, } from '../rotate.js';
|
|
8
|
-
import { getVersionHomePath } from '../versions.js';
|
|
7
|
+
import { collectRunCandidates, formatNoHealthyAccountError, pickBalancedCandidate, readinessFromCandidate, } from '../accounting/rotate.js';
|
|
8
|
+
import { getVersionHomePath } from '../installations/versions.js';
|
|
9
9
|
export class SessionRecoveryError extends Error {
|
|
10
10
|
constructor(message) {
|
|
11
11
|
super(message);
|
|
@@ -19,10 +19,19 @@ export interface RemoteActiveResult {
|
|
|
19
19
|
sessions: ActiveSession[];
|
|
20
20
|
/** How many peer machines we attempted to reach (drives the empty-fleet tip). */
|
|
21
21
|
deviceCount: number;
|
|
22
|
+
/**
|
|
23
|
+
* Peer device names that were unreachable, timed out, or lacked the CLI —
|
|
24
|
+
* distinct from a peer that answered with zero sessions. Named so an empty
|
|
25
|
+
* fleet-wide result can say WHICH peers went unheard rather than reading
|
|
26
|
+
* identical to "the fleet is genuinely idle" (RUSH-2507).
|
|
27
|
+
*/
|
|
28
|
+
skipped: string[];
|
|
29
|
+
/** True when the device list itself could not be loaded — no peer was even attempted. */
|
|
30
|
+
discoveryFailed: boolean;
|
|
22
31
|
}
|
|
23
32
|
/**
|
|
24
33
|
* Gather active sessions from other machines. With an explicit `hosts` list
|
|
25
|
-
* (from `--
|
|
34
|
+
* (from `--device`), fan out to exactly those. Otherwise sweep the registered,
|
|
26
35
|
* online devices from `ag devices`, excluding this machine and any without an
|
|
27
36
|
* address. Results from all peers run in parallel and are flattened.
|
|
28
37
|
* `opts.quiet` suppresses the per-device stderr line for callers that report
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* it came from so the renderer can bucket by computer.
|
|
8
8
|
*
|
|
9
9
|
* Peers are the registered, online devices from `ag devices` (or an explicit
|
|
10
|
-
* `--
|
|
10
|
+
* `--device` list). `--local` on the remote invocation is critical: it stops the
|
|
11
11
|
* peer from fanning out to *its* devices, so the sweep never recurses.
|
|
12
12
|
*
|
|
13
13
|
* A dead or slow host is skipped with a stderr note, never fatal — one asleep
|
|
@@ -67,7 +67,7 @@ export function parseRemoteActive(stdout, machine) {
|
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
69
69
|
* Gather active sessions from other machines. With an explicit `hosts` list
|
|
70
|
-
* (from `--
|
|
70
|
+
* (from `--device`), fan out to exactly those. Otherwise sweep the registered,
|
|
71
71
|
* online devices from `ag devices`, excluding this machine and any without an
|
|
72
72
|
* address. Results from all peers run in parallel and are flattened.
|
|
73
73
|
* `opts.quiet` suppresses the per-device stderr line for callers that report
|
|
@@ -81,5 +81,10 @@ export async function gatherRemoteActive(hosts, opts) {
|
|
|
81
81
|
parse: parseRemoteActive,
|
|
82
82
|
quiet: opts?.quiet,
|
|
83
83
|
});
|
|
84
|
-
return {
|
|
84
|
+
return {
|
|
85
|
+
sessions: result.items,
|
|
86
|
+
deviceCount: result.deviceCount,
|
|
87
|
+
skipped: result.skipped,
|
|
88
|
+
discoveryFailed: result.discoveryFailed,
|
|
89
|
+
};
|
|
85
90
|
}
|
|
@@ -7,6 +7,6 @@ export interface RemotePullResult {
|
|
|
7
7
|
* Run `agents sessions export …exportArgs --stdout` on each host and parse the
|
|
8
8
|
* streamed bundle. A host that fails (unreachable, remote error, bad output) is
|
|
9
9
|
* collected in `errors` and skipped — one asleep peer never aborts the pull.
|
|
10
|
-
* `exportArgs` must NOT contain --
|
|
10
|
+
* `exportArgs` must NOT contain --device (the remote export runs for itself only).
|
|
11
11
|
*/
|
|
12
12
|
export declare function pullBundlesFromHosts(hosts: string[], exportArgs: string[]): Promise<RemotePullResult>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Multi-device session transfer over the EXISTING SSH fleet transport
|
|
3
|
-
* (RUSH-1712) — no R2, no daemon. `agents sessions export --
|
|
3
|
+
* (RUSH-1712) — no R2, no daemon. `agents sessions export --device <h>` and
|
|
4
4
|
* `agents sessions import --from-host <h>` both run `agents sessions export
|
|
5
5
|
* … --stdout` ON the peer and stream the bundle back over the same SSH path the
|
|
6
6
|
* cross-machine listing already uses (resolveExplicitTargets + ssh-exec), then
|
|
@@ -31,7 +31,7 @@ function remoteAgentsCommand(args, os) {
|
|
|
31
31
|
* Run `agents sessions export …exportArgs --stdout` on each host and parse the
|
|
32
32
|
* streamed bundle. A host that fails (unreachable, remote error, bad output) is
|
|
33
33
|
* collected in `errors` and skipped — one asleep peer never aborts the pull.
|
|
34
|
-
* `exportArgs` must NOT contain --
|
|
34
|
+
* `exportArgs` must NOT contain --device (the remote export runs for itself only).
|
|
35
35
|
*/
|
|
36
36
|
export async function pullBundlesFromHosts(hosts, exportArgs) {
|
|
37
37
|
const targets = await resolveExplicitTargets(hosts);
|
|
@@ -60,7 +60,7 @@ export interface RemoteListResult {
|
|
|
60
60
|
export declare function isAutomaticSessionPeer(d: DeviceProfile, self: string): boolean;
|
|
61
61
|
/**
|
|
62
62
|
* Gather listing sessions from other machines. With an explicit `hosts` list
|
|
63
|
-
* (from `--
|
|
63
|
+
* (from `--device`), fan out to exactly those. Otherwise sweep the registered,
|
|
64
64
|
* online devices from `ag devices`, excluding this machine and any without an
|
|
65
65
|
* address. `forwardedArgs` are the caller's own sessions args (query + filters,
|
|
66
66
|
* already `--json`) so every peer returns the same slice this machine asked for.
|
|
@@ -113,22 +113,33 @@ export declare function resolvePeerTarget(machine: string): Promise<{
|
|
|
113
113
|
target: string;
|
|
114
114
|
os?: string;
|
|
115
115
|
} | undefined>;
|
|
116
|
+
/**
|
|
117
|
+
* Fetch one remote session's preview digest from its owning peer — the data
|
|
118
|
+
* behind the picker pane for a `_remote` row, whose transcript file this
|
|
119
|
+
* machine cannot parse. Runs the peer's own `agents sessions preview <id>
|
|
120
|
+
* --local --json` (the same envelope `agents sessions preview` already
|
|
121
|
+
* delegates to for a remote id) and returns its `preview` object, verbatim and
|
|
122
|
+
* UNSANITIZED — the caller owns scrubbing peer-supplied strings before any of
|
|
123
|
+
* them reach a TTY. Undefined on every failure: unregistered machine, SSH
|
|
124
|
+
* error, timeout, version-skewed peer with no `--json` preview envelope.
|
|
125
|
+
*/
|
|
126
|
+
export declare function fetchPeerPreviewDigest(sessionId: string, machine: string, timeoutMs?: number): Promise<unknown | undefined>;
|
|
116
127
|
/**
|
|
117
128
|
* Run `agents <args>` ON a peer over SSH, attached to this terminal (inherited
|
|
118
129
|
* stdio). `args` is the full arg vector after the binary — callers pass e.g.
|
|
119
130
|
* `['sessions', id, '--markdown']` or `['sessions', 'resume', id]`. Used when a
|
|
120
131
|
* picked session lives on another machine: its transcript and agent binary are
|
|
121
132
|
* there, so both reading (no TTY) and resuming (TTY) must execute on the peer —
|
|
122
|
-
* not via a local `--
|
|
133
|
+
* not via a local `--device` hop, which would discover locally and dead-end for a
|
|
123
134
|
* session that exists only on the peer. Resolves 'no-target' when the machine
|
|
124
135
|
* isn't a dialable registered device; the caller surfaces a clear message.
|
|
125
136
|
*
|
|
126
137
|
* `opts.env` adds variables to the remote command. It deliberately does NOT
|
|
127
|
-
* carry `AGENTS_FLEET_REMOTE` the way the `--
|
|
138
|
+
* carry `AGENTS_FLEET_REMOTE` the way the `--device` passthrough does: that marker
|
|
128
139
|
* gates consent-sensitive actions on the far side
|
|
129
140
|
* (lib/browser/remote-control.ts), and a resumed agent is a long-lived session
|
|
130
141
|
* that would inherit it for its whole life — `agents browser start` inside it
|
|
131
|
-
* would then be refused as a cross-machine drive. A one-shot `--
|
|
142
|
+
* would then be refused as a cross-machine drive. A one-shot `--device` command
|
|
132
143
|
* can carry the marker; a session cannot.
|
|
133
144
|
*/
|
|
134
145
|
export declare function runOnPeer(args: string[], machine: string, opts?: {
|
|
@@ -523,22 +523,59 @@ export async function resolvePeerTarget(machine) {
|
|
|
523
523
|
}
|
|
524
524
|
return undefined;
|
|
525
525
|
}
|
|
526
|
+
/** Interactive ceiling for a picker-driven peer preview fetch. Tighter than the
|
|
527
|
+
* fan-out's 60s: the user is arrowing through rows, and a peer that can't
|
|
528
|
+
* answer a one-session digest in this window should degrade to the metadata
|
|
529
|
+
* card rather than hold a "fetching…" pane open. */
|
|
530
|
+
const PEER_PREVIEW_TIMEOUT_MS = 15_000;
|
|
531
|
+
/**
|
|
532
|
+
* Fetch one remote session's preview digest from its owning peer — the data
|
|
533
|
+
* behind the picker pane for a `_remote` row, whose transcript file this
|
|
534
|
+
* machine cannot parse. Runs the peer's own `agents sessions preview <id>
|
|
535
|
+
* --local --json` (the same envelope `agents sessions preview` already
|
|
536
|
+
* delegates to for a remote id) and returns its `preview` object, verbatim and
|
|
537
|
+
* UNSANITIZED — the caller owns scrubbing peer-supplied strings before any of
|
|
538
|
+
* them reach a TTY. Undefined on every failure: unregistered machine, SSH
|
|
539
|
+
* error, timeout, version-skewed peer with no `--json` preview envelope.
|
|
540
|
+
*/
|
|
541
|
+
export async function fetchPeerPreviewDigest(sessionId, machine, timeoutMs = PEER_PREVIEW_TIMEOUT_MS) {
|
|
542
|
+
const peer = await resolvePeerTarget(machine);
|
|
543
|
+
if (!peer)
|
|
544
|
+
return undefined;
|
|
545
|
+
const cmd = remoteListCommand(['sessions', 'preview', sessionId, '--local', '--json'], peer.os);
|
|
546
|
+
const capture = await sshCapture(peer.target, cmd, timeoutMs);
|
|
547
|
+
if (capture.code !== 0)
|
|
548
|
+
return undefined;
|
|
549
|
+
let parsed;
|
|
550
|
+
try {
|
|
551
|
+
parsed = JSON.parse(stripClixml(capture.stdout));
|
|
552
|
+
}
|
|
553
|
+
catch {
|
|
554
|
+
return undefined;
|
|
555
|
+
}
|
|
556
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
557
|
+
return undefined;
|
|
558
|
+
const preview = parsed.preview;
|
|
559
|
+
if (!preview || typeof preview !== 'object' || Array.isArray(preview))
|
|
560
|
+
return undefined;
|
|
561
|
+
return preview;
|
|
562
|
+
}
|
|
526
563
|
/**
|
|
527
564
|
* Run `agents <args>` ON a peer over SSH, attached to this terminal (inherited
|
|
528
565
|
* stdio). `args` is the full arg vector after the binary — callers pass e.g.
|
|
529
566
|
* `['sessions', id, '--markdown']` or `['sessions', 'resume', id]`. Used when a
|
|
530
567
|
* picked session lives on another machine: its transcript and agent binary are
|
|
531
568
|
* there, so both reading (no TTY) and resuming (TTY) must execute on the peer —
|
|
532
|
-
* not via a local `--
|
|
569
|
+
* not via a local `--device` hop, which would discover locally and dead-end for a
|
|
533
570
|
* session that exists only on the peer. Resolves 'no-target' when the machine
|
|
534
571
|
* isn't a dialable registered device; the caller surfaces a clear message.
|
|
535
572
|
*
|
|
536
573
|
* `opts.env` adds variables to the remote command. It deliberately does NOT
|
|
537
|
-
* carry `AGENTS_FLEET_REMOTE` the way the `--
|
|
574
|
+
* carry `AGENTS_FLEET_REMOTE` the way the `--device` passthrough does: that marker
|
|
538
575
|
* gates consent-sensitive actions on the far side
|
|
539
576
|
* (lib/browser/remote-control.ts), and a resumed agent is a long-lived session
|
|
540
577
|
* that would inherit it for its whole life — `agents browser start` inside it
|
|
541
|
-
* would then be refused as a cross-machine drive. A one-shot `--
|
|
578
|
+
* would then be refused as a cross-machine drive. A one-shot `--device` command
|
|
542
579
|
* can carry the marker; a session cannot.
|
|
543
580
|
*/
|
|
544
581
|
export async function runOnPeer(args, machine, opts = {}) {
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export declare function shellQuote(s: string): string;
|
|
8
8
|
/**
|
|
9
|
-
* Strip the `--
|
|
9
|
+
* Strip the `--device`/`-D` flag (and its value) from a raw `agents sessions` argv,
|
|
10
10
|
* leaving the args to forward to the remote unchanged. The remote runs the same
|
|
11
11
|
* binary, so every other flag (`--since`, `--last`, `--json`, query, …) carries
|
|
12
|
-
* over for free. Handles every form commander accepts: `--
|
|
13
|
-
* `-
|
|
12
|
+
* over for free. Handles every form commander accepts: `--device h`, `--device=h`,
|
|
13
|
+
* `-D h`, `-D=h`, and the glued short form `-Dh`.
|
|
14
14
|
*
|
|
15
15
|
* @param argv full process argv; the sessions args begin at index 2
|
|
16
16
|
* (`[runtime, script, 'sessions', ...]`).
|
|
@@ -20,9 +20,9 @@ export declare function buildForwardedArgs(argv: string[], hosts?: Set<string>):
|
|
|
20
20
|
* Force a forwarded `agents sessions` listing to span the peer's WHOLE index.
|
|
21
21
|
*
|
|
22
22
|
* A remote listing runs in the peer's SSH-login cwd — its home dir — and the
|
|
23
|
-
* default listing is silently cwd-scoped, so `sessions --
|
|
23
|
+
* default listing is silently cwd-scoped, so `sessions --device box` reads as
|
|
24
24
|
* empty even when the box's index is full (`No sessions found for /home/<user>`).
|
|
25
|
-
* Across SSH a peer's cwd is meaningless, so `--
|
|
25
|
+
* Across SSH a peer's cwd is meaningless, so `--device` defaults to `--all`
|
|
26
26
|
* (whole-index) scope. This only drops the *cwd* narrowing — an explicit path
|
|
27
27
|
* query, `--project`, `--since`, or `--agent` filter still narrows on top, and
|
|
28
28
|
* a query that looks like a path takes precedence over `--all` on the remote.
|