@phnx-labs/agents-cli 1.22.39 → 1.22.40
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 +294 -0
- package/README.md +111 -70
- package/dist/bin/agents +0 -0
- package/dist/bootstrap.js +45 -26
- package/dist/browser.js +2 -2
- package/dist/cli/command-registry.d.ts +135 -0
- package/dist/cli/command-registry.js +260 -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.js +206 -94
- 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 +9 -12
- 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 +72 -63
- 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 +13 -0
- package/dist/commands/sessions-picker.js +182 -8
- package/dist/commands/sessions-resume.d.ts +7 -3
- package/dist/commands/sessions-resume.js +81 -33
- package/dist/commands/sessions-stats.js +2 -2
- package/dist/commands/sessions.d.ts +75 -68
- package/dist/commands/sessions.js +142 -180
- 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-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 +11 -25
- 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 +1 -1
- package/dist/lib/browser/drivers/ssh.d.ts +1 -1
- package/dist/lib/browser/drivers/ssh.js +2 -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 +67 -3
- package/dist/lib/browser/profiles.js +129 -7
- 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 +113 -1
- package/dist/lib/browser/service.js +454 -40
- 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 +18 -0
- 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 +102 -0
- package/dist/lib/daemon-webhooks.js +210 -0
- package/dist/lib/device-config.d.ts +85 -75
- package/dist/lib/device-config.js +279 -141
- 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 +2 -2
- package/dist/lib/observe-aliases.js +2 -11
- 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-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 +241 -62
- 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 +3 -3
- package/dist/lib/secrets/bundles.js +7 -7
- 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 +12 -10
- package/dist/lib/secrets/remote.js +21 -14
- 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/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/share/delete.d.ts +21 -0
- package/dist/lib/share/delete.js +42 -0
- package/dist/lib/share/publish.d.ts +82 -0
- package/dist/lib/share/publish.js +170 -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 +5 -147
- package/dist/lib/startup/command-registry.js +38 -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 +1 -1
- package/dist/lib/triggers/handlers.js +2 -2
- package/dist/lib/triggers/webhook.d.ts +36 -2
- package/dist/lib/triggers/webhook.js +97 -42
- package/dist/lib/types.d.ts +18 -6
- 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/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,12 +18,12 @@ 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
29
|
import { normalizeMode, resolveHeadlessMode, buildExecEnv, detectRateLimit, detectAuthFailure, isAuthFailureFromLog, authFailureReason, } from './exec.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 as AGENT_COMMANDS,
|
|
42
|
+
import { isSelfUpdatingAgent, ROUTINE_AGENT_COMMANDS as 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
|
}
|
|
@@ -320,9 +420,16 @@ function terminateRoutineTree(pid) {
|
|
|
320
420
|
killTree(pid);
|
|
321
421
|
return;
|
|
322
422
|
}
|
|
423
|
+
// Detached spawn makes the child a new process-group leader; kill the group.
|
|
424
|
+
// If setsid has not landed yet (or the pid is not a leader), -pid fails with
|
|
425
|
+
// ESRCH and the child stays up — also kill the pid itself.
|
|
323
426
|
try {
|
|
324
427
|
process.kill(-pid, 'SIGKILL');
|
|
325
428
|
}
|
|
429
|
+
catch { /* not a group leader, or already exited */ }
|
|
430
|
+
try {
|
|
431
|
+
process.kill(pid, 'SIGKILL');
|
|
432
|
+
}
|
|
326
433
|
catch { /* already exited */ }
|
|
327
434
|
}
|
|
328
435
|
/**
|
|
@@ -433,15 +540,6 @@ export function buildJobCommand(config, resolvedPrompt, forwardAccount = true) {
|
|
|
433
540
|
cmd.push(...codexPolicyArgs(policyMode, [...codexEditWritableRoots(), ...routineRoots]));
|
|
434
541
|
appendModelAndReasoning(cmd, config);
|
|
435
542
|
}
|
|
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
543
|
if (config.agent === 'cursor') {
|
|
446
544
|
if (mode === 'plan') {
|
|
447
545
|
cmd.push('--plan');
|
|
@@ -772,18 +870,31 @@ export async function resolveRoutineLaunch(config, cwd = process.cwd(), deps = {
|
|
|
772
870
|
// resolveRoutineLaunch is only called for agent jobs (workflow returns above;
|
|
773
871
|
// command jobs branch out of execute*Job before reaching this).
|
|
774
872
|
const agent = config.agent;
|
|
775
|
-
const { findAccount, resolveAccountSelection, resolveCredentialAccount } = await import('./account-registry.js');
|
|
873
|
+
const { findAccount, findUnifiedAccount, resolveAccountSelection, resolveCredentialAccount } = await import('./account-registry.js');
|
|
874
|
+
const meta = (deps.readMeta ?? readMeta)();
|
|
776
875
|
const explicitCredential = config.account
|
|
777
876
|
? (deps.findCredentialAccount?.(config.account) ?? (deps.resolveCredentialAccount !== undefined || findAccount(config.account) !== null))
|
|
778
877
|
: false;
|
|
779
878
|
const selectedCredential = config.account
|
|
780
879
|
? (explicitCredential ? config.account : undefined)
|
|
781
|
-
: resolveAccountSelection(undefined, agent,
|
|
880
|
+
: resolveAccountSelection(undefined, agent, meta);
|
|
782
881
|
if (selectedCredential) {
|
|
783
|
-
|
|
882
|
+
// A default/binding may resolve to a native account — never route that
|
|
883
|
+
// through the provider credential path (it has no bundle to resolve).
|
|
884
|
+
const unified = findUnifiedAccount(selectedCredential, meta);
|
|
885
|
+
if (unified?.kind !== 'native')
|
|
886
|
+
(deps.resolveCredentialAccount ?? resolveCredentialAccount)(selectedCredential, agent);
|
|
784
887
|
}
|
|
785
888
|
if (config.account && !explicitCredential) {
|
|
786
|
-
|
|
889
|
+
// A native routine account is named by its durable name; the version matcher
|
|
890
|
+
// keys on the identity (email/accountKey), so translate before resolving,
|
|
891
|
+
// and refuse a login that belongs to a different harness.
|
|
892
|
+
const unified = findUnifiedAccount(config.account, meta);
|
|
893
|
+
if (unified?.kind === 'native' && unified.agent !== agent) {
|
|
894
|
+
throw new Error(`Routine '${config.name}' account '${config.account}' is a ${unified.agent} login and cannot authenticate ${agent}.`);
|
|
895
|
+
}
|
|
896
|
+
const identity = unified?.kind === 'native' ? unified.identityKey : config.account;
|
|
897
|
+
const accountVersion = await (deps.resolveAccountVersion ?? resolveAccountVersion)(agent, identity);
|
|
787
898
|
if (accountVersion) {
|
|
788
899
|
if (config.version && config.version !== accountVersion) {
|
|
789
900
|
throw new Error(`Routine '${config.name}' account '${config.account}' is signed in at ${agent}@${accountVersion}, not pinned ${agent}@${config.version}.`);
|
|
@@ -809,7 +920,10 @@ export async function resolveRoutineLaunch(config, cwd = process.cwd(), deps = {
|
|
|
809
920
|
...(config.account ? { forwardAccount: explicitCredential } : {}),
|
|
810
921
|
};
|
|
811
922
|
}
|
|
812
|
-
|
|
923
|
+
// A per-routine strategy travels with the definition and beats the firing
|
|
924
|
+
// box's ambient run.<agent>.strategy — otherwise selection policy silently
|
|
925
|
+
// depends on whichever device fires the job (RUSH-2719).
|
|
926
|
+
const strategy = config.strategy ?? getConfiguredRunStrategy(agent, cwd);
|
|
813
927
|
let version;
|
|
814
928
|
let rotation = null;
|
|
815
929
|
let exhausted;
|
|
@@ -892,6 +1006,70 @@ export function pinJobBinary(cmd, agent, version) {
|
|
|
892
1006
|
* Such commands must NOT be binary-pinned (pinning rewrites cmd[0] to the agent binary,
|
|
893
1007
|
* producing a broken `<binary> run …`) and must not receive a version-pinned spawn env.
|
|
894
1008
|
*/
|
|
1009
|
+
/**
|
|
1010
|
+
* Assert a routine's account can be dispatched to the resolved placement, BEFORE
|
|
1011
|
+
* any off-box dispatch (placement is resolved before {@link resolveRoutineLaunch}),
|
|
1012
|
+
* at the top of both the foreground and detached paths:
|
|
1013
|
+
*
|
|
1014
|
+
* - **native** account → rejected for host AND cloud: a native login is a
|
|
1015
|
+
* device-local harness credential that cannot be forwarded off-box.
|
|
1016
|
+
* - **provider** account + **cloud** → rejected (fail loud): the cloud dispatch
|
|
1017
|
+
* has no secure way to inject a device-local provider bundle yet.
|
|
1018
|
+
* - **provider** account + **host** → allowed: the host dispatch forwards the
|
|
1019
|
+
* account NAME (the remote resolves its own local bundle — no secret copied).
|
|
1020
|
+
*
|
|
1021
|
+
* `account` is injectable so the guard is unit-tested for both modes without a
|
|
1022
|
+
* registry or a real dispatch.
|
|
1023
|
+
*/
|
|
1024
|
+
export async function assertRoutineAccountLocalForPlacement(config, mode, deps = {}) {
|
|
1025
|
+
if (!config.account)
|
|
1026
|
+
return;
|
|
1027
|
+
let account = deps.account;
|
|
1028
|
+
if (account === undefined) {
|
|
1029
|
+
const { findUnifiedAccount } = await import('./account-registry.js');
|
|
1030
|
+
account = findUnifiedAccount(config.account, (deps.readMeta ?? readMeta)());
|
|
1031
|
+
}
|
|
1032
|
+
if (!account) {
|
|
1033
|
+
throw new Error(`Routine '${config.name}' account '${config.account}' is unknown.`);
|
|
1034
|
+
}
|
|
1035
|
+
if (account?.kind === 'native') {
|
|
1036
|
+
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.`);
|
|
1037
|
+
}
|
|
1038
|
+
if (mode === 'cloud' && account?.kind === 'provider') {
|
|
1039
|
+
// RUSH-2689: cloud+provider injection not yet implemented.
|
|
1040
|
+
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.`);
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
export async function dispatchPlacedJob(config, target, attempt, deps = {}) {
|
|
1044
|
+
if (target.mode !== 'host' && target.mode !== 'cloud')
|
|
1045
|
+
return undefined;
|
|
1046
|
+
await assertRoutineAccountLocalForPlacement(config, target.mode, { account: deps.account });
|
|
1047
|
+
if (target.mode === 'host') {
|
|
1048
|
+
return (deps.host ?? executeJobOnHost)({ ...config, host: target.host }, { detached: false }, attempt);
|
|
1049
|
+
}
|
|
1050
|
+
return (deps.cloud ?? executeJobOnCloud)(config, { detached: false }, attempt);
|
|
1051
|
+
}
|
|
1052
|
+
/**
|
|
1053
|
+
* Build the options passed to `dispatchPromptToHost` for a host routine. Split
|
|
1054
|
+
* out so the execution boundary is unit-testable: it MUST forward the routine's
|
|
1055
|
+
* `account` by name (the remote resolves its own local bundle; no secret copied)
|
|
1056
|
+
* — dropping it silently ran the remote under the wrong identity.
|
|
1057
|
+
*/
|
|
1058
|
+
export function buildHostDispatchOptions(config, ctx) {
|
|
1059
|
+
return {
|
|
1060
|
+
agent: config.agent,
|
|
1061
|
+
prompt: resolveJobPrompt(config),
|
|
1062
|
+
mode: normalizeMode(config.mode),
|
|
1063
|
+
effort: config.effort,
|
|
1064
|
+
model: config.config?.model,
|
|
1065
|
+
account: config.account,
|
|
1066
|
+
timeout: config.timeout, // enforced by the REMOTE agents run
|
|
1067
|
+
remoteCwd: ctx.remoteCwd,
|
|
1068
|
+
name: config.name,
|
|
1069
|
+
cwd: ctx.runDir,
|
|
1070
|
+
follow: !ctx.detached,
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
895
1073
|
export function dispatchesViaAgentsRun(config) {
|
|
896
1074
|
return Boolean(config.workflow || config.resume);
|
|
897
1075
|
}
|
|
@@ -1069,13 +1247,10 @@ async function executeJobPlaced(config, deps, attempt) {
|
|
|
1069
1247
|
// remote run to completion when possible.
|
|
1070
1248
|
{
|
|
1071
1249
|
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
|
-
}
|
|
1250
|
+
const target = await resolvePlacementTarget(config);
|
|
1251
|
+
const placed = await dispatchPlacedJob(config, target, attempt);
|
|
1252
|
+
if (placed)
|
|
1253
|
+
return placed;
|
|
1079
1254
|
}
|
|
1080
1255
|
// Command-mode: run a plain shell command directly (no agent, no rotation,
|
|
1081
1256
|
// no pinning, no sandbox overlay). Reuses the run-record machinery so
|
|
@@ -1111,12 +1286,16 @@ async function executeJobPlaced(config, deps, attempt) {
|
|
|
1111
1286
|
// (command jobs branched out earlier, so config.agent is set on the non-workflow path.)
|
|
1112
1287
|
const effectiveAgent = config.workflow ? 'claude' : config.agent;
|
|
1113
1288
|
if (!dispatchesViaAgentsRun(config)) {
|
|
1114
|
-
const {
|
|
1115
|
-
const
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1289
|
+
const { findUnifiedAccount, resolveAccountSelection, resolveCredentialAccount } = await import('./account-registry.js');
|
|
1290
|
+
const meta = readMeta();
|
|
1291
|
+
const selectedAccount = resolveAccountSelection(config.account, effectiveAgent, meta);
|
|
1292
|
+
if (selectedAccount) {
|
|
1293
|
+
// Only a provider account injects env; a native account (explicit or via a
|
|
1294
|
+
// device-scoped binding) is read from the harness home and forwards nothing.
|
|
1295
|
+
const unified = findUnifiedAccount(selectedAccount, meta);
|
|
1296
|
+
if (unified?.kind === 'provider')
|
|
1297
|
+
Object.assign(baseEnv, resolveCredentialAccount(selectedAccount, effectiveAgent).env);
|
|
1298
|
+
}
|
|
1120
1299
|
}
|
|
1121
1300
|
const meta = {
|
|
1122
1301
|
jobName: config.name,
|
|
@@ -1443,18 +1622,7 @@ async function executeJobOnHost(config, opts, attempt) {
|
|
|
1443
1622
|
host: host.name,
|
|
1444
1623
|
};
|
|
1445
1624
|
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
|
-
});
|
|
1625
|
+
const { task, exitCode } = await dispatchPromptToHost(host, buildHostDispatchOptions(config, { remoteCwd, runDir, detached: opts.detached }));
|
|
1458
1626
|
meta.hostTaskId = task.id;
|
|
1459
1627
|
// Sync path: a real exit code finalizes now. -1 (follow window closed) and
|
|
1460
1628
|
// the detached path leave the meta `running` for the monitor to reconcile.
|
|
@@ -1572,7 +1740,10 @@ async function executeJobDetachedClaimed(config, attempt, hooks) {
|
|
|
1572
1740
|
// sends the finish notification only for local detached runs below (RUSH-2030).
|
|
1573
1741
|
{
|
|
1574
1742
|
const { resolvePlacementTarget } = await import('./routines-placement.js');
|
|
1575
|
-
const target = resolvePlacementTarget(config);
|
|
1743
|
+
const target = await resolvePlacementTarget(config);
|
|
1744
|
+
if (target.mode === 'host' || target.mode === 'cloud') {
|
|
1745
|
+
await assertRoutineAccountLocalForPlacement(config, target.mode);
|
|
1746
|
+
}
|
|
1576
1747
|
if (target.mode === 'host') {
|
|
1577
1748
|
const { meta } = await executeJobOnHost({ ...config, host: target.host }, { detached: true }, attempt);
|
|
1578
1749
|
if (meta.status !== 'running')
|
|
@@ -2072,17 +2243,23 @@ export function monitorRunningJobs() {
|
|
|
2072
2243
|
finalizeHostRun(meta);
|
|
2073
2244
|
continue;
|
|
2074
2245
|
}
|
|
2075
|
-
if (!meta.pid)
|
|
2076
|
-
continue;
|
|
2077
2246
|
const runDirPath = path.join(jobRunsPath, runDirEntry.name);
|
|
2078
2247
|
const stdoutPath = path.join(runDirPath, 'stdout.log');
|
|
2079
2248
|
// Command-mode records carry no agent; there is no stream-json report to
|
|
2080
2249
|
// parse or extract. Reap them on pid liveness alone.
|
|
2081
2250
|
const isCommandRun = Boolean(meta.command) || !meta.agent;
|
|
2251
|
+
// Age-out runs FIRST, before the null-pid guard below, so a wedged record
|
|
2252
|
+
// still marked `running` past its deadline is always finalized — a
|
|
2253
|
+
// provisional launcher claim whose daemon crashed before spawning a child
|
|
2254
|
+
// (pid null), or an old record whose recorded pid was reused, would
|
|
2255
|
+
// otherwise linger as `running` forever (RUSH-2640). Only kill a process
|
|
2256
|
+
// group that is genuinely still ours; terminating a reused pid would kill
|
|
2257
|
+
// an unrelated process, and a null pid has nothing to kill.
|
|
2082
2258
|
const wallClockMs = Date.now() - Date.parse(meta.startedAt);
|
|
2083
2259
|
const timeoutMs = meta.timeoutMs ?? MAX_WALL_CLOCK_MS;
|
|
2084
2260
|
if (Number.isFinite(wallClockMs) && wallClockMs > timeoutMs) {
|
|
2085
|
-
|
|
2261
|
+
if (meta.pid && isPidOurs(meta.pid, meta.spawnedAt))
|
|
2262
|
+
terminateRoutineTree(meta.pid);
|
|
2086
2263
|
finalizeRunMeta(meta, 'timeout', null, { errorMessage: 'exceeded configured timeout' });
|
|
2087
2264
|
writeRunMeta(meta);
|
|
2088
2265
|
emitRoutineEnd(meta);
|
|
@@ -2092,6 +2269,8 @@ export function monitorRunningJobs() {
|
|
|
2092
2269
|
}
|
|
2093
2270
|
continue;
|
|
2094
2271
|
}
|
|
2272
|
+
if (!meta.pid)
|
|
2273
|
+
continue;
|
|
2095
2274
|
if (!isPidOurs(meta.pid, meta.spawnedAt)) {
|
|
2096
2275
|
if (isCommandRun) {
|
|
2097
2276
|
// 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();
|
|
@@ -6,9 +6,16 @@
|
|
|
6
6
|
* run metadata persistence, prompt variable expansion, and one-shot "at" time
|
|
7
7
|
* scheduling.
|
|
8
8
|
*/
|
|
9
|
-
import { type ResolvedExecutionContext, type ProjectResolution, type PlacementMode, type RoutineKind, type ContextFsProbe } from '
|
|
10
|
-
import type { AgentId } from '
|
|
11
|
-
import type { LoopConfig } from '
|
|
9
|
+
import { type ResolvedExecutionContext, type ProjectResolution, type PlacementMode, type RoutineKind, type ContextFsProbe } from '../routine-context.js';
|
|
10
|
+
import type { AgentId, RunStrategy } from '../types.js';
|
|
11
|
+
import type { LoopConfig } from '../loop.js';
|
|
12
|
+
import { JobScheduler } from '../scheduler.js';
|
|
13
|
+
export declare function fireConditionLabel(job: JobConfig): string;
|
|
14
|
+
export declare function nextRunForDisplay(job: JobConfig, scheduler: JobScheduler): Date | null;
|
|
15
|
+
export declare function nextRunLabel(job: JobConfig, scheduler: JobScheduler, now: Date): string;
|
|
16
|
+
export declare function localLatestRun(job: JobConfig): RunMeta | null;
|
|
17
|
+
export declare function listJobsForDisplay(cwd?: string): JobConfig[];
|
|
18
|
+
export declare function buildRoutineListJson(): Record<string, unknown>[];
|
|
12
19
|
/** Tool/site/directory allow-list for sandboxed job execution. */
|
|
13
20
|
export interface JobAllowConfig {
|
|
14
21
|
tools?: string[];
|
|
@@ -17,7 +24,7 @@ export interface JobAllowConfig {
|
|
|
17
24
|
}
|
|
18
25
|
/**
|
|
19
26
|
* Where a routine's job body executes when the daemon fires it.
|
|
20
|
-
* Distinct from `devices` (which daemon may *fire*) and from the CLI `--
|
|
27
|
+
* Distinct from `devices` (which daemon may *fire*) and from the CLI `--device`
|
|
21
28
|
* remote-management passthrough (manage routines *on* another machine).
|
|
22
29
|
*/
|
|
23
30
|
export type HostStrategy = 'local' | 'host' | 'fleet' | 'cloud';
|
|
@@ -184,7 +191,7 @@ export interface JobConfig {
|
|
|
184
191
|
* registered host, device, capability tag, or user@host) instead of locally.
|
|
185
192
|
* Distinct from `devices`: `devices` says which daemon may FIRE the job,
|
|
186
193
|
* `host` says where the dispatched run EXECUTES. CLI flag: `--run-on`
|
|
187
|
-
* (`--
|
|
194
|
+
* (`--device` on routines commands already means "manage routines on that
|
|
188
195
|
* machine" via the remote passthrough).
|
|
189
196
|
*
|
|
190
197
|
* When `hostStrategy` is set, it owns placement semantics; `host` is then
|
|
@@ -200,7 +207,7 @@ export interface JobConfig {
|
|
|
200
207
|
* double-fire; the firing pin stays on `devices`)
|
|
201
208
|
* - `cloud` — dispatch via the agent's native cloud provider
|
|
202
209
|
*
|
|
203
|
-
* CLI flag: `--placement` (not `--
|
|
210
|
+
* CLI flag: `--placement` (not `--device`, which is the remote-management
|
|
204
211
|
* passthrough). Omitted strategy falls back to `host` when `host:` is set,
|
|
205
212
|
* otherwise `local`.
|
|
206
213
|
*/
|
|
@@ -218,6 +225,16 @@ export interface JobConfig {
|
|
|
218
225
|
allow?: JobAllowConfig;
|
|
219
226
|
config?: Record<string, unknown>;
|
|
220
227
|
version?: string;
|
|
228
|
+
/**
|
|
229
|
+
* Explicit per-routine version/account selection strategy — the same
|
|
230
|
+
* vocabulary as `agents run --strategy` (RUN_STRATEGIES). Overrides
|
|
231
|
+
* `run.<agent>.strategy` from the FIRING device's own agents.yaml
|
|
232
|
+
* (getConfiguredRunStrategy) so a routine's selection policy travels with the
|
|
233
|
+
* definition instead of depending on whichever box happens to fire it.
|
|
234
|
+
* Conflicts with `version:` (an exact pin leaves nothing to select) —
|
|
235
|
+
* validateJob rejects the pair.
|
|
236
|
+
*/
|
|
237
|
+
strategy?: RunStrategy;
|
|
221
238
|
/**
|
|
222
239
|
* Pin this routine to a signed-in account by identity (its login email, or its
|
|
223
240
|
* account key) instead of rotating. At launch it resolves to whichever
|
|
@@ -268,6 +285,29 @@ export interface JobConfig {
|
|
|
268
285
|
* - Absent/empty — routine belongs to no project ("Operations" group).
|
|
269
286
|
*/
|
|
270
287
|
projects?: string[];
|
|
288
|
+
/**
|
|
289
|
+
* Set only by `lib/monitors/dispatch.ts` on the one-off job it synthesizes for
|
|
290
|
+
* a monitor's `run` action. Such a job is NOT a routine: it has no definition
|
|
291
|
+
* file, `agents routines` never lists it, and its name can therefore never
|
|
292
|
+
* appear in this device's routine activation manifest
|
|
293
|
+
* (`~/.agents/devices/<machine>/agents.yaml` → `routines:`). Gating it on that
|
|
294
|
+
* manifest refused every monitor action fleet-wide with `wrong_owner` and an
|
|
295
|
+
* empty allowlist (RUSH-2681), so {@link jobRunsOnThisDevice} skips the
|
|
296
|
+
* manifest for it. Exactly-once ownership is already resolved BEFORE dispatch
|
|
297
|
+
* by the monitor's own `device:` pin (`monitorRunsOnThisDevice`,
|
|
298
|
+
* `lib/monitors/config.ts`) — re-gating here was double-gating on the wrong
|
|
299
|
+
* key.
|
|
300
|
+
*
|
|
301
|
+
* Deliberately narrow: a monitor's `routine` action fires a REAL routine, which
|
|
302
|
+
* keeps its activation gate, so a routine defined but not activated on this
|
|
303
|
+
* device is still refused.
|
|
304
|
+
*
|
|
305
|
+
* Runtime-only, enforced at both ends of the schema boundary: `writeJob`
|
|
306
|
+
* strips it, and `readJobFileResult` refuses a definition that carries it
|
|
307
|
+
* (a hand-authored one would otherwise fire on every box regardless of
|
|
308
|
+
* activation, since the daemon's load path never calls `validateJob`).
|
|
309
|
+
*/
|
|
310
|
+
dispatchedBy?: 'monitor';
|
|
271
311
|
}
|
|
272
312
|
/**
|
|
273
313
|
* Canonical form of a routine's `projects` field: drop non-string and empty
|
|
@@ -463,8 +503,13 @@ export declare function finalizeRunMeta(meta: RunMeta, status: RunMeta['status']
|
|
|
463
503
|
* `normalizeHost` so `Yosemite-S0`, `yosemite-s0.tailnet.ts.net`, and
|
|
464
504
|
* `yosemite-s0` all agree. Every fire path (cron scheduler, webhook,
|
|
465
505
|
* catchup/overdue, manual run) gates on this.
|
|
506
|
+
*
|
|
507
|
+
* A monitor-dispatched job ({@link JobConfig.dispatchedBy} `=== 'monitor'`) skips
|
|
508
|
+
* the routine activation manifest: it is not a routine, so its name can never be
|
|
509
|
+
* a member and the lookup could only ever answer "not activated here"
|
|
510
|
+
* (RUSH-2681). Its ownership was already decided by the monitor's `device:` pin.
|
|
466
511
|
*/
|
|
467
|
-
export declare function jobRunsOnThisDevice(config: Pick<JobConfig, 'name' | 'devices'>): boolean;
|
|
512
|
+
export declare function jobRunsOnThisDevice(config: Pick<JobConfig, 'name' | 'devices' | 'dispatchedBy'>): boolean;
|
|
468
513
|
/**
|
|
469
514
|
* The ONE device that owns a routine — the single daemon allowed to fire it.
|
|
470
515
|
*
|
|
@@ -528,7 +573,7 @@ export declare function placementRequiresFiringPin(strategy: HostStrategy): bool
|
|
|
528
573
|
export interface JobEligibilityResult {
|
|
529
574
|
/** Full human message, e.g. "Job 'NAME' can only run on: a, b". */
|
|
530
575
|
message: string;
|
|
531
|
-
/** One-line copy-paste suggestion, e.g. "agents routines run NAME --
|
|
576
|
+
/** One-line copy-paste suggestion, e.g. "agents routines run NAME --device a". */
|
|
532
577
|
suggestion: string;
|
|
533
578
|
/** Comma-separated allowed devices label, e.g. "a, b". */
|
|
534
579
|
allowedLabel: string;
|
|
@@ -541,7 +586,7 @@ export interface JobEligibilityResult {
|
|
|
541
586
|
* construction so manual run, executeJob, and executeJobDetached stay in
|
|
542
587
|
* sync. Scheduler/webhook/overdue paths continue to use jobRunsOnThisDevice.
|
|
543
588
|
*/
|
|
544
|
-
export declare function checkJobDeviceEligibility(config: Pick<JobConfig, 'name' | 'devices'>): JobEligibilityResult | null;
|
|
589
|
+
export declare function checkJobDeviceEligibility(config: Pick<JobConfig, 'name' | 'devices' | 'dispatchedBy'>): JobEligibilityResult | null;
|
|
545
590
|
/**
|
|
546
591
|
* List all job configs, scanning project > user > system routine dirs.
|
|
547
592
|
* Higher layers shadow lower ones of the same name (first-seen wins): a project
|