@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/tmux/session.js
CHANGED
|
@@ -367,13 +367,14 @@ export async function paneExitStatus(pane, socket) {
|
|
|
367
367
|
* Best-effort — returns false when tmux rejects the hook so callers do not
|
|
368
368
|
* stamp a schema marker and daemon reconciliation can retry later.
|
|
369
369
|
*/
|
|
370
|
-
export async function setSessionHook(name, hook, command, socket) {
|
|
370
|
+
export async function setSessionHook(name, hook, command, socket, timeoutMs) {
|
|
371
371
|
assertValidSessionName(name);
|
|
372
372
|
const sock = socket ?? getDefaultSocketPath();
|
|
373
373
|
const result = await runTmux({
|
|
374
374
|
socket: sock,
|
|
375
375
|
args: ['set-hook', '-t', name, hook, command],
|
|
376
376
|
throwOnError: false,
|
|
377
|
+
timeoutMs,
|
|
377
378
|
}).catch(() => null);
|
|
378
379
|
return result?.code === 0;
|
|
379
380
|
}
|
|
@@ -405,6 +406,15 @@ export async function setSessionHook(name, hook, command, socket) {
|
|
|
405
406
|
export const AGENT_HOOK_SCHEMA = 5;
|
|
406
407
|
/** Per-session tmux user-option that records which AGENT_HOOK_SCHEMA a session's hook is at. */
|
|
407
408
|
const HOOK_SCHEMA_OPTION = '@ag_hook_schema';
|
|
409
|
+
/**
|
|
410
|
+
* Bound on every tmux call made by the hook-repair path (daemon startup,
|
|
411
|
+
* upgrade migration, and single-session repair-before-attach). A wedged tmux
|
|
412
|
+
* server would otherwise hang the caller indefinitely — exactly the class of
|
|
413
|
+
* bug RUSH-2507 fixed for `listTmuxAgentSessions`'s `list-panes` call, applied
|
|
414
|
+
* here to `reconcileSessionHooks`/`repairSessionHookIfStale`'s calls so a
|
|
415
|
+
* wedged shared socket can no longer wedge daemon startup (RUSH-2435 review).
|
|
416
|
+
*/
|
|
417
|
+
const TMUX_HOOK_REPAIR_TIMEOUT_MS = 5_000;
|
|
408
418
|
/**
|
|
409
419
|
* The guarded `pane-died` hook. Detach the client ONLY when the agent pane dies
|
|
410
420
|
* (so the blocking attach in runInTmux returns and the exit status can be read);
|
|
@@ -423,13 +433,13 @@ export function agentPaneDiedHook(sessionName, agentPane) {
|
|
|
423
433
|
return `if -F '#{==:#{hook_pane},${agentPane}}' 'detach-client -s =${sessionName}' 'run-shell -b -C "kill-pane -t #{hook_pane}"'`;
|
|
424
434
|
}
|
|
425
435
|
/** Stamp a session's hook-schema marker to the current version. */
|
|
426
|
-
export async function markSessionHookSchema(name, socket) {
|
|
436
|
+
export async function markSessionHookSchema(name, socket, timeoutMs) {
|
|
427
437
|
const sock = socket ?? getDefaultSocketPath();
|
|
428
|
-
await runTmux({ socket: sock, args: ['set-option', '-t', name, HOOK_SCHEMA_OPTION, String(AGENT_HOOK_SCHEMA)], throwOnError: false }).catch(() => { });
|
|
438
|
+
await runTmux({ socket: sock, args: ['set-option', '-t', name, HOOK_SCHEMA_OPTION, String(AGENT_HOOK_SCHEMA)], throwOnError: false, timeoutMs }).catch(() => { });
|
|
429
439
|
}
|
|
430
440
|
/** Read a session's hook-schema marker; undefined when unset (pre-marker sessions). */
|
|
431
|
-
async function readHookSchema(name, socket) {
|
|
432
|
-
const res = await runTmux({ socket, args: ['show-options', '-v', '-t', name, HOOK_SCHEMA_OPTION], throwOnError: false }).catch(() => null);
|
|
441
|
+
async function readHookSchema(name, socket, timeoutMs) {
|
|
442
|
+
const res = await runTmux({ socket, args: ['show-options', '-v', '-t', name, HOOK_SCHEMA_OPTION], throwOnError: false, timeoutMs }).catch(() => null);
|
|
433
443
|
if (!res || res.code !== 0)
|
|
434
444
|
return undefined;
|
|
435
445
|
const v = res.stdout.trim();
|
|
@@ -441,8 +451,8 @@ async function readHookSchema(name, socket) {
|
|
|
441
451
|
* for sessions whose SessionMeta (which records the agent pane) predates meta
|
|
442
452
|
* persistence. Undefined when the session has no panes (already torn down).
|
|
443
453
|
*/
|
|
444
|
-
async function lowestPaneId(name, socket) {
|
|
445
|
-
const res = await runTmux({ socket, args: ['list-panes', '-t', name, '-F', '#{pane_id}'], throwOnError: false }).catch(() => null);
|
|
454
|
+
async function lowestPaneId(name, socket, timeoutMs) {
|
|
455
|
+
const res = await runTmux({ socket, args: ['list-panes', '-t', name, '-F', '#{pane_id}'], throwOnError: false, timeoutMs }).catch(() => null);
|
|
446
456
|
if (!res || res.code !== 0)
|
|
447
457
|
return undefined;
|
|
448
458
|
const ids = res.stdout.split('\n').map(l => l.trim()).filter(id => /^%\d+$/.test(id));
|
|
@@ -467,11 +477,35 @@ export async function prepareSessionForResume(name, socket) {
|
|
|
467
477
|
? recordedPane
|
|
468
478
|
: await lowestPaneId(name, sock);
|
|
469
479
|
const state = pane ? await paneExitStatus(pane, sock) : undefined;
|
|
470
|
-
if (pane && state?.found && !state.dead)
|
|
480
|
+
if (pane && state?.found && !state.dead) {
|
|
481
|
+
// Self-heal a legacy/stale hook right before handing the session back to
|
|
482
|
+
// an attach client — the steady-state repair point between the daemon's
|
|
483
|
+
// startup and upgrade one-shots (RUSH-2435).
|
|
484
|
+
await ensureSessionHookRepaired(name, sock);
|
|
471
485
|
return { decision: 'attach', pane };
|
|
486
|
+
}
|
|
472
487
|
await killSession(name, sock);
|
|
473
488
|
return { decision: 'create' };
|
|
474
489
|
}
|
|
490
|
+
/**
|
|
491
|
+
* Repair ONE session's `pane-died` hook if it predates AGENT_HOOK_SCHEMA.
|
|
492
|
+
* Idempotent and NON-DESTRUCTIVE — only `set-hook`s, never kills a pane or
|
|
493
|
+
* detaches a client. Shared by {@link reconcileSessionHooks} (full sweep) and
|
|
494
|
+
* {@link ensureSessionHookRepaired} (single session, called before attach) so
|
|
495
|
+
* the two can never drift on what counts as "repaired" (RUSH-2435).
|
|
496
|
+
*/
|
|
497
|
+
async function repairSessionHookIfStale(name, sock, meta, timeoutMs = TMUX_HOOK_REPAIR_TIMEOUT_MS) {
|
|
498
|
+
if (await readHookSchema(name, sock, timeoutMs) === String(AGENT_HOOK_SCHEMA))
|
|
499
|
+
return false;
|
|
500
|
+
const agentPane = meta?.pane ?? await lowestPaneId(name, sock, timeoutMs);
|
|
501
|
+
if (!agentPane)
|
|
502
|
+
return false;
|
|
503
|
+
const installed = await setSessionHook(name, 'pane-died', agentPaneDiedHook(name, agentPane), sock, timeoutMs);
|
|
504
|
+
if (!installed)
|
|
505
|
+
return false;
|
|
506
|
+
await markSessionHookSchema(name, sock, timeoutMs);
|
|
507
|
+
return true;
|
|
508
|
+
}
|
|
475
509
|
/**
|
|
476
510
|
* Retrofit the current guarded `pane-died` hook onto every managed `agents run`
|
|
477
511
|
* session whose hook predates AGENT_HOOK_SCHEMA. Idempotent and NON-DESTRUCTIVE:
|
|
@@ -481,9 +515,15 @@ export async function prepareSessionForResume(name, socket) {
|
|
|
481
515
|
* exited a split — self-heals in place, without waiting for those agents to exit
|
|
482
516
|
* or for the server to be recycled.
|
|
483
517
|
*
|
|
484
|
-
*
|
|
485
|
-
*
|
|
486
|
-
*
|
|
518
|
+
* NOT a daemon poll — the 5-minute `tmux-reconcile` routine that used to call this
|
|
519
|
+
* was deleted (RUSH-2495). It survives as the version-skew ONE-SHOT: the daemon
|
|
520
|
+
* calls it once at startup (`runDaemon` in `../daemon.js`) and once from the
|
|
521
|
+
* upgrade-time migration (`runMigration` in `../migrate.js`), so a session a
|
|
522
|
+
* pre-fix binary left with a stale hook still self-heals without a live poller.
|
|
523
|
+
* `ensureSessionHookRepaired` covers the steady-state gap between those two
|
|
524
|
+
* points by repairing a single session right before it's attached to. The
|
|
525
|
+
* per-session `@ag_hook_schema` marker makes both paths a cheap no-op once a
|
|
526
|
+
* session is current. Only run-wrapped sessions (`ag-` prefix) are touched — an
|
|
487
527
|
* externally-created session on the socket keeps whatever hook it set.
|
|
488
528
|
*/
|
|
489
529
|
export async function reconcileSessionHooks(socket) {
|
|
@@ -492,7 +532,7 @@ export async function reconcileSessionHooks(socket) {
|
|
|
492
532
|
return { scanned: 0, reconciled: 0 };
|
|
493
533
|
let sessions;
|
|
494
534
|
try {
|
|
495
|
-
sessions = await listSessions({ socket: sock });
|
|
535
|
+
sessions = await listSessions({ socket: sock, timeoutMs: TMUX_HOOK_REPAIR_TIMEOUT_MS });
|
|
496
536
|
}
|
|
497
537
|
catch {
|
|
498
538
|
return { scanned: 0, reconciled: 0 };
|
|
@@ -501,19 +541,32 @@ export async function reconcileSessionHooks(socket) {
|
|
|
501
541
|
for (const s of sessions) {
|
|
502
542
|
if (!s.name.startsWith('ag-'))
|
|
503
543
|
continue; // only run-wrapped sessions
|
|
504
|
-
if (await
|
|
505
|
-
|
|
506
|
-
const agentPane = s.meta?.pane ?? await lowestPaneId(s.name, sock);
|
|
507
|
-
if (!agentPane)
|
|
508
|
-
continue;
|
|
509
|
-
const installed = await setSessionHook(s.name, 'pane-died', agentPaneDiedHook(s.name, agentPane), sock);
|
|
510
|
-
if (!installed)
|
|
511
|
-
continue;
|
|
512
|
-
await markSessionHookSchema(s.name, sock);
|
|
513
|
-
reconciled++;
|
|
544
|
+
if (await repairSessionHookIfStale(s.name, sock, s.meta))
|
|
545
|
+
reconciled++;
|
|
514
546
|
}
|
|
515
547
|
return { scanned: sessions.length, reconciled };
|
|
516
548
|
}
|
|
549
|
+
/**
|
|
550
|
+
* Repair a single managed session's `pane-died` hook right before it is
|
|
551
|
+
* attached to, so a legacy session left by a pre-fix binary self-heals on the
|
|
552
|
+
* next touch instead of waiting for the next daemon-startup/upgrade one-shot
|
|
553
|
+
* (RUSH-2435). Only `ag-`-prefixed (run-wrapped) sessions are touched; a no-op
|
|
554
|
+
* for anything else. Best-effort — never throws, so a repair failure can never
|
|
555
|
+
* block the attach it is protecting.
|
|
556
|
+
*/
|
|
557
|
+
export async function ensureSessionHookRepaired(name, socket) {
|
|
558
|
+
if (!name.startsWith('ag-'))
|
|
559
|
+
return;
|
|
560
|
+
const sock = socket ?? getDefaultSocketPath();
|
|
561
|
+
if (!fs.existsSync(sock))
|
|
562
|
+
return;
|
|
563
|
+
try {
|
|
564
|
+
await repairSessionHookIfStale(name, sock, readSessionMeta(name) ?? undefined);
|
|
565
|
+
}
|
|
566
|
+
catch {
|
|
567
|
+
// best-effort — an attach must never fail because a repair attempt did
|
|
568
|
+
}
|
|
569
|
+
}
|
|
517
570
|
/**
|
|
518
571
|
* List live sessions on the socket. Reconciles meta JSONs against tmux's view:
|
|
519
572
|
* - tmux session with no meta → returned without `meta` (external session)
|
|
@@ -532,6 +585,7 @@ export async function listSessions(opts = {}) {
|
|
|
532
585
|
socket,
|
|
533
586
|
args: ['list-sessions', '-F', fmt],
|
|
534
587
|
throwOnError: false,
|
|
588
|
+
timeoutMs: opts.timeoutMs,
|
|
535
589
|
});
|
|
536
590
|
// tmux returns nonzero with "no server running" or "no sessions" — both mean empty.
|
|
537
591
|
if (res.code !== 0) {
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* project/system layers). They complement routine triggers: a matching webhook
|
|
6
6
|
* can run an agent, workflow, shell command, or delegate to a routine.
|
|
7
7
|
*/
|
|
8
|
-
import type { JobConfig, RunMeta, WebhookContext } from '../routines.js';
|
|
8
|
+
import type { JobConfig, RunMeta, WebhookContext } from '../scheduling/routines.js';
|
|
9
9
|
import type { AgentId } from '../types.js';
|
|
10
|
-
import type { IncomingWebhook, WebhookSource } from './webhook.js';
|
|
10
|
+
import type { IncomingWebhook, SlackPayload, WebhookSource } from './webhook.js';
|
|
11
11
|
export interface WebhookHandler {
|
|
12
12
|
name: string;
|
|
13
13
|
enabled?: boolean;
|
|
@@ -21,6 +21,11 @@ export interface WebhookHandler {
|
|
|
21
21
|
label?: string;
|
|
22
22
|
repo?: string;
|
|
23
23
|
branch?: string;
|
|
24
|
+
/** Slack (source: slack) only — match one slash command, e.g. `/agents`. */
|
|
25
|
+
command?: string;
|
|
26
|
+
/** Slack (source: slack) only — restrict to one channel id (`C0…`). Lets a
|
|
27
|
+
* channel imply a project via a per-channel handler. */
|
|
28
|
+
channel?: string;
|
|
24
29
|
/**
|
|
25
30
|
* Where to run the action. A device name (`yosemite-s0`) runs there over SSH;
|
|
26
31
|
* `fleet` picks any eligible online worker; `fleet/<platform>` (or
|
|
@@ -92,10 +97,40 @@ export declare function resolveHandlerHost(host: string | undefined): HandlerHos
|
|
|
92
97
|
export declare function listHandlers(cwd?: string): WebhookHandler[];
|
|
93
98
|
/** Pure matcher: does this handler match the incoming webhook? */
|
|
94
99
|
export declare function handlerMatchesWebhook(handler: WebhookHandler, webhook: IncomingWebhook): boolean;
|
|
100
|
+
/**
|
|
101
|
+
* The `{{slack.*}}` substitution namespace: a Slack message split into an
|
|
102
|
+
* agent-actionable project + prompt, plus the coordinates a reply threads into.
|
|
103
|
+
*/
|
|
104
|
+
export interface SlackMessageContext {
|
|
105
|
+
/** The message with a leading bot mention stripped. */
|
|
106
|
+
text: string;
|
|
107
|
+
/** The `PROJECT:` token at the head of the message, or '' when absent. */
|
|
108
|
+
project: string;
|
|
109
|
+
/** The request — the text after `PROJECT:`, or the whole message. */
|
|
110
|
+
prompt: string;
|
|
111
|
+
/** Channel id to reply into (`C0…`). */
|
|
112
|
+
channel: string;
|
|
113
|
+
/** Thread ts to reply into (empty for a slash command → reply to the channel). */
|
|
114
|
+
thread_ts: string;
|
|
115
|
+
/** Invoking user id (`U0…`). */
|
|
116
|
+
user: string;
|
|
117
|
+
/** Slash command name (`/agents`), or '' for an event delivery. */
|
|
118
|
+
command: string;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Split a Slack message into a `{{slack.*}}` context. Strips a leading bot
|
|
122
|
+
* mention (`<@U0BOT> …`), then reads an optional `PROJECT:` prefix — a single
|
|
123
|
+
* bare token followed by a colon and a space — as the project, with the
|
|
124
|
+
* remainder the prompt. `AGI: rebase my PR` → project `AGI`, prompt
|
|
125
|
+
* `rebase my PR`; a message with no such prefix leaves `project` empty and the
|
|
126
|
+
* whole text as the prompt. The token pattern forbids slashes, so a project
|
|
127
|
+
* value can never carry a path into a `cwd`/`project` substitution.
|
|
128
|
+
*/
|
|
129
|
+
export declare function parseSlackMessage(payload: SlackPayload): SlackMessageContext;
|
|
95
130
|
/**
|
|
96
131
|
* Build the variable-substitution context for a webhook. Linear events expose
|
|
97
132
|
* `issue` and `updatedFrom`; GitHub events expose `repository`, `pull_request`,
|
|
98
|
-
* and `issue
|
|
133
|
+
* and `issue`; Slack events expose the `{{slack.*}}` namespace above.
|
|
99
134
|
*/
|
|
100
135
|
export declare function buildWebhookContext(webhook: IncomingWebhook): WebhookContext;
|
|
101
136
|
export interface ExecuteHandlerOptions {
|
|
@@ -9,11 +9,11 @@ import { exec } from 'child_process';
|
|
|
9
9
|
import * as fs from 'fs';
|
|
10
10
|
import * as path from 'path';
|
|
11
11
|
import * as yaml from 'yaml';
|
|
12
|
-
import { emit } from '../events.js';
|
|
12
|
+
import { emit } from '../feed/events.js';
|
|
13
13
|
import { machineId, normalizeHost } from '../machine-id.js';
|
|
14
14
|
import { safeJoin } from '../paths.js';
|
|
15
15
|
import { pickFleetDevice } from '../routines-placement.js';
|
|
16
|
-
import { assertShellSubstitutionSupported, readJob, substituteWebhookCommand, substituteWebhookPrompt, } from '../routines.js';
|
|
16
|
+
import { assertShellSubstitutionSupported, readJob, substituteWebhookCommand, substituteWebhookPrompt, } from '../scheduling/routines.js';
|
|
17
17
|
import { ensureAgentsDir, getProjectWebhooksDir, getSystemWebhooksDir, getWebhooksDir } from '../state.js';
|
|
18
18
|
const HANDLER_DEFAULTS = {
|
|
19
19
|
enabled: true,
|
|
@@ -208,6 +208,17 @@ export function handlerMatchesWebhook(handler, webhook) {
|
|
|
208
208
|
return false;
|
|
209
209
|
if (!handlerRunsOnThisDevice(handler))
|
|
210
210
|
return false;
|
|
211
|
+
// Slack has no GitHub/Linear action/label/branch vocabulary; it matches on the
|
|
212
|
+
// slash command and (optionally) the channel. `event` already pinned the
|
|
213
|
+
// subtype (`app_mention`) or the slash command name above.
|
|
214
|
+
if (webhook.source === 'slack') {
|
|
215
|
+
const slack = webhook.payload;
|
|
216
|
+
if (handler.command && slack.command !== handler.command)
|
|
217
|
+
return false;
|
|
218
|
+
if (handler.channel && slack.channel !== handler.channel)
|
|
219
|
+
return false;
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
211
222
|
if (handler.action) {
|
|
212
223
|
const action = webhook.source === 'github' ? githubAction(webhook.payload) : linearAction(webhook.payload);
|
|
213
224
|
if (action !== handler.action)
|
|
@@ -262,12 +273,47 @@ export function handlerMatchesWebhook(handler, webhook) {
|
|
|
262
273
|
}
|
|
263
274
|
return true;
|
|
264
275
|
}
|
|
276
|
+
const asString = (v) => (typeof v === 'string' ? v : '');
|
|
277
|
+
/**
|
|
278
|
+
* Split a Slack message into a `{{slack.*}}` context. Strips a leading bot
|
|
279
|
+
* mention (`<@U0BOT> …`), then reads an optional `PROJECT:` prefix — a single
|
|
280
|
+
* bare token followed by a colon and a space — as the project, with the
|
|
281
|
+
* remainder the prompt. `AGI: rebase my PR` → project `AGI`, prompt
|
|
282
|
+
* `rebase my PR`; a message with no such prefix leaves `project` empty and the
|
|
283
|
+
* whole text as the prompt. The token pattern forbids slashes, so a project
|
|
284
|
+
* value can never carry a path into a `cwd`/`project` substitution.
|
|
285
|
+
*/
|
|
286
|
+
export function parseSlackMessage(payload) {
|
|
287
|
+
const cleaned = asString(payload.text).replace(/^\s*<@[^>]+>\s*/, '').trim();
|
|
288
|
+
const m = /^([A-Za-z0-9][\w.-]*)\s*:\s+([\s\S]+)$/.exec(cleaned);
|
|
289
|
+
return {
|
|
290
|
+
text: cleaned,
|
|
291
|
+
project: m ? m[1] : '',
|
|
292
|
+
prompt: m ? m[2].trim() : cleaned,
|
|
293
|
+
channel: asString(payload.channel),
|
|
294
|
+
thread_ts: asString(payload.thread_ts),
|
|
295
|
+
user: asString(payload.user),
|
|
296
|
+
command: asString(payload.command),
|
|
297
|
+
};
|
|
298
|
+
}
|
|
265
299
|
/**
|
|
266
300
|
* Build the variable-substitution context for a webhook. Linear events expose
|
|
267
301
|
* `issue` and `updatedFrom`; GitHub events expose `repository`, `pull_request`,
|
|
268
|
-
* and `issue
|
|
302
|
+
* and `issue`; Slack events expose the `{{slack.*}}` namespace above.
|
|
269
303
|
*/
|
|
270
304
|
export function buildWebhookContext(webhook) {
|
|
305
|
+
if (webhook.source === 'slack') {
|
|
306
|
+
// The `{{slack.*}}` namespace rides an intersection over WebhookContext (a
|
|
307
|
+
// subtype of it) rather than a field on the shared type, so a Slack-only
|
|
308
|
+
// addition never touches the scheduling hub every routine test depends on.
|
|
309
|
+
// `substituteWebhookPrompt`/`getPath` read it dynamically at runtime.
|
|
310
|
+
const ctx = {
|
|
311
|
+
source: webhook.source,
|
|
312
|
+
event: webhook.event,
|
|
313
|
+
slack: parseSlackMessage(webhook.payload),
|
|
314
|
+
};
|
|
315
|
+
return ctx;
|
|
316
|
+
}
|
|
271
317
|
const action = webhook.source === 'github'
|
|
272
318
|
? githubAction(webhook.payload) ?? undefined
|
|
273
319
|
: linearAction(webhook.payload) ?? undefined;
|
|
@@ -346,6 +392,11 @@ export async function executeHandler(handler, webhook, opts = {}) {
|
|
|
346
392
|
}
|
|
347
393
|
async function executeHandlerAction(handler, webhook, context, opts) {
|
|
348
394
|
const substitutedPrompt = handler.run?.prompt ? substituteWebhookPrompt(handler.run.prompt, context) : '';
|
|
395
|
+
// Slack routes the project per-message (`AGI: …`), so a handler may template
|
|
396
|
+
// its project/cwd — e.g. `project: "{{slack.project}}"`. Substitute + trim; an
|
|
397
|
+
// empty result omits the field (falls back to the run's default cwd / $HOME).
|
|
398
|
+
const substitutedProject = handler.project ? substituteWebhookPrompt(handler.project, context).trim() : '';
|
|
399
|
+
const substitutedCwd = handler.cwd ? substituteWebhookPrompt(handler.cwd, context).trim() : '';
|
|
349
400
|
// Resolved once so a fleet pick can't differ between the two dispatch paths.
|
|
350
401
|
const hostFields = resolveHandlerHost(handler.host);
|
|
351
402
|
if (handler.run?.agent || handler.run?.workflow) {
|
|
@@ -359,8 +410,8 @@ async function executeHandlerAction(handler, webhook, context, opts) {
|
|
|
359
410
|
...(handler.run.agent ? { agent: handler.run.agent } : { workflow: handler.run.workflow }),
|
|
360
411
|
...(handler.devices ? { devices: handler.devices } : {}),
|
|
361
412
|
...(handler.run.env ? { env: handler.run.env } : {}),
|
|
362
|
-
...(
|
|
363
|
-
...(
|
|
413
|
+
...(substitutedProject ? { project: substitutedProject } : {}),
|
|
414
|
+
...(substitutedCwd ? { cwd: substitutedCwd } : {}),
|
|
364
415
|
...(hostFields.host ? { host: hostFields.host } : {}),
|
|
365
416
|
...(hostFields.hostStrategy ? { hostStrategy: hostFields.hostStrategy } : {}),
|
|
366
417
|
};
|
|
@@ -385,8 +436,8 @@ async function executeHandlerAction(handler, webhook, context, opts) {
|
|
|
385
436
|
...routine,
|
|
386
437
|
prompt: substituteWebhookPrompt(routine.prompt, context),
|
|
387
438
|
...(handler.devices ? { devices: handler.devices } : {}),
|
|
388
|
-
...(
|
|
389
|
-
...(
|
|
439
|
+
...(substitutedProject ? { project: substitutedProject } : {}),
|
|
440
|
+
...(substitutedCwd ? { cwd: substitutedCwd } : {}),
|
|
390
441
|
...(handler.mode ? { mode: handler.mode } : {}),
|
|
391
442
|
...(hostFields.host ? { host: hostFields.host } : {}),
|
|
392
443
|
...(hostFields.hostStrategy ? { hostStrategy: hostFields.hostStrategy } : {}),
|
|
@@ -13,15 +13,17 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import * as http from 'http';
|
|
15
15
|
import type { IncomingHttpHeaders } from 'http';
|
|
16
|
-
import type { JobConfig, RunMeta, WebhookContext } from '../routines.js';
|
|
16
|
+
import type { JobConfig, RunMeta, WebhookContext } from '../scheduling/routines.js';
|
|
17
17
|
import { type FiredHandler } from './handlers.js';
|
|
18
|
-
export type WebhookSource = 'github' | 'linear';
|
|
18
|
+
export type WebhookSource = 'github' | 'linear' | 'slack';
|
|
19
19
|
export interface IncomingWebhook {
|
|
20
20
|
/** Delivery source, derived from `/hooks/<source>` or one-shot command flags. */
|
|
21
21
|
source: WebhookSource;
|
|
22
|
-
/** Source event name: GitHub header event
|
|
22
|
+
/** Source event name: GitHub header event, Linear payload `type`, or the Slack
|
|
23
|
+
* event subtype (`app_mention`) / slash command (`/agents`). */
|
|
23
24
|
event: string;
|
|
24
|
-
/** Decoded
|
|
25
|
+
/** Decoded request body (JSON for GitHub/Linear/Slack-events; the normalized
|
|
26
|
+
* {@link SlackPayload} for a Slack slash command's form body). */
|
|
25
27
|
payload: Record<string, unknown>;
|
|
26
28
|
}
|
|
27
29
|
export type GithubWebhook = IncomingWebhook & {
|
|
@@ -30,6 +32,9 @@ export type GithubWebhook = IncomingWebhook & {
|
|
|
30
32
|
export type LinearWebhook = IncomingWebhook & {
|
|
31
33
|
source: 'linear';
|
|
32
34
|
};
|
|
35
|
+
export type SlackWebhook = IncomingWebhook & {
|
|
36
|
+
source: 'slack';
|
|
37
|
+
};
|
|
33
38
|
/** Read `repository.full_name` (`owner/name`) from a webhook payload, if present. */
|
|
34
39
|
export declare function webhookRepo(payload: Record<string, unknown>): string | null;
|
|
35
40
|
/**
|
|
@@ -96,9 +101,59 @@ export declare function fireWebhookJobs(webhook: IncomingWebhook, options?: Fire
|
|
|
96
101
|
export declare function verifyGithubSignature(headers: IncomingHttpHeaders, rawBody: Buffer, secret: string): boolean;
|
|
97
102
|
export declare function verifyLinearSignature(headers: IncomingHttpHeaders, rawBody: Buffer, secret: string): boolean;
|
|
98
103
|
export declare function verifyLinearTimestamp(payload: Record<string, unknown>, now?: number, toleranceMs?: number): boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Verify a Slack request signature (the `v0` scheme). Slack signs the base
|
|
106
|
+
* string `v0:${timestamp}:${rawBody}` with the app's signing secret and sends
|
|
107
|
+
* the hex digest as `X-Slack-Signature: v0=<hex>`, alongside the unix
|
|
108
|
+
* `X-Slack-Request-Timestamp`. The timestamp is BOTH part of the signed base
|
|
109
|
+
* string AND checked for freshness here — a request older than `toleranceSec`
|
|
110
|
+
* (default 5 min) is rejected, so a captured, correctly-signed body cannot be
|
|
111
|
+
* replayed later. Fails closed on any missing/malformed header.
|
|
112
|
+
*/
|
|
113
|
+
export declare function verifySlackSignature(headers: IncomingHttpHeaders, rawBody: Buffer, secret: string, now?: number, toleranceSec?: number): boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Normalized fields extracted from a Slack slash-command or Events API delivery.
|
|
116
|
+
* This is the `payload` of a Slack {@link IncomingWebhook}: transport-level
|
|
117
|
+
* parsing lives here, message *semantics* (splitting the mention text into an
|
|
118
|
+
* agent / project / prompt) live in `handlers.ts` `buildWebhookContext`.
|
|
119
|
+
*/
|
|
120
|
+
export interface SlackPayload extends Record<string, unknown> {
|
|
121
|
+
/** `url_verification` | `event_callback` | `slash_command`. */
|
|
122
|
+
type: string;
|
|
123
|
+
/** Echoed back for the one-time Events API URL-verification handshake. */
|
|
124
|
+
challenge?: string;
|
|
125
|
+
/** Slack event id (Events API) — the dedup key when present. */
|
|
126
|
+
event_id?: string;
|
|
127
|
+
/** Event subtype, e.g. `app_mention` (Events API). */
|
|
128
|
+
event_type?: string;
|
|
129
|
+
/** Raw message text (the mention body, or the slash-command text). */
|
|
130
|
+
text?: string;
|
|
131
|
+
/** Channel id (`C0…`) the message arrived in. */
|
|
132
|
+
channel?: string;
|
|
133
|
+
/** Thread to reply into: an existing thread's parent ts, else the message ts. */
|
|
134
|
+
thread_ts?: string;
|
|
135
|
+
/** Invoking user id (`U0…`). */
|
|
136
|
+
user?: string;
|
|
137
|
+
/** Slash command name, e.g. `/agents`. */
|
|
138
|
+
command?: string;
|
|
139
|
+
/** Slash-command `response_url` (valid ~30 min, 5 uses). */
|
|
140
|
+
response_url?: string;
|
|
141
|
+
/** Slack team / workspace id. */
|
|
142
|
+
team?: string;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Parse a Slack delivery body into a normalized {@link SlackPayload}. Slack
|
|
146
|
+
* sends slash commands as `application/x-www-form-urlencoded` and Events API
|
|
147
|
+
* deliveries (including the `url_verification` handshake) as
|
|
148
|
+
* `application/json` — this is the one place that content-type branch lives.
|
|
149
|
+
*/
|
|
150
|
+
export declare function parseSlackBody(contentType: string | undefined, rawBody: Buffer): SlackPayload;
|
|
151
|
+
/** The `event` name a Slack delivery fires under: the slash command, or the event subtype. */
|
|
152
|
+
export declare function slackEventName(payload: SlackPayload): string;
|
|
99
153
|
export interface WebhookSecrets {
|
|
100
154
|
github?: string;
|
|
101
155
|
linear?: string;
|
|
156
|
+
slack?: string;
|
|
102
157
|
}
|
|
103
158
|
export interface DeliveryStore {
|
|
104
159
|
seen(id: string): boolean;
|
|
@@ -123,6 +178,15 @@ export interface RateLimiter {
|
|
|
123
178
|
take(key: string): boolean;
|
|
124
179
|
}
|
|
125
180
|
export declare function createMemoryRateLimiter(limit: number, windowMs: number): RateLimiter;
|
|
181
|
+
/**
|
|
182
|
+
* Resolve once a receiver is actually accepting connections, REJECT if the bind
|
|
183
|
+
* failed. `server.listen()` reports a bind failure (EADDRINUSE, EACCES) as an
|
|
184
|
+
* asynchronous `'error'` event, never a throw — so a `try/catch` around
|
|
185
|
+
* `startWebhookServer` cannot see it, and without this the event reaches Node's
|
|
186
|
+
* default handler and takes the whole process down. Every caller that hosts a
|
|
187
|
+
* receiver MUST await this rather than assuming the return means "bound".
|
|
188
|
+
*/
|
|
189
|
+
export declare function waitForListening(server: http.Server): Promise<void>;
|
|
126
190
|
/** Options for the local webhook http listener. */
|
|
127
191
|
export interface WebhookServerOptions {
|
|
128
192
|
port?: number;
|
|
@@ -131,8 +195,33 @@ export interface WebhookServerOptions {
|
|
|
131
195
|
secrets: WebhookSecrets;
|
|
132
196
|
/** Override the fire options (mainly for tests). */
|
|
133
197
|
fire?: FireWebhookOptions;
|
|
134
|
-
/**
|
|
198
|
+
/**
|
|
199
|
+
* Called the moment a delivery's matches are known — BEFORE any routine or
|
|
200
|
+
* handler is dispatched. Matching is a pure, synchronous lookup (no I/O), so
|
|
201
|
+
* this fires immediately after the ack, regardless of how long the matched
|
|
202
|
+
* work then takes to run. This is the right hook for a "webhook X fired Y"
|
|
203
|
+
* log line: a `run.command` handler that shells out a long agent session
|
|
204
|
+
* (`exec()`, which only resolves on process exit) used to hold that log back
|
|
205
|
+
* for as long as the session ran — `ps` would show the agent already running
|
|
206
|
+
* while the log still implied nothing had matched (RUSH-2722). Names only
|
|
207
|
+
* (no runId/exitCode yet — those aren't known until dispatch settles).
|
|
208
|
+
*/
|
|
209
|
+
onMatch?: (webhook: IncomingWebhook, matchedJobNames: string[], matchedHandlerNames: string[]) => void;
|
|
210
|
+
/**
|
|
211
|
+
* Called after a delivery has fully settled — every matched routine and
|
|
212
|
+
* handler dispatched (and, for `run.command` handlers, exited). Because the
|
|
213
|
+
* receiver acks the HTTP response BEFORE dispatch (see `startWebhookServer`),
|
|
214
|
+
* this fires strictly after the response has been written, and is the only
|
|
215
|
+
* way a caller observes the dispatch outcome (runId/exitCode/output). It is
|
|
216
|
+
* NOT the right hook for "did this webhook match" logging — use `onMatch`.
|
|
217
|
+
*/
|
|
135
218
|
onDelivery?: (webhook: IncomingWebhook, fired: FiredJob[], handlers: FiredHandler[]) => void;
|
|
219
|
+
/**
|
|
220
|
+
* Called when settling an already-acked delivery threw. The HTTP status can
|
|
221
|
+
* no longer carry the failure, so this is the loud path — the daemon host and
|
|
222
|
+
* `agents webhooks serve` both log it. Never swallowed silently.
|
|
223
|
+
*/
|
|
224
|
+
onDeliveryError?: (webhook: IncomingWebhook, error: Error) => void;
|
|
136
225
|
deliveryStore?: DeliveryStore;
|
|
137
226
|
rateLimiter?: RateLimiter;
|
|
138
227
|
rateLimitPerMinute?: number;
|
|
@@ -149,6 +238,25 @@ export interface WebhookServerOptions {
|
|
|
149
238
|
* POST /hooks/github with X-Hub-Signature-256
|
|
150
239
|
* POST /hooks/linear with Linear-Signature + fresh webhookTimestamp
|
|
151
240
|
*
|
|
241
|
+
* **The ack is asynchronous (RUSH-2548).** Once a delivery has passed signature
|
|
242
|
+
* verification, freshness, dedup, and rate limiting, the receiver writes
|
|
243
|
+
* `202 {ok:true, accepted:true}` IMMEDIATELY and dispatches the matched routines
|
|
244
|
+
* and handlers afterwards. Dispatch starts an agent run and takes 15-20s, which
|
|
245
|
+
* exceeds Linear's delivery timeout — holding the socket open across it made
|
|
246
|
+
* every real delivery log a timeout + retry on Linear's side. Nothing about the
|
|
247
|
+
* dedup ledger changes: the `<source>:<delivery-id>` key is still what makes a
|
|
248
|
+
* retry a no-op, per-job `markJob` still lets a retry finish only the matches
|
|
249
|
+
* that failed, and the delivery is marked complete only after it settles.
|
|
250
|
+
*
|
|
251
|
+
* A retry that lands WHILE the first is still settling is answered as a
|
|
252
|
+
* duplicate from an in-flight set, since `deliveryStore.seen` only reports
|
|
253
|
+
* completed deliveries and would otherwise let a mid-flight retry double-fire.
|
|
254
|
+
*
|
|
255
|
+
* `onMatch` fires as soon as matching is known, before any dispatch; `onDelivery`
|
|
256
|
+
* fires only once every matched routine/handler has settled — see their docs on
|
|
257
|
+
* `WebhookServerOptions`. A caller that wants a prompt "this fired" log uses
|
|
258
|
+
* `onMatch`, not `onDelivery` (RUSH-2722).
|
|
259
|
+
*
|
|
152
260
|
* Returns the underlying server so callers can `close()` it.
|
|
153
261
|
*/
|
|
154
262
|
export declare function startWebhookServer(options: WebhookServerOptions): http.Server;
|