@phnx-labs/agents-cli 1.22.39 → 1.22.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +316 -0
- package/README.md +116 -70
- package/dist/bin/agents +0 -0
- package/dist/bootstrap.js +45 -27
- package/dist/browser.js +2 -2
- package/dist/cli/command-registry.d.ts +135 -0
- package/dist/cli/command-registry.js +259 -0
- package/dist/commands/accounts.d.ts +20 -0
- package/dist/commands/accounts.js +186 -25
- package/dist/commands/apply.d.ts +3 -3
- package/dist/commands/apply.js +20 -63
- package/dist/commands/browser.d.ts +15 -0
- package/dist/commands/browser.js +318 -131
- package/dist/commands/budget.d.ts +7 -6
- package/dist/commands/budget.js +8 -7
- package/dist/commands/cloud.js +17 -20
- package/dist/commands/commands.js +1 -1
- package/dist/commands/computer-actions.d.ts +1 -35
- package/dist/commands/computer-actions.js +13 -181
- package/dist/commands/computer.d.ts +28 -3
- package/dist/commands/computer.js +93 -65
- package/dist/commands/config.js +16 -3
- package/dist/commands/cost.d.ts +2 -1
- package/dist/commands/cost.js +7 -6
- package/dist/commands/daemon.js +151 -4
- package/dist/commands/detach.js +1 -1
- package/dist/commands/doctor.js +19 -11
- package/dist/commands/events.js +1 -1
- package/dist/commands/exec.d.ts +2 -50
- package/dist/commands/exec.js +160 -215
- package/dist/commands/factory.js +1 -1
- package/dist/commands/feed.d.ts +2 -2
- package/dist/commands/feed.js +12 -23
- package/dist/commands/fleet-capture.js +25 -27
- package/dist/commands/focus.d.ts +2 -3
- package/dist/commands/focus.js +34 -9
- package/dist/commands/go.js +15 -5
- package/dist/commands/harness.d.ts +3 -3
- package/dist/commands/harness.js +53 -5
- package/dist/commands/hooks.js +1 -1
- package/dist/commands/import.js +2 -2
- package/dist/commands/insights.d.ts +5 -5
- package/dist/commands/insights.js +15 -9
- package/dist/commands/inspect.d.ts +2 -3
- package/dist/commands/inspect.js +4 -16
- package/dist/commands/logs.d.ts +2 -2
- package/dist/commands/logs.js +9 -9
- package/dist/commands/mcp.js +2 -2
- package/dist/commands/memory.js +1 -1
- package/dist/commands/message.d.ts +1 -1
- package/dist/commands/message.js +7 -7
- package/dist/commands/mine.d.ts +11 -8
- package/dist/commands/mine.js +11 -10
- package/dist/commands/models.js +1 -1
- package/dist/commands/modes.js +1 -1
- package/dist/commands/monitors.js +23 -6
- package/dist/commands/output.d.ts +7 -6
- package/dist/commands/output.js +11 -10
- package/dist/commands/packages.js +4 -4
- package/dist/commands/perf.js +1 -1
- package/dist/commands/permissions.js +49 -32
- package/dist/commands/plugins.d.ts +1 -1
- package/dist/commands/plugins.js +3 -3
- package/dist/commands/profiles.d.ts +6 -9
- package/dist/commands/profiles.js +8 -321
- package/dist/commands/projects.d.ts +9 -0
- package/dist/commands/projects.js +140 -8
- package/dist/commands/prune.js +5 -13
- package/dist/commands/refresh-rules.js +1 -1
- package/dist/commands/repo.d.ts +5 -7
- package/dist/commands/repo.js +34 -18
- package/dist/commands/resource-view.js +4 -0
- package/dist/commands/resume.d.ts +11 -7
- package/dist/commands/resume.js +82 -98
- package/dist/commands/route.d.ts +12 -0
- package/dist/commands/route.js +261 -0
- package/dist/commands/routines.d.ts +2 -3
- package/dist/commands/routines.js +120 -145
- package/dist/commands/rules.js +1 -1
- package/dist/commands/run-account-picker.d.ts +1 -1
- package/dist/commands/run-account-picker.js +2 -2
- package/dist/commands/run-broadcast.d.ts +21 -0
- package/dist/commands/run-broadcast.js +89 -0
- package/dist/commands/run-cloud.js +1 -1
- package/dist/commands/secrets-vault.d.ts +10 -0
- package/dist/commands/{login.js → secrets-vault.js} +34 -14
- package/dist/commands/secrets.d.ts +4 -4
- package/dist/commands/secrets.js +158 -159
- package/dist/commands/sessions-backfill.js +1 -1
- package/dist/commands/sessions-browser.d.ts +1 -1
- package/dist/commands/sessions-browser.js +9 -5
- package/dist/commands/sessions-export.js +2 -2
- package/dist/commands/sessions-inject.js +4 -5
- package/dist/commands/sessions-migrate.js +16 -27
- package/dist/commands/sessions-picker.d.ts +14 -0
- package/dist/commands/sessions-picker.js +209 -13
- package/dist/commands/sessions-resume.d.ts +7 -3
- package/dist/commands/sessions-resume.js +81 -33
- package/dist/commands/sessions-share.d.ts +25 -0
- package/dist/commands/sessions-share.js +166 -0
- package/dist/commands/sessions-stats.js +2 -2
- package/dist/commands/sessions.d.ts +75 -68
- package/dist/commands/sessions.js +144 -180
- package/dist/commands/setup-browser.js +1 -1
- package/dist/commands/setup-computer.js +1 -1
- package/dist/commands/setup-fleet.js +3 -0
- package/dist/commands/setup-mine.d.ts +7 -3
- package/dist/commands/setup-mine.js +13 -8
- package/dist/commands/setup-preferences.js +2 -2
- package/dist/commands/setup-secrets.js +2 -2
- package/dist/commands/setup-watchdog.js +2 -2
- package/dist/commands/setup.js +7 -2
- package/dist/commands/share.d.ts +65 -0
- package/dist/commands/share.js +253 -20
- package/dist/commands/skills.js +3 -3
- package/dist/commands/snapshot.d.ts +2 -2
- package/dist/commands/snapshot.js +9 -9
- package/dist/commands/ssh.d.ts +1 -1
- package/dist/commands/ssh.js +186 -64
- package/dist/commands/subagents.js +1 -1
- package/dist/commands/sync.js +24 -9
- package/dist/commands/teams.d.ts +2 -2
- package/dist/commands/teams.js +9 -18
- package/dist/commands/tmux.js +5 -1
- package/dist/commands/trash.js +1 -1
- package/dist/commands/usage.d.ts +1 -1
- package/dist/commands/usage.js +2 -2
- package/dist/commands/utils.d.ts +4 -14
- package/dist/commands/utils.js +6 -27
- package/dist/commands/versions.js +2 -2
- package/dist/commands/view.d.ts +9 -77
- package/dist/commands/view.js +23 -8
- package/dist/commands/watchdog.js +1 -1
- package/dist/commands/webhook.js +25 -34
- package/dist/commands/workflows.js +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/account-capabilities.d.ts +39 -0
- package/dist/lib/account-capabilities.js +59 -0
- package/dist/lib/account-catalog.js +1 -1
- package/dist/lib/account-registry.d.ts +66 -0
- package/dist/lib/account-registry.js +151 -5
- package/dist/lib/{rotate.d.ts → accounting/rotate.d.ts} +4 -4
- package/dist/lib/{rotate.js → accounting/rotate.js} +8 -8
- package/dist/lib/{usage.d.ts → accounting/usage.d.ts} +4 -4
- package/dist/lib/{usage.js → accounting/usage.js} +11 -11
- package/dist/lib/agent-spec/provider.js +1 -1
- package/dist/lib/agents.d.ts +72 -4
- package/dist/lib/agents.js +231 -199
- package/dist/lib/answer-router.d.ts +2 -2
- package/dist/lib/ask-classifier.d.ts +1 -1
- package/dist/lib/ask-classifier.js +1 -1
- package/dist/lib/audit/log.js +1 -1
- package/dist/lib/auth-health.d.ts +1 -1
- package/dist/lib/auth-health.js +2 -2
- package/dist/lib/brand.js +1 -1
- package/dist/lib/browser/caller-identity.d.ts +28 -0
- package/dist/lib/browser/caller-identity.js +156 -0
- package/dist/lib/browser/cdp.js +5 -1
- package/dist/lib/browser/chrome.js +12 -1
- package/dist/lib/browser/drivers/ssh.d.ts +1 -1
- package/dist/lib/browser/drivers/ssh.js +3 -2
- package/dist/lib/browser/hygiene.d.ts +10 -2
- package/dist/lib/browser/hygiene.js +7 -4
- package/dist/lib/browser/ipc.d.ts +22 -2
- package/dist/lib/browser/ipc.js +185 -21
- package/dist/lib/browser/profiles.d.ts +69 -5
- package/dist/lib/browser/profiles.js +135 -13
- package/dist/lib/browser/remote-control.d.ts +2 -2
- package/dist/lib/browser/remote-control.js +3 -3
- package/dist/lib/browser/runtime-state.d.ts +79 -0
- package/dist/lib/browser/runtime-state.js +119 -1
- package/dist/lib/browser/service.d.ts +137 -2
- package/dist/lib/browser/service.js +492 -54
- package/dist/lib/browser/sessions-list.d.ts +2 -1
- package/dist/lib/browser/sessions-list.js +4 -13
- package/dist/lib/browser/types.d.ts +19 -1
- package/dist/lib/budget/config.js +1 -1
- package/dist/lib/budget/ledger.js +1 -1
- package/dist/lib/byok-usage.js +1 -1
- package/dist/lib/capabilities.js +3 -15
- package/dist/lib/catchup.d.ts +1 -1
- package/dist/lib/catchup.js +1 -1
- package/dist/lib/cloud/dispatch.js +1 -1
- package/dist/lib/cloud/host.d.ts +3 -3
- package/dist/lib/cloud/host.js +5 -5
- package/dist/lib/cloud/rush.d.ts +9 -21
- package/dist/lib/cloud/rush.js +33 -120
- package/dist/lib/cloud/types.d.ts +2 -2
- package/dist/lib/commands.js +3 -13
- package/dist/lib/computer/actions.d.ts +36 -0
- package/dist/lib/computer/actions.js +162 -0
- package/dist/lib/computer/dispatch.d.ts +2 -2
- package/dist/lib/computer/dispatch.js +2 -2
- package/dist/lib/computer/sessions-list.d.ts +3 -3
- package/dist/lib/computer/sessions-list.js +2 -2
- package/dist/lib/config-keys.d.ts +2 -1
- package/dist/lib/config-keys.js +8 -4
- package/dist/lib/config-machine-keys.d.ts +4 -2
- package/dist/lib/config-machine-keys.js +5 -2
- package/dist/lib/crabbox/lease.js +9 -1
- package/dist/lib/crabbox/runtimes.d.ts +32 -7
- package/dist/lib/crabbox/runtimes.js +72 -30
- package/dist/lib/{daemon.d.ts → daemon/daemon.d.ts} +59 -1
- package/dist/lib/{daemon.js → daemon/daemon.js} +237 -49
- package/dist/lib/daemon-services.d.ts +1 -1
- package/dist/lib/daemon-services.js +5 -0
- package/dist/lib/daemon-ticks.d.ts +25 -0
- package/dist/lib/daemon-ticks.js +31 -1
- package/dist/lib/daemon-webhooks.d.ts +104 -0
- package/dist/lib/daemon-webhooks.js +215 -0
- package/dist/lib/device-config.d.ts +85 -75
- package/dist/lib/device-config.js +280 -142
- package/dist/lib/devices/config-migration.d.ts +29 -34
- package/dist/lib/devices/config-migration.js +209 -130
- package/dist/lib/devices/connect.d.ts +2 -2
- package/dist/lib/devices/connect.js +2 -2
- package/dist/lib/devices/discovery-policy.d.ts +30 -0
- package/dist/lib/devices/discovery-policy.js +101 -0
- package/dist/lib/devices/fleet-inventory.js +8 -3
- package/dist/lib/devices/harness-inventory.d.ts +1 -1
- package/dist/lib/devices/harness-inventory.js +12 -3
- package/dist/lib/devices/known-hosts.js +1 -1
- package/dist/lib/devices/pool.d.ts +10 -5
- package/dist/lib/devices/pool.js +5 -7
- package/dist/lib/devices/registry.d.ts +1 -1
- package/dist/lib/devices/registry.js +1 -1
- package/dist/lib/devices/resolve-profile.d.ts +2 -2
- package/dist/lib/devices/resolve-profile.js +2 -2
- package/dist/lib/devices/resolve-target.d.ts +1 -1
- package/dist/lib/devices/resolve-target.js +4 -4
- package/dist/lib/devices/self-host.d.ts +1 -1
- package/dist/lib/devices/self-host.js +3 -3
- package/dist/lib/devices/ssh-config.d.ts +1 -1
- package/dist/lib/devices/stats-cache.js +1 -1
- package/dist/lib/devices/sync.d.ts +3 -1
- package/dist/lib/devices/sync.js +3 -3
- package/dist/lib/doctor-diff.js +4 -4
- package/dist/lib/drift-sync.js +2 -2
- package/dist/lib/drift.js +2 -2
- package/dist/lib/event-families.d.ts +1 -1
- package/dist/lib/event-stream.d.ts +1 -1
- package/dist/lib/event-stream.js +2 -2
- package/dist/lib/events-ingest.js +2 -2
- package/dist/lib/exec.d.ts +4 -4
- package/dist/lib/exec.js +11 -11
- package/dist/lib/factory/snapshot.d.ts +1 -1
- package/dist/lib/factory/snapshot.js +1 -1
- package/dist/lib/{activity.d.ts → feed/activity.d.ts} +1 -1
- package/dist/lib/{activity.js → feed/activity.js} +7 -7
- package/dist/lib/{events.d.ts → feed/events.d.ts} +2 -2
- package/dist/lib/{events.js → feed/events.js} +5 -5
- package/dist/lib/{feed.js → feed/feed.js} +4 -4
- package/dist/lib/feed-outcome.d.ts +1 -1
- package/dist/lib/feed-policy.d.ts +1 -1
- package/dist/lib/feed-policy.js +1 -1
- package/dist/lib/feed-post.d.ts +1 -1
- package/dist/lib/feed-post.js +1 -1
- package/dist/lib/feed-ranking.d.ts +1 -1
- package/dist/lib/fleet/apply.d.ts +0 -6
- package/dist/lib/fleet/apply.js +18 -45
- package/dist/lib/fleet/auth-sync.d.ts +16 -35
- package/dist/lib/fleet/auth-sync.js +16 -75
- package/dist/lib/fleet/capture.js +8 -6
- package/dist/lib/fleet/manifest.js +23 -11
- package/dist/lib/fleet/types.d.ts +19 -7
- package/dist/lib/fleet-cache.d.ts +1 -1
- package/dist/lib/fleet-cache.js +1 -1
- package/dist/lib/format.d.ts +19 -0
- package/dist/lib/format.js +44 -1
- package/dist/lib/friction-heuristics.d.ts +1 -1
- package/dist/lib/git.d.ts +24 -1
- package/dist/lib/git.js +82 -38
- package/dist/lib/heal.js +3 -3
- package/dist/lib/hooks.d.ts +18 -0
- package/dist/lib/hooks.js +113 -1
- package/dist/lib/hosts/credentials.d.ts +30 -10
- package/dist/lib/hosts/credentials.js +38 -26
- package/dist/lib/hosts/dispatch.d.ts +3 -3
- package/dist/lib/hosts/dispatch.js +3 -3
- package/dist/lib/hosts/option.d.ts +3 -3
- package/dist/lib/hosts/option.js +7 -8
- package/dist/lib/hosts/passthrough.d.ts +17 -17
- package/dist/lib/hosts/passthrough.js +67 -50
- package/dist/lib/hosts/providers/devices.d.ts +1 -1
- package/dist/lib/hosts/providers/devices.js +1 -1
- package/dist/lib/hosts/reconcile.d.ts +1 -1
- package/dist/lib/hosts/reconcile.js +1 -1
- package/dist/lib/hosts/reconnect.d.ts +1 -1
- package/dist/lib/hosts/reconnect.js +2 -2
- package/dist/lib/hosts/registry.d.ts +5 -5
- package/dist/lib/hosts/registry.js +5 -5
- package/dist/lib/hosts/remote-cmd.d.ts +10 -10
- package/dist/lib/hosts/remote-cmd.js +25 -18
- package/dist/lib/hosts/remote-os.d.ts +4 -4
- package/dist/lib/hosts/remote-os.js +4 -4
- package/dist/lib/hosts/remote-session-id.d.ts +2 -2
- package/dist/lib/hosts/remote-session-id.js +2 -2
- package/dist/lib/hosts/routing-flag.d.ts +3 -3
- package/dist/lib/hosts/routing-flag.js +4 -5
- package/dist/lib/hosts/run-target.d.ts +4 -4
- package/dist/lib/hosts/run-target.js +4 -4
- package/dist/lib/hosts/session-index.d.ts +2 -2
- package/dist/lib/hosts/session-index.js +1 -1
- package/dist/lib/hosts/session-marker.d.ts +1 -1
- package/dist/lib/hosts/session-marker.js +1 -1
- package/dist/lib/hosts/types.d.ts +2 -2
- package/dist/lib/hosts/types.js +2 -2
- package/dist/lib/import.js +1 -1
- package/dist/lib/{migrate.d.ts → installations/migrate.d.ts} +13 -1
- package/dist/lib/{migrate.js → installations/migrate.js} +160 -40
- package/dist/lib/installations/resolve.js +1 -1
- package/dist/lib/installations/strategies.js +1 -1
- package/dist/lib/installations/update.js +2 -2
- package/dist/lib/{versions.d.ts → installations/versions.d.ts} +12 -3
- package/dist/lib/{versions.js → installations/versions.js} +51 -31
- package/dist/lib/isolation-boundary-report.js +1 -1
- package/dist/lib/linear-projects.d.ts +28 -0
- package/dist/lib/linear-projects.js +30 -0
- package/dist/lib/loop.js +1 -1
- package/dist/lib/mailbox-gc.js +1 -1
- package/dist/lib/mailbox.js +1 -1
- package/dist/lib/mcp-registry.d.ts +62 -0
- package/dist/lib/mcp-registry.js +177 -0
- package/dist/lib/mcp.d.ts +5 -0
- package/dist/lib/mcp.js +124 -307
- package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
- package/dist/lib/menubar/install-menubar.d.ts +7 -0
- package/dist/lib/menubar/install-menubar.js +24 -6
- package/dist/lib/menubar/snapshot.d.ts +7 -0
- package/dist/lib/menubar/snapshot.js +8 -6
- package/dist/lib/models.js +1 -1
- package/dist/lib/monitors/config.d.ts +12 -0
- package/dist/lib/monitors/config.js +3 -0
- package/dist/lib/monitors/dispatch.js +26 -5
- package/dist/lib/monitors/engine.js +10 -0
- package/dist/lib/monitors/sources/webhook.d.ts +1 -1
- package/dist/lib/monitors/state.d.ts +42 -0
- package/dist/lib/monitors/state.js +30 -0
- package/dist/lib/notify.d.ts +1 -1
- package/dist/lib/observe-aliases.d.ts +3 -3
- package/dist/lib/observe-aliases.js +3 -21
- package/dist/lib/output/git-output.js +2 -2
- package/dist/lib/overdue.d.ts +1 -1
- package/dist/lib/overdue.js +1 -1
- package/dist/lib/permissions-registry.d.ts +65 -0
- package/dist/lib/permissions-registry.js +599 -0
- package/dist/lib/permissions.d.ts +24 -13
- package/dist/lib/permissions.js +52 -271
- package/dist/lib/picker.d.ts +16 -0
- package/dist/lib/picker.js +33 -3
- package/dist/lib/placement.d.ts +1 -1
- package/dist/lib/placement.js +4 -4
- package/dist/lib/platform/paths.d.ts +8 -0
- package/dist/lib/platform/paths.js +11 -0
- package/dist/lib/platform/posixpath.js +3 -3
- package/dist/lib/{plugin-marketplace.d.ts → plugins/plugin-marketplace.d.ts} +1 -1
- package/dist/lib/{plugin-marketplace.js → plugins/plugin-marketplace.js} +2 -2
- package/dist/lib/{plugins.d.ts → plugins/plugins.d.ts} +1 -1
- package/dist/lib/{plugins.js → plugins/plugins.js} +7 -7
- package/dist/lib/{skills.d.ts → plugins/skills.d.ts} +1 -1
- package/dist/lib/{skills.js → plugins/skills.js} +7 -7
- package/dist/lib/pricing/cost.d.ts +1 -1
- package/dist/lib/pricing/cost.js +1 -1
- package/dist/lib/profiles-presets.d.ts +1 -1
- package/dist/lib/profiles-presets.js +1 -1
- package/dist/lib/profiles.js +2 -2
- package/dist/lib/project-import.js +4 -1
- package/dist/lib/project-key.js +7 -0
- package/dist/lib/project-launch.d.ts +1 -1
- package/dist/lib/project-launch.js +3 -3
- package/dist/lib/project-pull.d.ts +128 -0
- package/dist/lib/project-pull.js +384 -0
- package/dist/lib/project-root.d.ts +2 -2
- package/dist/lib/project-root.js +2 -2
- package/dist/lib/project-status.js +1 -1
- package/dist/lib/projects.d.ts +23 -0
- package/dist/lib/projects.js +29 -6
- package/dist/lib/refresh.d.ts +12 -1
- package/dist/lib/refresh.js +16 -9
- package/dist/lib/registry.d.ts +9 -2
- package/dist/lib/registry.js +11 -4
- package/dist/lib/resources.d.ts +2 -2
- package/dist/lib/resources.js +2 -2
- package/dist/lib/routers.d.ts +81 -0
- package/dist/lib/routers.js +153 -0
- package/dist/lib/routine-context.d.ts +1 -0
- package/dist/lib/routine-context.js +7 -2
- package/dist/lib/routine-notify-owner.d.ts +1 -1
- package/dist/lib/routine-notify.d.ts +1 -1
- package/dist/lib/routine-notify.js +1 -1
- package/dist/lib/routine-process-cleanup.d.ts +1 -1
- package/dist/lib/routine-readiness.d.ts +1 -1
- package/dist/lib/routine-readiness.js +11 -4
- package/dist/lib/routines-placement.d.ts +12 -2
- package/dist/lib/routines-placement.js +20 -3
- package/dist/lib/routines-project.d.ts +1 -1
- package/dist/lib/routines-project.js +1 -1
- package/dist/lib/rules/compile.d.ts +1 -0
- package/dist/lib/rules/compile.js +10 -2
- package/dist/lib/rules/rules.js +1 -1
- package/dist/lib/run-notify.js +1 -1
- package/dist/lib/runner.d.ts +80 -2
- package/dist/lib/runner.js +261 -67
- package/dist/lib/sandbox.d.ts +1 -1
- package/dist/lib/scheduler.d.ts +1 -1
- package/dist/lib/scheduler.js +1 -1
- package/dist/lib/{routines.d.ts → scheduling/routines.d.ts} +54 -9
- package/dist/lib/{routines.js → scheduling/routines.js} +173 -14
- package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
- package/dist/lib/secrets/agent.js +2 -2
- package/dist/lib/secrets/audit.js +1 -1
- package/dist/lib/secrets/bundles.d.ts +4 -4
- package/dist/lib/secrets/bundles.js +8 -8
- package/dist/lib/secrets/headless.d.ts +16 -0
- package/dist/lib/secrets/headless.js +21 -0
- package/dist/lib/secrets/index.js +1 -1
- package/dist/lib/secrets/list-filter.d.ts +1 -1
- package/dist/lib/secrets/list-filter.js +2 -2
- package/dist/lib/secrets/push.d.ts +1 -1
- package/dist/lib/secrets/push.js +10 -12
- package/dist/lib/secrets/remote.d.ts +21 -17
- package/dist/lib/secrets/remote.js +39 -23
- package/dist/lib/secrets/vault.js +2 -2
- package/dist/lib/self-heal/checks/shadowing.js +1 -1
- package/dist/lib/self-heal/checks/shims.js +1 -1
- package/dist/lib/self-update.d.ts +39 -4
- package/dist/lib/self-update.js +78 -25
- package/dist/lib/serve/control.d.ts +1 -1
- package/dist/lib/serve/control.js +4 -4
- package/dist/lib/serve/data.d.ts +1 -1
- package/dist/lib/serve/data.js +1 -1
- package/dist/lib/serve/stream.js +1 -1
- package/dist/lib/service-manifest.d.ts +29 -0
- package/dist/lib/service-manifest.js +80 -0
- package/dist/lib/session/active.d.ts +59 -7
- package/dist/lib/session/active.js +158 -17
- package/dist/lib/session/bash-command.js +1 -1
- package/dist/lib/session/claude-accounts.d.ts +1 -1
- package/dist/lib/session/claude-accounts.js +1 -1
- package/dist/lib/session/db.d.ts +10 -2
- package/dist/lib/session/db.js +25 -6
- package/dist/lib/session/discover.d.ts +77 -0
- package/dist/lib/session/discover.js +130 -25
- package/dist/lib/session/fork.js +1 -1
- package/dist/lib/session/inject.d.ts +1 -1
- package/dist/lib/session/insights.d.ts +1 -1
- package/dist/lib/session/insights.js +1 -1
- package/dist/lib/session/live-metadata.d.ts +15 -0
- package/dist/lib/session/live-metadata.js +76 -0
- package/dist/lib/session/migrate-targets.d.ts +1 -1
- package/dist/lib/session/recovery.d.ts +1 -1
- package/dist/lib/session/recovery.js +2 -2
- package/dist/lib/session/remote-active.d.ts +10 -1
- package/dist/lib/session/remote-active.js +8 -3
- package/dist/lib/session/remote-bundle.d.ts +1 -1
- package/dist/lib/session/remote-bundle.js +2 -2
- package/dist/lib/session/remote-list.d.ts +15 -4
- package/dist/lib/session/remote-list.js +40 -3
- package/dist/lib/session/remote.d.ts +5 -5
- package/dist/lib/session/remote.js +13 -17
- package/dist/lib/session/resume-command.d.ts +3 -2
- package/dist/lib/session/resume-command.js +4 -3
- package/dist/lib/session/resume-owner.d.ts +3 -3
- package/dist/lib/session/resume-owner.js +3 -3
- package/dist/lib/session/session-cache.d.ts +12 -0
- package/dist/lib/session/session-cache.js +2 -0
- package/dist/lib/session/share-html.d.ts +55 -0
- package/dist/lib/session/share-html.js +319 -0
- package/dist/lib/session/shell-programs.js +1 -1
- package/dist/lib/session/state.js +5 -5
- package/dist/lib/session/team-filter.d.ts +1 -1
- package/dist/lib/session/team-filter.js +1 -1
- package/dist/lib/session/types.d.ts +3 -3
- package/dist/lib/session/width.d.ts +2 -2
- package/dist/lib/session/width.js +2 -2
- package/dist/lib/settings-manifest.d.ts +2 -0
- package/dist/lib/settings-manifest.js +81 -3
- package/dist/lib/share/delete.d.ts +21 -0
- package/dist/lib/share/delete.js +42 -0
- package/dist/lib/share/publish.d.ts +120 -0
- package/dist/lib/share/publish.js +243 -18
- package/dist/lib/share/worker-template.js +172 -9
- package/dist/lib/shims.js +35 -7
- package/dist/lib/smart-launch.d.ts +4 -4
- package/dist/lib/smart-launch.js +6 -4
- package/dist/lib/snapshot.d.ts +4 -4
- package/dist/lib/snapshot.js +2 -2
- package/dist/lib/ssh-exec.d.ts +1 -1
- package/dist/lib/ssh-exec.js +2 -2
- package/dist/lib/ssh-tunnel.d.ts +10 -10
- package/dist/lib/ssh-tunnel.js +12 -12
- package/dist/lib/staleness/checkers/hooks.d.ts +1 -1
- package/dist/lib/staleness/checkers/hooks.js +1 -1
- package/dist/lib/staleness/detectors/permissions.js +0 -23
- package/dist/lib/staleness/detectors/plugins.js +1 -1
- package/dist/lib/staleness/fingerprint.js +1 -1
- package/dist/lib/staleness/layers.d.ts +1 -1
- package/dist/lib/staleness/layers.js +1 -1
- package/dist/lib/staleness/writers/mcp.js +3 -1
- package/dist/lib/staleness/writers/plugins.js +1 -1
- package/dist/lib/staleness/writers/types.d.ts +8 -0
- package/dist/lib/startup/command-registry.d.ts +6 -147
- package/dist/lib/startup/command-registry.js +40 -303
- package/dist/lib/startup/dev-build.d.ts +0 -21
- package/dist/lib/startup/dev-build.js +29 -8
- package/dist/lib/state.d.ts +19 -1
- package/dist/lib/state.js +120 -51
- package/dist/lib/subagents.js +1 -1
- package/dist/lib/sync-status.js +1 -1
- package/dist/lib/sync-umbrella.d.ts +6 -1
- package/dist/lib/sync-umbrella.js +9 -4
- package/dist/lib/teams/agents.js +2 -2
- package/dist/lib/teams/registry.js +1 -1
- package/dist/lib/terminal/backends/vscodium-agent.js +1 -1
- package/dist/lib/terminal/engine.js +1 -1
- package/dist/lib/terminal/index.d.ts +4 -0
- package/dist/lib/terminal/index.js +3 -0
- package/dist/lib/terminal/inject.d.ts +2 -2
- package/dist/lib/terminal/inject.js +2 -2
- package/dist/lib/terminal/transport.js +1 -1
- package/dist/lib/tmux/index.d.ts +1 -1
- package/dist/lib/tmux/index.js +1 -1
- package/dist/lib/tmux/session.d.ts +21 -5
- package/dist/lib/tmux/session.js +76 -22
- package/dist/lib/triggers/handlers.d.ts +38 -3
- package/dist/lib/triggers/handlers.js +58 -7
- package/dist/lib/triggers/webhook.d.ts +113 -5
- package/dist/lib/triggers/webhook.js +223 -44
- package/dist/lib/types.d.ts +19 -7
- package/dist/lib/usage-fleet.d.ts +1 -1
- package/dist/lib/usage-fleet.js +1 -1
- package/dist/lib/usage-refresh.d.ts +1 -1
- package/dist/lib/usage-refresh.js +3 -3
- package/dist/lib/version-duplicates.js +2 -2
- package/dist/lib/view-types.d.ts +56 -0
- package/dist/lib/view-types.js +1 -0
- package/dist/lib/watchdog/rotate.d.ts +2 -2
- package/dist/lib/watchdog/rotate.js +3 -3
- package/dist/lib/watchdog/runner.d.ts +2 -3
- package/dist/lib/watchdog/runner.js +3 -4
- package/dist/lib/workflows.js +1 -1
- package/dist/lib/wrap.d.ts +33 -0
- package/dist/lib/wrap.js +70 -0
- package/package.json +2 -1
- package/scripts/postinstall.js +2 -2
- package/dist/commands/bench.d.ts +0 -2
- package/dist/commands/bench.js +0 -101
- package/dist/commands/cp.d.ts +0 -84
- package/dist/commands/cp.js +0 -231
- package/dist/commands/login.d.ts +0 -2
- package/dist/lib/resources/commands.d.ts +0 -46
- package/dist/lib/resources/commands.js +0 -211
- package/dist/lib/resources/hooks.d.ts +0 -16
- package/dist/lib/resources/hooks.js +0 -153
- package/dist/lib/resources/mcp.d.ts +0 -34
- package/dist/lib/resources/mcp.js +0 -250
- package/dist/lib/resources/memory.d.ts +0 -15
- package/dist/lib/resources/memory.js +0 -46
- package/dist/lib/resources/permissions.d.ts +0 -13
- package/dist/lib/resources/permissions.js +0 -202
- package/dist/lib/resources/rules.d.ts +0 -46
- package/dist/lib/resources/rules.js +0 -179
- package/dist/lib/resources/skills.d.ts +0 -37
- package/dist/lib/resources/skills.js +0 -247
- package/dist/lib/resources/subagents.d.ts +0 -46
- package/dist/lib/resources/subagents.js +0 -202
- /package/dist/lib/{feed.d.ts → feed/feed.d.ts} +0 -0
package/dist/lib/runner.js
CHANGED
|
@@ -18,15 +18,15 @@ import * as fs from 'fs';
|
|
|
18
18
|
import * as path from 'path';
|
|
19
19
|
import * as os from 'os';
|
|
20
20
|
import { getCliLaunch, getAgentsBinDir } from './cli-entry.js';
|
|
21
|
-
import { resolveJobPrompt, parseTimeout, writeRunMeta, listRuns, getJobRunsDir, getRunDir, checkJobDeviceEligibility, finalizeRunMeta, resolveJobExecutionContext, slotRunId, claimRunSlot, readRunMeta, resolveHostStrategy, } from './routines.js';
|
|
22
|
-
import { getRunsDir, getUserAgentsDir, readMeta } from './state.js';
|
|
21
|
+
import { resolveJobPrompt, parseTimeout, writeRunMeta, listRuns, getJobRunsDir, getRunDir, checkJobDeviceEligibility, finalizeRunMeta, resolveJobExecutionContext, slotRunId, claimRunSlot, readRunMeta, resolveHostStrategy, } from './scheduling/routines.js';
|
|
22
|
+
import { getRunsDir, getUserAgentsDir, readMeta, getDaemonDir } from './state.js';
|
|
23
23
|
import { shortCodexHome } from './codex-home.js';
|
|
24
24
|
import { prepareJobHome, buildSpawnEnv, getJobHomePath } from './sandbox.js';
|
|
25
25
|
import { resolveModel, buildReasoningFlags } from './models.js';
|
|
26
|
-
import { createTimer, redactPrompt, emitRoutineEnd } from './events.js';
|
|
26
|
+
import { createTimer, redactPrompt, emitRoutineEnd } from './feed/events.js';
|
|
27
27
|
import { codexEditWritableRoots, codexPolicyArgs } from './codex-policy.js';
|
|
28
28
|
import { applyAddDirs } from './add-dir.js';
|
|
29
|
-
import { normalizeMode, resolveHeadlessMode, buildExecEnv, detectRateLimit, detectAuthFailure, isAuthFailureFromLog, authFailureReason, } from './exec.js';
|
|
29
|
+
import { normalizeMode, resolveHeadlessMode, buildExecEnv, detectRateLimit, detectAuthFailure, isAuthFailureFromLog, authFailureReason, AGENT_COMMANDS, } from './exec.js';
|
|
30
30
|
import { resolveActor } from './actor.js';
|
|
31
31
|
import { loadTask as loadHostTask } from './hosts/tasks.js';
|
|
32
32
|
import { reconcileTask as reconcileHostTask } from './hosts/reconcile.js';
|
|
@@ -34,12 +34,12 @@ import { backgroundSpawnOptions, killTree } from './platform/process.js';
|
|
|
34
34
|
import lockfile from 'proper-lockfile';
|
|
35
35
|
import { ensureLockTarget } from './fs-atomic.js';
|
|
36
36
|
import { walkForFiles } from './fs-walk.js';
|
|
37
|
-
import { getBinaryPath, isVersionInstalled, resolveVersion, getVersionHomePath } from './versions.js';
|
|
37
|
+
import { getBinaryPath, isVersionInstalled, resolveVersion, getVersionHomePath } from './installations/versions.js';
|
|
38
38
|
import { resolveClaudeSetupToken } from './claude-account-token.js';
|
|
39
|
-
import { getConfiguredRunStrategy, resolveRunVersion, resolveAccountVersion, rotationFailoverChain, readinessFromCandidate, formatNoHealthyAccountError, } from './rotate.js';
|
|
39
|
+
import { getConfiguredRunStrategy, resolveRunVersion, resolveAccountVersion, rotationFailoverChain, readinessFromCandidate, formatNoHealthyAccountError, } from './accounting/rotate.js';
|
|
40
40
|
import { readAuthHealth, isDeadVerdict } from './auth-health.js';
|
|
41
41
|
import { machineId } from './machine-id.js';
|
|
42
|
-
import { isSelfUpdatingAgent, ROUTINE_AGENT_COMMANDS
|
|
42
|
+
import { isSelfUpdatingAgent, ROUTINE_AGENT_COMMANDS, isAgentHardDeprecated, hardDeprecationError } from './agents.js';
|
|
43
43
|
export class RoutineAlreadyRunningError extends Error {
|
|
44
44
|
constructor(jobName, runId) {
|
|
45
45
|
super(`Routine '${jobName}' already has a running execution (${runId})`);
|
|
@@ -48,24 +48,97 @@ export class RoutineAlreadyRunningError extends Error {
|
|
|
48
48
|
}
|
|
49
49
|
const ROUTINE_LAUNCH_LOCK_STALE_MS = 30_000;
|
|
50
50
|
const ROUTINE_LAUNCH_LOCK_WAIT_MS = 10_000;
|
|
51
|
+
/**
|
|
52
|
+
* The prior run of this routine that still holds the active-run slot, or null.
|
|
53
|
+
*
|
|
54
|
+
* ONLY a run still marked `running` can hold the slot. Every terminal status —
|
|
55
|
+
* completed / failed / timeout / missed / blocked / skipped — releases it the
|
|
56
|
+
* moment it is reached (RUSH-2640). A `failed`/`timeout` record used to keep the
|
|
57
|
+
* slot while its pid stayed alive, but that conflated two different operations:
|
|
58
|
+
* cleaning up a leftover process group (reapTerminalRoutineProcesses's job) with
|
|
59
|
+
* occupying the slot. A daemon-launched run that reached a terminal state while
|
|
60
|
+
* still carrying the daemon's own pid (a host run that threw `target_unreachable`
|
|
61
|
+
* before spawning a child) then held the slot forever, because the daemon never
|
|
62
|
+
* dies and `isPidOurs` never went false — every later scheduled slot was refused
|
|
63
|
+
* with `already has an active run` while the routine was silently dead.
|
|
64
|
+
*
|
|
65
|
+
* A `running` record is also aged out past its own timeout: a run cannot
|
|
66
|
+
* legitimately outlive its configured deadline, so past that window it is a
|
|
67
|
+
* wedged record (a daemon that died mid-run, a missed child-exit event, a reused
|
|
68
|
+
* pid an old record without `spawnedAt` reads as "ours"), not a live run — and it
|
|
69
|
+
* never holds the slot regardless of what its recorded pid now points at.
|
|
70
|
+
*/
|
|
51
71
|
function activeRoutineRun(config) {
|
|
52
72
|
const timeoutMs = parseTimeout(config.timeout) || 10 * 60 * 1000;
|
|
53
73
|
const now = Date.now();
|
|
54
74
|
const runs = listRuns(config.name);
|
|
55
75
|
for (let i = runs.length - 1; i >= 0; i--) {
|
|
56
76
|
const run = runs[i];
|
|
57
|
-
if (
|
|
77
|
+
if (run.status !== 'running')
|
|
78
|
+
continue;
|
|
79
|
+
const startedAt = Date.parse(run.startedAt);
|
|
80
|
+
const limit = run.timeoutMs ?? timeoutMs;
|
|
81
|
+
if (Number.isFinite(startedAt) && now - startedAt >= limit)
|
|
58
82
|
continue;
|
|
59
|
-
|
|
83
|
+
// A provisional launcher claim carries no child pid yet — trust it until the
|
|
84
|
+
// timeout window above elapses. A record with a child pid is active only
|
|
85
|
+
// while that pid is genuinely ours (alive with the same birth time).
|
|
86
|
+
if (!run.pid)
|
|
87
|
+
return run;
|
|
88
|
+
if (isPidOurs(run.pid, run.spawnedAt))
|
|
60
89
|
return run;
|
|
61
|
-
if (!run.pid) {
|
|
62
|
-
const startedAt = Date.parse(run.startedAt);
|
|
63
|
-
if (Number.isFinite(startedAt) && now - startedAt < (run.timeoutMs ?? timeoutMs))
|
|
64
|
-
return run;
|
|
65
|
-
}
|
|
66
90
|
}
|
|
67
91
|
return null;
|
|
68
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Consecutive trailing `skipped`/`active_run` records — a routine that keeps
|
|
95
|
+
* being refused because a prior run "still owns" the slot. After the slot is
|
|
96
|
+
* released correctly on terminal states (see {@link activeRoutineRun}) this can
|
|
97
|
+
* only accumulate for a genuine long-overlap or a new wedge; either way it means
|
|
98
|
+
* the routine has stopped firing on schedule and should be surfaced, not left to
|
|
99
|
+
* pile up silently. `runs` is oldest→newest (listRuns sorts by run id).
|
|
100
|
+
*/
|
|
101
|
+
export function activeRunSkipStreak(runs) {
|
|
102
|
+
let streak = 0;
|
|
103
|
+
for (let i = runs.length - 1; i >= 0; i--) {
|
|
104
|
+
const run = runs[i];
|
|
105
|
+
if (run.status === 'skipped' && run.skipReason === 'active_run') {
|
|
106
|
+
streak++;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
return streak;
|
|
112
|
+
}
|
|
113
|
+
/** How many consecutive active-run skips before a routine's stall is surfaced. */
|
|
114
|
+
const SKIP_STREAK_ALERT_THRESHOLD = 3;
|
|
115
|
+
/**
|
|
116
|
+
* The pid to stamp on a launcher's provisional active claim, or null when the
|
|
117
|
+
* launcher is this box's routines daemon.
|
|
118
|
+
*
|
|
119
|
+
* The claim pid exists so a launcher that dies between claiming the slot and
|
|
120
|
+
* spawning the child releases the slot quickly (`isPidOurs` goes false) instead
|
|
121
|
+
* of wedging it for the full timeout. That fast recovery only helps a SHORT-LIVED
|
|
122
|
+
* foreground launcher (`agents routines run`): the daemon never dies between
|
|
123
|
+
* claim and spawn, and recording ITS pid is actively harmful — the daemon
|
|
124
|
+
* outlives every run, so `isPidOurs` never goes false and a claim finalized to a
|
|
125
|
+
* terminal state before its child spawned kept the slot and drew
|
|
126
|
+
* `reapTerminalRoutineProcesses` at the daemon's own process group on every tick
|
|
127
|
+
* (RUSH-2640, requirement: never record the daemon's own pid as a run's pid). So
|
|
128
|
+
* the daemon records no claim pid; the timeout window bounds a daemon that
|
|
129
|
+
* crashes mid-claim instead.
|
|
130
|
+
*/
|
|
131
|
+
export function launcherClaimPid() {
|
|
132
|
+
try {
|
|
133
|
+
// Mirrors daemon.ts readDaemonPid() (PID_FILE = 'daemon.pid'); read directly
|
|
134
|
+
// rather than importing it to avoid a runner<->daemon import cycle.
|
|
135
|
+
const daemonPid = parseInt(fs.readFileSync(path.join(getDaemonDir(), 'daemon.pid'), 'utf-8').trim(), 10);
|
|
136
|
+
if (Number.isFinite(daemonPid) && daemonPid === process.pid)
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
catch { /* no daemon pid file — a foreground launcher; record its pid */ }
|
|
140
|
+
return process.pid;
|
|
141
|
+
}
|
|
69
142
|
/** Serialize concurrent launches of one routine on this box (the on-disk claim
|
|
70
143
|
* primitive `claimRunSlot` is what holds across processes; this lock only makes
|
|
71
144
|
* the allocate→spawn window atomic within this process's launch paths). */
|
|
@@ -150,10 +223,13 @@ function writeActiveClaim(config, attempt) {
|
|
|
150
223
|
...attempt.stamp,
|
|
151
224
|
...(config.workflow ? { workflow: config.workflow } : config.command ? { command: config.command } : config.agent ? { agent: config.agent } : {}),
|
|
152
225
|
// The launcher owns this provisional claim until the command/agent child
|
|
153
|
-
// replaces it with its own pid. Recording
|
|
154
|
-
// lock release and child spawn recoverable instead
|
|
155
|
-
// for its full configured timeout.
|
|
156
|
-
pid:
|
|
226
|
+
// replaces it with its own pid. Recording a SHORT-LIVED foreground launcher's
|
|
227
|
+
// pid makes a crash between lock release and child spawn recoverable instead
|
|
228
|
+
// of wedging the routine for its full configured timeout. The long-lived
|
|
229
|
+
// daemon records no pid here (see launcherClaimPid): its pid never dies, so
|
|
230
|
+
// recording it wedged the slot forever and mis-aimed the process reaper at the
|
|
231
|
+
// daemon itself (RUSH-2640).
|
|
232
|
+
pid: launcherClaimPid(),
|
|
157
233
|
// `isPidOurs` compares this value with the OS process birth time. The
|
|
158
234
|
// daemon may have been alive for days before claiming a routine, so the
|
|
159
235
|
// claim must carry the launcher's birth, not the claim timestamp.
|
|
@@ -228,7 +304,11 @@ function allocateRoutineAttempt(config, trigger) {
|
|
|
228
304
|
}),
|
|
229
305
|
};
|
|
230
306
|
}
|
|
231
|
-
|
|
307
|
+
// Gate on deprecation alone, not ROUTINE_AGENT_IDS membership — a retired
|
|
308
|
+
// harness leaves the command table (gemini did), and the legacy routine must
|
|
309
|
+
// still land a visible 'blocked' record, never a generic buildJobCommand
|
|
310
|
+
// failure (RUSH-2202).
|
|
311
|
+
if (!config.workflow && config.agent && isAgentHardDeprecated(config.agent)) {
|
|
232
312
|
const reason = hardDeprecationError(config.agent);
|
|
233
313
|
return {
|
|
234
314
|
proceed: false,
|
|
@@ -278,6 +358,24 @@ function allocateRoutineAttempt(config, trigger) {
|
|
|
278
358
|
}
|
|
279
359
|
return { proceed: true, attempt: { runId, stamp } };
|
|
280
360
|
}
|
|
361
|
+
/**
|
|
362
|
+
* Emit a loud, once-per-wedge warning when a routine has been refused its slot
|
|
363
|
+
* for {@link SKIP_STREAK_ALERT_THRESHOLD} consecutive scheduled runs. Fires only
|
|
364
|
+
* when the streak first reaches the threshold (not on every later skip), so a
|
|
365
|
+
* genuinely-stalled routine surfaces once instead of piling up silent `skipped`
|
|
366
|
+
* records the way RUSH-2640 did. Runs on the daemon's own stderr, so it lands in
|
|
367
|
+
* the daemon log the operator reads.
|
|
368
|
+
*/
|
|
369
|
+
function surfaceWedgedRoutine(config, terminal) {
|
|
370
|
+
if (terminal.status !== 'skipped' || terminal.skipReason !== 'active_run')
|
|
371
|
+
return;
|
|
372
|
+
const streak = activeRunSkipStreak(listRuns(config.name));
|
|
373
|
+
if (streak !== SKIP_STREAK_ALERT_THRESHOLD)
|
|
374
|
+
return;
|
|
375
|
+
const stuck = terminal.activeRunId ?? 'unknown';
|
|
376
|
+
process.stderr.write(`[agents] routine '${config.name}' skipped ${streak} consecutive scheduled runs — ` +
|
|
377
|
+
`its active-run slot is still held by ${stuck}; the routine is not firing on schedule.\n`);
|
|
378
|
+
}
|
|
281
379
|
/**
|
|
282
380
|
* Claim one routine attempt under the short launch lock, then execute after
|
|
283
381
|
* releasing it. The persisted `running` claim makes a concurrent entry point
|
|
@@ -293,8 +391,10 @@ async function runWithAttempt(config, trigger, run, wrapTerminal) {
|
|
|
293
391
|
writeActiveClaim(config, alloc.attempt);
|
|
294
392
|
return { attempt: alloc.attempt };
|
|
295
393
|
});
|
|
296
|
-
if ('terminal' in claimed)
|
|
394
|
+
if ('terminal' in claimed) {
|
|
395
|
+
surfaceWedgedRoutine(config, claimed.terminal);
|
|
297
396
|
return wrapTerminal(claimed.terminal);
|
|
397
|
+
}
|
|
298
398
|
try {
|
|
299
399
|
return await run(claimed.attempt);
|
|
300
400
|
}
|
|
@@ -316,13 +416,31 @@ async function runWithAttempt(config, trigger, run, wrapTerminal) {
|
|
|
316
416
|
function terminateRoutineTree(pid) {
|
|
317
417
|
if (!pid)
|
|
318
418
|
return;
|
|
419
|
+
// Never take THIS process down. Both kills below are unconditional SIGKILLs,
|
|
420
|
+
// so a RunMeta naming the reaper's own pid -- a reused pid, a record written
|
|
421
|
+
// by the process now doing the reaping, or a hand-written fixture -- makes the
|
|
422
|
+
// reaper SIGKILL itself, and via `-pid` its whole process group with it. There
|
|
423
|
+
// is no recovery from that: the run is never finalized, and on the daemon it
|
|
424
|
+
// takes the scheduler down mid-sweep. daemon.ts:457 already refuses to evict an
|
|
425
|
+
// incumbent whose pid is `process.pid` for exactly this reason; the reap path
|
|
426
|
+
// needs the same guard. Skipping the kill still lets the caller finalize the
|
|
427
|
+
// run record, which is the part that matters.
|
|
428
|
+
if (pid === process.pid)
|
|
429
|
+
return;
|
|
319
430
|
if (process.platform === 'win32') {
|
|
320
431
|
killTree(pid);
|
|
321
432
|
return;
|
|
322
433
|
}
|
|
434
|
+
// Detached spawn makes the child a new process-group leader; kill the group.
|
|
435
|
+
// If setsid has not landed yet (or the pid is not a leader), -pid fails with
|
|
436
|
+
// ESRCH and the child stays up — also kill the pid itself.
|
|
323
437
|
try {
|
|
324
438
|
process.kill(-pid, 'SIGKILL');
|
|
325
439
|
}
|
|
440
|
+
catch { /* not a group leader, or already exited */ }
|
|
441
|
+
try {
|
|
442
|
+
process.kill(pid, 'SIGKILL');
|
|
443
|
+
}
|
|
326
444
|
catch { /* already exited */ }
|
|
327
445
|
}
|
|
328
446
|
/**
|
|
@@ -396,7 +514,7 @@ export function buildJobCommand(config, resolvedPrompt, forwardAccount = true) {
|
|
|
396
514
|
cmd.push('--account', config.account);
|
|
397
515
|
return cmd;
|
|
398
516
|
}
|
|
399
|
-
const template =
|
|
517
|
+
const template = ROUTINE_AGENT_COMMANDS[agent];
|
|
400
518
|
if (!template) {
|
|
401
519
|
throw new Error(`Unsupported agent for daemon jobs: ${agent}`);
|
|
402
520
|
}
|
|
@@ -433,15 +551,6 @@ export function buildJobCommand(config, resolvedPrompt, forwardAccount = true) {
|
|
|
433
551
|
cmd.push(...codexPolicyArgs(policyMode, [...codexEditWritableRoots(), ...routineRoots]));
|
|
434
552
|
appendModelAndReasoning(cmd, config);
|
|
435
553
|
}
|
|
436
|
-
if (config.agent === 'gemini') {
|
|
437
|
-
if (mode === 'edit') {
|
|
438
|
-
cmd.push('--approval-mode', 'auto_edit');
|
|
439
|
-
}
|
|
440
|
-
else if (mode === 'skip') {
|
|
441
|
-
cmd.push('--yolo');
|
|
442
|
-
}
|
|
443
|
-
appendModelAndReasoning(cmd, config);
|
|
444
|
-
}
|
|
445
554
|
if (config.agent === 'cursor') {
|
|
446
555
|
if (mode === 'plan') {
|
|
447
556
|
cmd.push('--plan');
|
|
@@ -512,7 +621,7 @@ export function buildJobCommand(config, resolvedPrompt, forwardAccount = true) {
|
|
|
512
621
|
return cmd;
|
|
513
622
|
}
|
|
514
623
|
/**
|
|
515
|
-
* Append
|
|
624
|
+
* Append the agent's canonical model flag and reasoning flags to a command.
|
|
516
625
|
*
|
|
517
626
|
* Pass-through model resolution: validates against the installed (agent, version)
|
|
518
627
|
* catalog when possible and writes a warning to stderr on miss, but never blocks.
|
|
@@ -523,15 +632,19 @@ function appendModelAndReasoning(cmd, config) {
|
|
|
523
632
|
const agent = config.agent;
|
|
524
633
|
const model = config.config?.model;
|
|
525
634
|
if (model) {
|
|
635
|
+
const modelFlag = AGENT_COMMANDS[agent].modelFlag;
|
|
636
|
+
if (!modelFlag) {
|
|
637
|
+
throw new Error(`Agent ${agent} does not support routine model selection`);
|
|
638
|
+
}
|
|
526
639
|
if (config.version) {
|
|
527
640
|
const resolved = resolveModel(agent, config.version, model);
|
|
528
641
|
if (resolved.warning) {
|
|
529
642
|
process.stderr.write(`[agents] ${resolved.warning}\n`);
|
|
530
643
|
}
|
|
531
|
-
cmd.push(
|
|
644
|
+
cmd.push(modelFlag, resolved.forwarded);
|
|
532
645
|
}
|
|
533
646
|
else {
|
|
534
|
-
cmd.push(
|
|
647
|
+
cmd.push(modelFlag, model);
|
|
535
648
|
}
|
|
536
649
|
}
|
|
537
650
|
const reasoning = config.config?.reasoning;
|
|
@@ -772,18 +885,31 @@ export async function resolveRoutineLaunch(config, cwd = process.cwd(), deps = {
|
|
|
772
885
|
// resolveRoutineLaunch is only called for agent jobs (workflow returns above;
|
|
773
886
|
// command jobs branch out of execute*Job before reaching this).
|
|
774
887
|
const agent = config.agent;
|
|
775
|
-
const { findAccount, resolveAccountSelection, resolveCredentialAccount } = await import('./account-registry.js');
|
|
888
|
+
const { findAccount, findUnifiedAccount, resolveAccountSelection, resolveCredentialAccount } = await import('./account-registry.js');
|
|
889
|
+
const meta = (deps.readMeta ?? readMeta)();
|
|
776
890
|
const explicitCredential = config.account
|
|
777
891
|
? (deps.findCredentialAccount?.(config.account) ?? (deps.resolveCredentialAccount !== undefined || findAccount(config.account) !== null))
|
|
778
892
|
: false;
|
|
779
893
|
const selectedCredential = config.account
|
|
780
894
|
? (explicitCredential ? config.account : undefined)
|
|
781
|
-
: resolveAccountSelection(undefined, agent,
|
|
895
|
+
: resolveAccountSelection(undefined, agent, meta);
|
|
782
896
|
if (selectedCredential) {
|
|
783
|
-
|
|
897
|
+
// A default/binding may resolve to a native account — never route that
|
|
898
|
+
// through the provider credential path (it has no bundle to resolve).
|
|
899
|
+
const unified = findUnifiedAccount(selectedCredential, meta);
|
|
900
|
+
if (unified?.kind !== 'native')
|
|
901
|
+
(deps.resolveCredentialAccount ?? resolveCredentialAccount)(selectedCredential, agent);
|
|
784
902
|
}
|
|
785
903
|
if (config.account && !explicitCredential) {
|
|
786
|
-
|
|
904
|
+
// A native routine account is named by its durable name; the version matcher
|
|
905
|
+
// keys on the identity (email/accountKey), so translate before resolving,
|
|
906
|
+
// and refuse a login that belongs to a different harness.
|
|
907
|
+
const unified = findUnifiedAccount(config.account, meta);
|
|
908
|
+
if (unified?.kind === 'native' && unified.agent !== agent) {
|
|
909
|
+
throw new Error(`Routine '${config.name}' account '${config.account}' is a ${unified.agent} login and cannot authenticate ${agent}.`);
|
|
910
|
+
}
|
|
911
|
+
const identity = unified?.kind === 'native' ? unified.identityKey : config.account;
|
|
912
|
+
const accountVersion = await (deps.resolveAccountVersion ?? resolveAccountVersion)(agent, identity);
|
|
787
913
|
if (accountVersion) {
|
|
788
914
|
if (config.version && config.version !== accountVersion) {
|
|
789
915
|
throw new Error(`Routine '${config.name}' account '${config.account}' is signed in at ${agent}@${accountVersion}, not pinned ${agent}@${config.version}.`);
|
|
@@ -809,7 +935,10 @@ export async function resolveRoutineLaunch(config, cwd = process.cwd(), deps = {
|
|
|
809
935
|
...(config.account ? { forwardAccount: explicitCredential } : {}),
|
|
810
936
|
};
|
|
811
937
|
}
|
|
812
|
-
|
|
938
|
+
// A per-routine strategy travels with the definition and beats the firing
|
|
939
|
+
// box's ambient run.<agent>.strategy — otherwise selection policy silently
|
|
940
|
+
// depends on whichever device fires the job (RUSH-2719).
|
|
941
|
+
const strategy = config.strategy ?? getConfiguredRunStrategy(agent, cwd);
|
|
813
942
|
let version;
|
|
814
943
|
let rotation = null;
|
|
815
944
|
let exhausted;
|
|
@@ -892,6 +1021,70 @@ export function pinJobBinary(cmd, agent, version) {
|
|
|
892
1021
|
* Such commands must NOT be binary-pinned (pinning rewrites cmd[0] to the agent binary,
|
|
893
1022
|
* producing a broken `<binary> run …`) and must not receive a version-pinned spawn env.
|
|
894
1023
|
*/
|
|
1024
|
+
/**
|
|
1025
|
+
* Assert a routine's account can be dispatched to the resolved placement, BEFORE
|
|
1026
|
+
* any off-box dispatch (placement is resolved before {@link resolveRoutineLaunch}),
|
|
1027
|
+
* at the top of both the foreground and detached paths:
|
|
1028
|
+
*
|
|
1029
|
+
* - **native** account → rejected for host AND cloud: a native login is a
|
|
1030
|
+
* device-local harness credential that cannot be forwarded off-box.
|
|
1031
|
+
* - **provider** account + **cloud** → rejected (fail loud): the cloud dispatch
|
|
1032
|
+
* has no secure way to inject a device-local provider bundle yet.
|
|
1033
|
+
* - **provider** account + **host** → allowed: the host dispatch forwards the
|
|
1034
|
+
* account NAME (the remote resolves its own local bundle — no secret copied).
|
|
1035
|
+
*
|
|
1036
|
+
* `account` is injectable so the guard is unit-tested for both modes without a
|
|
1037
|
+
* registry or a real dispatch.
|
|
1038
|
+
*/
|
|
1039
|
+
export async function assertRoutineAccountLocalForPlacement(config, mode, deps = {}) {
|
|
1040
|
+
if (!config.account)
|
|
1041
|
+
return;
|
|
1042
|
+
let account = deps.account;
|
|
1043
|
+
if (account === undefined) {
|
|
1044
|
+
const { findUnifiedAccount } = await import('./account-registry.js');
|
|
1045
|
+
account = findUnifiedAccount(config.account, (deps.readMeta ?? readMeta)());
|
|
1046
|
+
}
|
|
1047
|
+
if (!account) {
|
|
1048
|
+
throw new Error(`Routine '${config.name}' account '${config.account}' is unknown.`);
|
|
1049
|
+
}
|
|
1050
|
+
if (account?.kind === 'native') {
|
|
1051
|
+
throw new Error(`Routine '${config.name}' account '${config.account}' is a device-local ${account.agent} login and cannot run on a ${mode} placement. Use a provider account, or place this routine on the device that holds the login.`);
|
|
1052
|
+
}
|
|
1053
|
+
if (mode === 'cloud' && account?.kind === 'provider') {
|
|
1054
|
+
// RUSH-2689: cloud+provider injection not yet implemented.
|
|
1055
|
+
throw new Error(`Routine '${config.name}' account '${config.account}' is a provider credential; cloud placement cannot securely inject it (RUSH-2689). Run this routine locally or on a host that holds the bundle.`);
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
export async function dispatchPlacedJob(config, target, attempt, deps = {}) {
|
|
1059
|
+
if (target.mode !== 'host' && target.mode !== 'cloud')
|
|
1060
|
+
return undefined;
|
|
1061
|
+
await assertRoutineAccountLocalForPlacement(config, target.mode, { account: deps.account });
|
|
1062
|
+
if (target.mode === 'host') {
|
|
1063
|
+
return (deps.host ?? executeJobOnHost)({ ...config, host: target.host }, { detached: false }, attempt);
|
|
1064
|
+
}
|
|
1065
|
+
return (deps.cloud ?? executeJobOnCloud)(config, { detached: false }, attempt);
|
|
1066
|
+
}
|
|
1067
|
+
/**
|
|
1068
|
+
* Build the options passed to `dispatchPromptToHost` for a host routine. Split
|
|
1069
|
+
* out so the execution boundary is unit-testable: it MUST forward the routine's
|
|
1070
|
+
* `account` by name (the remote resolves its own local bundle; no secret copied)
|
|
1071
|
+
* — dropping it silently ran the remote under the wrong identity.
|
|
1072
|
+
*/
|
|
1073
|
+
export function buildHostDispatchOptions(config, ctx) {
|
|
1074
|
+
return {
|
|
1075
|
+
agent: config.agent,
|
|
1076
|
+
prompt: resolveJobPrompt(config),
|
|
1077
|
+
mode: normalizeMode(config.mode),
|
|
1078
|
+
effort: config.effort,
|
|
1079
|
+
model: config.config?.model,
|
|
1080
|
+
account: config.account,
|
|
1081
|
+
timeout: config.timeout, // enforced by the REMOTE agents run
|
|
1082
|
+
remoteCwd: ctx.remoteCwd,
|
|
1083
|
+
name: config.name,
|
|
1084
|
+
cwd: ctx.runDir,
|
|
1085
|
+
follow: !ctx.detached,
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
895
1088
|
export function dispatchesViaAgentsRun(config) {
|
|
896
1089
|
return Boolean(config.workflow || config.resume);
|
|
897
1090
|
}
|
|
@@ -1069,13 +1262,10 @@ async function executeJobPlaced(config, deps, attempt) {
|
|
|
1069
1262
|
// remote run to completion when possible.
|
|
1070
1263
|
{
|
|
1071
1264
|
const { resolvePlacementTarget } = await import('./routines-placement.js');
|
|
1072
|
-
const target = resolvePlacementTarget(config);
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
if (target.mode === 'cloud') {
|
|
1077
|
-
return executeJobOnCloud(config, { detached: false }, attempt);
|
|
1078
|
-
}
|
|
1265
|
+
const target = await resolvePlacementTarget(config);
|
|
1266
|
+
const placed = await dispatchPlacedJob(config, target, attempt);
|
|
1267
|
+
if (placed)
|
|
1268
|
+
return placed;
|
|
1079
1269
|
}
|
|
1080
1270
|
// Command-mode: run a plain shell command directly (no agent, no rotation,
|
|
1081
1271
|
// no pinning, no sandbox overlay). Reuses the run-record machinery so
|
|
@@ -1111,12 +1301,16 @@ async function executeJobPlaced(config, deps, attempt) {
|
|
|
1111
1301
|
// (command jobs branched out earlier, so config.agent is set on the non-workflow path.)
|
|
1112
1302
|
const effectiveAgent = config.workflow ? 'claude' : config.agent;
|
|
1113
1303
|
if (!dispatchesViaAgentsRun(config)) {
|
|
1114
|
-
const {
|
|
1115
|
-
const
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1304
|
+
const { findUnifiedAccount, resolveAccountSelection, resolveCredentialAccount } = await import('./account-registry.js');
|
|
1305
|
+
const meta = readMeta();
|
|
1306
|
+
const selectedAccount = resolveAccountSelection(config.account, effectiveAgent, meta);
|
|
1307
|
+
if (selectedAccount) {
|
|
1308
|
+
// Only a provider account injects env; a native account (explicit or via a
|
|
1309
|
+
// device-scoped binding) is read from the harness home and forwards nothing.
|
|
1310
|
+
const unified = findUnifiedAccount(selectedAccount, meta);
|
|
1311
|
+
if (unified?.kind === 'provider')
|
|
1312
|
+
Object.assign(baseEnv, resolveCredentialAccount(selectedAccount, effectiveAgent).env);
|
|
1313
|
+
}
|
|
1120
1314
|
}
|
|
1121
1315
|
const meta = {
|
|
1122
1316
|
jobName: config.name,
|
|
@@ -1443,18 +1637,7 @@ async function executeJobOnHost(config, opts, attempt) {
|
|
|
1443
1637
|
host: host.name,
|
|
1444
1638
|
};
|
|
1445
1639
|
writeRunMeta(meta);
|
|
1446
|
-
const { task, exitCode } = await dispatchPromptToHost(host, {
|
|
1447
|
-
agent: config.agent,
|
|
1448
|
-
prompt: resolveJobPrompt(config),
|
|
1449
|
-
mode: normalizeMode(config.mode),
|
|
1450
|
-
effort: config.effort,
|
|
1451
|
-
model: config.config?.model,
|
|
1452
|
-
timeout: config.timeout, // enforced by the REMOTE agents run
|
|
1453
|
-
remoteCwd,
|
|
1454
|
-
name: config.name,
|
|
1455
|
-
cwd: runDir,
|
|
1456
|
-
follow: !opts.detached,
|
|
1457
|
-
});
|
|
1640
|
+
const { task, exitCode } = await dispatchPromptToHost(host, buildHostDispatchOptions(config, { remoteCwd, runDir, detached: opts.detached }));
|
|
1458
1641
|
meta.hostTaskId = task.id;
|
|
1459
1642
|
// Sync path: a real exit code finalizes now. -1 (follow window closed) and
|
|
1460
1643
|
// the detached path leave the meta `running` for the monitor to reconcile.
|
|
@@ -1572,7 +1755,10 @@ async function executeJobDetachedClaimed(config, attempt, hooks) {
|
|
|
1572
1755
|
// sends the finish notification only for local detached runs below (RUSH-2030).
|
|
1573
1756
|
{
|
|
1574
1757
|
const { resolvePlacementTarget } = await import('./routines-placement.js');
|
|
1575
|
-
const target = resolvePlacementTarget(config);
|
|
1758
|
+
const target = await resolvePlacementTarget(config);
|
|
1759
|
+
if (target.mode === 'host' || target.mode === 'cloud') {
|
|
1760
|
+
await assertRoutineAccountLocalForPlacement(config, target.mode);
|
|
1761
|
+
}
|
|
1576
1762
|
if (target.mode === 'host') {
|
|
1577
1763
|
const { meta } = await executeJobOnHost({ ...config, host: target.host }, { detached: true }, attempt);
|
|
1578
1764
|
if (meta.status !== 'running')
|
|
@@ -2072,17 +2258,23 @@ export function monitorRunningJobs() {
|
|
|
2072
2258
|
finalizeHostRun(meta);
|
|
2073
2259
|
continue;
|
|
2074
2260
|
}
|
|
2075
|
-
if (!meta.pid)
|
|
2076
|
-
continue;
|
|
2077
2261
|
const runDirPath = path.join(jobRunsPath, runDirEntry.name);
|
|
2078
2262
|
const stdoutPath = path.join(runDirPath, 'stdout.log');
|
|
2079
2263
|
// Command-mode records carry no agent; there is no stream-json report to
|
|
2080
2264
|
// parse or extract. Reap them on pid liveness alone.
|
|
2081
2265
|
const isCommandRun = Boolean(meta.command) || !meta.agent;
|
|
2266
|
+
// Age-out runs FIRST, before the null-pid guard below, so a wedged record
|
|
2267
|
+
// still marked `running` past its deadline is always finalized — a
|
|
2268
|
+
// provisional launcher claim whose daemon crashed before spawning a child
|
|
2269
|
+
// (pid null), or an old record whose recorded pid was reused, would
|
|
2270
|
+
// otherwise linger as `running` forever (RUSH-2640). Only kill a process
|
|
2271
|
+
// group that is genuinely still ours; terminating a reused pid would kill
|
|
2272
|
+
// an unrelated process, and a null pid has nothing to kill.
|
|
2082
2273
|
const wallClockMs = Date.now() - Date.parse(meta.startedAt);
|
|
2083
2274
|
const timeoutMs = meta.timeoutMs ?? MAX_WALL_CLOCK_MS;
|
|
2084
2275
|
if (Number.isFinite(wallClockMs) && wallClockMs > timeoutMs) {
|
|
2085
|
-
|
|
2276
|
+
if (meta.pid && isPidOurs(meta.pid, meta.spawnedAt))
|
|
2277
|
+
terminateRoutineTree(meta.pid);
|
|
2086
2278
|
finalizeRunMeta(meta, 'timeout', null, { errorMessage: 'exceeded configured timeout' });
|
|
2087
2279
|
writeRunMeta(meta);
|
|
2088
2280
|
emitRoutineEnd(meta);
|
|
@@ -2092,6 +2284,8 @@ export function monitorRunningJobs() {
|
|
|
2092
2284
|
}
|
|
2093
2285
|
continue;
|
|
2094
2286
|
}
|
|
2287
|
+
if (!meta.pid)
|
|
2288
|
+
continue;
|
|
2095
2289
|
if (!isPidOurs(meta.pid, meta.spawnedAt)) {
|
|
2096
2290
|
if (isCommandRun) {
|
|
2097
2291
|
// Command routines normally record their own terminal status via
|
package/dist/lib/sandbox.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* The spawned agent process sees only the overlay, limiting filesystem
|
|
7
7
|
* access to explicitly allowed paths.
|
|
8
8
|
*/
|
|
9
|
-
import type { JobConfig } from './routines.js';
|
|
9
|
+
import type { JobConfig } from './scheduling/routines.js';
|
|
10
10
|
/** Build a restricted environment for a sandboxed process, setting HOME to the overlay. */
|
|
11
11
|
export declare function buildSpawnEnv(overlayHome: string, extraEnv?: Record<string, string>): Record<string, string>;
|
|
12
12
|
/**
|
package/dist/lib/scheduler.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* process creates a single JobScheduler instance that loads enabled jobs
|
|
6
6
|
* on startup and reloads them on SIGHUP.
|
|
7
7
|
*/
|
|
8
|
-
import type { JobConfig } from './routines.js';
|
|
8
|
+
import type { JobConfig } from './scheduling/routines.js';
|
|
9
9
|
/** How a fire was triggered, carrying the scheduler's intended UTC slot time. */
|
|
10
10
|
export interface TriggerContext {
|
|
11
11
|
/** The cron slot this callback fires for (croner `currentRun()`), for the
|
package/dist/lib/scheduler.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* on startup and reloads them on SIGHUP.
|
|
7
7
|
*/
|
|
8
8
|
import { Cron } from 'croner';
|
|
9
|
-
import { listJobs, deleteJob, isPastEndAt, isPastOneShotRoutine, isOneShotRoutine, setJobEnabled, shouldPurgeCompletedOneShotRoutine, jobRunsOnThisDevice, hasAmbiguousDevicePin, routineOwnerDevice, } from './routines.js';
|
|
9
|
+
import { listJobs, deleteJob, isPastEndAt, isPastOneShotRoutine, isOneShotRoutine, setJobEnabled, shouldPurgeCompletedOneShotRoutine, jobRunsOnThisDevice, hasAmbiguousDevicePin, routineOwnerDevice, } from './scheduling/routines.js';
|
|
10
10
|
/** In-memory cron scheduler that triggers a callback when jobs fire. */
|
|
11
11
|
export class JobScheduler {
|
|
12
12
|
jobs = new Map();
|