@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,12 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hook management -- discovery, registration, and syncing of event hooks.
|
|
3
|
-
*
|
|
4
|
-
* Hooks are shell scripts in ~/.agents/hooks/ that fire on agent events
|
|
5
|
-
* (tool calls, session start, etc.). Each hook directory contains a manifest
|
|
6
|
-
* (agents.yaml) declaring events, matchers, and timeout. This module handles
|
|
7
|
-
* parsing those manifests, registering hooks into agent-native settings files,
|
|
8
|
-
* and syncing them across version switches.
|
|
9
|
-
*/
|
|
10
1
|
import * as crypto from 'crypto';
|
|
11
2
|
import * as fs from 'fs';
|
|
12
3
|
import * as os from 'os';
|
|
@@ -22,10 +13,6 @@ import { getHooksDir as getSystemHooksDir, getUserHooksDir, getUserAgentsDir, ge
|
|
|
22
13
|
import { collectSubruleHooksFromState } from '../rules/compose.js';
|
|
23
14
|
import { codexShortKey, resolveCodexHome } from '../codex-home.js';
|
|
24
15
|
function getCentralHooksDir() { return getUserHooksDir(); }
|
|
25
|
-
/**
|
|
26
|
-
* Resolve a hook script's absolute path. Checks user dir first, then enabled
|
|
27
|
-
* extra repos in insertion order, then system dir. Returns null if not found.
|
|
28
|
-
*/
|
|
29
16
|
function resolveContainedHookPath(hooksRoot, script) {
|
|
30
17
|
const resolvedRoot = path.resolve(hooksRoot);
|
|
31
18
|
const candidate = path.join(hooksRoot, script);
|
|
@@ -36,11 +23,6 @@ function resolveContainedHookPath(hooksRoot, script) {
|
|
|
36
23
|
return null;
|
|
37
24
|
return resolved;
|
|
38
25
|
}
|
|
39
|
-
/**
|
|
40
|
-
* Subdirectories under hooks/ that group event families (e.g. session-starts/).
|
|
41
|
-
* Scripts one level down are first-class hooks; their install name remains the
|
|
42
|
-
* file basename so version-home copies stay flat and doctor/diff keep matching.
|
|
43
|
-
*/
|
|
44
26
|
const HOOK_GROUP_SKIP_DIRS = new Set(['node_modules', '.git', '.cache']);
|
|
45
27
|
export function resolveHookScriptPath(script) {
|
|
46
28
|
const extraDirs = getEnabledExtraRepos().map(e => e.dir);
|
|
@@ -49,8 +31,6 @@ export function resolveHookScriptPath(script) {
|
|
|
49
31
|
const resolved = resolveContainedHookPath(hooksRoot, script);
|
|
50
32
|
if (resolved)
|
|
51
33
|
return resolved;
|
|
52
|
-
// Basename fallback: manifests may say `session-starts/foo.sh` or just
|
|
53
|
-
// `foo.sh` while the file lives under a one-level group dir.
|
|
54
34
|
const base = path.basename(script);
|
|
55
35
|
const nested = findHookScriptInGroupDirs(hooksRoot, base);
|
|
56
36
|
if (nested)
|
|
@@ -58,10 +38,6 @@ export function resolveHookScriptPath(script) {
|
|
|
58
38
|
}
|
|
59
39
|
return null;
|
|
60
40
|
}
|
|
61
|
-
/**
|
|
62
|
-
* Find `basename` under hooks/<group>/ (one level). Skips known non-group dirs.
|
|
63
|
-
* Returns the first match in sorted group order for stability.
|
|
64
|
-
*/
|
|
65
41
|
function findHookScriptInGroupDirs(hooksRoot, basename) {
|
|
66
42
|
if (!fs.existsSync(hooksRoot))
|
|
67
43
|
return null;
|
|
@@ -85,8 +61,6 @@ function findHookScriptInGroupDirs(hooksRoot, basename) {
|
|
|
85
61
|
}
|
|
86
62
|
if (!st.isDirectory() || st.isSymbolicLink())
|
|
87
63
|
continue;
|
|
88
|
-
// Only treat dirs that themselves contain scripts as groups (session-starts/),
|
|
89
|
-
// not fixture-only directory bundles (tests/).
|
|
90
64
|
let hasScript = false;
|
|
91
65
|
try {
|
|
92
66
|
for (const child of fs.readdirSync(groupDir)) {
|
|
@@ -110,38 +84,17 @@ function findHookScriptInGroupDirs(hooksRoot, basename) {
|
|
|
110
84
|
}
|
|
111
85
|
return null;
|
|
112
86
|
}
|
|
113
|
-
/**
|
|
114
|
-
* Prefixes used for stale-entry cleanup in agent settings files. A registered
|
|
115
|
-
* hook command is considered "managed" if it lives under any known hooks dir
|
|
116
|
-
* (user, extra repos, or system). Entries from removed extra repos are also
|
|
117
|
-
* garbage-collected because they won't appear in this list any more.
|
|
118
|
-
*/
|
|
119
87
|
function getManagedHookPrefixes() {
|
|
120
88
|
const extraDirs = getEnabledExtraRepos().map(e => e.dir);
|
|
121
89
|
return [
|
|
122
90
|
path.join(getUserAgentsDir(), 'hooks') + path.sep,
|
|
123
91
|
...extraDirs.map(d => path.join(d, 'hooks') + path.sep),
|
|
124
92
|
path.join(getSystemAgentsDir(), 'hooks') + path.sep,
|
|
125
|
-
// Subrule-dir hook scripts register by their absolute source path under a
|
|
126
|
-
// rules `subrules/` tree. Cover those trees so a removed subrule/hook's
|
|
127
|
-
// stale settings entry gets garbage-collected like any other managed hook.
|
|
128
93
|
path.join(getUserRulesDir(), 'subrules') + path.sep,
|
|
129
94
|
...extraDirs.map(d => path.join(d, 'rules', 'subrules') + path.sep),
|
|
130
95
|
path.join(getResolvedRulesDir(), 'subrules') + path.sep,
|
|
131
96
|
];
|
|
132
97
|
}
|
|
133
|
-
/**
|
|
134
|
-
* Convert an absolute path under HOME to a portable ~/... form with forward
|
|
135
|
-
* slashes. Hook commands stored this way work on both macOS and Windows:
|
|
136
|
-
* absolute Windows paths break in bash because backslashes are stripped as
|
|
137
|
-
* escape characters, whereas ~/... paths expand correctly via the ~/.claude
|
|
138
|
-
* symlink/junction on both platforms.
|
|
139
|
-
*
|
|
140
|
-
* `home` and `sep` are injectable so the Windows behavior (backslash sep,
|
|
141
|
-
* drive-letter home) is unit-testable on a POSIX CI host — pass sep='\\' to
|
|
142
|
-
* simulate Windows. With the defaults this is byte-identical to reading
|
|
143
|
-
* os.homedir()/path.sep at the call site.
|
|
144
|
-
*/
|
|
145
98
|
export function toPortableCommand(absPath, home = os.homedir(), sep = path.sep) {
|
|
146
99
|
const normalized = absPath.split(sep).join('/');
|
|
147
100
|
const homeNorm = home.split(sep).join('/');
|
|
@@ -150,123 +103,64 @@ export function toPortableCommand(absPath, home = os.homedir(), sep = path.sep)
|
|
|
150
103
|
}
|
|
151
104
|
return normalized;
|
|
152
105
|
}
|
|
106
|
+
const AGENTS_HOME_HOOK_RE = /\/\.agents\/\.history\/(?:versions\/[^/]+\/[^/]+\/home|accounts\/[^/]+\/[^/]+)\//;
|
|
153
107
|
function isManagedHookCommand(command, prefixes) {
|
|
154
|
-
// Expand ~/... so tilde-form portable commands can be matched against
|
|
155
|
-
// absolute managed prefixes.
|
|
156
108
|
let expanded = command;
|
|
157
109
|
if (command.startsWith('~/')) {
|
|
158
110
|
expanded = path.join(os.homedir(), command.slice(2));
|
|
159
111
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
// Resolve the dir, not the full path — the file may not exist after removal.
|
|
112
|
+
if (AGENTS_HOME_HOOK_RE.test(expanded.split(path.sep).join('/')))
|
|
113
|
+
return true;
|
|
163
114
|
const dir = path.dirname(expanded);
|
|
164
115
|
let resolvedDir = dir;
|
|
165
116
|
try {
|
|
166
117
|
resolvedDir = fs.realpathSync(dir);
|
|
167
118
|
}
|
|
168
|
-
catch {
|
|
119
|
+
catch { }
|
|
169
120
|
const resolved = path.join(resolvedDir, path.basename(expanded));
|
|
170
121
|
for (const prefix of prefixes) {
|
|
171
122
|
if (resolved.startsWith(prefix))
|
|
172
123
|
return true;
|
|
173
|
-
// The command dir above is realpath-resolved, but a raw prefix may still
|
|
174
|
-
// point through a symlink (macOS TMPDIR /var -> /private/var, or a
|
|
175
|
-
// symlinked ~/.agents). Compare against a realpath-normalized prefix too
|
|
176
|
-
// so the two sides match. Strip the trailing sep, resolve the dir, re-add.
|
|
177
124
|
const rawPrefixDir = prefix.endsWith(path.sep) ? prefix.slice(0, -path.sep.length) : prefix;
|
|
178
125
|
let resolvedPrefix = prefix;
|
|
179
126
|
try {
|
|
180
127
|
resolvedPrefix = fs.realpathSync(rawPrefixDir) + path.sep;
|
|
181
128
|
}
|
|
182
|
-
catch {
|
|
129
|
+
catch { }
|
|
183
130
|
if (resolvedPrefix !== prefix && resolved.startsWith(resolvedPrefix))
|
|
184
131
|
return true;
|
|
185
132
|
}
|
|
186
133
|
return false;
|
|
187
134
|
}
|
|
188
|
-
/**
|
|
189
|
-
* Per-version-home command detection. Sync copies each hook script into the
|
|
190
|
-
* active version's home and registers the command by that version-scoped path
|
|
191
|
-
* (`~/.agents/.history/versions/<agent>/<version>/home/…`). Because the path
|
|
192
|
-
* embeds the version number, a later version's sync appends a fresh set whose
|
|
193
|
-
* paths never string-match (and thus never prune) the prior version's entries —
|
|
194
|
-
* so entries for every version installed over time pile up in one settings
|
|
195
|
-
* file, and once a version is removed its entries become dead hooks that error
|
|
196
|
-
* on every tool call. `versionHomeIdentity` extracts the `<agent>/<version>` a
|
|
197
|
-
* command (or home path) belongs to so stale sibling-version entries can be
|
|
198
|
-
* pruned. Returns null for any path outside a per-version home (system hooks,
|
|
199
|
-
* the user's own custom hooks) — those are never a prune target.
|
|
200
|
-
*/
|
|
201
135
|
const VERSION_HOME_SEGMENT_RE = /\.history\/versions\/([^/]+)\/([^/]+)\/home(?:\/|$)/;
|
|
202
136
|
function versionHomeIdentity(commandOrPath) {
|
|
203
137
|
const norm = commandOrPath.split(/[\\/]/).join('/');
|
|
204
138
|
const m = VERSION_HOME_SEGMENT_RE.exec(norm);
|
|
205
139
|
return m ? { agent: m[1], version: m[2] } : null;
|
|
206
140
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
if (!active)
|
|
231
|
-
return [...commands];
|
|
232
|
-
const selected = new Map();
|
|
233
|
-
const passthrough = [];
|
|
234
|
-
for (const command of commands) {
|
|
235
|
-
const identity = versionHomeIdentity(command);
|
|
236
|
-
if (!identity || identity.agent !== active.agent) {
|
|
237
|
-
passthrough.push(command);
|
|
238
|
-
continue;
|
|
239
|
-
}
|
|
240
|
-
const key = `${identity.agent}\0${hookResourceName(command)}`;
|
|
241
|
-
const candidateIsActive = identity.version === active.version;
|
|
242
|
-
const prior = selected.get(key);
|
|
243
|
-
if (!prior || (!prior.active && candidateIsActive)) {
|
|
244
|
-
selected.set(key, { command, active: candidateIsActive });
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
return [...passthrough, ...Array.from(selected.values(), ({ command }) => command)];
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* Collapse a matcher group's hook entries down to the deduplicated command
|
|
251
|
-
* multiset {@link deduplicateVersionHookCommands} returns, preserving order and
|
|
252
|
-
* the concrete entry objects. The deduped list is honored as a per-command
|
|
253
|
-
* budget, NOT a membership set: two identical active-version entries collapse to
|
|
254
|
-
* one because the budget for that command is one. (A membership `Set.has` test
|
|
255
|
-
* would keep both — the bug this replaces.) Passthrough (user / non-version-home)
|
|
256
|
-
* commands keep their original multiplicity, so genuine user hooks are untouched.
|
|
257
|
-
*/
|
|
258
|
-
function collapseVersionHookEntries(entries, activeVersionHome) {
|
|
259
|
-
const budget = new Map();
|
|
260
|
-
for (const command of deduplicateVersionHookCommands(entries.map((e) => e.command), activeVersionHome)) {
|
|
261
|
-
budget.set(command, (budget.get(command) ?? 0) + 1);
|
|
262
|
-
}
|
|
263
|
-
return entries.filter((e) => {
|
|
264
|
-
const remaining = budget.get(e.command) ?? 0;
|
|
265
|
-
if (remaining <= 0)
|
|
266
|
-
return false;
|
|
267
|
-
budget.set(e.command, remaining - 1);
|
|
268
|
-
return true;
|
|
269
|
-
});
|
|
141
|
+
function hookEntryKey(event, matcher, command) {
|
|
142
|
+
return `${event}\0${matcher ?? ''}\0${command}`;
|
|
143
|
+
}
|
|
144
|
+
function pruneManagedHookEntries(hooks, expected, managedPrefixes) {
|
|
145
|
+
for (const [event, groups] of Object.entries(hooks)) {
|
|
146
|
+
if (!Array.isArray(groups))
|
|
147
|
+
continue;
|
|
148
|
+
for (const group of groups) {
|
|
149
|
+
if (!group.hooks)
|
|
150
|
+
continue;
|
|
151
|
+
const seen = new Set();
|
|
152
|
+
group.hooks = group.hooks.filter((h) => {
|
|
153
|
+
if (!isManagedHookCommand(h.command, managedPrefixes))
|
|
154
|
+
return true;
|
|
155
|
+
const key = hookEntryKey(event, group.matcher, h.command);
|
|
156
|
+
if (!expected.has(key) || seen.has(key))
|
|
157
|
+
return false;
|
|
158
|
+
seen.add(key);
|
|
159
|
+
return true;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
hooks[event] = groups.filter((g) => g.hooks && g.hooks.length > 0);
|
|
163
|
+
}
|
|
270
164
|
}
|
|
271
165
|
import { getEffectiveHome, getGlobalDefault, getVersionHomePath, isVersionIsolated, listInstalledVersions, resolveVersion, } from '../installations/versions.js';
|
|
272
166
|
import { generateHookShim, getHookShimPath, isValidHookShimName, parseCacheConfig, removeHookShim } from './cache.js';
|
|
@@ -274,12 +168,6 @@ import { getHookShimsDir } from '../state.js';
|
|
|
274
168
|
function hookContentHash(scriptPath) {
|
|
275
169
|
return crypto.createHash('sha256').update(fs.readFileSync(scriptPath)).digest('hex');
|
|
276
170
|
}
|
|
277
|
-
/**
|
|
278
|
-
* Inspect every installed hooks-capable harness without assuming a native
|
|
279
|
-
* settings format. Same-name copies with one content hash are installation
|
|
280
|
-
* noise; multiple hashes are drift. The active version is always selected as
|
|
281
|
-
* the authoritative copy when it participates in the group.
|
|
282
|
-
*/
|
|
283
171
|
export function inspectDuplicateVersionHooks(cwd = process.cwd()) {
|
|
284
172
|
const byResource = new Map();
|
|
285
173
|
for (const { agent, version } of iterHooksCapableVersions()) {
|
|
@@ -322,24 +210,6 @@ export function inspectDuplicateVersionHooks(cwd = process.cwd()) {
|
|
|
322
210
|
}
|
|
323
211
|
return findings.sort((a, b) => `${a.agent}/${a.name}`.localeCompare(`${b.agent}/${b.name}`));
|
|
324
212
|
}
|
|
325
|
-
/**
|
|
326
|
-
* Resolve the command path to register for a hook.
|
|
327
|
-
*
|
|
328
|
-
* Returns either the raw script path (no `cache:`, `matches:`, or `matcher:`
|
|
329
|
-
* set — a bare lifecycle hook with nothing to gate or time) or the path to a
|
|
330
|
-
* generated wrapper shim. The shim is written as a side effect when `cache:`
|
|
331
|
-
* and/or `matches:` is configured — it enforces the `matches:` gate at fire
|
|
332
|
-
* time and layers the caching/timing machinery when `cache:` is set.
|
|
333
|
-
*
|
|
334
|
-
* A hook that declares only `matcher:` (e.g. git-guard/rm-guard scoped to the
|
|
335
|
-
* `Bash` tool, no `cache:`/`matches:`) also gets a shim now — a pass-through
|
|
336
|
-
* one with no gate and no cache, whose only job is the trailing timing sample
|
|
337
|
-
* (see PASSTHROUGH_TAIL in hooks/cache.ts). Before this, a matcher-only hook
|
|
338
|
-
* took the raw-path branch and fired completely uninstrumented: `agents perf
|
|
339
|
-
* hooks` showed zero samples for it no matter how often it ran. The agent-
|
|
340
|
-
* native settings file gets the same shape either way — just a different
|
|
341
|
-
* command path.
|
|
342
|
-
*/
|
|
343
213
|
function resolveHookCommand(name, hookDef, resolveScript) {
|
|
344
214
|
const scriptPath = resolveScript(hookDef.script);
|
|
345
215
|
if (!scriptPath)
|
|
@@ -351,18 +221,9 @@ function resolveHookCommand(name, hookDef, resolveScript) {
|
|
|
351
221
|
const hasMatches = matches != null && Object.keys(matches).length > 0;
|
|
352
222
|
const hasMatcher = !!hookDef.matcher;
|
|
353
223
|
if (!cache && !hasMatches && !hasMatcher) {
|
|
354
|
-
// Nothing to gate, cache, or time: make sure a previously generated shim
|
|
355
|
-
// from an earlier cache:/matches:/matcher config is gone so the JSONL
|
|
356
|
-
// doesn't keep claiming hits.
|
|
357
224
|
removeHookShim(name);
|
|
358
225
|
return toPortableCommand(scriptPath);
|
|
359
226
|
}
|
|
360
|
-
// A shim is generated when the hook opts into caching, declares `matches:`
|
|
361
|
-
// predicates, or declares a `matcher:` (even alone — see the doc comment
|
|
362
|
-
// above). The shim enforces the `matches:` gate at fire time (skipping the
|
|
363
|
-
// script when predicates don't hold) and, when `cache:` is set, layers the
|
|
364
|
-
// cache/timing machinery on top; with neither, it is a pure pass-through
|
|
365
|
-
// timing wrapper.
|
|
366
227
|
return toPortableCommand(generateHookShim({
|
|
367
228
|
name,
|
|
368
229
|
scriptPath,
|
|
@@ -371,23 +232,10 @@ function resolveHookCommand(name, hookDef, resolveScript) {
|
|
|
371
232
|
failClosed: hookDef.events.includes('PreToolUse'),
|
|
372
233
|
}));
|
|
373
234
|
}
|
|
374
|
-
/**
|
|
375
|
-
* Extensions that are NEVER hooks — docs, configuration, plain data. A file
|
|
376
|
-
* in hooks/ with one of these extensions is auxiliary content (e.g., the
|
|
377
|
-
* `promptcuts.yaml` data file read directly by the expand-promptcuts
|
|
378
|
-
* script, or the `README.md` that documents the hooks directory). They
|
|
379
|
-
* sometimes carry an exec bit by accident (older sync runs chmod 0o755'd
|
|
380
|
-
* everything) but they are not scripts.
|
|
381
|
-
*/
|
|
382
235
|
const NON_SCRIPT_EXTENSIONS = new Set([
|
|
383
236
|
'.md', '.markdown', '.rst', '.txt',
|
|
384
237
|
'.yaml', '.yml', '.json', '.toml', '.ini', '.conf',
|
|
385
238
|
]);
|
|
386
|
-
// Documentation siblings of a hook (e.g. `git-guard.md` next to `git-guard.sh`)
|
|
387
|
-
// are human-readable docs the hook never reads at runtime — NOT a data sidecar.
|
|
388
|
-
// Treating them as the hook's `dataFile` made the installer's correct omission
|
|
389
|
-
// of docs look like perpetual drift in `agents doctor` that no sync could fix.
|
|
390
|
-
// Structured siblings (.yaml/.json/.toml/...) remain valid data files.
|
|
391
239
|
const DOC_EXTENSIONS = new Set(['.md', '.markdown', '.rst']);
|
|
392
240
|
const SCRIPT_EXTENSIONS = new Set([
|
|
393
241
|
'.sh',
|
|
@@ -407,18 +255,13 @@ const SCRIPT_EXTENSIONS = new Set([
|
|
|
407
255
|
function isExecutable(mode) {
|
|
408
256
|
return (mode & 0o111) !== 0;
|
|
409
257
|
}
|
|
410
|
-
/**
|
|
411
|
-
* Ensure a script file carries an exec bit. Subrule-dir hook scripts are
|
|
412
|
-
* registered by their source path (not copied), so they must be executable in
|
|
413
|
-
* place. Best-effort: a chmod failure (read-only fs, foreign owner) is ignored.
|
|
414
|
-
*/
|
|
415
258
|
function ensureExecutable(scriptPath) {
|
|
416
259
|
try {
|
|
417
260
|
const mode = fs.statSync(scriptPath).mode;
|
|
418
261
|
if (!isExecutable(mode))
|
|
419
262
|
fs.chmodSync(scriptPath, mode | 0o755);
|
|
420
263
|
}
|
|
421
|
-
catch {
|
|
264
|
+
catch { }
|
|
422
265
|
}
|
|
423
266
|
function getHooksDir(agentId) {
|
|
424
267
|
const agent = AGENTS[agentId];
|
|
@@ -457,12 +300,6 @@ function removeHookFiles(dir, name) {
|
|
|
457
300
|
}
|
|
458
301
|
}
|
|
459
302
|
}
|
|
460
|
-
/**
|
|
461
|
-
* Collect hook-adjacent files from a hooks root: top-level files plus files in
|
|
462
|
-
* one-level group subdirs (e.g. hooks/session-starts/*.sh). Group dirs exist
|
|
463
|
-
* only for layout; the install/list name stays the file basename so sync and
|
|
464
|
-
* doctor keep a flat version-home model.
|
|
465
|
-
*/
|
|
466
303
|
function collectHookFilesFromRoot(dir) {
|
|
467
304
|
const files = [];
|
|
468
305
|
const pushFile = (fullPath, fileName, mode) => {
|
|
@@ -502,8 +339,6 @@ function collectHookFilesFromRoot(dir) {
|
|
|
502
339
|
}
|
|
503
340
|
if (!stat.isDirectory() || HOOK_GROUP_SKIP_DIRS.has(file))
|
|
504
341
|
continue;
|
|
505
|
-
// One-level event-group layout: hooks/<group>/<script>. Only dirs that
|
|
506
|
-
// contain top-level scripts are groups; fixture-only dirs (tests/) are not.
|
|
507
342
|
let nested;
|
|
508
343
|
try {
|
|
509
344
|
nested = fs.readdirSync(fullPath);
|
|
@@ -537,23 +372,14 @@ function collectHookFilesFromRoot(dir) {
|
|
|
537
372
|
}
|
|
538
373
|
return files;
|
|
539
374
|
}
|
|
540
|
-
/**
|
|
541
|
-
* List hook entries in a single directory, grouping script + data files by
|
|
542
|
-
* basename. Also discovers scripts in one-level group subdirs
|
|
543
|
-
* (hooks/session-starts/). Exported so doctor-diff can reuse the same grouping
|
|
544
|
-
* the sync path applies; without this, doctor would double-count `foo.sh` and
|
|
545
|
-
* `foo.yaml`. On basename collision, the top-level file wins over a nested one.
|
|
546
|
-
*/
|
|
547
375
|
export function listHookEntriesFromDir(dir) {
|
|
548
376
|
if (!fs.existsSync(dir)) {
|
|
549
377
|
return [];
|
|
550
378
|
}
|
|
551
379
|
const files = collectHookFilesFromRoot(dir);
|
|
552
|
-
// Prefer top-level over nested when basenames collide (stable install name).
|
|
553
380
|
const byBase = new Map();
|
|
554
381
|
for (const file of files) {
|
|
555
382
|
const list = byBase.get(file.base) || [];
|
|
556
|
-
// Top-level files sit directly under dir; nested have an extra path segment.
|
|
557
383
|
const isTop = path.dirname(file.fullPath) === path.resolve(dir);
|
|
558
384
|
if (isTop)
|
|
559
385
|
list.unshift(file);
|
|
@@ -563,9 +389,6 @@ export function listHookEntriesFromDir(dir) {
|
|
|
563
389
|
}
|
|
564
390
|
const entries = [];
|
|
565
391
|
for (const [base, groupAll] of byBase) {
|
|
566
|
-
// Keep only files that share the winning script's directory so a nested
|
|
567
|
-
// data sidecar next to a nested script still pairs, and a top-level
|
|
568
|
-
// winner is not paired with a nested yaml of the same basename.
|
|
569
392
|
const winnerScript = groupAll.find((f) => SCRIPT_EXTENSIONS.has(f.ext.toLowerCase())) ||
|
|
570
393
|
groupAll.find((f) => f.isExec && !NON_SCRIPT_EXTENSIONS.has(f.ext.toLowerCase()));
|
|
571
394
|
if (!winnerScript)
|
|
@@ -573,13 +396,6 @@ export function listHookEntriesFromDir(dir) {
|
|
|
573
396
|
const groupDir = path.dirname(winnerScript.fullPath);
|
|
574
397
|
const group = groupAll.filter((f) => path.dirname(f.fullPath) === groupDir);
|
|
575
398
|
group.sort((a, b) => a.name.localeCompare(b.name));
|
|
576
|
-
// A group is a hook only if it has an actual script: a script extension,
|
|
577
|
-
// OR an executable bit on a file whose extension is not a known data /
|
|
578
|
-
// docs type. Files like `README.md` (docs) or `promptcuts.yaml` (data
|
|
579
|
-
// the expand-promptcuts hook reads directly) sit alongside hooks but
|
|
580
|
-
// are NOT hooks themselves and must not surface in the hooks list
|
|
581
|
-
// anywhere — doctor, sync, view, or otherwise. Older sync runs may have
|
|
582
|
-
// chmod 0o755'd these files; an exec bit alone is not enough.
|
|
583
399
|
const script = group.find((f) => SCRIPT_EXTENSIONS.has(f.ext.toLowerCase())) ||
|
|
584
400
|
group.find((f) => f.isExec && !NON_SCRIPT_EXTENSIONS.has(f.ext.toLowerCase()));
|
|
585
401
|
if (!script)
|
|
@@ -613,19 +429,9 @@ function copyHook(entry, targetDir) {
|
|
|
613
429
|
fs.copyFileSync(entry.dataFile, dataTarget);
|
|
614
430
|
}
|
|
615
431
|
}
|
|
616
|
-
/**
|
|
617
|
-
* Normalize content for comparison (trim, normalize line endings).
|
|
618
|
-
*/
|
|
619
432
|
function normalizeContent(content) {
|
|
620
433
|
return content.replace(/\r\n/g, '\n').trim();
|
|
621
434
|
}
|
|
622
|
-
/**
|
|
623
|
-
* Hooks dir for an agent under an arbitrary home (version home or effective
|
|
624
|
-
* home). An agent whose `hooksDir` is configured absolute under `$HOME` (grok,
|
|
625
|
-
* kimi) must be translated to config-dir-relative first — a raw `path.join`
|
|
626
|
-
* would embed the absolute path as a relative segment and produce a hybrid
|
|
627
|
-
* path that never exists (RUSH-2237).
|
|
628
|
-
*/
|
|
629
435
|
export function getHooksDirInHome(agentId, home) {
|
|
630
436
|
const config = AGENTS[agentId];
|
|
631
437
|
const hooksDir = path.isAbsolute(config.hooksDir)
|
|
@@ -652,7 +458,6 @@ export function listInstalledHooksWithScope(agentId, cwd = process.cwd(), option
|
|
|
652
458
|
});
|
|
653
459
|
seen.add(hook.name);
|
|
654
460
|
};
|
|
655
|
-
// Project-scoped hooks (project .agents overrides agent-specific dirs)
|
|
656
461
|
const projectDirs = getProjectHooksDirs(agentId, cwd);
|
|
657
462
|
for (const dir of projectDirs) {
|
|
658
463
|
const projectHooks = listHookEntriesFromDir(dir);
|
|
@@ -660,7 +465,6 @@ export function listInstalledHooksWithScope(agentId, cwd = process.cwd(), option
|
|
|
660
465
|
addHook(hook, 'project', agentId);
|
|
661
466
|
}
|
|
662
467
|
}
|
|
663
|
-
// User-scoped hooks (version-aware when home is provided)
|
|
664
468
|
const home = options?.home || getEffectiveHome(agentId);
|
|
665
469
|
const userDir = getHooksDirInHome(agentId, home);
|
|
666
470
|
const userHooks = listHookEntriesFromDir(userDir);
|
|
@@ -696,33 +500,15 @@ export async function installHooks(source, agents, options = {}) {
|
|
|
696
500
|
}
|
|
697
501
|
return { installed, errors };
|
|
698
502
|
}
|
|
699
|
-
/**
|
|
700
|
-
* Path to the hooks dir of a specific version home (not the active one).
|
|
701
|
-
*/
|
|
702
503
|
export function getVersionHooksDir(agent, version) {
|
|
703
504
|
return getHooksDirInHome(agent, getVersionHomePath(agent, version));
|
|
704
505
|
}
|
|
705
|
-
/**
|
|
706
|
-
* List hook entries in a specific version home.
|
|
707
|
-
*/
|
|
708
506
|
export function listHooksInVersionHome(agent, version) {
|
|
709
507
|
return listHookEntriesFromDir(getVersionHooksDir(agent, version));
|
|
710
508
|
}
|
|
711
|
-
// ─── wiring inspection ────────────────────────────────────────────────────────
|
|
712
|
-
/**
|
|
713
|
-
* Native hook-config families understood by this read-only inspector. Claude,
|
|
714
|
-
* Droid, and Muse share settings.json; Grok uses the same grouped event shape
|
|
715
|
-
* in hooks/hooks.json; Kimi stores one hook per [[hooks]] config.toml table.
|
|
716
|
-
* Other harnesses report unsupported rather than risk a false verdict.
|
|
717
|
-
*/
|
|
718
509
|
const SETTINGS_JSON_HOOK_FAMILY = ['claude', 'droid', 'muse'];
|
|
719
510
|
const HOOKS_JSON_HOOK_FAMILY = ['grok'];
|
|
720
511
|
const TOML_ARRAY_HOOK_FAMILY = ['kimi'];
|
|
721
|
-
/**
|
|
722
|
-
* Check the filesystem properties a shell hook needs without invoking it. A
|
|
723
|
-
* dangling symlink is deliberately distinguished from an absent file because
|
|
724
|
-
* the repair/remediation is the same but the diagnostic is materially clearer.
|
|
725
|
-
*/
|
|
726
512
|
function shellQuoteForHookShim(value) {
|
|
727
513
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
728
514
|
}
|
|
@@ -736,7 +522,6 @@ function hookRuntimeProblem(artifact, platform = process.platform) {
|
|
|
736
522
|
const code = err.code;
|
|
737
523
|
if (code === 'ENOENT')
|
|
738
524
|
return 'missing';
|
|
739
|
-
// Stable: errno code only — never absolute path text (fleet/menu aggregation).
|
|
740
525
|
return `cannot inspect (${code || 'error'})`;
|
|
741
526
|
}
|
|
742
527
|
let target;
|
|
@@ -751,18 +536,12 @@ function hookRuntimeProblem(artifact, platform = process.platform) {
|
|
|
751
536
|
}
|
|
752
537
|
if (!target.isFile())
|
|
753
538
|
return 'not a regular file';
|
|
754
|
-
// Generation always writes non-empty content; an empty placeholder is broken.
|
|
755
539
|
if (target.size === 0)
|
|
756
540
|
return 'broken (empty)';
|
|
757
|
-
// Windows does not use a POSIX executable bit; requiring it there would
|
|
758
|
-
// continuously rewrite healthy .sh files on Windows hosts.
|
|
759
541
|
if (platform !== 'win32' && (target.mode & 0o111) === 0)
|
|
760
542
|
return 'not executable';
|
|
761
543
|
try {
|
|
762
544
|
const body = fs.readFileSync(shimPath, 'utf-8');
|
|
763
|
-
// The global shim must name the selected live version-home script. A
|
|
764
|
-
// wrapper can remain executable while its SOURCE points to an older or
|
|
765
|
-
// deleted version; detect that without running either script.
|
|
766
545
|
if (!body.includes(`SOURCE=${shellQuoteForHookShim(artifact.scriptPath)}`)) {
|
|
767
546
|
return 'source mismatch';
|
|
768
547
|
}
|
|
@@ -773,12 +552,6 @@ function hookRuntimeProblem(artifact, platform = process.platform) {
|
|
|
773
552
|
}
|
|
774
553
|
return null;
|
|
775
554
|
}
|
|
776
|
-
/**
|
|
777
|
-
* Gather managed generated-shim expectations for one installed version. The
|
|
778
|
-
* script must resolve inside that version home (or be an existing absolute
|
|
779
|
-
* subrule), matching the registrar's selection rules. This function never
|
|
780
|
-
* creates a shim or runs a hook.
|
|
781
|
-
*/
|
|
782
555
|
function managedHookRuntimeArtifactsForVersion(agent, version) {
|
|
783
556
|
if (!AGENTS[agent].supportsHooks)
|
|
784
557
|
return [];
|
|
@@ -811,12 +584,7 @@ function managedHookRuntimeArtifactsForVersion(agent, version) {
|
|
|
811
584
|
}
|
|
812
585
|
return artifacts;
|
|
813
586
|
}
|
|
814
|
-
/** Inspect managed generated hook wrappers without executing user hook code. */
|
|
815
587
|
export function inspectBrokenManagedHookRuntimeArtifacts(filter, platform = process.platform) {
|
|
816
|
-
// Generated destinations are shared across every harness. Always select the
|
|
817
|
-
// owner from the global population first; an agent-scoped doctor call may
|
|
818
|
-
// restrict which shim names are relevant, but must not change the expected
|
|
819
|
-
// SOURCE for a shared wrapper.
|
|
820
588
|
const versions = iterHooksCapableVersions();
|
|
821
589
|
if (filter?.agent &&
|
|
822
590
|
filter.version &&
|
|
@@ -845,12 +613,6 @@ export function inspectBrokenManagedHookRuntimeArtifacts(filter, platform = proc
|
|
|
845
613
|
return broken.sort((a, b) => a.shimPath.localeCompare(b.shimPath) ||
|
|
846
614
|
`${a.agent}@${a.version}/${a.name}`.localeCompare(`${b.agent}@${b.version}/${b.name}`));
|
|
847
615
|
}
|
|
848
|
-
/**
|
|
849
|
-
* Prefer the agent's global default when it appears in the candidate set;
|
|
850
|
-
* otherwise the newest non-isolated version. Shared shim paths embed a single
|
|
851
|
-
* SOURCE script — picking the wrong version permanently points every harness
|
|
852
|
-
* at a stale or dead path.
|
|
853
|
-
*/
|
|
854
616
|
function pickCanonicalHookRuntimeArtifact(candidates) {
|
|
855
617
|
if (candidates.length === 1)
|
|
856
618
|
return candidates[0];
|
|
@@ -863,8 +625,6 @@ function pickCanonicalHookRuntimeArtifact(candidates) {
|
|
|
863
625
|
if (active)
|
|
864
626
|
return active;
|
|
865
627
|
}
|
|
866
|
-
// listInstalledVersions is the canonical semver ordering. Scan backward
|
|
867
|
-
// rather than inventing another version comparator at this call site.
|
|
868
628
|
for (const agent of agents) {
|
|
869
629
|
for (const version of [...listInstalledVersions(agent)].reverse()) {
|
|
870
630
|
const newest = candidates.find((c) => c.agent === agent && c.version === version);
|
|
@@ -874,14 +634,7 @@ function pickCanonicalHookRuntimeArtifact(candidates) {
|
|
|
874
634
|
}
|
|
875
635
|
return candidates[0];
|
|
876
636
|
}
|
|
877
|
-
/**
|
|
878
|
-
* One repair target per unique shim path. Generated shims are global, so both
|
|
879
|
-
* unattended and explicit repair leave isolated/private version homes out.
|
|
880
|
-
*/
|
|
881
637
|
function selectCanonicalHookRuntimeArtifacts(artifacts) {
|
|
882
|
-
// No hook runtime exists for a version that does not support hooks. Isolated
|
|
883
|
-
// versions never own a global generated shim, even when a caller names one:
|
|
884
|
-
// selecting it would repoint every harness at a private version home.
|
|
885
638
|
const pool = eligibleHookRuntimeArtifacts(artifacts);
|
|
886
639
|
const byPath = new Map();
|
|
887
640
|
for (const artifact of pool) {
|
|
@@ -895,33 +648,16 @@ function selectCanonicalHookRuntimeArtifacts(artifacts) {
|
|
|
895
648
|
}
|
|
896
649
|
return selected;
|
|
897
650
|
}
|
|
898
|
-
/** Versions that may own — and therefore diagnose — a shared generated shim. */
|
|
899
651
|
function eligibleHookRuntimeArtifacts(artifacts) {
|
|
900
652
|
return artifacts.filter((artifact) => supports(artifact.agent, 'hooks', artifact.version).ok &&
|
|
901
653
|
!isVersionIsolated(artifact.agent, artifact.version));
|
|
902
654
|
}
|
|
903
|
-
/**
|
|
904
|
-
* Stable failure text: errno code + detector reason only.
|
|
905
|
-
* Never include absolute paths or randomized atomic-temp basenames — those
|
|
906
|
-
* break cross-device / menu-bar aggregation of identical failures. The hook
|
|
907
|
-
* name is attached by the caller (`hook shim <name>: …`).
|
|
908
|
-
*/
|
|
909
655
|
function stableHookRuntimeRepairFailure(before, err) {
|
|
910
656
|
const code = err?.code;
|
|
911
657
|
return `repair failed [${code || 'UNKNOWN'}]: ${before}`;
|
|
912
658
|
}
|
|
913
|
-
/**
|
|
914
|
-
* Regenerate one known-broken wrapper and prove the result is usable. Callers
|
|
915
|
-
* provide a snapshot from inspectBrokenManagedHookRuntimeArtifacts; this never
|
|
916
|
-
* loops or retries and returns a stable error for the current pass.
|
|
917
|
-
*
|
|
918
|
-
* Generation is delegated to generateHookShim (idempotent — preserves mtime when
|
|
919
|
-
* content already matches). This path never calls registerHooksToSettings,
|
|
920
|
-
* installHooks, or any sync routine.
|
|
921
|
-
*/
|
|
922
659
|
function repairManagedHookRuntimeArtifact(artifact, platform = process.platform) {
|
|
923
660
|
const before = hookRuntimeProblem(artifact, platform);
|
|
924
|
-
// Already healthy (e.g. race with another pass) — no-op, no needsAttention.
|
|
925
661
|
if (!before)
|
|
926
662
|
return { repaired: false };
|
|
927
663
|
try {
|
|
@@ -935,24 +671,11 @@ function repairManagedHookRuntimeArtifact(artifact, platform = process.platform)
|
|
|
935
671
|
catch (err) {
|
|
936
672
|
return { repaired: false, reason: stableHookRuntimeRepairFailure(before, err) };
|
|
937
673
|
}
|
|
938
|
-
// Post-repair reinspection — prove the artifact is usable without executing it.
|
|
939
674
|
const after = hookRuntimeProblem(artifact, platform);
|
|
940
675
|
return after
|
|
941
676
|
? { repaired: false, reason: `${before}; repair did not produce a usable shim (${after})` }
|
|
942
677
|
: { repaired: true };
|
|
943
678
|
}
|
|
944
|
-
/**
|
|
945
|
-
* Bounded repair of all broken agents-managed generated hook shims.
|
|
946
|
-
*
|
|
947
|
-
* - Inspect first (read-only, no hook execution).
|
|
948
|
-
* - One generation attempt per unique shim path per call (no retry, no timer).
|
|
949
|
-
* - Canonical owner per shared path: global default, else newest non-isolated.
|
|
950
|
-
* - Post-repair reinspection; unresolved findings become stable needsAttention.
|
|
951
|
-
* - Never recurses into resource sync / registerHooksToSettings.
|
|
952
|
-
*
|
|
953
|
-
* This is the shared routine used by the self-heal `hook-runtime` check and
|
|
954
|
-
* exported for the doctor track.
|
|
955
|
-
*/
|
|
956
679
|
export function repairManagedHookRuntimeArtifacts(opts = {}) {
|
|
957
680
|
const platform = opts.platform ?? process.platform;
|
|
958
681
|
const dryRun = opts.dryRun ?? false;
|
|
@@ -965,8 +688,6 @@ export function repairManagedHookRuntimeArtifacts(opts = {}) {
|
|
|
965
688
|
for (const artifact of targets) {
|
|
966
689
|
attemptedPaths.push(artifact.shimPath);
|
|
967
690
|
if (dryRun) {
|
|
968
|
-
// Would-fix: same shape as a real fix so doctor dry-run and daemon previews
|
|
969
|
-
// stay consistent with other HealChecks.
|
|
970
691
|
attempts.push({
|
|
971
692
|
name: artifact.name,
|
|
972
693
|
path: artifact.shimPath,
|
|
@@ -990,31 +711,12 @@ export function repairManagedHookRuntimeArtifacts(opts = {}) {
|
|
|
990
711
|
fixed.push(`hook shim ${artifact.name}`);
|
|
991
712
|
}
|
|
992
713
|
else if (result.reason) {
|
|
993
|
-
// Stable needs-attention wording for aggregation across devices / menubar.
|
|
994
|
-
// No reason means already-healthy no-op (race) — do not emit attention noise.
|
|
995
714
|
needsAttention.push(`hook shim ${artifact.name}: ${result.reason}`);
|
|
996
715
|
}
|
|
997
716
|
}
|
|
998
717
|
return { brokenBefore, attemptedPaths, attempts, fixed, needsAttention };
|
|
999
718
|
}
|
|
1000
|
-
/**
|
|
1001
|
-
* Verify that every hook the manifest says should be wired is actually
|
|
1002
|
-
* referenced in that version's harness-native config, not merely present as a
|
|
1003
|
-
* file on disk.
|
|
1004
|
-
*
|
|
1005
|
-
* `agents doctor` compares hook FILES against source (see diffHooks in
|
|
1006
|
-
* doctor-diff.ts) but never checks the wiring, so a hook whose script is
|
|
1007
|
-
* byte-identical to source yet missing from settings.json's PreToolUse/Stop/…
|
|
1008
|
-
* array reads as "ok" while it never fires. This closes that blind spot.
|
|
1009
|
-
*
|
|
1010
|
-
* Read-only by construction: it mirrors registerHooksForClaude's command
|
|
1011
|
-
* resolution WITHOUT the shim-generation / chmod side effects that
|
|
1012
|
-
* resolveHookCommand performs, so it never mutates the version home.
|
|
1013
|
-
*/
|
|
1014
719
|
export function checkVersionHookWiring(agent, version) {
|
|
1015
|
-
// Runtime verification does not rely on parsing a native settings format.
|
|
1016
|
-
// That lets doctor catch a deleted generated shim for every hooks-capable
|
|
1017
|
-
// harness, including families whose wiring schema is intentionally unsupported.
|
|
1018
720
|
const runtimeBroken = inspectBrokenManagedHookRuntimeArtifacts({ agent, version })
|
|
1019
721
|
.map(({ name, shimPath, reason }) => ({ name, path: shimPath, reason }));
|
|
1020
722
|
if (!AGENTS[agent].supportsHooks ||
|
|
@@ -1030,21 +732,11 @@ export function checkVersionHookWiring(agent, version) {
|
|
|
1030
732
|
? path.join(versionHome, '.kimi-code', 'config.toml')
|
|
1031
733
|
: path.join(versionHome, agentConfigDirName(agent), 'settings.json');
|
|
1032
734
|
const localHooksDir = getVersionHooksDir(agent, version);
|
|
1033
|
-
// Resolve ONLY to a script that was actually synced for THIS agent+version: the
|
|
1034
|
-
// copy in the version home hooks dir, or an absolute subrule-dir path (those are
|
|
1035
|
-
// registered in place, never copied). Deliberately NO central-source fallback —
|
|
1036
|
-
// sync wires `selectHookManifest(parseHookManifest(), hooksToSync)` where
|
|
1037
|
-
// hooksToSync is the per-agent selected set (versions.ts), so a hook the manifest
|
|
1038
|
-
// declares but that was never synced into THIS version home (e.g. a claude-scoped
|
|
1039
|
-
// hook viewed for droid) must not be expected here. A missing-but-declared hook
|
|
1040
|
-
// is a FILE gap that diffHooks reports as `missing`, not a wiring gap.
|
|
1041
|
-
// No ensureExecutable — that chmods, and this path must not touch disk.
|
|
1042
735
|
const resolveScript = (script) => {
|
|
1043
736
|
if (path.isAbsolute(script) && fs.existsSync(script))
|
|
1044
737
|
return script;
|
|
1045
738
|
return resolveContainedHookPath(localHooksDir, script);
|
|
1046
739
|
};
|
|
1047
|
-
// Read-only mirror of resolveHookCommand — same command string, no shim write.
|
|
1048
740
|
const expectedCommand = (name, hookDef) => {
|
|
1049
741
|
const scriptPath = resolveScript(hookDef.script);
|
|
1050
742
|
if (!scriptPath)
|
|
@@ -1064,7 +756,7 @@ export function checkVersionHookWiring(agent, version) {
|
|
|
1064
756
|
continue;
|
|
1065
757
|
const command = expectedCommand(name, hookDef);
|
|
1066
758
|
if (!command)
|
|
1067
|
-
continue;
|
|
759
|
+
continue;
|
|
1068
760
|
for (const event of hookDef.events) {
|
|
1069
761
|
if (HOOKS_JSON_HOOK_FAMILY.includes(agent)) {
|
|
1070
762
|
const matcher = GROK_MATCHER_EVENTS.has(event)
|
|
@@ -1106,9 +798,6 @@ export function checkVersionHookWiring(agent, version) {
|
|
|
1106
798
|
runtimeBroken,
|
|
1107
799
|
};
|
|
1108
800
|
}
|
|
1109
|
-
// Command strings actually referenced, keyed by (event, matcher) — a hook wired
|
|
1110
|
-
// under the WRONG matcher group must NOT read as wired, so scope by matcher and
|
|
1111
|
-
// not just by event.
|
|
1112
801
|
const wiredByGroup = new Map();
|
|
1113
802
|
const groupKey = (event, matcher) => `${event}\n${matcher}`;
|
|
1114
803
|
if (TOML_ARRAY_HOOK_FAMILY.includes(agent)) {
|
|
@@ -1155,9 +844,6 @@ export function checkVersionHookWiring(agent, version) {
|
|
|
1155
844
|
const wired = expected.filter(isWired);
|
|
1156
845
|
return { supported: true, settingsPath, expected: expected.length, unwired, wired, runtimeBroken };
|
|
1157
846
|
}
|
|
1158
|
-
/**
|
|
1159
|
-
* Check if a hook installed in a specific version matches central content.
|
|
1160
|
-
*/
|
|
1161
847
|
function versionHookMatches(agent, version, hookName) {
|
|
1162
848
|
const central = listHookEntriesFromDir(getCentralHooksDir()).find((e) => e.name === hookName);
|
|
1163
849
|
if (!central)
|
|
@@ -1184,9 +870,6 @@ function versionHookMatches(agent, version, hookName) {
|
|
|
1184
870
|
return false;
|
|
1185
871
|
}
|
|
1186
872
|
}
|
|
1187
|
-
/**
|
|
1188
|
-
* Compare a version home's hooks against central. Returns the reconciliation diff.
|
|
1189
|
-
*/
|
|
1190
873
|
export function diffVersionHooks(agent, version) {
|
|
1191
874
|
const central = new Set(listHookEntriesFromDir(getCentralHooksDir()).map((e) => e.name));
|
|
1192
875
|
const installed = new Set(listHooksInVersionHome(agent, version).map((e) => e.name));
|
|
@@ -1211,10 +894,6 @@ export function diffVersionHooks(agent, version) {
|
|
|
1211
894
|
}
|
|
1212
895
|
return { agent, version, toAdd: toAdd.sort(), toUpdate: toUpdate.sort(), matched, orphans: orphans.sort() };
|
|
1213
896
|
}
|
|
1214
|
-
/**
|
|
1215
|
-
* Remove a single hook (script + data file) from a specific version home.
|
|
1216
|
-
* Soft-deletes to ~/.agents/.trash/hooks/.
|
|
1217
|
-
*/
|
|
1218
897
|
export function removeHookFromVersion(agent, version, hookName) {
|
|
1219
898
|
try {
|
|
1220
899
|
const hooksDir = getVersionHooksDir(agent, version);
|
|
@@ -1245,10 +924,6 @@ export function removeHookFromVersion(agent, version, hookName) {
|
|
|
1245
924
|
}
|
|
1246
925
|
return { success: true };
|
|
1247
926
|
}
|
|
1248
|
-
/**
|
|
1249
|
-
* Iterate all (agent, version) pairs that support hooks and are installed,
|
|
1250
|
-
* optionally scoped to a single agent/version.
|
|
1251
|
-
*/
|
|
1252
927
|
export function iterHooksCapableVersions(filter) {
|
|
1253
928
|
const pairs = [];
|
|
1254
929
|
const hookAgents = capableAgents('hooks');
|
|
@@ -1290,23 +965,18 @@ export async function removeHook(name, agents) {
|
|
|
1290
965
|
}
|
|
1291
966
|
return { removed, errors };
|
|
1292
967
|
}
|
|
1293
|
-
/**
|
|
1294
|
-
* Get detailed info about a hook from central storage.
|
|
1295
|
-
*/
|
|
1296
968
|
export function getHookInfo(name) {
|
|
1297
969
|
const centralDir = getCentralHooksDir();
|
|
1298
970
|
const hookPath = path.join(centralDir, name);
|
|
1299
971
|
if (!fs.existsSync(hookPath)) {
|
|
1300
972
|
return null;
|
|
1301
973
|
}
|
|
1302
|
-
// Read hook content - it could be a file or directory
|
|
1303
974
|
let content = '';
|
|
1304
975
|
const stat = fs.statSync(hookPath);
|
|
1305
976
|
if (stat.isFile()) {
|
|
1306
977
|
content = fs.readFileSync(hookPath, 'utf-8');
|
|
1307
978
|
}
|
|
1308
979
|
else if (stat.isDirectory()) {
|
|
1309
|
-
// For directory hooks, list the files
|
|
1310
980
|
const files = fs.readdirSync(hookPath);
|
|
1311
981
|
content = `Directory hook containing:\n${files.map((f) => ` - ${f}`).join('\n')}`;
|
|
1312
982
|
}
|
|
@@ -1320,10 +990,6 @@ export function discoverHooksFromRepo(repoPath) {
|
|
|
1320
990
|
const hooksDir = path.join(repoPath, 'hooks');
|
|
1321
991
|
return listHookEntriesFromDir(hooksDir).map((h) => h.name);
|
|
1322
992
|
}
|
|
1323
|
-
/**
|
|
1324
|
-
* Install hooks to central ~/.agents/hooks/ directory.
|
|
1325
|
-
* Shims will symlink this to per-agent directories for synced agents.
|
|
1326
|
-
*/
|
|
1327
993
|
export async function installHooksCentrally(source) {
|
|
1328
994
|
const installed = [];
|
|
1329
995
|
const errors = [];
|
|
@@ -1331,7 +997,6 @@ export async function installHooksCentrally(source) {
|
|
|
1331
997
|
if (!fs.existsSync(centralDir)) {
|
|
1332
998
|
fs.mkdirSync(centralDir, { recursive: true });
|
|
1333
999
|
}
|
|
1334
|
-
// Collect all hooks from shared directory
|
|
1335
1000
|
const sharedDir = path.join(source, 'hooks');
|
|
1336
1001
|
const sharedHooks = listHookEntriesFromDir(sharedDir);
|
|
1337
1002
|
for (const entry of sharedHooks) {
|
|
@@ -1345,10 +1010,6 @@ export async function installHooksCentrally(source) {
|
|
|
1345
1010
|
}
|
|
1346
1011
|
return { installed, errors };
|
|
1347
1012
|
}
|
|
1348
|
-
/**
|
|
1349
|
-
* List hooks from user (~/.agents/hooks/) and system (~/.agents/.system/hooks/) dirs.
|
|
1350
|
-
* User dir takes priority; deduplication preserves first occurrence.
|
|
1351
|
-
*/
|
|
1352
1013
|
export function listCentralHooks() {
|
|
1353
1014
|
const seen = new Set();
|
|
1354
1015
|
const results = [];
|
|
@@ -1363,21 +1024,6 @@ export function listCentralHooks() {
|
|
|
1363
1024
|
return results;
|
|
1364
1025
|
}
|
|
1365
1026
|
const MAX_HOOK_DURATION_SECONDS = 24 * 60 * 60;
|
|
1366
|
-
/**
|
|
1367
|
-
* Normalize a hook `timeout` from agents.yaml into a whole number of seconds.
|
|
1368
|
-
*
|
|
1369
|
-
* A bare number stays seconds (`timeout: 30` → 30) for backward compatibility.
|
|
1370
|
-
* A Go-style duration string is parsed into seconds: `5s`, `2m`, `1h30m`,
|
|
1371
|
-
* `90s`, `1h`. Suffixed durations longer than 24 hours are rejected as likely
|
|
1372
|
-
* typos, while bare seconds stay uncapped for backward compatibility. This
|
|
1373
|
-
* intentionally does NOT reuse {@link parseTimeout} from routines.ts — that one
|
|
1374
|
-
* returns milliseconds, has no seconds (`s`) unit, and floors at one minute,
|
|
1375
|
-
* none of which fit hook timeouts (typically 5–600s).
|
|
1376
|
-
*
|
|
1377
|
-
* Returns the seconds value, or `null` when the input is not a positive number,
|
|
1378
|
-
* is not parseable, or is a suffixed duration longer than 24 hours — the caller
|
|
1379
|
-
* decides how to surface that.
|
|
1380
|
-
*/
|
|
1381
1027
|
export function normalizeHookTimeoutSeconds(value) {
|
|
1382
1028
|
if (typeof value === 'number') {
|
|
1383
1029
|
return Number.isFinite(value) && value > 0 ? value : null;
|
|
@@ -1386,7 +1032,6 @@ export function normalizeHookTimeoutSeconds(value) {
|
|
|
1386
1032
|
const s = value.trim();
|
|
1387
1033
|
if (s === '')
|
|
1388
1034
|
return null;
|
|
1389
|
-
// A bare integer string means seconds, matching the bare-number form.
|
|
1390
1035
|
if (/^\d+$/.test(s)) {
|
|
1391
1036
|
const n = Number(s);
|
|
1392
1037
|
return n > 0 ? n : null;
|
|
@@ -1404,31 +1049,16 @@ export function normalizeHookTimeoutSeconds(value) {
|
|
|
1404
1049
|
}
|
|
1405
1050
|
return null;
|
|
1406
1051
|
}
|
|
1407
|
-
/**
|
|
1408
|
-
* Parse hook manifests. Reads system hooks from ~/.agents/.system/hooks.yaml
|
|
1409
|
-
* (npm-shipped defaults) and user hooks from the `hooks:` section of
|
|
1410
|
-
* ~/.agents/agents.yaml. Merges with user-wins-on-key-collision precedence.
|
|
1411
|
-
* A user entry with `enabled: false` disables the system-shipped hook of
|
|
1412
|
-
* the same name without forking the system file.
|
|
1413
|
-
*
|
|
1414
|
-
* Hooks marked `enabled: false` are dropped from the returned map. A hook
|
|
1415
|
-
* `timeout` written as a duration string (`5s`, `2m`) is normalized to a
|
|
1416
|
-
* seconds number here, so every downstream serializer keeps reading a number.
|
|
1417
|
-
*/
|
|
1418
1052
|
export function parseHookManifest(opts = {}) {
|
|
1419
1053
|
const warn = opts.warn !== false;
|
|
1420
1054
|
const merged = {};
|
|
1421
1055
|
const systemHooks = {};
|
|
1422
|
-
// Lowest-precedence layer: hooks declared inside active subrule directories.
|
|
1423
|
-
// Seeded first so any same-key entry from system/user agents.yaml wins.
|
|
1424
|
-
// Gated so a malformed hooks.yaml never breaks rule sync.
|
|
1425
1056
|
try {
|
|
1426
1057
|
const subruleHooks = collectSubruleHooksFromState();
|
|
1427
1058
|
for (const [name, def] of Object.entries(subruleHooks))
|
|
1428
1059
|
merged[name] = def;
|
|
1429
1060
|
}
|
|
1430
|
-
catch {
|
|
1431
|
-
// System layer: hooks: section of agents.yaml (npm-shipped, separate repo).
|
|
1061
|
+
catch { }
|
|
1432
1062
|
const systemPath = path.join(getSystemAgentsDir(), 'agents.yaml');
|
|
1433
1063
|
if (fs.existsSync(systemPath)) {
|
|
1434
1064
|
try {
|
|
@@ -1439,14 +1069,8 @@ export function parseHookManifest(opts = {}) {
|
|
|
1439
1069
|
merged[name] = def;
|
|
1440
1070
|
}
|
|
1441
1071
|
}
|
|
1442
|
-
catch {
|
|
1072
|
+
catch { }
|
|
1443
1073
|
}
|
|
1444
|
-
// Extra-repo layer: hooks: section of each enabled extra repo's agents.yaml.
|
|
1445
|
-
// Sits above system but below user, mirroring resolveHookScriptPath's
|
|
1446
|
-
// first-found order (user > extra > system). Without this layer the script
|
|
1447
|
-
// path of an extra-repo hook resolves but its events never register (#602).
|
|
1448
|
-
// Earlier extras win over later ones, so iterate in reverse: the last write
|
|
1449
|
-
// for a given name comes from the earliest-registered repo.
|
|
1450
1074
|
for (const { dir } of [...getEnabledExtraRepos()].reverse()) {
|
|
1451
1075
|
const extraMetaPath = path.join(dir, 'agents.yaml');
|
|
1452
1076
|
if (!fs.existsSync(extraMetaPath))
|
|
@@ -1457,9 +1081,8 @@ export function parseHookManifest(opts = {}) {
|
|
|
1457
1081
|
for (const [name, def] of Object.entries(meta.hooks))
|
|
1458
1082
|
merged[name] = def;
|
|
1459
1083
|
}
|
|
1460
|
-
catch {
|
|
1084
|
+
catch { }
|
|
1461
1085
|
}
|
|
1462
|
-
// User layer: hooks: section of agents.yaml.
|
|
1463
1086
|
const userMetaPath = path.join(getUserAgentsDir(), 'agents.yaml');
|
|
1464
1087
|
if (fs.existsSync(userMetaPath)) {
|
|
1465
1088
|
try {
|
|
@@ -1473,17 +1096,12 @@ export function parseHookManifest(opts = {}) {
|
|
|
1473
1096
|
merged[name] = def;
|
|
1474
1097
|
}
|
|
1475
1098
|
}
|
|
1476
|
-
catch {
|
|
1099
|
+
catch { }
|
|
1477
1100
|
}
|
|
1478
|
-
// Strip disabled hooks so they never reach the registrar.
|
|
1479
1101
|
for (const [name, def] of Object.entries(merged)) {
|
|
1480
1102
|
if (def.enabled === false)
|
|
1481
1103
|
delete merged[name];
|
|
1482
1104
|
}
|
|
1483
|
-
// Normalize each surviving hook's timeout to a seconds number, so the raw
|
|
1484
|
-
// agents.yaml can express it as a duration string (`5s`, `2m`) while every
|
|
1485
|
-
// downstream serializer keeps consuming a plain number. An unparseable value
|
|
1486
|
-
// is dropped with a warning rather than silently coerced to a wrong duration.
|
|
1487
1105
|
for (const [name, def] of Object.entries(merged)) {
|
|
1488
1106
|
const raw = def.timeout;
|
|
1489
1107
|
if (raw === undefined)
|
|
@@ -1506,37 +1124,10 @@ export function selectHookManifest(manifest, selected) {
|
|
|
1506
1124
|
const selectedHooks = new Set(selected);
|
|
1507
1125
|
return Object.fromEntries(Object.entries(manifest).filter(([name, hook]) => selectedHooks.has(name) || selectedHooks.has(path.basename(hook.script))));
|
|
1508
1126
|
}
|
|
1509
|
-
/**
|
|
1510
|
-
* Hook files present in a version home but absent from every configured
|
|
1511
|
-
* SOURCE — genuine orphans left behind by a removed/renamed source hook.
|
|
1512
|
-
*
|
|
1513
|
-
* The definition is deliberately source-based, not manifest-based (PHNX-2693).
|
|
1514
|
-
* Sync copies EVERY source hook file into a version home — registered hooks AND
|
|
1515
|
-
* the helper / test / benchmark scripts that sit alongside them — but only the
|
|
1516
|
-
* registered ones appear in `parseHookManifest`. Diffing installed names against
|
|
1517
|
-
* the manifest therefore flagged every source-present-but-unregistered file
|
|
1518
|
-
* (e.g. `permission-handler`, `verify-work-state`, `*_test`, `benchmark_*`) as
|
|
1519
|
-
* an orphan, so `agents prune cleanup` offered to trash ~1000 in-use files. An
|
|
1520
|
-
* installed hook is only truly orphaned when NO configured source still carries
|
|
1521
|
-
* a file of that name — which is exactly what the `prune`/`doctor` help already
|
|
1522
|
-
* promised ("present in a version home but missing from every configured
|
|
1523
|
-
* source").
|
|
1524
|
-
*
|
|
1525
|
-
* Pure on purpose (no disk reads) so it is trivially testable; callers pass the
|
|
1526
|
-
* installed hook names and the source hook script paths.
|
|
1527
|
-
*/
|
|
1528
1127
|
export function unmanagedHookNames(installedHookNames, sourceHookScripts) {
|
|
1529
1128
|
const inSource = new Set(sourceHookScripts.map((s) => path.basename(s).replace(/\.[^.]+$/, '')));
|
|
1530
1129
|
return installedHookNames.filter((name) => !inSource.has(name)).sort();
|
|
1531
1130
|
}
|
|
1532
|
-
/**
|
|
1533
|
-
* Every hook script path across the resolved SOURCE roots — user
|
|
1534
|
-
* (`~/.agents/hooks`), system (`~/.agents/.system/hooks`), and each enabled
|
|
1535
|
-
* extra repo's `hooks/` — grouped the same way sync materializes them
|
|
1536
|
-
* ({@link listHookEntriesFromDir}, which also descends one-level event-group
|
|
1537
|
-
* dirs). This is the set an installed hook must be absent from to count as an
|
|
1538
|
-
* orphan.
|
|
1539
|
-
*/
|
|
1540
1131
|
function listResolvedSourceHookScripts() {
|
|
1541
1132
|
const roots = [
|
|
1542
1133
|
getUserHooksDir(),
|
|
@@ -1550,22 +1141,13 @@ function listResolvedSourceHookScripts() {
|
|
|
1550
1141
|
}
|
|
1551
1142
|
return scripts;
|
|
1552
1143
|
}
|
|
1553
|
-
/**
|
|
1554
|
-
* The orphan hooks (see {@link unmanagedHookNames}) sitting in one version home:
|
|
1555
|
-
* installed hook files whose name matches no file in any configured source root.
|
|
1556
|
-
*/
|
|
1557
1144
|
export function listUnmanagedHooksInVersionHome(agent, version) {
|
|
1558
1145
|
if (!AGENTS[agent].supportsHooks)
|
|
1559
1146
|
return [];
|
|
1560
1147
|
const installed = listHooksInVersionHome(agent, version).map((e) => e.name);
|
|
1561
1148
|
return unmanagedHookNames(installed, listResolvedSourceHookScripts());
|
|
1562
1149
|
}
|
|
1563
|
-
// Codex events that support a matcher field (matches tool name or session type).
|
|
1564
|
-
// UserPromptSubmit and Stop never include a matcher.
|
|
1565
1150
|
const CODEX_MATCHER_EVENTS = new Set(['PreToolUse', 'PostToolUse', 'SessionStart']);
|
|
1566
|
-
// Maps PascalCase hook event names (as written in hooks.json) to the
|
|
1567
|
-
// snake_case labels Codex uses in its persisted [hooks.state] keys.
|
|
1568
|
-
// Mirrors hook_event_key_label() in codex-rs/hooks/src/lib.rs.
|
|
1569
1151
|
const CODEX_EVENT_KEY_LABELS = {
|
|
1570
1152
|
PreToolUse: 'pre_tool_use',
|
|
1571
1153
|
PermissionRequest: 'permission_request',
|
|
@@ -1578,9 +1160,6 @@ const CODEX_EVENT_KEY_LABELS = {
|
|
|
1578
1160
|
SubagentStop: 'subagent_stop',
|
|
1579
1161
|
Stop: 'stop',
|
|
1580
1162
|
};
|
|
1581
|
-
// Recursively sort object keys alphabetically at every level, mirroring
|
|
1582
|
-
// canonical_json() in codex-rs/config/src/fingerprint.rs. Codex hashes the
|
|
1583
|
-
// canonical JSON form so trust survives key-order differences.
|
|
1584
1163
|
function canonicalizeForHash(value) {
|
|
1585
1164
|
if (Array.isArray(value)) {
|
|
1586
1165
|
return value.map(canonicalizeForHash);
|
|
@@ -1594,22 +1173,6 @@ function canonicalizeForHash(value) {
|
|
|
1594
1173
|
}
|
|
1595
1174
|
return value;
|
|
1596
1175
|
}
|
|
1597
|
-
/**
|
|
1598
|
-
* Compute the trust hash Codex expects for a single command hook handler, so
|
|
1599
|
-
* agents-cli can pre-trust the hooks it registers. Without a matching
|
|
1600
|
-
* trusted_hash in [hooks.state], Codex classifies the hook Untrusted and
|
|
1601
|
-
* silently drops it in non-interactive (`codex exec`) mode where there is no
|
|
1602
|
-
* TUI prompt to approve it.
|
|
1603
|
-
*
|
|
1604
|
-
* Mirrors command_hook_hash() in codex-rs/hooks/src/engine/discovery.rs +
|
|
1605
|
-
* version_for_toml() in codex-rs/config/src/fingerprint.rs:
|
|
1606
|
-
* sha256( canonicalJson( NormalizedHookIdentity ) ) prefixed with "sha256:".
|
|
1607
|
-
*
|
|
1608
|
-
* The identity passes through TOML on the Codex side, which drops None fields
|
|
1609
|
-
* (commandWindows, statusMessage, and matcher when absent). `async` is always
|
|
1610
|
-
* false (async hooks are not yet supported) and is always present. `timeout`
|
|
1611
|
-
* is normalized to >= 1 (Codex: unwrap_or(600).max(1)).
|
|
1612
|
-
*/
|
|
1613
1176
|
export function computeCodexHookTrustHash(eventKeyLabel, command, timeout, matcher) {
|
|
1614
1177
|
const handler = {
|
|
1615
1178
|
type: 'command',
|
|
@@ -1628,22 +1191,6 @@ export function computeCodexHookTrustHash(eventKeyLabel, command, timeout, match
|
|
|
1628
1191
|
const hex = crypto.createHash('sha256').update(JSON.stringify(canonical), 'utf-8').digest('hex');
|
|
1629
1192
|
return `sha256:${hex}`;
|
|
1630
1193
|
}
|
|
1631
|
-
/**
|
|
1632
|
-
* Register hooks as lifecycle events in an agent's config.
|
|
1633
|
-
* Reads hooks.yaml manifest, merges into the agent's config file(s).
|
|
1634
|
-
* Only manages hooks whose command paths are under ~/.agents/hooks/ or
|
|
1635
|
-
* ~/.agents/.system/hooks/. Does not remove user-added hooks.
|
|
1636
|
-
*
|
|
1637
|
-
* @param agentsDirOverride - When provided, treats this single dir as the
|
|
1638
|
-
* only managed hook root. Used by tests to inject a temp path. In normal
|
|
1639
|
-
* operation, both user and system roots are consulted with user precedence.
|
|
1640
|
-
*/
|
|
1641
|
-
/**
|
|
1642
|
-
* Delete shim files for hooks that no longer exist in the manifest.
|
|
1643
|
-
* managedPrefixes already GCs the settings.json entries pointing at orphaned
|
|
1644
|
-
* shims, but the .sh files on disk would otherwise persist forever. Called
|
|
1645
|
-
* once per registerHooksToSettings invocation — cheap (a single readdir).
|
|
1646
|
-
*/
|
|
1647
1194
|
function sweepOrphanShims(manifest) {
|
|
1648
1195
|
const shimsDir = getHookShimsDir();
|
|
1649
1196
|
if (!fs.existsSync(shimsDir))
|
|
@@ -1658,7 +1205,7 @@ function sweepOrphanShims(manifest) {
|
|
|
1658
1205
|
try {
|
|
1659
1206
|
fs.unlinkSync(path.join(shimsDir, file));
|
|
1660
1207
|
}
|
|
1661
|
-
catch {
|
|
1208
|
+
catch { }
|
|
1662
1209
|
}
|
|
1663
1210
|
}
|
|
1664
1211
|
export function registerHooksToSettings(agentId, versionHome, hookManifest, agentsDirOverride, options) {
|
|
@@ -1681,14 +1228,10 @@ export function registerHooksToSettings(agentId, versionHome, hookManifest, agen
|
|
|
1681
1228
|
if (!options?.skipGlobalShimSweep)
|
|
1682
1229
|
sweepOrphanShims(manifest);
|
|
1683
1230
|
const overrideRoots = agentsDirOverride ? [agentsDirOverride] : null;
|
|
1684
|
-
// Scripts are copied into the version home during sync — prefer that stable
|
|
1685
|
-
// local path so registered commands don't break when source dirs change.
|
|
1686
1231
|
const localHooksDir = !overrideRoots
|
|
1687
1232
|
? getHooksDirInHome(agentId, versionHome)
|
|
1688
1233
|
: null;
|
|
1689
1234
|
const resolveScript = (script) => {
|
|
1690
|
-
// Subrule-dir hooks declare an already-absolute script path. Use it
|
|
1691
|
-
// directly (made executable) — these are not copied into the version home.
|
|
1692
1235
|
if (path.isAbsolute(script) && fs.existsSync(script)) {
|
|
1693
1236
|
ensureExecutable(script);
|
|
1694
1237
|
return script;
|
|
@@ -1697,8 +1240,6 @@ export function registerHooksToSettings(agentId, versionHome, hookManifest, agen
|
|
|
1697
1240
|
return resolveContainedHookPath(path.join(overrideRoots[0], 'hooks'), script);
|
|
1698
1241
|
}
|
|
1699
1242
|
if (localHooksDir) {
|
|
1700
|
-
// Prefer the exact relative path, then a flat basename copy (sync flattens
|
|
1701
|
-
// group-dir scripts into the version-home hooks/ root).
|
|
1702
1243
|
const local = resolveContainedHookPath(localHooksDir, script) ||
|
|
1703
1244
|
resolveContainedHookPath(localHooksDir, path.basename(script));
|
|
1704
1245
|
if (local)
|
|
@@ -1709,36 +1250,20 @@ export function registerHooksToSettings(agentId, versionHome, hookManifest, agen
|
|
|
1709
1250
|
const managedPrefixes = overrideRoots
|
|
1710
1251
|
? [
|
|
1711
1252
|
path.join(overrideRoots[0], 'hooks') + path.sep,
|
|
1712
|
-
// The shim dir is one global location regardless of which hooks
|
|
1713
|
-
// source (agentsDirOverride vs the normal user/system dirs) resolved
|
|
1714
|
-
// the underlying script, so it belongs in every managedPrefixes
|
|
1715
|
-
// shape — omitting it here left a shim path unrecognized as managed
|
|
1716
|
-
// under the override branch, so a hook's matcher/event change never
|
|
1717
|
-
// GC'd its stale shim-path entry (only reachable via a caller that
|
|
1718
|
-
// passes agentsDirOverride; no production call site does today).
|
|
1719
1253
|
getHookShimsDir() + path.sep,
|
|
1720
1254
|
]
|
|
1721
1255
|
: [
|
|
1722
1256
|
...getManagedHookPrefixes(),
|
|
1723
1257
|
...(localHooksDir ? [localHooksDir + path.sep] : []),
|
|
1724
|
-
// Generated cache/timing shims live here; needs GC coverage so that a
|
|
1725
|
-
// hook whose `cache:` field is removed gets its stale shim path purged
|
|
1726
|
-
// from the agent's settings file (see resolveHookCommand).
|
|
1727
1258
|
getHookShimsDir() + path.sep,
|
|
1728
1259
|
];
|
|
1729
1260
|
if (agentId === 'claude') {
|
|
1730
1261
|
return registerHooksForClaude(versionHome, manifest, resolveScript, managedPrefixes);
|
|
1731
1262
|
}
|
|
1732
1263
|
if (agentId === 'droid') {
|
|
1733
|
-
// Droid's settings.json hooks schema is identical to Claude's (top-level
|
|
1734
|
-
// `hooks` object → event → matcher-group array), so reuse the Claude
|
|
1735
|
-
// registrar targeting `.factory/settings.json` (agentConfigDirName('droid')).
|
|
1736
1264
|
return registerHooksForClaude(versionHome, manifest, resolveScript, managedPrefixes, agentConfigDirName('droid'));
|
|
1737
1265
|
}
|
|
1738
1266
|
if (agentId === 'muse') {
|
|
1739
|
-
// Muse Code: Claude-compatible hooks block in ~/.config/muse/settings.json
|
|
1740
|
-
// (events SessionStart / PreToolUse / …, matcher groups, command hooks).
|
|
1741
|
-
// settings.json MUST carry schema_version: 1 or Muse refuses to start.
|
|
1742
1267
|
return registerHooksForClaude(versionHome, manifest, resolveScript, managedPrefixes, agentConfigDirName('muse'), { schemaVersion: 1 });
|
|
1743
1268
|
}
|
|
1744
1269
|
if (agentId === 'codex') {
|
|
@@ -1770,19 +1295,6 @@ export function registerHooksToSettings(agentId, versionHome, hookManifest, agen
|
|
|
1770
1295
|
}
|
|
1771
1296
|
return { registered: [], errors: [] };
|
|
1772
1297
|
}
|
|
1773
|
-
/**
|
|
1774
|
-
* The concrete config file(s) `registerHooksToSettings` writes for `agentId` in
|
|
1775
|
-
* `home` — the settings/registrar leaves, NOT the per-hook script copies. A
|
|
1776
|
-
* caller materializing into an UNTRUSTED home (the portable-agent materializer)
|
|
1777
|
-
* uses this to verify none of those leaves is a preplanted symlink before the
|
|
1778
|
-
* registrar follows it and overwrites a file outside the home.
|
|
1779
|
-
*
|
|
1780
|
-
* This MUST mirror the `registerHooksToSettings` dispatch above — each arm's
|
|
1781
|
-
* write target is reproduced here, so a new registrar branch adds its leaf here
|
|
1782
|
-
* too. It intentionally returns only the primary settings/registrar file(s); the
|
|
1783
|
-
* per-event/script files a registrar also writes live under the hooks dir the
|
|
1784
|
-
* caller already guards. An agent with no hooks registrar returns `[]`.
|
|
1785
|
-
*/
|
|
1786
1298
|
export function hookRegistrationTargets(agentId, home) {
|
|
1787
1299
|
switch (agentId) {
|
|
1788
1300
|
case 'claude':
|
|
@@ -1824,15 +1336,6 @@ const OPENCODE_LIFECYCLE_EVENT_MAP = {
|
|
|
1824
1336
|
OnError: ['session.error'],
|
|
1825
1337
|
Notification: ['permission.asked'],
|
|
1826
1338
|
};
|
|
1827
|
-
/**
|
|
1828
|
-
* Compile canonical hooks.yaml entries into a local OpenCode plugin.
|
|
1829
|
-
*
|
|
1830
|
-
* OpenCode has no declarative shell-hook config block. It auto-loads direct
|
|
1831
|
-
* TS/JS modules from ~/.config/opencode/plugins/, and supplies Bun's `$` shell
|
|
1832
|
-
* primitive to each plugin. The generated module subscribes to native plugin
|
|
1833
|
-
* events, sends the event payload to the managed hook script as JSON on stdin,
|
|
1834
|
-
* and surfaces a non-zero script exit as a plugin error.
|
|
1835
|
-
*/
|
|
1836
1339
|
function registerHooksForOpenCode(versionHome, manifest, resolveScript) {
|
|
1837
1340
|
const registered = [];
|
|
1838
1341
|
const errors = [];
|
|
@@ -1870,8 +1373,6 @@ function registerHooksForOpenCode(versionHome, manifest, resolveScript) {
|
|
|
1870
1373
|
}
|
|
1871
1374
|
const serializedDirect = JSON.stringify(Object.fromEntries(direct), null, 2);
|
|
1872
1375
|
const serializedLifecycle = JSON.stringify(Object.fromEntries(lifecycle), null, 2);
|
|
1873
|
-
// Same disposable perf spool the bash shims (hooks/cache.ts) append to — see
|
|
1874
|
-
// the timedOut branch below for why OpenCode needs its own writer.
|
|
1875
1376
|
const perfSpoolPath = path.join(getPerfDir(), 'spool.jsonl');
|
|
1876
1377
|
const pluginSource = `// Generated by agents-cli. Re-run agents sync to update.
|
|
1877
1378
|
import fs from "node:fs"
|
|
@@ -1988,18 +1489,8 @@ export const AgentsCliHooks = async ({ $ }) => ({
|
|
|
1988
1489
|
}
|
|
1989
1490
|
return { registered, errors };
|
|
1990
1491
|
}
|
|
1991
|
-
/**
|
|
1992
|
-
* Antigravity (agy) event names differ from agents-cli manifest names. The
|
|
1993
|
-
* mapping below is the documented agy schema. PostToolUse has no exact
|
|
1994
|
-
* agy equivalent — agy fires `after_model_call` after the model finishes a
|
|
1995
|
-
* turn (which includes any tool calls in that turn), so it's the closest
|
|
1996
|
-
* lifecycle phase but not a 1:1 match. Manifest events not in this map are
|
|
1997
|
-
* skipped silently (the manifest may declare events for other agents).
|
|
1998
|
-
*/
|
|
1999
1492
|
const ANTIGRAVITY_EVENT_MAP = {
|
|
2000
1493
|
PreToolUse: 'before_tool_call',
|
|
2001
|
-
// Imperfect mapping: agy has no per-tool post-event. after_model_call
|
|
2002
|
-
// fires once at the end of the turn, after all tool calls completed.
|
|
2003
1494
|
PostToolUse: 'after_model_call',
|
|
2004
1495
|
Stop: 'on_loop_stop',
|
|
2005
1496
|
OnError: 'on_error',
|
|
@@ -2021,7 +1512,6 @@ function registerHooksForClaude(versionHome, manifest, resolveScript, managedPre
|
|
|
2021
1512
|
return { registered, errors };
|
|
2022
1513
|
}
|
|
2023
1514
|
}
|
|
2024
|
-
// Muse (and any future agent that pins a settings schema) requires this key.
|
|
2025
1515
|
if (options?.schemaVersion !== undefined && config.schema_version === undefined) {
|
|
2026
1516
|
config.schema_version = options.schemaVersion;
|
|
2027
1517
|
}
|
|
@@ -2029,41 +1519,17 @@ function registerHooksForClaude(versionHome, manifest, resolveScript, managedPre
|
|
|
2029
1519
|
config.hooks = {};
|
|
2030
1520
|
}
|
|
2031
1521
|
const hooks = config.hooks;
|
|
2032
|
-
|
|
2033
|
-
// Used to garbage-collect stale entries left behind after hook renames
|
|
2034
|
-
// or after a `cache:` field is added/removed (raw script vs shim path).
|
|
2035
|
-
const currentManifestPaths = new Set();
|
|
1522
|
+
const expected = new Set();
|
|
2036
1523
|
for (const [hookName, hookDef] of Object.entries(manifest)) {
|
|
2037
1524
|
if (!hookDef.events || hookDef.events.length === 0)
|
|
2038
1525
|
continue;
|
|
2039
1526
|
const resolved = resolveHookCommand(hookName, hookDef, resolveScript);
|
|
2040
|
-
if (resolved)
|
|
2041
|
-
currentManifestPaths.add(resolved);
|
|
2042
|
-
}
|
|
2043
|
-
// Identity of the version home being synced. Used to prune entries that point
|
|
2044
|
-
// at a DIFFERENT version home of the same agent (see isStaleSiblingVersionCommand).
|
|
2045
|
-
const currentVh = versionHomeIdentity(versionHome);
|
|
2046
|
-
// Remove stale entries: any hook command under a managed root that isn't in
|
|
2047
|
-
// the current manifest is a leftover from a renamed/deleted hook script; any
|
|
2048
|
-
// command pointing at a sibling version's home is a leftover from that
|
|
2049
|
-
// version's sync (its version-scoped path never matches the current set).
|
|
2050
|
-
for (const eventEntries of Object.values(hooks)) {
|
|
2051
|
-
if (!Array.isArray(eventEntries))
|
|
2052
|
-
continue;
|
|
2053
|
-
for (const group of eventEntries) {
|
|
2054
|
-
if (!group.hooks)
|
|
2055
|
-
continue;
|
|
2056
|
-
const managed = group.hooks.filter((h) => (!isManagedHookCommand(h.command, managedPrefixes) || currentManifestPaths.has(h.command)) &&
|
|
2057
|
-
!isStaleSiblingVersionCommand(h.command, currentVh));
|
|
2058
|
-
group.hooks = collapseVersionHookEntries(managed, versionHome);
|
|
2059
|
-
}
|
|
2060
|
-
}
|
|
2061
|
-
// Remove empty matcher groups left after cleanup
|
|
2062
|
-
for (const [event, eventEntries] of Object.entries(hooks)) {
|
|
2063
|
-
if (!Array.isArray(eventEntries))
|
|
1527
|
+
if (!resolved)
|
|
2064
1528
|
continue;
|
|
2065
|
-
|
|
1529
|
+
for (const event of hookDef.events)
|
|
1530
|
+
expected.add(hookEntryKey(event, hookDef.matcher, resolved));
|
|
2066
1531
|
}
|
|
1532
|
+
pruneManagedHookEntries(hooks, expected, managedPrefixes);
|
|
2067
1533
|
for (const [name, hookDef] of Object.entries(manifest)) {
|
|
2068
1534
|
if (!hookDef.events || hookDef.events.length === 0)
|
|
2069
1535
|
continue;
|
|
@@ -2110,19 +1576,6 @@ function registerHooksForClaude(versionHome, manifest, resolveScript, managedPre
|
|
|
2110
1576
|
}
|
|
2111
1577
|
return { registered, errors };
|
|
2112
1578
|
}
|
|
2113
|
-
/**
|
|
2114
|
-
* Prune every Claude-family (`settings.json`) hook entry whose command lives
|
|
2115
|
-
* under a removed version's home
|
|
2116
|
-
* (`~/.agents/.history/versions/<agent>/<removedVersion>/home/…`).
|
|
2117
|
-
*
|
|
2118
|
-
* `agents remove <agent>@<version>` soft-deletes the version's files but leaves
|
|
2119
|
-
* the hook entries other version homes registered against it — dead hooks that
|
|
2120
|
-
* error on every tool call ("No such file or directory") until the next sync.
|
|
2121
|
-
* This clears them from a remaining version's settings immediately. Only the
|
|
2122
|
-
* removed version's entries are touched; the current version's entries, system
|
|
2123
|
-
* hooks, and the user's own custom hooks are left intact. Returns the number of
|
|
2124
|
-
* entries removed.
|
|
2125
|
-
*/
|
|
2126
1579
|
export function pruneVersionHomeHookEntriesFromSettings(settingsPath, agent, removedVersion) {
|
|
2127
1580
|
if (!fs.existsSync(settingsPath))
|
|
2128
1581
|
return 0;
|
|
@@ -2153,7 +1606,6 @@ export function pruneVersionHomeHookEntriesFromSettings(settingsPath, agent, rem
|
|
|
2153
1606
|
}
|
|
2154
1607
|
if (removed === 0)
|
|
2155
1608
|
return 0;
|
|
2156
|
-
// Drop matcher groups left empty by the prune.
|
|
2157
1609
|
for (const [event, eventEntries] of Object.entries(hooks)) {
|
|
2158
1610
|
if (!Array.isArray(eventEntries))
|
|
2159
1611
|
continue;
|
|
@@ -2163,8 +1615,6 @@ export function pruneVersionHomeHookEntriesFromSettings(settingsPath, agent, rem
|
|
|
2163
1615
|
fs.writeFileSync(settingsPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
2164
1616
|
}
|
|
2165
1617
|
catch {
|
|
2166
|
-
// Best-effort cleanup: a write failure leaves the dead entry to be pruned
|
|
2167
|
-
// on the next sync (see isStaleSiblingVersionCommand).
|
|
2168
1618
|
return 0;
|
|
2169
1619
|
}
|
|
2170
1620
|
return removed;
|
|
@@ -2180,16 +1630,9 @@ function trustCodexHooks(hooksPath) {
|
|
|
2180
1630
|
if (!tomlConfig.features || typeof tomlConfig.features !== 'object') {
|
|
2181
1631
|
tomlConfig.features = {};
|
|
2182
1632
|
}
|
|
2183
|
-
// Codex 0.116+ feature flag is `hooks` (the legacy `codex_hooks` name is
|
|
2184
|
-
// an unrecognized key that triggers a deprecation error and is ignored).
|
|
2185
1633
|
const features = tomlConfig.features;
|
|
2186
1634
|
delete features.codex_hooks;
|
|
2187
1635
|
features.hooks = true;
|
|
2188
|
-
// Pre-trust hooks. The [hooks.state] key is keyed by the hooks.json path
|
|
2189
|
-
// exactly as Codex resolves it (the absolute CODEX_HOME path), the
|
|
2190
|
-
// snake_case event label, and the per-event group/handler indices — which
|
|
2191
|
-
// must match Codex's parse order, so we iterate the just-written
|
|
2192
|
-
// hooksFile structure in array order.
|
|
2193
1636
|
if (!tomlConfig.hooks || typeof tomlConfig.hooks !== 'object') {
|
|
2194
1637
|
tomlConfig.hooks = {};
|
|
2195
1638
|
}
|
|
@@ -2210,8 +1653,6 @@ function trustCodexHooks(hooksPath) {
|
|
|
2210
1653
|
return;
|
|
2211
1654
|
const keys = hookPaths.map((file) => `${file}:${eventKeyLabel}:${groupIdx}:${handlerIdx}`);
|
|
2212
1655
|
const trustedHash = computeCodexHookTrustHash(eventKeyLabel, handler.command, handler.timeout, group.matcher);
|
|
2213
|
-
// Preserve a user's explicit `enabled = false` for this exact hook;
|
|
2214
|
-
// only (re)write the trust hash.
|
|
2215
1656
|
const entry = { trusted_hash: trustedHash };
|
|
2216
1657
|
if (keys.some((key) => existingState[key]?.enabled === false)) {
|
|
2217
1658
|
entry.enabled = false;
|
|
@@ -2221,8 +1662,6 @@ function trustCodexHooks(hooksPath) {
|
|
|
2221
1662
|
});
|
|
2222
1663
|
});
|
|
2223
1664
|
}
|
|
2224
|
-
// Carry forward trust state for any hooks we did not (re)register this
|
|
2225
|
-
// pass — e.g. user-added hooks under a different command path.
|
|
2226
1665
|
for (const [key, entry] of Object.entries(existingState)) {
|
|
2227
1666
|
if (!(key in hookState)) {
|
|
2228
1667
|
hookState[key] = entry;
|
|
@@ -2236,7 +1675,6 @@ function registerHooksForCodex(versionHome, manifest, resolveScript, managedPref
|
|
|
2236
1675
|
const errors = [];
|
|
2237
1676
|
const configDir = path.join(versionHome, '.codex');
|
|
2238
1677
|
const hooksPath = path.join(configDir, 'hooks.json');
|
|
2239
|
-
// Read existing hooks.json — must have top-level "hooks" wrapper key
|
|
2240
1678
|
let hooksFile = { hooks: {} };
|
|
2241
1679
|
if (fs.existsSync(hooksPath)) {
|
|
2242
1680
|
try {
|
|
@@ -2254,33 +1692,19 @@ function registerHooksForCodex(versionHome, manifest, resolveScript, managedPref
|
|
|
2254
1692
|
return { registered, errors };
|
|
2255
1693
|
}
|
|
2256
1694
|
}
|
|
2257
|
-
|
|
2258
|
-
// Uses resolveHookCommand so cached hooks resolve to their shim path.
|
|
2259
|
-
const currentManifestPaths = new Set();
|
|
1695
|
+
const expected = new Set();
|
|
2260
1696
|
for (const [hookName, hookDef] of Object.entries(manifest)) {
|
|
2261
1697
|
if (!hookDef.events || hookDef.events.length === 0)
|
|
2262
1698
|
continue;
|
|
2263
1699
|
const resolved = resolveHookCommand(hookName, hookDef, resolveScript);
|
|
2264
|
-
if (resolved)
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
// paths; without this, old version entries keep firing after upgrades.
|
|
2270
|
-
const currentVh = versionHomeIdentity(versionHome);
|
|
2271
|
-
// Remove stale entries from all event groups
|
|
2272
|
-
for (const eventGroups of Object.values(hooksFile.hooks)) {
|
|
2273
|
-
for (const group of eventGroups) {
|
|
2274
|
-
if (!group.hooks)
|
|
2275
|
-
continue;
|
|
2276
|
-
const managed = group.hooks.filter((h) => (!isManagedHookCommand(h.command, managedPrefixes) || currentManifestPaths.has(h.command)) &&
|
|
2277
|
-
!isStaleSiblingVersionCommand(h.command, currentVh));
|
|
2278
|
-
group.hooks = collapseVersionHookEntries(managed, versionHome);
|
|
1700
|
+
if (!resolved)
|
|
1701
|
+
continue;
|
|
1702
|
+
for (const event of hookDef.events) {
|
|
1703
|
+
const matcher = CODEX_MATCHER_EVENTS.has(event) ? hookDef.matcher : undefined;
|
|
1704
|
+
expected.add(hookEntryKey(event, matcher, resolved));
|
|
2279
1705
|
}
|
|
2280
1706
|
}
|
|
2281
|
-
|
|
2282
|
-
hooksFile.hooks[event] = eventGroups.filter((g) => g.hooks && g.hooks.length > 0);
|
|
2283
|
-
}
|
|
1707
|
+
pruneManagedHookEntries(hooksFile.hooks, expected, managedPrefixes);
|
|
2284
1708
|
for (const [name, hookDef] of Object.entries(manifest)) {
|
|
2285
1709
|
if (!hookDef.events || hookDef.events.length === 0)
|
|
2286
1710
|
continue;
|
|
@@ -2295,11 +1719,8 @@ function registerHooksForCodex(versionHome, manifest, resolveScript, managedPref
|
|
|
2295
1719
|
hooksFile.hooks[event] = [];
|
|
2296
1720
|
}
|
|
2297
1721
|
const eventGroups = hooksFile.hooks[event];
|
|
2298
|
-
// PreToolUse / PostToolUse / SessionStart use a matcher field.
|
|
2299
|
-
// UserPromptSubmit / Stop never include a matcher.
|
|
2300
1722
|
const usesMatcher = CODEX_MATCHER_EVENTS.has(event);
|
|
2301
1723
|
const matcherValue = usesMatcher ? (hookDef.matcher ?? '') : undefined;
|
|
2302
|
-
// Find the group for this matcher (or the sole no-matcher group)
|
|
2303
1724
|
let group;
|
|
2304
1725
|
if (matcherValue !== undefined) {
|
|
2305
1726
|
group = eventGroups.find((g) => (g.matcher ?? '') === matcherValue);
|
|
@@ -2341,11 +1762,6 @@ function registerHooksForCodex(versionHome, manifest, resolveScript, managedPref
|
|
|
2341
1762
|
errors.push(`Failed to write hooks.json: ${err.message}`);
|
|
2342
1763
|
return { registered, errors };
|
|
2343
1764
|
}
|
|
2344
|
-
// Ensure [features] hooks = true and pre-trust every registered hook in
|
|
2345
|
-
// config.toml. Codex only runs hooks that are enabled AND trusted; in
|
|
2346
|
-
// non-interactive (`codex exec`) mode there is no TUI prompt to approve
|
|
2347
|
-
// them, so an untrusted hook is silently dropped. We compute the same
|
|
2348
|
-
// trust hash Codex would and persist it under [hooks.state].
|
|
2349
1765
|
try {
|
|
2350
1766
|
trustCodexHooks(hooksPath);
|
|
2351
1767
|
}
|
|
@@ -2354,14 +1770,6 @@ function registerHooksForCodex(versionHome, manifest, resolveScript, managedPref
|
|
|
2354
1770
|
}
|
|
2355
1771
|
return { registered, errors };
|
|
2356
1772
|
}
|
|
2357
|
-
/**
|
|
2358
|
-
* Register hooks into antigravity's (agy) settings.json. Unlike gemini, agy uses
|
|
2359
|
-
* a flat per-event array of `{ command }` entries (no matcher groups). Events
|
|
2360
|
-
* are renamed via ANTIGRAVITY_EVENT_MAP; unmapped manifest events are skipped.
|
|
2361
|
-
*
|
|
2362
|
-
* settings.json lives at `${versionHome}/.gemini/antigravity-cli/settings.json`
|
|
2363
|
-
* because agy nests its config under the shared `.gemini` parent dir.
|
|
2364
|
-
*/
|
|
2365
1773
|
function registerHooksForAntigravity(versionHome, manifest, resolveScript, managedPrefixes) {
|
|
2366
1774
|
const registered = [];
|
|
2367
1775
|
const errors = [];
|
|
@@ -2384,16 +1792,10 @@ function registerHooksForAntigravity(versionHome, manifest, resolveScript, manag
|
|
|
2384
1792
|
config.hooks = {};
|
|
2385
1793
|
}
|
|
2386
1794
|
const hooks = config.hooks;
|
|
2387
|
-
// Build set of all command paths the current manifest will register, so we
|
|
2388
|
-
// can garbage-collect stale managed entries left over from renamed/deleted
|
|
2389
|
-
// hooks. Only managed paths are considered for removal — user-added entries
|
|
2390
|
-
// outside managedPrefixes are preserved.
|
|
2391
1795
|
const currentManifestPaths = new Set();
|
|
2392
1796
|
for (const [hookName, hookDef] of Object.entries(manifest)) {
|
|
2393
1797
|
if (!hookDef.events || hookDef.events.length === 0)
|
|
2394
1798
|
continue;
|
|
2395
|
-
// Only paths whose events map to a known agy event would actually be
|
|
2396
|
-
// registered, so only those should survive GC.
|
|
2397
1799
|
const anyMapped = hookDef.events.some((e) => ANTIGRAVITY_EVENT_MAP[e]);
|
|
2398
1800
|
if (!anyMapped)
|
|
2399
1801
|
continue;
|
|
@@ -2430,12 +1832,10 @@ function registerHooksForAntigravity(versionHome, manifest, resolveScript, manag
|
|
|
2430
1832
|
for (const event of hookDef.events) {
|
|
2431
1833
|
const agyEvent = ANTIGRAVITY_EVENT_MAP[event];
|
|
2432
1834
|
if (!agyEvent)
|
|
2433
|
-
continue;
|
|
1835
|
+
continue;
|
|
2434
1836
|
if (!hooks[agyEvent]) {
|
|
2435
1837
|
hooks[agyEvent] = [];
|
|
2436
1838
|
}
|
|
2437
|
-
// Antigravity settings entries: command + optional matcher (tool scope).
|
|
2438
|
-
// Without matcher every PreToolUse guard fires on ALL tools (RUSH-1353).
|
|
2439
1839
|
const list = hooks[agyEvent];
|
|
2440
1840
|
const existingIdx = list.findIndex((e) => e && typeof e === 'object' && e.command === commandPath);
|
|
2441
1841
|
const entry = { command: commandPath };
|
|
@@ -2459,44 +1859,10 @@ function registerHooksForAntigravity(versionHome, manifest, resolveScript, manag
|
|
|
2459
1859
|
}
|
|
2460
1860
|
return { registered, errors };
|
|
2461
1861
|
}
|
|
2462
|
-
/**
|
|
2463
|
-
* Grok events that accept a `matcher` field. Per the Grok hooks guide
|
|
2464
|
-
* (docs/user-guide/10-hooks.md, "Key Fields"): the matcher applies to the tool
|
|
2465
|
-
* events — `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionDenied`
|
|
2466
|
-
* (matches the tool name) — and to `Notification` (matches the notification
|
|
2467
|
-
* type). The lifecycle events `SessionStart`, `SessionEnd`, `Stop`,
|
|
2468
|
-
* `UserPromptSubmit` REJECT a matcher (they raise loading errors); other events
|
|
2469
|
-
* ignore it. Of the events this registrar emits (see GROK_EVENT_MAP), only these
|
|
2470
|
-
* three accept a matcher, so we emit it for these alone.
|
|
2471
|
-
*/
|
|
2472
1862
|
const GROK_MATCHER_EVENTS = new Set(['PreToolUse', 'PostToolUse', 'Notification']);
|
|
2473
|
-
/**
|
|
2474
|
-
* Tool-name matcher aliases for tools Grok does NOT auto-alias. Grok maps common
|
|
2475
|
-
* Claude tool names to its own (Bash → run_terminal_command, Read → read_file,
|
|
2476
|
-
* etc. — docs/user-guide/10-hooks.md, "Tool Name Aliases") and "a matcher keeps
|
|
2477
|
-
* its original name too", so most matchers need no translation. But there is no
|
|
2478
|
-
* alias for `ExitPlanMode`: Grok's plan tools are `enter_plan_mode` /
|
|
2479
|
-
* `exit_plan_mode` (docs/user-guide/19-plan-mode.md line 14), so a bare
|
|
2480
|
-
* `ExitPlanMode` matcher would never fire. Broaden it to a regex that matches
|
|
2481
|
-
* both names. Keep this an explicit, minimal map — not a general translation
|
|
2482
|
-
* engine.
|
|
2483
|
-
*/
|
|
2484
1863
|
const GROK_MATCHER_ALIASES = {
|
|
2485
1864
|
ExitPlanMode: 'ExitPlanMode|exit_plan_mode',
|
|
2486
1865
|
};
|
|
2487
|
-
/**
|
|
2488
|
-
* Register hooks for Grok Build.
|
|
2489
|
-
*
|
|
2490
|
-
* Grok merges ALL of `~/.grok/hooks/*.json` (docs/user-guide/10-hooks.md, "Hook
|
|
2491
|
-
* Locations"), so this registrar writes exactly ONE manifest file, `hooks.json`,
|
|
2492
|
-
* and prunes any stale per-event files (`pretooluse.json`, …) that an older
|
|
2493
|
-
* build wrote — otherwise every hook would run twice per event, forever, on
|
|
2494
|
-
* already-synced installs.
|
|
2495
|
-
*
|
|
2496
|
-
* Matchers are grouped one-per-distinct-matcher (like the Claude writer) and are
|
|
2497
|
-
* emitted only for the events that accept them (GROK_MATCHER_EVENTS); tool-name
|
|
2498
|
-
* matchers Grok does not auto-alias are translated via GROK_MATCHER_ALIASES.
|
|
2499
|
-
*/
|
|
2500
1866
|
function registerHooksForGrok(versionHome, manifest, resolveScript, managedPrefixes) {
|
|
2501
1867
|
const registered = [];
|
|
2502
1868
|
const errors = [];
|
|
@@ -2528,14 +1894,10 @@ function registerHooksForGrok(versionHome, manifest, resolveScript, managedPrefi
|
|
|
2528
1894
|
grokHooks.hooks[grokEvent] = [];
|
|
2529
1895
|
}
|
|
2530
1896
|
const groups = grokHooks.hooks[grokEvent];
|
|
2531
|
-
// Emit the matcher only for events that accept one; translate tool names
|
|
2532
|
-
// Grok does not auto-alias. Empty/omitted matcher matches everything.
|
|
2533
1897
|
let matcher;
|
|
2534
1898
|
if (GROK_MATCHER_EVENTS.has(grokEvent) && hookDef.matcher) {
|
|
2535
1899
|
matcher = GROK_MATCHER_ALIASES[hookDef.matcher] ?? hookDef.matcher;
|
|
2536
1900
|
}
|
|
2537
|
-
// Group by matcher the way the Claude writer does: one group per distinct
|
|
2538
|
-
// matcher, hooks appended into the group — not one group per hook.
|
|
2539
1901
|
let group = groups.find((g) => (g.matcher ?? '') === (matcher ?? ''));
|
|
2540
1902
|
if (!group) {
|
|
2541
1903
|
group = matcher ? { matcher, hooks: [] } : { hooks: [] };
|
|
@@ -2552,8 +1914,6 @@ function registerHooksForGrok(versionHome, manifest, resolveScript, managedPrefi
|
|
|
2552
1914
|
registered.push(`${name} -> ${grokEvent}`);
|
|
2553
1915
|
}
|
|
2554
1916
|
}
|
|
2555
|
-
// Single source of truth: hooks.json. Written fresh from the manifest every
|
|
2556
|
-
// sync, so the registrar owns it outright.
|
|
2557
1917
|
const mainHooksPath = path.join(grokHooksDir, 'hooks.json');
|
|
2558
1918
|
try {
|
|
2559
1919
|
fs.writeFileSync(mainHooksPath, JSON.stringify(grokHooks, null, 2));
|
|
@@ -2561,11 +1921,6 @@ function registerHooksForGrok(versionHome, manifest, resolveScript, managedPrefi
|
|
|
2561
1921
|
catch (e) {
|
|
2562
1922
|
errors.push(`Failed to write hooks.json: ${e.message}`);
|
|
2563
1923
|
}
|
|
2564
|
-
// Clean up stale per-event files (pretooluse.json, session-start.json, …) that
|
|
2565
|
-
// older builds double-wrote. Grok merges every *.json in this dir, so leaving
|
|
2566
|
-
// them would run each hook twice per event. Only remove files whose contents
|
|
2567
|
-
// are entirely managed by us (a lone `hooks` object referencing our managed
|
|
2568
|
-
// command paths); a user's own custom *.json is left untouched.
|
|
2569
1924
|
try {
|
|
2570
1925
|
for (const file of fs.readdirSync(grokHooksDir)) {
|
|
2571
1926
|
if (!file.endsWith('.json') || file === 'hooks.json')
|
|
@@ -2581,13 +1936,6 @@ function registerHooksForGrok(versionHome, manifest, resolveScript, managedPrefi
|
|
|
2581
1936
|
}
|
|
2582
1937
|
return { registered, errors };
|
|
2583
1938
|
}
|
|
2584
|
-
/**
|
|
2585
|
-
* A per-event Grok hook file is "ours" (safe to prune) when it is a
|
|
2586
|
-
* `{ hooks: { <Event>: [...] } }` document in which every command entry points
|
|
2587
|
-
* at a managed path (see isManagedHookCommand). This is exactly the shape older
|
|
2588
|
-
* builds double-wrote; a user's hand-authored *.json that mixes in unmanaged
|
|
2589
|
-
* commands is preserved. A file we can't parse is treated as not-ours.
|
|
2590
|
-
*/
|
|
2591
1939
|
function isManagedGrokHookFile(filePath, managedPrefixes) {
|
|
2592
1940
|
let parsed;
|
|
2593
1941
|
try {
|
|
@@ -2625,7 +1973,6 @@ function registerHooksForKimi(versionHome, manifest, resolveScript, managedPrefi
|
|
|
2625
1973
|
const registered = [];
|
|
2626
1974
|
const errors = [];
|
|
2627
1975
|
const configPath = path.join(versionHome, '.kimi-code', 'config.toml');
|
|
2628
|
-
// Read existing config.toml
|
|
2629
1976
|
let config = {};
|
|
2630
1977
|
if (fs.existsSync(configPath)) {
|
|
2631
1978
|
try {
|
|
@@ -2636,7 +1983,6 @@ function registerHooksForKimi(versionHome, manifest, resolveScript, managedPrefi
|
|
|
2636
1983
|
return { registered, errors };
|
|
2637
1984
|
}
|
|
2638
1985
|
}
|
|
2639
|
-
// Build set of current manifest command paths for GC
|
|
2640
1986
|
const currentManifestPaths = new Set();
|
|
2641
1987
|
for (const [hookName, hookDef] of Object.entries(manifest)) {
|
|
2642
1988
|
if (!hookDef.events || hookDef.events.length === 0)
|
|
@@ -2645,7 +1991,6 @@ function registerHooksForKimi(versionHome, manifest, resolveScript, managedPrefi
|
|
|
2645
1991
|
if (resolved)
|
|
2646
1992
|
currentManifestPaths.add(resolved);
|
|
2647
1993
|
}
|
|
2648
|
-
// Remove stale managed hooks from existing hooks array
|
|
2649
1994
|
let hooksArray = [];
|
|
2650
1995
|
if (Array.isArray(config.hooks)) {
|
|
2651
1996
|
hooksArray = config.hooks;
|
|
@@ -2658,7 +2003,6 @@ function registerHooksForKimi(versionHome, manifest, resolveScript, managedPrefi
|
|
|
2658
2003
|
return true;
|
|
2659
2004
|
return currentManifestPaths.has(cmd);
|
|
2660
2005
|
});
|
|
2661
|
-
// Add/update hooks from manifest
|
|
2662
2006
|
for (const [name, hookDef] of Object.entries(manifest)) {
|
|
2663
2007
|
if (!hookDef.events || hookDef.events.length === 0)
|
|
2664
2008
|
continue;
|
|
@@ -2670,7 +2014,6 @@ function registerHooksForKimi(versionHome, manifest, resolveScript, managedPrefi
|
|
|
2670
2014
|
const timeout = hookDef.timeout ?? 30;
|
|
2671
2015
|
for (const event of hookDef.events) {
|
|
2672
2016
|
const matcher = hookDef.matcher;
|
|
2673
|
-
// Find existing hook with same event, command, and matcher
|
|
2674
2017
|
const existingIdx = filteredHooks.findIndex((h) => {
|
|
2675
2018
|
const sameEvent = h.event === event;
|
|
2676
2019
|
const sameCmd = h.command === commandPath;
|
|
@@ -2704,13 +2047,6 @@ function registerHooksForKimi(versionHome, manifest, resolveScript, managedPrefi
|
|
|
2704
2047
|
}
|
|
2705
2048
|
return { registered, errors };
|
|
2706
2049
|
}
|
|
2707
|
-
/**
|
|
2708
|
-
* Canonical hooks.yaml event names → Copilot camelCase event names.
|
|
2709
|
-
* Copilot accepts both camelCase (native) and PascalCase (VS Code-compatible).
|
|
2710
|
-
* We emit camelCase, the format documented at
|
|
2711
|
-
* https://docs.github.com/en/copilot/reference/hooks-configuration.
|
|
2712
|
-
* Unmapped events are skipped so a Claude-only event does not land in the file.
|
|
2713
|
-
*/
|
|
2714
2050
|
const COPILOT_EVENT_MAP = {
|
|
2715
2051
|
SessionStart: 'sessionStart',
|
|
2716
2052
|
SessionEnd: 'sessionEnd',
|
|
@@ -2726,10 +2062,6 @@ const COPILOT_EVENT_MAP = {
|
|
|
2726
2062
|
Notification: 'notification',
|
|
2727
2063
|
PermissionRequest: 'permissionRequest',
|
|
2728
2064
|
};
|
|
2729
|
-
/**
|
|
2730
|
-
* Copilot events that accept a `matcher` field (regex, full-string match).
|
|
2731
|
-
* See "Matcher filtering" in the Copilot hooks reference.
|
|
2732
|
-
*/
|
|
2733
2065
|
const COPILOT_MATCHER_EVENTS = new Set([
|
|
2734
2066
|
'preToolUse',
|
|
2735
2067
|
'postToolUse',
|
|
@@ -2738,18 +2070,7 @@ const COPILOT_MATCHER_EVENTS = new Set([
|
|
|
2738
2070
|
'notification',
|
|
2739
2071
|
'subagentStart',
|
|
2740
2072
|
]);
|
|
2741
|
-
/** Managed filename under ~/.copilot/hooks/ — we own this file entirely. */
|
|
2742
2073
|
const COPILOT_MANAGED_HOOKS_FILE = 'agents-cli-hooks.json';
|
|
2743
|
-
/**
|
|
2744
|
-
* Register hooks for GitHub Copilot CLI.
|
|
2745
|
-
*
|
|
2746
|
-
* Copilot loads every `*.json` under `~/.copilot/hooks/` (and project
|
|
2747
|
-
* `.github/hooks/`). Schema: `{ "version": 1, "hooks": { event: [entries] } }`
|
|
2748
|
-
* with command entries `{ type: "command", bash|command, timeoutSec?, matcher? }`.
|
|
2749
|
-
*
|
|
2750
|
-
* We rewrite a single managed file (`agents-cli-hooks.json`) on every sync so
|
|
2751
|
-
* GC is trivial — user-authored sibling JSON files are never touched.
|
|
2752
|
-
*/
|
|
2753
2074
|
function registerHooksForCopilot(versionHome, manifest, resolveScript, _managedPrefixes) {
|
|
2754
2075
|
const registered = [];
|
|
2755
2076
|
const errors = [];
|
|
@@ -2768,7 +2089,7 @@ function registerHooksForCopilot(versionHome, manifest, resolveScript, _managedP
|
|
|
2768
2089
|
for (const event of hookDef.events) {
|
|
2769
2090
|
const copilotEvent = COPILOT_EVENT_MAP[event];
|
|
2770
2091
|
if (!copilotEvent)
|
|
2771
|
-
continue;
|
|
2092
|
+
continue;
|
|
2772
2093
|
if (!hooks[copilotEvent])
|
|
2773
2094
|
hooks[copilotEvent] = [];
|
|
2774
2095
|
const entry = {
|
|
@@ -2779,7 +2100,6 @@ function registerHooksForCopilot(versionHome, manifest, resolveScript, _managedP
|
|
|
2779
2100
|
if (COPILOT_MATCHER_EVENTS.has(copilotEvent) && hookDef.matcher) {
|
|
2780
2101
|
entry.matcher = hookDef.matcher;
|
|
2781
2102
|
}
|
|
2782
|
-
// De-dupe on (event, command, matcher) so repeated sync is idempotent.
|
|
2783
2103
|
const existingIdx = hooks[copilotEvent].findIndex((h) => h.command === entry.command && (h.matcher ?? '') === (entry.matcher ?? ''));
|
|
2784
2104
|
if (existingIdx >= 0) {
|
|
2785
2105
|
hooks[copilotEvent][existingIdx] = entry;
|
|
@@ -2792,7 +2112,6 @@ function registerHooksForCopilot(versionHome, manifest, resolveScript, _managedP
|
|
|
2792
2112
|
}
|
|
2793
2113
|
const outPath = path.join(copilotHooksDir, COPILOT_MANAGED_HOOKS_FILE);
|
|
2794
2114
|
try {
|
|
2795
|
-
// Always rewrite: empty manifest → empty hooks object (GC of prior managed entries).
|
|
2796
2115
|
fs.writeFileSync(outPath, JSON.stringify({ version: 1, hooks }, null, 2) + '\n', 'utf-8');
|
|
2797
2116
|
}
|
|
2798
2117
|
catch (err) {
|
|
@@ -2800,10 +2119,6 @@ function registerHooksForCopilot(versionHome, manifest, resolveScript, _managedP
|
|
|
2800
2119
|
}
|
|
2801
2120
|
return { registered, errors };
|
|
2802
2121
|
}
|
|
2803
|
-
/**
|
|
2804
|
-
* Canonical hooks.yaml event names that goose supports (Open Plugins PascalCase).
|
|
2805
|
-
* Unmapped events are skipped. Goose ≥ 1.34.0.
|
|
2806
|
-
*/
|
|
2807
2122
|
const GOOSE_EVENT_MAP = {
|
|
2808
2123
|
SessionStart: 'SessionStart',
|
|
2809
2124
|
SessionEnd: 'SessionEnd',
|
|
@@ -2816,22 +2131,8 @@ const GOOSE_EVENT_MAP = {
|
|
|
2816
2131
|
AfterFileEdit: 'AfterFileEdit',
|
|
2817
2132
|
BeforeShellExecution: 'BeforeShellExecution',
|
|
2818
2133
|
AfterShellExecution: 'AfterShellExecution',
|
|
2819
|
-
// SubagentStart/SubagentStop are not emitted by Goose — do not advertise them.
|
|
2820
2134
|
};
|
|
2821
|
-
/** Managed Open Plugins directory name under ~/.agents/plugins/. */
|
|
2822
2135
|
const GOOSE_MANAGED_PLUGIN_NAME = 'agents-cli-hooks';
|
|
2823
|
-
/**
|
|
2824
|
-
* Register hooks for Goose (block-goose-cli ≥ 1.34.0).
|
|
2825
|
-
*
|
|
2826
|
-
* Goose auto-discovers Open Plugins under `$HOME/.agents/plugins/<name>/` that
|
|
2827
|
-
* contain `hooks/hooks.json` (HOME is the version home under the agents-cli
|
|
2828
|
-
* shim). Schema (Open Plugins / Claude-shaped):
|
|
2829
|
-
* { "hooks": { Event: [ { matcher?, hooks: [{ type: "command", command }] } ] } }
|
|
2830
|
-
*
|
|
2831
|
-
* We own a single managed plugin (`agents-cli-hooks`) under the version home
|
|
2832
|
-
* and rewrite its hooks.json on every sync. Command paths are absolute
|
|
2833
|
-
* (portable ~/ form) pointing at the already-copied hook scripts.
|
|
2834
|
-
*/
|
|
2835
2136
|
function registerHooksForGoose(versionHome, manifest, resolveScript, _managedPrefixes) {
|
|
2836
2137
|
const registered = [];
|
|
2837
2138
|
const errors = [];
|
|
@@ -2871,15 +2172,11 @@ function registerHooksForGoose(versionHome, manifest, resolveScript, _managedPre
|
|
|
2871
2172
|
registered.push(`${name} -> ${gooseEvent}`);
|
|
2872
2173
|
}
|
|
2873
2174
|
}
|
|
2874
|
-
// Goose discovers Open Plugins at ~/.agents/plugins/<name>/ when HOME is the
|
|
2875
|
-
// version home (shim sets HOME). Write under versionHome so each installed
|
|
2876
|
-
// goose version gets its own managed plugin and tests stay hermetic.
|
|
2877
2175
|
const pluginRoot = path.join(versionHome, '.agents', 'plugins', GOOSE_MANAGED_PLUGIN_NAME);
|
|
2878
2176
|
const hooksDir = path.join(pluginRoot, 'hooks');
|
|
2879
2177
|
const outPath = path.join(hooksDir, 'hooks.json');
|
|
2880
2178
|
try {
|
|
2881
2179
|
fs.mkdirSync(hooksDir, { recursive: true });
|
|
2882
|
-
// Minimal plugin marker so the directory is a valid Open Plugins bundle.
|
|
2883
2180
|
const markerPath = path.join(pluginRoot, '.agents-cli-managed');
|
|
2884
2181
|
if (!fs.existsSync(markerPath)) {
|
|
2885
2182
|
fs.writeFileSync(markerPath, 'managed by agents-cli hooks sync\n', 'utf-8');
|
|
@@ -2891,16 +2188,6 @@ function registerHooksForGoose(versionHome, manifest, resolveScript, _managedPre
|
|
|
2891
2188
|
}
|
|
2892
2189
|
return { registered, errors };
|
|
2893
2190
|
}
|
|
2894
|
-
/**
|
|
2895
|
-
* Canonical → Cursor CLI camelCase events.
|
|
2896
|
-
*
|
|
2897
|
-
* Only events verified to fire in cursor-agent CLI (not full IDE parity).
|
|
2898
|
-
* Ticket RUSH-1326 note (2026-06): working = sessionStart, stop, preToolUse,
|
|
2899
|
-
* postToolUse, beforeShellExecution, afterShellExecution, beforeReadFile,
|
|
2900
|
-
* afterFileEdit. Also map SessionEnd / beforeSubmitPrompt / preCompact /
|
|
2901
|
-
* subagent* which Cursor documents for agent hooks.
|
|
2902
|
-
* Unmapped events (e.g. afterAgentResponse) are skipped.
|
|
2903
|
-
*/
|
|
2904
2191
|
const CURSOR_EVENT_MAP = {
|
|
2905
2192
|
SessionStart: 'sessionStart',
|
|
2906
2193
|
SessionEnd: 'sessionEnd',
|
|
@@ -2917,15 +2204,6 @@ const CURSOR_EVENT_MAP = {
|
|
|
2917
2204
|
BeforeReadFile: 'beforeReadFile',
|
|
2918
2205
|
AfterFileEdit: 'afterFileEdit',
|
|
2919
2206
|
};
|
|
2920
|
-
/**
|
|
2921
|
-
* Register hooks for Cursor CLI (`cursor-agent`).
|
|
2922
|
-
*
|
|
2923
|
-
* Writes `~/.cursor/hooks.json` (under version home):
|
|
2924
|
-
* { "version": 1, "hooks": { event: [{ command, timeout?, matcher? }] } }
|
|
2925
|
-
*
|
|
2926
|
-
* GC: rewrite managed entries by command path under managedPrefixes; preserve
|
|
2927
|
-
* user-authored entries whose command is outside managed roots.
|
|
2928
|
-
*/
|
|
2929
2207
|
function registerHooksForCursor(versionHome, manifest, resolveScript, managedPrefixes) {
|
|
2930
2208
|
const registered = [];
|
|
2931
2209
|
const errors = [];
|
|
@@ -2943,8 +2221,6 @@ function registerHooksForCursor(versionHome, manifest, resolveScript, managedPre
|
|
|
2943
2221
|
return { registered, errors };
|
|
2944
2222
|
}
|
|
2945
2223
|
}
|
|
2946
|
-
// Desired managed entries keyed by event|command|matcher so a matcher or
|
|
2947
|
-
// event change drops the stale entry instead of retaining it by command path alone.
|
|
2948
2224
|
const desiredManaged = new Set();
|
|
2949
2225
|
for (const [hookName, hookDef] of Object.entries(manifest)) {
|
|
2950
2226
|
if (!hookDef.events || hookDef.events.length === 0)
|
|
@@ -2959,7 +2235,6 @@ function registerHooksForCursor(versionHome, manifest, resolveScript, managedPre
|
|
|
2959
2235
|
desiredManaged.add(`${cursorEvent}|${resolved}|${hookDef.matcher ?? ''}`);
|
|
2960
2236
|
}
|
|
2961
2237
|
}
|
|
2962
|
-
// GC managed entries that are no longer in the manifest (by event+command+matcher)
|
|
2963
2238
|
const hooks = {};
|
|
2964
2239
|
for (const [event, entries] of Object.entries(existing.hooks || {})) {
|
|
2965
2240
|
if (!Array.isArray(entries))
|
|
@@ -3011,15 +2286,6 @@ function registerHooksForCursor(versionHome, manifest, resolveScript, managedPre
|
|
|
3011
2286
|
}
|
|
3012
2287
|
return { registered, errors };
|
|
3013
2288
|
}
|
|
3014
|
-
/**
|
|
3015
|
-
* Canonical → Hermes (Nous Research) snake_case lifecycle events.
|
|
3016
|
-
*
|
|
3017
|
-
* Hermes ≥ 0.11.0 runs configurable hooks declared under `hooks:` in
|
|
3018
|
-
* ~/.hermes/config.yaml. Only events with a documented Hermes equivalent are
|
|
3019
|
-
* mapped; unmapped canonical events (the manifest may declare events for other
|
|
3020
|
-
* agents) are skipped silently. UserPromptSubmit maps to `pre_llm_call` (the
|
|
3021
|
-
* closest pre-turn phase) and Stop to `on_session_finalize`.
|
|
3022
|
-
*/
|
|
3023
2289
|
const HERMES_EVENT_MAP = {
|
|
3024
2290
|
SessionStart: 'on_session_start',
|
|
3025
2291
|
SessionEnd: 'on_session_end',
|
|
@@ -3029,29 +2295,13 @@ const HERMES_EVENT_MAP = {
|
|
|
3029
2295
|
UserPromptSubmit: 'pre_llm_call',
|
|
3030
2296
|
Stop: 'on_session_finalize',
|
|
3031
2297
|
};
|
|
3032
|
-
/** Hermes caps hook timeouts at 300s (default 60s). */
|
|
3033
2298
|
const HERMES_TIMEOUT_CAP = 300;
|
|
3034
2299
|
const HERMES_TIMEOUT_DEFAULT = 60;
|
|
3035
|
-
/**
|
|
3036
|
-
* Register hooks for Hermes Agent (Nous Research ≥ 0.11.0).
|
|
3037
|
-
*
|
|
3038
|
-
* Read-modify-writes the shared `~/.hermes/config.yaml` (under the version
|
|
3039
|
-
* home): it merges a `hooks:` block of the form
|
|
3040
|
-
* hooks: { <event>: [ { command, timeout, matcher? } ] }
|
|
3041
|
-
* into the YAML doc WITHOUT touching sibling keys (`mcp_servers` in
|
|
3042
|
-
* particular — a naive overwrite would wipe the user's MCP servers). No
|
|
3043
|
-
* `version` wrapper: Hermes' config is a flat YAML map.
|
|
3044
|
-
*
|
|
3045
|
-
* GC: rewrite managed entries by command path under managedPrefixes; preserve
|
|
3046
|
-
* user-authored entries whose command is outside managed roots. Keyed by
|
|
3047
|
-
* event|command|matcher so a matcher or event change drops the stale entry.
|
|
3048
|
-
*/
|
|
3049
2300
|
function registerHooksForHermes(versionHome, manifest, resolveScript, managedPrefixes) {
|
|
3050
2301
|
const registered = [];
|
|
3051
2302
|
const errors = [];
|
|
3052
2303
|
const configDir = path.join(versionHome, '.hermes');
|
|
3053
2304
|
const configPath = path.join(configDir, 'config.yaml');
|
|
3054
|
-
// Read-modify-write: preserve the full existing YAML doc (mcp_servers, etc.).
|
|
3055
2305
|
let config = {};
|
|
3056
2306
|
if (fs.existsSync(configPath)) {
|
|
3057
2307
|
try {
|
|
@@ -3068,8 +2318,6 @@ function registerHooksForHermes(versionHome, manifest, resolveScript, managedPre
|
|
|
3068
2318
|
const existingHooks = config.hooks && typeof config.hooks === 'object' && !Array.isArray(config.hooks)
|
|
3069
2319
|
? config.hooks
|
|
3070
2320
|
: {};
|
|
3071
|
-
// Desired managed entries keyed by event|command|matcher so a matcher or
|
|
3072
|
-
// event change drops the stale entry instead of retaining it by command alone.
|
|
3073
2321
|
const desiredManaged = new Set();
|
|
3074
2322
|
for (const [hookName, hookDef] of Object.entries(manifest)) {
|
|
3075
2323
|
if (!hookDef.events || hookDef.events.length === 0)
|
|
@@ -3084,7 +2332,6 @@ function registerHooksForHermes(versionHome, manifest, resolveScript, managedPre
|
|
|
3084
2332
|
desiredManaged.add(`${hermesEvent}|${resolved}|${hookDef.matcher ?? ''}`);
|
|
3085
2333
|
}
|
|
3086
2334
|
}
|
|
3087
|
-
// GC managed entries that are no longer in the manifest; preserve user entries.
|
|
3088
2335
|
const hooks = {};
|
|
3089
2336
|
for (const [event, entries] of Object.entries(existingHooks)) {
|
|
3090
2337
|
if (!Array.isArray(entries))
|
|
@@ -3145,12 +2392,10 @@ function registerHooksForHermes(versionHome, manifest, resolveScript, managedPre
|
|
|
3145
2392
|
const execFileAsync = promisify(execFile);
|
|
3146
2393
|
function resolveSessionTrackerRoot() {
|
|
3147
2394
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
3148
|
-
// Built/installed layout: dist/lib/hooks/ -> dist/session-tracker
|
|
3149
2395
|
const built = path.resolve(here, '..', '..', 'session-tracker');
|
|
3150
2396
|
if (fs.existsSync(path.join(built, 'dist', 'hook.sh'))) {
|
|
3151
2397
|
return built;
|
|
3152
2398
|
}
|
|
3153
|
-
// Source layout: cli/src/lib/hooks/ -> repo root (4 up) -> packages/session-tracker
|
|
3154
2399
|
const source = path.resolve(here, '..', '..', '..', '..', 'packages', 'session-tracker');
|
|
3155
2400
|
if (fs.existsSync(path.join(source, 'src', 'hook.sh'))) {
|
|
3156
2401
|
return source;
|
|
@@ -3176,14 +2421,6 @@ function buildInstallHookInvocation(trackerRoot, agent) {
|
|
|
3176
2421
|
args: [loader, path.join(trackerRoot, 'src', 'install-hook.ts'), agent],
|
|
3177
2422
|
};
|
|
3178
2423
|
}
|
|
3179
|
-
/**
|
|
3180
|
-
* Install the shared SessionStart state-writer hook (`packages/session-tracker`)
|
|
3181
|
-
* into the harness's native config. Gated by `supports(agent, 'hooks', version)`;
|
|
3182
|
-
* unsupported agents return `installed: false` with a reason instead of throwing.
|
|
3183
|
-
*
|
|
3184
|
-
* This is the bridge that makes bare `claude` / `codex` / `kimi` launches write
|
|
3185
|
-
* `~/.agents/.cache/terminals/sessions/<pid>.json`, not just `agents run` launches.
|
|
3186
|
-
*/
|
|
3187
2424
|
export async function installSessionTrackerHook(agent, version, home) {
|
|
3188
2425
|
const gate = supports(agent, 'hooks', version);
|
|
3189
2426
|
if (!gate.ok) {
|
|
@@ -3211,11 +2448,6 @@ export async function installSessionTrackerHook(agent, version, home) {
|
|
|
3211
2448
|
return { installed: false, error: installFailureMessage(err) };
|
|
3212
2449
|
}
|
|
3213
2450
|
}
|
|
3214
|
-
/**
|
|
3215
|
-
* The child reports its refusal reason on stdout (its HOOK_SUPPORT table), not
|
|
3216
|
-
* stderr — and a Buffer-typed empty stderr is truthy, so a bare `err.stderr ??
|
|
3217
|
-
* err.message` surfaced an empty string. Prefer the first NON-EMPTY stream.
|
|
3218
|
-
*/
|
|
3219
2451
|
function installFailureMessage(err) {
|
|
3220
2452
|
const e = err;
|
|
3221
2453
|
for (const stream of [e.stderr, e.stdout]) {
|
|
@@ -3225,10 +2457,6 @@ function installFailureMessage(err) {
|
|
|
3225
2457
|
}
|
|
3226
2458
|
return e.message;
|
|
3227
2459
|
}
|
|
3228
|
-
/**
|
|
3229
|
-
* Synchronous variant for callers that cannot be made async (e.g.
|
|
3230
|
-
* `syncResourcesToVersion`). Best-effort: failures are returned, not thrown.
|
|
3231
|
-
*/
|
|
3232
2460
|
export function installSessionTrackerHookSync(agent, version, home) {
|
|
3233
2461
|
const gate = supports(agent, 'hooks', version);
|
|
3234
2462
|
if (!gate.ok) {
|
|
@@ -3257,7 +2485,6 @@ export function installSessionTrackerHookSync(agent, version, home) {
|
|
|
3257
2485
|
return { installed: false, error: installFailureMessage(err) };
|
|
3258
2486
|
}
|
|
3259
2487
|
}
|
|
3260
|
-
/** The hook installer must target this account, not the current global home. */
|
|
3261
2488
|
function sessionTrackerInstallEnv(agent, version, home) {
|
|
3262
2489
|
const target = home ?? (version ? getVersionHomePath(agent, version) : undefined);
|
|
3263
2490
|
if (agent === 'codex' && target && version) {
|