@phnx-labs/agents-cli 1.22.119 → 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 +236 -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 +20 -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
package/dist/lib/teams/agents.js
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Teams agent lifecycle management.
|
|
3
|
-
*
|
|
4
|
-
* Defines the AgentProcess and AgentManager classes that handle spawning,
|
|
5
|
-
* monitoring, stopping, and persisting teammate processes across all supported
|
|
6
|
-
* agent CLIs (Claude, Codex, Cursor, OpenCode). Supports DAG-based
|
|
7
|
-
* dependency scheduling via --after, per-teammate model/effort overrides, and
|
|
8
|
-
* multiple permission modes (plan, edit, full).
|
|
9
|
-
*/
|
|
10
1
|
import { spawn, execSync } from 'child_process';
|
|
11
2
|
import { getAgentsInvocation } from '../daemon/daemon.js';
|
|
12
3
|
import * as fs from 'fs/promises';
|
|
@@ -42,10 +33,6 @@ import { filterAutoPool, listWorkerDevices } from '../devices/pool.js';
|
|
|
42
33
|
import { redactSecrets, sanitizeForTerminal } from '../redact.js';
|
|
43
34
|
import chalk from 'chalk';
|
|
44
35
|
let lastMemoryWarnAt = 0;
|
|
45
|
-
// On macOS, os.freemem() returns only the truly-free pool and ignores the
|
|
46
|
-
// large inactive+purgeable cache the kernel will reclaim under pressure, so
|
|
47
|
-
// it always looks alarmingly low on a healthy Mac. Parse vm_stat to get the
|
|
48
|
-
// real "available" figure: free + inactive + purgeable + speculative.
|
|
49
36
|
function availableMemoryBytes() {
|
|
50
37
|
if (process.platform !== 'darwin')
|
|
51
38
|
return os.freemem();
|
|
@@ -86,26 +73,17 @@ function warnIfMemoryLow(runningCount) {
|
|
|
86
73
|
process.stderr.write(`Heads up: only ${freeGb}GB of ${totalGb}GB free with ${runningCount} teammates already running. ` +
|
|
87
74
|
`Spawning more may slow your machine.\n`);
|
|
88
75
|
}
|
|
89
|
-
/**
|
|
90
|
-
* Compute the Lowest Common Ancestor (LCA) of multiple file paths.
|
|
91
|
-
* Returns the deepest common directory shared by all paths.
|
|
92
|
-
* Returns null if paths is empty or paths have no common ancestor (different roots).
|
|
93
|
-
*/
|
|
94
76
|
export function computePathLCA(paths) {
|
|
95
77
|
const validPaths = paths.filter(p => p && p.trim());
|
|
96
78
|
if (validPaths.length === 0)
|
|
97
79
|
return null;
|
|
98
80
|
if (validPaths.length === 1)
|
|
99
81
|
return validPaths[0];
|
|
100
|
-
// Normalize and split all paths into segments
|
|
101
82
|
const splitPaths = validPaths.map(p => {
|
|
102
83
|
const normalized = path.resolve(p);
|
|
103
|
-
// Split by path separator, filter empty segments
|
|
104
84
|
return normalized.split(path.sep).filter(seg => seg);
|
|
105
85
|
});
|
|
106
|
-
// Find minimum length
|
|
107
86
|
const minLen = Math.min(...splitPaths.map(p => p.length));
|
|
108
|
-
// Find common prefix
|
|
109
87
|
const commonSegments = [];
|
|
110
88
|
for (let i = 0; i < minLen; i++) {
|
|
111
89
|
const segment = splitPaths[0][i];
|
|
@@ -119,11 +97,9 @@ export function computePathLCA(paths) {
|
|
|
119
97
|
}
|
|
120
98
|
if (commonSegments.length === 0)
|
|
121
99
|
return null;
|
|
122
|
-
// Reconstruct path (add leading separator for absolute paths)
|
|
123
100
|
const lca = path.sep + commonSegments.join(path.sep);
|
|
124
101
|
return lca;
|
|
125
102
|
}
|
|
126
|
-
/** Lifecycle status of a teammate process. */
|
|
127
103
|
export var AgentStatus;
|
|
128
104
|
(function (AgentStatus) {
|
|
129
105
|
AgentStatus["PENDING"] = "pending";
|
|
@@ -132,57 +108,35 @@ export var AgentStatus;
|
|
|
132
108
|
AgentStatus["FAILED"] = "failed";
|
|
133
109
|
AgentStatus["STOPPED"] = "stopped";
|
|
134
110
|
})(AgentStatus || (AgentStatus = {}));
|
|
135
|
-
/**
|
|
136
|
-
* The statuses a teammate can never leave — its process has run and finished
|
|
137
|
-
* (or been stopped). Everything else (pending, running) is still live work.
|
|
138
|
-
*
|
|
139
|
-
* This is the ONLY set that retention (cleanupOldAgents) may reap: a `pending`
|
|
140
|
-
* teammate has not launched yet and a `running` one is doing work, so deleting
|
|
141
|
-
* either is data loss. Treating "not running" as "completed" was the RUSH-2356
|
|
142
|
-
* bug — it swept live `pending` `--after` teammates past the 50-record cap.
|
|
143
|
-
*/
|
|
144
111
|
export const TERMINAL_STATUSES = new Set([
|
|
145
112
|
AgentStatus.COMPLETED,
|
|
146
113
|
AgentStatus.FAILED,
|
|
147
114
|
AgentStatus.STOPPED,
|
|
148
115
|
]);
|
|
149
|
-
|
|
116
|
+
// Retention owns terminal records only; pending/running teammates may still hold work.
|
|
150
117
|
function isTerminalStatus(status) {
|
|
151
118
|
return TERMINAL_STATUSES.has(status);
|
|
152
119
|
}
|
|
153
120
|
function safeFailureMessage(message) {
|
|
154
121
|
return redactSecrets(sanitizeForTerminal(message)).replace(/\s+/g, ' ').trim().slice(0, 500);
|
|
155
122
|
}
|
|
156
|
-
/**
|
|
157
|
-
* The per-teammate shell that emits `<id> <ALIVE|EXITED|GONE> <codeOrEmpty>`.
|
|
158
|
-
* Shared by the batched prefetch (many teammates, one round-trip) and the
|
|
159
|
-
* direct single-teammate probe, so both classify liveness identically.
|
|
160
|
-
* `exitFile` is interpolated UNQUOTED so `$HOME` in the dispatch path expands on
|
|
161
|
-
* the remote shell (shellQuote would defeat the `[ -f ]` test).
|
|
162
|
-
*/
|
|
163
123
|
export function remoteLivenessSnippet(id, exitFile, pid) {
|
|
124
|
+
// Missing process plus missing exit sentinel is terminal failure, never indefinite running.
|
|
164
125
|
return (`printf '%s ' ${shellQuote(id)}; ` +
|
|
165
126
|
`if [ -f ${exitFile} ]; then printf 'EXITED '; cat ${exitFile} 2>/dev/null | tr -d '\\n'; printf '\\n'; ` +
|
|
166
127
|
`elif kill -0 ${pid} 2>/dev/null; then printf 'ALIVE\\n'; ` +
|
|
167
128
|
`else printf 'GONE\\n'; fi`);
|
|
168
129
|
}
|
|
169
|
-
/** Parse one `<STATE> <codeOrEmpty>` reading into a snapshot. */
|
|
170
130
|
export function parseRemoteLivenessState(state, code) {
|
|
171
131
|
if (state === 'ALIVE')
|
|
172
132
|
return { alive: true, exit: null, exitFilePresent: false };
|
|
173
133
|
if (state === 'EXITED')
|
|
174
134
|
return { alive: false, exit: code ?? '', exitFilePresent: true };
|
|
175
|
-
// GONE (or an unrecognised token): process not alive, no sentinel recorded.
|
|
176
135
|
return { alive: false, exit: null, exitFilePresent: false };
|
|
177
136
|
}
|
|
178
137
|
export const VALID_TASK_TYPES = [
|
|
179
138
|
'plan', 'implement', 'test', 'review', 'bugfix', 'docs',
|
|
180
139
|
];
|
|
181
|
-
/**
|
|
182
|
-
* Walk the `after` chain from `startName` within the given map; returns true
|
|
183
|
-
* if `targetName` appears anywhere in the transitive dependency closure.
|
|
184
|
-
* Used to detect cycles before adding a new --after edge.
|
|
185
|
-
*/
|
|
186
140
|
function hasTransitiveDep(byName, startName, targetName, seen = new Set()) {
|
|
187
141
|
if (seen.has(startName))
|
|
188
142
|
return false;
|
|
@@ -198,34 +152,12 @@ function hasTransitiveDep(byName, startName, targetName, seen = new Set()) {
|
|
|
198
152
|
}
|
|
199
153
|
return false;
|
|
200
154
|
}
|
|
201
|
-
/**
|
|
202
|
-
* Single-quote a string for safe interpolation into a POSIX `sh -c` command.
|
|
203
|
-
* Wraps in single quotes and escapes embedded single quotes via the standard
|
|
204
|
-
* `'\''` close-escape-reopen idiom, so arbitrary prompts/paths can't break out
|
|
205
|
-
* of quoting or inject shell syntax.
|
|
206
|
-
*/
|
|
207
155
|
function shSingleQuote(value) {
|
|
208
156
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
209
157
|
}
|
|
210
|
-
/**
|
|
211
|
-
* Wrap a teammate argv in a POSIX shell command that runs it and then records
|
|
212
|
-
* the real exit code to `exitCodePath`. `echo $?` captures the status of the
|
|
213
|
-
* preceding command, so the sentinel reflects the underlying CLI's exit code,
|
|
214
|
-
* not the shell's. Single source of truth shared by launchProcess() and its
|
|
215
|
-
* test. See reapProcess() for how the sentinel is consumed.
|
|
216
|
-
*/
|
|
217
158
|
export function buildSentinelCommand(cmd, exitCodePath) {
|
|
218
159
|
return `${cmd.map(shSingleQuote).join(' ')}; echo $? > ${shSingleQuote(exitCodePath)}`;
|
|
219
160
|
}
|
|
220
|
-
/**
|
|
221
|
-
* Env for a locally-spawned teammate. Freezes ONE actor for the whole spawn
|
|
222
|
-
* tree: actorEnv(resolveActor()) stamps AGENTS_ACTOR* onto the child env, so the
|
|
223
|
-
* teammate's inner `agents run` reads it via inheritedActor and short-circuits
|
|
224
|
-
* computeActor instead of re-resolving — every teammate under one orchestrator
|
|
225
|
-
* shares the orchestrator's single frozen actor (see actor.ts). Precedence:
|
|
226
|
-
* process env < actor < the teammate's --env overrides, so an explicit override
|
|
227
|
-
* still wins. Single source of truth shared by launchProcess() and its test.
|
|
228
|
-
*/
|
|
229
161
|
export function buildTeammateSpawnEnv(envOverrides) {
|
|
230
162
|
return {
|
|
231
163
|
...sanitizeProcessEnv(process.env),
|
|
@@ -233,48 +165,17 @@ export function buildTeammateSpawnEnv(envOverrides) {
|
|
|
233
165
|
...(envOverrides ?? {}),
|
|
234
166
|
};
|
|
235
167
|
}
|
|
236
|
-
/**
|
|
237
|
-
* Re-exported from `platform/process.ts`, which owns the one implementation.
|
|
238
|
-
*
|
|
239
|
-
* This module used to carry its own near-identical copy, and that copy had no
|
|
240
|
-
* Windows branch — it fell through to `ps`, which does not exist there, so
|
|
241
|
-
* `captureProcessStartTime` always returned null and the pid-reuse guard at
|
|
242
|
-
* `stop()` was silently inert on Windows. That is exactly how `agents teams stop`
|
|
243
|
-
* ends up SIGKILLing an unrelated process group once the OS recycles a pid.
|
|
244
|
-
*/
|
|
245
168
|
export { captureProcessStartTime };
|
|
246
|
-
/** Agent types the team runner supports. */
|
|
247
169
|
const TEAM_AGENT_TYPES = ['codex', 'cursor', 'claude', 'opencode', 'grok', 'antigravity', 'kimi', 'droid', 'warp'];
|
|
248
|
-
// Suffix appended to all prompts to ensure agents provide a summary
|
|
249
170
|
const PROMPT_SUFFIX = `
|
|
250
171
|
|
|
251
172
|
When you're done, provide a brief summary of:
|
|
252
173
|
1. What you did (1-2 sentences)
|
|
253
174
|
2. Key files modified and why
|
|
254
175
|
3. Any important classes, functions, or components you added/changed`;
|
|
255
|
-
// Prefix for Claude agents in plan mode - explains the headless plan mode restrictions
|
|
256
176
|
const CLAUDE_PLAN_MODE_PREFIX = `You are running in HEADLESS PLAN MODE. This mode works like normal plan mode with one exception: you cannot write to ~/.claude/plans/ directory. Instead of writing a plan file, output your complete plan/response as your final message.
|
|
257
177
|
|
|
258
178
|
`;
|
|
259
|
-
// PHNX-3236: the teammate self-merge boundary, injected as a DISPATCH DEFAULT.
|
|
260
|
-
// A write-capable teammate has `gh pr merge` and authenticates as the repo owner,
|
|
261
|
-
// so it can merge its OWN PR past the required non-author-review gate — which is
|
|
262
|
-
// exactly what happened in the RUSH-2988 wave-1 dispatch (PR #1817, #1820). The
|
|
263
|
-
// root cause was that the boundary lived in per-brief wording: one teammate in the
|
|
264
|
-
// batch was told "open the PR, don't merge" and held off; the others weren't and
|
|
265
|
-
// self-merged. Making it a default the runner appends to every non-plan teammate
|
|
266
|
-
// gives one HARNESS-INDEPENDENT layer instead of relying on each dispatch prompt
|
|
267
|
-
// remembering to say it. The HARD enforcement is merge-guard.sh — a PreToolUse hook
|
|
268
|
-
// the teammate inherits from the shared version home, whose self-authored-verdict
|
|
269
|
-
// exclusion was closed in the same ticket (.agents-system #395) so a verdict a
|
|
270
|
-
// teammate posts on its own PR no longer clears the gate. The two layers do NOT
|
|
271
|
-
// overlap everywhere: hook-capable local/remote teammates get both, but cloud
|
|
272
|
-
// teammates (provider sandbox, no inherited hook) and hook-incapable harnesses
|
|
273
|
-
// (Warp/oz — no hook surface, no allowlist) get ONLY this prompt, so for them it is
|
|
274
|
-
// a soft control. That residual is documented in cli/AGENTS.md §6; server-side
|
|
275
|
-
// branch protection is the client-independent way to close it. This is the
|
|
276
|
-
// harness-independent layer plus the operator hand-off contract, not a replacement
|
|
277
|
-
// for the hard block where the hard block can run.
|
|
278
179
|
const TEAMMATE_PR_POLICY = `
|
|
279
180
|
|
|
280
181
|
Teammate PR policy (agents teams): when your work opens a pull request, open it and
|
|
@@ -285,23 +186,9 @@ does not count as a non-author review. \`gh pr merge\` on your own PR is blocked
|
|
|
285
186
|
merge-guard until a genuine non-author verdict exists on it; never pass --admin or
|
|
286
187
|
otherwise route around that guard. Report the PR as open and let the orchestrator
|
|
287
188
|
or a separate reviewer take it to merge.`;
|
|
288
|
-
/**
|
|
289
|
-
* Append {@link TEAMMATE_PR_POLICY} to a teammate prompt for every WRITE-capable
|
|
290
|
-
* mode (all but plan, which is read-only and opens no PR). Exported so the CLOUD
|
|
291
|
-
* dispatch path (`cloudDispatchOptions` in `commands/teams.ts`) applies the SAME
|
|
292
|
-
* boundary this file's `buildRunArgv` applies to LOCAL and REMOTE teammates. A
|
|
293
|
-
* cloud teammate is the case that needs it MOST: it runs in the provider's
|
|
294
|
-
* sandbox, not the shared local version home, so it never inherits the
|
|
295
|
-
* `merge-guard.sh` PreToolUse hook — the prompt policy is then its ONLY
|
|
296
|
-
* self-merge layer. Routing every dispatch surface through one helper keeps that
|
|
297
|
-
* parity from drifting (PHNX-3236).
|
|
298
|
-
*/
|
|
299
189
|
export function withTeammatePrPolicy(prompt, mode) {
|
|
300
190
|
return mode === 'plan' ? prompt : prompt + TEAMMATE_PR_POLICY;
|
|
301
191
|
}
|
|
302
|
-
// Canonical modes plus the historical `full` alias (rewritten to `skip` by
|
|
303
|
-
// normalizeModeValue). Keep `full` listed so user-typed CLI flags and stored
|
|
304
|
-
// metadata that pre-date the rename continue to parse.
|
|
305
192
|
export const VALID_MODES = ['plan', 'edit', 'auto', 'skip', 'full'];
|
|
306
193
|
function normalizeModeValue(modeValue) {
|
|
307
194
|
if (!modeValue)
|
|
@@ -370,7 +257,6 @@ function extractTimestamp(raw) {
|
|
|
370
257
|
}
|
|
371
258
|
return null;
|
|
372
259
|
}
|
|
373
|
-
/** Resolve a mode string to a validated Mode, falling back to the given default. */
|
|
374
260
|
export function resolveMode(requestedMode, defaultMode = 'plan') {
|
|
375
261
|
const normalizedDefault = normalizeModeValue(defaultMode);
|
|
376
262
|
if (!normalizedDefault) {
|
|
@@ -385,17 +271,6 @@ export function resolveMode(requestedMode, defaultMode = 'plan') {
|
|
|
385
271
|
}
|
|
386
272
|
return normalizedDefault;
|
|
387
273
|
}
|
|
388
|
-
/**
|
|
389
|
-
* Check whether the CLI binary for a given agent type is installed.
|
|
390
|
-
* Returns [available, pathOrError].
|
|
391
|
-
*
|
|
392
|
-
* The agents-managed shims dir (`~/.agents/.cache/shims`) is the canonical
|
|
393
|
-
* install location, so a shim there means installed regardless of the caller's
|
|
394
|
-
* PATH. Non-interactive callers — the menu-bar helper, cron, CI — run with a
|
|
395
|
-
* minimal launchd PATH that omits the shims dir; a bare PATH lookup false-flags
|
|
396
|
-
* every shim-based CLI as "not installed". Check the shim first, PATH second
|
|
397
|
-
* (for CLIs the user installed outside agents-cli).
|
|
398
|
-
*/
|
|
399
274
|
export function checkCliAvailable(agentType) {
|
|
400
275
|
const agent = agentType;
|
|
401
276
|
const executable = AGENTS[agent]?.cliCommand;
|
|
@@ -407,18 +282,12 @@ export function checkCliAvailable(agentType) {
|
|
|
407
282
|
if (!dispatch) {
|
|
408
283
|
return [false, `CLI tool '${executable}' not found in PATH. Install it first.`];
|
|
409
284
|
}
|
|
410
|
-
// A shim file (or a PATH entry) existing does NOT mean the agent is runnable:
|
|
411
|
-
// the managed default version's binary can be a stub or gutted (a partial/raced
|
|
412
|
-
// npm extract leaves the version dir + JS wrapper but no real binary). Verify
|
|
413
|
-
// the resolved default version is actually installed so `teams doctor` reports
|
|
414
|
-
// the truth instead of a false `installed: true` that ENOENTs at spawn.
|
|
415
285
|
const version = resolveVersion(agent);
|
|
416
286
|
if (version && !isVersionInstalled(agent, version)) {
|
|
417
287
|
return [false, `${executable}@${version} is not runnable — its binary is missing/incomplete. Repair: agents add ${agent}@${version}`];
|
|
418
288
|
}
|
|
419
289
|
return [true, dispatch];
|
|
420
290
|
}
|
|
421
|
-
/** Check availability of all known agent CLIs. Returns a map of agent type to install status. */
|
|
422
291
|
export function checkAllClis() {
|
|
423
292
|
const results = {};
|
|
424
293
|
for (const agentType of TEAM_AGENT_TYPES) {
|
|
@@ -449,29 +318,13 @@ export async function checkCliSignedIn(agentType) {
|
|
|
449
318
|
return false;
|
|
450
319
|
}
|
|
451
320
|
}
|
|
452
|
-
/**
|
|
453
|
-
* Resolve the advisory sign-in status shown by `teams doctor`. An agent that is
|
|
454
|
-
* currently RUNNING in a team is live proof it works, so it overrides a
|
|
455
|
-
* (frequently false-negative) sign-in probe — doctor must never report a
|
|
456
|
-
* working agent as logged out. Not installed → `signedIn: null` (nothing to
|
|
457
|
-
* probe). Never flips the authoritative installed/ready column.
|
|
458
|
-
*/
|
|
459
321
|
export function resolveSignInAdvisory(installed, running, probeSignedIn) {
|
|
460
322
|
if (!installed)
|
|
461
323
|
return { signedIn: null, running: false };
|
|
462
324
|
return { signedIn: running ? true : probeSignedIn, running };
|
|
463
325
|
}
|
|
464
|
-
/**
|
|
465
|
-
* Collect the same data `agents teams doctor` prints: per-agent install status,
|
|
466
|
-
* launch health, and advisory sign-in state. Kept in one place so `agents doctor
|
|
467
|
-
* --devices` can run it locally or compare it against remote JSON without
|
|
468
|
-
* duplicating the probe logic.
|
|
469
|
-
*/
|
|
470
326
|
export async function collectTeamsDoctorData() {
|
|
471
327
|
const info = checkAllClis();
|
|
472
|
-
// Deep integrity probe. `checkAllClis` reports presence (shim + stub guard),
|
|
473
|
-
// but a gutted native binary still passes that, so actually launch the default
|
|
474
|
-
// version and flip the agent to not-installed if it won't run.
|
|
475
328
|
await Promise.all(Object.entries(info).map(async ([name, entry]) => {
|
|
476
329
|
if (!entry.installed)
|
|
477
330
|
return;
|
|
@@ -487,15 +340,12 @@ export async function collectTeamsDoctorData() {
|
|
|
487
340
|
+ `${health.detail ? ` (${health.detail})` : ''}. Repair: agents add ${agent}@${version}`;
|
|
488
341
|
}
|
|
489
342
|
}));
|
|
490
|
-
// Advisory enrichment only. Sign-in detection is unreliable, so it never
|
|
491
|
-
// changes the authoritative installed/ready column — it annotates. A running
|
|
492
|
-
// teammate overrides a negative probe.
|
|
493
343
|
const running = new Set();
|
|
494
344
|
try {
|
|
495
345
|
for (const a of await new AgentManager().listRunning())
|
|
496
346
|
running.add(a.agentType);
|
|
497
347
|
}
|
|
498
|
-
catch {
|
|
348
|
+
catch { }
|
|
499
349
|
const result = {};
|
|
500
350
|
await Promise.all(Object.entries(info).map(async ([name, entry]) => {
|
|
501
351
|
const isRunning = running.has(name);
|
|
@@ -506,20 +356,12 @@ export async function collectTeamsDoctorData() {
|
|
|
506
356
|
return result;
|
|
507
357
|
}
|
|
508
358
|
let AGENTS_DIR = null;
|
|
509
|
-
/** Resolve and cache the base directory where teammate process data is stored. */
|
|
510
359
|
export async function getAgentsDir() {
|
|
511
360
|
if (!AGENTS_DIR) {
|
|
512
361
|
AGENTS_DIR = await resolveAgentsDir();
|
|
513
362
|
}
|
|
514
363
|
return AGENTS_DIR;
|
|
515
364
|
}
|
|
516
|
-
/**
|
|
517
|
-
* Represents a single teammate process within a team.
|
|
518
|
-
*
|
|
519
|
-
* Tracks process metadata (PID, status, timestamps), reads incremental
|
|
520
|
-
* stdout events, persists state to disk as meta.json, and can be
|
|
521
|
-
* reconstituted from disk via loadFromDisk().
|
|
522
|
-
*/
|
|
523
365
|
export class AgentProcess {
|
|
524
366
|
agentId;
|
|
525
367
|
taskName;
|
|
@@ -529,18 +371,11 @@ export class AgentProcess {
|
|
|
529
371
|
workspaceDir;
|
|
530
372
|
mode = 'plan';
|
|
531
373
|
pid = null;
|
|
532
|
-
// Captured at spawn time so we can detect PID reuse before signaling.
|
|
533
|
-
// Compared against the live /proc or `ps` value at every kill() call.
|
|
534
374
|
startTime = null;
|
|
535
375
|
status = AgentStatus.RUNNING;
|
|
536
376
|
startedAt = new Date();
|
|
537
377
|
completedAt = null;
|
|
538
378
|
parentSessionId = null;
|
|
539
|
-
// Frozen actor (resolveActor().id) this teammate runs under. Stamped onto the
|
|
540
|
-
// local spawn env via actorEnv (buildTeammateSpawnEnv) so the teammate's inner
|
|
541
|
-
// `agents run` inherits one actor for the whole tree instead of re-resolving,
|
|
542
|
-
// and persisted so the record shows who ran it. Set from the resolved actor at
|
|
543
|
-
// construction; loadFromDisk restores the persisted value.
|
|
544
379
|
actor = null;
|
|
545
380
|
cloudSessionId = null;
|
|
546
381
|
cloudProvider = null;
|
|
@@ -548,45 +383,17 @@ export class AgentProcess {
|
|
|
548
383
|
version = null;
|
|
549
384
|
remoteSessionId = null;
|
|
550
385
|
name = null;
|
|
551
|
-
// Names of teammates in the same team that this teammate is waiting on.
|
|
552
|
-
// Empty array = no deps = can run immediately. Populated by `teams add --after`.
|
|
553
386
|
after = [];
|
|
554
|
-
// Reasoning-intensity knob wired into buildReasoningFlags at launch time.
|
|
555
|
-
// Resolved late so config/effort-default changes between spawn and launch
|
|
556
|
-
// are honored for teammates staged via `teams add --after`.
|
|
557
387
|
effort = null;
|
|
558
|
-
// Pinned model for this teammate. When null, the agent's CLI picks its
|
|
559
|
-
// own default (no --model forwarded).
|
|
560
388
|
model = null;
|
|
561
|
-
// Profile target name when the teammate was added via `agents teams add
|
|
562
|
-
// <team> <profile>`. The launcher targets the profile name so env/keychain
|
|
563
|
-
// injection happens; agentType stays the underlying harness so event
|
|
564
|
-
// parsers and CLI availability checks keep working.
|
|
565
389
|
profileName = null;
|
|
566
|
-
// Extra env vars passed through to the child process (from --env KEY=VALUE).
|
|
567
390
|
envOverrides = null;
|
|
568
|
-
// Factory task-type label. Drives planner fan-out. Null for plain teammates — no behavioral change.
|
|
569
391
|
taskType = null;
|
|
570
|
-
// Repo/branch for cloud dispatches that stage behind --after. Captured
|
|
571
|
-
// at spawn time so startReady() can invoke the dispatcher with the same
|
|
572
|
-
// options the user originally supplied.
|
|
573
392
|
cloudRepo = null;
|
|
574
393
|
cloudBranch = null;
|
|
575
|
-
// Worktree isolation: when non-null, this teammate runs in its own git worktree.
|
|
576
394
|
worktreeName = null;
|
|
577
395
|
worktreePath = null;
|
|
578
|
-
// The team's `--project`, if it has one. Stored as the NAME, not as resolved
|
|
579
|
-
// directories: an unpinned teammate on a `--devices` pool is placed at LAUNCH
|
|
580
|
-
// (maybeSchedulePlacement), so grants resolved at add time would carry this
|
|
581
|
-
// box's absolute paths onto whatever host the scheduler later picked — and
|
|
582
|
-
// would already have dropped any directory that exists only there. Resolving
|
|
583
|
-
// per launch is what makes local and remote placement both correct.
|
|
584
396
|
project = null;
|
|
585
|
-
// Distributed teams: when hostName is non-null, this teammate runs on another
|
|
586
|
-
// machine over SSH (the "remote-host" backend), not as a local process. These
|
|
587
|
-
// are set post-construction (like startTime/pid) — placement config at add
|
|
588
|
-
// time (hostName/hostTarget/repoPath) and runtime handles at launch time
|
|
589
|
-
// (remotePid/remoteLog/remoteExit) — so the giant constructor stays untouched.
|
|
590
397
|
hostName = null;
|
|
591
398
|
hostTarget = null;
|
|
592
399
|
hostIdentityFile = null;
|
|
@@ -595,17 +402,7 @@ export class AgentProcess {
|
|
|
595
402
|
remoteLog = null;
|
|
596
403
|
remoteExit = null;
|
|
597
404
|
failure = null;
|
|
598
|
-
// Offset-tail cursor into the REMOTE log (bytes already pulled). Distinct from
|
|
599
|
-
// lastReadPos, which tracks the LOCAL mirror the parser consumes.
|
|
600
405
|
remoteLogOffset = 0;
|
|
601
|
-
// Per-wave batched-poll snapshot, refreshed each wave by the supervisor's
|
|
602
|
-
// one-ssh-per-host pre-pass (AgentManager.prefetchRemoteStatus) and read by
|
|
603
|
-
// isProcessAlive()/readNewEvents() so they skip their own SSH round-trip. It is
|
|
604
|
-
// set anew (and cleared for uncovered teammates) at the START of every prefetch,
|
|
605
|
-
// so it persists across BOTH poll passes within one wave (startReady's roster
|
|
606
|
-
// scan + the supervisor's listByTask) yet never carries into the next wave. Null
|
|
607
|
-
// outside a batched wave (e.g. a bare `teams status`), where a direct per-teammate
|
|
608
|
-
// SSH probe is the correctness fallback.
|
|
609
406
|
remotePollSnapshot = null;
|
|
610
407
|
eventsCache = [];
|
|
611
408
|
lastReadPos = 0;
|
|
@@ -643,18 +440,12 @@ export class AgentProcess {
|
|
|
643
440
|
this.version = version;
|
|
644
441
|
}
|
|
645
442
|
get isEditMode() {
|
|
646
|
-
// Any mode that can mutate the workspace counts as "edit mode" for the
|
|
647
|
-
// purposes of guarding read-only flows (plan-mode teammates).
|
|
648
443
|
return this.mode === 'edit' || this.mode === 'auto' || this.mode === 'skip';
|
|
649
444
|
}
|
|
650
445
|
async getAgentDir() {
|
|
651
446
|
const base = this.baseDir || await getAgentsDir();
|
|
652
447
|
return path.join(base, this.agentId);
|
|
653
448
|
}
|
|
654
|
-
/**
|
|
655
|
-
* Dump the subset of state the Ledger sync hook needs. Keeps sync.ts
|
|
656
|
-
* free of any teams-internal imports.
|
|
657
|
-
*/
|
|
658
449
|
async toSnapshot() {
|
|
659
450
|
return {
|
|
660
451
|
agent_id: this.agentId,
|
|
@@ -681,12 +472,6 @@ export class AgentProcess {
|
|
|
681
472
|
async getMetaPath() {
|
|
682
473
|
return path.join(await this.getAgentDir(), 'meta.json');
|
|
683
474
|
}
|
|
684
|
-
/**
|
|
685
|
-
* Path to the exit-code sentinel. The launcher wraps the teammate command in
|
|
686
|
-
* a shell that writes the underlying CLI's `$?` here once it exits. Detached
|
|
687
|
-
* teammates can't be wait()ed on by the parent, so this file is the only
|
|
688
|
-
* durable record of the real exit status — see reapProcess().
|
|
689
|
-
*/
|
|
690
475
|
async getExitCodePath() {
|
|
691
476
|
return path.join(await this.getAgentDir(), 'exit_code');
|
|
692
477
|
}
|
|
@@ -743,10 +528,6 @@ export class AgentProcess {
|
|
|
743
528
|
get events() {
|
|
744
529
|
return this.eventsCache;
|
|
745
530
|
}
|
|
746
|
-
/**
|
|
747
|
-
* Return the latest timestamp we have seen in the agent's events.
|
|
748
|
-
* Falls back to null when none are available.
|
|
749
|
-
*/
|
|
750
531
|
getLatestEventTime() {
|
|
751
532
|
let latest = null;
|
|
752
533
|
for (const event of this.eventsCache) {
|
|
@@ -762,33 +543,11 @@ export class AgentProcess {
|
|
|
762
543
|
}
|
|
763
544
|
return latest;
|
|
764
545
|
}
|
|
765
|
-
/**
|
|
766
|
-
* For a distributed (remote-host) teammate, pull NEW bytes of the host's log
|
|
767
|
-
* into the LOCAL mirror the parser consumes, advance the remote offset, and
|
|
768
|
-
* resolve terminal status from the remote `.exit` sentinel. Runs BEFORE the
|
|
769
|
-
* local read in readNewEvents(), so the existing stream-json parse path then
|
|
770
|
-
* runs unchanged over the freshly-mirrored bytes.
|
|
771
|
-
*
|
|
772
|
-
* Uses a per-wave batched snapshot (remotePollSnapshot) when the supervisor's
|
|
773
|
-
* one-ssh-per-host pre-pass populated it; otherwise falls back to its own
|
|
774
|
-
* round-trips so a bare `teams status`/`teams logs` is still correct.
|
|
775
|
-
*
|
|
776
|
-
* Only polls a teammate that is plausibly still RUNNING (RUSH-2118). Once a
|
|
777
|
-
* remote teammate reaches a terminal status, the poll that resolved it already
|
|
778
|
-
* mirrored the final log bytes and read the `.exit` sentinel in this SAME
|
|
779
|
-
* function (delta pulled before the exit check below) — the underlying process
|
|
780
|
-
* is gone and can never write more, so there is nothing left to fetch. Without
|
|
781
|
-
* this guard every finished remote teammate still cost one ssh round-trip on
|
|
782
|
-
* EVERY `--active`/`listAll` poll forever, which is what made `agents sessions
|
|
783
|
-
* --active --local` take ~4.3s on a box with 30 completed teammates.
|
|
784
|
-
*/
|
|
785
546
|
async syncRemoteMirror() {
|
|
786
547
|
if (!this.hostName || !this.hostTarget || !this.remoteLog)
|
|
787
548
|
return;
|
|
788
549
|
if (this.status !== AgentStatus.RUNNING)
|
|
789
550
|
return;
|
|
790
|
-
// Pull the new remote bytes and append them to the local mirror the parser
|
|
791
|
-
// reads. One offset-tail round-trip; nothing to write when the log is quiet.
|
|
792
551
|
const delta = pullRemoteLogDelta(this.hostTarget, {
|
|
793
552
|
remoteLog: this.remoteLog,
|
|
794
553
|
offset: this.remoteLogOffset,
|
|
@@ -801,19 +560,11 @@ export class AgentProcess {
|
|
|
801
560
|
this.remoteLogOffset = delta.newOffset;
|
|
802
561
|
}
|
|
803
562
|
catch {
|
|
804
|
-
// best-effort mirror — leave the offset unadvanced so we retry next poll
|
|
805
563
|
}
|
|
806
564
|
}
|
|
807
|
-
// Resolve terminal status from the host. Prefer this wave's batched snapshot;
|
|
808
|
-
// else probe this teammate directly. The snapshot is left in place (refreshed
|
|
809
|
-
// each wave by prefetch), so a second poll pass within the same wave reuses it.
|
|
810
565
|
const snap = this.remotePollSnapshot ?? (await this.probeRemoteLiveness());
|
|
811
566
|
if (!snap)
|
|
812
|
-
return;
|
|
813
|
-
// Only latch terminal on a PARSEABLE exit code. A `.exit` that exists but is
|
|
814
|
-
// momentarily empty (created, not yet written) or garbage must NOT force a
|
|
815
|
-
// spurious FAILED — leave the teammate RUNNING and let the next poll resolve
|
|
816
|
-
// it once the code lands.
|
|
567
|
+
return;
|
|
817
568
|
if (snap.exit !== null && snap.exit.trim() !== '' && this.status === AgentStatus.RUNNING) {
|
|
818
569
|
const code = Number.parseInt(snap.exit.trim(), 10);
|
|
819
570
|
if (Number.isFinite(code)) {
|
|
@@ -830,12 +581,6 @@ export class AgentProcess {
|
|
|
830
581
|
return;
|
|
831
582
|
}
|
|
832
583
|
}
|
|
833
|
-
// No exit code resolved it. If the remote process is GONE with NO sentinel at
|
|
834
|
-
// all, the wrapper died before recording `$?` (killed, box lost, OOM) — it can
|
|
835
|
-
// never write a code, so this teammate is FAILED, not "running forever"
|
|
836
|
-
// (RUSH-2366). This is the remote analog of reapProcess()'s "sentinel absent
|
|
837
|
-
// -> 1 -> FAILED". An EXITED-but-empty `.exit` (wrapper mid-write) is left
|
|
838
|
-
// RUNNING above precisely so this branch does not misfire on that race.
|
|
839
584
|
if (this.status === AgentStatus.RUNNING && !snap.alive && !snap.exitFilePresent) {
|
|
840
585
|
this.status = AgentStatus.FAILED;
|
|
841
586
|
this.failure = {
|
|
@@ -847,12 +592,6 @@ export class AgentProcess {
|
|
|
847
592
|
this.completedAt = this.getLatestEventTime() || this.startedAt || new Date();
|
|
848
593
|
}
|
|
849
594
|
}
|
|
850
|
-
/**
|
|
851
|
-
* One-shot direct liveness probe for a single remote teammate — the fallback
|
|
852
|
-
* used outside a batched supervisor wave (a bare `teams status`, `mgr.get()`
|
|
853
|
-
* for `teams resume`). Returns null on a transient ssh failure so the caller
|
|
854
|
-
* leaves the teammate RUNNING rather than reaping it on a dropped connection.
|
|
855
|
-
*/
|
|
856
595
|
async probeRemoteLiveness() {
|
|
857
596
|
if (!this.hostTarget || !this.remotePid || !this.remoteExit)
|
|
858
597
|
return null;
|
|
@@ -862,7 +601,7 @@ export class AgentProcess {
|
|
|
862
601
|
extraSshArgs: this.hostIdentityFile ? ['-i', this.hostIdentityFile, '-o', 'IdentitiesOnly=yes'] : [],
|
|
863
602
|
});
|
|
864
603
|
if (res.code === null)
|
|
865
|
-
return null;
|
|
604
|
+
return null;
|
|
866
605
|
const trimmed = res.stdout.trim();
|
|
867
606
|
if (!trimmed)
|
|
868
607
|
return null;
|
|
@@ -871,27 +610,17 @@ export class AgentProcess {
|
|
|
871
610
|
return null;
|
|
872
611
|
return parseRemoteLivenessState(state, code);
|
|
873
612
|
}
|
|
874
|
-
/** Reset the local stdout cursor for a newly truncated resume log. */
|
|
875
613
|
resetLogReadPosition() {
|
|
876
614
|
const previous = this.lastReadPos;
|
|
877
615
|
this.lastReadPos = 0;
|
|
878
616
|
return previous;
|
|
879
617
|
}
|
|
880
|
-
/** Restore the cursor when a resume transaction puts the prior log back. */
|
|
881
618
|
restoreLogReadPosition(position) {
|
|
882
619
|
this.lastReadPos = position;
|
|
883
620
|
}
|
|
884
|
-
/**
|
|
885
|
-
* @param opts.skipRemote A `--local` caller (RUSH-2118): never dial a
|
|
886
|
-
* remote-host teammate, not even a still-RUNNING one — report its
|
|
887
|
-
* last-persisted meta.json state as-is. A local-only query is by definition
|
|
888
|
-
* this-machine-only, so it must not issue an ssh round-trip at all.
|
|
889
|
-
*/
|
|
890
621
|
async readNewEvents(opts = {}) {
|
|
891
622
|
if (this.hostName && opts.skipRemote)
|
|
892
623
|
return;
|
|
893
|
-
// Distributed teammate: mirror the host's new log bytes locally first, then
|
|
894
|
-
// fall through to the identical local read+parse below.
|
|
895
624
|
if (this.hostName) {
|
|
896
625
|
await this.syncRemoteMirror();
|
|
897
626
|
}
|
|
@@ -918,11 +647,6 @@ export class AgentProcess {
|
|
|
918
647
|
for (const event of events) {
|
|
919
648
|
event.timestamp = resolvedTimestamp;
|
|
920
649
|
this.eventsCache.push(event);
|
|
921
|
-
// Capture the agent's own session/thread id the first time we see
|
|
922
|
-
// it. For Claude it's the same uuid we passed via --session-id;
|
|
923
|
-
// for others (Codex thread_id, Gemini/Cursor/OpenCode sessionID)
|
|
924
|
-
// it's their internal id, which lets us cross-reference with
|
|
925
|
-
// `agents sessions <id>`.
|
|
926
650
|
if (!this.remoteSessionId && event.session_id) {
|
|
927
651
|
this.remoteSessionId = event.session_id;
|
|
928
652
|
}
|
|
@@ -955,20 +679,11 @@ export class AgentProcess {
|
|
|
955
679
|
catch (err) {
|
|
956
680
|
console.error(`Error reading events for agent ${this.agentId}:`, err);
|
|
957
681
|
}
|
|
958
|
-
// Distributed teammate: keep the orchestrator bounded across 10+ remote
|
|
959
|
-
// teammates. The parser has already consumed everything up to lastReadPos
|
|
960
|
-
// (status/digest updated), so both the on-disk mirror tail and the in-memory
|
|
961
|
-
// event backlog are safe to trim. The host keeps the full log.
|
|
962
682
|
if (this.hostName) {
|
|
963
683
|
await this.capMirrorToTail();
|
|
964
684
|
this.capEventsCache();
|
|
965
685
|
}
|
|
966
686
|
}
|
|
967
|
-
/**
|
|
968
|
-
* Truncate the local mirror to its trailing REMOTE_MIRROR_MAX_BYTES and reset
|
|
969
|
-
* lastReadPos to the new (smaller) size so the parser doesn't re-read the kept
|
|
970
|
-
* tail. Only trims when over the cap — a normal-length log is untouched.
|
|
971
|
-
*/
|
|
972
687
|
async capMirrorToTail() {
|
|
973
688
|
const stdoutPath = await this.getStdoutPath();
|
|
974
689
|
try {
|
|
@@ -981,24 +696,12 @@ export class AgentProcess {
|
|
|
981
696
|
const { bytesRead } = await fd.read(buf, 0, keep, stats.size - keep);
|
|
982
697
|
await fd.close();
|
|
983
698
|
await fs.writeFile(stdoutPath, buf.subarray(0, bytesRead));
|
|
984
|
-
// The parser consumed up to lastReadPos already; after truncation the file
|
|
985
|
-
// is `bytesRead` long, so clamp the cursor to the new EOF. It never needs
|
|
986
|
-
// to re-read the retained tail (events already cached).
|
|
987
699
|
this.lastReadPos = Math.min(this.lastReadPos, bytesRead);
|
|
988
700
|
}
|
|
989
701
|
catch {
|
|
990
|
-
// best-effort — a failed cap just leaves the mirror larger this wave
|
|
991
702
|
}
|
|
992
703
|
}
|
|
993
|
-
/** Cap on the in-memory event backlog kept per remote teammate. */
|
|
994
704
|
static REMOTE_EVENTS_MAX = 200;
|
|
995
|
-
/**
|
|
996
|
-
* Drop the oldest cached events for a remote teammate once past the cap. The
|
|
997
|
-
* status path only needs recent events (last N messages, recentToolCalls,
|
|
998
|
-
* terminal status) and the getDelta cursor filters by timestamp, so a bounded
|
|
999
|
-
* recent window preserves the digest while bounding the heap. Terminal status
|
|
1000
|
-
* is already latched onto `this.status`, so trimming can't lose it.
|
|
1001
|
-
*/
|
|
1002
705
|
capEventsCache() {
|
|
1003
706
|
const max = AgentProcess.REMOTE_EVENTS_MAX;
|
|
1004
707
|
if (this.eventsCache.length > max) {
|
|
@@ -1006,14 +709,6 @@ export class AgentProcess {
|
|
|
1006
709
|
}
|
|
1007
710
|
}
|
|
1008
711
|
async saveMeta() {
|
|
1009
|
-
// RUSH-2450: a long-lived supervisor (teams start --watch) holds AgentProcess
|
|
1010
|
-
// objects in memory. After another process disbands the team and deletes
|
|
1011
|
-
// every meta.json, the supervisor's next status refresh would re-write those
|
|
1012
|
-
// files via saveMeta — resurrecting PENDING teammates the operator just
|
|
1013
|
-
// disbanded, and making `teams start` re-launch already-merged work. Refuse
|
|
1014
|
-
// when a disband tombstone is present (set by removeTeam / markTeamDisbanded).
|
|
1015
|
-
// Not gated on "team not in registry" alone: tests and mid-add paths write
|
|
1016
|
-
// meta before/without a registry entry, and those must keep working.
|
|
1017
712
|
if (this.taskName && (await isTeamDisbanded(this.taskName))) {
|
|
1018
713
|
debug(`saveMeta: refusing to re-persist ${this.agentId} — team '${this.taskName}' was disbanded`);
|
|
1019
714
|
return;
|
|
@@ -1065,25 +760,6 @@ export class AgentProcess {
|
|
|
1065
760
|
const metaPath = await this.getMetaPath();
|
|
1066
761
|
atomicWriteJsonSync(metaPath, meta);
|
|
1067
762
|
}
|
|
1068
|
-
/**
|
|
1069
|
-
* Rename an unreadable meta.json out of the way so it stops silently
|
|
1070
|
-
* masquerading as "no record" (RUSH-2429). Before saveMeta() wrote atomically,
|
|
1071
|
-
* a process killed mid-write left a truncated, unparseable meta.json that
|
|
1072
|
-
* loadFromDisk() returned null for -- indistinguishable from ENOENT -- so
|
|
1073
|
-
* retention (loadExistingAgents/rescanFromDisk) never reaped it and
|
|
1074
|
-
* isWorktreeClaimed() (which reads meta.json directly, not through this
|
|
1075
|
-
* method) failed CLOSED on it forever: it scans every record and answers
|
|
1076
|
-
* "claimed" for every worktree name in every team the first time it cannot
|
|
1077
|
-
* read one. Quarantining removes meta.json so the NEXT read of this record
|
|
1078
|
-
* sees ENOENT (genuinely absent) instead of "unreadable" -- that is what lets
|
|
1079
|
-
* isWorktreeClaimed's fail-closed guard recover once the corrupt record is
|
|
1080
|
-
* gone, without weakening the guard itself for a record that is still
|
|
1081
|
-
* present-but-unreadable at decision time.
|
|
1082
|
-
*
|
|
1083
|
-
* Best-effort: if the rename itself fails (e.g. EACCES on the directory),
|
|
1084
|
-
* the record is left in place and the fail-closed guard keeps protecting
|
|
1085
|
-
* worktree removal -- quarantine only ever ADDS a recovery path.
|
|
1086
|
-
*/
|
|
1087
763
|
static async quarantineCorruptMeta(metaPath, cause) {
|
|
1088
764
|
const quarantinePath = `${metaPath}.corrupt`;
|
|
1089
765
|
const reason = cause instanceof Error ? cause.message : String(cause);
|
|
@@ -1105,36 +781,20 @@ export class AgentProcess {
|
|
|
1105
781
|
metaContent = await fs.readFile(metaPath, 'utf-8');
|
|
1106
782
|
}
|
|
1107
783
|
catch (err) {
|
|
1108
|
-
// A READ error is not a corrupt record. ENOENT proves the record is
|
|
1109
|
-
// genuinely ABSENT; anything else -- EACCES, EIO, a transient EMFILE
|
|
1110
|
-
// under fd pressure -- means the file exists and could not be read THIS
|
|
1111
|
-
// time, but its contents are intact. We MUST NOT quarantine (rename) it:
|
|
1112
|
-
// renaming a valid record away is exactly the fail-open that RUSH-2429
|
|
1113
|
-
// forbids -- isWorktreeClaimed() reads meta.json directly and fails
|
|
1114
|
-
// CLOSED on the same read error (safe), but a rename here would delete
|
|
1115
|
-
// the record it relies on and turn a live teammate's worktree into
|
|
1116
|
-
// "unclaimed", re-arming `git worktree remove --force` over uncommitted
|
|
1117
|
-
// work. Return null (skip this scan); the file stays for the next read.
|
|
1118
784
|
return null;
|
|
1119
785
|
}
|
|
1120
786
|
try {
|
|
1121
787
|
const meta = JSON.parse(metaContent);
|
|
1122
|
-
// Legacy teammates may have mode='ralph', 'cloud', or 'full' from before
|
|
1123
|
-
// modes were narrowed/renamed. Coerce to the closest current mode so they
|
|
1124
|
-
// still load.
|
|
1125
788
|
const modeMap = {
|
|
1126
789
|
plan: 'plan',
|
|
1127
790
|
edit: 'edit',
|
|
1128
791
|
auto: 'auto',
|
|
1129
792
|
skip: 'skip',
|
|
1130
|
-
full: 'skip',
|
|
1131
|
-
ralph: 'skip',
|
|
1132
|
-
cloud: 'edit',
|
|
793
|
+
full: 'skip',
|
|
794
|
+
ralph: 'skip',
|
|
795
|
+
cloud: 'edit',
|
|
1133
796
|
};
|
|
1134
797
|
const resolvedMode = modeMap[meta.mode] || 'plan';
|
|
1135
|
-
// AgentStatus is a string enum. Validate meta.status against its VALUES
|
|
1136
|
-
// (not its keys) — `AgentStatus["pending"]` is undefined but
|
|
1137
|
-
// `AgentStatus.PENDING === "pending"` works.
|
|
1138
798
|
const validStatuses = Object.values(AgentStatus);
|
|
1139
799
|
const resolvedStatus = validStatuses.includes(meta.status)
|
|
1140
800
|
? meta.status
|
|
@@ -1143,12 +803,7 @@ export class AgentProcess {
|
|
|
1143
803
|
? meta.task_type
|
|
1144
804
|
: null, meta.cloud_repo || null, meta.cloud_branch || null, meta.worktree_name || null, meta.worktree_path || null, meta.profile_name || null);
|
|
1145
805
|
agent.startTime = typeof meta.start_time === 'string' ? meta.start_time : null;
|
|
1146
|
-
// The persisted actor is the truth for a reload; the constructor set it to
|
|
1147
|
-
// THIS process's resolved actor, which is wrong for a teammate someone else
|
|
1148
|
-
// ran. Legacy teammates predating the field carry no actor -> null.
|
|
1149
806
|
agent.actor = meta.actor ?? null;
|
|
1150
|
-
// Distributed-team fields: set post-construction (like startTime) so the
|
|
1151
|
-
// constructor signature stays fixed. Null on every pre-existing teammate.
|
|
1152
807
|
agent.hostName = meta.host_name || null;
|
|
1153
808
|
agent.hostTarget = meta.host_target || null;
|
|
1154
809
|
agent.hostIdentityFile = meta.host_identity_file || null;
|
|
@@ -1167,33 +822,20 @@ export class AgentProcess {
|
|
|
1167
822
|
observed_at: String(meta.failure.observed_at),
|
|
1168
823
|
}
|
|
1169
824
|
: null;
|
|
1170
|
-
// The team's project. Absent on every teammate added before `--project`.
|
|
1171
825
|
agent.project = typeof meta.project === 'string' ? meta.project : null;
|
|
1172
826
|
return agent;
|
|
1173
827
|
}
|
|
1174
828
|
catch (err) {
|
|
1175
|
-
// The file exists but is not valid JSON (or fails a constructor
|
|
1176
|
-
// invariant) -- most likely a torn write from before saveMeta() became
|
|
1177
|
-
// atomic. Quarantine it; see quarantineCorruptMeta() above.
|
|
1178
829
|
await AgentProcess.quarantineCorruptMeta(metaPath, err);
|
|
1179
830
|
return null;
|
|
1180
831
|
}
|
|
1181
832
|
}
|
|
1182
833
|
isProcessAlive() {
|
|
1183
|
-
// Distributed teammate: a local PID is meaningless. Alive = the remote `.exit`
|
|
1184
|
-
// sentinel is absent AND `kill -0 <remotePid>` succeeds on the host, resolved
|
|
1185
|
-
// in a single ssh round-trip. Prefer the supervisor's batched snapshot when
|
|
1186
|
-
// present (consume it once so it can't go stale); otherwise probe directly.
|
|
1187
834
|
if (this.hostName) {
|
|
1188
|
-
// Prefer this wave's batched snapshot (persists across the wave's poll
|
|
1189
|
-
// passes; the supervisor refreshes it each wave). Fall back to a direct
|
|
1190
|
-
// probe outside a wave.
|
|
1191
835
|
if (this.remotePollSnapshot)
|
|
1192
836
|
return this.remotePollSnapshot.alive;
|
|
1193
837
|
if (!this.hostTarget || !this.remotePid || !this.remoteExit)
|
|
1194
838
|
return false;
|
|
1195
|
-
// remoteExit is a dispatch `$HOME/.agents/.cache/hosts/<hex>.exit` path —
|
|
1196
|
-
// interpolate UNQUOTED so `$HOME` expands (shellQuote would defeat it).
|
|
1197
839
|
const probe = `test -f ${this.remoteExit} && echo DEAD || ` +
|
|
1198
840
|
`(kill -0 ${this.remotePid} 2>/dev/null && echo ALIVE || echo DEAD)`;
|
|
1199
841
|
const res = sshExec(this.hostTarget, probe, {
|
|
@@ -1202,7 +844,7 @@ export class AgentProcess {
|
|
|
1202
844
|
extraSshArgs: this.hostIdentityFile ? ['-i', this.hostIdentityFile, '-o', 'IdentitiesOnly=yes'] : [],
|
|
1203
845
|
});
|
|
1204
846
|
if (res.code === null)
|
|
1205
|
-
return true;
|
|
847
|
+
return true;
|
|
1206
848
|
return res.stdout.trim().endsWith('ALIVE');
|
|
1207
849
|
}
|
|
1208
850
|
if (!this.pid)
|
|
@@ -1213,11 +855,6 @@ export class AgentProcess {
|
|
|
1213
855
|
catch {
|
|
1214
856
|
return false;
|
|
1215
857
|
}
|
|
1216
|
-
// PID is occupied — but is it still OUR process? If we captured a
|
|
1217
|
-
// start-time at spawn, refuse to claim aliveness when the live value
|
|
1218
|
-
// differs. A null startTime means we never captured one (legacy
|
|
1219
|
-
// teammates loaded from disk before this field existed) — fall back to
|
|
1220
|
-
// the bare kill(pid, 0) result for those.
|
|
1221
858
|
if (this.startTime !== null) {
|
|
1222
859
|
const current = captureProcessStartTime(this.pid);
|
|
1223
860
|
if (current === null || current !== this.startTime) {
|
|
@@ -1226,12 +863,6 @@ export class AgentProcess {
|
|
|
1226
863
|
}
|
|
1227
864
|
return true;
|
|
1228
865
|
}
|
|
1229
|
-
/**
|
|
1230
|
-
* Read just the persisted status + completion time from meta.json, without
|
|
1231
|
-
* reconstructing the whole teammate. Returns null when there is no readable
|
|
1232
|
-
* record on disk. Used to detect that ANOTHER process (a `teams stop`, a
|
|
1233
|
-
* sibling supervisor) has already moved this teammate to a terminal status.
|
|
1234
|
-
*/
|
|
1235
866
|
async readDiskStatus() {
|
|
1236
867
|
let raw;
|
|
1237
868
|
try {
|
|
@@ -1253,16 +884,6 @@ export class AgentProcess {
|
|
|
1253
884
|
return null;
|
|
1254
885
|
}
|
|
1255
886
|
}
|
|
1256
|
-
/**
|
|
1257
|
-
* If this in-memory teammate is still non-terminal but disk already shows a
|
|
1258
|
-
* terminal status, adopt the disk state. Returns true when it did.
|
|
1259
|
-
*
|
|
1260
|
-
* This is the guard against the stale-manager race (RUSH-2366): a long-lived
|
|
1261
|
-
* supervisor holding a teammate as `running` must never re-persist that stale
|
|
1262
|
-
* `running` over a `stopped`/`failed`/`completed` another process just wrote
|
|
1263
|
-
* (e.g. an explicit `teams stop` in a separate CLI invocation). A terminal
|
|
1264
|
-
* status is a one-way latch, so disk-terminal always wins over memory-running.
|
|
1265
|
-
*/
|
|
1266
887
|
async adoptDiskTerminalIfNewer() {
|
|
1267
888
|
if (isTerminalStatus(this.status))
|
|
1268
889
|
return false;
|
|
@@ -1273,33 +894,13 @@ export class AgentProcess {
|
|
|
1273
894
|
this.completedAt = disk.completedAt ?? this.completedAt ?? new Date();
|
|
1274
895
|
return true;
|
|
1275
896
|
}
|
|
1276
|
-
/**
|
|
1277
|
-
* @param opts.skipRemote A `--local` caller (RUSH-2118): a distributed
|
|
1278
|
-
* teammate is never dialed — its in-memory state (already loaded from
|
|
1279
|
-
* meta.json) stands as-is, no ssh, no re-save.
|
|
1280
|
-
*/
|
|
1281
897
|
async updateStatusFromProcess(opts = {}) {
|
|
1282
|
-
// Stale-manager guard (RUSH-2366): if disk has already latched this teammate
|
|
1283
|
-
// terminal, adopt that and stop — a poll of a process that no longer exists
|
|
1284
|
-
// must not re-persist `running` over the newer on-disk terminal status.
|
|
1285
898
|
if (await this.adoptDiskTerminalIfNewer())
|
|
1286
899
|
return;
|
|
1287
900
|
if (!this.pid) {
|
|
1288
|
-
// Distributed (remote-host) teammates have no local PID by design; their
|
|
1289
|
-
// lifecycle lives on the host. readNewEvents() mirrors the remote log and
|
|
1290
|
-
// resolves terminal status from the remote `.exit` sentinel (see
|
|
1291
|
-
// syncRemoteMirror), so we just persist and return — never the local
|
|
1292
|
-
// "RUNNING without a PID is impossible" fail path below.
|
|
1293
901
|
if (this.hostName) {
|
|
1294
902
|
if (opts.skipRemote)
|
|
1295
903
|
return;
|
|
1296
|
-
// Staged (--after) distributed teammates also have hostName set but no
|
|
1297
|
-
// PID yet (RUSH-2356 sibling bug): without this guard the `!== RUNNING`
|
|
1298
|
-
// fallback below stamps a completedAt on a teammate that hasn't even
|
|
1299
|
-
// launched, which the age-based reap in loadExistingAgents() would
|
|
1300
|
-
// later delete outright once it aged past cleanupAgeDays. Leave it
|
|
1301
|
-
// alone until startReady() launches it — matches the local-only guard
|
|
1302
|
-
// further below.
|
|
1303
904
|
if (this.status === AgentStatus.PENDING)
|
|
1304
905
|
return;
|
|
1305
906
|
await this.readNewEvents();
|
|
@@ -1310,11 +911,7 @@ export class AgentProcess {
|
|
|
1310
911
|
return;
|
|
1311
912
|
}
|
|
1312
913
|
await this.readNewEvents();
|
|
1313
|
-
// Cloud-backed teammates have no local PID by design; their lifecycle
|
|
1314
|
-
// is driven by the remote provider instead of a local process.
|
|
1315
914
|
if (this.cloudProvider) {
|
|
1316
|
-
// Same staged-teammate guard as the hostName branch above — a staged
|
|
1317
|
-
// cloud teammate is PENDING with no PID until its deps resolve.
|
|
1318
915
|
if (this.status === AgentStatus.PENDING)
|
|
1319
916
|
return;
|
|
1320
917
|
if (!this.completedAt && this.status !== AgentStatus.RUNNING) {
|
|
@@ -1324,15 +921,9 @@ export class AgentProcess {
|
|
|
1324
921
|
}
|
|
1325
922
|
return;
|
|
1326
923
|
}
|
|
1327
|
-
// Pending teammates with unresolved --after deps also have no PID yet.
|
|
1328
|
-
// Leave them alone until startReady() launches them.
|
|
1329
924
|
if (this.status === AgentStatus.PENDING) {
|
|
1330
925
|
return;
|
|
1331
926
|
}
|
|
1332
|
-
// A local teammate marked RUNNING without a PID is an impossible state:
|
|
1333
|
-
// launch never produced a durable process identity, so it cannot still
|
|
1334
|
-
// be doing work. Keep any terminal event parsed from stdout; otherwise
|
|
1335
|
-
// fail it and stamp completion so team rollups stop showing it as live.
|
|
1336
927
|
if (this.status === AgentStatus.RUNNING) {
|
|
1337
928
|
const fallbackCompletion = this.getLatestEventTime() || this.startedAt || new Date();
|
|
1338
929
|
if (this.status === AgentStatus.RUNNING) {
|
|
@@ -1389,28 +980,9 @@ export class AgentProcess {
|
|
|
1389
980
|
}
|
|
1390
981
|
await this.saveMeta();
|
|
1391
982
|
}
|
|
1392
|
-
/**
|
|
1393
|
-
* Recover the teammate's exit status after its process is gone.
|
|
1394
|
-
*
|
|
1395
|
-
* The teammate is spawned detached + unref()'d (see launchProcess), so the
|
|
1396
|
-
* parent never gets the child's exit code from the OS. Instead the launcher
|
|
1397
|
-
* wraps the command in a shell that records `$?` to the exit-code sentinel.
|
|
1398
|
-
* This reads that file:
|
|
1399
|
-
* - still alive -> null (no verdict yet)
|
|
1400
|
-
* - sentinel present -> the real exit code (0 = success)
|
|
1401
|
-
* - sentinel absent -> 1 (the shell was killed before it could write
|
|
1402
|
-
* it, e.g. SIGKILL on timeout/stop — a real
|
|
1403
|
-
* failure)
|
|
1404
|
-
*
|
|
1405
|
-
* Returning a real code (not a hardcoded 1) is what lets agents whose stream
|
|
1406
|
-
* never emits a parsed terminal event — kimi, antigravity, droid — be marked
|
|
1407
|
-
* completed on success instead of falsely failed.
|
|
1408
|
-
*/
|
|
1409
983
|
async reapProcess() {
|
|
1410
984
|
if (!this.pid)
|
|
1411
985
|
return null;
|
|
1412
|
-
// isProcessAlive() applies the start-time guard, so a recycled PID now
|
|
1413
|
-
// owned by an unrelated process doesn't read as still-alive.
|
|
1414
986
|
if (this.isProcessAlive())
|
|
1415
987
|
return null;
|
|
1416
988
|
try {
|
|
@@ -1419,24 +991,10 @@ export class AgentProcess {
|
|
|
1419
991
|
return { code: Number.isNaN(code) ? 1 : code, sentinelPresent: true };
|
|
1420
992
|
}
|
|
1421
993
|
catch {
|
|
1422
|
-
// No sentinel: the shell died before recording $? (killed mid-run).
|
|
1423
994
|
return { code: 1, sentinelPresent: false };
|
|
1424
995
|
}
|
|
1425
996
|
}
|
|
1426
997
|
}
|
|
1427
|
-
/**
|
|
1428
|
-
* The directories, beyond its cwd, a teammate may reach because of the team's
|
|
1429
|
-
* `--project`. Resolved at LAUNCH, from the project name on the record.
|
|
1430
|
-
*
|
|
1431
|
-
* Resolving here rather than at `teams add` is load-bearing for a pooled team:
|
|
1432
|
-
* an unpinned teammate has no host until `maybeSchedulePlacement` runs, so add
|
|
1433
|
-
* time cannot know whether to produce absolute local paths or `~/…` — and the
|
|
1434
|
-
* local form would additionally have dropped any directory that exists only on
|
|
1435
|
-
* the host it later landed on.
|
|
1436
|
-
*
|
|
1437
|
-
* A project that no longer resolves (renamed, definition deleted) yields no
|
|
1438
|
-
* grants rather than failing the launch: the teammate still gets its cwd.
|
|
1439
|
-
*/
|
|
1440
998
|
async function resolveTeammateGrants(agent, opts) {
|
|
1441
999
|
if (!agent.project)
|
|
1442
1000
|
return [];
|
|
@@ -1446,8 +1004,6 @@ async function resolveTeammateGrants(agent, opts) {
|
|
|
1446
1004
|
return extraDirs;
|
|
1447
1005
|
}
|
|
1448
1006
|
catch (err) {
|
|
1449
|
-
// Degrading is deliberate, but silently degrading is not: a teammate that
|
|
1450
|
-
// lost its grants to a renamed or deleted definition should leave a trace.
|
|
1451
1007
|
debug(`teammate ${agent.agentId}: project '${agent.project}' did not resolve, no grants: ${err.message}`);
|
|
1452
1008
|
return [];
|
|
1453
1009
|
}
|
|
@@ -1517,21 +1073,8 @@ export class AgentManager {
|
|
|
1517
1073
|
defaultMode;
|
|
1518
1074
|
initPromise = null;
|
|
1519
1075
|
cloudDispatcher = null;
|
|
1520
|
-
/**
|
|
1521
|
-
* A `--local` caller (RUSH-2118): every poll this manager issues skips the
|
|
1522
|
-
* ssh round-trip for a distributed (remote-host) teammate, reporting its
|
|
1523
|
-
* last-persisted meta.json state instead. Set once at construction so the
|
|
1524
|
-
* INITIAL load in doInitialize()/loadExistingAgents() — which polls every
|
|
1525
|
-
* teammate before listRunning()/listAll() ever run — honors it too.
|
|
1526
|
-
*/
|
|
1527
1076
|
localOnly;
|
|
1528
1077
|
constructorAgentsDir = null;
|
|
1529
|
-
/**
|
|
1530
|
-
* One-shot memo of the last `validateAddPreconditions` result, so the
|
|
1531
|
-
* command-layer pre-worktree call and spawn()'s own call don't each pay a
|
|
1532
|
-
* full `listAll()` status refresh (a round of SSH probes on a `--device`
|
|
1533
|
-
* team). Consumed by the first matching call — see that method.
|
|
1534
|
-
*/
|
|
1535
1078
|
validatedAdd = null;
|
|
1536
1079
|
constructor(maxAgents = 50, agentsDir = null, defaultMode = null, filterByCwd = null, cleanupAgeDays = 7, localOnly = false) {
|
|
1537
1080
|
this.maxAgents = maxAgents;
|
|
@@ -1545,14 +1088,6 @@ export class AgentManager {
|
|
|
1545
1088
|
}
|
|
1546
1089
|
this.defaultMode = resolvedDefaultMode;
|
|
1547
1090
|
this.initPromise = this.doInitialize();
|
|
1548
|
-
// Mark the deferred rejection as observed. Construction fires init
|
|
1549
|
-
// fire-and-forget; every public method still surfaces a failed init at its
|
|
1550
|
-
// own `await this.initialize()` (the same promise rejects for each new
|
|
1551
|
-
// awaiter). Without this, an init that loses a race with its directory
|
|
1552
|
-
// being removed — measured twice as an unhandled
|
|
1553
|
-
// `ENOENT mkdir /tmp/agents-retention-*` that failed a fully-green suite
|
|
1554
|
-
// (exit 1 with 12k tests passed) and blocked release attestation — crashes
|
|
1555
|
-
// the process instead of failing the caller that actually cares.
|
|
1556
1091
|
this.initPromise.catch(() => { });
|
|
1557
1092
|
}
|
|
1558
1093
|
async initialize() {
|
|
@@ -1569,10 +1104,6 @@ export class AgentManager {
|
|
|
1569
1104
|
getDefaultMode() {
|
|
1570
1105
|
return this.defaultMode;
|
|
1571
1106
|
}
|
|
1572
|
-
/**
|
|
1573
|
-
* Register the callback used to dispatch cloud-backed teammates when their
|
|
1574
|
-
* --after deps resolve. Called once at CLI startup by `agents teams`.
|
|
1575
|
-
*/
|
|
1576
1107
|
setCloudDispatcher(fn) {
|
|
1577
1108
|
this.cloudDispatcher = fn;
|
|
1578
1109
|
}
|
|
@@ -1599,20 +1130,6 @@ export class AgentManager {
|
|
|
1599
1130
|
agent.completedAt = null;
|
|
1600
1131
|
await agent.saveMeta();
|
|
1601
1132
|
}
|
|
1602
|
-
/**
|
|
1603
|
-
* Scan the agents dir for meta.json files not already in the in-memory
|
|
1604
|
-
* cache and load them. Needed when another process (e.g. a Planner
|
|
1605
|
-
* teammate running `agents teams add`) creates new teammates while this
|
|
1606
|
-
* manager is alive — the supervisor loop calls this each wave so
|
|
1607
|
-
* dynamically-added teammates get picked up.
|
|
1608
|
-
*
|
|
1609
|
-
* For a teammate ALREADY cached, refreshes it only when disk has latched it
|
|
1610
|
-
* terminal while the cache still holds it non-terminal — the case where
|
|
1611
|
-
* another process (e.g. `agents teams stop` in a separate CLI invocation)
|
|
1612
|
-
* moved it to `stopped`/`failed` and this long-lived manager would otherwise
|
|
1613
|
-
* never see it and re-persist a stale `running` (RUSH-2366). A still-live
|
|
1614
|
-
* cached teammate is left untouched; updateStatusFromProcess() owns that path.
|
|
1615
|
-
*/
|
|
1616
1133
|
async rescanFromDisk() {
|
|
1617
1134
|
await this.initialize();
|
|
1618
1135
|
try {
|
|
@@ -1630,9 +1147,6 @@ export class AgentManager {
|
|
|
1630
1147
|
continue;
|
|
1631
1148
|
const cached = this.agents.get(entry);
|
|
1632
1149
|
if (cached) {
|
|
1633
|
-
// Adopt a disk-terminal status the cache hasn't seen; never overwrite a
|
|
1634
|
-
// cached teammate that is still live with a stale disk read. Terminal is
|
|
1635
|
-
// a one-way latch, so this can only move a teammate forward.
|
|
1636
1150
|
if (!isTerminalStatus(cached.status)) {
|
|
1637
1151
|
const fresh = await AgentProcess.loadFromDisk(entry, this.agentsDir);
|
|
1638
1152
|
if (fresh && isTerminalStatus(fresh.status)) {
|
|
@@ -1672,12 +1186,6 @@ export class AgentManager {
|
|
|
1672
1186
|
const agent = await AgentProcess.loadFromDisk(agentId, this.agentsDir);
|
|
1673
1187
|
if (!agent)
|
|
1674
1188
|
continue;
|
|
1675
|
-
// Age-based reap is a SECOND retention mechanism, independent of
|
|
1676
|
-
// cleanupOldAgents()'s cap-based one — and must obey the same invariant
|
|
1677
|
-
// (RUSH-2356): a non-terminal teammate is never a reap candidate,
|
|
1678
|
-
// however old its (possibly spuriously stamped) completedAt is. Belt and
|
|
1679
|
-
// suspenders alongside the PENDING guards above that stop completedAt
|
|
1680
|
-
// from getting set on a staged teammate in the first place.
|
|
1681
1189
|
if (agent.completedAt && agent.completedAt < cutoffDate && isTerminalStatus(agent.status)) {
|
|
1682
1190
|
try {
|
|
1683
1191
|
await fs.rm(agentDir, { recursive: true });
|
|
@@ -1707,32 +1215,12 @@ export class AgentManager {
|
|
|
1707
1215
|
}
|
|
1708
1216
|
debug(`Loaded ${loadedCount} agents from disk`);
|
|
1709
1217
|
}
|
|
1710
|
-
/**
|
|
1711
|
-
* Validate an add's name uniqueness and `--after` dependency graph, without
|
|
1712
|
-
* any side effects. Throws a user-facing error on: a duplicate name, `--after`
|
|
1713
|
-
* without `--name`, an unknown dependency, or a cycle. Returns the cleaned
|
|
1714
|
-
* (whitespace-filtered) `after` list.
|
|
1715
|
-
*
|
|
1716
|
-
* Extracted from spawn() so the command layer can run it BEFORE creating a
|
|
1717
|
-
* worktree — a rejected add must not leave an orphan `agents/<name>` branch
|
|
1718
|
-
* that then breaks the retry with `fatal: a branch ... already exists`
|
|
1719
|
-
* (RUSH-2356). spawn() calls it too, so validation lives in exactly one place.
|
|
1720
|
-
*
|
|
1721
|
-
* The result is cached for exactly ONE subsequent call with the same
|
|
1722
|
-
* arguments, which spawn() then consumes. `listByTask()` → `listAll()`
|
|
1723
|
-
* refreshes every sibling's status, and on a `--device` team that is a full
|
|
1724
|
-
* round of SSH liveness probes — running it twice per `teams add` would
|
|
1725
|
-
* double that cost for no gain, since the second pass reads the same snapshot
|
|
1726
|
-
* and cannot catch anything the first missed. The cache is single-use so any
|
|
1727
|
-
* later spawn (a `teams start --watch` supervisor launching staged teammates)
|
|
1728
|
-
* still validates against fresh state and still rejects a duplicate name.
|
|
1729
|
-
*/
|
|
1730
1218
|
async validateAddPreconditions(taskName, name, after) {
|
|
1731
1219
|
await this.initialize();
|
|
1732
1220
|
const key = JSON.stringify([taskName, name, after]);
|
|
1733
1221
|
if (this.validatedAdd?.key === key) {
|
|
1734
1222
|
const cached = this.validatedAdd.cleanAfter;
|
|
1735
|
-
this.validatedAdd = null;
|
|
1223
|
+
this.validatedAdd = null;
|
|
1736
1224
|
return cached;
|
|
1737
1225
|
}
|
|
1738
1226
|
const siblings = await this.listByTask(taskName);
|
|
@@ -1744,15 +1232,12 @@ export class AgentManager {
|
|
|
1744
1232
|
if (!name) {
|
|
1745
1233
|
throw new Error("Can't use --after without --name. Dependencies reference teammates by name.");
|
|
1746
1234
|
}
|
|
1747
|
-
// Every --after entry must resolve to an existing teammate name.
|
|
1748
1235
|
const siblingNames = new Set(siblings.map((a) => a.name).filter(Boolean));
|
|
1749
1236
|
const missing = cleanAfter.filter((dep) => !siblingNames.has(dep));
|
|
1750
1237
|
if (missing.length > 0) {
|
|
1751
1238
|
throw new Error(`Team '${taskName}' has no teammate named ${missing.map((m) => `'${m}'`).join(', ')} yet.\n` +
|
|
1752
1239
|
` Add them first, then add this one.`);
|
|
1753
1240
|
}
|
|
1754
|
-
// Cycle check: walk the transitive deps of each --after entry; if the
|
|
1755
|
-
// new teammate's own name shows up, we'd create a cycle.
|
|
1756
1241
|
const byName = new Map(siblings.filter((a) => a.name).map((a) => [a.name, a]));
|
|
1757
1242
|
for (const dep of cleanAfter) {
|
|
1758
1243
|
if (hasTransitiveDep(byName, dep, name)) {
|
|
@@ -1763,35 +1248,6 @@ export class AgentManager {
|
|
|
1763
1248
|
this.validatedAdd = { key, cleanAfter };
|
|
1764
1249
|
return cleanAfter;
|
|
1765
1250
|
}
|
|
1766
|
-
/**
|
|
1767
|
-
* Does any LIVE teammate — in any team — already own `worktreeName`?
|
|
1768
|
-
*
|
|
1769
|
-
* A RAW disk scan: no status probing, no cache, no `listAll()`. The caller is
|
|
1770
|
-
* the `teams add` failure path, where the manager's own status refresh can be
|
|
1771
|
-
* the very thing that threw (`cleanupOldAgents()` → `listAll()` →
|
|
1772
|
-
* `updateStatusFromProcess()` runs AFTER the staged record is saved), so a
|
|
1773
|
-
* check that re-entered that machinery would throw again and answer nothing.
|
|
1774
|
-
*
|
|
1775
|
-
* `teams add` asks this before removing a worktree, to tell an ORPHAN from
|
|
1776
|
-
* someone's live checkout (RUSH-2356). Two deliberate scoping choices:
|
|
1777
|
-
*
|
|
1778
|
-
* - **Any team, not just the one being added to.** Worktree names are global
|
|
1779
|
-
* to the repo but records are per-team, so a same-named worktree owned by
|
|
1780
|
-
* another team's teammate must also block the removal.
|
|
1781
|
-
* - **Non-terminal records only.** A completed/failed/stopped teammate's
|
|
1782
|
-
* worktree was already cleaned up at `teams stop`, and its record lingers
|
|
1783
|
-
* until retention reaps it — counting those would leave a genuine orphan
|
|
1784
|
-
* branch stranded forever, which is the bug this all exists to fix.
|
|
1785
|
-
* - **Fails CLOSED.** This guards a `git worktree remove --force`, so the two
|
|
1786
|
-
* errors are not symmetric: a false "claimed" strands an orphan branch that
|
|
1787
|
-
* a human can delete, while a false "unclaimed" deletes a live agent's
|
|
1788
|
-
* checkout and its uncommitted work. Only `ENOENT` proves absence — no
|
|
1789
|
-
* agents dir means no records, and a record with no `meta.json` is not a
|
|
1790
|
-
* record. Any other failure (EACCES, EIO, half-written or invalid JSON,
|
|
1791
|
-
* a race with a writer) means we could not READ the records, which is not
|
|
1792
|
-
* the same as there being none, so it answers `true`. This is deliberate
|
|
1793
|
-
* asymmetry, not defensive coding: the caller acts destructively on `false`.
|
|
1794
|
-
*/
|
|
1795
1251
|
async isWorktreeClaimed(worktreeName) {
|
|
1796
1252
|
const base = this.agentsDir ?? (await getAgentsDir());
|
|
1797
1253
|
let entries;
|
|
@@ -1799,10 +1255,6 @@ export class AgentManager {
|
|
|
1799
1255
|
entries = await fs.readdir(base);
|
|
1800
1256
|
}
|
|
1801
1257
|
catch (err) {
|
|
1802
|
-
// ENOENT is the only error that PROVES nothing claims the worktree: there
|
|
1803
|
-
// are no records at all. Every other failure (EACCES, EIO, a transient
|
|
1804
|
-
// races with a writer) means we could not read the records, which is not
|
|
1805
|
-
// the same as there being none — fail closed.
|
|
1806
1258
|
if (err?.code === 'ENOENT')
|
|
1807
1259
|
return false;
|
|
1808
1260
|
return true;
|
|
@@ -1817,9 +1269,6 @@ export class AgentManager {
|
|
|
1817
1269
|
return true;
|
|
1818
1270
|
}
|
|
1819
1271
|
catch (err) {
|
|
1820
|
-
// A record without a meta.json is not a record — skip it. Anything else
|
|
1821
|
-
// (unreadable, half-written, invalid JSON) may be the very record that
|
|
1822
|
-
// claims this worktree, and we cannot tell. Fail closed.
|
|
1823
1272
|
if (err?.code === 'ENOENT')
|
|
1824
1273
|
continue;
|
|
1825
1274
|
return true;
|
|
@@ -1830,19 +1279,10 @@ export class AgentManager {
|
|
|
1830
1279
|
async spawn(taskName, agentType, prompt, cwd = null, mode = null, effort = 'medium', parentSessionId = null, workspaceDir = null, version = null, name = null, after = [], model = null, envOverrides = null, taskType = null, cloudProvider = null, cloudSessionId = null, cloudRepo = null, cloudBranch = null, worktreeName = null, worktreePath = null, profileName = null, hostName = null, hostTarget = null, repoPath = null, project = null) {
|
|
1831
1280
|
await this.initialize();
|
|
1832
1281
|
const resolvedMode = resolveMode(mode, this.defaultMode);
|
|
1833
|
-
// Lineage (RUSH-2019): when the caller didn't name a parent, inherit the
|
|
1834
|
-
// orchestrator's own session id from its env (exec.ts stamps AGENTS_SESSION_ID
|
|
1835
|
-
// onto every agent process). A team spawned from inside a running agent then
|
|
1836
|
-
// records which session created it, so the spawn chain traces back to a parent
|
|
1837
|
-
// session; a team started outside any agent simply carries none.
|
|
1838
1282
|
if (!parentSessionId) {
|
|
1839
1283
|
parentSessionId = process.env.AGENTS_SESSION_ID ?? null;
|
|
1840
1284
|
}
|
|
1841
|
-
// Validate name uniqueness + --after deps. Throws on any violation. The
|
|
1842
|
-
// command layer calls this BEFORE creating a worktree so a rejected add
|
|
1843
|
-
// never leaves an orphan `agents/<name>` branch behind (RUSH-2356).
|
|
1844
1285
|
const cleanAfter = await this.validateAddPreconditions(taskName, name, after);
|
|
1845
|
-
// Resolve and validate cwd
|
|
1846
1286
|
let resolvedCwd = null;
|
|
1847
1287
|
if (cwd !== null) {
|
|
1848
1288
|
resolvedCwd = path.resolve(cwd);
|
|
@@ -1854,40 +1294,23 @@ export class AgentManager {
|
|
|
1854
1294
|
throw new Error(`Working directory is not a directory: ${cwd}`);
|
|
1855
1295
|
}
|
|
1856
1296
|
}
|
|
1857
|
-
// Cloud-backed teammates run on remote infrastructure; we don't need the
|
|
1858
|
-
// local CLI for them (the pod has its own). The caller has already
|
|
1859
|
-
// dispatched via the cloud provider and passed us the provider + session.
|
|
1860
1297
|
const isCloudBacked = Boolean(cloudProvider);
|
|
1861
|
-
// Distributed teammates run on another machine over SSH — the agent CLI must
|
|
1862
|
-
// be present on the HOST (checked via ensureHostReady in the command), not
|
|
1863
|
-
// locally. So skip the local availability check for both remote backends.
|
|
1864
1298
|
const isRemoteBacked = Boolean(hostName);
|
|
1865
1299
|
if (!isCloudBacked && !isRemoteBacked) {
|
|
1866
|
-
// Profile-backed teammates still spawn through `agents run`, which
|
|
1867
|
-
// resolves the profile to its host harness — so the CLI we need to be
|
|
1868
|
-
// present is the underlying agentType, not the profile name.
|
|
1869
1300
|
const [available, pathOrError] = checkCliAvailable(agentType);
|
|
1870
1301
|
if (!available) {
|
|
1871
1302
|
throw new Error(pathOrError || 'CLI tool not available');
|
|
1872
1303
|
}
|
|
1873
1304
|
}
|
|
1874
|
-
// Use a full UUIDv4 as the canonical agent_id. For Claude, we pass it via
|
|
1875
|
-
// --session-id so it's also Claude's session id (unified identity).
|
|
1876
1305
|
const agentId = randomUUID();
|
|
1877
1306
|
const isStaged = cleanAfter.length > 0;
|
|
1878
1307
|
const initialStatus = isStaged || !isCloudBacked || !cloudSessionId
|
|
1879
1308
|
? AgentStatus.PENDING
|
|
1880
1309
|
: AgentStatus.RUNNING;
|
|
1881
1310
|
const agent = new AgentProcess(agentId, taskName, agentType, prompt, resolvedCwd, resolvedMode, null, initialStatus, new Date(), null, this.agentsDir, parentSessionId, workspaceDir, cloudSessionId, cloudProvider, null, version, null, name, cleanAfter, effort, model, envOverrides && Object.keys(envOverrides).length > 0 ? envOverrides : null, taskType, cloudRepo, cloudBranch, worktreeName, worktreePath, profileName);
|
|
1882
|
-
// Distributed-team placement: set post-construction (like startTime), so the
|
|
1883
|
-
// giant constructor stays fixed. launchRemoteProcess() reads these to dispatch
|
|
1884
|
-
// over SSH and fills in the runtime handles (remotePid/remoteLog/remoteExit).
|
|
1885
1311
|
agent.hostName = hostName;
|
|
1886
1312
|
agent.hostTarget = hostTarget;
|
|
1887
1313
|
agent.repoPath = repoPath;
|
|
1888
|
-
// Must be set BEFORE the launch below — this method launches inline for a
|
|
1889
|
-
// teammate with no unmet --after deps, so assigning it after spawn()
|
|
1890
|
-
// returns would miss the only launch that matters.
|
|
1891
1314
|
agent.project = project;
|
|
1892
1315
|
const agentDir = await agent.getAgentDir();
|
|
1893
1316
|
try {
|
|
@@ -1897,11 +1320,6 @@ export class AgentManager {
|
|
|
1897
1320
|
throw new Error(`Failed to create agent directory: ${err.message}`);
|
|
1898
1321
|
}
|
|
1899
1322
|
this.agents.set(agentId, agent);
|
|
1900
|
-
// Seed the teammate's session label with its friendly team name, so the run
|
|
1901
|
-
// shows up as `<name>` in `agents sessions` and resolves by it — consistent
|
|
1902
|
-
// with `agents run --name`. For Claude the agent id IS the session id (passed
|
|
1903
|
-
// via --session-id in buildCommand); other agents don't expose a launch-time
|
|
1904
|
-
// id, so they're seeded once discovery captures one. Best-effort.
|
|
1905
1323
|
if (agentType === 'claude' && name && !isCloudBacked) {
|
|
1906
1324
|
recordRunName({ sessionId: agentId, name, agent: agentType, cwd: resolvedCwd ?? undefined });
|
|
1907
1325
|
}
|
|
@@ -1911,7 +1329,6 @@ export class AgentManager {
|
|
|
1911
1329
|
}
|
|
1912
1330
|
else if (isCloudBacked) {
|
|
1913
1331
|
if (cloudSessionId) {
|
|
1914
|
-
// Compatibility path for API callers that already dispatched remotely.
|
|
1915
1332
|
await agent.saveMeta();
|
|
1916
1333
|
debug(`Cloud-backed ${agentType} teammate via ${cloudProvider} (session=${cloudSessionId})`);
|
|
1917
1334
|
}
|
|
@@ -1935,14 +1352,9 @@ export class AgentManager {
|
|
|
1935
1352
|
}
|
|
1936
1353
|
}
|
|
1937
1354
|
else if (isRemoteBacked) {
|
|
1938
|
-
// Distributed teammate that can run now (no unmet --after deps): dispatch
|
|
1939
|
-
// it onto its host over SSH instead of a local spawn.
|
|
1940
1355
|
await this.launchRemoteProcess(agent);
|
|
1941
1356
|
}
|
|
1942
1357
|
else {
|
|
1943
|
-
// Unpinned + launching now: consult the pool scheduler before defaulting to
|
|
1944
|
-
// local, so an unpinned teammate on a --devices team auto-schedules even when
|
|
1945
|
-
// added without --after (it wouldn't pass through startReady otherwise).
|
|
1946
1358
|
try {
|
|
1947
1359
|
await this.maybeSchedulePlacement(agent, taskName);
|
|
1948
1360
|
}
|
|
@@ -1970,12 +1382,6 @@ export class AgentManager {
|
|
|
1970
1382
|
await this.launchProcess(agent);
|
|
1971
1383
|
}
|
|
1972
1384
|
await this.cleanupOldAgents();
|
|
1973
|
-
// Postcondition: the teammate MUST be durably on disk before we report
|
|
1974
|
-
// success. saveMeta() ran above and cleanupOldAgents() can no longer reap a
|
|
1975
|
-
// non-terminal record, but a failed write (full disk, permissions) or any
|
|
1976
|
-
// future retention regression would otherwise let `teams add` print a full
|
|
1977
|
-
// success block for a teammate that does not exist — the RUSH-2356
|
|
1978
|
-
// silent-success class. Assert the outcome, not the exit code.
|
|
1979
1385
|
const persisted = await AgentProcess.loadFromDisk(agentId, this.agentsDir);
|
|
1980
1386
|
if (!persisted) {
|
|
1981
1387
|
this.agents.delete(agentId);
|
|
@@ -1984,45 +1390,20 @@ export class AgentManager {
|
|
|
1984
1390
|
}
|
|
1985
1391
|
return agent;
|
|
1986
1392
|
}
|
|
1987
|
-
/**
|
|
1988
|
-
* Resume a STOPPED teammate (completed / failed / stopped) by re-entering its
|
|
1989
|
-
* own session with `message` as the next user turn. Re-launches through the
|
|
1990
|
-
* SAME backend the teammate first used (local process or remote host), reusing
|
|
1991
|
-
* its stored cwd / worktree / host / version / model / effort, and flips it
|
|
1992
|
-
* back to RUNNING so the team tracks it live again.
|
|
1993
|
-
*
|
|
1994
|
-
* The resume target is the teammate's underlying agent session id: for Claude
|
|
1995
|
-
* that IS its agent_id (unified identity, pinned via --session-id at first
|
|
1996
|
-
* launch); other harnesses only expose their session/thread id after their
|
|
1997
|
-
* first stream event, captured as `remoteSessionId`.
|
|
1998
|
-
*
|
|
1999
|
-
* Callers branch on status first — a RUNNING teammate is steered via its
|
|
2000
|
-
* mailbox, never re-launched — so this method assumes a non-running teammate.
|
|
2001
|
-
*/
|
|
2002
1393
|
async resumeTeammate(agentId, message) {
|
|
2003
1394
|
await this.initialize();
|
|
2004
1395
|
const agent = await this.get(agentId);
|
|
2005
1396
|
if (!agent)
|
|
2006
1397
|
throw new Error(`No teammate with id ${agentId}`);
|
|
2007
1398
|
const who = agent.name ?? agent.agentId.slice(0, 8);
|
|
2008
|
-
// The message rides as `agents run`'s prompt positional. A leading '-' makes
|
|
2009
|
-
// commander parse it as an (unknown) flag, exiting the child non-zero — the
|
|
2010
|
-
// teammate would silently land FAILED. `--` can't rescue it: `agents run`
|
|
2011
|
-
// treats post-`--` tokens as native passthrough and unsets the prompt. Fail
|
|
2012
|
-
// loud and early instead. (Steer/mailbox delivery has no such limit.)
|
|
2013
1399
|
if (message.startsWith('-')) {
|
|
2014
1400
|
throw new Error(`Resume message can't start with '-' — \`agents run\` would parse it as a flag. ` +
|
|
2015
1401
|
`Rephrase so it leads with a word (e.g. "Please ${message}").`);
|
|
2016
1402
|
}
|
|
2017
|
-
// Cloud-backed teammates run on remote provider infrastructure with no local
|
|
2018
|
-
// or host process to re-launch; continuing them goes through the provider.
|
|
2019
1403
|
if (agent.cloudProvider) {
|
|
2020
1404
|
throw new Error(`Teammate '${who}' is a ${agent.cloudProvider} cloud task — resume it with ` +
|
|
2021
1405
|
`\`agents message ${agent.cloudSessionId ?? agent.agentId} "<message>"\` instead.`);
|
|
2022
1406
|
}
|
|
2023
|
-
// For non-Claude teammates the agent_id is NOT the harness session id — that
|
|
2024
|
-
// is only known once the agent emitted its first stream event. If it never
|
|
2025
|
-
// did (e.g. it failed before its first turn), there is no resumable handle.
|
|
2026
1407
|
if (agent.agentType !== 'claude' && !agent.remoteSessionId) {
|
|
2027
1408
|
throw new Error(`No resumable session id was captured for ${agent.agentType} teammate '${who}' — ` +
|
|
2028
1409
|
`its session id is discovered from the agent's own output, which never arrived ` +
|
|
@@ -2042,18 +1423,7 @@ export class AgentManager {
|
|
|
2042
1423
|
remoteLogOffset: agent.remoteLogOffset,
|
|
2043
1424
|
worktreePath: agent.worktreePath,
|
|
2044
1425
|
};
|
|
2045
|
-
// Flip to RUNNING up front so a concurrent status poll can't reap the
|
|
2046
|
-
// teammate between the exit-sentinel clear and the new PID landing; the
|
|
2047
|
-
// launch re-persists with the fresh pid/startTime. If relaunch fails before
|
|
2048
|
-
// that happens, restore the stopped lifecycle state and keep its existing
|
|
2049
|
-
// metadata/log directory intact so the user can retry.
|
|
2050
1426
|
agent.status = AgentStatus.RUNNING;
|
|
2051
|
-
// Failure evidence describes the CURRENT attempt. Once a resume has
|
|
2052
|
-
// successfully launched, retaining the prior terminal attempt's failure on
|
|
2053
|
-
// a RUNNING (and eventually COMPLETED) teammate is false state. Clear it
|
|
2054
|
-
// before either launcher persists RUNNING; priorRuntime restores it if the
|
|
2055
|
-
// replacement launch fails, so a failed resume never erases the evidence
|
|
2056
|
-
// needed to diagnose and retry the original attempt.
|
|
2057
1427
|
agent.failure = null;
|
|
2058
1428
|
agent.completedAt = null;
|
|
2059
1429
|
try {
|
|
@@ -2076,17 +1446,10 @@ export class AgentManager {
|
|
|
2076
1446
|
}
|
|
2077
1447
|
return agent;
|
|
2078
1448
|
}
|
|
2079
|
-
/**
|
|
2080
|
-
* Actually spawn the OS process for a teammate. Extracted from spawn() so
|
|
2081
|
-
* staged teammates can be launched later by startReady().
|
|
2082
|
-
*/
|
|
2083
1449
|
async launchProcess(agent, resume) {
|
|
2084
1450
|
const running = await this.listRunning();
|
|
2085
1451
|
warnIfMemoryLow(running.length);
|
|
2086
1452
|
const effort = agent.effort ?? 'medium';
|
|
2087
|
-
// null model means "let the CLI pick its own default" (no --model flag
|
|
2088
|
-
// forwarded). Effort is a separate knob wired into buildReasoningFlags
|
|
2089
|
-
// inside buildCommand.
|
|
2090
1453
|
const resolvedModel = agent.model ?? null;
|
|
2091
1454
|
const cmd = this.buildCommand(agent.agentType, agent.prompt, agent.mode, resolvedModel, agent.cwd, agent.agentId, effort, agent.version, agent.profileName, resume, await resolveTeammateGrants(agent, { forRemote: false }));
|
|
2092
1455
|
debug(`Launching ${agent.agentType} agent ${agent.agentId} [${agent.mode}]${resume ? ' (resume)' : ''}: ${cmd.slice(0, 3).join(' ')}...`);
|
|
@@ -2097,30 +1460,11 @@ export class AgentManager {
|
|
|
2097
1460
|
if (resume)
|
|
2098
1461
|
resumeLog = await beginResumeLogTransaction(agent);
|
|
2099
1462
|
const stdoutPath = resumeLog?.stdoutPath ?? await agent.getStdoutPath();
|
|
2100
|
-
// Always TRUNCATE — including on resume. The status reader re-reads the
|
|
2101
|
-
// whole log from byte 0 every poll (lastReadPos is in-memory, not
|
|
2102
|
-
// persisted) and marks terminal status from the last `result` event it
|
|
2103
|
-
// sees, with no liveness guard. If the resumed turn's stream were appended
|
|
2104
|
-
// after the prior turn's `result:success`, that stale event would win for
|
|
2105
|
-
// the entire duration of the new (still-running) turn — reporting the
|
|
2106
|
-
// teammate COMPLETED while it works, and steering a second follow-up into
|
|
2107
|
-
// a forked session. Truncating keeps exactly one turn in the log, so the
|
|
2108
|
-
// re-read is always correct. The authoritative transcript lives in the
|
|
2109
|
-
// agent's own session (resumed via --resume), not this stdout mirror.
|
|
2110
1463
|
stdoutFile = await fs.open(stdoutPath, 'w');
|
|
2111
1464
|
const stdoutFd = stdoutFile.fd;
|
|
2112
|
-
// Wrap the teammate command in a shell that records the underlying CLI's
|
|
2113
|
-
// exit code to a sentinel file. Detached + unref()'d children can't be
|
|
2114
|
-
// wait()ed on by this parent, so the sentinel is the only durable record
|
|
2115
|
-
// of the real exit status — reapProcess() reads it to decide
|
|
2116
|
-
// completed-vs-failed for agents whose stream emits no parsed terminal
|
|
2117
|
-
// event (kimi, antigravity, droid). Remove any stale sentinel from a
|
|
2118
|
-
// prior run of the same agent id first so a restart can't read it.
|
|
2119
1465
|
const exitCodePath = await agent.getExitCodePath();
|
|
2120
1466
|
await fs.rm(exitCodePath, { force: true }).catch(() => { });
|
|
2121
1467
|
const wrappedCmd = buildSentinelCommand(cmd, exitCodePath);
|
|
2122
|
-
// detached:true makes the shell the process-group leader, so stop()'s
|
|
2123
|
-
// `kill(-pid)` still reaches the underlying CLI through the group.
|
|
2124
1468
|
childProcess = spawn('/bin/sh', ['-c', wrappedCmd], {
|
|
2125
1469
|
stdio: ['ignore', stdoutFd, stdoutFd],
|
|
2126
1470
|
cwd: agent.cwd || undefined,
|
|
@@ -2135,10 +1479,6 @@ export class AgentManager {
|
|
|
2135
1479
|
await stdoutFile.close();
|
|
2136
1480
|
stdoutFile = null;
|
|
2137
1481
|
agent.pid = childProcess.pid || null;
|
|
2138
|
-
// Capture start-time NOW, while we know the PID is ours. Once the
|
|
2139
|
-
// OS reuses this PID slot, /proc and `ps` will report a different
|
|
2140
|
-
// value — that's the signal stop() uses to refuse to signal an
|
|
2141
|
-
// unrelated process.
|
|
2142
1482
|
agent.startTime = agent.pid ? captureProcessStartTime(agent.pid) : null;
|
|
2143
1483
|
agent.status = AgentStatus.RUNNING;
|
|
2144
1484
|
agent.startedAt = new Date();
|
|
@@ -2167,33 +1507,15 @@ export class AgentManager {
|
|
|
2167
1507
|
}
|
|
2168
1508
|
debug(`Launched agent ${agent.agentId} with PID ${agent.pid}`);
|
|
2169
1509
|
}
|
|
2170
|
-
/**
|
|
2171
|
-
* Dispatch a distributed teammate onto its host over SSH — the remote-host
|
|
2172
|
-
* analog of launchProcess(). Symmetric to the cloud path: no local process; the
|
|
2173
|
-
* lifecycle lives on the host and is polled (isProcessAlive/readNewEvents over
|
|
2174
|
-
* SSH via the remote `.exit` sentinel + offset-tailed log).
|
|
2175
|
-
*
|
|
2176
|
-
* When the team uses worktrees (agent.worktreeName set), a git worktree is first
|
|
2177
|
-
* created ON THE HOST off the freshly-fetched default branch; the teammate runs
|
|
2178
|
-
* there. Otherwise it runs in the host repo path directly.
|
|
2179
|
-
*/
|
|
2180
1510
|
async launchRemoteProcess(agent, resume) {
|
|
2181
1511
|
if (!agent.hostName || !agent.hostTarget || !agent.repoPath) {
|
|
2182
1512
|
throw new Error(`Remote teammate ${agent.agentId} is missing host placement (host/target/repo).`);
|
|
2183
1513
|
}
|
|
2184
|
-
// Re-resolve the device → Host at launch time (it may have moved / changed
|
|
2185
|
-
// address since `add` staged the teammate), matching how the command resolved
|
|
2186
|
-
// it. The target string on the agent stays the launch-time source of truth for
|
|
2187
|
-
// subsequent polling.
|
|
2188
1514
|
const host = await resolveHost(agent.hostName);
|
|
2189
1515
|
if (!host) {
|
|
2190
1516
|
throw new Error(`Cannot launch remote teammate ${agent.agentId}: device "${agent.hostName}" no longer resolves.`);
|
|
2191
1517
|
}
|
|
2192
1518
|
agent.hostIdentityFile = host.identityFile ?? null;
|
|
2193
|
-
// Ensure agents-cli is present + the pin is installed on the host. A bare
|
|
2194
|
-
// agent name still warns (like dispatch.ts); a concrete agent.version pin
|
|
2195
|
-
// fails loud so the teammate never reports launched against a missing pin
|
|
2196
|
-
// (RUSH-2313).
|
|
2197
1519
|
try {
|
|
2198
1520
|
const { warnings } = ensureHostReady(host, {
|
|
2199
1521
|
agent: agent.agentType,
|
|
@@ -2205,11 +1527,6 @@ export class AgentManager {
|
|
|
2205
1527
|
catch (err) {
|
|
2206
1528
|
throw new Error(`Host "${agent.hostName}" not ready for teammate ${agent.agentId}: ${err.message}`);
|
|
2207
1529
|
}
|
|
2208
|
-
// Worktree isolation on the host, if the team enables it. createRemoteWorktree
|
|
2209
|
-
// fetches origin and branches off origin/<default>, returning the host path.
|
|
2210
|
-
// On RESUME the worktree already exists from the original launch — reuse it
|
|
2211
|
-
// (its path is persisted) instead of re-creating (which would fail on the
|
|
2212
|
-
// existing branch and would also discard the teammate's in-progress work).
|
|
2213
1530
|
let remoteCwd = agent.repoPath;
|
|
2214
1531
|
if (agent.worktreeName) {
|
|
2215
1532
|
if (resume && agent.worktreePath) {
|
|
@@ -2223,16 +1540,8 @@ export class AgentManager {
|
|
|
2223
1540
|
remoteCwd = worktreePath;
|
|
2224
1541
|
}
|
|
2225
1542
|
}
|
|
2226
|
-
// Same run argv the local path builds (shared buildRunArgv keeps the prompt
|
|
2227
|
-
// scaffolding + flags from drifting); dispatched non-blocking (follow:false)
|
|
2228
|
-
// — the supervisor polls the host, we don't block here.
|
|
2229
1543
|
const effort = agent.effort ?? 'medium';
|
|
2230
1544
|
const forwardedArgs = this.buildRunArgv(agent.agentType, agent.prompt, agent.mode, agent.model ?? null, effort, agent.version, agent.profileName, resume);
|
|
2231
|
-
// Project grants for a remote teammate, resolved HERE rather than at add
|
|
2232
|
-
// time: an unpinned teammate only learns its host from the scheduler, which
|
|
2233
|
-
// runs at launch. `forRemote: true` keeps them `~/…` and skips this box's
|
|
2234
|
-
// existence check — the host has its own checkouts. The remote `agents run`
|
|
2235
|
-
// expands `~` against the host's HOME before handing it to the harness.
|
|
2236
1545
|
for (const dir of await resolveTeammateGrants(agent, { forRemote: true })) {
|
|
2237
1546
|
if (dir !== remoteCwd)
|
|
2238
1547
|
forwardedArgs.push('--add-dir', dir);
|
|
@@ -2254,10 +1563,6 @@ export class AgentManager {
|
|
|
2254
1563
|
agent.remoteLog = task.remoteLog ?? null;
|
|
2255
1564
|
agent.remoteExit = task.remoteExit ?? null;
|
|
2256
1565
|
agent.remoteLogOffset = 0;
|
|
2257
|
-
// On resume the offset resets to 0 against a FRESH remote log, and
|
|
2258
|
-
// syncRemoteMirror appends the delta onto the local mirror. Truncate that
|
|
2259
|
-
// mirror first so the prior turn's terminal event can't linger and get
|
|
2260
|
-
// re-read as the current status (same hazard the local path truncates for).
|
|
2261
1566
|
agent.status = AgentStatus.RUNNING;
|
|
2262
1567
|
agent.startedAt = new Date();
|
|
2263
1568
|
await agent.saveMeta();
|
|
@@ -2299,15 +1604,6 @@ export class AgentManager {
|
|
|
2299
1604
|
}
|
|
2300
1605
|
debug(`Launched remote agent ${agent.agentId} on ${agent.hostName} (remote pid ${agent.remotePid})`);
|
|
2301
1606
|
}
|
|
2302
|
-
/**
|
|
2303
|
-
* Resolve a scheduler-picked device to host placement fields on an unpinned
|
|
2304
|
-
* teammate at LAUNCH time (the same resolution `teams add --device` runs, minus
|
|
2305
|
-
* the fatal `die()` — a scheduling failure here is per-teammate, not per-add).
|
|
2306
|
-
* Sets hostName/hostTarget/repoPath + persists, so the subsequent
|
|
2307
|
-
* launchRemoteProcess dispatches over SSH. Mirrors the `add`-time pin path:
|
|
2308
|
-
* resolve device → reject Windows (POSIX-only) → ssh target → ensure the repo
|
|
2309
|
-
* is present on the host from the team's --repo (ensureRemoteRepo).
|
|
2310
|
-
*/
|
|
2311
1607
|
async resolveScheduledPlacement(agent, device, taskName) {
|
|
2312
1608
|
const host = await resolveHost(device);
|
|
2313
1609
|
if (!host) {
|
|
@@ -2327,15 +1623,6 @@ export class AgentManager {
|
|
|
2327
1623
|
agent.repoPath = repoRoot;
|
|
2328
1624
|
await agent.saveMeta();
|
|
2329
1625
|
}
|
|
2330
|
-
/**
|
|
2331
|
-
* Place an UNPINNED, non-cloud teammate onto the team pool via the cascade
|
|
2332
|
-
* (least-loaded). A poolless team consumes the active worker allowlist and
|
|
2333
|
-
* fails loud when none exists; it never silently lands on the orchestrator.
|
|
2334
|
-
* A no-op only for a pinned teammate (hostName already set from `--device`) or
|
|
2335
|
-
* a cloud teammate. Shared by spawn()
|
|
2336
|
-
* (immediate add-launch) and startReady() (staged launch) so an unpinned pool
|
|
2337
|
-
* teammate schedules identically no matter how it was fired.
|
|
2338
|
-
*/
|
|
2339
1626
|
async maybeSchedulePlacement(agent, taskName, opts = {}) {
|
|
2340
1627
|
if (agent.hostName || agent.cloudProvider)
|
|
2341
1628
|
return;
|
|
@@ -2343,17 +1630,10 @@ export class AgentManager {
|
|
|
2343
1630
|
if (!teamMeta)
|
|
2344
1631
|
return;
|
|
2345
1632
|
const roster = await this.listByTask(taskName);
|
|
2346
|
-
// A poolless team is still an automatic placement request: use the same
|
|
2347
|
-
// explicit worker allowlist as `--device auto`. Never silently run it on a
|
|
2348
|
-
// personal/desktop orchestrator merely because `devices` was omitted.
|
|
2349
1633
|
const pool = teamMeta.devices?.length
|
|
2350
1634
|
? teamMeta.devices
|
|
2351
1635
|
: filterAutoPool(listWorkerDevices());
|
|
2352
1636
|
const maxConcurrent = pool.length > 1 ? readMaxConcurrentCaps(pool) : undefined;
|
|
2353
|
-
// On the start path (opts.probe), gather live signals so the pick is health-,
|
|
2354
|
-
// harness-, and load-aware (RUSH-2002); the add path stays the cap-only
|
|
2355
|
-
// roster count so `teams add` never blocks on an SSH fan-out. Cached per
|
|
2356
|
-
// (pool, agent), so a wave placing many teammates probes the pool once.
|
|
2357
1637
|
const signals = opts.probe && pool.length > 0
|
|
2358
1638
|
? await probePoolSignals(pool, agent.agentType, { now: Date.now() })
|
|
2359
1639
|
: undefined;
|
|
@@ -2379,27 +1659,12 @@ export class AgentManager {
|
|
|
2379
1659
|
if (device)
|
|
2380
1660
|
await this.resolveScheduledPlacement(agent, device, taskName);
|
|
2381
1661
|
}
|
|
2382
|
-
/** Human label of a teammate's agent for the placement fail-loud message. */
|
|
2383
1662
|
placementAgentLabel(agent) {
|
|
2384
1663
|
return agent.version ? `${agent.agentType}@${agent.version}` : String(agent.agentType);
|
|
2385
1664
|
}
|
|
2386
|
-
/**
|
|
2387
|
-
* One-ssh-per-host batched liveness/exit pre-pass for a team's remote teammates.
|
|
2388
|
-
* The supervisor calls this each wave BEFORE listByTask() so the per-teammate
|
|
2389
|
-
* isProcessAlive()/readNewEvents() consume a cached snapshot instead of each
|
|
2390
|
-
* issuing its own SSH handshake — avoiding N round-trips per wave at 10+ remote
|
|
2391
|
-
* teammates. Groups by hostTarget and, for each host, checks every teammate's
|
|
2392
|
-
* `.exit` + `kill -0` in a single ssh call over the shared ControlMaster socket.
|
|
2393
|
-
*/
|
|
2394
1665
|
async prefetchRemoteStatus(taskName) {
|
|
2395
1666
|
await this.initialize();
|
|
2396
|
-
// Read the in-memory roster directly — going through listByTask()/listAll()
|
|
2397
|
-
// would poll each teammate first (an SSH round-trip apiece), defeating the
|
|
2398
|
-
// batch. The caller (supervisor) has already rescanned from disk this wave.
|
|
2399
1667
|
const remotes = Array.from(this.agents.values()).filter((a) => a.taskName === taskName && a.hostName);
|
|
2400
|
-
// Fresh snapshots each wave: clear stale ones first so a teammate that has
|
|
2401
|
-
// since finished (dropped from the RUNNING filter below) can't carry an old
|
|
2402
|
-
// ALIVE reading into this wave's poll.
|
|
2403
1668
|
for (const a of remotes)
|
|
2404
1669
|
a.remotePollSnapshot = null;
|
|
2405
1670
|
const teammates = remotes.filter((a) => a.hostTarget && a.remotePid && a.remoteExit &&
|
|
@@ -2414,11 +1679,6 @@ export class AgentManager {
|
|
|
2414
1679
|
byTarget.set(key, group);
|
|
2415
1680
|
}
|
|
2416
1681
|
for (const { target, agents } of byTarget.values()) {
|
|
2417
|
-
// Emit one line per teammate: "<agentId> <ALIVE|EXITED|GONE> <codeOrEmpty>".
|
|
2418
|
-
// A single round-trip over the multiplexed socket, regardless of teammate
|
|
2419
|
-
// count. GONE (process gone, no `.exit`) is kept distinct from EXITED so a
|
|
2420
|
-
// teammate killed without recording `$?` resolves terminal instead of
|
|
2421
|
-
// reporting RUNNING forever (RUSH-2366).
|
|
2422
1682
|
const parts = agents.map((a) => remoteLivenessSnippet(a.agentId, a.remoteExit, a.remotePid));
|
|
2423
1683
|
const identityFile = agents[0]?.hostIdentityFile;
|
|
2424
1684
|
const res = sshExec(target, parts.join('; '), {
|
|
@@ -2427,7 +1687,7 @@ export class AgentManager {
|
|
|
2427
1687
|
extraSshArgs: identityFile ? ['-i', identityFile, '-o', 'IdentitiesOnly=yes'] : [],
|
|
2428
1688
|
});
|
|
2429
1689
|
if (res.code === null)
|
|
2430
|
-
continue;
|
|
1690
|
+
continue;
|
|
2431
1691
|
const snapshots = new Map();
|
|
2432
1692
|
for (const line of res.stdout.split('\n')) {
|
|
2433
1693
|
const trimmed = line.trim();
|
|
@@ -2445,12 +1705,6 @@ export class AgentManager {
|
|
|
2445
1705
|
}
|
|
2446
1706
|
}
|
|
2447
1707
|
}
|
|
2448
|
-
/**
|
|
2449
|
-
* Fire any pending teammates in the given team whose `after` deps have all
|
|
2450
|
-
* completed. Returns the list of teammates just launched. Repeatable:
|
|
2451
|
-
* call it once per DAG wave. Safe to call on teams with no pending work
|
|
2452
|
-
* (returns empty list).
|
|
2453
|
-
*/
|
|
2454
1708
|
async startReady(taskName) {
|
|
2455
1709
|
await this.initialize();
|
|
2456
1710
|
const teammates = await this.listByTask(taskName);
|
|
@@ -2479,10 +1733,6 @@ export class AgentManager {
|
|
|
2479
1733
|
});
|
|
2480
1734
|
if (!depsReady)
|
|
2481
1735
|
continue;
|
|
2482
|
-
// Auto-scheduling: an UNPINNED teammate (no explicit --device at add time)
|
|
2483
|
-
// gets placed now via the pool cascade — same helper spawn() uses so the
|
|
2484
|
-
// immediate-add and staged paths agree. A null pick keeps hostName null →
|
|
2485
|
-
// local spawn, unchanged. Cloud teammates never schedule.
|
|
2486
1736
|
try {
|
|
2487
1737
|
await this.maybeSchedulePlacement(agent, taskName, { probe: true });
|
|
2488
1738
|
}
|
|
@@ -2507,7 +1757,6 @@ export class AgentManager {
|
|
|
2507
1757
|
}
|
|
2508
1758
|
try {
|
|
2509
1759
|
if (agent.hostName) {
|
|
2510
|
-
// Distributed teammate: dispatch onto its host over SSH.
|
|
2511
1760
|
await this.launchRemoteProcess(agent);
|
|
2512
1761
|
launched.push(agent);
|
|
2513
1762
|
}
|
|
@@ -2546,33 +1795,7 @@ export class AgentManager {
|
|
|
2546
1795
|
}
|
|
2547
1796
|
return launched;
|
|
2548
1797
|
}
|
|
2549
|
-
/**
|
|
2550
|
-
* Build the argv to spawn for a teammate. Delegates to `agents run` so the
|
|
2551
|
-
* agent's CLI flags, version routing, mode handling (plan/edit/full), model
|
|
2552
|
-
* injection, and reasoning-intensity flags are owned by a single canonical
|
|
2553
|
-
* exec path (src/lib/exec.ts). The team runner just supplies prompt + mode
|
|
2554
|
-
* and reads stream-json events off stdout.
|
|
2555
|
-
*/
|
|
2556
|
-
/**
|
|
2557
|
-
* Build the `agents run …` argv AFTER the `agents` binary — the flags + prompt
|
|
2558
|
-
* scaffolding shared by the LOCAL launch (buildCommand, which prefixes
|
|
2559
|
-
* process.execPath + the agents CLI path) and the REMOTE launch
|
|
2560
|
-
* (launchRemoteProcess, which prefixes `agents` on the host via dispatch). Kept
|
|
2561
|
-
* in one place so the PROMPT_SUFFIX / CLAUDE_PLAN_MODE_PREFIX scaffolding and the
|
|
2562
|
-
* flag set can never drift between the two backends.
|
|
2563
|
-
*
|
|
2564
|
-
* `cwd` is intentionally NOT emitted here: the local path passes it as
|
|
2565
|
-
* `--cwd`/`--add-dir` (below), while the remote path `cd`s into the host cwd
|
|
2566
|
-
* before invoking `agents`. `sessionId` is likewise local-only (the remote run
|
|
2567
|
-
* mints its own session on the host).
|
|
2568
|
-
*/
|
|
2569
1798
|
buildRunArgv(agentType, prompt, mode, model, effort, version, profileName, resume) {
|
|
2570
|
-
// Compose the prompt. On RESUME the message is the teammate's next user turn,
|
|
2571
|
-
// not a fresh brief — so skip the original brief and the plan-mode prefix, but
|
|
2572
|
-
// keep PROMPT_SUFFIX so the resumed run still emits a final summary the team
|
|
2573
|
-
// parser reads. On a fresh launch, add the plan-mode prefix for Claude and the
|
|
2574
|
-
// universal summary suffix. These are team-specific prompt scaffolding —
|
|
2575
|
-
// `agents run` does not apply them.
|
|
2576
1799
|
let fullPrompt;
|
|
2577
1800
|
if (resume) {
|
|
2578
1801
|
fullPrompt = resume.message + PROMPT_SUFFIX;
|
|
@@ -2583,22 +1806,8 @@ export class AgentManager {
|
|
|
2583
1806
|
fullPrompt = CLAUDE_PLAN_MODE_PREFIX + fullPrompt;
|
|
2584
1807
|
}
|
|
2585
1808
|
}
|
|
2586
|
-
// PHNX-3236: append the self-merge boundary to every WRITE-capable teammate,
|
|
2587
|
-
// fresh or resumed. A plan-mode teammate produces no PR (read-only), so it is
|
|
2588
|
-
// skipped to keep its prompt clean; every other mode can open — and could
|
|
2589
|
-
// self-merge — a PR, so the policy rides along regardless of harness. The
|
|
2590
|
-
// hard block is still merge-guard.sh (inherited hook); see TEAMMATE_PR_POLICY.
|
|
2591
|
-
// The cloud dispatch path applies the SAME helper (withTeammatePrPolicy) so
|
|
2592
|
-
// local, remote, and cloud teammates never diverge on this boundary.
|
|
2593
1809
|
fullPrompt = withTeammatePrPolicy(fullPrompt, mode);
|
|
2594
|
-
// Profile target takes precedence — `agents run <profile>` resolves the
|
|
2595
|
-
// host harness, version pin, and env injection in one place. Plain
|
|
2596
|
-
// version pins only apply when no profile is selected.
|
|
2597
1810
|
const target = profileName ?? (version ? `${agentType}@${version}` : agentType);
|
|
2598
|
-
// Keep the prompt as the first positional (right after target), matching the
|
|
2599
|
-
// fresh-launch shape, and add `--resume <id>` among the flags. `agents run`
|
|
2600
|
-
// continues the teammate's own session natively (claude `--resume`, codex
|
|
2601
|
-
// `resume`) or via the universal `/continue` replay for other harnesses.
|
|
2602
1811
|
const args = ['run', target, fullPrompt];
|
|
2603
1812
|
if (resume) {
|
|
2604
1813
|
args.push('--resume', resume.id);
|
|
@@ -2610,38 +1819,20 @@ export class AgentManager {
|
|
|
2610
1819
|
return args;
|
|
2611
1820
|
}
|
|
2612
1821
|
buildCommand(agentType, prompt, mode, model, cwd = null, sessionId = null, effort = 'medium', version = null, profileName = null, resume, addDirs = []) {
|
|
2613
|
-
// Route through getAgentsInvocation so a teammate launched by the compiled
|
|
2614
|
-
// standalone binary (#315) doesn't relaunch as `agents /$bunfs/root/agents …`
|
|
2615
|
-
// (process.argv[1] is the bun virtual entry there) → "unknown command".
|
|
2616
1822
|
const inv = getAgentsInvocation(this.buildRunArgv(agentType, prompt, mode, model, effort, version, profileName, resume));
|
|
2617
1823
|
const cmd = [inv.command, ...inv.args];
|
|
2618
1824
|
if (cwd)
|
|
2619
1825
|
cmd.push('--cwd', cwd);
|
|
2620
|
-
// Pin the session UUID to our agent_id so buildExecEnv keys
|
|
2621
|
-
// AGENTS_MAILBOX_DIR by the same id mailboxIdForActiveSession returns.
|
|
2622
|
-
// Claude also forwards --session-id to its CLI (unified identity);
|
|
2623
|
-
// other agents ignore the flag but still get the correct mailbox dir.
|
|
2624
|
-
// On RESUME we continue an existing session — `--session-id` CREATES one and
|
|
2625
|
-
// `agents run` rejects it alongside `--resume`, so it must be omitted.
|
|
2626
1826
|
if (sessionId && !resume) {
|
|
2627
1827
|
cmd.push('--session-id', sessionId);
|
|
2628
1828
|
}
|
|
2629
|
-
// Claude: grant access to the teammate's working directory.
|
|
2630
1829
|
if (agentType === 'claude' && cwd) {
|
|
2631
1830
|
cmd.push('--add-dir', cwd);
|
|
2632
1831
|
}
|
|
2633
|
-
// The team's project directories, beyond the one the teammate sits in.
|
|
2634
|
-
// `agents run` re-dedupes, but skipping cwd here keeps the launch line
|
|
2635
|
-
// readable. Codex folds these into its workspace_roots; other harnesses
|
|
2636
|
-
// ignore --add-dir entirely.
|
|
2637
1832
|
for (const dir of new Set(addDirs)) {
|
|
2638
1833
|
if (dir !== cwd)
|
|
2639
1834
|
cmd.push('--add-dir', dir);
|
|
2640
1835
|
}
|
|
2641
|
-
// Codex's workspace-write sandbox blocks writes outside cwd. Factory
|
|
2642
|
-
// teammates need to run further `agents teams add` commands, which
|
|
2643
|
-
// write to ~/.agents/. Grant that root so subprocess-issued
|
|
2644
|
-
// `agents teams add` calls hit the real store.
|
|
2645
1836
|
if (agentType === 'codex') {
|
|
2646
1837
|
cmd.push('--add-dir', getSystemAgentsDir());
|
|
2647
1838
|
}
|
|
@@ -2664,18 +1855,6 @@ export class AgentManager {
|
|
|
2664
1855
|
}
|
|
2665
1856
|
return null;
|
|
2666
1857
|
}
|
|
2667
|
-
/**
|
|
2668
|
-
* Resolve a teammate reference to a single agent_id within a team.
|
|
2669
|
-
* Accepts (in priority order):
|
|
2670
|
-
* 1. exact teammate name ("alice")
|
|
2671
|
-
* 2. exact UUID ("b2438499-dc25-4a5e-9e02-9916012580b8")
|
|
2672
|
-
* 3. UUID prefix, if unique ("b2438499")
|
|
2673
|
-
*
|
|
2674
|
-
* Returns:
|
|
2675
|
-
* - { kind: 'ok', agentId } when exactly one teammate matches
|
|
2676
|
-
* - { kind: 'none' } when nothing matches
|
|
2677
|
-
* - { kind: 'ambiguous', matches } when the prefix matches multiple ids
|
|
2678
|
-
*/
|
|
2679
1858
|
async resolveAgentIdInTask(taskName, ref) {
|
|
2680
1859
|
const agents = await this.listByTask(taskName);
|
|
2681
1860
|
const byName = agents.find((a) => a.name === ref);
|
|
@@ -2704,13 +1883,6 @@ export class AgentManager {
|
|
|
2704
1883
|
const all = await this.listAll();
|
|
2705
1884
|
return all.filter(a => a.status === AgentStatus.RUNNING);
|
|
2706
1885
|
}
|
|
2707
|
-
/**
|
|
2708
|
-
* Teammates that have reached a terminal status (completed/failed/stopped) —
|
|
2709
|
-
* the ONLY records retention may reap. A `pending` teammate has not launched
|
|
2710
|
-
* and a `running` one is working, so neither is "completed"; classifying them
|
|
2711
|
-
* as such let cleanupOldAgents sweep live `pending` `--after` teammates past
|
|
2712
|
-
* the cap (RUSH-2356). Filter on `isTerminalStatus`, never `!== RUNNING`.
|
|
2713
|
-
*/
|
|
2714
1886
|
async listCompleted() {
|
|
2715
1887
|
const all = await this.listAll();
|
|
2716
1888
|
return all.filter(a => isTerminalStatus(a.status));
|
|
@@ -2719,22 +1891,6 @@ export class AgentManager {
|
|
|
2719
1891
|
const all = await this.listAll();
|
|
2720
1892
|
return all.filter(a => a.taskName === taskName);
|
|
2721
1893
|
}
|
|
2722
|
-
/**
|
|
2723
|
-
* Terminal removal of every teammate record for a team (RUSH-2450).
|
|
2724
|
-
*
|
|
2725
|
-
* `teams disband` used to delete log dirs and the registry entry, but left
|
|
2726
|
-
* the in-memory AgentProcess cache intact. A concurrent `teams start --watch`
|
|
2727
|
-
* supervisor then re-persisted those records via saveMeta, so a second
|
|
2728
|
-
* disband still found N logs to clear and `teams start` could re-launch
|
|
2729
|
-
* PENDING work that had already merged.
|
|
2730
|
-
*
|
|
2731
|
-
* This drops every matching record from the manager map AND removes its
|
|
2732
|
-
* durable state. With `keepLogs`, only `meta.json` is removed so the
|
|
2733
|
-
* teammate is no longer discoverable/startable while stdout/stderr logs
|
|
2734
|
-
* remain for postmortem.
|
|
2735
|
-
*
|
|
2736
|
-
* Returns the agent_ids that were purged.
|
|
2737
|
-
*/
|
|
2738
1894
|
async purgeByTask(taskName, opts) {
|
|
2739
1895
|
await this.initialize();
|
|
2740
1896
|
const roster = await this.listByTask(taskName);
|
|
@@ -2745,8 +1901,6 @@ export class AgentManager {
|
|
|
2745
1901
|
const agentDir = path.join(base, agent.agentId);
|
|
2746
1902
|
try {
|
|
2747
1903
|
if (opts?.keepLogs) {
|
|
2748
|
-
// Keep log files; remove only the record that makes the teammate
|
|
2749
|
-
// reappear in list/status/start.
|
|
2750
1904
|
await fs.rm(path.join(agentDir, 'meta.json'), { force: true });
|
|
2751
1905
|
}
|
|
2752
1906
|
else {
|
|
@@ -2756,8 +1910,6 @@ export class AgentManager {
|
|
|
2756
1910
|
}
|
|
2757
1911
|
catch (err) {
|
|
2758
1912
|
debug(`purgeByTask: failed to remove ${agent.agentId}: ${err}`);
|
|
2759
|
-
// Still count as purged from the roster — the in-memory drop above is
|
|
2760
|
-
// the load-bearing half against same-process resurrection.
|
|
2761
1913
|
purged.push(agent.agentId);
|
|
2762
1914
|
}
|
|
2763
1915
|
}
|
|
@@ -2790,9 +1942,6 @@ export class AgentManager {
|
|
|
2790
1942
|
if (!agent) {
|
|
2791
1943
|
return false;
|
|
2792
1944
|
}
|
|
2793
|
-
// Distributed teammate: no local PID — signal the dedicated process group
|
|
2794
|
-
// created by dispatch.ts. The persisted PID is the group leader, so one
|
|
2795
|
-
// negative-PID signal reaches the login-shell wrapper and every descendant.
|
|
2796
1945
|
if (agent.hostName && agent.status === AgentStatus.RUNNING) {
|
|
2797
1946
|
if (agent.hostTarget && agent.remotePid) {
|
|
2798
1947
|
try {
|
|
@@ -2803,7 +1952,6 @@ export class AgentManager {
|
|
|
2803
1952
|
});
|
|
2804
1953
|
}
|
|
2805
1954
|
catch {
|
|
2806
|
-
// best-effort — record the stop regardless
|
|
2807
1955
|
}
|
|
2808
1956
|
}
|
|
2809
1957
|
agent.status = AgentStatus.STOPPED;
|
|
@@ -2813,10 +1961,6 @@ export class AgentManager {
|
|
|
2813
1961
|
return true;
|
|
2814
1962
|
}
|
|
2815
1963
|
if (agent.pid && agent.status === AgentStatus.RUNNING) {
|
|
2816
|
-
// PID-reuse guard: if the PID we recorded at spawn no longer maps to
|
|
2817
|
-
// our process (start-time mismatch), the OS has recycled it. Sending
|
|
2818
|
-
// SIGTERM/SIGKILL to -pid here would kill an unrelated process group.
|
|
2819
|
-
// Treat as already gone and just record the stop without signaling.
|
|
2820
1964
|
if (!agent.isProcessAlive()) {
|
|
2821
1965
|
debug(`Agent ${agentId} PID ${agent.pid} no longer ours (start-time mismatch or exited); skipping signal`);
|
|
2822
1966
|
agent.status = AgentStatus.STOPPED;
|
|
@@ -2844,10 +1988,6 @@ export class AgentManager {
|
|
|
2844
1988
|
return false;
|
|
2845
1989
|
}
|
|
2846
1990
|
async cleanupOldAgents() {
|
|
2847
|
-
// listCompleted() is terminal-only (isTerminalStatus), so a pending or
|
|
2848
|
-
// running teammate is never a reap candidate — retention can only delete a
|
|
2849
|
-
// record whose process has finished. (RUSH-2356: the old `!== RUNNING`
|
|
2850
|
-
// filter reaped live `pending` `--after` teammates.)
|
|
2851
1991
|
const completed = await this.listCompleted();
|
|
2852
1992
|
if (completed.length > this.maxAgents) {
|
|
2853
1993
|
completed.sort((a, b) => {
|