@phnx-labs/agents-cli 1.22.120 → 1.22.121
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 +227 -0
- package/README.md +19 -2
- package/dist/bootstrap.d.ts +0 -15
- package/dist/bootstrap.js +10 -409
- package/dist/cli/command-registry.d.ts +0 -58
- package/dist/cli/command-registry.js +2 -74
- package/dist/commands/accounts.d.ts +0 -17
- package/dist/commands/accounts.js +1 -52
- package/dist/commands/alias.d.ts +0 -12
- package/dist/commands/alias.js +0 -6
- package/dist/commands/apply.d.ts +0 -15
- package/dist/commands/apply.js +0 -63
- package/dist/commands/audit.d.ts +0 -12
- package/dist/commands/audit.js +0 -13
- package/dist/commands/auth.js +4 -12
- package/dist/commands/beta.d.ts +0 -6
- package/dist/commands/beta.js +2 -6
- package/dist/commands/browser-sessions-picker.d.ts +0 -8
- package/dist/commands/browser-sessions-picker.js +0 -26
- package/dist/commands/browser.d.ts +0 -57
- package/dist/commands/browser.js +0 -80
- package/dist/commands/budget.d.ts +0 -13
- package/dist/commands/budget.js +0 -2
- package/dist/commands/cli.d.ts +0 -12
- package/dist/commands/cli.js +0 -4
- package/dist/commands/cloud.d.ts +0 -9
- package/dist/commands/cloud.js +0 -43
- package/dist/commands/commands.d.ts +0 -9
- package/dist/commands/commands.js +0 -18
- package/dist/commands/computer-sessions-picker.d.ts +0 -11
- package/dist/commands/computer-sessions-picker.js +0 -29
- package/dist/commands/computer.d.ts +0 -62
- package/dist/commands/computer.js +3 -114
- package/dist/commands/config.d.ts +0 -14
- package/dist/commands/config.js +21 -60
- package/dist/commands/cost.d.ts +0 -11
- package/dist/commands/cost.js +1 -17
- package/dist/commands/daemon-test-harness.d.ts +0 -32
- package/dist/commands/daemon-test-harness.js +1 -36
- package/dist/commands/daemon.d.ts +0 -46
- package/dist/commands/daemon.js +8 -255
- package/dist/commands/detach-core.d.ts +0 -28
- package/dist/commands/detach-core.js +0 -30
- package/dist/commands/detach.d.ts +1 -12
- package/dist/commands/detach.js +16 -52
- package/dist/commands/device-config-test-harness.js +0 -12
- package/dist/commands/doctor.d.ts +0 -103
- package/dist/commands/doctor.js +3 -279
- package/dist/commands/events.d.ts +0 -29
- package/dist/commands/events.js +1 -55
- package/dist/commands/exec.d.ts +0 -163
- package/dist/commands/exec.js +15 -964
- package/dist/commands/factory.d.ts +0 -6
- package/dist/commands/factory.js +0 -2
- package/dist/commands/feed-watch.js +0 -20
- package/dist/commands/feed.d.ts +0 -38
- package/dist/commands/feed.js +1 -151
- package/dist/commands/feedback.d.ts +0 -5
- package/dist/commands/feedback.js +0 -5
- package/dist/commands/fleet-capture.d.ts +0 -12
- package/dist/commands/fleet-capture.js +1 -39
- package/dist/commands/focus.d.ts +6 -94
- package/dist/commands/focus.js +13 -183
- package/dist/commands/fork.d.ts +0 -21
- package/dist/commands/fork.js +0 -45
- package/dist/commands/funnel.d.ts +0 -3
- package/dist/commands/go.d.ts +2 -71
- package/dist/commands/go.js +5 -99
- package/dist/commands/harness-hooks.d.ts +0 -41
- package/dist/commands/harness-hooks.js +0 -48
- package/dist/commands/harness-wizard.d.ts +0 -137
- package/dist/commands/harness-wizard.js +0 -109
- package/dist/commands/harness.d.ts +0 -63
- package/dist/commands/harness.js +0 -103
- package/dist/commands/hooks.d.ts +0 -9
- package/dist/commands/hooks.js +0 -26
- package/dist/commands/humans.d.ts +0 -8
- package/dist/commands/humans.js +0 -8
- package/dist/commands/import.d.ts +0 -22
- package/dist/commands/import.js +0 -79
- package/dist/commands/insights.d.ts +0 -37
- package/dist/commands/insights.js +3 -115
- package/dist/commands/inspect.d.ts +0 -117
- package/dist/commands/inspect.js +2 -448
- package/dist/commands/lease.d.ts +0 -28
- package/dist/commands/lease.js +0 -43
- package/dist/commands/logs.d.ts +0 -23
- package/dist/commands/logs.js +0 -30
- package/dist/commands/mailboxes.d.ts +0 -18
- package/dist/commands/mailboxes.js +0 -29
- package/dist/commands/mcp.d.ts +0 -9
- package/dist/commands/mcp.js +0 -53
- package/dist/commands/memory.d.ts +0 -7
- package/dist/commands/memory.js +0 -7
- package/dist/commands/menubar.d.ts +0 -8
- package/dist/commands/menubar.js +0 -24
- package/dist/commands/message.d.ts +0 -23
- package/dist/commands/message.js +0 -50
- package/dist/commands/mine.d.ts +0 -22
- package/dist/commands/mine.js +0 -21
- package/dist/commands/models.d.ts +0 -8
- package/dist/commands/models.js +0 -33
- package/dist/commands/modes.d.ts +0 -10
- package/dist/commands/modes.js +0 -13
- package/dist/commands/monitors.d.ts +0 -9
- package/dist/commands/monitors.js +3 -160
- package/dist/commands/open.d.ts +0 -26
- package/dist/commands/open.js +0 -10
- package/dist/commands/output.d.ts +0 -18
- package/dist/commands/output.js +1 -34
- package/dist/commands/packages-materialize.d.ts +0 -11
- package/dist/commands/packages-materialize.js +0 -3
- package/dist/commands/packages.d.ts +0 -10
- package/dist/commands/packages.js +0 -50
- package/dist/commands/perf.d.ts +0 -41
- package/dist/commands/perf.js +0 -55
- package/dist/commands/permissions.d.ts +0 -9
- package/dist/commands/permissions.js +0 -43
- package/dist/commands/plugins.d.ts +0 -14
- package/dist/commands/plugins.js +2 -55
- package/dist/commands/profiles.d.ts +0 -25
- package/dist/commands/profiles.js +0 -27
- package/dist/commands/projects-todo.d.ts +2 -0
- package/dist/commands/projects-todo.js +132 -0
- package/dist/commands/projects.d.ts +0 -85
- package/dist/commands/projects.js +344 -291
- package/dist/commands/prune.js +0 -30
- package/dist/commands/ps-roster.d.ts +92 -0
- package/dist/commands/ps-roster.js +744 -0
- package/dist/commands/ps.d.ts +6 -0
- package/dist/commands/ps.js +98 -0
- package/dist/commands/refresh-rules.d.ts +0 -13
- package/dist/commands/refresh-rules.js +0 -14
- package/dist/commands/reminders.d.ts +0 -7
- package/dist/commands/repo.d.ts +0 -89
- package/dist/commands/repo.js +7 -205
- package/dist/commands/resource-view.d.ts +0 -33
- package/dist/commands/resource-view.js +0 -49
- package/dist/commands/resume.d.ts +1 -19
- package/dist/commands/resume.js +0 -50
- package/dist/commands/route.d.ts +0 -10
- package/dist/commands/route.js +0 -19
- package/dist/commands/routines.d.ts +0 -42
- package/dist/commands/routines.js +5 -290
- package/dist/commands/routines.test-fixture.d.ts +0 -34
- package/dist/commands/routines.test-fixture.js +4 -100
- package/dist/commands/rules.d.ts +0 -9
- package/dist/commands/rules.js +1 -6
- package/dist/commands/run-account-picker.d.ts +0 -59
- package/dist/commands/run-account-picker.js +0 -71
- package/dist/commands/run-broadcast.d.ts +0 -9
- package/dist/commands/run-broadcast.js +0 -7
- package/dist/commands/run-cloud.d.ts +0 -15
- package/dist/commands/run-cloud.js +0 -37
- package/dist/commands/run-device-picker.d.ts +0 -25
- package/dist/commands/run-device-picker.js +1 -53
- package/dist/commands/secrets-passthrough.d.ts +0 -31
- package/dist/commands/secrets-passthrough.js +0 -10
- package/dist/commands/send.d.ts +0 -20
- package/dist/commands/send.js +14 -18
- package/dist/commands/sessions-backfill.d.ts +0 -7
- package/dist/commands/sessions-backfill.js +1 -16
- package/dist/commands/sessions-backup-setup.js +0 -11
- package/dist/commands/sessions-bookmark.d.ts +0 -8
- package/dist/commands/sessions-bookmark.js +0 -28
- package/dist/commands/sessions-browser.d.ts +2 -117
- package/dist/commands/sessions-browser.js +5 -243
- package/dist/commands/sessions-export.d.ts +1 -26
- package/dist/commands/sessions-export.js +3 -81
- package/dist/commands/sessions-import.d.ts +0 -14
- package/dist/commands/sessions-import.js +0 -59
- package/dist/commands/sessions-inject.d.ts +0 -60
- package/dist/commands/sessions-inject.js +3 -96
- package/dist/commands/sessions-migrate.d.ts +2 -37
- package/dist/commands/sessions-migrate.js +7 -159
- package/dist/commands/sessions-optimize.d.ts +0 -12
- package/dist/commands/sessions-picker-factory.d.ts +0 -7
- package/dist/commands/sessions-picker-factory.js +0 -8
- package/dist/commands/sessions-picker.d.ts +4 -103
- package/dist/commands/sessions-picker.js +13 -352
- package/dist/commands/sessions-render.d.ts +1 -2
- package/dist/commands/sessions-render.js +3 -7
- package/dist/commands/sessions-resume.d.ts +1 -24
- package/dist/commands/sessions-resume.js +2 -65
- package/dist/commands/sessions-share.d.ts +1 -9
- package/dist/commands/sessions-share.js +1 -45
- package/dist/commands/sessions-stats.d.ts +0 -24
- package/dist/commands/sessions-stats.js +0 -49
- package/dist/commands/sessions-stop.d.ts +1 -20
- package/dist/commands/sessions-stop.js +4 -9
- package/dist/commands/sessions-tail.d.ts +1 -19
- package/dist/commands/sessions-tail.js +3 -36
- package/dist/commands/sessions-trace.d.ts +5 -36
- package/dist/commands/sessions-trace.js +7 -82
- package/dist/commands/sessions.d.ts +1 -666
- package/dist/commands/sessions.js +30 -2279
- package/dist/commands/sessions.test-fixture.d.ts +0 -9
- package/dist/commands/sessions.test-fixture.js +8 -23
- package/dist/commands/setup-accounts.d.ts +0 -6
- package/dist/commands/setup-browser.d.ts +0 -23
- package/dist/commands/setup-browser.js +0 -28
- package/dist/commands/setup-computer.d.ts +0 -16
- package/dist/commands/setup-computer.js +0 -28
- package/dist/commands/setup-fleet.d.ts +0 -8
- package/dist/commands/setup-fleet.js +0 -11
- package/dist/commands/setup-mine.d.ts +0 -14
- package/dist/commands/setup-mine.js +0 -25
- package/dist/commands/setup-preferences.d.ts +0 -47
- package/dist/commands/setup-preferences.js +0 -53
- package/dist/commands/setup-secrets.d.ts +2 -24
- package/dist/commands/setup-secrets.js +0 -24
- package/dist/commands/setup-term.d.ts +0 -21
- package/dist/commands/setup-term.js +0 -21
- package/dist/commands/setup-terminal.d.ts +0 -1
- package/dist/commands/setup-terminal.js +0 -1
- package/dist/commands/setup-tools.d.ts +2 -0
- package/dist/commands/setup-tools.js +73 -0
- package/dist/commands/setup.d.ts +0 -20
- package/dist/commands/setup.js +4 -57
- package/dist/commands/skills.d.ts +0 -9
- package/dist/commands/skills.js +1 -22
- package/dist/commands/snapshot.d.ts +0 -9
- package/dist/commands/snapshot.js +0 -10
- package/dist/commands/ssh.d.ts +0 -64
- package/dist/commands/ssh.js +9 -420
- package/dist/commands/status.d.ts +0 -12
- package/dist/commands/status.js +0 -26
- package/dist/commands/subagents.d.ts +0 -8
- package/dist/commands/subagents.js +0 -31
- package/dist/commands/sync.d.ts +0 -37
- package/dist/commands/sync.js +0 -256
- package/dist/commands/teams-picker.d.ts +0 -3
- package/dist/commands/teams-picker.js +0 -34
- package/dist/commands/teams.d.ts +1 -76
- package/dist/commands/teams.js +9 -477
- package/dist/commands/tmux.d.ts +0 -25
- package/dist/commands/tmux.js +0 -46
- package/dist/commands/traces.js +0 -19
- package/dist/commands/trash.d.ts +0 -17
- package/dist/commands/trash.js +1 -11
- package/dist/commands/uninstall.d.ts +0 -9
- package/dist/commands/uninstall.js +0 -6
- package/dist/commands/update.d.ts +0 -22
- package/dist/commands/update.js +0 -44
- package/dist/commands/upgrade.d.ts +0 -1
- package/dist/commands/upgrade.js +0 -1
- package/dist/commands/utils.d.ts +0 -85
- package/dist/commands/utils.js +1 -95
- package/dist/commands/versions.d.ts +0 -16
- package/dist/commands/versions.js +0 -134
- package/dist/commands/view.d.ts +0 -90
- package/dist/commands/view.js +4 -343
- package/dist/commands/watchdog.d.ts +0 -19
- package/dist/commands/watchdog.js +3 -43
- package/dist/commands/webhook.d.ts +0 -8
- package/dist/commands/webhook.js +0 -14
- package/dist/commands/workflows.d.ts +0 -8
- package/dist/commands/workflows.js +0 -6
- package/dist/index.d.ts +0 -25
- package/dist/index.js +5 -119
- package/dist/lib/account-capabilities.d.ts +0 -34
- package/dist/lib/account-capabilities.js +0 -32
- package/dist/lib/account-catalog.d.ts +0 -128
- package/dist/lib/account-catalog.js +8 -154
- package/dist/lib/account-provider-registry.d.ts +0 -14
- package/dist/lib/account-provider-registry.js +0 -8
- package/dist/lib/account-registry.d.ts +0 -74
- package/dist/lib/account-registry.js +14 -189
- package/dist/lib/account-schema.d.ts +0 -19
- package/dist/lib/account-schema.js +0 -43
- package/dist/lib/accounting/account-launch.d.ts +0 -15
- package/dist/lib/accounting/account-launch.js +1 -3
- package/dist/lib/accounting/account-pool-collect.d.ts +0 -26
- package/dist/lib/accounting/account-pool-collect.js +0 -42
- package/dist/lib/accounting/account-pool.d.ts +0 -41
- package/dist/lib/accounting/account-pool.js +0 -17
- package/dist/lib/accounting/capacity.d.ts +0 -32
- package/dist/lib/accounting/capacity.js +0 -32
- package/dist/lib/accounting/rotate.d.ts +0 -518
- package/dist/lib/accounting/rotate.js +4 -598
- package/dist/lib/accounting/usage-ingest.d.ts +0 -1
- package/dist/lib/accounting/usage-ingest.js +0 -44
- package/dist/lib/accounting/usage-sync.d.ts +0 -60
- package/dist/lib/accounting/usage-sync.js +4 -51
- package/dist/lib/accounting/usage.d.ts +0 -632
- package/dist/lib/accounting/usage.js +14 -1055
- package/dist/lib/accounts/add.d.ts +0 -60
- package/dist/lib/accounts/add.js +0 -127
- package/dist/lib/accounts/auth-operation-lock.d.ts +0 -1
- package/dist/lib/accounts/auth-operation-lock.js +0 -4
- package/dist/lib/accounts/migrate.d.ts +0 -9
- package/dist/lib/accounts/migrate.js +3 -42
- package/dist/lib/accounts/slots.d.ts +0 -25
- package/dist/lib/accounts/slots.js +1 -49
- package/dist/lib/acp/client.d.ts +0 -16
- package/dist/lib/acp/client.js +0 -29
- package/dist/lib/acp/harnesses.d.ts +0 -15
- package/dist/lib/acp/harnesses.js +0 -16
- package/dist/lib/acp/run.d.ts +0 -8
- package/dist/lib/acp/run.js +0 -8
- package/dist/lib/actor.d.ts +1 -71
- package/dist/lib/actor.js +1 -99
- package/dist/lib/add-dir.d.ts +0 -46
- package/dist/lib/add-dir.js +1 -70
- package/dist/lib/address.d.ts +0 -17
- package/dist/lib/address.js +0 -15
- package/dist/lib/agent-cli-commands.d.ts +0 -10
- package/dist/lib/agent-cli-commands.js +0 -10
- package/dist/lib/agent-modes.d.ts +0 -29
- package/dist/lib/agent-modes.js +0 -31
- package/dist/lib/agent-spec/agents.d.ts +0 -426
- package/dist/lib/agent-spec/agents.js +37 -924
- package/dist/lib/agent-spec/index.d.ts +0 -5
- package/dist/lib/agent-spec/index.js +0 -14
- package/dist/lib/agent-spec/materialize.d.ts +0 -10
- package/dist/lib/agent-spec/materialize.js +2 -139
- package/dist/lib/agent-spec/package-resolve.d.ts +0 -8
- package/dist/lib/agent-spec/package-resolve.js +1 -44
- package/dist/lib/agent-spec/package-schema.d.ts +0 -2
- package/dist/lib/agent-spec/package-schema.js +0 -11
- package/dist/lib/agent-spec/package-types.d.ts +0 -27
- package/dist/lib/agent-spec/package-types.js +0 -1
- package/dist/lib/agent-spec/primitives.d.ts +0 -18
- package/dist/lib/agent-spec/primitives.js +0 -27
- package/dist/lib/agent-spec/provider.js +0 -2
- package/dist/lib/agent-spec/resolve.d.ts +0 -23
- package/dist/lib/agent-spec/resolve.js +0 -41
- package/dist/lib/agent-spec/types.d.ts +0 -34
- package/dist/lib/agent-spec/types.js +0 -6
- package/dist/lib/agents.d.ts +0 -1
- package/dist/lib/agents.js +0 -1
- package/dist/lib/analytics/mix-commands.d.ts +0 -23
- package/dist/lib/analytics/mix-commands.js +0 -26
- package/dist/lib/analytics/recipes.d.ts +0 -1
- package/dist/lib/analytics/recipes.js +5 -10
- package/dist/lib/analytics/usage-db.js +4 -6
- package/dist/lib/answer-router.d.ts +0 -61
- package/dist/lib/answer-router.js +0 -57
- package/dist/lib/app-bundle-install.d.ts +0 -13
- package/dist/lib/app-bundle-install.js +0 -50
- package/dist/lib/artifact-actions.d.ts +0 -15
- package/dist/lib/artifact-actions.js +0 -18
- package/dist/lib/artifacts-client.d.ts +0 -10
- package/dist/lib/artifacts-client.js +0 -17
- package/dist/lib/ask-classifier.d.ts +0 -38
- package/dist/lib/ask-classifier.js +0 -27
- package/dist/lib/audit/log.d.ts +0 -47
- package/dist/lib/audit/log.js +1 -59
- package/dist/lib/auth-health.d.ts +0 -213
- package/dist/lib/auth-health.js +16 -266
- package/dist/lib/auth-mint.d.ts +0 -83
- package/dist/lib/auth-mint.js +8 -85
- package/dist/lib/auto-pull-worker.d.ts +0 -10
- package/dist/lib/auto-pull-worker.js +3 -48
- package/dist/lib/auto-pull.d.ts +0 -64
- package/dist/lib/auto-pull.js +0 -79
- package/dist/lib/beta.d.ts +0 -9
- package/dist/lib/beta.js +0 -9
- package/dist/lib/binary-shadow.d.ts +0 -22
- package/dist/lib/binary-shadow.js +4 -34
- package/dist/lib/boot-profile.d.ts +0 -10
- package/dist/lib/boot-profile.js +1 -31
- package/dist/lib/brand.d.ts +0 -20
- package/dist/lib/brand.js +0 -50
- package/dist/lib/browser/context.d.ts +0 -54
- package/dist/lib/browser/context.js +0 -49
- package/dist/lib/browser/paths.d.ts +0 -21
- package/dist/lib/browser/paths.js +0 -26
- package/dist/lib/browser/record.d.ts +0 -34
- package/dist/lib/browser/record.js +0 -38
- package/dist/lib/browser/sessions-list.d.ts +1 -79
- package/dist/lib/browser/sessions-list.js +2 -98
- package/dist/lib/browser-client.d.ts +0 -112
- package/dist/lib/browser-client.js +1 -90
- package/dist/lib/budget/config.d.ts +0 -6
- package/dist/lib/budget/config.js +0 -29
- package/dist/lib/budget/enforce.d.ts +0 -50
- package/dist/lib/budget/enforce.js +0 -27
- package/dist/lib/budget/ledger.d.ts +0 -23
- package/dist/lib/budget/ledger.js +0 -28
- package/dist/lib/budget/live-cloud.d.ts +0 -26
- package/dist/lib/budget/live-cloud.js +0 -12
- package/dist/lib/budget/live-team.d.ts +0 -17
- package/dist/lib/budget/live-team.js +1 -35
- package/dist/lib/budget/preflight.d.ts +0 -51
- package/dist/lib/budget/preflight.js +0 -36
- package/dist/lib/byok-usage.d.ts +0 -20
- package/dist/lib/byok-usage.js +1 -24
- package/dist/lib/capabilities.d.ts +0 -24
- package/dist/lib/capabilities.js +0 -29
- package/dist/lib/catchup.d.ts +0 -87
- package/dist/lib/catchup.js +1 -81
- package/dist/lib/channels/owner-forward.d.ts +0 -70
- package/dist/lib/channels/owner-forward.js +1 -43
- package/dist/lib/channels/owner-sink.js +0 -21
- package/dist/lib/channels/providers/desktop.d.ts +0 -37
- package/dist/lib/channels/providers/desktop.js +0 -72
- package/dist/lib/channels/providers/index.d.ts +0 -1
- package/dist/lib/channels/providers/index.js +2 -6
- package/dist/lib/channels/providers/mailbox.js +0 -7
- package/dist/lib/channels/providers/openclaw-telegram.js +0 -8
- package/dist/lib/channels/providers/rush.d.ts +0 -2
- package/dist/lib/channels/providers/rush.js +0 -26
- package/dist/lib/channels/providers/session.d.ts +2 -0
- package/dist/lib/channels/providers/session.js +26 -0
- package/dist/lib/channels/registry.d.ts +0 -27
- package/dist/lib/channels/registry.js +0 -10
- package/dist/lib/channels/resolve.d.ts +0 -19
- package/dist/lib/channels/resolve.js +0 -2
- package/dist/lib/channels/send.d.ts +0 -50
- package/dist/lib/channels/send.js +0 -25
- package/dist/lib/checkpoint.d.ts +0 -36
- package/dist/lib/checkpoint.js +0 -28
- package/dist/lib/claude-account-token.d.ts +0 -98
- package/dist/lib/claude-account-token.js +7 -169
- package/dist/lib/claude-statusline.d.ts +0 -41
- package/dist/lib/claude-statusline.js +0 -68
- package/dist/lib/cli-entry.d.ts +0 -26
- package/dist/lib/cli-entry.js +1 -61
- package/dist/lib/cli-resources.d.ts +31 -89
- package/dist/lib/cli-resources.js +116 -152
- package/dist/lib/cloud/antigravity.d.ts +0 -29
- package/dist/lib/cloud/antigravity.js +0 -36
- package/dist/lib/cloud/codex.d.ts +0 -8
- package/dist/lib/cloud/codex.js +0 -41
- package/dist/lib/cloud/cursor.d.ts +0 -5
- package/dist/lib/cloud/cursor.js +2 -7
- package/dist/lib/cloud/dispatch.d.ts +0 -13
- package/dist/lib/cloud/dispatch.js +1 -48
- package/dist/lib/cloud/factory.d.ts +0 -52
- package/dist/lib/cloud/factory.js +3 -67
- package/dist/lib/cloud/host.d.ts +0 -39
- package/dist/lib/cloud/host.js +5 -48
- package/dist/lib/cloud/registry.d.ts +0 -25
- package/dist/lib/cloud/registry.js +0 -29
- package/dist/lib/cloud/rush.d.ts +0 -47
- package/dist/lib/cloud/rush.js +1 -82
- package/dist/lib/cloud/session-index.d.ts +0 -27
- package/dist/lib/cloud/session-index.js +1 -32
- package/dist/lib/cloud/store.d.ts +0 -18
- package/dist/lib/cloud/store.js +0 -28
- package/dist/lib/cloud/stream.d.ts +0 -14
- package/dist/lib/cloud/stream.js +0 -25
- package/dist/lib/cloud/types.d.ts +0 -168
- package/dist/lib/cloud/types.js +0 -46
- package/dist/lib/cloudflare/creds.d.ts +0 -2
- package/dist/lib/cloudflare/creds.js +0 -14
- package/dist/lib/cloudflare/provision.d.ts +0 -8
- package/dist/lib/cloudflare/provision.js +1 -19
- package/dist/lib/codex-home.d.ts +0 -60
- package/dist/lib/codex-home.js +2 -72
- package/dist/lib/codex-policy.d.ts +0 -10
- package/dist/lib/codex-policy.js +0 -13
- package/dist/lib/command-skills.d.ts +0 -10
- package/dist/lib/command-skills.js +0 -10
- package/dist/lib/commands.d.ts +0 -74
- package/dist/lib/commands.js +0 -112
- package/dist/lib/comms-render.d.ts +0 -5
- package/dist/lib/comms-render.js +0 -5
- package/dist/lib/computer/context.d.ts +0 -23
- package/dist/lib/computer/context.js +0 -14
- package/dist/lib/computer/policy.d.ts +0 -20
- package/dist/lib/computer/policy.js +0 -53
- package/dist/lib/computer/record.d.ts +0 -33
- package/dist/lib/computer/record.js +1 -48
- package/dist/lib/computer/sessions-list.d.ts +1 -128
- package/dist/lib/computer/sessions-list.js +6 -165
- package/dist/lib/computer-client.d.ts +0 -106
- package/dist/lib/computer-client.js +5 -86
- package/dist/lib/concurrency.d.ts +0 -14
- package/dist/lib/concurrency.js +0 -3
- package/dist/lib/config-drift.d.ts +0 -31
- package/dist/lib/config-drift.js +0 -32
- package/dist/lib/config-keys.d.ts +1 -65
- package/dist/lib/config-keys.js +6 -52
- package/dist/lib/config-transfer.d.ts +0 -14
- package/dist/lib/config-transfer.js +0 -26
- package/dist/lib/convert.d.ts +0 -17
- package/dist/lib/convert.js +0 -18
- package/dist/lib/crabbox/cli.d.ts +0 -156
- package/dist/lib/crabbox/cli.js +1 -188
- package/dist/lib/crabbox/config.d.ts +0 -18
- package/dist/lib/crabbox/config.js +1 -19
- package/dist/lib/crabbox/lease.d.ts +0 -93
- package/dist/lib/crabbox/lease.js +4 -148
- package/dist/lib/crabbox/progress.d.ts +0 -56
- package/dist/lib/crabbox/progress.js +2 -49
- package/dist/lib/crabbox/runtimes.d.ts +0 -94
- package/dist/lib/crabbox/runtimes.js +1 -111
- package/dist/lib/crabbox/setup-copy.d.ts +0 -64
- package/dist/lib/crabbox/setup-copy.js +1 -53
- package/dist/lib/daemon/account-state-daemon-service.d.ts +0 -48
- package/dist/lib/daemon/account-state-daemon-service.js +2 -63
- package/dist/lib/daemon/attention-notify-service.d.ts +0 -12
- package/dist/lib/daemon/attention-notify-service.js +1 -24
- package/dist/lib/daemon/auth-sync-service.d.ts +0 -28
- package/dist/lib/daemon/auth-sync-service.js +0 -56
- package/dist/lib/daemon/catchup-service.d.ts +0 -34
- package/dist/lib/daemon/catchup-service.js +0 -30
- package/dist/lib/daemon/daemon.d.ts +0 -374
- package/dist/lib/daemon/daemon.js +44 -1049
- package/dist/lib/daemon/daemon.test-fixture.d.ts +0 -19
- package/dist/lib/daemon/daemon.test-fixture.js +1 -24
- package/dist/lib/daemon/device-probe-service.d.ts +0 -16
- package/dist/lib/daemon/device-probe-service.js +0 -20
- package/dist/lib/daemon/feed-stream-service.d.ts +0 -15
- package/dist/lib/daemon/feed-stream-service.js +0 -20
- package/dist/lib/daemon/harness-update-service.d.ts +2 -61
- package/dist/lib/daemon/harness-update-service.js +6 -86
- package/dist/lib/daemon/heartbeat-service.d.ts +0 -1
- package/dist/lib/daemon/heartbeat-service.js +0 -1
- package/dist/lib/daemon/leaked-daemons.d.ts +0 -46
- package/dist/lib/daemon/leaked-daemons.js +2 -78
- package/dist/lib/daemon/monitor-engine-service.d.ts +0 -13
- package/dist/lib/daemon/monitor-engine-service.js +3 -15
- package/dist/lib/daemon/runner.d.ts +0 -194
- package/dist/lib/daemon/runner.js +39 -760
- package/dist/lib/daemon/self-heal-service.d.ts +18 -17
- package/dist/lib/daemon/self-heal-service.js +83 -37
- package/dist/lib/daemon/self-update-service.d.ts +1 -131
- package/dist/lib/daemon/self-update-service.js +26 -189
- package/dist/lib/daemon/service.d.ts +0 -73
- package/dist/lib/daemon/service.js +0 -34
- package/dist/lib/daemon/session-index-service.d.ts +0 -12
- package/dist/lib/daemon/session-index-service.js +0 -23
- package/dist/lib/daemon/session-state-service.d.ts +0 -8
- package/dist/lib/daemon/session-state-service.js +0 -8
- package/dist/lib/daemon/session-summarizer-service.d.ts +0 -14
- package/dist/lib/daemon/session-summarizer-service.js +1 -19
- package/dist/lib/daemon/session-title-service.d.ts +0 -25
- package/dist/lib/daemon/session-title-service.js +0 -32
- package/dist/lib/daemon/state-dir-check-service.d.ts +0 -24
- package/dist/lib/daemon/state-dir-check-service.js +0 -29
- package/dist/lib/daemon/supervisor.d.ts +0 -112
- package/dist/lib/daemon/supervisor.js +4 -147
- package/dist/lib/daemon/testdata/process-view-daemon.js +0 -2
- package/dist/lib/daemon/testdata/process-view-start.js +0 -5
- package/dist/lib/daemon/tmux-reap-service.d.ts +0 -1
- package/dist/lib/daemon/tmux-reap-service.js +0 -1
- package/dist/lib/daemon/usage-sync-service.d.ts +0 -23
- package/dist/lib/daemon/usage-sync-service.js +0 -26
- package/dist/lib/daemon/watchdog-service.d.ts +0 -9
- package/dist/lib/daemon/watchdog-service.js +0 -13
- package/dist/lib/daemon/webhook-receiver-service.d.ts +0 -1
- package/dist/lib/daemon/webhook-receiver-service.js +0 -1
- package/dist/lib/daemon-health.d.ts +0 -55
- package/dist/lib/daemon-health.js +4 -77
- package/dist/lib/daemon-services.d.ts +0 -36
- package/dist/lib/daemon-services.js +0 -45
- package/dist/lib/daemon-ticks.d.ts +0 -126
- package/dist/lib/daemon-ticks.js +1 -156
- package/dist/lib/daemon-webhooks.d.ts +0 -57
- package/dist/lib/daemon-webhooks.js +2 -54
- package/dist/lib/deeplink/register.d.ts +0 -15
- package/dist/lib/deeplink/register.js +0 -60
- package/dist/lib/deeplink/url.d.ts +0 -24
- package/dist/lib/deeplink/url.js +1 -33
- package/dist/lib/device-config.d.ts +1 -192
- package/dist/lib/device-config.js +86 -240
- package/dist/lib/devices/config-migration.d.ts +0 -43
- package/dist/lib/devices/config-migration.js +7 -127
- package/dist/lib/devices/connect.d.ts +0 -168
- package/dist/lib/devices/connect.js +6 -254
- package/dist/lib/devices/device-docs.d.ts +0 -24
- package/dist/lib/devices/device-docs.js +0 -46
- package/dist/lib/devices/discovery-policy.d.ts +0 -30
- package/dist/lib/devices/discovery-policy.js +3 -34
- package/dist/lib/devices/doctor-findings.d.ts +0 -109
- package/dist/lib/devices/doctor-findings.js +30 -326
- package/dist/lib/devices/doctor-overview-cache.d.ts +0 -33
- package/dist/lib/devices/doctor-overview-cache.js +0 -81
- package/dist/lib/devices/fleet-divergence.d.ts +0 -89
- package/dist/lib/devices/fleet-divergence.js +1 -60
- package/dist/lib/devices/fleet-inventory.d.ts +0 -27
- package/dist/lib/devices/fleet-inventory.js +0 -38
- package/dist/lib/devices/fleet.d.ts +0 -95
- package/dist/lib/devices/fleet.js +0 -79
- package/dist/lib/devices/harness-inventory.d.ts +0 -75
- package/dist/lib/devices/harness-inventory.js +0 -101
- package/dist/lib/devices/health-report.d.ts +0 -37
- package/dist/lib/devices/health-report.js +0 -73
- package/dist/lib/devices/health.d.ts +0 -71
- package/dist/lib/devices/health.js +2 -82
- package/dist/lib/devices/interactive-host.d.ts +0 -10
- package/dist/lib/devices/interactive-host.js +0 -34
- package/dist/lib/devices/known-hosts.d.ts +0 -45
- package/dist/lib/devices/known-hosts.js +0 -77
- package/dist/lib/devices/pending.d.ts +0 -31
- package/dist/lib/devices/pending.js +7 -67
- package/dist/lib/devices/pool.d.ts +0 -36
- package/dist/lib/devices/pool.js +0 -30
- package/dist/lib/devices/reachability.d.ts +0 -25
- package/dist/lib/devices/reachability.js +0 -14
- package/dist/lib/devices/registry.d.ts +0 -141
- package/dist/lib/devices/registry.js +4 -151
- package/dist/lib/devices/resolve-profile.d.ts +0 -18
- package/dist/lib/devices/resolve-profile.js +0 -18
- package/dist/lib/devices/resolve-target.d.ts +0 -20
- package/dist/lib/devices/resolve-target.js +1 -51
- package/dist/lib/devices/rollout-verify.d.ts +1 -81
- package/dist/lib/devices/rollout-verify.js +0 -77
- package/dist/lib/devices/self-host.d.ts +0 -7
- package/dist/lib/devices/self-host.js +1 -29
- package/dist/lib/devices/ssh-config.d.ts +0 -18
- package/dist/lib/devices/ssh-config.js +0 -9
- package/dist/lib/devices/stats-cache.d.ts +0 -48
- package/dist/lib/devices/stats-cache.js +0 -80
- package/dist/lib/devices/sync.d.ts +0 -97
- package/dist/lib/devices/sync.js +0 -88
- package/dist/lib/devices/tailscale.d.ts +0 -18
- package/dist/lib/devices/tailscale.js +1 -38
- package/dist/lib/devices/terminfo.d.ts +0 -27
- package/dist/lib/devices/terminfo.js +2 -64
- package/dist/lib/devices/worker-pick.d.ts +0 -15
- package/dist/lib/devices/worker-pick.js +0 -48
- package/dist/lib/diff-text.d.ts +0 -18
- package/dist/lib/diff-text.js +0 -15
- package/dist/lib/doctor-diff.d.ts +0 -79
- package/dist/lib/doctor-diff.js +2 -181
- package/dist/lib/drift-sync.d.ts +0 -29
- package/dist/lib/drift-sync.js +0 -40
- package/dist/lib/drift.d.ts +0 -43
- package/dist/lib/drift.js +0 -31
- package/dist/lib/event-families.d.ts +0 -17
- package/dist/lib/event-families.js +0 -33
- package/dist/lib/event-provenance.d.ts +0 -4
- package/dist/lib/event-provenance.js +0 -5
- package/dist/lib/event-stream.d.ts +0 -29
- package/dist/lib/event-stream.js +0 -36
- package/dist/lib/events-ingest.d.ts +0 -27
- package/dist/lib/events-ingest.js +0 -54
- package/dist/lib/exec-account-home.d.ts +0 -24
- package/dist/lib/exec-account-home.js +0 -41
- package/dist/lib/exec-bounded.d.ts +1 -37
- package/dist/lib/exec-bounded.js +10 -46
- package/dist/lib/exec.d.ts +3 -583
- package/dist/lib/exec.js +18 -1025
- package/dist/lib/factory/snapshot.js +1 -15
- package/dist/lib/feed/activity-stream.d.ts +0 -27
- package/dist/lib/feed/activity-stream.js +4 -80
- package/dist/lib/feed/activity.d.ts +1 -243
- package/dist/lib/feed/activity.js +8 -273
- package/dist/lib/feed/answer.d.ts +0 -103
- package/dist/lib/feed/answer.js +0 -267
- package/dist/lib/feed/attention.d.ts +0 -56
- package/dist/lib/feed/attention.js +0 -161
- package/dist/lib/feed/envelope.d.ts +2 -17
- package/dist/lib/feed/envelope.js +0 -14
- package/dist/lib/feed/events.d.ts +0 -118
- package/dist/lib/feed/events.js +13 -213
- package/dist/lib/feed/feed.d.ts +1 -250
- package/dist/lib/feed/feed.js +24 -334
- package/dist/lib/feed/hub-server.d.ts +0 -100
- package/dist/lib/feed/hub-server.js +1 -191
- package/dist/lib/feed/hub.d.ts +0 -53
- package/dist/lib/feed/hub.js +0 -89
- package/dist/lib/feed/pr-status.d.ts +1 -19
- package/dist/lib/feed/pr-status.js +0 -18
- package/dist/lib/feed/tool-activity.d.ts +0 -59
- package/dist/lib/feed/tool-activity.js +1 -119
- package/dist/lib/feed/tools.d.ts +0 -100
- package/dist/lib/feed/tools.js +0 -89
- package/dist/lib/feed/watch.d.ts +0 -33
- package/dist/lib/feed/watch.js +2 -94
- package/dist/lib/feed-broadcast.d.ts +0 -148
- package/dist/lib/feed-broadcast.js +1 -283
- package/dist/lib/feed-outcome.d.ts +0 -50
- package/dist/lib/feed-outcome.js +1 -67
- package/dist/lib/feed-policy.d.ts +0 -6
- package/dist/lib/feed-policy.js +1 -27
- package/dist/lib/feed-post.d.ts +0 -61
- package/dist/lib/feed-post.js +4 -61
- package/dist/lib/feed-ranking.d.ts +1 -1
- package/dist/lib/fleet/apply.d.ts +0 -64
- package/dist/lib/fleet/apply.js +0 -125
- package/dist/lib/fleet/auth-sync.d.ts +0 -48
- package/dist/lib/fleet/auth-sync.js +4 -49
- package/dist/lib/fleet/capture.d.ts +0 -26
- package/dist/lib/fleet/capture.js +1 -36
- package/dist/lib/fleet/manifest.d.ts +0 -38
- package/dist/lib/fleet/manifest.js +0 -40
- package/dist/lib/fleet/types.d.ts +1 -138
- package/dist/lib/fleet/types.js +0 -12
- package/dist/lib/fleet-cache.d.ts +0 -12
- package/dist/lib/fleet-cache.js +0 -24
- package/dist/lib/fleet-shared-state.d.ts +6 -59
- package/dist/lib/fleet-shared-state.js +5 -51
- package/dist/lib/fleet-status.d.ts +0 -27
- package/dist/lib/fleet-status.js +0 -48
- package/dist/lib/format.d.ts +0 -74
- package/dist/lib/format.js +3 -77
- package/dist/lib/friction-heuristics.d.ts +0 -20
- package/dist/lib/friction-heuristics.js +0 -8
- package/dist/lib/fs-atomic.d.ts +0 -51
- package/dist/lib/fs-atomic.js +8 -66
- package/dist/lib/fs-walk.d.ts +0 -13
- package/dist/lib/fs-walk.js +0 -22
- package/dist/lib/fuzzy.d.ts +0 -29
- package/dist/lib/fuzzy.js +0 -31
- package/dist/lib/gemini-settings.js +0 -12
- package/dist/lib/git.d.ts +0 -366
- package/dist/lib/git.js +7 -574
- package/dist/lib/github/ci-failure.d.ts +30 -0
- package/dist/lib/github/ci-failure.js +95 -0
- package/dist/lib/github/gh-overload.d.ts +0 -38
- package/dist/lib/github/gh-overload.js +3 -55
- package/dist/lib/github/pr-mergeable.d.ts +3 -34
- package/dist/lib/github/pr-mergeable.js +2 -42
- package/dist/lib/github/pr-verdict.d.ts +0 -44
- package/dist/lib/github/pr-verdict.js +0 -36
- package/dist/lib/github/project-prs.d.ts +135 -105
- package/dist/lib/github/project-prs.js +530 -170
- package/dist/lib/github/release-drift.d.ts +45 -0
- package/dist/lib/github/release-drift.js +91 -0
- package/dist/lib/github/rest.d.ts +0 -50
- package/dist/lib/github/rest.js +0 -49
- package/dist/lib/github/viewer.d.ts +27 -0
- package/dist/lib/github/viewer.js +101 -0
- package/dist/lib/goose-commands.d.ts +0 -29
- package/dist/lib/goose-commands.js +3 -48
- package/dist/lib/harness/adapter.d.ts +0 -151
- package/dist/lib/harness/adapter.js +0 -41
- package/dist/lib/harness/adapters/claude.d.ts +0 -8
- package/dist/lib/harness/adapters/claude.js +0 -89
- package/dist/lib/harness/adapters/codex.js +0 -18
- package/dist/lib/harness/adapters/copilot.js +0 -3
- package/dist/lib/harness/adapters/cursor.js +0 -16
- package/dist/lib/harness/adapters/droid.js +0 -3
- package/dist/lib/harness/adapters/kimi.js +0 -19
- package/dist/lib/harness/adapters/muse.js +0 -9
- package/dist/lib/harness/adapters/opencode.js +0 -2
- package/dist/lib/harness/exec-config-version.d.ts +0 -2
- package/dist/lib/harness/exec-config-version.js +0 -13
- package/dist/lib/harness/index.js +0 -10
- package/dist/lib/harness-auth-capabilities.d.ts +0 -26
- package/dist/lib/harness-auth-capabilities.js +0 -18
- package/dist/lib/harness-connection-test.d.ts +0 -27
- package/dist/lib/harness-connection-test.js +2 -20
- package/dist/lib/heal.d.ts +0 -45
- package/dist/lib/heal.js +2 -82
- package/dist/lib/help.d.ts +0 -32
- package/dist/lib/help.js +0 -41
- package/dist/lib/helper-download.d.ts +0 -85
- package/dist/lib/helper-download.js +0 -95
- package/dist/lib/helper-versions.d.ts +0 -51
- package/dist/lib/helper-versions.js +1 -45
- package/dist/lib/hooks/cache.d.ts +0 -40
- package/dist/lib/hooks/cache.js +8 -122
- package/dist/lib/hooks/install.d.ts +0 -253
- package/dist/lib/hooks/install.js +49 -822
- package/dist/lib/hooks/match.d.ts +0 -24
- package/dist/lib/hooks/match.js +0 -31
- package/dist/lib/hooks/profile.d.ts +0 -21
- package/dist/lib/hooks/profile.js +0 -28
- package/dist/lib/hosts/credential-transport.d.ts +0 -6
- package/dist/lib/hosts/credential-transport.js +0 -17
- package/dist/lib/hosts/credentials.d.ts +0 -35
- package/dist/lib/hosts/credentials.js +0 -38
- package/dist/lib/hosts/dispatch.d.ts +0 -140
- package/dist/lib/hosts/dispatch.js +0 -176
- package/dist/lib/hosts/logs.d.ts +0 -25
- package/dist/lib/hosts/logs.js +1 -51
- package/dist/lib/hosts/option.d.ts +0 -12
- package/dist/lib/hosts/option.js +0 -12
- package/dist/lib/hosts/passthrough.d.ts +0 -129
- package/dist/lib/hosts/passthrough.js +12 -249
- package/dist/lib/hosts/progress.d.ts +0 -90
- package/dist/lib/hosts/progress.js +5 -115
- package/dist/lib/hosts/providers/devices.d.ts +0 -19
- package/dist/lib/hosts/providers/devices.js +1 -34
- package/dist/lib/hosts/providers/local.d.ts +0 -14
- package/dist/lib/hosts/providers/local.js +0 -22
- package/dist/lib/hosts/ready.d.ts +0 -99
- package/dist/lib/hosts/ready.js +0 -101
- package/dist/lib/hosts/reconcile.d.ts +0 -38
- package/dist/lib/hosts/reconcile.js +1 -50
- package/dist/lib/hosts/reconnect.d.ts +0 -75
- package/dist/lib/hosts/reconnect.js +0 -98
- package/dist/lib/hosts/registry.d.ts +0 -74
- package/dist/lib/hosts/registry.js +0 -110
- package/dist/lib/hosts/remote-cmd.d.ts +1 -228
- package/dist/lib/hosts/remote-cmd.js +19 -294
- package/dist/lib/hosts/remote-cmd.test-fixture.d.ts +0 -1
- package/dist/lib/hosts/remote-cmd.test-fixture.js +0 -12
- package/dist/lib/hosts/remote-os.d.ts +0 -19
- package/dist/lib/hosts/remote-os.js +0 -22
- package/dist/lib/hosts/remote-session-id.d.ts +0 -22
- package/dist/lib/hosts/remote-session-id.js +0 -24
- package/dist/lib/hosts/routing-flag.d.ts +0 -21
- package/dist/lib/hosts/routing-flag.js +0 -21
- package/dist/lib/hosts/run-target.d.ts +0 -53
- package/dist/lib/hosts/run-target.js +0 -56
- package/dist/lib/hosts/session-index.d.ts +1 -53
- package/dist/lib/hosts/session-index.js +2 -59
- package/dist/lib/hosts/session-marker.d.ts +0 -31
- package/dist/lib/hosts/session-marker.js +0 -32
- package/dist/lib/hosts/ssh-config.d.ts +0 -25
- package/dist/lib/hosts/ssh-config.js +1 -32
- package/dist/lib/hosts/tasks.d.ts +0 -54
- package/dist/lib/hosts/tasks.js +0 -35
- package/dist/lib/hosts/types.d.ts +0 -39
- package/dist/lib/hosts/types.js +0 -22
- package/dist/lib/humans.d.ts +0 -21
- package/dist/lib/humans.js +0 -30
- package/dist/lib/identity/client.d.ts +1 -35
- package/dist/lib/identity/client.js +3 -29
- package/dist/lib/identity/index.d.ts +3 -27
- package/dist/lib/identity/index.js +8 -24
- package/dist/lib/import.d.ts +0 -104
- package/dist/lib/import.js +1 -137
- package/dist/lib/installations/active-check.d.ts +0 -53
- package/dist/lib/installations/active-check.js +0 -49
- package/dist/lib/installations/index.d.ts +0 -9
- package/dist/lib/installations/index.js +0 -9
- package/dist/lib/installations/installation-lock.js +0 -8
- package/dist/lib/installations/launch-gate.d.ts +0 -56
- package/dist/lib/installations/launch-gate.js +0 -83
- package/dist/lib/installations/migrate.d.ts +0 -100
- package/dist/lib/installations/migrate.js +105 -572
- package/dist/lib/installations/native-command.d.ts +0 -1
- package/dist/lib/installations/native-command.js +0 -6
- package/dist/lib/installations/resolve.d.ts +0 -24
- package/dist/lib/installations/resolve.js +0 -24
- package/dist/lib/installations/shims.d.ts +0 -395
- package/dist/lib/installations/shims.js +30 -957
- package/dist/lib/installations/store.d.ts +0 -199
- package/dist/lib/installations/store.js +1 -297
- package/dist/lib/installations/strategies.d.ts +0 -44
- package/dist/lib/installations/strategies.js +0 -87
- package/dist/lib/installations/types.d.ts +1 -67
- package/dist/lib/installations/types.js +0 -6
- package/dist/lib/installations/update-cancellation.d.ts +0 -74
- package/dist/lib/installations/update-cancellation.js +0 -74
- package/dist/lib/installations/update-policy.d.ts +0 -57
- package/dist/lib/installations/update-policy.js +0 -62
- package/dist/lib/installations/update-runtime.d.ts +0 -88
- package/dist/lib/installations/update-runtime.js +1 -127
- package/dist/lib/installations/update.d.ts +0 -53
- package/dist/lib/installations/update.js +0 -95
- package/dist/lib/installations/versions.d.ts +0 -310
- package/dist/lib/installations/versions.js +14 -837
- package/dist/lib/isolation-boundary-report.d.ts +0 -7
- package/dist/lib/isolation-boundary-report.js +0 -7
- package/dist/lib/launch-identity.d.ts +0 -8
- package/dist/lib/launch-identity.js +0 -8
- package/dist/lib/linear-autoclose.d.ts +0 -25
- package/dist/lib/linear-autoclose.js +0 -19
- package/dist/lib/linear-cache.d.ts +0 -57
- package/dist/lib/linear-cache.js +1 -81
- package/dist/lib/linear-project-counts.d.ts +0 -83
- package/dist/lib/linear-project-counts.js +2 -64
- package/dist/lib/linear-projects.d.ts +0 -62
- package/dist/lib/linear-projects.js +0 -85
- package/dist/lib/linear-rate-limit.d.ts +0 -21
- package/dist/lib/linear-rate-limit.js +1 -93
- package/dist/lib/linux-userns.d.ts +1 -42
- package/dist/lib/linux-userns.js +0 -47
- package/dist/lib/lock-compromise.d.ts +0 -7
- package/dist/lib/lock-compromise.js +0 -7
- package/dist/lib/log-follow.d.ts +0 -2
- package/dist/lib/log-follow.js +5 -15
- package/dist/lib/loop.d.ts +0 -106
- package/dist/lib/loop.js +0 -135
- package/dist/lib/machine-id.d.ts +0 -19
- package/dist/lib/machine-id.js +0 -19
- package/dist/lib/mailbox-gc.d.ts +0 -7
- package/dist/lib/mailbox-gc.js +0 -25
- package/dist/lib/mailbox-target.d.ts +0 -31
- package/dist/lib/mailbox-target.js +0 -27
- package/dist/lib/mailbox.d.ts +0 -77
- package/dist/lib/mailbox.js +5 -105
- package/dist/lib/manifest.d.ts +0 -4
- package/dist/lib/manifest.js +0 -36
- package/dist/lib/markdown.d.ts +0 -3
- package/dist/lib/markdown.js +0 -9
- package/dist/lib/mcp-registry.d.ts +1 -50
- package/dist/lib/mcp-registry.js +0 -64
- package/dist/lib/mcp.d.ts +0 -115
- package/dist/lib/mcp.js +3 -199
- package/dist/lib/memory-cache.d.ts +0 -11
- package/dist/lib/memory-cache.js +0 -9
- package/dist/lib/memory.d.ts +0 -52
- package/dist/lib/memory.js +12 -74
- package/dist/lib/menubar/download-menubar.d.ts +0 -35
- package/dist/lib/menubar/download-menubar.js +0 -38
- package/dist/lib/menubar/install-menubar.d.ts +0 -405
- package/dist/lib/menubar/install-menubar.js +25 -667
- package/dist/lib/menubar/migrate-prefs.d.ts +0 -47
- package/dist/lib/menubar/migrate-prefs.js +1 -70
- package/dist/lib/menubar/notify-desktop.d.ts +0 -82
- package/dist/lib/menubar/notify-desktop.js +0 -68
- package/dist/lib/menubar/resolve-version.d.ts +0 -41
- package/dist/lib/menubar/resolve-version.js +2 -44
- package/dist/lib/menubar/snapshot.d.ts +13 -66
- package/dist/lib/menubar/snapshot.js +45 -39
- package/dist/lib/merged-resources.d.ts +0 -10
- package/dist/lib/merged-resources.js +0 -10
- package/dist/lib/migrate-fold.d.ts +0 -31
- package/dist/lib/migrate-fold.js +6 -38
- package/dist/lib/model-tier-overrides.d.ts +0 -30
- package/dist/lib/model-tier-overrides.js +0 -14
- package/dist/lib/model-tiers.d.ts +0 -43
- package/dist/lib/model-tiers.js +5 -78
- package/dist/lib/models.d.ts +0 -145
- package/dist/lib/models.js +3 -333
- package/dist/lib/monitors/config.d.ts +0 -187
- package/dist/lib/monitors/config.js +4 -101
- package/dist/lib/monitors/dispatch.d.ts +0 -22
- package/dist/lib/monitors/dispatch.js +0 -35
- package/dist/lib/monitors/engine.d.ts +1 -53
- package/dist/lib/monitors/engine.js +17 -106
- package/dist/lib/monitors/fingerprint.d.ts +0 -43
- package/dist/lib/monitors/fingerprint.js +0 -57
- package/dist/lib/monitors/pid-watch.d.ts +0 -31
- package/dist/lib/monitors/pid-watch.js +0 -31
- package/dist/lib/monitors/remote.d.ts +0 -52
- package/dist/lib/monitors/remote.js +0 -42
- package/dist/lib/monitors/sources/command.d.ts +2 -9
- package/dist/lib/monitors/sources/command.js +13 -34
- package/dist/lib/monitors/sources/device.d.ts +0 -10
- package/dist/lib/monitors/sources/device.js +0 -14
- package/dist/lib/monitors/sources/failure.d.ts +0 -27
- package/dist/lib/monitors/sources/failure.js +0 -27
- package/dist/lib/monitors/sources/file.d.ts +0 -10
- package/dist/lib/monitors/sources/file.js +0 -11
- package/dist/lib/monitors/sources/http.d.ts +0 -7
- package/dist/lib/monitors/sources/http.js +0 -9
- package/dist/lib/monitors/sources/index.d.ts +0 -9
- package/dist/lib/monitors/sources/index.js +0 -9
- package/dist/lib/monitors/sources/poll.d.ts +0 -8
- package/dist/lib/monitors/sources/poll.js +0 -8
- package/dist/lib/monitors/sources/types.d.ts +0 -18
- package/dist/lib/monitors/sources/types.js +0 -8
- package/dist/lib/monitors/sources/webhook.d.ts +0 -7
- package/dist/lib/monitors/sources/webhook.js +0 -7
- package/dist/lib/monitors/sources/ws.d.ts +0 -10
- package/dist/lib/monitors/sources/ws.js +3 -13
- package/dist/lib/monitors/state.d.ts +0 -132
- package/dist/lib/monitors/state.js +2 -86
- package/dist/lib/native-accounts.d.ts +0 -32
- package/dist/lib/native-accounts.js +0 -17
- package/dist/lib/net-close.d.ts +0 -9
- package/dist/lib/net-close.js +0 -5
- package/dist/lib/notify.d.ts +0 -47
- package/dist/lib/notify.js +0 -30
- package/dist/lib/onepassword.d.ts +0 -14
- package/dist/lib/onepassword.js +0 -12
- package/dist/lib/open-url.d.ts +0 -38
- package/dist/lib/open-url.js +1 -69
- package/dist/lib/openclaw-keychain.js +2 -7
- package/dist/lib/operator.d.ts +0 -9
- package/dist/lib/operator.js +0 -34
- package/dist/lib/origin-machine.d.ts +0 -16
- package/dist/lib/origin-machine.js +0 -16
- package/dist/lib/output/git-output.d.ts +0 -31
- package/dist/lib/output/git-output.js +4 -43
- package/dist/lib/overdue.d.ts +0 -35
- package/dist/lib/overdue.js +0 -60
- package/dist/lib/owner-message.d.ts +0 -20
- package/dist/lib/owner-message.js +1 -40
- package/dist/lib/packages/output-home.d.ts +0 -28
- package/dist/lib/packages/output-home.js +0 -114
- package/dist/lib/paths.d.ts +0 -26
- package/dist/lib/paths.js +1 -27
- package/dist/lib/percentile.d.ts +0 -11
- package/dist/lib/percentile.js +0 -11
- package/dist/lib/perf/db.d.ts +0 -16
- package/dist/lib/perf/db.js +3 -32
- package/dist/lib/perf/spool.d.ts +0 -12
- package/dist/lib/perf/spool.js +0 -13
- package/dist/lib/perf/types.d.ts +0 -26
- package/dist/lib/perf/types.js +0 -1
- package/dist/lib/permissions-registry.d.ts +0 -48
- package/dist/lib/permissions-registry.js +0 -108
- package/dist/lib/permissions.d.ts +0 -215
- package/dist/lib/permissions.js +4 -407
- package/dist/lib/picker.d.ts +0 -124
- package/dist/lib/picker.js +0 -140
- package/dist/lib/placement.d.ts +0 -57
- package/dist/lib/placement.js +0 -47
- package/dist/lib/platform/exec.d.ts +0 -73
- package/dist/lib/platform/exec.js +0 -80
- package/dist/lib/platform/index.d.ts +0 -14
- package/dist/lib/platform/index.js +0 -14
- package/dist/lib/platform/ipc.d.ts +0 -10
- package/dist/lib/platform/ipc.js +0 -13
- package/dist/lib/platform/links.d.ts +0 -14
- package/dist/lib/platform/links.js +0 -25
- package/dist/lib/platform/paths.d.ts +0 -48
- package/dist/lib/platform/paths.js +0 -52
- package/dist/lib/platform/posixpath.d.ts +0 -18
- package/dist/lib/platform/posixpath.js +0 -62
- package/dist/lib/platform/process.d.ts +0 -67
- package/dist/lib/platform/process.js +5 -99
- package/dist/lib/platform/winpath.d.ts +0 -50
- package/dist/lib/platform/winpath.js +0 -81
- package/dist/lib/plugins/plugin-marketplace.d.ts +0 -165
- package/dist/lib/plugins/plugin-marketplace.js +10 -238
- package/dist/lib/plugins/plugins.d.ts +0 -238
- package/dist/lib/plugins/plugins.js +20 -454
- package/dist/lib/plugins/skills.d.ts +0 -86
- package/dist/lib/plugins/skills.js +1 -139
- package/dist/lib/pr-land-detach.d.ts +0 -17
- package/dist/lib/pr-land-detach.js +0 -30
- package/dist/lib/pricing/cost.d.ts +0 -29
- package/dist/lib/pricing/cost.js +0 -38
- package/dist/lib/pricing/index.d.ts +0 -6
- package/dist/lib/pricing/index.js +0 -6
- package/dist/lib/pricing/table.d.ts +0 -8
- package/dist/lib/pricing/table.js +3 -56
- package/dist/lib/probe.d.ts +0 -5
- package/dist/lib/probe.js +0 -40
- package/dist/lib/profiles-presets.d.ts +0 -20
- package/dist/lib/profiles-presets.js +1 -36
- package/dist/lib/profiles.d.ts +0 -185
- package/dist/lib/profiles.js +1 -158
- package/dist/lib/project-doctor.d.ts +0 -29
- package/dist/lib/project-doctor.js +0 -26
- package/dist/lib/project-focus.d.ts +0 -41
- package/dist/lib/project-focus.js +0 -49
- package/dist/lib/project-import.d.ts +0 -41
- package/dist/lib/project-import.js +0 -36
- package/dist/lib/project-key.d.ts +0 -65
- package/dist/lib/project-key.js +0 -70
- package/dist/lib/project-launch.d.ts +0 -49
- package/dist/lib/project-launch.js +2 -91
- package/dist/lib/project-probe.d.ts +0 -86
- package/dist/lib/project-probe.js +1 -88
- package/dist/lib/project-pull.d.ts +0 -96
- package/dist/lib/project-pull.js +0 -122
- package/dist/lib/project-resources.d.ts +0 -44
- package/dist/lib/project-resources.js +7 -171
- package/dist/lib/project-root.d.ts +0 -95
- package/dist/lib/project-root.js +0 -101
- package/dist/lib/project-schedule.d.ts +0 -43
- package/dist/lib/project-schedule.js +0 -52
- package/dist/lib/project-status.d.ts +0 -108
- package/dist/lib/project-status.js +0 -117
- package/dist/lib/projects.d.ts +0 -197
- package/dist/lib/projects.js +1 -213
- package/dist/lib/pwsh.d.ts +0 -41
- package/dist/lib/pwsh.js +0 -51
- package/dist/lib/quick-todo.d.ts +84 -0
- package/dist/lib/quick-todo.js +243 -0
- package/dist/lib/reconcile-and-repair.d.ts +0 -78
- package/dist/lib/reconcile-and-repair.js +3 -66
- package/dist/lib/redact.d.ts +0 -29
- package/dist/lib/redact.js +0 -54
- package/dist/lib/refresh-coordinator.d.ts +0 -15
- package/dist/lib/refresh-coordinator.js +0 -10
- package/dist/lib/refresh.d.ts +0 -39
- package/dist/lib/refresh.js +0 -45
- package/dist/lib/registry.d.ts +0 -65
- package/dist/lib/registry.js +0 -127
- package/dist/lib/reminders.d.ts +0 -21
- package/dist/lib/reminders.js +0 -30
- package/dist/lib/remote-agents-json.d.ts +0 -44
- package/dist/lib/remote-agents-json.js +1 -44
- package/dist/lib/reserved-stores.d.ts +0 -28
- package/dist/lib/reserved-stores.js +2 -28
- package/dist/lib/resource-aliases.d.ts +0 -12
- package/dist/lib/resource-aliases.js +0 -12
- package/dist/lib/resource-content-diff.d.ts +0 -28
- package/dist/lib/resource-content-diff.js +7 -34
- package/dist/lib/resource-inventory.d.ts +0 -51
- package/dist/lib/resource-inventory.js +0 -45
- package/dist/lib/resource-patterns.d.ts +0 -32
- package/dist/lib/resource-patterns.js +0 -34
- package/dist/lib/resource-profiles.d.ts +0 -7
- package/dist/lib/resource-profiles.js +0 -11
- package/dist/lib/resources/types.d.ts +0 -50
- package/dist/lib/resources/types.js +0 -7
- package/dist/lib/resources/workflows.d.ts +0 -7
- package/dist/lib/resources/workflows.js +0 -13
- package/dist/lib/resources.d.ts +0 -65
- package/dist/lib/resources.js +0 -78
- package/dist/lib/routers.d.ts +0 -67
- package/dist/lib/routers.js +0 -60
- package/dist/lib/routine-activation.d.ts +0 -23
- package/dist/lib/routine-activation.js +0 -24
- package/dist/lib/routine-context.d.ts +1 -91
- package/dist/lib/routine-context.js +0 -107
- package/dist/lib/routine-notify-owner.d.ts +0 -79
- package/dist/lib/routine-notify-owner.js +1 -103
- package/dist/lib/routine-notify.d.ts +0 -70
- package/dist/lib/routine-notify.js +1 -75
- package/dist/lib/routine-process-cleanup.d.ts +0 -1
- package/dist/lib/routine-process-cleanup.js +1 -4
- package/dist/lib/routine-readiness.d.ts +0 -63
- package/dist/lib/routine-readiness.js +4 -86
- package/dist/lib/routines-format.d.ts +0 -40
- package/dist/lib/routines-format.js +0 -67
- package/dist/lib/routines-placement.d.ts +0 -33
- package/dist/lib/routines-placement.js +0 -40
- package/dist/lib/routines-project.d.ts +0 -57
- package/dist/lib/routines-project.js +6 -80
- package/dist/lib/rules/compile.d.ts +0 -66
- package/dist/lib/rules/compile.js +6 -118
- package/dist/lib/rules/compose.d.ts +0 -56
- package/dist/lib/rules/compose.js +2 -83
- package/dist/lib/rules/rules.d.ts +0 -23
- package/dist/lib/rules/rules.js +0 -35
- package/dist/lib/rules/run-sync.d.ts +0 -16
- package/dist/lib/rules/run-sync.js +1 -44
- package/dist/lib/run-config.d.ts +0 -7
- package/dist/lib/run-config.js +0 -8
- package/dist/lib/run-defaults.d.ts +0 -14
- package/dist/lib/run-defaults.js +0 -14
- package/dist/lib/run-notify.d.ts +0 -18
- package/dist/lib/run-notify.js +0 -36
- package/dist/lib/run-trace-sync.d.ts +0 -21
- package/dist/lib/run-trace-sync.js +2 -66
- package/dist/lib/rush-session.d.ts +0 -26
- package/dist/lib/rush-session.js +0 -28
- package/dist/lib/sandbox.d.ts +0 -45
- package/dist/lib/sandbox.js +5 -93
- package/dist/lib/scheduler.d.ts +0 -28
- package/dist/lib/scheduler.js +0 -45
- package/dist/lib/scheduling/routines.d.ts +0 -652
- package/dist/lib/scheduling/routines.js +8 -475
- package/dist/lib/secrets-cli.d.ts +3 -8
- package/dist/lib/secrets-cli.js +1 -19
- package/dist/lib/secrets-client.d.ts +0 -117
- package/dist/lib/secrets-client.js +4 -275
- package/dist/lib/secrets-policy.d.ts +0 -142
- package/dist/lib/secrets-policy.js +4 -237
- package/dist/lib/secrets-types.d.ts +0 -87
- package/dist/lib/secrets-types.js +0 -13
- package/dist/lib/self-heal/checks/hook-manifest.js +0 -25
- package/dist/lib/self-heal/checks/hook-runtime.js +0 -5
- package/dist/lib/self-heal/checks/install-staging.d.ts +0 -1
- package/dist/lib/self-heal/checks/install-staging.js +1 -28
- package/dist/lib/self-heal/checks/menubar-helper.js +0 -5
- package/dist/lib/self-heal/checks/path.js +0 -9
- package/dist/lib/self-heal/checks/resources.js +0 -5
- package/dist/lib/self-heal/checks/shadowing.js +2 -16
- package/dist/lib/self-heal/checks/shims.js +0 -14
- package/dist/lib/self-heal/child.d.ts +12 -0
- package/dist/lib/self-heal/child.js +23 -0
- package/dist/lib/self-heal/registry.d.ts +0 -9
- package/dist/lib/self-heal/registry.js +0 -16
- package/dist/lib/self-heal/types.d.ts +0 -12
- package/dist/lib/self-heal/types.js +0 -15
- package/dist/lib/self-update.d.ts +0 -312
- package/dist/lib/self-update.js +9 -360
- package/dist/lib/service-manifest.d.ts +0 -39
- package/dist/lib/service-manifest.js +0 -72
- package/dist/lib/session/active.d.ts +13 -869
- package/dist/lib/session/active.js +17 -976
- package/dist/lib/session/actor-sidecar.d.ts +1 -32
- package/dist/lib/session/actor-sidecar.js +1 -41
- package/dist/lib/session/bookmarks.d.ts +0 -33
- package/dist/lib/session/bookmarks.js +0 -37
- package/dist/lib/session/bundle.d.ts +0 -86
- package/dist/lib/session/bundle.js +0 -54
- package/dist/lib/session/claude-accounts.d.ts +0 -40
- package/dist/lib/session/claude-accounts.js +0 -49
- package/dist/lib/session/cloud.d.ts +1 -23
- package/dist/lib/session/cloud.js +0 -26
- package/dist/lib/session/db.d.ts +5 -658
- package/dist/lib/session/db.js +22 -1443
- package/dist/lib/session/detached.d.ts +0 -21
- package/dist/lib/session/detached.js +0 -29
- package/dist/lib/session/discover.d.ts +3 -420
- package/dist/lib/session/discover.js +30 -1123
- package/dist/lib/session/fork.d.ts +1 -41
- package/dist/lib/session/fork.js +0 -19
- package/dist/lib/session/ghostty-tabs.d.ts +0 -24
- package/dist/lib/session/ghostty-tabs.js +0 -37
- package/dist/lib/session/glance-files.d.ts +19 -0
- package/dist/lib/session/glance-files.js +258 -0
- package/dist/lib/session/hook-sessions.d.ts +0 -33
- package/dist/lib/session/hook-sessions.js +4 -99
- package/dist/lib/session/host-link.d.ts +1 -94
- package/dist/lib/session/host-link.js +1 -81
- package/dist/lib/session/inject-target.d.ts +8 -0
- package/dist/lib/session/inject-target.js +32 -0
- package/dist/lib/session/inject.d.ts +0 -15
- package/dist/lib/session/inject.js +0 -15
- package/dist/lib/session/live-metadata.d.ts +1 -34
- package/dist/lib/session/live-metadata.js +1 -73
- package/dist/lib/session/local-tmux-attach.d.ts +0 -37
- package/dist/lib/session/local-tmux-attach.js +1 -76
- package/dist/lib/session/migrate-targets.d.ts +0 -46
- package/dist/lib/session/migrate-targets.js +0 -24
- package/dist/lib/session/migrations.d.ts +0 -12
- package/dist/lib/session/migrations.js +1 -20
- package/dist/lib/session/mirror.d.ts +0 -32
- package/dist/lib/session/mirror.js +0 -77
- package/dist/lib/session/origin-machine.js +0 -3
- package/dist/lib/session/pid-registry.d.ts +0 -80
- package/dist/lib/session/pid-registry.js +2 -81
- package/dist/lib/session/presence.d.ts +0 -39
- package/dist/lib/session/presence.js +2 -52
- package/dist/lib/session/process-view.d.ts +0 -11
- package/dist/lib/session/process-view.js +0 -25
- package/dist/lib/session/projection.d.ts +0 -3
- package/dist/lib/session/projection.js +0 -10
- package/dist/lib/session/provenance.d.ts +1 -37
- package/dist/lib/session/provenance.js +0 -69
- package/dist/lib/session/recovery.d.ts +1 -40
- package/dist/lib/session/recovery.js +2 -80
- package/dist/lib/session/relative-time.js +0 -3
- package/dist/lib/session/remote/peer-stream.d.ts +0 -42
- package/dist/lib/session/remote/peer-stream.js +0 -64
- package/dist/lib/session/remote/remote-bundle.d.ts +0 -6
- package/dist/lib/session/remote/remote-bundle.js +0 -21
- package/dist/lib/session/remote/remote-list.d.ts +1 -110
- package/dist/lib/session/remote/remote-list.js +5 -139
- package/dist/lib/session/remote/remote.d.ts +0 -98
- package/dist/lib/session/remote/remote.js +3 -119
- package/dist/lib/session/remote/watch.d.ts +1 -34
- package/dist/lib/session/remote/watch.js +12 -72
- package/dist/lib/session/remote-active.d.ts +0 -35
- package/dist/lib/session/remote-active.js +0 -48
- package/dist/lib/session/remote-bundle.js +0 -2
- package/dist/lib/session/remote-list.js +0 -2
- package/dist/lib/session/remote-preview-cache.d.ts +0 -7
- package/dist/lib/session/remote-preview-cache.js +1 -76
- package/dist/lib/session/remote.js +0 -2
- package/dist/lib/session/resume-command.d.ts +0 -6
- package/dist/lib/session/resume-command.js +0 -6
- package/dist/lib/session/resume-owner.d.ts +1 -52
- package/dist/lib/session/resume-owner.js +0 -56
- package/dist/lib/session/run-names.d.ts +0 -24
- package/dist/lib/session/run-names.js +0 -26
- package/dist/lib/session/session-cache.d.ts +2 -146
- package/dist/lib/session/session-cache.js +26 -203
- package/dist/lib/session/short-id.js +0 -3
- package/dist/lib/session/sync/agents.d.ts +0 -68
- package/dist/lib/session/sync/agents.js +0 -0
- package/dist/lib/session/sync/backend.d.ts +0 -39
- package/dist/lib/session/sync/backend.js +0 -45
- package/dist/lib/session/sync/config.d.ts +0 -27
- package/dist/lib/session/sync/config.js +0 -56
- package/dist/lib/session/sync/managed-config.d.ts +0 -17
- package/dist/lib/session/sync/managed-config.js +0 -17
- package/dist/lib/session/sync/managed-key.d.ts +0 -38
- package/dist/lib/session/sync/managed-key.js +1 -42
- package/dist/lib/session/sync/net-client.d.ts +0 -36
- package/dist/lib/session/sync/net-client.js +0 -30
- package/dist/lib/session/sync/provision.d.ts +0 -2
- package/dist/lib/session/sync/provision.js +0 -13
- package/dist/lib/session/sync/r2.d.ts +0 -20
- package/dist/lib/session/sync/r2.js +0 -20
- package/dist/lib/session/sync/transcript-crypto.d.ts +0 -37
- package/dist/lib/session/sync/transcript-crypto.js +5 -37
- package/dist/lib/session/sync/worker-template.d.ts +0 -5
- package/dist/lib/session/sync/worker-template.js +0 -40
- package/dist/lib/session/testdata/pid-registry-namespace.js +0 -2
- package/dist/lib/session/testdata/process-view-private.js +0 -1
- package/dist/lib/session/throughput.d.ts +0 -24
- package/dist/lib/session/throughput.js +1 -25
- package/dist/lib/session/timeline-pass.d.ts +1 -63
- package/dist/lib/session/timeline-pass.js +161 -148
- package/dist/lib/session/title.d.ts +0 -182
- package/dist/lib/session/title.js +0 -139
- package/dist/lib/session/tool-index.d.ts +2 -21
- package/dist/lib/session/tool-index.js +3 -75
- package/dist/lib/session/tool-store.d.ts +2 -48
- package/dist/lib/session/tool-store.js +1 -33
- package/dist/lib/session/viewing-in.d.ts +0 -67
- package/dist/lib/session/viewing-in.js +1 -71
- package/dist/lib/session/watch.js +0 -2
- package/dist/lib/session/width.js +0 -3
- package/dist/lib/sessions-client.d.ts +0 -46
- package/dist/lib/sessions-client.js +36 -113
- package/dist/lib/settings-manifest.d.ts +1 -17
- package/dist/lib/settings-manifest.js +4 -57
- package/dist/lib/setup-tool-install.d.ts +0 -1
- package/dist/lib/setup-tool-install.js +2 -7
- package/dist/lib/setup-tool-status.d.ts +0 -3
- package/dist/lib/setup-tool-status.js +4 -14
- package/dist/lib/sha256-asset.d.ts +0 -20
- package/dist/lib/sha256-asset.js +0 -20
- package/dist/lib/share-runtime.d.ts +0 -10
- package/dist/lib/share-runtime.js +1 -27
- package/dist/lib/shim-heal.d.ts +0 -15
- package/dist/lib/shim-heal.js +3 -29
- package/dist/lib/signin-badge.d.ts +0 -72
- package/dist/lib/signin-badge.js +0 -86
- package/dist/lib/sink-format.d.ts +0 -32
- package/dist/lib/sink-format.js +0 -14
- package/dist/lib/smart-launch.d.ts +0 -75
- package/dist/lib/smart-launch.js +1 -83
- package/dist/lib/snapshot.d.ts +0 -46
- package/dist/lib/snapshot.js +5 -31
- package/dist/lib/spinner.d.ts +0 -37
- package/dist/lib/spinner.js +0 -37
- package/dist/lib/sqlite.d.ts +0 -13
- package/dist/lib/sqlite.js +3 -71
- package/dist/lib/ssh-exec.d.ts +0 -209
- package/dist/lib/ssh-exec.js +11 -248
- package/dist/lib/ssh-tunnel.d.ts +0 -43
- package/dist/lib/ssh-tunnel.js +2 -48
- package/dist/lib/staleness/checkers/commands.d.ts +0 -4
- package/dist/lib/staleness/checkers/commands.js +0 -4
- package/dist/lib/staleness/checkers/hooks.d.ts +0 -10
- package/dist/lib/staleness/checkers/hooks.js +0 -15
- package/dist/lib/staleness/checkers/mcp.d.ts +0 -9
- package/dist/lib/staleness/checkers/mcp.js +0 -9
- package/dist/lib/staleness/checkers/permissions.d.ts +0 -12
- package/dist/lib/staleness/checkers/permissions.js +0 -13
- package/dist/lib/staleness/checkers/plugins.d.ts +0 -8
- package/dist/lib/staleness/checkers/plugins.js +0 -8
- package/dist/lib/staleness/checkers/rules.d.ts +0 -15
- package/dist/lib/staleness/checkers/rules.js +0 -26
- package/dist/lib/staleness/checkers/skills.d.ts +0 -4
- package/dist/lib/staleness/checkers/skills.js +0 -4
- package/dist/lib/staleness/checkers/subagents.d.ts +0 -9
- package/dist/lib/staleness/checkers/subagents.js +0 -9
- package/dist/lib/staleness/checkers/types.d.ts +0 -34
- package/dist/lib/staleness/checkers/types.js +0 -19
- package/dist/lib/staleness/checkers/workflows.d.ts +0 -7
- package/dist/lib/staleness/checkers/workflows.js +0 -7
- package/dist/lib/staleness/detectors/commands.js +0 -17
- package/dist/lib/staleness/detectors/hooks.js +1 -6
- package/dist/lib/staleness/detectors/mcp.js +0 -4
- package/dist/lib/staleness/detectors/permissions.js +10 -23
- package/dist/lib/staleness/detectors/rules.js +0 -6
- package/dist/lib/staleness/detectors/skills.d.ts +0 -1
- package/dist/lib/staleness/detectors/skills.js +1 -12
- package/dist/lib/staleness/detectors/types.d.ts +0 -10
- package/dist/lib/staleness/fingerprint.d.ts +0 -19
- package/dist/lib/staleness/fingerprint.js +0 -35
- package/dist/lib/staleness/index.d.ts +0 -28
- package/dist/lib/staleness/index.js +1 -45
- package/dist/lib/staleness/layers.d.ts +0 -23
- package/dist/lib/staleness/layers.js +0 -34
- package/dist/lib/staleness/prune.d.ts +0 -71
- package/dist/lib/staleness/prune.js +2 -27
- package/dist/lib/staleness/registry.d.ts +0 -10
- package/dist/lib/staleness/registry.js +3 -33
- package/dist/lib/staleness/types.d.ts +0 -36
- package/dist/lib/staleness/types.js +0 -5
- package/dist/lib/staleness/writers/commands.js +1 -48
- package/dist/lib/staleness/writers/hooks.js +1 -18
- package/dist/lib/staleness/writers/kinds.d.ts +0 -12
- package/dist/lib/staleness/writers/kinds.js +0 -1
- package/dist/lib/staleness/writers/lazy-map.d.ts +0 -11
- package/dist/lib/staleness/writers/mcp.js +0 -13
- package/dist/lib/staleness/writers/plugins.js +0 -4
- package/dist/lib/staleness/writers/rules.d.ts +0 -1
- package/dist/lib/staleness/writers/rules.js +1 -19
- package/dist/lib/staleness/writers/skills.js +3 -14
- package/dist/lib/staleness/writers/sources.d.ts +0 -11
- package/dist/lib/staleness/writers/sources.js +0 -32
- package/dist/lib/staleness/writers/subagents.js +0 -16
- package/dist/lib/staleness/writers/types.d.ts +0 -58
- package/dist/lib/staleness/writers/workflows.js +1 -1
- package/dist/lib/standalone-tools.d.ts +24 -0
- package/dist/lib/standalone-tools.js +58 -0
- package/dist/lib/star-nudge.d.ts +0 -32
- package/dist/lib/star-nudge.js +2 -36
- package/dist/lib/startup/command-registry.d.ts +0 -45
- package/dist/lib/startup/command-registry.js +1 -46
- package/dist/lib/startup/dev-build.d.ts +0 -9
- package/dist/lib/startup/dev-build.js +1 -42
- package/dist/lib/startup/root-command.d.ts +0 -19
- package/dist/lib/startup/root-command.js +0 -19
- package/dist/lib/startup/spellcheck.d.ts +0 -13
- package/dist/lib/startup/spellcheck.js +0 -13
- package/dist/lib/state.d.ts +0 -376
- package/dist/lib/state.js +19 -737
- package/dist/lib/storage/selection.d.ts +0 -40
- package/dist/lib/storage/selection.js +0 -29
- package/dist/lib/subagents-registry.d.ts +0 -56
- package/dist/lib/subagents-registry.js +0 -99
- package/dist/lib/subagents.d.ts +0 -128
- package/dist/lib/subagents.js +1 -158
- package/dist/lib/summarizer/config.d.ts +0 -37
- package/dist/lib/summarizer/config.js +0 -37
- package/dist/lib/summarizer/pass.d.ts +0 -20
- package/dist/lib/summarizer/pass.js +1 -34
- package/dist/lib/summarizer/summarize.d.ts +1 -49
- package/dist/lib/summarizer/summarize.js +0 -35
- package/dist/lib/sync-passphrase.d.ts +0 -16
- package/dist/lib/sync-passphrase.js +1 -18
- package/dist/lib/sync-status.d.ts +0 -72
- package/dist/lib/sync-status.js +0 -55
- package/dist/lib/sync-umbrella.d.ts +0 -54
- package/dist/lib/sync-umbrella.js +0 -48
- package/dist/lib/system-run-sync.d.ts +0 -5
- package/dist/lib/system-run-sync.js +1 -31
- package/dist/lib/teams/agents.d.ts +1 -444
- package/dist/lib/teams/agents.js +11 -871
- package/dist/lib/teams/api.d.ts +2 -52
- package/dist/lib/teams/api.js +4 -63
- package/dist/lib/teams/debug.d.ts +0 -6
- package/dist/lib/teams/debug.js +0 -6
- package/dist/lib/teams/delivery.d.ts +0 -41
- package/dist/lib/teams/delivery.js +0 -32
- package/dist/lib/teams/file_ops.d.ts +0 -11
- package/dist/lib/teams/file_ops.js +0 -11
- package/dist/lib/teams/forEach.d.ts +0 -76
- package/dist/lib/teams/forEach.js +1 -77
- package/dist/lib/teams/index.d.ts +1 -7
- package/dist/lib/teams/index.js +1 -7
- package/dist/lib/teams/parsers.d.ts +0 -4
- package/dist/lib/teams/parsers.js +0 -81
- package/dist/lib/teams/persistence.d.ts +0 -2
- package/dist/lib/teams/persistence.js +0 -12
- package/dist/lib/teams/placement-probe.d.ts +0 -12
- package/dist/lib/teams/placement-probe.js +1 -51
- package/dist/lib/teams/pr-watch.d.ts +0 -107
- package/dist/lib/teams/pr-watch.js +1 -107
- package/dist/lib/teams/registry.d.ts +0 -36
- package/dist/lib/teams/registry.js +0 -47
- package/dist/lib/teams/remoteWorktree.d.ts +0 -50
- package/dist/lib/teams/remoteWorktree.js +1 -96
- package/dist/lib/teams/scheduler.d.ts +0 -111
- package/dist/lib/teams/scheduler.js +2 -125
- package/dist/lib/teams/summarizer.d.ts +0 -22
- package/dist/lib/teams/summarizer.js +6 -50
- package/dist/lib/teams/supervisor.d.ts +0 -38
- package/dist/lib/teams/supervisor.js +0 -21
- package/dist/lib/teams/worktree.d.ts +0 -95
- package/dist/lib/teams/worktree.js +3 -110
- package/dist/lib/template.d.ts +0 -21
- package/dist/lib/template.js +0 -23
- package/dist/lib/term-client.d.ts +0 -26
- package/dist/lib/term-client.js +0 -48
- package/dist/lib/term-driver.d.ts +0 -5
- package/dist/lib/term-driver.js +0 -8
- package/dist/lib/terminal/backends/ghostty.d.ts +0 -2
- package/dist/lib/terminal/backends/ghostty.js +0 -12
- package/dist/lib/terminal/backends/index.d.ts +0 -17
- package/dist/lib/terminal/backends/index.js +0 -15
- package/dist/lib/terminal/backends/iterm.d.ts +0 -2
- package/dist/lib/terminal/backends/iterm.js +0 -10
- package/dist/lib/terminal/backends/terminal-app.d.ts +0 -10
- package/dist/lib/terminal/backends/terminal-app.js +0 -30
- package/dist/lib/terminal/backends/tmux.d.ts +0 -10
- package/dist/lib/terminal/backends/tmux.js +0 -2
- package/dist/lib/terminal/backends/vscodium-agent.d.ts +0 -25
- package/dist/lib/terminal/backends/vscodium-agent.js +0 -36
- package/dist/lib/terminal/engine.d.ts +0 -17
- package/dist/lib/terminal/engine.js +0 -10
- package/dist/lib/terminal/index.d.ts +0 -8
- package/dist/lib/terminal/inject.d.ts +1 -173
- package/dist/lib/terminal/inject.js +0 -146
- package/dist/lib/terminal/policy.d.ts +0 -8
- package/dist/lib/terminal/policy.js +0 -1
- package/dist/lib/terminal/preferred.d.ts +0 -66
- package/dist/lib/terminal/preferred.js +0 -30
- package/dist/lib/terminal/quote.d.ts +0 -8
- package/dist/lib/terminal/quote.js +0 -8
- package/dist/lib/terminal/resolve.d.ts +0 -46
- package/dist/lib/terminal/resolve.js +0 -30
- package/dist/lib/terminal/run-surface.d.ts +0 -56
- package/dist/lib/terminal/run-surface.js +0 -46
- package/dist/lib/terminal/shell.d.ts +0 -3
- package/dist/lib/terminal/shell.js +0 -13
- package/dist/lib/terminal/transport.d.ts +0 -14
- package/dist/lib/terminal/transport.js +1 -30
- package/dist/lib/terminal/types.d.ts +0 -40
- package/dist/lib/terminal/types.js +0 -10
- package/dist/lib/text/relative-time.d.ts +0 -36
- package/dist/lib/text/relative-time.js +0 -43
- package/dist/lib/text/short-id.d.ts +0 -16
- package/dist/lib/text/short-id.js +0 -16
- package/dist/lib/text/width.d.ts +0 -24
- package/dist/lib/text/width.js +10 -52
- package/dist/lib/tmux/binary.d.ts +0 -36
- package/dist/lib/tmux/binary.js +0 -28
- package/dist/lib/tmux/index.d.ts +0 -5
- package/dist/lib/tmux/index.js +0 -5
- package/dist/lib/tmux/orphan-reap.d.ts +0 -253
- package/dist/lib/tmux/orphan-reap.js +3 -299
- package/dist/lib/tmux/paths.d.ts +0 -14
- package/dist/lib/tmux/paths.js +0 -14
- package/dist/lib/tmux/session.d.ts +0 -263
- package/dist/lib/tmux/session.js +6 -344
- package/dist/lib/traces/backend.d.ts +0 -20
- package/dist/lib/traces/backend.js +0 -23
- package/dist/lib/traces/classify.d.ts +0 -20
- package/dist/lib/traces/classify.js +0 -7
- package/dist/lib/traces/insights.d.ts +1 -84
- package/dist/lib/traces/insights.js +0 -126
- package/dist/lib/traces/phenotype.d.ts +0 -69
- package/dist/lib/traces/phenotype.js +0 -150
- package/dist/lib/traces/provision.d.ts +0 -1
- package/dist/lib/traces/provision.js +0 -5
- package/dist/lib/traces/schema2-build.d.ts +3 -60
- package/dist/lib/traces/schema2-build.js +8 -149
- package/dist/lib/traces/schema2-danger.d.ts +0 -30
- package/dist/lib/traces/schema2-danger.js +1 -63
- package/dist/lib/traces/schema2.d.ts +0 -11
- package/dist/lib/traces/segments.d.ts +0 -44
- package/dist/lib/traces/segments.js +0 -65
- package/dist/lib/traces/sync.d.ts +2 -239
- package/dist/lib/traces/sync.js +15 -237
- package/dist/lib/traces/worker-template.d.ts +0 -3
- package/dist/lib/traces/worker-template.js +0 -29
- package/dist/lib/triggers/handlers.d.ts +0 -82
- package/dist/lib/triggers/handlers.js +0 -75
- package/dist/lib/triggers/webhook.d.ts +0 -158
- package/dist/lib/triggers/webhook.js +0 -143
- package/dist/lib/types.d.ts +0 -736
- package/dist/lib/types.js +0 -50
- package/dist/lib/uninstall.d.ts +0 -17
- package/dist/lib/uninstall.js +0 -75
- package/dist/lib/usage-backoff.d.ts +0 -20
- package/dist/lib/usage-backoff.js +3 -60
- package/dist/lib/usage-refresh.d.ts +0 -154
- package/dist/lib/usage-refresh.js +8 -212
- package/dist/lib/verbs.d.ts +0 -12
- package/dist/lib/verbs.js +0 -12
- package/dist/lib/version-duplicates.d.ts +0 -6
- package/dist/lib/version-duplicates.js +0 -6
- package/dist/lib/version.d.ts +0 -55
- package/dist/lib/version.js +1 -58
- package/dist/lib/view-types.d.ts +0 -48
- package/dist/lib/warn-unpushed.d.ts +0 -27
- package/dist/lib/warn-unpushed.js +1 -45
- package/dist/lib/watchdog/history.d.ts +0 -1
- package/dist/lib/watchdog/history.js +0 -3
- package/dist/lib/watchdog/index.js +0 -2
- package/dist/lib/watchdog/log.d.ts +0 -19
- package/dist/lib/watchdog/log.js +0 -34
- package/dist/lib/watchdog/read.d.ts +0 -27
- package/dist/lib/watchdog/read.js +3 -58
- package/dist/lib/watchdog/rotate.d.ts +0 -139
- package/dist/lib/watchdog/rotate.js +2 -151
- package/dist/lib/watchdog/runner.d.ts +0 -125
- package/dist/lib/watchdog/runner.js +3 -223
- package/dist/lib/watchdog/service.d.ts +0 -1
- package/dist/lib/watchdog/service.js +0 -2
- package/dist/lib/watchdog/watchdog-agent.d.ts +0 -31
- package/dist/lib/watchdog/watchdog-agent.js +0 -27
- package/dist/lib/watchdog/watchdog.d.ts +0 -7
- package/dist/lib/watchdog/watchdog.js +0 -10
- package/dist/lib/watchdog/watchdogTail.js +0 -7
- package/dist/lib/whats-new.d.ts +0 -10
- package/dist/lib/whats-new.js +0 -21
- package/dist/lib/workflows-registry.d.ts +0 -45
- package/dist/lib/workflows-registry.js +0 -60
- package/dist/lib/workflows.d.ts +0 -282
- package/dist/lib/workflows.js +3 -213
- package/dist/lib/worktree/held.d.ts +0 -89
- package/dist/lib/worktree/held.js +1 -103
- package/dist/lib/wrap.d.ts +0 -32
- package/dist/lib/wrap.js +0 -32
- package/dist/lib/yaml-io.d.ts +0 -45
- package/dist/lib/yaml-io.js +0 -47
- package/dist/session-tracker/dist/adapters/claude.js +0 -2
- package/dist/session-tracker/dist/hook.sh +4 -37
- package/dist/session-tracker/dist/index.d.ts +0 -7
- package/dist/session-tracker/dist/index.js +0 -5
- package/dist/session-tracker/dist/install-hook.d.ts +0 -5
- package/dist/session-tracker/dist/install-hook.js +1 -15
- package/dist/session-tracker/dist/prune-state.js +0 -4
- package/dist/session-tracker/dist/reader.js +0 -4
- package/dist/session-tracker/dist/state-file.d.ts +0 -3
- package/dist/session-tracker/dist/state-file.js +3 -8
- package/package.json +3 -4
- package/scripts/postinstall.js +8 -116
- package/dist/lib/session/artifacts.d.ts +0 -14
- package/dist/lib/session/artifacts.js +0 -101
- package/dist/lib/session/bash-command.d.ts +0 -63
- package/dist/lib/session/bash-command.js +0 -490
- package/dist/lib/session/digest.d.ts +0 -66
- package/dist/lib/session/digest.js +0 -328
- package/dist/lib/session/highlights.d.ts +0 -151
- package/dist/lib/session/highlights.js +0 -391
- package/dist/lib/session/insights.d.ts +0 -165
- package/dist/lib/session/insights.js +0 -563
- package/dist/lib/session/linear.d.ts +0 -19
- package/dist/lib/session/linear.js +0 -99
- package/dist/lib/session/parse.d.ts +0 -224
- package/dist/lib/session/parse.js +0 -2408
- package/dist/lib/session/prompt.d.ts +0 -213
- package/dist/lib/session/prompt.js +0 -601
- package/dist/lib/session/render.d.ts +0 -133
- package/dist/lib/session/render.js +0 -1047
- package/dist/lib/session/share-html.d.ts +0 -35
- package/dist/lib/session/share-html.js +0 -319
- package/dist/lib/session/shell-programs.d.ts +0 -33
- package/dist/lib/session/shell-programs.js +0 -380
- package/dist/lib/session/state.d.ts +0 -269
- package/dist/lib/session/state.js +0 -777
- package/dist/lib/session/stream-render.d.ts +0 -4
- package/dist/lib/session/stream-render.js +0 -131
- package/dist/lib/session/tail.d.ts +0 -88
- package/dist/lib/session/tail.js +0 -294
- package/dist/lib/session/team-filter.d.ts +0 -129
- package/dist/lib/session/team-filter.js +0 -269
- package/dist/lib/session/timeline.d.ts +0 -172
- package/dist/lib/session/timeline.js +0 -636
- package/dist/lib/session/tool-calls.d.ts +0 -132
- package/dist/lib/session/tool-calls.js +0 -674
- package/dist/lib/session/trajectory-compare.d.ts +0 -48
- package/dist/lib/session/trajectory-compare.js +0 -116
- package/dist/lib/session/trajectory-html.d.ts +0 -19
- package/dist/lib/session/trajectory-html.js +0 -771
- package/dist/lib/session/trajectory-lineage.d.ts +0 -93
- package/dist/lib/session/trajectory-lineage.js +0 -195
- package/dist/lib/session/trajectory-text.d.ts +0 -38
- package/dist/lib/session/trajectory-text.js +0 -284
- package/dist/lib/session/trajectory.d.ts +0 -145
- package/dist/lib/session/trajectory.js +0 -394
- package/dist/lib/session/types.d.ts +0 -627
- package/dist/lib/session/types.js +0 -43
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Version lifecycle, resource sync, and agent@version resolution for agents-cli.
|
|
3
|
-
* Each version lives in an isolated home under ~/.agents/.history/versions/{agent}/{version}/.
|
|
4
|
-
*/
|
|
5
1
|
import * as fs from 'fs';
|
|
6
2
|
import * as path from 'path';
|
|
7
3
|
import * as yaml from 'yaml';
|
|
@@ -13,9 +9,6 @@ import { getVersionsDir, ensureAgentsDir, readMeta, writeMeta, getSkillsDir, get
|
|
|
13
9
|
import { defaultPatterns, expandPatterns } from '../resource-patterns.js';
|
|
14
10
|
import { listResources } from '../resources.js';
|
|
15
11
|
import { activeRulesPreset, filterNamesForActiveResourceProfile } from '../resource-profiles.js';
|
|
16
|
-
// VERSION_RE + compareVersions are owned by the agent-spec engine primitives
|
|
17
|
-
// (single source of truth). Re-exported below so existing importers of
|
|
18
|
-
// `compareVersions` from './versions.js' keep working.
|
|
19
12
|
import { VERSION_RE, compareVersions } from '../agent-spec/primitives.js';
|
|
20
13
|
import { AGENTS, agentConfigDirName, getAccountEmail, resolveAgentName, formatAgentError, findInPath, isSelfUpdatingAgent, isAgentHardDeprecated, hardDeprecationError } from '../agents.js';
|
|
21
14
|
import { discoverPermissionGroups, getActivePermissionPresetName, readPermissionPresetRecipe, PERMISSION_PRESET_ENV_VAR } from '../permissions.js';
|
|
@@ -44,7 +37,6 @@ import { syncMemoryToVersionHome, syncClaudeProjectMemoryDir } from '../memory.j
|
|
|
44
37
|
import { listPluginSkillNames, resolveCommandSource, resolveSkillSource } from '../staleness/writers/sources.js';
|
|
45
38
|
import { syncProjectResourcesToAgent } from '../project-resources.js';
|
|
46
39
|
import { installClaudeStatusLine } from '../claude-statusline.js';
|
|
47
|
-
/** Promisified exec for running shell commands. */
|
|
48
40
|
const execAsync = promisify(exec);
|
|
49
41
|
const execFileAsync = promisify(execFile);
|
|
50
42
|
const RULES_DOC_FILENAME = 'README.md';
|
|
@@ -112,7 +104,6 @@ function sourceMapFromWorkflows(cwd) {
|
|
|
112
104
|
.filter(d => d.isDirectory() && fs.existsSync(path.join(dir, d.name, 'WORKFLOW.md')))
|
|
113
105
|
.map(d => d.name));
|
|
114
106
|
}
|
|
115
|
-
// Attribute each plugin to the layer it resolves from so `system:*` selections include system-layer plugins.
|
|
116
107
|
function sourceMapFromPlugins(cwd) {
|
|
117
108
|
return sourceMapFromLayeredDirectory(cwd, ['plugins'], (dir) => fs.readdirSync(dir, { withFileTypes: true })
|
|
118
109
|
.filter(d => d.isDirectory() && fs.existsSync(path.join(dir, d.name, '.claude-plugin', 'plugin.json')))
|
|
@@ -141,7 +132,6 @@ function sourceMapFromPluginSkills(plugins, activePluginNames, cwd) {
|
|
|
141
132
|
}
|
|
142
133
|
return sources;
|
|
143
134
|
}
|
|
144
|
-
/** Discover all resources available for syncing from ~/.agents/. */
|
|
145
135
|
export function getAvailableResources(cwd = process.cwd()) {
|
|
146
136
|
const result = {
|
|
147
137
|
commands: [],
|
|
@@ -157,7 +147,6 @@ export function getAvailableResources(cwd = process.cwd()) {
|
|
|
157
147
|
};
|
|
158
148
|
const projectAgentsDir = getProjectAgentsDir(cwd);
|
|
159
149
|
const resourceBases = getResourceBases(cwd);
|
|
160
|
-
// Commands (*.md files)
|
|
161
150
|
const commandNames = new Set();
|
|
162
151
|
for (const { base } of resourceBases) {
|
|
163
152
|
const commandsDir = path.join(base, 'commands');
|
|
@@ -171,7 +160,6 @@ export function getAvailableResources(cwd = process.cwd()) {
|
|
|
171
160
|
}
|
|
172
161
|
}
|
|
173
162
|
result.commands = filterNamesForActiveResourceProfile('commands', Array.from(commandNames), sourceMapFromResources('commands', cwd));
|
|
174
|
-
// Skills (directories, excluding hidden)
|
|
175
163
|
const skillNames = new Set();
|
|
176
164
|
for (const { base } of resourceBases) {
|
|
177
165
|
const skillsDir = path.join(base, 'skills');
|
|
@@ -185,7 +173,6 @@ export function getAvailableResources(cwd = process.cwd()) {
|
|
|
185
173
|
}
|
|
186
174
|
}
|
|
187
175
|
result.skills = filterNamesForActiveResourceProfile('skills', Array.from(skillNames), sourceMapFromResources('skills', cwd));
|
|
188
|
-
// Hooks: top-level scripts, expanded one-level group dirs, or whole-dir bundles. Exec bit alone is not the signal (older syncs chmod'd everything).
|
|
189
176
|
const NON_SCRIPT_EXTS = new Set(['.md', '.markdown', '.rst', '.txt', '.yaml', '.yml', '.json', '.toml', '.ini', '.conf']);
|
|
190
177
|
const SCRIPT_EXTS = new Set(['.sh', '.bash', '.zsh', '.py', '.js', '.ts', '.mjs', '.cjs', '.rb', '.pl', '.ps1']);
|
|
191
178
|
const HOOK_GROUP_SKIP = new Set(['node_modules', '.git', '.cache']);
|
|
@@ -215,7 +202,6 @@ export function getAvailableResources(cwd = process.cwd()) {
|
|
|
215
202
|
}
|
|
216
203
|
if (!stat.isDirectory() || HOOK_GROUP_SKIP.has(name))
|
|
217
204
|
continue;
|
|
218
|
-
// Expand dirs containing top-level scripts; bundle dirs without any.
|
|
219
205
|
let nestedNames;
|
|
220
206
|
try {
|
|
221
207
|
nestedNames = fs.readdirSync(full);
|
|
@@ -235,7 +221,7 @@ export function getAvailableResources(cwd = process.cwd()) {
|
|
|
235
221
|
if (isHookScriptName(nested, nstat.mode))
|
|
236
222
|
scripts.push(nested);
|
|
237
223
|
}
|
|
238
|
-
catch {
|
|
224
|
+
catch { }
|
|
239
225
|
}
|
|
240
226
|
if (scripts.length > 0) {
|
|
241
227
|
for (const s of scripts)
|
|
@@ -245,11 +231,10 @@ export function getAvailableResources(cwd = process.cwd()) {
|
|
|
245
231
|
hookNames.add(name);
|
|
246
232
|
}
|
|
247
233
|
}
|
|
248
|
-
catch {
|
|
234
|
+
catch { }
|
|
249
235
|
}
|
|
250
236
|
}
|
|
251
237
|
result.hooks = filterNamesForActiveResourceProfile('hooks', Array.from(hookNames), sourceMapFromResources('hooks', cwd));
|
|
252
|
-
// Rules — list available presets across layers.
|
|
253
238
|
const presetNames = new Set();
|
|
254
239
|
const rulesDirs = [];
|
|
255
240
|
if (projectAgentsDir)
|
|
@@ -270,7 +255,6 @@ export function getAvailableResources(cwd = process.cwd()) {
|
|
|
270
255
|
}
|
|
271
256
|
}
|
|
272
257
|
catch {
|
|
273
|
-
// malformed rules.yaml — skip silently; the composer will surface the error.
|
|
274
258
|
}
|
|
275
259
|
}
|
|
276
260
|
result.memory = filterNamesForActiveResourceProfile('memory', Array.from(presetNames));
|
|
@@ -293,7 +277,6 @@ export function getAvailableResources(cwd = process.cwd()) {
|
|
|
293
277
|
result.subagents = filterNamesForActiveResourceProfile('subagents', Array.from(subagentNames), sourceMapFromResources('subagents', cwd));
|
|
294
278
|
const workflowSources = sourceMapFromWorkflows(cwd);
|
|
295
279
|
result.workflows = filterNamesForActiveResourceProfile('workflows', Array.from(workflowSources.keys()), workflowSources);
|
|
296
|
-
// Plugins (directories with .claude-plugin/plugin.json)
|
|
297
280
|
const allPlugins = discoverPlugins();
|
|
298
281
|
result.plugins = filterNamesForActiveResourceProfile('plugins', allPlugins.map(p => p.name), new Map(allPlugins.map(p => [p.name, 'user'])));
|
|
299
282
|
const activePlugins = new Set(result.plugins);
|
|
@@ -302,17 +285,13 @@ export function getAvailableResources(cwd = process.cwd()) {
|
|
|
302
285
|
if (!skillNames.has(name))
|
|
303
286
|
result.skills.push(name);
|
|
304
287
|
}
|
|
305
|
-
// Promptcuts — present if either layer exists. Reads merge user + system
|
|
306
|
-
// with user precedence (see readMergedPromptcuts); writes always go to user.
|
|
307
288
|
result.promptcuts = fs.existsSync(getUserPromptcutsPath()) || fs.existsSync(getPromptcutsPath());
|
|
308
289
|
return result;
|
|
309
290
|
}
|
|
310
|
-
// Files/dirs that are never synced into a version home (OS metadata, local tooling).
|
|
311
291
|
const SKILL_COPY_IGNORE = new Set(['.DS_Store', '.git', '.gitignore', '.venv', '__pycache__', 'node_modules']);
|
|
312
292
|
function shouldSkillEntryBeSkipped(name) {
|
|
313
293
|
return SKILL_COPY_IGNORE.has(name);
|
|
314
294
|
}
|
|
315
|
-
/** Recursively compare two directories for identical content, skipping symlinks and ignored entries. */
|
|
316
295
|
function skillDirsMatch(src, dest) {
|
|
317
296
|
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
318
297
|
for (const entry of entries) {
|
|
@@ -329,7 +308,6 @@ function skillDirsMatch(src, dest) {
|
|
|
329
308
|
return false;
|
|
330
309
|
}
|
|
331
310
|
else {
|
|
332
|
-
// Size-first check avoids reads on mismatch; equal mtimes are unreliable across trees.
|
|
333
311
|
let srcStat;
|
|
334
312
|
let destStat;
|
|
335
313
|
try {
|
|
@@ -341,13 +319,12 @@ function skillDirsMatch(src, dest) {
|
|
|
341
319
|
}
|
|
342
320
|
if (srcStat.size !== destStat.size)
|
|
343
321
|
return false;
|
|
344
|
-
if (fs.readFileSync(srcPath
|
|
322
|
+
if (!fs.readFileSync(srcPath).equals(fs.readFileSync(destPath)))
|
|
345
323
|
return false;
|
|
346
324
|
}
|
|
347
325
|
}
|
|
348
326
|
return true;
|
|
349
327
|
}
|
|
350
|
-
/** Return what's actually synced to a version home (source of truth, not agents.yaml tracking). */
|
|
351
328
|
export function getActuallySyncedResources(agent, version, options = {}) {
|
|
352
329
|
const versionHome = path.join(getVersionsDir(), agent, version, 'home');
|
|
353
330
|
const cwd = options.cwd || process.cwd();
|
|
@@ -363,7 +340,6 @@ export function getActuallySyncedResources(agent, version, options = {}) {
|
|
|
363
340
|
workflows: [],
|
|
364
341
|
promptcuts: false,
|
|
365
342
|
};
|
|
366
|
-
// Dispatch through per-kind detectors; unsupported (agent, kind) pairs leave the field empty.
|
|
367
343
|
const ctx = { version, versionHome, cwd };
|
|
368
344
|
result.commands = getDetector('commands', agent)?.list(ctx) ?? [];
|
|
369
345
|
result.skills = getDetector('skills', agent)?.list(ctx) ?? [];
|
|
@@ -376,7 +352,6 @@ export function getActuallySyncedResources(agent, version, options = {}) {
|
|
|
376
352
|
result.workflows = getDetector('workflows', agent)?.list(ctx) ?? [];
|
|
377
353
|
return result;
|
|
378
354
|
}
|
|
379
|
-
/** Names that exist only in the project's `.agents/` layer. Sync skips project-layer resources for security, so filter them out of the "new resources" diff. */
|
|
380
355
|
export function getProjectOnlyResources(cwd = process.cwd()) {
|
|
381
356
|
const empty = {
|
|
382
357
|
commands: new Set(), skills: new Set(), hooks: new Set(),
|
|
@@ -400,7 +375,7 @@ export function getProjectOnlyResources(cwd = process.cwd()) {
|
|
|
400
375
|
acc.add(entry);
|
|
401
376
|
}
|
|
402
377
|
}
|
|
403
|
-
catch {
|
|
378
|
+
catch { }
|
|
404
379
|
}
|
|
405
380
|
return acc;
|
|
406
381
|
};
|
|
@@ -440,8 +415,6 @@ export function getProjectOnlyResources(cwd = process.cwd()) {
|
|
|
440
415
|
for (const n of readProjectNames('skills', (full) => isDir(full)))
|
|
441
416
|
if (!trustedSkills.has(n))
|
|
442
417
|
empty.skills.add(n);
|
|
443
|
-
// Hooks: project entries are files; trusted entries are also files. Name match
|
|
444
|
-
// is filename-with-extension (sync compares by full filename, line 2031).
|
|
445
418
|
const trustedHooks = trustedNames('hooks', (full) => { try {
|
|
446
419
|
return fs.statSync(full).isFile();
|
|
447
420
|
}
|
|
@@ -474,7 +447,6 @@ export function getProjectOnlyResources(cwd = process.cwd()) {
|
|
|
474
447
|
}
|
|
475
448
|
return empty;
|
|
476
449
|
}
|
|
477
|
-
/** Return resources in `available` that are not yet synced to the version home. `projectOnly` filters project-layer resources that sync skips for security. */
|
|
478
450
|
export function getNewResources(available, actuallySynced, projectOnly) {
|
|
479
451
|
const exclude = projectOnly || {
|
|
480
452
|
commands: new Set(), skills: new Set(), hooks: new Set(),
|
|
@@ -484,7 +456,6 @@ export function getNewResources(available, actuallySynced, projectOnly) {
|
|
|
484
456
|
commands: available.commands.filter(c => !actuallySynced.commands.includes(c) && !exclude.commands.has(c)),
|
|
485
457
|
skills: available.skills.filter(s => !actuallySynced.skills.includes(s) && !exclude.skills.has(s)),
|
|
486
458
|
hooks: available.hooks.filter(h => !actuallySynced.hooks.includes(h) && !exclude.hooks.has(h)),
|
|
487
|
-
// Only one rules preset can be active; if any is synced, don't report others as new.
|
|
488
459
|
memory: actuallySynced.memory.length > 0
|
|
489
460
|
? []
|
|
490
461
|
: available.memory.filter(m => !actuallySynced.memory.includes(m)),
|
|
@@ -493,11 +464,9 @@ export function getNewResources(available, actuallySynced, projectOnly) {
|
|
|
493
464
|
subagents: available.subagents.filter(s => !actuallySynced.subagents.includes(s) && !exclude.subagents.has(s)),
|
|
494
465
|
plugins: available.plugins.filter(p => !actuallySynced.plugins.includes(p) && !exclude.plugins.has(p)),
|
|
495
466
|
workflows: available.workflows.filter(w => !actuallySynced.workflows.includes(w) && !exclude.workflows.has(w)),
|
|
496
|
-
// Promptcuts are not version-scoped; the hook reads the user/system file directly.
|
|
497
467
|
promptcuts: false,
|
|
498
468
|
};
|
|
499
469
|
}
|
|
500
|
-
/** Return true when `diff` contains any resources the agent/version actually supports. */
|
|
501
470
|
export function hasNewResources(diff, agent, version) {
|
|
502
471
|
const commandsApply = agent ? supports(agent, 'commands', version).ok : true;
|
|
503
472
|
const hooksApply = agent ? supports(agent, 'hooks', version).ok : true;
|
|
@@ -516,11 +485,9 @@ export function hasNewResources(diff, agent, version) {
|
|
|
516
485
|
(diff.plugins.length > 0 && pluginsApply) ||
|
|
517
486
|
(diff.workflows.length > 0 && workflowsApply));
|
|
518
487
|
}
|
|
519
|
-
/** Build a human-readable summary of new resources, e.g. "2 commands, 5 permission groups". */
|
|
520
488
|
function buildNewResourcesSummary(newResources, agent, version) {
|
|
521
489
|
const agentConfig = AGENTS[agent];
|
|
522
490
|
const parts = [];
|
|
523
|
-
// Version-aware gates avoid double-counting commands already emitted as skills (Codex >= 0.117.0).
|
|
524
491
|
const commandsApply = supports(agent, 'commands', version).ok;
|
|
525
492
|
const commandsAsSkills = version ? shouldInstallCommandAsSkill(agent, version) : false;
|
|
526
493
|
const rulesApply = supports(agent, 'rules', version).ok;
|
|
@@ -553,13 +520,9 @@ function buildNewResourcesSummary(newResources, agent, version) {
|
|
|
553
520
|
}
|
|
554
521
|
return parts.join(', ');
|
|
555
522
|
}
|
|
556
|
-
/** Prompt the user to select which new resources to sync. */
|
|
557
523
|
export async function promptNewResourceSelection(agent, newResources, version) {
|
|
558
524
|
const agentConfig = AGENTS[agent];
|
|
559
525
|
const selection = {};
|
|
560
|
-
// Version-aware gates. When version is known, prefer per-version capability checks; the
|
|
561
|
-
// commands branch is allowed when either native commands are supported OR when the
|
|
562
|
-
// version emits commands as converted skills (Codex >= 0.117.0).
|
|
563
526
|
const commandsApply = supports(agent, 'commands', version).ok;
|
|
564
527
|
const commandsAsSkills = version ? shouldInstallCommandAsSkill(agent, version) : false;
|
|
565
528
|
const commandsBranch = commandsApply || commandsAsSkills;
|
|
@@ -687,7 +650,6 @@ export async function promptNewResourceSelection(agent, newResources, version) {
|
|
|
687
650
|
}
|
|
688
651
|
return selection;
|
|
689
652
|
}
|
|
690
|
-
/** Prompt the user to select which resources to sync from ~/.agents/. */
|
|
691
653
|
export async function promptResourceSelection(agent) {
|
|
692
654
|
const available = getAvailableResources();
|
|
693
655
|
const agentConfig = AGENTS[agent];
|
|
@@ -718,7 +680,7 @@ export async function promptResourceSelection(agent) {
|
|
|
718
680
|
...availableCategories.map(c => ({
|
|
719
681
|
name: `${c.label} (${c.displayCount})`,
|
|
720
682
|
value: c.key,
|
|
721
|
-
checked: true,
|
|
683
|
+
checked: true,
|
|
722
684
|
})),
|
|
723
685
|
],
|
|
724
686
|
});
|
|
@@ -789,11 +751,9 @@ export async function promptResourceSelection(agent) {
|
|
|
789
751
|
}
|
|
790
752
|
}
|
|
791
753
|
}
|
|
792
|
-
// 'skip' means we don't set anything for this category
|
|
793
754
|
}
|
|
794
755
|
return selection;
|
|
795
756
|
}
|
|
796
|
-
/** Parse an `agent@version` spec; bare agent means `latest`. */
|
|
797
757
|
export function parseAgentSpec(spec) {
|
|
798
758
|
const parts = spec.split('@');
|
|
799
759
|
if (parts.length > 2) {
|
|
@@ -804,8 +764,6 @@ export function parseAgentSpec(spec) {
|
|
|
804
764
|
if (!agent) {
|
|
805
765
|
return null;
|
|
806
766
|
}
|
|
807
|
-
// Reject any version string that could escape an exec context or a
|
|
808
|
-
// bash-shim interpolation. Real agent versions are semver-shaped or "latest".
|
|
809
767
|
if (!VERSION_RE.test(version)) {
|
|
810
768
|
return null;
|
|
811
769
|
}
|
|
@@ -833,7 +791,6 @@ export async function getOldestNpmVersion(agent) {
|
|
|
833
791
|
try {
|
|
834
792
|
const { stdout } = await execFileAsync('npm', ['view', agentConfig.npmPackage, 'versions', '--json'], { shell: process.platform === 'win32' });
|
|
835
793
|
const parsed = JSON.parse(stdout.trim());
|
|
836
|
-
// npm view returns an array for multiple versions or a bare string for one.
|
|
837
794
|
const versions = Array.isArray(parsed) ? parsed : [parsed];
|
|
838
795
|
const sorted = versions.filter((v) => VERSION_RE.test(v)).sort(compareVersions);
|
|
839
796
|
return sorted[0] ?? null;
|
|
@@ -842,7 +799,6 @@ export async function getOldestNpmVersion(agent) {
|
|
|
842
799
|
return null;
|
|
843
800
|
}
|
|
844
801
|
}
|
|
845
|
-
/** Check whether the npm `latest` version is installed. */
|
|
846
802
|
export async function isLatestInstalled(agent) {
|
|
847
803
|
const latestVersion = await getLatestNpmVersion(agent);
|
|
848
804
|
if (!latestVersion) {
|
|
@@ -850,7 +806,6 @@ export async function isLatestInstalled(agent) {
|
|
|
850
806
|
}
|
|
851
807
|
return { installed: isVersionInstalled(agent, latestVersion), version: latestVersion };
|
|
852
808
|
}
|
|
853
|
-
/** Check whether the npm `oldest` version is installed. */
|
|
854
809
|
export async function isOldestInstalled(agent) {
|
|
855
810
|
const oldestVersion = await getOldestNpmVersion(agent);
|
|
856
811
|
if (!oldestVersion) {
|
|
@@ -858,11 +813,6 @@ export async function isOldestInstalled(agent) {
|
|
|
858
813
|
}
|
|
859
814
|
return { installed: isVersionInstalled(agent, oldestVersion), version: oldestVersion };
|
|
860
815
|
}
|
|
861
|
-
/**
|
|
862
|
-
* List every version directory for an agent, including home-only leftovers, for
|
|
863
|
-
* `agents prune cleanup` only. Do NOT use elsewhere — every other call site
|
|
864
|
-
* assumes a working binary.
|
|
865
|
-
*/
|
|
866
816
|
export function listInstalledVersionDirs(agent) {
|
|
867
817
|
const agentVersionsDir = path.join(getVersionsDir(), agent);
|
|
868
818
|
if (!fs.existsSync(agentVersionsDir)) {
|
|
@@ -880,9 +830,7 @@ export function listInstalledVersionDirs(agent) {
|
|
|
880
830
|
}
|
|
881
831
|
return out.sort((a, b) => compareVersions(a.version, b.version));
|
|
882
832
|
}
|
|
883
|
-
/** Set (or clear) the global default version for an agent. */
|
|
884
833
|
export function setGlobalDefault(agent, version) {
|
|
885
|
-
// Setting a global default for an isolated-only agent would breach the isolation boundary; clearing is allowed.
|
|
886
834
|
if (version !== undefined) {
|
|
887
835
|
assertIsolationBoundary(agent, 'set a global default');
|
|
888
836
|
}
|
|
@@ -899,7 +847,6 @@ export function setGlobalDefault(agent, version) {
|
|
|
899
847
|
}
|
|
900
848
|
writeMeta(meta);
|
|
901
849
|
}
|
|
902
|
-
/** Set (or clear) the preferred isolated version without touching the launcher, shim, or global default. */
|
|
903
850
|
export function setIsolatedDefault(agent, version) {
|
|
904
851
|
const meta = readMeta();
|
|
905
852
|
if (!meta.isolatedAgents) {
|
|
@@ -913,11 +860,6 @@ export function setIsolatedDefault(agent, version) {
|
|
|
913
860
|
}
|
|
914
861
|
writeMeta(meta);
|
|
915
862
|
}
|
|
916
|
-
/**
|
|
917
|
-
* Move any `grok-<installedVersion>-...` binary (and its generic platform
|
|
918
|
-
* copy) found directly under `sourceDownloads` into `targetDownloads`.
|
|
919
|
-
* Returns true if the versioned binary was transferred.
|
|
920
|
-
*/
|
|
921
863
|
function transferGrokDownloads(sourceDownloads, targetDownloads, copy) {
|
|
922
864
|
if (!fs.existsSync(sourceDownloads))
|
|
923
865
|
return false;
|
|
@@ -940,8 +882,6 @@ function transferGrokDownloads(sourceDownloads, targetDownloads, copy) {
|
|
|
940
882
|
catch {
|
|
941
883
|
return false;
|
|
942
884
|
}
|
|
943
|
-
// The installer also creates a generic platform binary (e.g. grok-macos-aarch64)
|
|
944
|
-
// that is a copy of the versioned binary. Move it too if its size matches.
|
|
945
885
|
const movedSize = fs.statSync(transferred).size;
|
|
946
886
|
for (const entry of entries) {
|
|
947
887
|
if (entry === path.basename(realBinary))
|
|
@@ -959,24 +899,10 @@ function transferGrokDownloads(sourceDownloads, targetDownloads, copy) {
|
|
|
959
899
|
}
|
|
960
900
|
}
|
|
961
901
|
catch {
|
|
962
|
-
/* ignore per-file failures */
|
|
963
902
|
}
|
|
964
903
|
}
|
|
965
904
|
return true;
|
|
966
905
|
}
|
|
967
|
-
/**
|
|
968
|
-
* Grok's official installer writes into ~/.grok/downloads, which (because we
|
|
969
|
-
* symlink ~/.grok to the active version home) resolves to the PREVIOUS default
|
|
970
|
-
* home during `agents add grok@<new>`. Move the freshly-downloaded binary and
|
|
971
|
-
* its generic platform copy into the target version's isolated home so
|
|
972
|
-
* `listInstalledVersions` and the shim resolve the right binary.
|
|
973
|
-
*
|
|
974
|
-
* Self-healing: if `~/.grok`'s current target has nothing matching (e.g. a
|
|
975
|
-
* PAST install mislabeled `installedVersion` as the literal string 'latest',
|
|
976
|
-
* whose regex never matched the real filename, stranding the binary in
|
|
977
|
-
* whatever version was default at the time), sweep every other installed
|
|
978
|
-
* grok version home for the missing file before giving up.
|
|
979
|
-
*/
|
|
980
906
|
function relocateGrokBinaryToVersionHome(installationLabel, copyExisting) {
|
|
981
907
|
const hostGrokLink = path.join(getHomeDir(), agentConfigDirName('grok'));
|
|
982
908
|
let sourceDownloads;
|
|
@@ -994,33 +920,18 @@ function relocateGrokBinaryToVersionHome(installationLabel, copyExisting) {
|
|
|
994
920
|
continue;
|
|
995
921
|
const candidate = path.join(getVersionHomePath('grok', version), agentConfigDirName('grok'), 'downloads');
|
|
996
922
|
if (path.resolve(candidate) === path.resolve(sourceDownloads))
|
|
997
|
-
continue;
|
|
923
|
+
continue;
|
|
998
924
|
if (transferGrokDownloads(candidate, targetDownloads, copyExisting))
|
|
999
925
|
return;
|
|
1000
926
|
}
|
|
1001
927
|
}
|
|
1002
|
-
/**
|
|
1003
|
-
* Grok's version directory is keyed by release number alone, not by account —
|
|
1004
|
-
* so two DIFFERENT accounts that both self-update to the identical upstream
|
|
1005
|
-
* release ("latest") target the SAME on-disk `versions/grok/<version>/` home.
|
|
1006
|
-
* When that happens, the second account's `agents add grok@latest` writes
|
|
1007
|
-
* into an already-signed-in directory: grok's own auth flow treats
|
|
1008
|
-
* `~/.grok/auth.json` as authoritative for whichever process invoked it, so
|
|
1009
|
-
* the second account's credential record lands in a file that still names it
|
|
1010
|
-
* as the first account's install everywhere else in agents-cli's bookkeeping.
|
|
1011
|
-
*
|
|
1012
|
-
* Refuse before that happens: if the target version's home already has a
|
|
1013
|
-
* signed-in account whose identity differs from the account currently
|
|
1014
|
-
* driving this update (the previous global default), fail loud instead of
|
|
1015
|
-
* letting the second account silently displace the first's install.
|
|
1016
|
-
*/
|
|
1017
928
|
async function checkGrokAccountCollision(installedVersion) {
|
|
1018
929
|
const targetHome = getVersionHomePath('grok', installedVersion);
|
|
1019
930
|
if (!fs.existsSync(targetHome))
|
|
1020
|
-
return;
|
|
931
|
+
return;
|
|
1021
932
|
const sourceVersion = getGlobalDefault('grok');
|
|
1022
933
|
if (!sourceVersion || sourceVersion === installedVersion)
|
|
1023
|
-
return;
|
|
934
|
+
return;
|
|
1024
935
|
const [targetEmail, sourceEmail] = await Promise.all([
|
|
1025
936
|
getAccountEmail('grok', targetHome),
|
|
1026
937
|
getAccountEmail('grok', getVersionHomePath('grok', sourceVersion)),
|
|
@@ -1031,7 +942,6 @@ async function checkGrokAccountCollision(installedVersion) {
|
|
|
1031
942
|
`Grok's self-updater can't distinguish two accounts that land on the same release — sign in to ${targetEmail}'s ` +
|
|
1032
943
|
`install (agents use grok@${installedVersion}) before updating it, or wait until the releases diverge.`);
|
|
1033
944
|
}
|
|
1034
|
-
/** Install a specific version of an agent. */
|
|
1035
945
|
export async function installVersion(agent, version, onProgress, opts) {
|
|
1036
946
|
const agentConfig = AGENTS[agent];
|
|
1037
947
|
const requestedLabel = opts?.installationLabel ?? version;
|
|
@@ -1039,16 +949,9 @@ export async function installVersion(agent, version, onProgress, opts) {
|
|
|
1039
949
|
if (isAgentHardDeprecated(agent)) {
|
|
1040
950
|
return { success: false, installedVersion: version, error: hardDeprecationError(agent) };
|
|
1041
951
|
}
|
|
1042
|
-
// Also validate at the source so direct callers and tests cannot pass invalid versions.
|
|
1043
952
|
if (!VERSION_RE.test(version)) {
|
|
1044
953
|
throw new Error(`Invalid version: ${JSON.stringify(version)}`);
|
|
1045
954
|
}
|
|
1046
|
-
// A caller-supplied installation label decouples the addressable version-dir
|
|
1047
|
-
// name from the vendor release (PHNX-3940): `agents accounts add` mints an
|
|
1048
|
-
// opaque stable label so ten accounts can share the same upstream `latest`
|
|
1049
|
-
// under distinct isolated homes, each with its own native login. It follows
|
|
1050
|
-
// the same identity/release split the installScript branch already uses via
|
|
1051
|
-
// `requestedLabel`, and must be a real label, never a release alias.
|
|
1052
955
|
if (opts?.installationLabel !== undefined) {
|
|
1053
956
|
if (!VERSION_RE.test(opts.installationLabel)) {
|
|
1054
957
|
throw new Error(`Invalid installation label: ${JSON.stringify(opts.installationLabel)}`);
|
|
@@ -1061,7 +964,6 @@ export async function installVersion(agent, version, onProgress, opts) {
|
|
|
1061
964
|
if (!agentConfig.installScript) {
|
|
1062
965
|
return { success: false, installedVersion: version, error: 'Agent has no npm package' };
|
|
1063
966
|
}
|
|
1064
|
-
// Self-updating agents have no pinnable semver; an installed binary is a no-op, otherwise redirect to latest.
|
|
1065
967
|
let runInstaller = true;
|
|
1066
968
|
if (version !== 'latest' && isSelfUpdatingAgent(agent)) {
|
|
1067
969
|
const liveVersion = await getLiveVersion(agent);
|
|
@@ -1082,15 +984,6 @@ export async function installVersion(agent, version, onProgress, opts) {
|
|
|
1082
984
|
await execAsync(script, { timeout: 120000 });
|
|
1083
985
|
}
|
|
1084
986
|
if (version === 'latest') {
|
|
1085
|
-
// A freshly-installed self-updating binary (grok, …) can take a
|
|
1086
|
-
// moment to become resolvable on PATH right after the installer
|
|
1087
|
-
// exits — retry briefly rather than silently falling back to the
|
|
1088
|
-
// literal string 'latest'. That fallback used to corrupt version
|
|
1089
|
-
// bookkeeping downstream: it creates a bogus `versions/<agent>/latest/`
|
|
1090
|
-
// dir, and for grok specifically defeats relocateGrokBinaryToVersionHome
|
|
1091
|
-
// (its exact-filename regex can never match `grok-latest-...`), which
|
|
1092
|
-
// permanently strands the real downloaded binary in the PREVIOUS
|
|
1093
|
-
// default's downloads dir.
|
|
1094
987
|
let probed = await getCliVersionFromPath(agent);
|
|
1095
988
|
for (let attempt = 0; !probed && attempt < 2; attempt++) {
|
|
1096
989
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
@@ -1104,15 +997,8 @@ export async function installVersion(agent, version, onProgress, opts) {
|
|
|
1104
997
|
};
|
|
1105
998
|
}
|
|
1106
999
|
releaseVersion = probed;
|
|
1107
|
-
// Fold any stale literal `latest` dir from an earlier probe-failed
|
|
1108
|
-
// install into the real version so it stops shadowing `agents view`.
|
|
1109
1000
|
await reconcileStaleLatestDir(agent, releaseVersion);
|
|
1110
1001
|
}
|
|
1111
|
-
// Self-updating installers always fetch the current vendor release, but a
|
|
1112
|
-
// concrete requested token is still the stable installation/account slot.
|
|
1113
|
-
// Keeping the two strings separate lets several homes carry the same
|
|
1114
|
-
// release without sharing credentials. `latest` remains the convenient
|
|
1115
|
-
// release-named slot; concrete tokens remain exactly addressable.
|
|
1116
1002
|
const installationLabel = requestedLabel === 'latest' ? releaseVersion : requestedLabel;
|
|
1117
1003
|
if (agent === 'grok') {
|
|
1118
1004
|
await checkGrokAccountCollision(installationLabel);
|
|
@@ -1128,66 +1014,25 @@ export async function installVersion(agent, version, onProgress, opts) {
|
|
|
1128
1014
|
const versionDir = getVersionDir(agent, installationLabel);
|
|
1129
1015
|
fs.mkdirSync(versionDir, { recursive: true });
|
|
1130
1016
|
fs.mkdirSync(path.join(versionDir, 'home'), { recursive: true });
|
|
1131
|
-
// Grok's installer drops the binary into ~/.grok/downloads, which currently
|
|
1132
|
-
// resolves to the PREVIOUS default home. Move it into the target version home
|
|
1133
|
-
// so version isolation is correct.
|
|
1134
1017
|
if (agent === 'grok') {
|
|
1135
1018
|
relocateGrokBinaryToVersionHome(installationLabel, !runInstaller);
|
|
1136
1019
|
}
|
|
1137
|
-
// Symlink the installed binary into the version's node_modules/.bin so
|
|
1138
|
-
// listInstalledVersions (which checks getBinaryPath) sees this version as
|
|
1139
|
-
// installed. Without this, `agents add antigravity@latest` succeeds
|
|
1140
|
-
// but `agents view` shows the agent under "Not Managed" because
|
|
1141
|
-
// listInstalledVersions returns [] — the installer drops the binary in
|
|
1142
|
-
// ~/.local/bin (or similar) rather than the version's node_modules/.bin.
|
|
1143
|
-
//
|
|
1144
|
-
// Agents whose binary is special-cased in getBinaryPath (grok ->
|
|
1145
|
-
// ~/.grok/downloads, droid/muse -> ~/.local/bin/<cli>) need no symlink — and
|
|
1146
|
-
// creating one is actively harmful: `which <cli>` can resolve to OUR OWN
|
|
1147
|
-
// dispatcher shim, because ~/.agents/.cache/shims sits ahead of ~/.local/bin
|
|
1148
|
-
// on PATH. Symlinking node_modules/.bin/<cli> at the shim makes the shim
|
|
1149
|
-
// exec itself forever. So we skip the resolver-backed agents here AND, for
|
|
1150
|
-
// everyone else, filter the shims dir out of the `which` candidates so the
|
|
1151
|
-
// same race can't bite a non-special-cased installScript agent.
|
|
1152
1020
|
if (agent !== 'grok' && agent !== 'droid' && agent !== 'muse' && agent !== 'warp') {
|
|
1153
|
-
// findInPath is a pure-Node PATH scan that already skips our own shims
|
|
1154
|
-
// dir — so it returns the genuine install, never our dispatcher shim
|
|
1155
|
-
// (which sits ahead of ~/.local/bin on PATH and would otherwise be
|
|
1156
|
-
// captured, producing a self-referential node_modules/.bin/<cli> link
|
|
1157
|
-
// that exec-loops forever).
|
|
1158
1021
|
const installedBinary = findInPath(agentConfig.cliCommand);
|
|
1159
1022
|
if (installedBinary) {
|
|
1160
1023
|
importInstallScriptBinary({ agentId: agent, npmPackage: agentConfig.npmPackage, cliCommand: agentConfig.cliCommand }, installationLabel, installedBinary, versionDir);
|
|
1161
1024
|
}
|
|
1162
|
-
/* If null: binary missing from PATH (install script failed silently) or
|
|
1163
|
-
only our shim is present. Leave the version dir empty so getBinaryPath
|
|
1164
|
-
correctly reports it uninstalled. */
|
|
1165
1025
|
}
|
|
1166
1026
|
createVersionedAlias(agent, installationLabel);
|
|
1167
|
-
// Freeze this installation's identity. The dir name is its stable label from
|
|
1168
|
-
// here on; the release it carries is recorded separately so `agents update`
|
|
1169
|
-
// can move the release without invalidating any reference to the label.
|
|
1170
1027
|
createInstallation(agent, installationLabel, releaseVersion, initialUpdatePolicy);
|
|
1171
1028
|
const trackerInstall = await installSessionTrackerHook(agent, installationLabel);
|
|
1172
1029
|
if (!trackerInstall.installed && trackerInstall.error) {
|
|
1173
1030
|
console.warn(`agents: SessionStart hook not installed for ${agent}@${installationLabel}: ${trackerInstall.error}`);
|
|
1174
1031
|
}
|
|
1175
|
-
// The self-updating binary just changed on disk — drop the cached
|
|
1176
|
-
// `--version` so `agents view` reflects the freshly-installed release.
|
|
1177
1032
|
invalidateLiveVersionCache(agent);
|
|
1178
1033
|
emit('version.install', { agent, version: installationLabel });
|
|
1179
1034
|
return { success: true, installedVersion: installationLabel };
|
|
1180
1035
|
}
|
|
1181
|
-
// Resolve the `latest`/`oldest` aliases to a concrete npm version up front so
|
|
1182
|
-
// the rest of the install path treats them as an ordinary pinned install.
|
|
1183
|
-
// This is what keeps concurrent installs safe: resolving `latest` only AFTER
|
|
1184
|
-
// npm finished meant the install ran in a shared, well-known
|
|
1185
|
-
// `versions/<agent>/latest/` scratch dir that was renamed to the real version
|
|
1186
|
-
// at the end — so a concurrent `agents view` reconcile
|
|
1187
|
-
// (reconcileStaleLatestForAgent) or a second `latest` install could rename
|
|
1188
|
-
// that dir out from under npm mid-extraction and corrupt the install (the
|
|
1189
|
-
// seeded package.json and half-extracted node_modules would vanish, yielding
|
|
1190
|
-
// ENOENT). A concrete dir per version has no shared name to race on.
|
|
1191
1036
|
if (version === 'latest' || version === 'oldest') {
|
|
1192
1037
|
const resolved = version === 'latest'
|
|
1193
1038
|
? await getLatestNpmVersion(agent)
|
|
@@ -1201,48 +1046,28 @@ export async function installVersion(agent, version, onProgress, opts) {
|
|
|
1201
1046
|
}
|
|
1202
1047
|
version = resolved;
|
|
1203
1048
|
}
|
|
1204
|
-
// `version` is now the concrete vendor release. The addressable slot is the
|
|
1205
|
-
// caller's opaque installation label when given (connect), else the release
|
|
1206
|
-
// itself — the identity/release split (PHNX-3940). Everything on disk (dir,
|
|
1207
|
-
// alias, record, tracker) keys on `label`; only the npm spec uses `release`.
|
|
1208
1049
|
const releaseVersion = version;
|
|
1209
1050
|
const label = opts?.installationLabel ?? releaseVersion;
|
|
1210
1051
|
ensureAgentsDir();
|
|
1211
1052
|
const versionDir = getVersionDir(agent, label);
|
|
1212
1053
|
return withFileLockAsync(installationLockTarget(agent, label), async () => {
|
|
1213
|
-
// Installs and repairs mutate the same executable as updates. Hold the same
|
|
1214
|
-
// lock before touching artifacts, even before the first record exists.
|
|
1215
1054
|
if (await isInstallationLikelyActive({ agent, label })) {
|
|
1216
1055
|
return { success: false, installedVersion: label, error: `${agent} account home ${label} is in use. Retry after its sessions finish.` };
|
|
1217
1056
|
}
|
|
1218
|
-
// A `clean` (repair) reinstall wipes a possibly partially-extracted
|
|
1219
|
-
// node_modules first. npm treats a present-but-gutted platform package (its
|
|
1220
|
-
// package.json landed, its vendored native binary did not) as already
|
|
1221
|
-
// installed and would skip re-fetching it — so without this the corrupt
|
|
1222
|
-
// vendor/ survives the reinstall and the ENOENT persists. home/ is preserved.
|
|
1223
1057
|
if (opts?.clean && fs.existsSync(versionDir)) {
|
|
1224
1058
|
removeInstallArtifacts(versionDir);
|
|
1225
1059
|
}
|
|
1226
|
-
// Create version directory and isolated home
|
|
1227
1060
|
fs.mkdirSync(versionDir, { recursive: true });
|
|
1228
1061
|
fs.mkdirSync(path.join(versionDir, 'home'), { recursive: true });
|
|
1229
|
-
// Initialize package.json (only for real npm agents)
|
|
1230
1062
|
const packageJson = {
|
|
1231
1063
|
name: `agents-${agent}-${version}`,
|
|
1232
1064
|
version: '1.0.0',
|
|
1233
1065
|
private: true,
|
|
1234
1066
|
};
|
|
1235
1067
|
fs.writeFileSync(path.join(versionDir, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
1236
|
-
// Install the package. `version` is always concrete here (`latest`/`oldest`
|
|
1237
|
-
// were resolved above), so the spec is always pinned. The `@` prefix is
|
|
1238
|
-
// load-bearing: it ensures `version` (which VERSION_RE permits to start with
|
|
1239
|
-
// `-`) is never passed as a standalone npm CLI flag.
|
|
1240
1068
|
const packageSpec = `${agentConfig.npmPackage}@${version}`;
|
|
1241
|
-
// Set once the install has passed its integrity gate; read after the try so
|
|
1242
|
-
// the success path's bookkeeping sits outside the catch's cleanup.
|
|
1243
1069
|
let healthyVersion;
|
|
1244
1070
|
try {
|
|
1245
|
-
// Check npm is available
|
|
1246
1071
|
const winShell = process.platform === 'win32';
|
|
1247
1072
|
try {
|
|
1248
1073
|
await execFileAsync('npm', ['--version'], { shell: winShell });
|
|
@@ -1256,64 +1081,28 @@ export async function installVersion(agent, version, onProgress, opts) {
|
|
|
1256
1081
|
}
|
|
1257
1082
|
onProgress?.(`Installing ${packageSpec}...`);
|
|
1258
1083
|
await execFileAsync('npm', ['install', packageSpec, '--ignore-scripts'], { cwd: versionDir, shell: winShell });
|
|
1259
|
-
// The release installed directly into its final labeled dir (`versionDir` is
|
|
1260
|
-
// keyed on `label`) — no post-install rename, no shared `latest/` dir for a
|
|
1261
|
-
// concurrent process to move out from under us. The addressable slot is the
|
|
1262
|
-
// label; `releaseVersion` is what npm actually staged.
|
|
1263
1084
|
const installedVersion = label;
|
|
1264
|
-
// Create versioned alias (e.g., claude@2.0.65, or claude@ins_… for connect)
|
|
1265
1085
|
createVersionedAlias(agent, installedVersion);
|
|
1266
|
-
// Claude reads its global config from CLAUDE_CONFIG_DIR/.claude.json —
|
|
1267
|
-
// i.e. inside the per-version .claude dir — while the rest of agents-cli
|
|
1268
|
-
// manages the home-level file. Symlink INSIDE to OUTSIDE so Claude and
|
|
1269
|
-
// agents-cli see the same content.
|
|
1270
1086
|
if (agent === 'claude') {
|
|
1271
1087
|
try {
|
|
1272
1088
|
ensureClaudeInsideSymlink(installedVersion);
|
|
1273
1089
|
}
|
|
1274
1090
|
catch {
|
|
1275
|
-
/* non-fatal; the install itself succeeded */
|
|
1276
1091
|
}
|
|
1277
1092
|
}
|
|
1278
|
-
// The `npm install` above ran with `--ignore-scripts` — the right posture for
|
|
1279
|
-
// the dependency TREE (never run arbitrary transitive postinstalls), but it
|
|
1280
|
-
// also skips the agent package's OWN postinstall, which for some agents is a
|
|
1281
|
-
// required install step. @anthropic-ai/claude-code ships a ~500-byte stub at
|
|
1282
|
-
// `bin/claude.exe` plus per-arch native binaries as optional deps; its
|
|
1283
|
-
// `postinstall` (`node install.cjs`) is what copies the correct native binary
|
|
1284
|
-
// over the stub. Skip it and every launch dies with "native binary not
|
|
1285
|
-
// installed". So run the first-party package's declared postinstall here —
|
|
1286
|
-
// scoped to that one package, never `prepare` (claude-code's `prepare` is an
|
|
1287
|
-
// unconditional `exit 1` publish guard). Same precedent as the keychain-helper
|
|
1288
|
-
// postinstall re-run after a `--ignore-scripts` upgrade (see index.ts).
|
|
1289
|
-
// Best-effort: the integrity gate below is the real backstop — a still-broken
|
|
1290
|
-
// binary (postinstall failed, or a platform with no published native dep)
|
|
1291
|
-
// fails there with the correct message rather than throwing here.
|
|
1292
1093
|
if (agentConfig.npmPackage) {
|
|
1293
|
-
// The install landed in `versionDir` (the labeled dir) with no rename to
|
|
1294
|
-
// chase, so the package root is exactly there.
|
|
1295
1094
|
const pkgRoot = path.join(versionDir, 'node_modules', agentConfig.npmPackage);
|
|
1296
1095
|
try {
|
|
1297
1096
|
const pkg = JSON.parse(fs.readFileSync(path.join(pkgRoot, 'package.json'), 'utf-8'));
|
|
1298
1097
|
const postinstall = pkg?.scripts?.postinstall;
|
|
1299
1098
|
if (typeof postinstall === 'string' && postinstall.trim()) {
|
|
1300
1099
|
onProgress?.(`Running ${agentConfig.name} postinstall...`);
|
|
1301
|
-
// The declared postinstall is a shell command string (e.g. `node
|
|
1302
|
-
// install.cjs`), so it must run through a shell on ALL platforms —
|
|
1303
|
-
// shell:true, empty args. cwd is the package root; install.cjs anchors
|
|
1304
|
-
// its paths to __dirname, so that is correct and sufficient.
|
|
1305
1100
|
await execFileAsync(postinstall, [], { cwd: pkgRoot, shell: true });
|
|
1306
1101
|
}
|
|
1307
1102
|
}
|
|
1308
1103
|
catch {
|
|
1309
|
-
/* non-fatal; the integrity gate below catches a still-broken binary */
|
|
1310
1104
|
}
|
|
1311
1105
|
}
|
|
1312
|
-
// Integrity gate: confirm the install actually launches, not just that the
|
|
1313
|
-
// JS wrapper landed. A gutted install (wrapper present, native platform
|
|
1314
|
-
// binary missing) otherwise gets silently pinned as the default and crashes
|
|
1315
|
-
// with ENOENT on run. Fail loudly here so `agents add` never records a
|
|
1316
|
-
// broken version as healthy — the caller then won't set it as default.
|
|
1317
1106
|
const health = await verifyInstalledBinaryLaunches(agent, installedVersion);
|
|
1318
1107
|
if (!health.ok) {
|
|
1319
1108
|
if (fs.existsSync(versionDir))
|
|
@@ -1327,24 +1116,15 @@ export async function installVersion(agent, version, onProgress, opts) {
|
|
|
1327
1116
|
+ `The install is incomplete — the platform binary is missing. Re-run: agents add ${agent}@${installedVersion}`,
|
|
1328
1117
|
};
|
|
1329
1118
|
}
|
|
1330
|
-
// The install is healthy from here. Identity is frozen AFTER the try (see
|
|
1331
|
-
// below) so a bookkeeping write failure cannot fall into the catch and wipe
|
|
1332
|
-
// a working install.
|
|
1333
1119
|
healthyVersion = installedVersion;
|
|
1334
1120
|
}
|
|
1335
1121
|
catch (err) {
|
|
1336
|
-
// Clean up on failure — preserve `home/` in case a prior install left
|
|
1337
|
-
// conversation history behind that we must not wipe on a failed reinstall.
|
|
1338
1122
|
if (fs.existsSync(versionDir)) {
|
|
1339
1123
|
removeInstallArtifacts(versionDir);
|
|
1340
1124
|
}
|
|
1341
1125
|
emit('version.install', { agent, version, error: err.message });
|
|
1342
1126
|
return { success: false, installedVersion: version, error: err.message };
|
|
1343
1127
|
}
|
|
1344
|
-
// Freeze this installation's identity (see the installScript branch above).
|
|
1345
|
-
// The label is the frozen identity; the release it carries is recorded
|
|
1346
|
-
// separately so a connect home under an opaque label records the real vendor
|
|
1347
|
-
// release it installed rather than the label string.
|
|
1348
1128
|
createInstallation(agent, healthyVersion, releaseVersion, initialUpdatePolicy);
|
|
1349
1129
|
const trackerInstall = await installSessionTrackerHook(agent, healthyVersion);
|
|
1350
1130
|
if (!trackerInstall.installed && trackerInstall.error) {
|
|
@@ -1354,23 +1134,7 @@ export async function installVersion(agent, version, onProgress, opts) {
|
|
|
1354
1134
|
return { success: true, installedVersion: healthyVersion };
|
|
1355
1135
|
}, { ...INSTALLATION_LOCK_OPTIONS, realpath: false });
|
|
1356
1136
|
}
|
|
1357
|
-
// Version-dir entries that are STATE, not install output, and so must survive a
|
|
1358
|
-
// clean reinstall: `home/`, the `.isolated` marker that is the single source
|
|
1359
|
-
// of truth for "this copy is walled off", and `installation.json`, which carries
|
|
1360
|
-
// this installation's frozen identity. Losing the marker would silently demote
|
|
1361
|
-
// an isolated copy to a normal one on its first repair — after which shim
|
|
1362
|
-
// self-heal would hand it a bare `<agent>` shim and a PATH entry. Losing the
|
|
1363
|
-
// installation record would mint a NEW id for the same install on its first
|
|
1364
|
-
// repair, discarding its release history.
|
|
1365
1137
|
const PRESERVED_ON_CLEAN_REINSTALL = new Set(['home', '.isolated', '.launch-leases', INSTALLATION_RECORD_FILE, `${INSTALLATION_RECORD_FILE}.lock`]);
|
|
1366
|
-
/**
|
|
1367
|
-
* Remove install artifacts from a version directory, preserving `home/` which
|
|
1368
|
-
* contains the user's conversation history, sessions, history.jsonl, tasks,
|
|
1369
|
-
* todos, file-history, etc. (and the `.isolated` marker — see
|
|
1370
|
-
* PRESERVED_ON_CLEAN_REINSTALL). Used by the install pipeline (NOT by
|
|
1371
|
-
* removeVersion) to clean up staging artifacts when a fresh install collides
|
|
1372
|
-
* with an existing dir. removeVersion uses soft-delete instead.
|
|
1373
|
-
*/
|
|
1374
1138
|
function removeInstallArtifacts(versionDir) {
|
|
1375
1139
|
for (const entry of fs.readdirSync(versionDir)) {
|
|
1376
1140
|
if (PRESERVED_ON_CLEAN_REINSTALL.has(entry) || entry.startsWith('.rollback-'))
|
|
@@ -1378,39 +1142,7 @@ function removeInstallArtifacts(versionDir) {
|
|
|
1378
1142
|
fs.rmSync(path.join(versionDir, entry), { recursive: true, force: true });
|
|
1379
1143
|
}
|
|
1380
1144
|
}
|
|
1381
|
-
/**
|
|
1382
|
-
* Fold a stale literal `latest` version dir into the real resolved version.
|
|
1383
|
-
*
|
|
1384
|
-
* Script-installed agents (droid, grok) have no npm package to read a version
|
|
1385
|
-
* from, so the installer resolves the version by probing `<cli> --version`
|
|
1386
|
-
* after the install script runs. When that probe failed (3s timeout, or the
|
|
1387
|
-
* freshly-dropped binary not yet resolvable on PATH) the installer fell back to
|
|
1388
|
-
* the literal string `latest`, creating a `versions/<agent>/latest/` dir. A
|
|
1389
|
-
* later install where the probe succeeded then created a SECOND dir at the real
|
|
1390
|
-
* semver, orphaning `latest` — and because these agents' getBinaryPath points
|
|
1391
|
-
* at a single global binary regardless of version dir, `latest` keeps showing
|
|
1392
|
-
* up in `agents view` next to the real version forever.
|
|
1393
|
-
*
|
|
1394
|
-
* Call this once the install path has resolved a real version: if a stale
|
|
1395
|
-
* `latest` dir exists, rename it onto the real version (preserving `home/`), or
|
|
1396
|
-
* if the real dir already exists, soft-delete the `latest` dir to trash. No-op
|
|
1397
|
-
* when nothing was resolved or no stale dir is present, so it is safe to call
|
|
1398
|
-
* on every script-based install. Returns the action taken (for tests/logging).
|
|
1399
|
-
*/
|
|
1400
|
-
/**
|
|
1401
|
-
* Proactively fold a stale `latest` version-home into its concrete version,
|
|
1402
|
-
* WITHOUT needing a fresh install (RUSH-1320). `reconcileStaleLatestDir` only
|
|
1403
|
-
* fires at install time, so a `latest` dir left by an old probe-failed install
|
|
1404
|
-
* lingers in `agents view` indefinitely. This resolves the live CLI version and
|
|
1405
|
-
* reconciles — cheap no-op when there's no `latest` dir (the common case, so
|
|
1406
|
-
* `agents view` pays a `--version` shell-out only the once, until it's folded).
|
|
1407
|
-
* Skipped when the active config symlink still points at `latest`, since
|
|
1408
|
-
* renaming that dir would dangle the live symlink.
|
|
1409
|
-
*/
|
|
1410
1145
|
export async function reconcileStaleLatestForAgent(agent) {
|
|
1411
|
-
// Global-binary agents (droid) can accumulate MANY stale semver dirs — not
|
|
1412
|
-
// just a literal `latest` — because every `agents add` after an in-place
|
|
1413
|
-
// self-update creates a fresh dir for the same one binary. Fold them all.
|
|
1414
1146
|
if (isGlobalBinaryAgent(agent)) {
|
|
1415
1147
|
await reconcileGlobalBinaryVersions(agent);
|
|
1416
1148
|
return;
|
|
@@ -1424,32 +1156,13 @@ export async function reconcileStaleLatestForAgent(agent) {
|
|
|
1424
1156
|
await reconcileStaleLatestDir(agent, concrete);
|
|
1425
1157
|
}
|
|
1426
1158
|
}
|
|
1427
|
-
/**
|
|
1428
|
-
* Fold every stale version-dir of a global-binary agent (droid) into the single
|
|
1429
|
-
* canonical survivor. All its dirs point at ONE binary, so the extras — left by
|
|
1430
|
-
* successive `agents add` + in-place self-updates, and by probe-failed installs
|
|
1431
|
-
* that created a literal `latest` dir — are phantom labels. Soft-delete each
|
|
1432
|
-
* non-survivor dir (its `home/` stays recoverable via `agents restore`) so disk
|
|
1433
|
-
* converges to a single install matching what `agents view` shows.
|
|
1434
|
-
*
|
|
1435
|
-
* Survivor selection matches listInstalledVersions' canonical choice
|
|
1436
|
-
* (config-symlink target → global default → live version → newest). The survivor
|
|
1437
|
-
* is NOT renamed: droid's ~/.factory symlink points inside its home, and the
|
|
1438
|
-
* live version label is surfaced by the view renderer via getLiveVersion.
|
|
1439
|
-
*/
|
|
1440
1159
|
async function reconcileGlobalBinaryVersions(agent) {
|
|
1441
|
-
// Step 1 — preserve the original literal-`latest` reconcile: a probe-failed
|
|
1442
|
-
// install leaves a `versions/<agent>/latest/` dir; fold it onto the concrete
|
|
1443
|
-
// live version (rename if that dir is absent, else trash). Skipped while the
|
|
1444
|
-
// config symlink still points at `latest` (renaming would dangle it).
|
|
1445
1160
|
if (fs.existsSync(getVersionDir(agent, 'latest')) && getConfigSymlinkVersion(agent) !== 'latest') {
|
|
1446
1161
|
const concrete = await getCliVersionFromPath(agent);
|
|
1447
1162
|
if (concrete && concrete !== 'latest') {
|
|
1448
1163
|
await reconcileStaleLatestDir(agent, concrete);
|
|
1449
1164
|
}
|
|
1450
1165
|
}
|
|
1451
|
-
// Step 2 — collapse any remaining phantom SEMVER dirs (successive `agents add`
|
|
1452
|
-
// after in-place self-updates) into a single survivor.
|
|
1453
1166
|
const agentVersionsDir = path.join(getVersionsDir(), agent);
|
|
1454
1167
|
let entries;
|
|
1455
1168
|
try {
|
|
@@ -1461,8 +1174,6 @@ async function reconcileGlobalBinaryVersions(agent) {
|
|
|
1461
1174
|
const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name).sort(compareVersions);
|
|
1462
1175
|
if (dirs.length <= 1)
|
|
1463
1176
|
return;
|
|
1464
|
-
// Warm the live-version cache so the survivor pick (and later view labels) can
|
|
1465
|
-
// prefer the version the binary actually reports.
|
|
1466
1177
|
await getLiveVersion(agent);
|
|
1467
1178
|
const survivor = pickCanonicalGlobalBinaryVersion(agent, dirs);
|
|
1468
1179
|
const symlinkVersion = getConfigSymlinkVersion(agent);
|
|
@@ -1470,9 +1181,6 @@ async function reconcileGlobalBinaryVersions(agent) {
|
|
|
1470
1181
|
for (const version of dirs) {
|
|
1471
1182
|
if (version === survivor)
|
|
1472
1183
|
continue;
|
|
1473
|
-
// Never trash the dir the live config symlink points at — that would dangle
|
|
1474
|
-
// the symlink. pickCanonical already prefers it as survivor; this guards the
|
|
1475
|
-
// rare mismatch.
|
|
1476
1184
|
if (version === symlinkVersion)
|
|
1477
1185
|
continue;
|
|
1478
1186
|
const staleDir = getVersionDir(agent, version);
|
|
@@ -1485,10 +1193,6 @@ async function reconcileGlobalBinaryVersions(agent) {
|
|
|
1485
1193
|
}
|
|
1486
1194
|
if (foldedAny) {
|
|
1487
1195
|
invalidateInstalledVersionsCache(agent);
|
|
1488
|
-
// Keep the recorded default pointing at a dir that still exists on disk —
|
|
1489
|
-
// but never promote an isolated copy into the default slot (same rule as the
|
|
1490
|
-
// post-removal promotion filter and `agents use`). Leaving it unset is right:
|
|
1491
|
-
// an isolated-only agent has no default by design.
|
|
1492
1196
|
const def = getGlobalDefault(agent);
|
|
1493
1197
|
if ((!def || !fs.existsSync(getVersionDir(agent, def))) && !isVersionIsolated(agent, survivor)) {
|
|
1494
1198
|
setGlobalDefault(agent, survivor);
|
|
@@ -1507,13 +1211,6 @@ export async function reconcileStaleLatestDir(agent, installedVersion) {
|
|
|
1507
1211
|
fs.renameSync(staleLatestDir, realVersionDir);
|
|
1508
1212
|
return 'renamed';
|
|
1509
1213
|
}
|
|
1510
|
-
// Both dirs exist. Stripping install artifacts would not hide `latest` for
|
|
1511
|
-
// global-binary agents (getBinaryPath ignores dir contents), so the whole
|
|
1512
|
-
// dir must go. Soft-delete to trash so any `home/` data stays recoverable
|
|
1513
|
-
// via `agents restore <agent>@latest`, then rewrite session file paths to
|
|
1514
|
-
// point at the trashed location so history stays readable. The session-db
|
|
1515
|
-
// module is imported lazily — it carries a top-level await that the CJS test
|
|
1516
|
-
// harness can't statically transform, so it must stay out of the eager graph.
|
|
1517
1214
|
const trashPath = softDeleteVersionDir(agent, 'latest');
|
|
1518
1215
|
if (trashPath) {
|
|
1519
1216
|
const { updateSessionFilePaths } = await import('../session/db.js');
|
|
@@ -1521,18 +1218,6 @@ export async function reconcileStaleLatestDir(agent, installedVersion) {
|
|
|
1521
1218
|
}
|
|
1522
1219
|
return 'trashed';
|
|
1523
1220
|
}
|
|
1524
|
-
/**
|
|
1525
|
-
* Soft-delete a version directory by moving it to ~/.agents/.system/trash/versions/.
|
|
1526
|
-
* Returns the trash path on success or null on failure / no source.
|
|
1527
|
-
*
|
|
1528
|
-
* Trash layout: ~/.agents/.system/trash/versions/<agent>/<version>/<timestamp>/
|
|
1529
|
-
* The timestamp suffix lets a user soft-delete the same version twice (after
|
|
1530
|
-
* re-install) without collision and gives a chronological audit trail.
|
|
1531
|
-
*
|
|
1532
|
-
* The whole versionDir moves — including `home/` (transcripts, sessions). The
|
|
1533
|
-
* user can recover everything via `agents restore <agent>@<version>`.
|
|
1534
|
-
* Nothing is ever hard-deleted.
|
|
1535
|
-
*/
|
|
1536
1221
|
export function softDeleteVersionDir(agent, version) {
|
|
1537
1222
|
const versionDir = getVersionDir(agent, version);
|
|
1538
1223
|
if (!fs.existsSync(versionDir))
|
|
@@ -1547,8 +1232,6 @@ export function softDeleteVersionDir(agent, version) {
|
|
|
1547
1232
|
fs.renameSync(versionDir, trashDest);
|
|
1548
1233
|
}
|
|
1549
1234
|
catch (renameErr) {
|
|
1550
|
-
// On Windows, rename fails with EPERM/EACCES when any file in the tree
|
|
1551
|
-
// is locked by a running process. Fall back to recursive copy + delete.
|
|
1552
1235
|
if (renameErr.code !== 'EPERM' && renameErr.code !== 'EACCES')
|
|
1553
1236
|
throw renameErr;
|
|
1554
1237
|
fs.cpSync(versionDir, trashDest, { recursive: true });
|
|
@@ -1560,13 +1243,6 @@ export function softDeleteVersionDir(agent, version) {
|
|
|
1560
1243
|
return null;
|
|
1561
1244
|
}
|
|
1562
1245
|
}
|
|
1563
|
-
/**
|
|
1564
|
-
* Remove a specific version of an agent.
|
|
1565
|
-
*
|
|
1566
|
-
* Soft-delete only: moves the entire version directory (including `home/`)
|
|
1567
|
-
* to ~/.agents/.system/trash/versions/. Recoverable via `agents restore`.
|
|
1568
|
-
* Nothing is hard-deleted.
|
|
1569
|
-
*/
|
|
1570
1246
|
export function removeVersion(agent, version) {
|
|
1571
1247
|
const versionDir = getVersionDir(agent, version);
|
|
1572
1248
|
if (!fs.existsSync(versionDir)) {
|
|
@@ -1576,19 +1252,9 @@ export function removeVersion(agent, version) {
|
|
|
1576
1252
|
if (!trashPath) {
|
|
1577
1253
|
return false;
|
|
1578
1254
|
}
|
|
1579
|
-
// Remove versioned alias (e.g., claude@2.0.65)
|
|
1580
1255
|
removeVersionedAlias(agent, version);
|
|
1581
|
-
// If the removed version was the global default, keep launchers working:
|
|
1582
|
-
// reassign the default to the newest remaining version, or clear it outright
|
|
1583
|
-
// only when nothing is left. Leaving a dangling default pointer here is what
|
|
1584
|
-
// broke every launcher after removing the pinned default.
|
|
1585
1256
|
if (getGlobalDefault(agent) === version) {
|
|
1586
1257
|
const remaining = listInstalledVersions(agent);
|
|
1587
|
-
// Never auto-promote an isolated install to the global default: it was
|
|
1588
|
-
// installed to stay separate from the user's setup, and promoting it would
|
|
1589
|
-
// silently make `<agent>` resolve to it (and let a later `use` adopt its
|
|
1590
|
-
// home into `~/.<agent>`). Prefer the newest NON-isolated survivor; if every
|
|
1591
|
-
// survivor is isolated, clear the default rather than adopt one.
|
|
1592
1258
|
const promotable = remaining.filter((v) => !isVersionIsolated(agent, v));
|
|
1593
1259
|
if (promotable.length > 0) {
|
|
1594
1260
|
const newestRemaining = promotable[promotable.length - 1];
|
|
@@ -1600,14 +1266,10 @@ export function removeVersion(agent, version) {
|
|
|
1600
1266
|
console.log(chalk.yellow(`Removed the last non-isolated ${agent} version and cleared its default. Reinstall with: agents add ${agent}, then set one with: agents use ${agent}@<version>`));
|
|
1601
1267
|
}
|
|
1602
1268
|
}
|
|
1603
|
-
// Same for the isolated pointer: a removed version must not stay the answer to a
|
|
1604
|
-
// bare `agents run <agent>`. Prefer the newest remaining isolated copy so removing
|
|
1605
|
-
// one of several does not silently drop the user back to their PATH binary.
|
|
1606
1269
|
if (getIsolatedDefault(agent) === version) {
|
|
1607
1270
|
const survivors = listInstalledVersions(agent).filter((v) => isVersionIsolated(agent, v));
|
|
1608
1271
|
setIsolatedDefault(agent, survivors.length > 0 ? survivors[survivors.length - 1] : undefined);
|
|
1609
1272
|
}
|
|
1610
|
-
// Clean up dangling config symlink if it pointed to the removed version
|
|
1611
1273
|
const symlinkVersion = getConfigSymlinkVersion(agent);
|
|
1612
1274
|
if (symlinkVersion === version) {
|
|
1613
1275
|
const configPath = path.join(getHomeDir(), agentConfigDirName(agent));
|
|
@@ -1615,14 +1277,8 @@ export function removeVersion(agent, version) {
|
|
|
1615
1277
|
fs.unlinkSync(configPath);
|
|
1616
1278
|
}
|
|
1617
1279
|
catch {
|
|
1618
|
-
// Ignore if already gone
|
|
1619
1280
|
}
|
|
1620
1281
|
}
|
|
1621
|
-
// Clear dead per-version hook entries the removed version left behind in the
|
|
1622
|
-
// remaining versions' settings. Their command paths point under the now-gone
|
|
1623
|
-
// version home, so they error on every tool call until the next sync. Scoped
|
|
1624
|
-
// to the Claude-family settings.json format (claude + droid) — the surface
|
|
1625
|
-
// where per-version guard hooks accumulate; other agents self-heal on sync.
|
|
1626
1282
|
if (agent === 'claude' || agent === 'droid') {
|
|
1627
1283
|
const configDir = agentConfigDirName(agent);
|
|
1628
1284
|
for (const remaining of listInstalledVersions(agent)) {
|
|
@@ -1630,11 +1286,6 @@ export function removeVersion(agent, version) {
|
|
|
1630
1286
|
pruneVersionHomeHookEntriesFromSettings(settingsPath, agent, version);
|
|
1631
1287
|
}
|
|
1632
1288
|
}
|
|
1633
|
-
// The global hook shims embed one SOURCE path. When it pointed into this
|
|
1634
|
-
// version home every shimmed guard would exit 127 (allow) until a self-heal
|
|
1635
|
-
// pass ran, and that pass needs a live daemon. Re-point them now. Best
|
|
1636
|
-
// effort: the removal itself already succeeded, and a repair failure on an
|
|
1637
|
-
// unrelated harness's shim must not abort a bulk removal.
|
|
1638
1289
|
try {
|
|
1639
1290
|
repairManagedHookRuntimeArtifacts();
|
|
1640
1291
|
}
|
|
@@ -1644,10 +1295,6 @@ export function removeVersion(agent, version) {
|
|
|
1644
1295
|
emit('version.remove', { agent, version });
|
|
1645
1296
|
return true;
|
|
1646
1297
|
}
|
|
1647
|
-
/**
|
|
1648
|
-
* Print the standard footer after one or more versions were soft-deleted to
|
|
1649
|
-
* trash. Reminds the user that sessions stay readable and how to restore.
|
|
1650
|
-
*/
|
|
1651
1298
|
export function printTrashFooter(moved) {
|
|
1652
1299
|
if (moved.length === 0)
|
|
1653
1300
|
return;
|
|
@@ -1661,11 +1308,6 @@ export function printTrashFooter(moved) {
|
|
|
1661
1308
|
console.log(chalk.gray('Restore with: agents restore <agent>@<version> (run `agents trash list` to see)'));
|
|
1662
1309
|
}
|
|
1663
1310
|
}
|
|
1664
|
-
/**
|
|
1665
|
-
* Remove all versions of an agent. Preserves each version's `home/` directory
|
|
1666
|
-
* so conversation history is never deleted; the per-version folders (now
|
|
1667
|
-
* containing only `home/`) remain under the agent dir.
|
|
1668
|
-
*/
|
|
1669
1311
|
export function removeAllVersions(agent) {
|
|
1670
1312
|
const versions = listInstalledVersions(agent);
|
|
1671
1313
|
let removed = 0;
|
|
@@ -1676,28 +1318,6 @@ export function removeAllVersions(agent) {
|
|
|
1676
1318
|
}
|
|
1677
1319
|
return removed;
|
|
1678
1320
|
}
|
|
1679
|
-
/**
|
|
1680
|
-
* Repoint an agent's version pointers — the global/isolated default and the
|
|
1681
|
-
* `~/.<agent>` config symlink — off any version that is no longer installed, so
|
|
1682
|
-
* neither `agents sync`/`agents run` resolution nor the conventional-path home
|
|
1683
|
-
* can land on a dead version (RUSH-2471).
|
|
1684
|
-
*
|
|
1685
|
-
* How a pointer goes dangling: {@link removeVersion} reassigns the defaults and
|
|
1686
|
-
* clears the config symlink only when IT removes the pointed-at version. A
|
|
1687
|
-
* version-home whose launch binary disappears by any other route — grok
|
|
1688
|
-
* self-updated its per-version binary out from under the old dir, a manual
|
|
1689
|
-
* delete, a half-finished install that seeded the home but never landed the
|
|
1690
|
-
* binary — leaves the default and/or the symlink pointing at something
|
|
1691
|
-
* {@link isVersionInstalled} reports as gone.
|
|
1692
|
-
*
|
|
1693
|
-
* Called from the sync resolve path so the invariant self-heals. Mirrors
|
|
1694
|
-
* {@link removeVersion}'s reassignment: the global default prefers the newest
|
|
1695
|
-
* NON-isolated survivor else clears; the isolated default prefers the newest
|
|
1696
|
-
* remaining isolated copy else clears. The symlink is repointed at the now-healed
|
|
1697
|
-
* resolved default, else the newest installed non-isolated version. A symlink
|
|
1698
|
-
* already on an installed version, a real (non-symlink) config dir, and an
|
|
1699
|
-
* isolated-only agent are left untouched.
|
|
1700
|
-
*/
|
|
1701
1321
|
export async function healDanglingVersionPointers(agent, cwd) {
|
|
1702
1322
|
const healed = {};
|
|
1703
1323
|
const installed = listInstalledVersions(agent);
|
|
@@ -1731,7 +1351,6 @@ export async function healDanglingVersionPointers(agent, cwd) {
|
|
|
1731
1351
|
}
|
|
1732
1352
|
return healed;
|
|
1733
1353
|
}
|
|
1734
|
-
/** Normalize a user-supplied `@version` token. `default`/`pinned`/`any` → undefined; `latest`/`oldest` → extreme installed version; concrete versions must be installed. */
|
|
1735
1354
|
export function resolveVersionAlias(agent, raw) {
|
|
1736
1355
|
if (!raw || raw === 'default' || raw === 'pinned' || raw === 'any')
|
|
1737
1356
|
return undefined;
|
|
@@ -1755,12 +1374,6 @@ export function resolveVersionAlias(agent, raw) {
|
|
|
1755
1374
|
}
|
|
1756
1375
|
return raw;
|
|
1757
1376
|
}
|
|
1758
|
-
/**
|
|
1759
|
-
* Loose variant of resolveVersionAlias for record-filter contexts (sessions,
|
|
1760
|
-
* team history). Same `default`/`pinned`/`latest`/`oldest` semantics, but explicit
|
|
1761
|
-
* versions pass through unchanged so historical records of uninstalled versions
|
|
1762
|
-
* remain queryable.
|
|
1763
|
-
*/
|
|
1764
1377
|
export function resolveVersionAliasLoose(agent, raw) {
|
|
1765
1378
|
if (!raw || raw === 'default' || raw === 'pinned' || raw === 'any')
|
|
1766
1379
|
return undefined;
|
|
@@ -1772,12 +1385,7 @@ export function resolveVersionAliasLoose(agent, raw) {
|
|
|
1772
1385
|
}
|
|
1773
1386
|
return raw;
|
|
1774
1387
|
}
|
|
1775
|
-
// compareVersions is defined in ./agent-spec/primitives.ts and re-exported here
|
|
1776
|
-
// so existing `import { compareVersions } from './versions.js'` sites keep working.
|
|
1777
1388
|
export { compareVersions };
|
|
1778
|
-
/**
|
|
1779
|
-
* Get actual version from an installed 'latest' directory.
|
|
1780
|
-
*/
|
|
1781
1389
|
export async function getInstalledVersion(agent, version) {
|
|
1782
1390
|
const binaryPath = getBinaryPath(agent, version);
|
|
1783
1391
|
if (!fs.existsSync(binaryPath)) {
|
|
@@ -1792,52 +1400,9 @@ export async function getInstalledVersion(agent, version) {
|
|
|
1792
1400
|
return version;
|
|
1793
1401
|
}
|
|
1794
1402
|
}
|
|
1795
|
-
/**
|
|
1796
|
-
* True when a probe's combined output/error looks like the runnable binary (or a
|
|
1797
|
-
* native sub-binary it execs) is MISSING — the "gutted install" signature. This
|
|
1798
|
-
* is the exact class of failure behind the ENOENT crash: an npm package whose JS
|
|
1799
|
-
* wrapper landed at node_modules/.bin/<cli> while its native platform binary
|
|
1800
|
-
* (shipped via an optional per-arch dependency, e.g. @openai/codex-<platform>)
|
|
1801
|
-
* did not — so the wrapper spawns and immediately dies with `spawn … ENOENT`.
|
|
1802
|
-
*
|
|
1803
|
-
* Deliberately narrow: only the missing-file signature counts. An agent that
|
|
1804
|
-
* merely dislikes `--version` (nonzero exit, ordinary error text) or ignores it
|
|
1805
|
-
* (times out) must NOT match, so a healthy install is never falsely condemned.
|
|
1806
|
-
*
|
|
1807
|
-
* The trailing phrases catch a gutted install that reports its own breakage
|
|
1808
|
-
* *politely* rather than with a raw ENOENT: @anthropic-ai/claude-code's stub
|
|
1809
|
-
* (run when its postinstall never copied the native binary in) prints "native
|
|
1810
|
-
* binary not installed / postinstall did not run / … optional dependency was not
|
|
1811
|
-
* downloaded" and exits nonzero — which the generic patterns above miss. Anchored
|
|
1812
|
-
* tightly so a healthy `--version` can never emit them.
|
|
1813
|
-
*/
|
|
1814
1403
|
export function isMissingBinarySignature(output) {
|
|
1815
1404
|
return /\bENOENT\b|no such file|cannot find|command not found|is not recognized|native binary not installed|postinstall did not run|optional dependency was not downloaded/i.test(output);
|
|
1816
1405
|
}
|
|
1817
|
-
/**
|
|
1818
|
-
* Verify a freshly-installed agent can actually LAUNCH — not merely that its JS
|
|
1819
|
-
* wrapper exists. getBinaryPath()/isVersionInstalled() only check the wrapper, so
|
|
1820
|
-
* a gutted install (wrapper present, native binary missing) reads as healthy,
|
|
1821
|
-
* gets pinned as the default, and gets picked to run — then dies with ENOENT the
|
|
1822
|
-
* instant it spawns (which, wrapped in tmux, showed up as a silent `[detached]`).
|
|
1823
|
-
*
|
|
1824
|
-
* We probe `<binary> --version` under the version's isolated HOME so config
|
|
1825
|
-
* resolution matches a real launch. Because the ENOENT originates in the child
|
|
1826
|
-
* (the wrapper spawns fine, then fails to exec the absent native binary), we
|
|
1827
|
-
* inspect the child's OUTPUT, not just whether our spawn succeeded. Only the
|
|
1828
|
-
* missing-binary signature (see isMissingBinarySignature) fails the check; a
|
|
1829
|
-
* plain nonzero exit or a timeout is treated as healthy so we never false-fail.
|
|
1830
|
-
*/
|
|
1831
|
-
/**
|
|
1832
|
-
* Compose the spawn spec for a `<binary> --version` launch probe. On Windows the
|
|
1833
|
-
* `.cmd` wrapper runs through cmd.exe, so the path is fully quoted into ONE
|
|
1834
|
-
* command line and the args array is emptied (composeWin32CommandLine) — the
|
|
1835
|
-
* DEP0190-safe pattern the real launch uses. Critically this keeps a spaced
|
|
1836
|
-
* Windows profile path (`C:\Users\John Doe\…\claude.cmd`) intact; passing the raw
|
|
1837
|
-
* path to a shell would split it at the space and false-fail a HEALTHY install.
|
|
1838
|
-
* On POSIX no shell is involved and the binary is exec'd directly. Pure/exported
|
|
1839
|
-
* so the quoting is unit-testable without spawning.
|
|
1840
|
-
*/
|
|
1841
1406
|
export function probeSpawnSpec(binary, isWin) {
|
|
1842
1407
|
if (isWin)
|
|
1843
1408
|
return { command: composeWin32CommandLine(binary, ['--version']), args: [], shell: true };
|
|
@@ -1846,41 +1411,13 @@ export function probeSpawnSpec(binary, isWin) {
|
|
|
1846
1411
|
export async function verifyInstalledBinaryLaunches(agent, version) {
|
|
1847
1412
|
return verifyBinaryLaunches(getBinaryPath(agent, version), getVersionHomePath(agent, version));
|
|
1848
1413
|
}
|
|
1849
|
-
/**
|
|
1850
|
-
* The launch probe itself, addressed by PATH rather than by installed version.
|
|
1851
|
-
*
|
|
1852
|
-
* `verifyInstalledBinaryLaunches` is this function applied to a version dir that
|
|
1853
|
-
* is already live. `agents update` needs the identical check applied to a release
|
|
1854
|
-
* that is still STAGED — probing it before the swap is what makes the update
|
|
1855
|
-
* transactional, since a staged release that cannot launch is discarded instead
|
|
1856
|
-
* of replacing a working one. Both callers must agree byte-for-byte on what
|
|
1857
|
-
* "launches" means, hence one implementation.
|
|
1858
|
-
*
|
|
1859
|
-
* `posixBinary` is the extensionless launch target. The real launch target
|
|
1860
|
-
* differs by platform, so we probe whatever `agents run` actually execs: on
|
|
1861
|
-
* Windows that is the npm `.cmd` wrapper beside it (exec.ts uses
|
|
1862
|
-
* `absPath + '.cmd'`), which chains to the native `.exe`; a gutted install
|
|
1863
|
-
* (renamed/missing `.exe`) makes that wrapper emit "is not recognized" — the
|
|
1864
|
-
* exact win-mini failure a vendor auto-update leaves behind. Probing the
|
|
1865
|
-
* extensionless `.bin/<cli>` instead would ENOENT even on a HEALTHY Windows
|
|
1866
|
-
* install, so we DON'T. On POSIX the `.bin/<cli>` binary is the launch target
|
|
1867
|
-
* and is probed directly.
|
|
1868
|
-
*/
|
|
1869
1414
|
export async function verifyBinaryLaunches(posixBinary, home) {
|
|
1870
1415
|
const isWin = process.platform === 'win32';
|
|
1871
1416
|
const binary = isWin ? posixBinary + '.cmd' : posixBinary;
|
|
1872
1417
|
if (!fs.existsSync(binary)) {
|
|
1873
|
-
// Windows: a missing `.cmd` means a non-npm/global agent (droid.exe) we can't
|
|
1874
|
-
// safely probe — treat as healthy (isVersionInstalled validates presence).
|
|
1875
|
-
// POSIX: a missing launch binary is a genuine gutted install.
|
|
1876
1418
|
return isWin ? { ok: true } : { ok: false, detail: `binary not found at ${binary}` };
|
|
1877
1419
|
}
|
|
1878
1420
|
try {
|
|
1879
|
-
// On Windows the `.cmd` runs via cmd.exe (shell). Pass a single FULLY-QUOTED
|
|
1880
|
-
// command line + EMPTY args (composeWin32CommandLine) — the same DEP0190-safe
|
|
1881
|
-
// pattern the real launch uses (exec.ts) — so a space in the Windows profile
|
|
1882
|
-
// path (`C:\Users\John Doe\…`) can't split the path and false-fail a healthy
|
|
1883
|
-
// install into a destructive reinstall.
|
|
1884
1421
|
const spec = probeSpawnSpec(binary, isWin);
|
|
1885
1422
|
await execFileAsync(spec.command, spec.args, {
|
|
1886
1423
|
timeout: 15000,
|
|
@@ -1896,59 +1433,16 @@ export async function verifyBinaryLaunches(posixBinary, home) {
|
|
|
1896
1433
|
.split('\n').map((s) => s.trim()).filter(Boolean)[0];
|
|
1897
1434
|
return { ok: false, detail: detail || 'native binary missing (ENOENT)' };
|
|
1898
1435
|
}
|
|
1899
|
-
// Launched but exited nonzero without a missing-file signature, or timed out
|
|
1900
|
-
// waiting for input: the binary is present and runnable. Healthy.
|
|
1901
1436
|
return { ok: true };
|
|
1902
1437
|
}
|
|
1903
1438
|
}
|
|
1904
|
-
/**
|
|
1905
|
-
* Launch-path self-heal. Given the concrete version `agents run` is about to
|
|
1906
|
-
* spawn, make sure it will actually run — and if not, repair it instead of
|
|
1907
|
-
* letting the agent die with a raw `ENOENT` deep inside its own wrapper.
|
|
1908
|
-
*
|
|
1909
|
-
* Steps, cheapest first:
|
|
1910
|
-
* 1. Probe the version (verifyInstalledBinaryLaunches). Healthy → return it.
|
|
1911
|
-
* 2. Broken → **clean** reinstall in place (wipes the partial node_modules so
|
|
1912
|
-
* npm actually re-fetches the platform binary). Re-probe; good → return it.
|
|
1913
|
-
* 3. Still broken → fall back to another INSTALLED version that launches,
|
|
1914
|
-
* re-pinning it as the default so the shim path heals too. Return it.
|
|
1915
|
-
* 4. Nothing runnable installed → install `latest`, pin it, return it.
|
|
1916
|
-
* 5. Give up → return null (caller surfaces a clear error).
|
|
1917
|
-
*
|
|
1918
|
-
* Isolation boundary (both directions — steps 3/4 are the only mutating ones):
|
|
1919
|
-
* - An ISOLATED target gets step 2 and nothing else. Falling back would let
|
|
1920
|
-
* `agents run <agent>@<isolated>` silently repoint the user's NORMAL default,
|
|
1921
|
-
* and installing `latest` would materialize a version they never asked for.
|
|
1922
|
-
* A failed repair returns null so the caller says so plainly.
|
|
1923
|
-
* - An isolated version is never a fallback CANDIDATE either, whatever the
|
|
1924
|
-
* target is: promoting one to the global default is exactly what `agents use`
|
|
1925
|
-
* refuses and what removeVersion's promotion filter excludes, so it must not
|
|
1926
|
-
* happen here by the back door (the daemon's launch-health pass calls this
|
|
1927
|
-
* unattended every ~6h).
|
|
1928
|
-
*
|
|
1929
|
-
* Gated to npm-package agents: their native binary ships as an optional per-arch
|
|
1930
|
-
* dependency whose tarball can extract partially (interrupted/raced install) —
|
|
1931
|
-
* the exact failure this repairs. Agents with a global/native binary (grok,
|
|
1932
|
-
* droid) have no such tarball and are returned unchanged.
|
|
1933
|
-
*/
|
|
1934
1439
|
export async function ensureAgentRunnable(agent, version, log, opts) {
|
|
1935
|
-
// Whether this heal may REPOINT the global default (adopt another version, or
|
|
1936
|
-
// install `latest` and pin it). Interactive callers (`agents run`, `agents
|
|
1937
|
-
// add`) allow it. The daemon's unattended 6-hourly launch-health pass sets
|
|
1938
|
-
// this false: a background pass that silently switches the default installs a
|
|
1939
|
-
// fresh version home → a fresh, empty Claude credential scope (macOS keychain
|
|
1940
|
-
// keyed off CLAUDE_CONFIG_DIR; Linux per-version token file), i.e. an
|
|
1941
|
-
// "unprovoked logout" at a time uncorrelated with anything the user did. In
|
|
1942
|
-
// refuse-mode we still repair the CURRENT default in place (no scope change),
|
|
1943
|
-
// but never repoint — we return null so the caller can alert instead.
|
|
1944
1440
|
const allowDefaultSwitch = opts?.allowDefaultSwitch ?? true;
|
|
1945
1441
|
const cfg = AGENTS[agent];
|
|
1946
1442
|
if (!cfg?.npmPackage)
|
|
1947
1443
|
return version;
|
|
1948
1444
|
if ((await verifyInstalledBinaryLaunches(agent, version)).ok)
|
|
1949
1445
|
return version;
|
|
1950
|
-
// Read the marker BEFORE the repair: the reinstall rewrites the version dir,
|
|
1951
|
-
// so isolation must be decided from the pre-repair state, not re-read after.
|
|
1952
1446
|
const targetIsolated = isVersionIsolated(agent, version);
|
|
1953
1447
|
log?.(`${cfg.name}@${version} is broken (platform binary missing) — repairing…`);
|
|
1954
1448
|
const record = readInstallation(agent, version);
|
|
@@ -1957,23 +1451,14 @@ export async function ensureAgentRunnable(agent, version, log, opts) {
|
|
|
1957
1451
|
log?.(`repaired ${cfg.name}@${version}.`);
|
|
1958
1452
|
return version;
|
|
1959
1453
|
}
|
|
1960
|
-
// An isolated copy is walled off from the rest of the setup: repairing it in
|
|
1961
|
-
// place is the ONLY thing we may do. No fallback, no install, no default
|
|
1962
|
-
// switch — surface the failure and let the caller tell the user.
|
|
1963
1454
|
if (targetIsolated || (record && record.label !== record.releaseVersion)) {
|
|
1964
1455
|
log?.(`${cfg.name}@${version} is an isolated install and could not be repaired — leaving your default ${cfg.name} untouched.`);
|
|
1965
1456
|
return null;
|
|
1966
1457
|
}
|
|
1967
|
-
// In-place repair failed → normally adopt another installed version and repoint
|
|
1968
|
-
// the default. When default-switching is disallowed (unattended daemon pass),
|
|
1969
|
-
// refuse: repointing would swap the live credential scope out from under the
|
|
1970
|
-
// user with no signal. Surface it so the caller can notify.
|
|
1971
1458
|
if (!allowDefaultSwitch) {
|
|
1972
1459
|
log?.(`${cfg.name}@${version} won't launch and could not be repaired in place — NOT repointing your default ${cfg.name} unattended. Run \`agents use ${agent} <version>\` or \`agents add ${agent}@latest\` to choose one.`);
|
|
1973
1460
|
return null;
|
|
1974
1461
|
}
|
|
1975
|
-
// In-place repair failed → adopt another installed version that launches.
|
|
1976
|
-
// Isolated copies are excluded: they are deliberately not promotable.
|
|
1977
1462
|
const others = listInstalledVersions(agent)
|
|
1978
1463
|
.filter(v => v !== version && !isVersionIsolated(agent, v))
|
|
1979
1464
|
.sort(compareVersions)
|
|
@@ -1985,14 +1470,6 @@ export async function ensureAgentRunnable(agent, version, log, opts) {
|
|
|
1985
1470
|
return cand;
|
|
1986
1471
|
}
|
|
1987
1472
|
}
|
|
1988
|
-
// Nothing runnable installed → last resort: install latest and pin it.
|
|
1989
|
-
//
|
|
1990
|
-
// …unless `latest` is a version the user already holds as an ISOLATED copy. A
|
|
1991
|
-
// normal and an isolated install of the same version share one on-disk dir
|
|
1992
|
-
// (see the coexistence refusal in commands/versions.ts), so installing would
|
|
1993
|
-
// commandeer that copy and pinning it would hand an isolated install the
|
|
1994
|
-
// global default — the same breach the candidate filter above prevents.
|
|
1995
|
-
// Resolved BEFORE installing so the isolated copy is not even rebuilt.
|
|
1996
1473
|
const latestVersion = await getLatestNpmVersion(agent);
|
|
1997
1474
|
if (latestVersion && isVersionIsolated(agent, latestVersion)) {
|
|
1998
1475
|
log?.(`no runnable ${cfg.name} version installed — ${cfg.name}@${latestVersion} is the latest, but you hold it as an isolated copy, so it can't become your default.`);
|
|
@@ -2002,8 +1479,6 @@ export async function ensureAgentRunnable(agent, version, log, opts) {
|
|
|
2002
1479
|
log?.(`no runnable ${cfg.name} version installed — installing ${cfg.name}@latest…`);
|
|
2003
1480
|
const latest = await installVersion(agent, 'latest', undefined, { clean: true });
|
|
2004
1481
|
if (latest.success) {
|
|
2005
|
-
// Belt-and-braces: `latest` could have moved between the probe above and the
|
|
2006
|
-
// install. Never pin an isolated version, whatever the resolution said.
|
|
2007
1482
|
if (isVersionIsolated(agent, latest.installedVersion)) {
|
|
2008
1483
|
log?.(`${cfg.name}@${latest.installedVersion} is an isolated copy and can't be set as your default.`);
|
|
2009
1484
|
return null;
|
|
@@ -2014,20 +1489,6 @@ export async function ensureAgentRunnable(agent, version, log, opts) {
|
|
|
2014
1489
|
}
|
|
2015
1490
|
return null;
|
|
2016
1491
|
}
|
|
2017
|
-
/**
|
|
2018
|
-
* Proactive launch-health pass for the daemon. Probe the DEFAULT version of
|
|
2019
|
-
* every npm-package agent and repair any that won't launch (via
|
|
2020
|
-
* ensureAgentRunnable), so a gutted install is healed BEFORE the user's next
|
|
2021
|
-
* `agents run` hits a raw ENOENT — the run-time heal (ensureAgentRunnable) only
|
|
2022
|
-
* fires once a run is already starting; this catches it in the background.
|
|
2023
|
-
*
|
|
2024
|
-
* Returns `{ repaired, unhealed }`: `repaired` is a label (`agent@broken→healed`)
|
|
2025
|
-
* for each version actually fixed; `unhealed` is `agent@version` for each broken
|
|
2026
|
-
* default that could not be fixed (including, under `allowDefaultSwitch:false`,
|
|
2027
|
-
* one that was deliberately not repointed), so the daemon can log/notify. A
|
|
2028
|
-
* version that already launches costs one cheap `--version` probe and is left
|
|
2029
|
-
* untouched.
|
|
2030
|
-
*/
|
|
2031
1492
|
const failedRepairAt = new Map();
|
|
2032
1493
|
const REPAIR_COOLDOWN_MS = 24 * 60 * 60_000;
|
|
2033
1494
|
export async function healBrokenDefaultLaunches(log, opts) {
|
|
@@ -2035,16 +1496,12 @@ export async function healBrokenDefaultLaunches(log, opts) {
|
|
|
2035
1496
|
const unhealed = [];
|
|
2036
1497
|
for (const agent of Object.keys(AGENTS)) {
|
|
2037
1498
|
if (!AGENTS[agent].npmPackage)
|
|
2038
|
-
continue;
|
|
1499
|
+
continue;
|
|
2039
1500
|
const version = getGlobalDefault(agent);
|
|
2040
1501
|
if (!version)
|
|
2041
1502
|
continue;
|
|
2042
1503
|
if ((await verifyInstalledBinaryLaunches(agent, version)).ok)
|
|
2043
1504
|
continue;
|
|
2044
|
-
// Backoff: a version whose repair just failed (offline, npm 404, an arch the
|
|
2045
|
-
// registry can't serve) must NOT re-trigger a full clean-reinstall +
|
|
2046
|
-
// install-latest on every 6h pass. Skip it for a day; a daemon restart clears
|
|
2047
|
-
// the memo, giving a fresh attempt.
|
|
2048
1505
|
const key = `${agent}@${version}`;
|
|
2049
1506
|
const last = failedRepairAt.get(key);
|
|
2050
1507
|
if (last !== undefined && Date.now() - last < REPAIR_COOLDOWN_MS) {
|
|
@@ -2064,26 +1521,9 @@ export async function healBrokenDefaultLaunches(log, opts) {
|
|
|
2064
1521
|
}
|
|
2065
1522
|
return { repaired, unhealed };
|
|
2066
1523
|
}
|
|
2067
|
-
/**
|
|
2068
|
-
* Enumerate the DotAgent repo names that resources can be scoped to:
|
|
2069
|
-
* the fixed `project` / `user` / `system` layers plus every enabled extra
|
|
2070
|
-
* repo alias. Used to validate `agents sync <agent> --repo <name>`.
|
|
2071
|
-
*/
|
|
2072
1524
|
export function listRepoNames() {
|
|
2073
1525
|
return ['project', 'user', 'system', ...getEnabledExtraRepos().map(e => e.alias)];
|
|
2074
1526
|
}
|
|
2075
|
-
/**
|
|
2076
|
-
* Build the name→source-layer map for one resource kind, the input
|
|
2077
|
-
* `expandPatterns` matches `source:*` patterns against. This is the single
|
|
2078
|
-
* source of truth for how each kind attributes its source layer:
|
|
2079
|
-
* - commands/skills/hooks/subagents → real layer from `listResources`
|
|
2080
|
-
* - permissions → real layer from permissions/groups
|
|
2081
|
-
* - mcp → project vs user scope preserved
|
|
2082
|
-
* - plugins → user repo
|
|
2083
|
-
* - workflows → real layer from workflow directories
|
|
2084
|
-
* Both the persisted-pattern sync path and `buildRepoScopedSelection` use it
|
|
2085
|
-
* so the attribution can't drift between the two.
|
|
2086
|
-
*/
|
|
2087
1527
|
function resourceSourceMap(kind, cwd, available) {
|
|
2088
1528
|
switch (kind) {
|
|
2089
1529
|
case 'commands':
|
|
@@ -2116,33 +1556,9 @@ function resourceSourceMap(kind, cwd, available) {
|
|
|
2116
1556
|
}
|
|
2117
1557
|
}
|
|
2118
1558
|
}
|
|
2119
|
-
/**
|
|
2120
|
-
* Build a ResourceSelection from source-pattern expansion and an optional
|
|
2121
|
-
* per-kind name filter. Both dimensions are optional and compose:
|
|
2122
|
-
*
|
|
2123
|
-
* patterns only → resources from those source layers (all matching names)
|
|
2124
|
-
* kindFilter only → only those specific kinds / names, no source restriction
|
|
2125
|
-
* both combined → patterns scope the source layer; kindFilter further
|
|
2126
|
-
* limits which names within each kind are included
|
|
2127
|
-
*
|
|
2128
|
-
* Typical callers:
|
|
2129
|
-
* `--repo system` → buildSelection(['system:*'])
|
|
2130
|
-
* `--plugin` → buildSelection([], { plugins: 'all' })
|
|
2131
|
-
* `--plugin fleet` → buildSelection([], { plugins: ['fleet'] })
|
|
2132
|
-
* no flags → buildSelection([]) → full selection
|
|
2133
|
-
*
|
|
2134
|
-
* Memory (`kindFilter.memory`):
|
|
2135
|
-
* - Always `'all'` when patterns are active (repo scope must recompile the
|
|
2136
|
-
* composed file from all layers, RUSH-1354).
|
|
2137
|
-
* - `'all'` when `kindFilter.memory` is set (--rule / --memory flag).
|
|
2138
|
-
* - Absent (skipped) when kindFilter is given but does not include memory,
|
|
2139
|
-
* so `--plugin fleet` does NOT trigger a memory recompile.
|
|
2140
|
-
* - `'all'` when no kindFilter is given (full sync includes everything).
|
|
2141
|
-
*/
|
|
2142
1559
|
export function buildSelection(patterns, kindFilter, cwd = process.cwd()) {
|
|
2143
1560
|
const hasPatterns = patterns.length > 0;
|
|
2144
1561
|
const hasKindFilter = kindFilter !== undefined;
|
|
2145
|
-
// Fast path: no restrictions → sync every kind
|
|
2146
1562
|
if (!hasPatterns && !hasKindFilter) {
|
|
2147
1563
|
return {
|
|
2148
1564
|
commands: 'all', skills: 'all', hooks: 'all',
|
|
@@ -2158,7 +1574,6 @@ export function buildSelection(patterns, kindFilter, cwd = process.cwd()) {
|
|
|
2158
1574
|
const available = hasPatterns ? getAvailableResources(cwd) : undefined;
|
|
2159
1575
|
for (const kind of allKinds) {
|
|
2160
1576
|
const filterVal = kindFilter?.[kind];
|
|
2161
|
-
// When a kind filter is active, skip kinds not listed in it
|
|
2162
1577
|
if (hasKindFilter && filterVal === undefined)
|
|
2163
1578
|
continue;
|
|
2164
1579
|
if (hasPatterns) {
|
|
@@ -2170,7 +1585,6 @@ export function buildSelection(patterns, kindFilter, cwd = process.cwd()) {
|
|
|
2170
1585
|
selection[kind] = patternNames;
|
|
2171
1586
|
}
|
|
2172
1587
|
else {
|
|
2173
|
-
// Intersect pattern-expanded names with the caller's name filter
|
|
2174
1588
|
const filterSet = new Set(filterVal);
|
|
2175
1589
|
const intersected = patternNames.filter(n => filterSet.has(n));
|
|
2176
1590
|
if (intersected.length > 0)
|
|
@@ -2178,35 +1592,17 @@ export function buildSelection(patterns, kindFilter, cwd = process.cwd()) {
|
|
|
2178
1592
|
}
|
|
2179
1593
|
}
|
|
2180
1594
|
else {
|
|
2181
|
-
// Kind filter only — no pattern restriction; use the filter value directly
|
|
2182
1595
|
selection[kind] = filterVal === 'all' || !filterVal ? 'all' : filterVal;
|
|
2183
1596
|
}
|
|
2184
1597
|
}
|
|
2185
|
-
// Memory is always 'all' when patterns are active (RUSH-1354), when the
|
|
2186
|
-
// memory/rule flag was given, or when no kind filter restricts what is synced.
|
|
2187
1598
|
const memoryRequested = hasPatterns || kindFilter?.memory !== undefined || !hasKindFilter;
|
|
2188
1599
|
if (memoryRequested)
|
|
2189
1600
|
selection.memory = 'all';
|
|
2190
1601
|
return selection;
|
|
2191
1602
|
}
|
|
2192
|
-
/**
|
|
2193
|
-
* Build a ResourceSelection scoped to a single DotAgent repo (`system`,
|
|
2194
|
-
* `user`, `project`, or an extra-repo alias). Delegates to `buildSelection`
|
|
2195
|
-
* so the source-map and pattern-expansion logic stays in one place.
|
|
2196
|
-
*
|
|
2197
|
-
* `memory` is always `'all'`: the composed rules-memory file spans all layers
|
|
2198
|
-
* and must be recompiled in the same pass (RUSH-1354).
|
|
2199
|
-
*/
|
|
2200
1603
|
export function buildRepoScopedSelection(repo, cwd = process.cwd()) {
|
|
2201
1604
|
return buildSelection([`${repo}:*`], undefined, cwd);
|
|
2202
1605
|
}
|
|
2203
|
-
/**
|
|
2204
|
-
* Union several ResourceSelections into one, deduping names per kind. Pure — no
|
|
2205
|
-
* FS — so the merge logic is unit-tested without a DotAgents layout. `memory` is
|
|
2206
|
-
* a whole-file merge of the user+system layers, not a per-repo artifact: pass
|
|
2207
|
-
* `includeMemory` to request a full memory write (`'all'`), else the skip
|
|
2208
|
-
* sentinel (`[]`) is kept.
|
|
2209
|
-
*/
|
|
2210
1606
|
export function unionResourceSelections(selections, includeMemory) {
|
|
2211
1607
|
const merged = {};
|
|
2212
1608
|
const kinds = ['commands', 'skills', 'hooks', 'subagents', 'permissions', 'mcp', 'plugins', 'workflows'];
|
|
@@ -2222,44 +1618,10 @@ export function unionResourceSelections(selections, includeMemory) {
|
|
|
2222
1618
|
merged.memory = includeMemory ? 'all' : [];
|
|
2223
1619
|
return merged;
|
|
2224
1620
|
}
|
|
2225
|
-
/**
|
|
2226
|
-
* Build one selection spanning several DotAgent repos — the source set an
|
|
2227
|
-
* interactive `agents sync` picker collects. Each repo is scoped via
|
|
2228
|
-
* `buildRepoScopedSelection`, then unioned. Memory is written whole when the
|
|
2229
|
-
* `user` or `system` layer is among the selected repos (that's where the memory
|
|
2230
|
-
* file's content comes from); a project-only / alias-only pick leaves it
|
|
2231
|
-
* untouched.
|
|
2232
|
-
*/
|
|
2233
1621
|
export function mergeRepoScopedSelections(repos, cwd = process.cwd()) {
|
|
2234
1622
|
const includeMemory = repos.includes('user') || repos.includes('system');
|
|
2235
1623
|
return unionResourceSelections(repos.map((r) => buildRepoScopedSelection(r, cwd)), includeMemory);
|
|
2236
1624
|
}
|
|
2237
|
-
/**
|
|
2238
|
-
* Sync central resources (~/.agents/) into a specific version's config directory.
|
|
2239
|
-
* Copies selected resources from central storage into {versionHome}/.{agent}/.
|
|
2240
|
-
*
|
|
2241
|
-
* @param agent - The agent ID
|
|
2242
|
-
* @param version - The version string
|
|
2243
|
-
* @param selection - Optional resource selection. If not provided, syncs all resources.
|
|
2244
|
-
*
|
|
2245
|
-
* For Gemini: commands are converted from markdown to TOML.
|
|
2246
|
-
*/
|
|
2247
|
-
/**
|
|
2248
|
-
* Resolve a caller's hook selection against the available hook set, matching a
|
|
2249
|
-
* selection entry by exact name OR by its extensionless basename, and returning
|
|
2250
|
-
* the AVAILABLE (extensioned) name in every case.
|
|
2251
|
-
*
|
|
2252
|
-
* `available.hooks` carries the source filename WITH its extension
|
|
2253
|
-
* (`git-guard.sh`) — the shape the hooks writer's source resolver requires — but
|
|
2254
|
-
* the doctor/heal resource diff identifies a hook by its extensionless basename
|
|
2255
|
-
* (`git-guard`). A heal pass feeds those diff names straight back as the
|
|
2256
|
-
* selection, so a plain exact-set filter matched NOTHING and `agents doctor
|
|
2257
|
-
* --fix` could never reconcile a flagged hook (PHNX-3187). Basename tolerance
|
|
2258
|
-
* closes that gap without changing the extensioned names the writer needs.
|
|
2259
|
-
*
|
|
2260
|
-
* Order-stable and de-duplicated; a selection entry that matches nothing is
|
|
2261
|
-
* dropped (mirrors resolveSelection).
|
|
2262
|
-
*/
|
|
2263
1625
|
export function resolveHookSelection(sel, available) {
|
|
2264
1626
|
if (sel === 'all')
|
|
2265
1627
|
return available;
|
|
@@ -2271,7 +1633,7 @@ export function resolveHookSelection(sel, available) {
|
|
|
2271
1633
|
for (const a of available) {
|
|
2272
1634
|
const base = stripExt(a);
|
|
2273
1635
|
if (!byBase.has(base))
|
|
2274
|
-
byBase.set(base, a);
|
|
1636
|
+
byBase.set(base, a);
|
|
2275
1637
|
}
|
|
2276
1638
|
const out = [];
|
|
2277
1639
|
const seen = new Set();
|
|
@@ -2292,27 +1654,15 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2292
1654
|
const versionHome = getVersionHomePath(agent, version);
|
|
2293
1655
|
const agentDir = path.join(versionHome, agentConfigDirName(agent));
|
|
2294
1656
|
fs.mkdirSync(agentDir, { recursive: true });
|
|
2295
|
-
// Capture whether the caller passed a selection. The pattern-expansion
|
|
2296
|
-
// path below reassigns `selection`, but for manifest write semantics we
|
|
2297
|
-
// care about the ORIGINAL intent: a caller passing no selection means
|
|
2298
|
-
// "full sync; persist the staleness manifest after."
|
|
2299
1657
|
const userPassedSelection = selection !== undefined;
|
|
2300
1658
|
const result = { commands: false, skills: false, hooks: false, memory: [], permissions: false, mcp: [], subagents: [], plugins: [], workflows: [], projectSkipped: [], pruned: { commands: [], skills: [] }, declined: [] };
|
|
2301
1659
|
const cwd = options.cwd || process.cwd();
|
|
2302
1660
|
const projectAgentsDir = options.projectDir || getProjectAgentsDir(cwd);
|
|
2303
1661
|
const userAgentsDir = getUserAgentsDir();
|
|
2304
|
-
// Extra DotAgent repos registered via `agents repo add`. Looked up last so
|
|
2305
|
-
// project/user/system repos win on name collisions.
|
|
2306
1662
|
const extraRepos = getEnabledExtraRepos();
|
|
2307
|
-
// Project-layer fan-out always runs — even on the early guard hit — so the
|
|
2308
|
-
// `projectSkipped` contract is preserved for callers (RUSH-2320 #4).
|
|
2309
1663
|
if (projectAgentsDir) {
|
|
2310
1664
|
result.projectSkipped = syncProjectResourcesToAgent(agent, version, projectAgentsDir).skipped;
|
|
2311
1665
|
}
|
|
2312
|
-
// Install the shared SessionStart state-writer hook for every hook-capable
|
|
2313
|
-
// harness. This must run even when the rest of the sync is skipped by the
|
|
2314
|
-
// staleness guard, because the hook is registered in the harness's native
|
|
2315
|
-
// config (not in the version-home resource tree the manifest tracks).
|
|
2316
1666
|
if (supports(agent, 'hooks', version).ok) {
|
|
2317
1667
|
const trackerResult = installSessionTrackerHookSync(agent, version);
|
|
2318
1668
|
if (!trackerResult.installed && trackerResult.error) {
|
|
@@ -2325,32 +1675,20 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2325
1675
|
console.warn(`agents: Claude status line not installed for ${agent}@${version}: ${statusLine.error}`);
|
|
2326
1676
|
}
|
|
2327
1677
|
}
|
|
2328
|
-
// Fast guard BEFORE getAvailableResources / pattern expansion /
|
|
2329
|
-
// ensureVersionResourcePatterns. Guard needs only loadManifest + isStale
|
|
2330
|
-
// (~6 ms); the work that used to sit ahead of it was ~12.5 ms of the 21.5 ms
|
|
2331
|
-
// guard-hit path and is discarded when nothing changed (RUSH-2320 #4).
|
|
2332
|
-
// Behavior note: a valid manifest implies a prior full sync already wrote
|
|
2333
|
-
// version resource patterns, so skipping ensureVersionResourcePatterns on
|
|
2334
|
-
// the hit path is safe in practice but is not byte-identical to the old
|
|
2335
|
-
// order (that call always wrote missing pattern defaults).
|
|
2336
1678
|
if (!userPassedSelection && !options.force) {
|
|
2337
1679
|
const manifest = loadManifest(agent, version);
|
|
2338
1680
|
if (manifest && !isStale(manifest, agent, version, cwd)) {
|
|
2339
1681
|
return { ...result };
|
|
2340
1682
|
}
|
|
2341
1683
|
}
|
|
2342
|
-
// Prefer a caller-supplied inventory (refresh already built one) so multi-
|
|
2343
|
-
// version fan-out does not re-scan resource trees per version (RUSH-2320 #5).
|
|
2344
1684
|
const available = options.available ?? getAvailableResources(cwd);
|
|
2345
|
-
// Write default resource selection patterns for this version (idempotent —
|
|
2346
|
-
// only sets fields that aren't already present, preserving user edits).
|
|
2347
1685
|
{
|
|
2348
1686
|
const extraAliases = extraRepos.map(e => e.alias);
|
|
2349
1687
|
const noProject = defaultPatterns(extraAliases, false);
|
|
2350
1688
|
ensureVersionResourcePatterns(agent, version, {
|
|
2351
1689
|
commands: noProject,
|
|
2352
1690
|
skills: noProject,
|
|
2353
|
-
hooks: noProject,
|
|
1691
|
+
hooks: noProject,
|
|
2354
1692
|
subagents: noProject,
|
|
2355
1693
|
plugins: noProject,
|
|
2356
1694
|
workflows: noProject,
|
|
@@ -2358,16 +1696,10 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2358
1696
|
mcp: ['user:*'],
|
|
2359
1697
|
});
|
|
2360
1698
|
}
|
|
2361
|
-
// If no explicit selection was passed, build one from the persisted resource
|
|
2362
|
-
// patterns. This lets users customize agents.yaml to control which resources
|
|
2363
|
-
// are synced (e.g. "skills: [system:brain-scan user:creative]").
|
|
2364
|
-
// When patterns are the default (every layer wildcard), the expanded result
|
|
2365
|
-
// equals the full available set — identical to the old behavior.
|
|
2366
1699
|
if (!selection) {
|
|
2367
1700
|
const vr = getVersionResources(agent, version);
|
|
2368
1701
|
if (vr) {
|
|
2369
1702
|
const patternSelection = {};
|
|
2370
|
-
// Listable resource types: use listResources to get name→source maps.
|
|
2371
1703
|
const listableTypes = [
|
|
2372
1704
|
['commands', 'commands'],
|
|
2373
1705
|
['skills', 'skills'],
|
|
@@ -2380,8 +1712,6 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2380
1712
|
continue;
|
|
2381
1713
|
patternSelection[type] = expandPatterns(patterns, resourceSourceMap(kind, cwd, available));
|
|
2382
1714
|
}
|
|
2383
|
-
// permissions / mcp / plugins / workflows: source attribution lives in
|
|
2384
|
-
// resourceSourceMap so it can't drift from buildRepoScopedSelection.
|
|
2385
1715
|
if (Array.isArray(vr.permissions) && vr.permissions.length > 0) {
|
|
2386
1716
|
patternSelection.permissions = expandPatterns(vr.permissions, resourceSourceMap('permissions', cwd, available));
|
|
2387
1717
|
}
|
|
@@ -2394,14 +1724,12 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2394
1724
|
if (Array.isArray(vr.workflows) && vr.workflows.length > 0) {
|
|
2395
1725
|
patternSelection.workflows = expandPatterns(vr.workflows, resourceSourceMap('workflows', cwd, available));
|
|
2396
1726
|
}
|
|
2397
|
-
// memory is not pattern-controlled (rulesPreset handles it) — always sync.
|
|
2398
1727
|
patternSelection.memory = 'all';
|
|
2399
1728
|
if (Object.keys(patternSelection).length > 0) {
|
|
2400
1729
|
selection = patternSelection;
|
|
2401
1730
|
}
|
|
2402
1731
|
}
|
|
2403
1732
|
}
|
|
2404
|
-
// Helper: remove a path (symlink or real) if it exists
|
|
2405
1733
|
const removePath = (p) => {
|
|
2406
1734
|
try {
|
|
2407
1735
|
const stat = fs.lstatSync(p);
|
|
@@ -2412,9 +1740,8 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2412
1740
|
fs.rmSync(p, { recursive: true, force: true });
|
|
2413
1741
|
}
|
|
2414
1742
|
}
|
|
2415
|
-
catch {
|
|
1743
|
+
catch { }
|
|
2416
1744
|
};
|
|
2417
|
-
// Helper: copy a directory recursively
|
|
2418
1745
|
const copyDir = (src, dest) => {
|
|
2419
1746
|
fs.mkdirSync(dest, { recursive: true });
|
|
2420
1747
|
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
@@ -2433,7 +1760,6 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2433
1760
|
}
|
|
2434
1761
|
}
|
|
2435
1762
|
};
|
|
2436
|
-
// Helper: resolve selection to list of items
|
|
2437
1763
|
const resolveSelection = (sel, available) => {
|
|
2438
1764
|
if (sel === 'all')
|
|
2439
1765
|
return available;
|
|
@@ -2444,30 +1770,16 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2444
1770
|
return [];
|
|
2445
1771
|
};
|
|
2446
1772
|
const trustedCommandNames = (names) => names.filter((name) => resolveCommandSource(name) !== null);
|
|
2447
|
-
// Sync commands — dispatch through WRITERS.commands. The writer dispatches
|
|
2448
|
-
// between native (file copy / TOML conversion), commands-as-skills, and the
|
|
2449
|
-
// registry-driven dual-write path based on the command-skill predicates. The
|
|
2450
|
-
// previous COMMANDS_CAPABLE_AGENTS gate excluded skills-only targets such as
|
|
2451
|
-
// Kimi, silently dropping every converted command.
|
|
2452
1773
|
const commandsWriter = getWriter('commands', agent);
|
|
2453
1774
|
const commandsToSync = selection
|
|
2454
1775
|
? trustedCommandNames(resolveSelection(selection.commands, available.commands))
|
|
2455
|
-
: trustedCommandNames(available.commands);
|
|
1776
|
+
: trustedCommandNames(available.commands);
|
|
2456
1777
|
const commandsAsSkills = shouldInstallCommandAsSkill(agent, version);
|
|
2457
1778
|
const commandsAlsoAsSkills = shouldAlsoInstallCommandAsSkill(agent, version);
|
|
2458
1779
|
const commandsInstallAsSkills = commandsAsSkills || commandsAlsoAsSkills;
|
|
2459
1780
|
let writtenCommands = [];
|
|
2460
|
-
// Artifact paths the writers report (WriteResult.paths), persisted to the
|
|
2461
|
-
// manifest as `writtenTargets` after a full sync so isStale can flag a
|
|
2462
|
-
// deleted artifact as stale (#2398).
|
|
2463
1781
|
const writtenTargets = [];
|
|
2464
1782
|
if (commandsToSync.length > 0 && commandsWriter) {
|
|
2465
|
-
// Agents that replace native command files with skills (codex >= 0.117.0,
|
|
2466
|
-
// kimi) must have their legacy command dir removed, or files written by an
|
|
2467
|
-
// older version linger forever: the orphan sweep below is gated off for
|
|
2468
|
-
// them, and `agents prune` only sees their skills. Gated on
|
|
2469
|
-
// `commandsAsSkills`, never `commandsAlsoAsSkills` -- a dual-write agent's
|
|
2470
|
-
// native dir is a live product surface (Cursor IDE) and must not be wiped.
|
|
2471
1783
|
if (commandsAsSkills && agentConfig.commandsSubdir) {
|
|
2472
1784
|
removePath(path.join(agentDir, agentConfig.commandsSubdir));
|
|
2473
1785
|
}
|
|
@@ -2477,22 +1789,11 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2477
1789
|
writtenTargets.push(...r.paths);
|
|
2478
1790
|
result.commands = r.synced.length > 0;
|
|
2479
1791
|
}
|
|
2480
|
-
// Orphan-sweep stale top-level command files from previous syncs under a
|
|
2481
|
-
// different cwd. Only runs in "full sync" mode — i.e. when the caller did
|
|
2482
|
-
// not pass an explicit `selection`. Callers that pass explicit selections
|
|
2483
|
-
// are using the incremental/additive API (sync exactly these; leave others
|
|
2484
|
-
// alone), so the sweep would be a contract violation there. The
|
|
2485
|
-
// cross-project leak comes from no-selection full syncs run under different
|
|
2486
|
-
// cwds (`agents sync` / `agents refresh`; the shim's `agents sync --launch`
|
|
2487
|
-
// skips version-home reconciliation and never reaches this path).
|
|
2488
1792
|
if (!userPassedSelection && commandsWriter && !shouldInstallCommandAsSkill(agent, version)) {
|
|
2489
1793
|
const commandsTargetSweep = path.join(agentDir, agentConfig.commandsSubdir);
|
|
2490
1794
|
if (fs.existsSync(commandsTargetSweep)) {
|
|
2491
1795
|
const ext = agentConfig.format === 'toml' ? '.toml' : '.md';
|
|
2492
1796
|
const trustedCommands = new Set(commandsToSync);
|
|
2493
|
-
// A dual-write target's native directory also belongs to another product
|
|
2494
|
-
// surface (Cursor IDE). Delete only names the command writer recorded as
|
|
2495
|
-
// successfully emitted during the preceding full sync.
|
|
2496
1797
|
const previouslyManagedCommands = commandsAlsoAsSkills
|
|
2497
1798
|
? new Set(loadManifest(agent, version)?.writtenCommands ?? [])
|
|
2498
1799
|
: null;
|
|
@@ -2508,9 +1809,6 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2508
1809
|
}
|
|
2509
1810
|
}
|
|
2510
1811
|
}
|
|
2511
|
-
// Sync skills — dispatch through WRITERS.skills. Agents that natively read
|
|
2512
|
-
// ~/.agents/skills/ (Gemini) are not registered; we clear the version-home
|
|
2513
|
-
// skills dir for them so a stale per-version copy never shadows central.
|
|
2514
1812
|
const skillsWriter = getWriter('skills', agent);
|
|
2515
1813
|
const pluginsWriter = getWriter('plugins', agent);
|
|
2516
1814
|
const pluginsToSync = selection
|
|
@@ -2547,18 +1845,8 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2547
1845
|
writtenTargets.push(...r.paths);
|
|
2548
1846
|
result.skills = r.synced.length > 0;
|
|
2549
1847
|
}
|
|
2550
|
-
// Orphan-sweep stale skill directories from previous syncs under a
|
|
2551
|
-
// different cwd. Only runs in "full sync" mode (no explicit selection) —
|
|
2552
|
-
// see the matching guard on the commands sweep above for why. Skip
|
|
2553
|
-
// dot-dirs to keep plugin-managed subtrees (.plugins/, .promptcuts) intact,
|
|
2554
|
-
// and the harness's own directories (ownedSkillDirs), which it writes itself.
|
|
2555
1848
|
const skillsTargetSweep = path.join(agentDir, 'skills');
|
|
2556
1849
|
if (!userPassedSelection && fs.existsSync(skillsTargetSweep) && !fs.lstatSync(skillsTargetSweep).isSymbolicLink()) {
|
|
2557
|
-
// Trust real skills AND command-skills: when commandsInstallAsSkills, the
|
|
2558
|
-
// commands writer (above) materialized each command as a skill dir under
|
|
2559
|
-
// skills/. Those names are not in skillsToSync, so without this they'd be
|
|
2560
|
-
// swept as orphans — silently deleting every converted command (e.g.
|
|
2561
|
-
// /recap on Kimi or newer Codex releases).
|
|
2562
1850
|
const trustedSkills = new Set([...skillsToSync, ...(agentConfig.ownedSkillDirs ?? [])]);
|
|
2563
1851
|
if (commandsInstallAsSkills)
|
|
2564
1852
|
for (const cmd of commandsToSync)
|
|
@@ -2572,8 +1860,6 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2572
1860
|
}
|
|
2573
1861
|
}
|
|
2574
1862
|
}
|
|
2575
|
-
// Sync hooks — dispatch through WRITERS.hooks. supports() gate enforces
|
|
2576
|
-
// the version cutoff (codex >= 0.116.0, gemini >= 0.26.0).
|
|
2577
1863
|
const hooksGate = supports(agent, 'hooks', version);
|
|
2578
1864
|
const hooksWriter = getWriter('hooks', agent);
|
|
2579
1865
|
if (agentConfig.supportsHooks && hooksWriter) {
|
|
@@ -2581,23 +1867,12 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2581
1867
|
console.warn(explainSkip(agent, 'hooks', hooksGate, version) + ' -- skipped');
|
|
2582
1868
|
}
|
|
2583
1869
|
else {
|
|
2584
|
-
// Resolve requested hooks against the available set BY BASENAME as well as
|
|
2585
|
-
// exact name. `available.hooks` carries the source filename WITH its
|
|
2586
|
-
// extension (`git-guard.sh`), but the doctor/heal diff identifies a hook
|
|
2587
|
-
// by its extensionless basename (`git-guard`) — so a heal pass that feeds
|
|
2588
|
-
// the diff's names straight back through the plain resolveSelection
|
|
2589
|
-
// matched NOTHING and could never reconcile a flagged hook (PHNX-3187).
|
|
2590
1870
|
const hooksToSync = selection
|
|
2591
1871
|
? resolveHookSelection(selection.hooks, available.hooks)
|
|
2592
1872
|
: available.hooks;
|
|
2593
1873
|
let hookManifest = {};
|
|
2594
1874
|
if (hooksToSync.length > 0) {
|
|
2595
1875
|
const r = hooksWriter.write({ version, versionHome, selection: hooksToSync, cwd });
|
|
2596
|
-
// Remove orphan files from version home. The trusted set is the
|
|
2597
|
-
// manifest-declared hook list (`available.hooks`) — auxiliary files
|
|
2598
|
-
// like README.md or promptcuts.yaml may exist alongside hooks at the
|
|
2599
|
-
// source but are not hooks and must not linger in version homes from
|
|
2600
|
-
// older syncs.
|
|
2601
1876
|
const hooksTarget = path.join(agentDir, 'hooks');
|
|
2602
1877
|
const trustedHookNames = new Set(available.hooks);
|
|
2603
1878
|
if (fs.existsSync(hooksTarget)) {
|
|
@@ -2618,18 +1893,10 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2618
1893
|
}
|
|
2619
1894
|
}
|
|
2620
1895
|
}
|
|
2621
|
-
// Sync rules — dispatch through WRITERS.rules. The registry routes to the
|
|
2622
|
-
// single-target writer for any agent that declares `rules: { file }` in
|
|
2623
|
-
// its capability matrix (grok included; the previous gate used the wrong
|
|
2624
|
-
// CAPABLE_AGENTS list and silently skipped it). Project rules are NOT
|
|
2625
|
-
// synced into the version home — they are composed into the workspace at
|
|
2626
|
-
// agents-run time (see compileRulesForProject).
|
|
2627
1896
|
const skipMemory = selection && Array.isArray(selection.memory) && selection.memory.length === 0;
|
|
2628
1897
|
const rulesWriter = getWriter('rules', agent);
|
|
2629
1898
|
if (!skipMemory && rulesWriter) {
|
|
2630
1899
|
try {
|
|
2631
|
-
// If selection.memory names a single preset, treat it as a one-shot
|
|
2632
|
-
// override; otherwise read the persisted active preset.
|
|
2633
1900
|
const overridePreset = Array.isArray(selection?.memory) && selection.memory.length === 1 && selection.memory[0] !== 'AGENTS'
|
|
2634
1901
|
? selection.memory[0]
|
|
2635
1902
|
: null;
|
|
@@ -2638,23 +1905,11 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2638
1905
|
if (r.paths)
|
|
2639
1906
|
writtenTargets.push(...r.paths);
|
|
2640
1907
|
result.memory.push(...r.synced);
|
|
2641
|
-
// rulesPreset is tracked separately via setActiveRulesPreset.
|
|
2642
1908
|
}
|
|
2643
1909
|
catch (err) {
|
|
2644
|
-
// No rules.yaml yet, or a typo'd preset name. Don't fail the whole sync —
|
|
2645
|
-
// just leave the agent without a synced rules file.
|
|
2646
1910
|
console.warn(`Skipping rules sync for ${agent}@${version}: ${err.message}`);
|
|
2647
1911
|
}
|
|
2648
1912
|
}
|
|
2649
|
-
// Apply permissions (if agent supports them).
|
|
2650
|
-
// Groups live in ~/.agents/permissions/groups/. Optional recipes in
|
|
2651
|
-
// ~/.agents/permissions/presets/<name>.yaml pick a subset via `includes:`.
|
|
2652
|
-
// If AGENTS_PERMISSION_PRESET is set, we resolve that recipe and use its
|
|
2653
|
-
// includes list as the group filter (intersected with groups on disk).
|
|
2654
|
-
// Note: discoverPermissionGroups intentionally reads from user + system
|
|
2655
|
-
// only — never from a project's .agents/permissions/. Permissions gate
|
|
2656
|
-
// every other action, so a cloned public repo must not be able to widen
|
|
2657
|
-
// its own sandbox by shipping a permissions group. Same defense as hooks.
|
|
2658
1913
|
const permissionGroups = discoverPermissionGroups();
|
|
2659
1914
|
const allGroupNames = permissionGroups.map(g => g.name);
|
|
2660
1915
|
const activePresetName = getActivePermissionPresetName();
|
|
@@ -2673,11 +1928,6 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2673
1928
|
let permsToSync;
|
|
2674
1929
|
if (selection) {
|
|
2675
1930
|
permsToSync = resolveSelection(selection.permissions, allGroupNames);
|
|
2676
|
-
// If a preset recipe is active, the recipe's includes list always wins —
|
|
2677
|
-
// even when the caller passed an explicit array via selection. Without
|
|
2678
|
-
// this intersection, `agents add`'s buildAutomaticSelection would pass
|
|
2679
|
-
// every group name discovered on disk (including 99-deny), bypassing
|
|
2680
|
-
// the sandbox filter.
|
|
2681
1931
|
if (presetFilteredGroups) {
|
|
2682
1932
|
const filterSet = new Set(presetFilteredGroups);
|
|
2683
1933
|
permsToSync = permsToSync.filter(g => filterSet.has(g));
|
|
@@ -2689,20 +1939,7 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2689
1939
|
if (permsToSync.length > 0 && permissionsWriter) {
|
|
2690
1940
|
const r = permissionsWriter.write({ version, versionHome, selection: permsToSync, cwd });
|
|
2691
1941
|
result.permissions = r.synced.length > 0;
|
|
2692
|
-
|
|
2693
|
-
}
|
|
2694
|
-
// Install MCP servers (if agent supports them)
|
|
2695
|
-
// For Claude/Codex: uses CLI commands (claude mcp add, codex mcp add)
|
|
2696
|
-
// For others: edits config files directly
|
|
2697
|
-
//
|
|
2698
|
-
// Mirror the hooks defense: an MCP server is an executable invoked under the
|
|
2699
|
-
// agent's authority, so a cloned public repo's .agents/mcp/foo.yaml could
|
|
2700
|
-
// install an arbitrary command (RUSH-1776). Project-scoped MCPs are UNTRUSTED
|
|
2701
|
-
// by default — drop them before handing the list to installMcpServers unless
|
|
2702
|
-
// the user has explicitly trusted this project (`agents mcp trust`). The
|
|
2703
|
-
// register/spawn choke in lib/mcp.ts (getMcpServersByName) enforces the same
|
|
2704
|
-
// trust gate and drops untrusted project entries before dedup, so a project
|
|
2705
|
-
// entry can no longer shadow a same-named user entry either.
|
|
1942
|
+
}
|
|
2706
1943
|
const projectMcpTrusted = projectAgentsDir ? isProjectMcpTrusted(projectAgentsDir) : false;
|
|
2707
1944
|
const untrustedProjectMcpNames = new Set(projectMcpTrusted
|
|
2708
1945
|
? []
|
|
@@ -2719,11 +1956,7 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2719
1956
|
result.mcp = r.synced;
|
|
2720
1957
|
if (r.errors?.length)
|
|
2721
1958
|
result.declined.push(...r.errors.map((e) => `mcp: ${e}`));
|
|
2722
|
-
// mcp patterns already written via ensureVersionResourcePatterns above.
|
|
2723
1959
|
}
|
|
2724
|
-
// Sync subagents — dispatch through WRITERS.subagents. listInstalledSubagents
|
|
2725
|
-
// reads only user + system layers (project excluded for the same defense
|
|
2726
|
-
// as commands/skills/hooks).
|
|
2727
1960
|
const subagentsWriter = getWriter('subagents', agent);
|
|
2728
1961
|
const subagentsGate = supports(agent, 'subagents', version);
|
|
2729
1962
|
const installedSubagentNames = new Set(listInstalledSubagents().map((subagent) => subagent.name));
|
|
@@ -2742,9 +1975,6 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2742
1975
|
result.subagents.push(...r.synced);
|
|
2743
1976
|
if (r.errors?.length)
|
|
2744
1977
|
result.declined.push(...r.errors.map((e) => `subagents: ${e}`));
|
|
2745
|
-
// Orphan-sweep for Claude only — see comment on commands/skills sweep
|
|
2746
|
-
// for the no-selection guard. OpenClaw stores subagents as siblings of
|
|
2747
|
-
// other resources so a readdir sweep would over-reach.
|
|
2748
1978
|
if (!userPassedSelection && agent === 'claude') {
|
|
2749
1979
|
const claudeAgentsDir = path.join(agentDir, 'agents');
|
|
2750
1980
|
if (fs.existsSync(claudeAgentsDir)) {
|
|
@@ -2762,15 +1992,9 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2762
1992
|
}
|
|
2763
1993
|
}
|
|
2764
1994
|
}
|
|
2765
|
-
// Sync plugins — dispatch through WRITERS.plugins (or directly via
|
|
2766
|
-
// syncPluginToVersion when allowExecSurfaces is requested, since WriteArgs
|
|
2767
|
-
// has no channel for that option).
|
|
2768
1995
|
if (pluginsToSync.length > 0 && pluginsWriter) {
|
|
2769
1996
|
if (options.allowExecSurfaces) {
|
|
2770
1997
|
const allPlugins = discoverPlugins();
|
|
2771
|
-
// Pass the discovered plugins (with marketplace provenance) so a stale
|
|
2772
|
-
// install under one marketplace is trashed even when another marketplace
|
|
2773
|
-
// still ships that name — the PHNX-2618 shadow `code` plugin.
|
|
2774
1998
|
cleanOrphanedPluginSkills(agent, versionHome, allPlugins);
|
|
2775
1999
|
const pluginMap = new Map(allPlugins.map(p => [p.name, p]));
|
|
2776
2000
|
for (const name of pluginsToSync) {
|
|
@@ -2787,7 +2011,6 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2787
2011
|
result.plugins.push(...r.synced);
|
|
2788
2012
|
}
|
|
2789
2013
|
}
|
|
2790
|
-
// Sync workflows — dispatch through WRITERS.workflows.
|
|
2791
2014
|
const workflowsWriter = getWriter('workflows', agent);
|
|
2792
2015
|
const workflowsGate = supports(agent, 'workflows', version);
|
|
2793
2016
|
const trustedWorkflowNames = (names) => {
|
|
@@ -2807,28 +2030,12 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2807
2030
|
const r = workflowsWriter.write({ version, versionHome, selection: workflowsToSync, cwd });
|
|
2808
2031
|
result.workflows.push(...r.synced);
|
|
2809
2032
|
}
|
|
2810
|
-
// Knowledge memory (RUSH-1330) — distinct from selection.memory which still
|
|
2811
|
-
// means the composed *rules* file. Always fan out ~/.agents/memory/ facts
|
|
2812
|
-
// into capable agent version homes on every full or partial sync.
|
|
2813
2033
|
if (supports(agent, 'memory', version).ok) {
|
|
2814
2034
|
syncMemoryToVersionHome(agent, versionHome, cwd);
|
|
2815
2035
|
}
|
|
2816
|
-
// Claude Code's own NATIVE per-project auto-memory (.claude/projects/<key>/memory/,
|
|
2817
|
-
// PHNX-2817) is a separate, unmanaged directory Claude writes into itself — make it
|
|
2818
|
-
// version-independent the same way project-level rules already are, via a shared
|
|
2819
|
-
// symlink, so a note survives an agent version upgrade instead of vanishing into a
|
|
2820
|
-
// fresh, empty version home.
|
|
2821
2036
|
if (agent === 'claude') {
|
|
2822
2037
|
syncClaudeProjectMemoryDir(versionHome, cwd);
|
|
2823
2038
|
}
|
|
2824
|
-
// Prune resources deleted from source (RUSH-2438). Runs only on a repo-scope
|
|
2825
|
-
// reconcile (`options.prune`) with a caller selection — a full sync
|
|
2826
|
-
// (`!userPassedSelection`) already sweeps orphans above, and an additive
|
|
2827
|
-
// interactive/`agents add` selection must not delete anything. The prune is
|
|
2828
|
-
// manifest-bounded: only names the last full sync recorded are candidates,
|
|
2829
|
-
// and only when they are gone from ALL source layers — so a user-authored
|
|
2830
|
-
// file the sync never placed, or a same-named resource still provided by
|
|
2831
|
-
// another layer, is never removed. No manifest → fail loud (delete nothing).
|
|
2832
2039
|
if (options.prune && userPassedSelection) {
|
|
2833
2040
|
const previousManifest = loadManifest(agent, version);
|
|
2834
2041
|
const outcome = pruneRemovedResources({
|
|
@@ -2848,23 +2055,15 @@ export function syncResourcesToVersion(agent, version, selection, options = {})
|
|
|
2848
2055
|
`Run 'agents sync ${agent}@${version}' (a full sync) to establish the baseline.`);
|
|
2849
2056
|
}
|
|
2850
2057
|
}
|
|
2851
|
-
// Write manifest after a full sync (no user-passed selection) so the next
|
|
2852
|
-
// launch can skip the slow path. Pattern-derived selections still count as
|
|
2853
|
-
// "full" — the agents.yaml patterns describe the intended scope, not a
|
|
2854
|
-
// one-off override, so the resulting state matches what the manifest
|
|
2855
|
-
// records as the synced set. Carry forward still-fresh fingerprints from
|
|
2856
|
-
// the previous manifest so we do not re-hash an unchanged tree (RUSH-2320 #3).
|
|
2857
2058
|
if (!userPassedSelection) {
|
|
2858
2059
|
const previous = loadManifest(agent, version);
|
|
2859
2060
|
const manifest = buildSyncManifest(agent, version, cwd, previous);
|
|
2860
2061
|
manifest.writtenCommands = writtenCommands;
|
|
2861
|
-
// Deduped + sorted so repeated full syncs write byte-identical manifests.
|
|
2862
2062
|
manifest.writtenTargets = Array.from(new Set(writtenTargets)).sort();
|
|
2863
2063
|
saveManifest(agent, version, manifest);
|
|
2864
2064
|
}
|
|
2865
2065
|
return result;
|
|
2866
2066
|
}
|
|
2867
|
-
/** Thrown when an `agent@version` target is not installed; carries the parsed ids so callers can react without parsing the message. */
|
|
2868
2067
|
export class VersionNotInstalledError extends Error {
|
|
2869
2068
|
agentId;
|
|
2870
2069
|
version;
|
|
@@ -2878,7 +2077,6 @@ export class VersionNotInstalledError extends Error {
|
|
|
2878
2077
|
this.name = 'VersionNotInstalledError';
|
|
2879
2078
|
}
|
|
2880
2079
|
}
|
|
2881
|
-
/** Resolve a comma-separated `--agents` list into concrete installed version selections. */
|
|
2882
2080
|
export function resolveAgentVersionTargets(value, availableAgents, options = {}) {
|
|
2883
2081
|
const selectedAgents = [];
|
|
2884
2082
|
const versionSelections = new Map();
|
|
@@ -2887,9 +2085,6 @@ export function resolveAgentVersionTargets(value, availableAgents, options = {})
|
|
|
2887
2085
|
.split(',')
|
|
2888
2086
|
.map((item) => item.trim())
|
|
2889
2087
|
.filter(Boolean);
|
|
2890
|
-
// Expand literal `all` (with optional @all) into every available agent's all
|
|
2891
|
-
// installed versions. Skip agents with no installed versions so `all` is
|
|
2892
|
-
// lenient — only explicit `claude@all` errors when claude isn't installed.
|
|
2893
2088
|
const targets = [];
|
|
2894
2089
|
for (const t of rawTargets) {
|
|
2895
2090
|
if (t === 'all' || t === 'all@all') {
|
|
@@ -2970,7 +2165,6 @@ export function resolveAgentVersionTargets(value, availableAgents, options = {})
|
|
|
2970
2165
|
}
|
|
2971
2166
|
return { selectedAgents, versionSelections };
|
|
2972
2167
|
}
|
|
2973
|
-
/** Resolve a comma-separated `--agents` list into install/apply targets, distinguishing managed versions from direct homes. */
|
|
2974
2168
|
export function resolveInstalledAgentTargets(value, availableAgents, options = {}) {
|
|
2975
2169
|
const selectedAgents = [];
|
|
2976
2170
|
const directAgents = [];
|
|
@@ -2979,11 +2173,6 @@ export function resolveInstalledAgentTargets(value, availableAgents, options = {
|
|
|
2979
2173
|
.split(',')
|
|
2980
2174
|
.map((item) => item.trim())
|
|
2981
2175
|
.filter(Boolean);
|
|
2982
|
-
// Expand literal `all` (with optional @all) into every available agent's all
|
|
2983
|
-
// installed versions. Skip agents with no installed versions so `all` is
|
|
2984
|
-
// lenient — only explicit `claude@all` errors when claude isn't installed.
|
|
2985
|
-
// Mirrors resolveAgentVersionTargets so every --agents flag site supports
|
|
2986
|
-
// the same selector syntax.
|
|
2987
2176
|
const targets = [];
|
|
2988
2177
|
for (const t of rawTargets) {
|
|
2989
2178
|
if (t === 'all' || t === 'all@all') {
|
|
@@ -3068,7 +2257,6 @@ export function resolveInstalledAgentTargets(value, availableAgents, options = {
|
|
|
3068
2257
|
}
|
|
3069
2258
|
return { selectedAgents, directAgents, versionSelections };
|
|
3070
2259
|
}
|
|
3071
|
-
/** Resolve configured manifest targets into direct homes and managed versions. */
|
|
3072
2260
|
export function resolveConfiguredAgentTargets(agents, agentVersions, availableAgents, options = {}) {
|
|
3073
2261
|
const targetSpecs = [];
|
|
3074
2262
|
const broadTargets = agents ? [...agents] : [...availableAgents];
|
|
@@ -3095,10 +2283,8 @@ export function resolveConfiguredAgentTargets(agents, agentVersions, availableAg
|
|
|
3095
2283
|
}
|
|
3096
2284
|
return resolveInstalledAgentTargets(targetSpecs.join(','), availableAgents, options);
|
|
3097
2285
|
}
|
|
3098
|
-
/** Prompt the user to select agents and versions for resource installation. */
|
|
3099
2286
|
export async function promptAgentVersionSelection(availableAgents, options = {}) {
|
|
3100
2287
|
const versionSelections = new Map();
|
|
3101
|
-
// Filter to installed agents (only those with versions managed by agents CLI)
|
|
3102
2288
|
const installedAgents = availableAgents.filter((id) => {
|
|
3103
2289
|
const versions = listInstalledVersions(id);
|
|
3104
2290
|
return versions.length > 0;
|
|
@@ -3111,9 +2297,6 @@ export async function promptAgentVersionSelection(availableAgents, options = {})
|
|
|
3111
2297
|
const defaultVer = getGlobalDefault(agentId);
|
|
3112
2298
|
if (versions.length === 0)
|
|
3113
2299
|
return `${AGENTS[agentId].name} ${chalk.gray('(not installed)')}`;
|
|
3114
|
-
// Surface the version count when there's more than one — mirrors the new
|
|
3115
|
-
// `--agents <agent>@all` syntax so users can see at a glance how many
|
|
3116
|
-
// versions `@all` would target before the per-version prompt fires.
|
|
3117
2300
|
const detail = versions.length > 1
|
|
3118
2301
|
? (defaultVer
|
|
3119
2302
|
? `active: ${defaultVer}, ${versions.length} versions installed`
|
|
@@ -3123,7 +2306,6 @@ export async function promptAgentVersionSelection(availableAgents, options = {})
|
|
|
3123
2306
|
};
|
|
3124
2307
|
let selectedAgents;
|
|
3125
2308
|
if (options.skipPrompts) {
|
|
3126
|
-
// Auto-select all installed agents with default versions
|
|
3127
2309
|
selectedAgents = [...installedAgents];
|
|
3128
2310
|
for (const agentId of selectedAgents) {
|
|
3129
2311
|
const versions = listInstalledVersions(agentId);
|
|
@@ -3134,9 +2316,6 @@ export async function promptAgentVersionSelection(availableAgents, options = {})
|
|
|
3134
2316
|
}
|
|
3135
2317
|
}
|
|
3136
2318
|
else {
|
|
3137
|
-
// Non-TTY without an explicit --agents value used to silently fall through
|
|
3138
|
-
// to default-picking inside the caller. That's surprising in scripts — fail
|
|
3139
|
-
// loud and point at the new `--agents` syntax instead.
|
|
3140
2319
|
if (!(process.stdin.isTTY && process.stdout.isTTY)) {
|
|
3141
2320
|
throw new Error('Non-interactive shell: cannot prompt for agent/version selection.\n' +
|
|
3142
2321
|
'Pass --agents explicitly. Examples:\n' +
|
|
@@ -3146,7 +2325,6 @@ export async function promptAgentVersionSelection(availableAgents, options = {})
|
|
|
3146
2325
|
' --agents all (every installed version of every capable agent)\n' +
|
|
3147
2326
|
'Or pass --yes to auto-pick defaults.');
|
|
3148
2327
|
}
|
|
3149
|
-
// Prompt for agent selection
|
|
3150
2328
|
const checkboxResult = await checkbox({
|
|
3151
2329
|
message: 'Which agents should receive these resources?',
|
|
3152
2330
|
choices: [
|
|
@@ -3164,7 +2342,6 @@ export async function promptAgentVersionSelection(availableAgents, options = {})
|
|
|
3164
2342
|
else {
|
|
3165
2343
|
selectedAgents = checkboxResult;
|
|
3166
2344
|
}
|
|
3167
|
-
// Version selection per agent
|
|
3168
2345
|
for (const agentId of selectedAgents) {
|
|
3169
2346
|
const versions = listInstalledVersions(agentId);
|
|
3170
2347
|
if (versions.length === 0)
|