@phnx-labs/agents-cli 1.22.39 → 1.22.41
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 +316 -0
- package/README.md +116 -70
- package/dist/bin/agents +0 -0
- package/dist/bootstrap.js +45 -27
- package/dist/browser.js +2 -2
- package/dist/cli/command-registry.d.ts +135 -0
- package/dist/cli/command-registry.js +259 -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.d.ts +15 -0
- package/dist/commands/browser.js +318 -131
- 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 +16 -3
- 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 +160 -215
- package/dist/commands/factory.js +1 -1
- package/dist/commands/feed.d.ts +2 -2
- package/dist/commands/feed.js +12 -23
- 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 +158 -159
- 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 +14 -0
- package/dist/commands/sessions-picker.js +209 -13
- package/dist/commands/sessions-resume.d.ts +7 -3
- package/dist/commands/sessions-resume.js +81 -33
- package/dist/commands/sessions-share.d.ts +25 -0
- package/dist/commands/sessions-share.js +166 -0
- package/dist/commands/sessions-stats.js +2 -2
- package/dist/commands/sessions.d.ts +75 -68
- package/dist/commands/sessions.js +144 -180
- package/dist/commands/setup-browser.js +1 -1
- 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-preferences.js +2 -2
- 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 +186 -64
- 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 +25 -34
- 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 +5 -1
- package/dist/lib/browser/chrome.js +12 -1
- package/dist/lib/browser/drivers/ssh.d.ts +1 -1
- package/dist/lib/browser/drivers/ssh.js +3 -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 +69 -5
- package/dist/lib/browser/profiles.js +135 -13
- 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 +137 -2
- package/dist/lib/browser/service.js +492 -54
- 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 +19 -1
- 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 +2 -1
- package/dist/lib/config-keys.js +8 -4
- package/dist/lib/config-machine-keys.d.ts +4 -2
- package/dist/lib/config-machine-keys.js +5 -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 +104 -0
- package/dist/lib/daemon-webhooks.js +215 -0
- package/dist/lib/device-config.d.ts +85 -75
- package/dist/lib/device-config.js +280 -142
- 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 +10 -5
- package/dist/lib/devices/pool.js +5 -7
- 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 +4 -4
- package/dist/lib/exec.js +11 -11
- 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} +13 -1
- package/dist/lib/{migrate.js → installations/migrate.js} +160 -40
- 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 +3 -3
- package/dist/lib/observe-aliases.js +3 -21
- 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-key.js +7 -0
- 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 +261 -67
- 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 +4 -4
- package/dist/lib/secrets/bundles.js +8 -8
- package/dist/lib/secrets/headless.d.ts +16 -0
- package/dist/lib/secrets/headless.js +21 -0
- 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 +21 -17
- package/dist/lib/secrets/remote.js +39 -23
- 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/share-html.d.ts +55 -0
- package/dist/lib/session/share-html.js +319 -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/settings-manifest.d.ts +2 -0
- package/dist/lib/settings-manifest.js +81 -3
- package/dist/lib/share/delete.d.ts +21 -0
- package/dist/lib/share/delete.js +42 -0
- package/dist/lib/share/publish.d.ts +120 -0
- package/dist/lib/share/publish.js +243 -18
- package/dist/lib/share/worker-template.js +172 -9
- package/dist/lib/shims.js +35 -7
- package/dist/lib/smart-launch.d.ts +4 -4
- package/dist/lib/smart-launch.js +6 -4
- 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 +6 -147
- package/dist/lib/startup/command-registry.js +40 -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 +38 -3
- package/dist/lib/triggers/handlers.js +58 -7
- package/dist/lib/triggers/webhook.d.ts +113 -5
- package/dist/lib/triggers/webhook.js +223 -44
- package/dist/lib/types.d.ts +19 -7
- 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/dist/lib/wrap.d.ts +33 -0
- package/dist/lib/wrap.js +70 -0
- 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
|
@@ -81,7 +81,7 @@ export declare function sessionMatchesQuery(s: SessionMeta, query: string): bool
|
|
|
81
81
|
* `--print-cmd`.
|
|
82
82
|
*/
|
|
83
83
|
export declare function browserFilterToArgv(f: BrowserFilter, query?: string): string[];
|
|
84
|
-
/** Normalize a `--
|
|
84
|
+
/** Normalize a `--device`/`--device` token (`alias`, `user@host`, `host.domain`) to
|
|
85
85
|
* the canonical machine id the rows carry in `.machine`, so a flag seed matches
|
|
86
86
|
* (the `d` hotkey already cycles canonical ids). Mirrors sessions.ts `hostToken`. */
|
|
87
87
|
export declare function normalizeDeviceSeed(host: string | undefined): string | undefined;
|
|
@@ -16,12 +16,12 @@ import { dynamicPicker } from '../lib/picker.js';
|
|
|
16
16
|
import { isSessionTrackedAgent } from '../lib/session/types.js';
|
|
17
17
|
import { discoverSessions } from '../lib/session/discover.js';
|
|
18
18
|
import { gatherRemoteList } from '../lib/session/remote-list.js';
|
|
19
|
-
import { resolveVersionAliasLoose } from '../lib/versions.js';
|
|
19
|
+
import { resolveVersionAliasLoose } from '../lib/installations/versions.js';
|
|
20
20
|
import { AGENTS } from '../lib/agents.js';
|
|
21
21
|
import { enrichTeamOrigins, safeTeamText, shouldShowTeamSessions } from '../lib/session/team-filter.js';
|
|
22
22
|
import { listBookmarks, toggleBookmark } from '../lib/session/bookmarks.js';
|
|
23
23
|
import { machineId, normalizeHost } from '../lib/session/sync/config.js';
|
|
24
|
-
import { buildPreview } from './sessions-picker.js';
|
|
24
|
+
import { buildPreview, setRemotePreviewRepaint } from './sessions-picker.js';
|
|
25
25
|
import { formatPickerLabel, pickerColumnsFor, ticketLabel, mergeLocalFirst, gatherActiveSessions, liveHostLabel, LIVE_ROW_PREFIX, cleanPreview, handlePickedSession, shouldIncludeLocal, remoteHostsToDial, matchesTeam, formatLiveStatusHeadline, isRunningLiveSession, matchesLiveStatus, parseAgentFilter, resolveRoutineName, } from './sessions.js';
|
|
26
26
|
/**
|
|
27
27
|
* Complete a seed into the filter the picker actually runs on.
|
|
@@ -164,7 +164,7 @@ export function browserFilterToArgv(f, query = '') {
|
|
|
164
164
|
a.push(JSON.stringify(q));
|
|
165
165
|
return a;
|
|
166
166
|
}
|
|
167
|
-
/** Normalize a `--
|
|
167
|
+
/** Normalize a `--device`/`--device` token (`alias`, `user@host`, `host.domain`) to
|
|
168
168
|
* the canonical machine id the rows carry in `.machine`, so a flag seed matches
|
|
169
169
|
* (the `d` hotkey already cycles canonical ids). Mirrors sessions.ts `hostToken`. */
|
|
170
170
|
export function normalizeDeviceSeed(host) {
|
|
@@ -253,7 +253,7 @@ function copyToClipboard(text) {
|
|
|
253
253
|
* The live index is fetched separately/lazily — it's the slow part and only the
|
|
254
254
|
* running filter needs it, so a bare browse stays instant.
|
|
255
255
|
*
|
|
256
|
-
* `hosts` is the explicit `--
|
|
256
|
+
* `hosts` is the explicit `--device`/`--device` scope (if any): it restricts which
|
|
257
257
|
* peers are dialed and whether local is included, honoring the flag's "scope,
|
|
258
258
|
* not add" contract instead of always sweeping the whole fleet. */
|
|
259
259
|
async function fetchRawPool(f, self, local, hosts, fixedFilters = false) {
|
|
@@ -699,6 +699,9 @@ export async function runSessionBrowser(initial = {}, opts = {}) {
|
|
|
699
699
|
const body = buildPreview(s);
|
|
700
700
|
return headline ? `${headline}\n${body}` : body;
|
|
701
701
|
},
|
|
702
|
+
// A remote row's digest arrives over SSH after the pane painted — this is
|
|
703
|
+
// what lets its completion swap the metadata card for the full preview.
|
|
704
|
+
registerPreviewRepaint: setRemotePreviewRepaint,
|
|
702
705
|
headerFor: (f) => unreachable.length > 0
|
|
703
706
|
? `${headerFor(f)} · ${chalk.yellow(`${unreachable.join(', ')}: unreachable`)}`
|
|
704
707
|
: headerFor(f),
|
|
@@ -741,7 +744,8 @@ export async function runSessionBrowser(initial = {}, opts = {}) {
|
|
|
741
744
|
}
|
|
742
745
|
return undefined;
|
|
743
746
|
},
|
|
744
|
-
|
|
747
|
+
// A late digest fetch must not poke a closed prompt.
|
|
748
|
+
}).finally(() => setRemotePreviewRepaint(undefined));
|
|
745
749
|
if (!picked)
|
|
746
750
|
return;
|
|
747
751
|
if (picked.action === 'focus') {
|
|
@@ -196,7 +196,7 @@ export function r2ExportGateError(g, isConfigured) {
|
|
|
196
196
|
if (!g.toR2)
|
|
197
197
|
return null;
|
|
198
198
|
if (g.host && g.host.length > 0) {
|
|
199
|
-
return "--to-r2 backs up THIS machine's sessions; it cannot be combined with --
|
|
199
|
+
return "--to-r2 backs up THIS machine's sessions; it cannot be combined with --device.";
|
|
200
200
|
}
|
|
201
201
|
if (!isConfigured) {
|
|
202
202
|
return ('R2 backup is not configured: the r2.backups secrets bundle is missing or locked.\n' +
|
|
@@ -266,7 +266,7 @@ export function resolveR2BackupKey() {
|
|
|
266
266
|
*/
|
|
267
267
|
async function runRemoteExport(g, selectors, command) {
|
|
268
268
|
if (g.encrypt) {
|
|
269
|
-
process.stderr.write(chalk.yellow('Note: --encrypt is ignored with --
|
|
269
|
+
process.stderr.write(chalk.yellow('Note: --encrypt is ignored with --device (the SSH stream is already encrypted). Encrypt a local bundle instead.\n'));
|
|
270
270
|
}
|
|
271
271
|
const { bundles, errors } = await pullBundlesFromHosts(g.host, forwardExportArgs(g, selectors, command));
|
|
272
272
|
for (const e of errors)
|
|
@@ -14,8 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import chalk from 'chalk';
|
|
16
16
|
import { getActiveSessions } from '../lib/session/active.js';
|
|
17
|
-
import { resolveInjectTargetForSession } from '../lib/terminal/
|
|
18
|
-
import { injectIntoTerminal } from '../lib/terminal/index.js';
|
|
17
|
+
import { injectIntoTerminal, resolveInjectTargetForSession } from '../lib/terminal/index.js';
|
|
19
18
|
import { setHelpSections } from '../lib/help.js';
|
|
20
19
|
/** Resolve a session id (short or full) to an addressable terminal target, via the
|
|
21
20
|
* same resolver the watchdog uses so both agree on what is reachable. */
|
|
@@ -56,7 +55,7 @@ async function runInject(sessionId, text, options) {
|
|
|
56
55
|
enter: options.enter !== false,
|
|
57
56
|
combined: options.combined,
|
|
58
57
|
socket: options.socket,
|
|
59
|
-
host: options.
|
|
58
|
+
host: options.device,
|
|
60
59
|
});
|
|
61
60
|
if (options.json) {
|
|
62
61
|
console.log(JSON.stringify(res));
|
|
@@ -78,7 +77,7 @@ export function registerSessionsInjectCommand(sessionsCmd) {
|
|
|
78
77
|
.option('--pane <id>', 'Target a tmux pane id directly (e.g. %3), skipping session lookup')
|
|
79
78
|
.option('--pty <id>', 'Target an agents-pty session id directly, skipping session lookup')
|
|
80
79
|
.option('--socket <path>', 'tmux socket path (defaults to the session/shared socket)')
|
|
81
|
-
.option('--
|
|
80
|
+
.option('--device <target>', 'Deliver on a remote device over SSH (tmux/AppleScript backends)')
|
|
82
81
|
.option('--no-enter', 'Send only the text, without a trailing Enter')
|
|
83
82
|
.option('--combined', 'Fuse text + Enter into ONE write (default: two writes, Ink-TUI safe)')
|
|
84
83
|
.option('--json', 'Output the InjectResult as JSON');
|
|
@@ -99,7 +98,7 @@ export function registerSessionsInjectCommand(sessionsCmd) {
|
|
|
99
98
|
- A session is addressable by id when it resolves to a precise split —
|
|
100
99
|
tmux, iTerm, a VSCodium/Cursor/VS Code integrated terminal, or a pty
|
|
101
100
|
(resolveInjectTargetForSession). Use --pane/--pty for direct targeting.
|
|
102
|
-
- Built on the Terminal Engine (src/lib/terminal): --
|
|
101
|
+
- Built on the Terminal Engine (src/lib/terminal): --device runs the tmux /
|
|
103
102
|
AppleScript spec over the same SSH transport the launch engine uses.
|
|
104
103
|
`,
|
|
105
104
|
});
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* - ship the transcript with the SAME bundle pipeline as
|
|
16
16
|
* `sessions export --stdout | sessions import -`, over `sshExec`;
|
|
17
17
|
* - resume on the target through the SAME `openSurfaces({ backend:'tmux', host })`
|
|
18
|
-
* path `sessions resume --
|
|
18
|
+
* path `sessions resume --device` uses;
|
|
19
19
|
* - only AFTER the target's prompt is confirmed live, kill the source tmux
|
|
20
20
|
* session (`killSession`). --keep skips the kill (copy, not move).
|
|
21
21
|
*
|
|
@@ -33,9 +33,7 @@ import { getActiveSessions } from '../lib/session/active.js';
|
|
|
33
33
|
import { discoverSessions, resolveSessionById } from '../lib/session/discover.js';
|
|
34
34
|
import { buildResumeCommand } from './sessions.js';
|
|
35
35
|
import { injectTargetFromReplyRail } from '../lib/session/inject.js';
|
|
36
|
-
import { injectIntoTerminal } from '../lib/terminal/index.js';
|
|
37
|
-
import { iLoginShell } from '../lib/terminal/shell.js';
|
|
38
|
-
import { shellQuote as quoteArg } from '../lib/terminal/quote.js';
|
|
36
|
+
import { injectIntoTerminal, iLoginShell, shellQuote as quoteArg } from '../lib/terminal/index.js';
|
|
39
37
|
import { killSession } from '../lib/tmux/session.js';
|
|
40
38
|
import { getDefaultSocketPath } from '../lib/tmux/paths.js';
|
|
41
39
|
import { listAllHosts, resolveHost } from '../lib/hosts/registry.js';
|
|
@@ -57,7 +55,7 @@ export function registerSessionsMigrateCommand(sessionsCmd) {
|
|
|
57
55
|
.alias('relocate')
|
|
58
56
|
.description('Relocate a running session onto another machine (fleet worker, device, or ephemeral box), then stop the source here.')
|
|
59
57
|
.option('--auto', 'Pick the best target host automatically (idle fleet worker preferred)')
|
|
60
|
-
.option('--
|
|
58
|
+
.option('--device <name>', 'Explicit target: an enrolled host, device, or a warm ephemeral box slug')
|
|
61
59
|
.option('--lease', 'Provision a fresh ephemeral crabbox box as the target')
|
|
62
60
|
.option('--mode <mode>', 'rehydrate (default: the target agent reads the transported transcript) or resume (best-effort native --resume)', 'rehydrate')
|
|
63
61
|
.option('--keep', 'Copy, not move — do NOT stop the source after resuming on the target')
|
|
@@ -68,13 +66,13 @@ export function registerSessionsMigrateCommand(sessionsCmd) {
|
|
|
68
66
|
agents sessions migrate --auto
|
|
69
67
|
|
|
70
68
|
# Move a specific session onto a named host
|
|
71
|
-
agents sessions migrate a1b2c3d4 --
|
|
69
|
+
agents sessions migrate a1b2c3d4 --device yosemite-s1
|
|
72
70
|
|
|
73
71
|
# Spin up a fresh ephemeral box and move onto it
|
|
74
72
|
agents sessions migrate --lease
|
|
75
73
|
|
|
76
74
|
# Copy (don't stop the source), letting the agent wrap up its own dirty tree
|
|
77
|
-
agents sessions migrate --
|
|
75
|
+
agents sessions migrate --device box-a --keep --agent-wrapup
|
|
78
76
|
`,
|
|
79
77
|
notes: `
|
|
80
78
|
- Without a [session-id], migrate resolves the session running in THIS tmux pane ($TMUX_PANE).
|
|
@@ -87,17 +85,8 @@ export function registerSessionsMigrateCommand(sessionsCmd) {
|
|
|
87
85
|
- Every migrate appends to the ledger — see 'agents sessions migrations' for where each session went.
|
|
88
86
|
`,
|
|
89
87
|
});
|
|
90
|
-
cmd.action(async (sessionId, options
|
|
91
|
-
|
|
92
|
-
// listing fan-out), which shadows this subcommand's own --host — the value
|
|
93
|
-
// lands in the merged globals, not `options.host`. Read it from there so
|
|
94
|
-
// `agents sessions migrate --host <name>` binds.
|
|
95
|
-
const globals = command.optsWithGlobals();
|
|
96
|
-
const hosts = Array.isArray(globals.host) ? globals.host : globals.host ? [globals.host] : [];
|
|
97
|
-
if (hosts.length > 1) {
|
|
98
|
-
console.error(chalk.yellow(`Multiple --host values given; migrating to the first (${hosts[0]}).`));
|
|
99
|
-
}
|
|
100
|
-
await sessionsMigrateAction(sessionId, { ...options, host: hosts[0] });
|
|
88
|
+
cmd.action(async (sessionId, options) => {
|
|
89
|
+
await sessionsMigrateAction(sessionId, options);
|
|
101
90
|
});
|
|
102
91
|
}
|
|
103
92
|
function fail(message) {
|
|
@@ -141,7 +130,7 @@ function statsByName() {
|
|
|
141
130
|
const cache = readStatsCache();
|
|
142
131
|
return new Map(Object.entries(cache));
|
|
143
132
|
}
|
|
144
|
-
/** Enumerate + rank targets, honoring --
|
|
133
|
+
/** Enumerate + rank targets, honoring --device / --auto / --lease. */
|
|
145
134
|
async function resolveTarget(options, source) {
|
|
146
135
|
const selfHostname = os.hostname();
|
|
147
136
|
const ctx = {
|
|
@@ -162,17 +151,17 @@ async function resolveTarget(options, source) {
|
|
|
162
151
|
warm = []; // crabbox not configured — fleet-only targets
|
|
163
152
|
}
|
|
164
153
|
const stats = statsByName();
|
|
165
|
-
if (options.
|
|
154
|
+
if (options.device) {
|
|
166
155
|
// Explicit target: a fleet host/device, or a warm box slug.
|
|
167
|
-
const box = warm.find((b) => b.slug === options.
|
|
156
|
+
const box = warm.find((b) => b.slug === options.device);
|
|
168
157
|
if (box) {
|
|
169
158
|
return { name: box.slug, kind: 'ephemeral', os: 'linux', headroom: 'unknown', box };
|
|
170
159
|
}
|
|
171
|
-
const host = await resolveHost(options.
|
|
160
|
+
const host = await resolveHost(options.device);
|
|
172
161
|
if (!host)
|
|
173
|
-
fail(`No host, device, or warm box named "${options.
|
|
162
|
+
fail(`No host, device, or warm box named "${options.device}".`);
|
|
174
163
|
if (host.name.toLowerCase() === selfHostname.toLowerCase()) {
|
|
175
|
-
fail(`"${options.
|
|
164
|
+
fail(`"${options.device}" is this machine — migrate needs a different target.`);
|
|
176
165
|
}
|
|
177
166
|
return { name: host.name, kind: 'fleet', os: host.os, headroom: 'unknown', host };
|
|
178
167
|
}
|
|
@@ -186,7 +175,7 @@ async function resolveTarget(options, source) {
|
|
|
186
175
|
}
|
|
187
176
|
// Interactive: rank the candidates and let the user pick.
|
|
188
177
|
if (!isInteractiveTerminal()) {
|
|
189
|
-
fail('Pass --auto, --
|
|
178
|
+
fail('Pass --auto, --device <name>, or --lease to choose a target (no interactive picker without a tty).');
|
|
190
179
|
}
|
|
191
180
|
const ranked = rankTargets(enumerateTargets(hosts, warm, stats, ctx), ctx);
|
|
192
181
|
if (ranked.length === 0) {
|
|
@@ -447,7 +436,7 @@ export function buildMigrateResumeCommands(opts) {
|
|
|
447
436
|
}
|
|
448
437
|
/**
|
|
449
438
|
* Resume the session on the target through the SAME host path as
|
|
450
|
-
* `sessions resume --
|
|
439
|
+
* `sessions resume --device` (tmux backend). Returns true when the resume launched.
|
|
451
440
|
*/
|
|
452
441
|
async function resumeOnTarget(sshTarget, source, remoteCwd, mode) {
|
|
453
442
|
const command = mode === 'resume' ? buildResumeCommand(source) : rehydrateCommand(source);
|
|
@@ -459,7 +448,7 @@ async function resumeOnTarget(sshTarget, source, remoteCwd, mode) {
|
|
|
459
448
|
// box has none ("no server running"), so we create the session (and thus the
|
|
460
449
|
// server) directly with `new-session -d`, mirroring the local `createSession`
|
|
461
450
|
// helper (remain-on-exit keeps the pane inspectable if the agent exits), over
|
|
462
|
-
// the same SSH transport as `sessions resume --
|
|
451
|
+
// the same SSH transport as `sessions resume --device`.
|
|
463
452
|
//
|
|
464
453
|
// Each argv element is quoted BEFORE the zsh -ilc wrapper so a command that
|
|
465
454
|
// carries spaces or backticks (the rehydrate prompt) reaches the agent as one
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SessionEvent, SessionMeta, TodoProgress } from '../lib/session/types.js';
|
|
2
|
+
import { fetchPeerPreviewDigest } from '../lib/session/remote-list.js';
|
|
2
3
|
import { classifyFileChanges, changeCounts, toolHistogram, detectTestResult } from '../lib/session/digest.js';
|
|
3
4
|
import { extractArtifacts, extractHooks, extractLinks, extractSkills } from '../lib/session/highlights.js';
|
|
4
5
|
/**
|
|
@@ -32,6 +33,18 @@ export interface SessionPickerConfig {
|
|
|
32
33
|
/** Lines the caller printed above the prompt (hidden-session footer). */
|
|
33
34
|
linesAbovePrompt?: number;
|
|
34
35
|
}
|
|
36
|
+
export declare function setRemotePreviewRepaint(repaint?: () => void): void;
|
|
37
|
+
export declare function setPeerDigestFetcherForTest(fetcher?: typeof fetchPeerPreviewDigest): void;
|
|
38
|
+
export declare function clearRemoteDigestCacheForTest(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Validate + scrub a peer-supplied preview digest before any of it reaches this
|
|
41
|
+
* terminal. Peer JSON is untrusted at this boundary — the same rule
|
|
42
|
+
* `sanitizeMeta` applies to fan-out rows — so every string is stripped of
|
|
43
|
+
* terminal escapes and every list re-shaped field by field. Anything that
|
|
44
|
+
* doesn't look like the v1 digest is rejected, so a version-skewed peer
|
|
45
|
+
* degrades to the metadata card instead of a corrupted pane.
|
|
46
|
+
*/
|
|
47
|
+
export declare function sanitizeRemoteDigest(raw: unknown): SessionPreviewDigest | undefined;
|
|
35
48
|
export declare function clearPreviewMemoryCacheForTest(): void;
|
|
36
49
|
export declare function loadSessionPreviewDigest(session: SessionMeta): {
|
|
37
50
|
digest?: SessionPreviewDigest;
|
|
@@ -106,5 +119,6 @@ export declare function buildSessionPreviewDigest(events: SessionEvent[], sessio
|
|
|
106
119
|
export declare function directoriesTouched(session: SessionMeta, events: SessionEvent[], changes: ReturnType<typeof classifyFileChanges>): string[];
|
|
107
120
|
/** Relativize a file path to its parent dir, short enough for one preview line. */
|
|
108
121
|
export declare function relativizeDir(filePath: string, cwd?: string): string | undefined;
|
|
122
|
+
export declare function renderLastResponse(content: string, maxLines?: number, width?: number): string[];
|
|
109
123
|
/** Show an interactive session picker and return the selected session with its action (resume or view). */
|
|
110
124
|
export declare function sessionPicker(config: SessionPickerConfig): Promise<PickedSession | null>;
|
|
@@ -9,6 +9,7 @@ import fs from 'node:fs';
|
|
|
9
9
|
import path from 'node:path';
|
|
10
10
|
import chalk from 'chalk';
|
|
11
11
|
import { truncate, humanDuration } from '../lib/format.js';
|
|
12
|
+
import { fetchPeerPreviewDigest } from '../lib/session/remote-list.js';
|
|
12
13
|
import { parseSession, sanitizeForTerminal, SNAPSHOT_TODO_TOOLS } from '../lib/session/parse.js';
|
|
13
14
|
import { safeTeamText } from '../lib/session/team-filter.js';
|
|
14
15
|
import { cleanSessionPrompt, extractSessionTopic, isSyntheticUserMessage } from '../lib/session/prompt.js';
|
|
@@ -16,6 +17,8 @@ import { linkPath, linkUrl, relativeToCwd, shortenModel } from '../lib/session/r
|
|
|
16
17
|
import { linearIssueUrl } from '../lib/session/linear.js';
|
|
17
18
|
import { extractTodoProgress, WORKTREE_RE } from '../lib/session/state.js';
|
|
18
19
|
import { renderMarkdown } from '../lib/markdown.js';
|
|
20
|
+
import { wrapToWidth } from '../lib/wrap.js';
|
|
21
|
+
import { terminalWidth, stringWidth } from '../lib/session/width.js';
|
|
19
22
|
import { itemPicker } from '../lib/picker.js';
|
|
20
23
|
import { createMemoryCache } from '../lib/memory-cache.js';
|
|
21
24
|
import { classifyFileChanges, changeCounts, toolHistogram, detectTestResult } from '../lib/session/digest.js';
|
|
@@ -23,9 +26,10 @@ import { extractArtifacts, extractHooks, extractLinks, extractRepos, extractSkil
|
|
|
23
26
|
import { getSessionPlugins, readSessionPreviewCache, writeSessionPreviewCache, readSessionContent, readArchivedSessionPreview } from '../lib/session/db.js';
|
|
24
27
|
/** A session whose transcript FILE is on another machine (folded in over the
|
|
25
28
|
* live cross-machine fan-out): its `filePath` is on that peer's disk, so the
|
|
26
|
-
* preview can't parse it locally — it
|
|
27
|
-
*
|
|
28
|
-
* mirrors still parse their
|
|
29
|
+
* preview can't parse it locally — it fetches the peer's digest over SSH and
|
|
30
|
+
* shows metadata + a "resume there" note until that lands. Keys off `_remote`,
|
|
31
|
+
* not the machine tag, so locally-readable synced mirrors still parse their
|
|
32
|
+
* file normally.
|
|
29
33
|
*
|
|
30
34
|
* This is the READ rule and only the read rule. Whether a session may be
|
|
31
35
|
* RESUMED here is a different question with a different answer — a mirror is
|
|
@@ -106,6 +110,155 @@ const previewCache = createMemoryCache({
|
|
|
106
110
|
max: 256,
|
|
107
111
|
ttlMs: 5 * 60_000,
|
|
108
112
|
});
|
|
113
|
+
const remoteDigestCache = createMemoryCache({
|
|
114
|
+
max: 256,
|
|
115
|
+
ttlMs: 5 * 60_000,
|
|
116
|
+
});
|
|
117
|
+
function remoteDigestKey(sessionId, machine) {
|
|
118
|
+
return `${machine}:${sessionId}`;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The open picker's repaint trigger. The peer fetch resolves while the pane is
|
|
122
|
+
* already painted, so completion has to nudge the picker into re-rendering —
|
|
123
|
+
* pickers register their trigger here (via `registerPreviewRepaint`) and clear
|
|
124
|
+
* it when they close, making a late fetch after close a no-op.
|
|
125
|
+
*/
|
|
126
|
+
let remotePreviewRepaint;
|
|
127
|
+
export function setRemotePreviewRepaint(repaint) {
|
|
128
|
+
remotePreviewRepaint = repaint;
|
|
129
|
+
}
|
|
130
|
+
/** Seam for tests: the real fetcher opens an SSH connection to the peer. */
|
|
131
|
+
let peerDigestFetcher = fetchPeerPreviewDigest;
|
|
132
|
+
export function setPeerDigestFetcherForTest(fetcher) {
|
|
133
|
+
peerDigestFetcher = fetcher ?? fetchPeerPreviewDigest;
|
|
134
|
+
}
|
|
135
|
+
export function clearRemoteDigestCacheForTest() {
|
|
136
|
+
remoteDigestCache.clear();
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Look up (or start fetching) the peer digest for a remote row. Returns the
|
|
140
|
+
* current entry synchronously — `buildPreview` renders whatever state exists
|
|
141
|
+
* now, and the fetch's completion repaints the pane through the registered
|
|
142
|
+
* trigger.
|
|
143
|
+
*/
|
|
144
|
+
function remoteDigestForPreview(session, machine) {
|
|
145
|
+
const key = remoteDigestKey(session.id, machine);
|
|
146
|
+
const existing = remoteDigestCache.get(key);
|
|
147
|
+
if (existing)
|
|
148
|
+
return existing;
|
|
149
|
+
const pending = { state: 'pending' };
|
|
150
|
+
remoteDigestCache.set(key, pending);
|
|
151
|
+
void peerDigestFetcher(session.id, machine)
|
|
152
|
+
.then((raw) => {
|
|
153
|
+
const digest = sanitizeRemoteDigest(raw);
|
|
154
|
+
remoteDigestCache.set(key, digest ? { state: 'ready', digest } : { state: 'failed' });
|
|
155
|
+
})
|
|
156
|
+
.catch(() => {
|
|
157
|
+
remoteDigestCache.set(key, { state: 'failed' });
|
|
158
|
+
})
|
|
159
|
+
.then(() => remotePreviewRepaint?.());
|
|
160
|
+
return pending;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Validate + scrub a peer-supplied preview digest before any of it reaches this
|
|
164
|
+
* terminal. Peer JSON is untrusted at this boundary — the same rule
|
|
165
|
+
* `sanitizeMeta` applies to fan-out rows — so every string is stripped of
|
|
166
|
+
* terminal escapes and every list re-shaped field by field. Anything that
|
|
167
|
+
* doesn't look like the v1 digest is rejected, so a version-skewed peer
|
|
168
|
+
* degrades to the metadata card instead of a corrupted pane.
|
|
169
|
+
*/
|
|
170
|
+
export function sanitizeRemoteDigest(raw) {
|
|
171
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw))
|
|
172
|
+
return undefined;
|
|
173
|
+
const d = raw;
|
|
174
|
+
if (d.schemaVersion !== 1)
|
|
175
|
+
return undefined;
|
|
176
|
+
const str = (v) => (typeof v === 'string' ? sanitizeForTerminal(v) : '');
|
|
177
|
+
const optStr = (v) => (typeof v === 'string' ? sanitizeForTerminal(v) : undefined);
|
|
178
|
+
const num = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : 0);
|
|
179
|
+
const optNum = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : undefined);
|
|
180
|
+
const strList = (v) => Array.isArray(v) ? v.filter((x) => typeof x === 'string').map(sanitizeForTerminal) : [];
|
|
181
|
+
const objList = (v, map) => Array.isArray(v)
|
|
182
|
+
? v.flatMap((x) => {
|
|
183
|
+
if (!x || typeof x !== 'object' || Array.isArray(x))
|
|
184
|
+
return [];
|
|
185
|
+
const mapped = map(x);
|
|
186
|
+
return mapped === undefined ? [] : [mapped];
|
|
187
|
+
})
|
|
188
|
+
: [];
|
|
189
|
+
let todos;
|
|
190
|
+
if (d.todos && typeof d.todos === 'object' && !Array.isArray(d.todos)) {
|
|
191
|
+
const t = d.todos;
|
|
192
|
+
const items = objList(t.items, (it) => {
|
|
193
|
+
const content = str(it.content ?? it.text);
|
|
194
|
+
if (!content)
|
|
195
|
+
return undefined;
|
|
196
|
+
const status = it.status === 'completed' || it.status === 'in_progress' ? it.status : 'pending';
|
|
197
|
+
return { content, status, activeForm: optStr(it.activeForm) };
|
|
198
|
+
});
|
|
199
|
+
todos = { items, done: num(t.done), total: num(t.total), activeForm: optStr(t.activeForm) };
|
|
200
|
+
}
|
|
201
|
+
const changes = d.changes && typeof d.changes === 'object' && !Array.isArray(d.changes)
|
|
202
|
+
? {
|
|
203
|
+
created: num(d.changes.created),
|
|
204
|
+
modified: num(d.changes.modified),
|
|
205
|
+
deleted: num(d.changes.deleted),
|
|
206
|
+
}
|
|
207
|
+
: { created: 0, modified: 0, deleted: 0 };
|
|
208
|
+
let test;
|
|
209
|
+
if (d.test && typeof d.test === 'object' && !Array.isArray(d.test)) {
|
|
210
|
+
const t = d.test;
|
|
211
|
+
const runner = str(t.runner);
|
|
212
|
+
if (runner) {
|
|
213
|
+
test = { runner, ok: t.ok === true, ts: num(t.ts), passed: optNum(t.passed), failed: optNum(t.failed) };
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
schemaVersion: 1,
|
|
218
|
+
firstUser: str(d.firstUser),
|
|
219
|
+
lastAssistant: str(d.lastAssistant),
|
|
220
|
+
filesRead: num(d.filesRead),
|
|
221
|
+
toolCalls: num(d.toolCalls),
|
|
222
|
+
planFile: str(d.planFile),
|
|
223
|
+
todos,
|
|
224
|
+
subAgentCount: num(d.subAgentCount),
|
|
225
|
+
toolTags: strList(d.toolTags),
|
|
226
|
+
changes,
|
|
227
|
+
dirs: strList(d.dirs),
|
|
228
|
+
repos: strList(d.repos),
|
|
229
|
+
artifacts: objList(d.artifacts, (a) => {
|
|
230
|
+
const p = str(a.path);
|
|
231
|
+
const basename = str(a.basename);
|
|
232
|
+
if (!p || !basename)
|
|
233
|
+
return undefined;
|
|
234
|
+
const bucket = a.bucket === 'artifacts' || a.bucket === 'plans' || a.bucket === 'reports' ? a.bucket : 'docs';
|
|
235
|
+
return { path: p, basename, bucket };
|
|
236
|
+
}),
|
|
237
|
+
skills: objList(d.skills, (s) => {
|
|
238
|
+
const name = str(s.name);
|
|
239
|
+
return name ? { name, count: num(s.count) } : undefined;
|
|
240
|
+
}),
|
|
241
|
+
plugins: strList(d.plugins),
|
|
242
|
+
hooks: objList(d.hooks, (h) => {
|
|
243
|
+
const name = str(h.name);
|
|
244
|
+
return name ? { name, event: optStr(h.event), count: num(h.count), failed: num(h.failed) } : undefined;
|
|
245
|
+
}),
|
|
246
|
+
links: objList(d.links, (l) => {
|
|
247
|
+
const url = str(l.url);
|
|
248
|
+
const label = str(l.label);
|
|
249
|
+
// Only http(s) URLs render as OSC 8 hyperlinks — anything else a peer
|
|
250
|
+
// sends (file:, a bare payload) is dropped rather than linkified.
|
|
251
|
+
return /^https?:\/\//.test(url) && label ? { kind: 'other', url, label } : undefined;
|
|
252
|
+
}),
|
|
253
|
+
errorCount: num(d.errorCount),
|
|
254
|
+
firstError: optStr(d.firstError),
|
|
255
|
+
toolHistogram: objList(d.toolHistogram, (h) => {
|
|
256
|
+
const tool = str(h.tool);
|
|
257
|
+
return tool ? { tool, count: num(h.count) } : undefined;
|
|
258
|
+
}),
|
|
259
|
+
test,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
109
262
|
function previewCacheKey(session, remote) {
|
|
110
263
|
let fileStamp = '';
|
|
111
264
|
if (!remote && session.filePath) {
|
|
@@ -117,10 +270,16 @@ function previewCacheKey(session, remote) {
|
|
|
117
270
|
fileStamp = 'missing';
|
|
118
271
|
}
|
|
119
272
|
}
|
|
273
|
+
// A remote row's rendered pane depends on the fetched digest's state
|
|
274
|
+
// (none → pending → ready/failed), so the state rides the key — otherwise the
|
|
275
|
+
// memoized metadata-only card would keep serving after the digest arrived.
|
|
276
|
+
const remoteDigestState = remote
|
|
277
|
+
? remoteDigestCache.get(remoteDigestKey(session.id, remote))?.state ?? 'none'
|
|
278
|
+
: '';
|
|
120
279
|
// The transcript stamp invalidates derived activity. Metadata that can change
|
|
121
280
|
// independently (label/ticket/PR/live scanner enrichment) also rides the key.
|
|
122
281
|
return JSON.stringify([
|
|
123
|
-
remote ?? '', session.id, fileStamp, session.lastActivity, session.label,
|
|
282
|
+
remote ?? '', remoteDigestState, session.id, fileStamp, session.lastActivity, session.label,
|
|
124
283
|
session.topic, session.ticketId, session.prUrl, session.messageCount,
|
|
125
284
|
session.tokenCount, session.model, session.todos, session.plan,
|
|
126
285
|
session.recentDirectoriesTouched, session.skillsUsed,
|
|
@@ -181,13 +340,26 @@ export function buildPreview(session) {
|
|
|
181
340
|
return cached;
|
|
182
341
|
const safe = sanitizeMeta(session);
|
|
183
342
|
// Remote session: the transcript is on the peer's disk, so there is nothing to
|
|
184
|
-
// parse here.
|
|
185
|
-
//
|
|
343
|
+
// parse here. Fetch the peer's already-computed digest over SSH (kicked off on
|
|
344
|
+
// first render; the pane repaints when it lands) and render the same compact
|
|
345
|
+
// preview a local row gets. Until it arrives — or when the peer can't answer —
|
|
346
|
+
// show the metadata header (agent, cwd, msgs, tokens — all carried over in the
|
|
347
|
+
// fan-out) plus where it lives and how to open it.
|
|
186
348
|
if (remote) {
|
|
187
349
|
const note = ' ' + chalk.gray(`on `) + chalk.bold.white(remote)
|
|
188
350
|
+ chalk.gray(` — enter to resume there, or space then enter to read it over SSH`);
|
|
351
|
+
const entry = remoteDigestForPreview(session, remote);
|
|
352
|
+
if (entry.state === 'ready') {
|
|
353
|
+
const body = formatCompactPreview(entry.digest, safe);
|
|
354
|
+
const output = [formatHeader(safe, []), '', note, body].filter(Boolean).join('\n');
|
|
355
|
+
previewCache.set(cacheKey, output);
|
|
356
|
+
return output;
|
|
357
|
+
}
|
|
358
|
+
const fetching = entry.state === 'pending'
|
|
359
|
+
? ' ' + chalk.gray(`fetching preview from ${remote} over SSH…`)
|
|
360
|
+
: '';
|
|
189
361
|
const metaBody = formatMetaOnlyBody(safe);
|
|
190
|
-
const output = [formatHeader(safe, []), '', note, metaBody].filter(Boolean).join('\n');
|
|
362
|
+
const output = [formatHeader(safe, []), '', note, fetching, metaBody].filter(Boolean).join('\n');
|
|
191
363
|
previewCache.set(cacheKey, output);
|
|
192
364
|
return output;
|
|
193
365
|
}
|
|
@@ -265,8 +437,6 @@ function formatHeader(session, events) {
|
|
|
265
437
|
if (totalTokens !== undefined) {
|
|
266
438
|
line3.push(chalk.bold.white(formatTokens(totalTokens)) + chalk.gray(' tokens'));
|
|
267
439
|
}
|
|
268
|
-
if (session.label)
|
|
269
|
-
line3.push(chalk.white(session.label));
|
|
270
440
|
if (session.filePath)
|
|
271
441
|
line3.push(chalk.gray(linkPath(session.filePath, session.id)));
|
|
272
442
|
else
|
|
@@ -282,7 +452,19 @@ function formatHeader(session, events) {
|
|
|
282
452
|
const label = session.prNumber ? `PR#${session.prNumber}` : 'PR';
|
|
283
453
|
line4.push(chalk.blue(linkUrl(session.prUrl, label)));
|
|
284
454
|
}
|
|
455
|
+
// Lead with the session's human title: `session.label` — an agent-generated
|
|
456
|
+
// name / `/rename`, else the `--name` launch handle. NOT `session.topic`: the
|
|
457
|
+
// topic is the derived first-prompt, already shown on the `Prompt:` line, so
|
|
458
|
+
// using it here too would print the same text twice. Unlabelled sessions keep
|
|
459
|
+
// that `Prompt:` line as their topic indicator and simply lead with the agent
|
|
460
|
+
// line. Wrapped to the pane (the header sits at column 0, full terminal width);
|
|
461
|
+
// nothing renders when there is no label.
|
|
462
|
+
const title = (session.label || '').trim();
|
|
463
|
+
const titleLines = title
|
|
464
|
+
? wrapToWidth(title, terminalWidth()).map(l => chalk.bold.white(l))
|
|
465
|
+
: [];
|
|
285
466
|
return [
|
|
467
|
+
...titleLines,
|
|
286
468
|
line1.join(DOT),
|
|
287
469
|
line2.join(DOT),
|
|
288
470
|
line3.join(DOT),
|
|
@@ -651,7 +833,9 @@ function formatCompactPreview(digest, session) {
|
|
|
651
833
|
}
|
|
652
834
|
if (lastAssistant) {
|
|
653
835
|
const maxLines = todosRendered.length > 0 || compact ? LAST_RESPONSE_MAX_LINES_WITH_TODOS : LAST_RESPONSE_MAX_LINES;
|
|
654
|
-
|
|
836
|
+
// Content sits at column 4 (outer body indent + the ' ' prefix below), so
|
|
837
|
+
// wrap it to the pane minus that indent.
|
|
838
|
+
const rendered = renderLastResponse(lastAssistant, maxLines, terminalWidth() - 4);
|
|
655
839
|
if (rendered.length > 0) {
|
|
656
840
|
lines.push('');
|
|
657
841
|
lines.push(chalk.cyan('Last response:'));
|
|
@@ -829,7 +1013,7 @@ export function relativizeDir(filePath, cwd) {
|
|
|
829
1013
|
dir = parts.slice(-3).join('/');
|
|
830
1014
|
return dir || undefined;
|
|
831
1015
|
}
|
|
832
|
-
function renderLastResponse(content, maxLines = LAST_RESPONSE_MAX_LINES) {
|
|
1016
|
+
export function renderLastResponse(content, maxLines = LAST_RESPONSE_MAX_LINES, width = terminalWidth()) {
|
|
833
1017
|
const cleaned = stripTags(content).trim();
|
|
834
1018
|
if (!cleaned)
|
|
835
1019
|
return [];
|
|
@@ -840,7 +1024,15 @@ function renderLastResponse(content, maxLines = LAST_RESPONSE_MAX_LINES) {
|
|
|
840
1024
|
catch {
|
|
841
1025
|
rendered = cleaned;
|
|
842
1026
|
}
|
|
843
|
-
|
|
1027
|
+
// `marked-terminal` runs with `reflowText` off, so a paragraph with no hard
|
|
1028
|
+
// breaks renders as one long line that overflows the pane. Wrap any line whose
|
|
1029
|
+
// VISIBLE width exceeds the budget; leave lines that already fit untouched so
|
|
1030
|
+
// rendered-markdown indentation (lists, code blocks) is preserved. The text is
|
|
1031
|
+
// ANSI-coloured, so width is measured with `stringWidth`, never `String.length`.
|
|
1032
|
+
const all = rendered
|
|
1033
|
+
.replace(/\s+$/, '')
|
|
1034
|
+
.split('\n')
|
|
1035
|
+
.flatMap(line => (stringWidth(line) <= width ? [line] : wrapToWidth(line, width)));
|
|
844
1036
|
// Drop leading/trailing empty lines
|
|
845
1037
|
while (all.length && !all[0].trim())
|
|
846
1038
|
all.shift();
|
|
@@ -895,13 +1087,17 @@ export async function sessionPicker(config) {
|
|
|
895
1087
|
filter: config.filter,
|
|
896
1088
|
labelFor: config.labelFor,
|
|
897
1089
|
buildPreview,
|
|
1090
|
+
// A remote row's digest arrives over SSH after the pane painted — this is
|
|
1091
|
+
// what lets its completion swap the metadata card for the full preview.
|
|
1092
|
+
registerPreviewRepaint: setRemotePreviewRepaint,
|
|
898
1093
|
shortIdFor: (s) => s.shortId,
|
|
899
1094
|
pageSize: config.pageSize,
|
|
900
1095
|
initialSearch: config.initialSearch,
|
|
901
1096
|
emptyMessage: 'No sessions match.',
|
|
902
1097
|
enterHint: config.enterHint ?? 'resume',
|
|
903
1098
|
linesAbovePrompt: config.linesAbovePrompt,
|
|
904
|
-
|
|
1099
|
+
// A late digest fetch must not poke a closed prompt.
|
|
1100
|
+
}).finally(() => setRemotePreviewRepaint(undefined));
|
|
905
1101
|
if (!picked)
|
|
906
1102
|
return null;
|
|
907
1103
|
return { session: picked.item, action: 'resume' };
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import type { Command } from 'commander';
|
|
2
2
|
import { type SessionMeta } from '../lib/session/types.js';
|
|
3
3
|
import { type Backend, type EngineContext, type Packing } from '../lib/terminal/index.js';
|
|
4
|
+
import { type StrictResumeOptions } from './resume.js';
|
|
4
5
|
/** Opening more than this many live sessions at once asks for confirmation first. */
|
|
5
6
|
export declare const CONFIRM_THRESHOLD = 5;
|
|
6
|
-
export interface ResumeOptions {
|
|
7
|
+
export interface ResumeOptions extends StrictResumeOptions {
|
|
7
8
|
agent?: string;
|
|
8
9
|
all?: boolean;
|
|
9
10
|
teams?: boolean;
|
|
10
11
|
since?: string;
|
|
11
12
|
limit?: string;
|
|
12
|
-
|
|
13
|
+
device?: string;
|
|
13
14
|
iterm?: boolean;
|
|
14
15
|
ghostty?: boolean;
|
|
15
16
|
tmux?: boolean;
|
|
@@ -24,12 +25,15 @@ export declare function registerSessionsResumeCommand(sessionsCmd: Command): voi
|
|
|
24
25
|
/** IDs and tmux aliases are actions, not picker search text. Human phrases keep
|
|
25
26
|
* the existing pre-filtered picker, while an explicit identity resumes directly. */
|
|
26
27
|
export declare function isDirectResumeSelector(query: string): boolean;
|
|
27
|
-
/** Re-enter through
|
|
28
|
+
/** Re-enter through sessions resume so fleet routing and harness policy
|
|
28
29
|
* stay centralized. The child inherits this terminal for a real interactive resume. */
|
|
29
30
|
export declare function resumeSelectorInPlace(selector: string): Promise<void>;
|
|
30
31
|
/** Direct identities use focus as the lifecycle dispatcher: it rechecks the
|
|
31
32
|
* live fleet, attaches a healthy pane, and falls through to `agents resume`
|
|
32
33
|
* only when the process is no longer attachable. */
|
|
34
|
+
/** True when `sessions resume <id> --attach-only|--local` must go through
|
|
35
|
+
* `sessions focus` instead of `runStrictResume` (which can fork a copy). */
|
|
36
|
+
export declare function resumeUsesLifecycleDispatch(query: string | undefined, prompt: string | undefined, options: Pick<ResumeOptions, 'attachOnly' | 'local' | 'mode' | 'interactive' | 'headless' | 'here'>): boolean;
|
|
33
37
|
export declare function dispatchSessionLifecycleInPlace(selector: string, hosts?: string[], attachOnly?: boolean, local?: boolean): Promise<void>;
|
|
34
38
|
export declare function buildSessionLifecycleArgs(selector: string, hosts?: string[], attachOnly?: boolean, local?: boolean): string[];
|
|
35
39
|
export declare function resolveResumePacking(options: Pick<ResumeOptions, 'splits'>): Packing;
|