@phnx-labs/agents-cli 1.22.35 → 1.22.37
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 +666 -2
- package/README.md +75 -35
- package/dist/bin/agents +0 -0
- package/dist/bootstrap.d.ts +15 -0
- package/dist/bootstrap.js +1211 -0
- package/dist/commands/accounts.d.ts +4 -11
- package/dist/commands/accounts.js +159 -27
- package/dist/commands/attach.js +17 -4
- package/dist/commands/audit.d.ts +8 -8
- package/dist/commands/audit.js +57 -47
- package/dist/commands/browser.js +15 -11
- package/dist/commands/cloud.js +1 -1
- package/dist/commands/commands.js +0 -11
- package/dist/commands/computer-actions.js +33 -0
- package/dist/commands/computer-sessions-picker.d.ts +21 -0
- package/dist/commands/computer-sessions-picker.js +141 -0
- package/dist/commands/computer.d.ts +16 -0
- package/dist/commands/computer.js +37 -0
- package/dist/commands/config.d.ts +17 -0
- package/dist/commands/config.js +401 -0
- package/dist/commands/cp.d.ts +84 -0
- package/dist/commands/cp.js +231 -0
- package/dist/commands/daemon.js +243 -14
- package/dist/commands/detach-core.d.ts +1 -1
- package/dist/commands/detach-core.js +12 -2
- package/dist/commands/detach.js +1 -1
- package/dist/commands/doctor.js +64 -5
- package/dist/commands/events.d.ts +24 -12
- package/dist/commands/events.js +144 -28
- package/dist/commands/exec.js +85 -41
- package/dist/commands/feed.d.ts +1 -1
- package/dist/commands/feed.js +16 -8
- package/dist/commands/focus.d.ts +33 -1
- package/dist/commands/focus.js +177 -17
- package/dist/commands/funnel.d.ts +1 -1
- package/dist/commands/go.js +9 -8
- package/dist/commands/harness-wizard.d.ts +1 -0
- package/dist/commands/harness-wizard.js +18 -20
- package/dist/commands/harness.d.ts +2 -0
- package/dist/commands/harness.js +59 -26
- package/dist/commands/hooks.js +0 -11
- package/dist/commands/inspect.d.ts +94 -1
- package/dist/commands/inspect.js +866 -40
- package/dist/commands/lease.d.ts +4 -4
- package/dist/commands/lease.js +6 -6
- package/dist/commands/login.js +0 -13
- package/dist/commands/logs.d.ts +2 -2
- package/dist/commands/logs.js +2 -2
- package/dist/commands/mcp.js +7 -2
- package/dist/commands/memory.js +7 -2
- package/dist/commands/message.d.ts +1 -1
- package/dist/commands/message.js +37 -6
- package/dist/commands/models.js +4 -0
- package/dist/commands/monitors.d.ts +0 -1
- package/dist/commands/monitors.js +199 -16
- package/dist/commands/open.d.ts +18 -0
- package/dist/commands/open.js +57 -0
- package/dist/commands/packages.js +2 -107
- package/dist/commands/plugins.js +6 -3
- package/dist/commands/profiles.d.ts +1 -0
- package/dist/commands/profiles.js +16 -160
- package/dist/commands/projects.d.ts +28 -0
- package/dist/commands/projects.js +125 -5
- package/dist/commands/reconnect.js +9 -3
- package/dist/commands/repo.js +42 -1
- package/dist/commands/resource-view.d.ts +17 -0
- package/dist/commands/resource-view.js +36 -14
- package/dist/commands/resume.js +9 -2
- package/dist/commands/routines.d.ts +0 -2
- package/dist/commands/routines.js +473 -289
- package/dist/commands/secrets.js +52 -9
- package/dist/commands/sessions-export.d.ts +47 -0
- package/dist/commands/sessions-export.js +116 -6
- package/dist/commands/sessions-import.d.ts +17 -0
- package/dist/commands/sessions-import.js +114 -6
- package/dist/commands/sessions-migrate.d.ts +27 -0
- package/dist/commands/sessions-migrate.js +50 -9
- package/dist/commands/sessions-picker.js +23 -4
- package/dist/commands/sessions-resume.d.ts +5 -3
- package/dist/commands/sessions-resume.js +30 -8
- package/dist/commands/sessions-watch.d.ts +2 -0
- package/dist/commands/sessions-watch.js +53 -0
- package/dist/commands/sessions.d.ts +66 -3
- package/dist/commands/sessions.js +298 -47
- package/dist/commands/set.d.ts +1 -1
- package/dist/commands/set.js +2 -2
- package/dist/commands/setup-browser.js +2 -2
- package/dist/commands/setup-mine.js +0 -1
- package/dist/commands/setup-preferences.js +1 -1
- package/dist/commands/setup-share.js +34 -4
- package/dist/commands/setup.d.ts +5 -0
- package/dist/commands/setup.js +26 -0
- package/dist/commands/share.d.ts +67 -0
- package/dist/commands/share.js +275 -12
- package/dist/commands/skills.js +0 -11
- package/dist/commands/snapshot.js +1 -1
- package/dist/commands/ssh.d.ts +18 -0
- package/dist/commands/ssh.js +549 -210
- package/dist/commands/sync.d.ts +5 -0
- package/dist/commands/sync.js +212 -32
- package/dist/commands/teams.d.ts +13 -0
- package/dist/commands/teams.js +187 -30
- package/dist/commands/tickets.d.ts +2 -0
- package/dist/commands/tickets.js +43 -0
- package/dist/commands/update.js +2 -4
- package/dist/commands/usage.js +5 -3
- package/dist/commands/versions.js +11 -5
- package/dist/commands/view.js +15 -7
- package/dist/commands/webhook.d.ts +2 -2
- package/dist/commands/webhook.js +7 -7
- package/dist/index.d.ts +18 -2
- package/dist/index.js +53 -1264
- package/dist/lib/account-catalog.d.ts +18 -0
- package/dist/lib/account-catalog.js +38 -0
- package/dist/lib/account-provider-registry.d.ts +18 -0
- package/dist/lib/account-provider-registry.js +59 -0
- package/dist/lib/account-registry.d.ts +40 -0
- package/dist/lib/account-registry.js +239 -0
- package/dist/lib/account-schema.d.ts +44 -0
- package/dist/lib/account-schema.js +91 -0
- package/dist/lib/account-state-service.d.ts +21 -0
- package/dist/lib/account-state-service.js +60 -0
- package/dist/lib/activity.d.ts +1 -1
- package/dist/lib/activity.js +8 -1
- package/dist/lib/add-dir.d.ts +80 -0
- package/dist/lib/add-dir.js +241 -0
- package/dist/lib/agent-cli-commands.d.ts +11 -0
- package/dist/lib/agent-cli-commands.js +30 -0
- package/dist/lib/agents.js +44 -36
- package/dist/lib/answer-router.js +1 -1
- package/dist/lib/audit/log.d.ts +10 -27
- package/dist/lib/audit/log.js +20 -33
- package/dist/lib/auth-health.d.ts +9 -2
- package/dist/lib/auth-health.js +42 -9
- package/dist/lib/auto-pull-worker.js +7 -3
- package/dist/lib/auto-pull.d.ts +44 -3
- package/dist/lib/auto-pull.js +88 -5
- package/dist/lib/binary-shadow.d.ts +28 -0
- package/dist/lib/binary-shadow.js +121 -0
- package/dist/lib/brand.js +9 -3
- package/dist/lib/browser/ipc.d.ts +30 -0
- package/dist/lib/browser/ipc.js +81 -4
- package/dist/lib/browser/profiles.d.ts +3 -2
- package/dist/lib/browser/profiles.js +65 -22
- package/dist/lib/browser/service.d.ts +4 -0
- package/dist/lib/browser/service.js +30 -3
- package/dist/lib/browser/sessions-list.d.ts +22 -2
- package/dist/lib/browser/sessions-list.js +54 -6
- package/dist/lib/browser/stream.d.ts +2 -0
- package/dist/lib/browser/stream.js +1 -0
- package/dist/lib/browser/types.d.ts +19 -0
- package/dist/lib/byok-usage.d.ts +9 -2
- package/dist/lib/byok-usage.js +133 -31
- package/dist/lib/cli-entry.d.ts +11 -0
- package/dist/lib/cli-entry.js +46 -0
- package/dist/lib/cloud/host.d.ts +1 -1
- package/dist/lib/cloud/host.js +2 -2
- package/dist/lib/cloud/registry.js +1 -1
- package/dist/lib/cloud/types.d.ts +1 -1
- package/dist/lib/commands.d.ts +2 -0
- package/dist/lib/commands.js +2 -0
- package/dist/lib/computer/sessions-list.d.ts +150 -0
- package/dist/lib/computer/sessions-list.js +363 -0
- package/dist/lib/config-keys.d.ts +86 -0
- package/dist/lib/config-keys.js +193 -0
- package/dist/lib/config-machine-keys.d.ts +12 -0
- package/dist/lib/config-machine-keys.js +17 -0
- package/dist/lib/config-transfer.js +3 -4
- package/dist/lib/crabbox/cli.d.ts +2 -2
- package/dist/lib/crabbox/cli.js +3 -3
- package/dist/lib/daemon-health.d.ts +22 -0
- package/dist/lib/daemon-health.js +33 -3
- package/dist/lib/daemon-services.d.ts +50 -0
- package/dist/lib/daemon-services.js +147 -0
- package/dist/lib/daemon-ticks.d.ts +35 -66
- package/dist/lib/daemon-ticks.js +77 -159
- package/dist/lib/daemon.d.ts +72 -4
- package/dist/lib/daemon.js +792 -202
- package/dist/lib/deeplink/register.d.ts +49 -0
- package/dist/lib/deeplink/register.js +253 -0
- package/dist/lib/deeplink/url.d.ts +34 -0
- package/dist/lib/deeplink/url.js +78 -0
- package/dist/lib/device-config.d.ts +124 -29
- package/dist/lib/device-config.js +346 -141
- package/dist/lib/devices/config-migration.d.ts +42 -0
- package/dist/lib/devices/config-migration.js +203 -0
- package/dist/lib/devices/connect.js +14 -7
- package/dist/lib/devices/doctor-findings.d.ts +4 -1
- package/dist/lib/devices/doctor-findings.js +20 -1
- package/dist/lib/devices/harness-inventory.d.ts +11 -2
- package/dist/lib/devices/harness-inventory.js +0 -0
- package/dist/lib/devices/health.d.ts +1 -1
- package/dist/lib/devices/health.js +1 -1
- package/dist/lib/devices/pending.d.ts +22 -1
- package/dist/lib/devices/pending.js +67 -2
- package/dist/lib/devices/registry.d.ts +0 -25
- package/dist/lib/devices/registry.js +2 -83
- package/dist/lib/devices/resolve-profile.d.ts +20 -0
- package/dist/lib/devices/resolve-profile.js +44 -0
- package/dist/lib/devices/rollout-verify.d.ts +101 -0
- package/dist/lib/devices/rollout-verify.js +193 -0
- package/dist/lib/devices/ssh-config.js +10 -6
- package/dist/lib/event-families.d.ts +28 -0
- package/dist/lib/event-families.js +159 -0
- package/dist/lib/event-stream.d.ts +9 -1
- package/dist/lib/event-stream.js +26 -9
- package/dist/lib/events.d.ts +9 -1
- package/dist/lib/events.js +21 -6
- package/dist/lib/exec.d.ts +30 -0
- package/dist/lib/exec.js +219 -121
- package/dist/lib/feed-broadcast.d.ts +25 -0
- package/dist/lib/feed-broadcast.js +33 -0
- package/dist/lib/feed.d.ts +1 -1
- package/dist/lib/feed.js +12 -2
- package/dist/lib/fleet/capture.js +15 -0
- package/dist/lib/fleet/manifest.js +9 -0
- package/dist/lib/fleet/types.d.ts +9 -0
- package/dist/lib/fleet-status.js +10 -8
- package/dist/lib/git.d.ts +20 -6
- package/dist/lib/git.js +121 -17
- package/dist/lib/hosts/dispatch.d.ts +8 -3
- package/dist/lib/hosts/dispatch.js +29 -3
- package/dist/lib/hosts/logs.d.ts +2 -2
- package/dist/lib/hosts/logs.js +2 -2
- package/dist/lib/hosts/option.js +1 -1
- package/dist/lib/hosts/passthrough.d.ts +2 -3
- package/dist/lib/hosts/passthrough.js +10 -24
- package/dist/lib/hosts/progress.js +2 -2
- package/dist/lib/hosts/providers/devices.d.ts +3 -3
- package/dist/lib/hosts/providers/devices.js +18 -12
- package/dist/lib/hosts/ready.d.ts +5 -1
- package/dist/lib/hosts/ready.js +9 -3
- package/dist/lib/hosts/reconcile.d.ts +2 -2
- package/dist/lib/hosts/reconcile.js +2 -2
- package/dist/lib/hosts/registry.js +14 -9
- package/dist/lib/hosts/remote-cmd.js +1 -1
- package/dist/lib/hosts/remote-os.d.ts +9 -6
- package/dist/lib/hosts/remote-os.js +13 -6
- package/dist/lib/hosts/routing-flag.d.ts +23 -0
- package/dist/lib/hosts/routing-flag.js +41 -0
- package/dist/lib/hosts/run-target.js +1 -1
- package/dist/lib/hosts/session-index.js +1 -1
- package/dist/lib/hosts/tasks.d.ts +6 -6
- package/dist/lib/hosts/tasks.js +4 -4
- package/dist/lib/hosts/types.js +1 -2
- package/dist/lib/installations/resolve.js +2 -8
- package/dist/lib/isolation-boundary-report.js +0 -1
- package/dist/lib/linear-cache.d.ts +7 -0
- package/dist/lib/linear-cache.js +31 -4
- package/dist/lib/linear-project-counts.d.ts +1 -1
- package/dist/lib/linear-project-counts.js +2 -3
- package/dist/lib/linear-projects.js +1 -1
- package/dist/lib/loop.d.ts +2 -2
- package/dist/lib/loop.js +1 -1
- package/dist/lib/mailbox-target.d.ts +1 -1
- package/dist/lib/mailbox-target.js +1 -1
- package/dist/lib/manifest.js +7 -4
- 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/snapshot.d.ts +3 -2
- package/dist/lib/menubar/snapshot.js +6 -2
- package/dist/lib/migrate-fold.d.ts +33 -0
- package/dist/lib/migrate-fold.js +130 -0
- package/dist/lib/migrate.d.ts +34 -34
- package/dist/lib/migrate.js +106 -128
- package/dist/lib/model-tier-overrides.d.ts +1 -1
- package/dist/lib/model-tier-overrides.js +15 -2
- package/dist/lib/monitors/config.d.ts +17 -3
- package/dist/lib/monitors/config.js +52 -18
- package/dist/lib/monitors/engine.d.ts +32 -1
- package/dist/lib/monitors/engine.js +94 -11
- package/dist/lib/monitors/fingerprint.d.ts +46 -0
- package/dist/lib/monitors/fingerprint.js +100 -0
- package/dist/lib/monitors/remote.d.ts +47 -0
- package/dist/lib/monitors/remote.js +81 -0
- package/dist/lib/monitors/state.d.ts +39 -0
- package/dist/lib/monitors/state.js +56 -0
- package/dist/lib/onepassword.d.ts +17 -0
- package/dist/lib/onepassword.js +52 -22
- package/dist/lib/open-url.js +1 -1
- package/dist/lib/picker.d.ts +14 -2
- package/dist/lib/picker.js +35 -13
- package/dist/lib/placement.d.ts +1 -1
- package/dist/lib/placement.js +1 -1
- package/dist/lib/pr-land-detach.d.ts +32 -0
- package/dist/lib/pr-land-detach.js +79 -0
- package/dist/lib/profiles-presets.js +13 -0
- package/dist/lib/profiles.d.ts +2 -0
- package/dist/lib/profiles.js +44 -1
- package/dist/lib/project-focus.d.ts +1 -1
- package/dist/lib/project-focus.js +1 -1
- package/dist/lib/project-probe.d.ts +4 -1
- package/dist/lib/project-probe.js +5 -4
- package/dist/lib/project-resources.js +2 -18
- package/dist/lib/project-root.d.ts +16 -0
- package/dist/lib/project-root.js +20 -2
- package/dist/lib/projects.d.ts +20 -1
- package/dist/lib/projects.js +78 -1
- package/dist/lib/refresh-coordinator.d.ts +24 -0
- package/dist/lib/refresh-coordinator.js +52 -0
- package/dist/lib/registry.d.ts +2 -2
- package/dist/lib/registry.js +1 -1
- package/dist/lib/resource-aliases.d.ts +13 -0
- package/dist/lib/resource-aliases.js +26 -0
- package/dist/lib/resources/types.d.ts +1 -1
- package/dist/lib/resources.d.ts +16 -0
- package/dist/lib/resources.js +66 -10
- package/dist/lib/rotate.d.ts +3 -4
- package/dist/lib/rotate.js +4 -5
- package/dist/lib/routine-activation.d.ts +22 -2
- package/dist/lib/routine-activation.js +63 -16
- package/dist/lib/routine-context.d.ts +9 -2
- package/dist/lib/routine-context.js +21 -6
- package/dist/lib/routines-project.d.ts +58 -48
- package/dist/lib/routines-project.js +190 -159
- package/dist/lib/routines.d.ts +41 -6
- package/dist/lib/routines.js +92 -34
- package/dist/lib/run-defaults.d.ts +5 -0
- package/dist/lib/run-defaults.js +11 -1
- package/dist/lib/runner.d.ts +10 -8
- package/dist/lib/runner.js +122 -39
- 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.d.ts +10 -3
- package/dist/lib/secrets/agent.js +43 -8
- package/dist/lib/secrets/bundles.d.ts +1 -0
- package/dist/lib/secrets/bundles.js +92 -80
- package/dist/lib/secrets/index.js +32 -9
- package/dist/lib/secrets/install-helper.d.ts +4 -4
- package/dist/lib/secrets/install-helper.js +4 -4
- package/dist/lib/secrets/push.d.ts +40 -6
- package/dist/lib/secrets/push.js +58 -11
- package/dist/lib/secrets/read-backoff.d.ts +1 -1
- package/dist/lib/secrets/read-backoff.js +1 -1
- package/dist/lib/secrets/remote.d.ts +24 -0
- package/dist/lib/secrets/remote.js +54 -4
- package/dist/lib/self-update.d.ts +108 -0
- package/dist/lib/self-update.js +276 -1
- package/dist/lib/session/active.d.ts +89 -5
- package/dist/lib/session/active.js +165 -10
- package/dist/lib/session/actor-sidecar.d.ts +1 -1
- package/dist/lib/session/actor-sidecar.js +2 -1
- package/dist/lib/session/db.d.ts +176 -2
- package/dist/lib/session/db.js +484 -17
- package/dist/lib/session/discover.js +27 -4
- package/dist/lib/session/hook-sessions.js +2 -2
- package/dist/lib/session/host-link.d.ts +2 -2
- package/dist/lib/session/host-link.js +2 -2
- package/dist/lib/session/pid-registry.d.ts +21 -0
- package/dist/lib/session/pid-registry.js +57 -0
- package/dist/lib/session/remote-active.js +15 -1
- package/dist/lib/session/remote.js +2 -2
- package/dist/lib/session/session-cache.d.ts +14 -7
- package/dist/lib/session/session-cache.js +51 -9
- package/dist/lib/session/state.d.ts +2 -2
- package/dist/lib/session/state.js +1 -1
- package/dist/lib/session/sync/config.d.ts +10 -10
- package/dist/lib/session/sync/config.js +10 -10
- package/dist/lib/session/sync/r2.d.ts +34 -0
- package/dist/lib/session/sync/r2.js +123 -0
- package/dist/lib/session/throughput.d.ts +1 -1
- package/dist/lib/session/throughput.js +1 -1
- package/dist/lib/session/types.d.ts +23 -1
- package/dist/lib/session/types.js +15 -0
- package/dist/lib/session/viewing-in.d.ts +1 -1
- package/dist/lib/session/viewing-in.js +1 -1
- package/dist/lib/session/watch.d.ts +101 -0
- package/dist/lib/session/watch.js +242 -0
- package/dist/lib/share/config.d.ts +4 -0
- package/dist/lib/share/config.js +1 -0
- package/dist/lib/share/provision.d.ts +38 -0
- package/dist/lib/share/provision.js +50 -0
- package/dist/lib/share/publish.d.ts +40 -1
- package/dist/lib/share/publish.js +116 -3
- package/dist/lib/share/worker-template.js +71 -6
- package/dist/lib/shims.d.ts +17 -3
- package/dist/lib/shims.js +98 -26
- package/dist/lib/signin-badge.js +3 -2
- package/dist/lib/skills.js +2 -0
- package/dist/lib/smart-launch.d.ts +8 -8
- package/dist/lib/smart-launch.js +80 -59
- package/dist/lib/ssh-exec.d.ts +1 -1
- package/dist/lib/ssh-exec.js +1 -1
- package/dist/lib/staleness/prune.d.ts +88 -0
- package/dist/lib/staleness/prune.js +69 -0
- package/dist/lib/staleness/registry.d.ts +1 -1
- package/dist/lib/staleness/writers/commands.js +34 -2
- package/dist/lib/staleness/writers/hooks.js +16 -0
- package/dist/lib/staleness/writers/kinds.d.ts +6 -0
- package/dist/lib/staleness/writers/skills.js +19 -0
- package/dist/lib/staleness/writers/subagents.d.ts +2 -3
- package/dist/lib/staleness/writers/subagents.js +0 -4
- package/dist/lib/staleness/writers/types.d.ts +32 -0
- package/dist/lib/startup/command-registry.d.ts +6 -12
- package/dist/lib/startup/command-registry.js +11 -31
- package/dist/lib/startup/dev-build.d.ts +10 -0
- package/dist/lib/startup/dev-build.js +13 -1
- package/dist/lib/startup/spellcheck.d.ts +18 -0
- package/dist/lib/startup/spellcheck.js +45 -0
- package/dist/lib/state.d.ts +36 -9
- package/dist/lib/state.js +96 -46
- package/dist/lib/subagents-registry.d.ts +0 -7
- package/dist/lib/subagents-registry.js +38 -65
- package/dist/lib/subagents.d.ts +0 -33
- package/dist/lib/subagents.js +0 -75
- package/dist/lib/sync-umbrella.js +1 -1
- package/dist/lib/teams/agents.d.ts +41 -1
- package/dist/lib/teams/agents.js +187 -9
- package/dist/lib/teams/api.d.ts +11 -1
- package/dist/lib/teams/api.js +11 -2
- package/dist/lib/teams/delivery.d.ts +41 -0
- package/dist/lib/teams/delivery.js +60 -0
- package/dist/lib/teams/registry.d.ts +14 -0
- package/dist/lib/teams/registry.js +51 -1
- package/dist/lib/teams/remoteWorktree.d.ts +19 -0
- package/dist/lib/teams/remoteWorktree.js +29 -0
- package/dist/lib/teams/scheduler.d.ts +1 -1
- package/dist/lib/teams/scheduler.js +1 -1
- package/dist/lib/teams/worktree.d.ts +24 -0
- package/dist/lib/teams/worktree.js +42 -0
- package/dist/lib/terminal/backends/vscodium-agent.d.ts +10 -1
- package/dist/lib/terminal/backends/vscodium-agent.js +16 -5
- package/dist/lib/terminal/engine.d.ts +4 -0
- package/dist/lib/terminal/engine.js +8 -2
- package/dist/lib/terminal/types.d.ts +21 -2
- package/dist/lib/testdata/refresh-coordinator-worker.d.ts +1 -0
- package/dist/lib/testdata/refresh-coordinator-worker.js +23 -0
- package/dist/lib/tickets/list.d.ts +53 -0
- package/dist/lib/tickets/list.js +153 -0
- package/dist/lib/tmux/orphan-reap.d.ts +320 -0
- package/dist/lib/tmux/orphan-reap.js +644 -0
- package/dist/lib/tmux/session.d.ts +68 -3
- package/dist/lib/tmux/session.js +95 -5
- package/dist/lib/triggers/handlers.d.ts +20 -0
- package/dist/lib/triggers/handlers.js +6 -1
- package/dist/lib/types.d.ts +46 -34
- package/dist/lib/usage-fleet.d.ts +32 -0
- package/dist/lib/usage-fleet.js +125 -0
- package/dist/lib/usage-refresh.d.ts +3 -3
- package/dist/lib/usage-refresh.js +19 -16
- package/dist/lib/usage.d.ts +51 -47
- package/dist/lib/usage.js +145 -153
- package/dist/lib/version-duplicates.js +2 -2
- package/dist/lib/versions.d.ts +56 -13
- package/dist/lib/versions.js +195 -45
- package/dist/lib/watchdog/log.d.ts +1 -1
- package/dist/lib/watchdog/log.js +3 -3
- package/dist/lib/watchdog/rotate.d.ts +6 -6
- package/dist/lib/watchdog/rotate.js +6 -6
- package/dist/lib/workflows.d.ts +1 -1
- package/dist/lib/yaml-io.d.ts +47 -0
- package/dist/lib/yaml-io.js +55 -0
- package/package.json +2 -1
- package/scripts/install-helper.js +2 -2
- package/scripts/postinstall.js +23 -20
- package/dist/commands/defaults.d.ts +0 -7
- package/dist/commands/defaults.js +0 -107
- package/dist/commands/export.d.ts +0 -11
- package/dist/commands/export.js +0 -215
- package/dist/commands/helper.d.ts +0 -12
- package/dist/commands/helper.js +0 -87
- package/dist/commands/hosts.d.ts +0 -11
- package/dist/commands/hosts.js +0 -330
- package/dist/commands/lock.d.ts +0 -12
- package/dist/commands/lock.js +0 -70
- package/dist/commands/pull.d.ts +0 -17
- package/dist/commands/pull.js +0 -39
- package/dist/commands/push.d.ts +0 -14
- package/dist/commands/push.js +0 -30
- package/dist/commands/wallet.d.ts +0 -20
- package/dist/commands/wallet.js +0 -216
- package/dist/commands/worktree.d.ts +0 -19
- package/dist/commands/worktree.js +0 -272
- package/dist/lib/account-labels.d.ts +0 -24
- package/dist/lib/account-labels.js +0 -72
- package/dist/lib/auto-dispatch-linear.d.ts +0 -18
- package/dist/lib/auto-dispatch-linear.js +0 -107
- package/dist/lib/auto-dispatch-provider.d.ts +0 -10
- package/dist/lib/auto-dispatch-provider.js +0 -30
- package/dist/lib/auto-dispatch.d.ts +0 -93
- package/dist/lib/auto-dispatch.js +0 -128
- package/dist/lib/export.d.ts +0 -72
- package/dist/lib/export.js +0 -269
- package/dist/lib/lock.d.ts +0 -93
- package/dist/lib/lock.js +0 -207
- package/dist/lib/wallet/index.d.ts +0 -78
- package/dist/lib/wallet/index.js +0 -253
|
@@ -102,6 +102,35 @@ export function createRemoteWorktree(target, repoPath, worktreeName, opts = {})
|
|
|
102
102
|
remoteGit(target, gitRoot, ['worktree', 'add', '-b', branchName, worktreePath, `origin/${base}`], 120000, opts);
|
|
103
103
|
return worktreePath;
|
|
104
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* How many commits the host checkout at `repoPath` is behind `origin/<default>` —
|
|
107
|
+
* the remote analog of the local {@link commitsBehindDefault} staleness probe, and
|
|
108
|
+
* the exact case from the incident this guard exists for (a distributed team
|
|
109
|
+
* pointed at a 71-commit-stale checkout on another box).
|
|
110
|
+
*
|
|
111
|
+
* `ensureRemoteRepo` already fetched `origin` when it provisioned/reused the
|
|
112
|
+
* checkout right before this runs, so the remote-tracking ref is usually fresh and
|
|
113
|
+
* this reads it WITHOUT a second fetch: resolve the default branch, then
|
|
114
|
+
* `rev-list --count HEAD..origin/<default>`. (That reuse fetch is best-effort —
|
|
115
|
+
* an offline host leaves the ref stale, so this under-reports rather than blocks;
|
|
116
|
+
* `createRemoteWorktree` re-fetches at launch so the teammate's base is still
|
|
117
|
+
* fresh regardless.) Returns null on any git/ssh error (unreachable host, non-repo
|
|
118
|
+
* path) — the caller treats null as "can't tell, don't block".
|
|
119
|
+
*/
|
|
120
|
+
export function remoteCommitsBehindDefault(target, repoPath, opts = {}) {
|
|
121
|
+
assertValidSshTarget(target);
|
|
122
|
+
try {
|
|
123
|
+
const base = remoteDefaultBranch(target, repoPath, opts);
|
|
124
|
+
const raw = remoteGit(target, repoPath, ['rev-list', '--count', `HEAD..origin/${base}`], 30000, opts);
|
|
125
|
+
const behind = parseInt(raw, 10);
|
|
126
|
+
if (!Number.isFinite(behind))
|
|
127
|
+
return null;
|
|
128
|
+
return { behind, base };
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
105
134
|
// Team-name → repos-dir slug: same allowlist a worktree name uses, so it lands
|
|
106
135
|
// safely in a path (`~/.agents/repos/<slug>`) with no shell metacharacters.
|
|
107
136
|
const SLUG_RE = /[^A-Za-z0-9_-]/g;
|
|
@@ -30,7 +30,7 @@ export interface PlacementTeam {
|
|
|
30
30
|
* device name to its `agents.max-concurrent` cap (from the device doc — read
|
|
31
31
|
* locally via `readMaxConcurrentCaps`, never probed over SSH). Teams counts
|
|
32
32
|
* the team's OWN roster against the cap (device-global counting would need an
|
|
33
|
-
* SSH probe per candidate — out of the hot path;
|
|
33
|
+
* SSH probe per candidate — out of the hot path; AGI EXT auto-launch is the
|
|
34
34
|
* device-wide counter). Only the least-loaded AUTO-PICK (cascade step 3)
|
|
35
35
|
* honors caps: an explicit pin or a pool of one is the user's own choice and
|
|
36
36
|
* is never second-guessed.
|
|
@@ -132,7 +132,7 @@ export function pickLeastLoaded(devices, roster, maxConcurrent) {
|
|
|
132
132
|
.map((d) => `${d} (${load.get(d) ?? 0}/${maxConcurrent[d]})`)
|
|
133
133
|
.join(', ');
|
|
134
134
|
throw new Error(`Every device in the pool is at its agents.max-concurrent cap: ${detail}. ` +
|
|
135
|
-
`Raise a cap with 'agents devices
|
|
135
|
+
`Raise a cap with 'agents devices config <name> agents.max-concurrent N' or add a device to the pool.`);
|
|
136
136
|
}
|
|
137
137
|
// Iterate the pool in declared order so the first device wins ties.
|
|
138
138
|
let best = eligible[0];
|
|
@@ -27,6 +27,30 @@ export declare function gitDiff(worktreePath: string, maxBytes?: number): Promis
|
|
|
27
27
|
* Falls back to `main` when origin/HEAD isn't set.
|
|
28
28
|
*/
|
|
29
29
|
export declare function localDefaultBranch(gitRoot: string): Promise<string>;
|
|
30
|
+
/**
|
|
31
|
+
* How many commits the checkout at `repoDir` is behind freshly-fetched
|
|
32
|
+
* `origin/<default>` — the staleness the `teams add` guard checks before pointing
|
|
33
|
+
* a team at a repo.
|
|
34
|
+
*
|
|
35
|
+
* Fetches `origin` FIRST, on purpose: the exact failure this guards (a team
|
|
36
|
+
* pointed at a repo "without fetching first" — a 71-commit-stale s1 checkout in
|
|
37
|
+
* the real incident) leaves the remote-tracking ref itself stale, so a naive
|
|
38
|
+
* `HEAD..origin/<default>` reads 0 and hides the drift. After the fetch the count
|
|
39
|
+
* is against the true remote.
|
|
40
|
+
*
|
|
41
|
+
* Measures the passed checkout's OWN root ({@link getGitRoot} / `--show-toplevel`,
|
|
42
|
+
* worktree-correct) — NOT {@link getMainRepoRoot}: for a `--use-worktree` shared
|
|
43
|
+
* worktree (or a caller standing inside a linked worktree), the teammate runs in
|
|
44
|
+
* THAT worktree, whose HEAD differs from the main checkout's, so folding to the
|
|
45
|
+
* main root would report the wrong tree's staleness. `origin/<default>` resolves
|
|
46
|
+
* from the shared object store regardless of which worktree we stand in. Returns
|
|
47
|
+
* null when `repoDir` isn't a git repo, origin is unreachable, or git errors — the
|
|
48
|
+
* caller treats null as "can't tell, don't block".
|
|
49
|
+
*/
|
|
50
|
+
export declare function commitsBehindDefault(repoDir: string): Promise<{
|
|
51
|
+
behind: number;
|
|
52
|
+
base: string;
|
|
53
|
+
} | null>;
|
|
30
54
|
/**
|
|
31
55
|
* Create a new git worktree for a teammate, branched off the freshly-fetched
|
|
32
56
|
* default branch. Fetches `origin` first and bases the branch on
|
|
@@ -100,6 +100,48 @@ export async function localDefaultBranch(gitRoot) {
|
|
|
100
100
|
}
|
|
101
101
|
return 'main';
|
|
102
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* How many commits the checkout at `repoDir` is behind freshly-fetched
|
|
105
|
+
* `origin/<default>` — the staleness the `teams add` guard checks before pointing
|
|
106
|
+
* a team at a repo.
|
|
107
|
+
*
|
|
108
|
+
* Fetches `origin` FIRST, on purpose: the exact failure this guards (a team
|
|
109
|
+
* pointed at a repo "without fetching first" — a 71-commit-stale s1 checkout in
|
|
110
|
+
* the real incident) leaves the remote-tracking ref itself stale, so a naive
|
|
111
|
+
* `HEAD..origin/<default>` reads 0 and hides the drift. After the fetch the count
|
|
112
|
+
* is against the true remote.
|
|
113
|
+
*
|
|
114
|
+
* Measures the passed checkout's OWN root ({@link getGitRoot} / `--show-toplevel`,
|
|
115
|
+
* worktree-correct) — NOT {@link getMainRepoRoot}: for a `--use-worktree` shared
|
|
116
|
+
* worktree (or a caller standing inside a linked worktree), the teammate runs in
|
|
117
|
+
* THAT worktree, whose HEAD differs from the main checkout's, so folding to the
|
|
118
|
+
* main root would report the wrong tree's staleness. `origin/<default>` resolves
|
|
119
|
+
* from the shared object store regardless of which worktree we stand in. Returns
|
|
120
|
+
* null when `repoDir` isn't a git repo, origin is unreachable, or git errors — the
|
|
121
|
+
* caller treats null as "can't tell, don't block".
|
|
122
|
+
*/
|
|
123
|
+
export async function commitsBehindDefault(repoDir) {
|
|
124
|
+
const gitRoot = await getGitRoot(repoDir).catch(() => null);
|
|
125
|
+
if (!gitRoot)
|
|
126
|
+
return null;
|
|
127
|
+
try {
|
|
128
|
+
await execFileAsync('git', ['fetch', 'origin'], { cwd: gitRoot });
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return null; // offline / no origin — can't assess staleness, don't block a team.
|
|
132
|
+
}
|
|
133
|
+
const base = await localDefaultBranch(gitRoot);
|
|
134
|
+
try {
|
|
135
|
+
const { stdout } = await execFileAsync('git', ['rev-list', '--count', `HEAD..origin/${base}`], { cwd: gitRoot });
|
|
136
|
+
const behind = parseInt(stdout.trim(), 10);
|
|
137
|
+
if (!Number.isFinite(behind))
|
|
138
|
+
return null;
|
|
139
|
+
return { behind, base };
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return null; // no origin/<default> tracking ref, detached probe, etc.
|
|
143
|
+
}
|
|
144
|
+
}
|
|
103
145
|
/**
|
|
104
146
|
* Create a new git worktree for a teammate, branched off the freshly-fetched
|
|
105
147
|
* default branch. Fetches `origin` first and bases the branch on
|
|
@@ -23,8 +23,17 @@ export declare const EDITOR_VARIANTS: EditorVariant[];
|
|
|
23
23
|
* it, so a `command`/`cwd` containing `&` (or `=`) would be mis-split by a naive
|
|
24
24
|
* multi-param query. base64url is `[A-Za-z0-9_-]` only (no `&`, `=`, `%`, `+`,
|
|
25
25
|
* `/`), so it survives that decode untouched and round-trips exactly.
|
|
26
|
+
*
|
|
27
|
+
* Optional `meta.agent` / `meta.sessionId` / `meta.title` let the extension set
|
|
28
|
+
* the tab chip and status bar without sniffing the local process tree — required
|
|
29
|
+
* when `command` is a remote attach (`ssh … tmux attach`) with no agent binary
|
|
30
|
+
* on this box (#2478).
|
|
26
31
|
*/
|
|
27
|
-
export declare function spawnUri(scheme: string, cwd: string, command: string[], direction?: SplitDirection
|
|
32
|
+
export declare function spawnUri(scheme: string, cwd: string, command: string[], direction?: SplitDirection, meta?: {
|
|
33
|
+
agent?: string;
|
|
34
|
+
sessionId?: string;
|
|
35
|
+
title?: string;
|
|
36
|
+
}): string;
|
|
28
37
|
/** Build a backend bound to one editor variant. */
|
|
29
38
|
export declare function makeVscodiumAgentBackend(variant: EditorVariant): TerminalBackend;
|
|
30
39
|
/** Default backend: VSCodium (`codium` CLI, `vscodium://` scheme). */
|
|
@@ -41,14 +41,25 @@ function appExists(p) {
|
|
|
41
41
|
* it, so a `command`/`cwd` containing `&` (or `=`) would be mis-split by a naive
|
|
42
42
|
* multi-param query. base64url is `[A-Za-z0-9_-]` only (no `&`, `=`, `%`, `+`,
|
|
43
43
|
* `/`), so it survives that decode untouched and round-trips exactly.
|
|
44
|
+
*
|
|
45
|
+
* Optional `meta.agent` / `meta.sessionId` / `meta.title` let the extension set
|
|
46
|
+
* the tab chip and status bar without sniffing the local process tree — required
|
|
47
|
+
* when `command` is a remote attach (`ssh … tmux attach`) with no agent binary
|
|
48
|
+
* on this box (#2478).
|
|
44
49
|
*/
|
|
45
|
-
export function spawnUri(scheme, cwd, command, direction) {
|
|
50
|
+
export function spawnUri(scheme, cwd, command, direction, meta) {
|
|
46
51
|
const payload = {
|
|
47
52
|
command: command.join(' '),
|
|
48
53
|
cwd,
|
|
49
54
|
};
|
|
50
55
|
if (direction)
|
|
51
56
|
payload.split = direction;
|
|
57
|
+
if (meta?.agent)
|
|
58
|
+
payload.agent = meta.agent;
|
|
59
|
+
if (meta?.sessionId)
|
|
60
|
+
payload.sessionId = meta.sessionId;
|
|
61
|
+
if (meta?.title)
|
|
62
|
+
payload.title = meta.title;
|
|
52
63
|
const p = Buffer.from(JSON.stringify(payload), 'utf8').toString('base64url');
|
|
53
64
|
return `${scheme}://${EXTENSION_AUTHORITY}/spawn?p=${p}`;
|
|
54
65
|
}
|
|
@@ -60,11 +71,11 @@ export function makeVscodiumAgentBackend(variant) {
|
|
|
60
71
|
isAvailable(ctx) {
|
|
61
72
|
return ctx.platform === 'darwin' && appExists(variant.app);
|
|
62
73
|
},
|
|
63
|
-
buildTab(cwd, command) {
|
|
64
|
-
return { argv: [variant.cli, '--open-url', spawnUri(variant.scheme, cwd, command)] };
|
|
74
|
+
buildTab(cwd, command, meta) {
|
|
75
|
+
return { argv: [variant.cli, '--open-url', spawnUri(variant.scheme, cwd, command, undefined, meta)] };
|
|
65
76
|
},
|
|
66
|
-
buildSplit(cwd, command, direction) {
|
|
67
|
-
return { argv: [variant.cli, '--open-url', spawnUri(variant.scheme, cwd, command, direction)] };
|
|
77
|
+
buildSplit(cwd, command, direction, meta) {
|
|
78
|
+
return { argv: [variant.cli, '--open-url', spawnUri(variant.scheme, cwd, command, direction, meta)] };
|
|
68
79
|
},
|
|
69
80
|
};
|
|
70
81
|
}
|
|
@@ -21,6 +21,10 @@ export declare function openSurface(req: LaunchRequest, opts?: OpenOptions): Pro
|
|
|
21
21
|
export interface SurfaceItem {
|
|
22
22
|
cwd: string;
|
|
23
23
|
command: string[];
|
|
24
|
+
/** Optional harness identity for editor-backed backends (vscodium-agent). */
|
|
25
|
+
agent?: string;
|
|
26
|
+
sessionId?: string;
|
|
27
|
+
title?: string;
|
|
24
28
|
}
|
|
25
29
|
export interface BuildRequestsOptions {
|
|
26
30
|
backend: Backend;
|
|
@@ -8,9 +8,12 @@ export function specForRequest(req) {
|
|
|
8
8
|
const backend = BACKENDS[req.backend];
|
|
9
9
|
if (!backend)
|
|
10
10
|
throw new Error(`unknown backend: ${req.backend}`);
|
|
11
|
+
const meta = req.agent || req.sessionId || req.title
|
|
12
|
+
? { agent: req.agent, sessionId: req.sessionId, title: req.title }
|
|
13
|
+
: undefined;
|
|
11
14
|
if (req.layout === 'tab')
|
|
12
|
-
return backend.buildTab(req.cwd, req.command);
|
|
13
|
-
return backend.buildSplit(req.cwd, req.command, req.layout === 'split-down' ? 'down' : 'right');
|
|
15
|
+
return backend.buildTab(req.cwd, req.command, meta);
|
|
16
|
+
return backend.buildSplit(req.cwd, req.command, req.layout === 'split-down' ? 'down' : 'right', meta);
|
|
14
17
|
}
|
|
15
18
|
/** Open a single surface for one request. Never throws — failures come back in the result. */
|
|
16
19
|
export async function openSurface(req, opts = {}) {
|
|
@@ -35,6 +38,9 @@ export function buildRequests(items, opts) {
|
|
|
35
38
|
cwd: item.cwd,
|
|
36
39
|
command: item.command,
|
|
37
40
|
host: opts.host,
|
|
41
|
+
agent: item.agent,
|
|
42
|
+
sessionId: item.sessionId,
|
|
43
|
+
title: item.title,
|
|
38
44
|
}));
|
|
39
45
|
}
|
|
40
46
|
/**
|
|
@@ -25,6 +25,21 @@ export interface LaunchSpec {
|
|
|
25
25
|
/** argv to run (e.g. `['osascript','-e',script]` or `['tmux','split-window',…]`). */
|
|
26
26
|
argv: string[];
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Optional identity the caller already knows about the surface. The
|
|
30
|
+
* vscodium-agent backend forwards these into the swarm-ext `/spawn` URI so the
|
|
31
|
+
* extension can set the tab chip/name/session without sniffing the local
|
|
32
|
+
* process tree (required for remote `ssh … tmux attach` resumes — #2478).
|
|
33
|
+
* Other backends ignore them.
|
|
34
|
+
*/
|
|
35
|
+
export interface SurfaceMeta {
|
|
36
|
+
/** Harness id: claude, codex, grok, … */
|
|
37
|
+
agent?: string;
|
|
38
|
+
/** Canonical session id. */
|
|
39
|
+
sessionId?: string;
|
|
40
|
+
/** Optional pre-baked tab title. */
|
|
41
|
+
title?: string;
|
|
42
|
+
}
|
|
28
43
|
/** A single "open this command as this surface" instruction. */
|
|
29
44
|
export interface LaunchRequest {
|
|
30
45
|
backend: Backend;
|
|
@@ -35,6 +50,10 @@ export interface LaunchRequest {
|
|
|
35
50
|
command: string[];
|
|
36
51
|
/** undefined / 'local' = this machine; otherwise a resolvable host alias. */
|
|
37
52
|
host?: string;
|
|
53
|
+
/** Optional agent identity for editor-backed backends. */
|
|
54
|
+
agent?: string;
|
|
55
|
+
sessionId?: string;
|
|
56
|
+
title?: string;
|
|
38
57
|
}
|
|
39
58
|
/** Outcome of opening one surface. Never throws for launch failures — reports them. */
|
|
40
59
|
export interface LaunchResult {
|
|
@@ -53,7 +72,7 @@ export interface TerminalBackend {
|
|
|
53
72
|
/** Can this backend be driven here? (platform + app installed / inside tmux). */
|
|
54
73
|
isAvailable(ctx: EngineContext): boolean;
|
|
55
74
|
/** Command that opens a new tab running `command` in `cwd`. */
|
|
56
|
-
buildTab(cwd: string, command: string[]): LaunchSpec;
|
|
75
|
+
buildTab(cwd: string, command: string[], meta?: SurfaceMeta): LaunchSpec;
|
|
57
76
|
/** Command that splits the current surface, running `command` in `cwd`. */
|
|
58
|
-
buildSplit(cwd: string, command: string[], direction: SplitDirection): LaunchSpec;
|
|
77
|
+
buildSplit(cwd: string, command: string[], direction: SplitDirection, meta?: SurfaceMeta): LaunchSpec;
|
|
59
78
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import { setRefreshLockRootForTest, withRefreshLease } from '../refresh-coordinator.js';
|
|
3
|
+
const [lockRoot, resultPath, countPath, key] = process.argv.slice(2);
|
|
4
|
+
setRefreshLockRootForTest(lockRoot);
|
|
5
|
+
await withRefreshLease({
|
|
6
|
+
scope: 'cross-process-test',
|
|
7
|
+
key,
|
|
8
|
+
readCompleted: () => {
|
|
9
|
+
try {
|
|
10
|
+
return Number(fs.readFileSync(resultPath, 'utf-8'));
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
isCompleted: (value) => value === 1,
|
|
17
|
+
refresh: async () => {
|
|
18
|
+
fs.appendFileSync(countPath, 'refresh\n');
|
|
19
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
20
|
+
fs.writeFileSync(resultPath, '1');
|
|
21
|
+
return 1;
|
|
22
|
+
},
|
|
23
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export type TicketSource = 'linear' | 'github';
|
|
2
|
+
export interface TicketComment {
|
|
3
|
+
body: string;
|
|
4
|
+
createdAt?: string;
|
|
5
|
+
author?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface TicketRow {
|
|
8
|
+
id: string;
|
|
9
|
+
source: TicketSource;
|
|
10
|
+
title: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
status: 'todo' | 'in_progress' | 'done';
|
|
13
|
+
priority?: 'urgent' | 'high' | 'medium' | 'low';
|
|
14
|
+
metadata: {
|
|
15
|
+
identifier?: string;
|
|
16
|
+
url?: string;
|
|
17
|
+
labels?: string[];
|
|
18
|
+
assignee?: string;
|
|
19
|
+
assigneeKind?: 'user' | 'agent';
|
|
20
|
+
state?: string;
|
|
21
|
+
createdAt?: string;
|
|
22
|
+
dueDate?: string;
|
|
23
|
+
project?: string;
|
|
24
|
+
repo?: string;
|
|
25
|
+
comments?: TicketComment[];
|
|
26
|
+
images?: string[];
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export interface TicketListResult {
|
|
30
|
+
tickets: TicketRow[];
|
|
31
|
+
cycleInfo: {
|
|
32
|
+
name: string;
|
|
33
|
+
startsAt: string;
|
|
34
|
+
endsAt: string;
|
|
35
|
+
} | null;
|
|
36
|
+
sources: {
|
|
37
|
+
linear: {
|
|
38
|
+
available: boolean;
|
|
39
|
+
error?: string;
|
|
40
|
+
};
|
|
41
|
+
github: {
|
|
42
|
+
available: boolean;
|
|
43
|
+
error?: string;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export interface TicketListOptions {
|
|
48
|
+
cwd: string;
|
|
49
|
+
linear: boolean;
|
|
50
|
+
github: boolean;
|
|
51
|
+
githubAssignedOnly: boolean;
|
|
52
|
+
}
|
|
53
|
+
export declare function listTickets(options: TicketListOptions): Promise<TicketListResult>;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
const run = promisify(execFile);
|
|
4
|
+
const AGENT_ASSIGNEE = /^(claude|codex|gemini|cursor|opencode|antigravity|grok|kimi|droid)$/i;
|
|
5
|
+
function assigneeKind(name) {
|
|
6
|
+
if (!name)
|
|
7
|
+
return undefined;
|
|
8
|
+
return AGENT_ASSIGNEE.test(name.trim()) ? 'agent' : 'user';
|
|
9
|
+
}
|
|
10
|
+
function imageUrls(...bodies) {
|
|
11
|
+
const urls = new Set();
|
|
12
|
+
const pattern = /!\[[^\]]*\]\(\s*(https?:\/\/[^)\s]+)|<img\b[^>]*?\bsrc\s*=\s*["'](https?:\/\/[^"']+)/gi;
|
|
13
|
+
for (const body of bodies) {
|
|
14
|
+
if (typeof body !== 'string')
|
|
15
|
+
continue;
|
|
16
|
+
let match;
|
|
17
|
+
while ((match = pattern.exec(body)))
|
|
18
|
+
urls.add(match[1] || match[2]);
|
|
19
|
+
}
|
|
20
|
+
return urls.size > 0 ? [...urls] : undefined;
|
|
21
|
+
}
|
|
22
|
+
function errorMessage(error) {
|
|
23
|
+
if (error instanceof Error)
|
|
24
|
+
return error.message;
|
|
25
|
+
return String(error);
|
|
26
|
+
}
|
|
27
|
+
async function readLinear(cwd) {
|
|
28
|
+
const { stdout } = await run('linear', ['tasks', '--json'], {
|
|
29
|
+
cwd,
|
|
30
|
+
timeout: 15_000,
|
|
31
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
32
|
+
});
|
|
33
|
+
const data = JSON.parse(stdout);
|
|
34
|
+
const cycle = data?.cycle;
|
|
35
|
+
const cycleInfo = cycle?.startsAt && cycle?.endsAt
|
|
36
|
+
? { name: String(cycle.name ?? ''), startsAt: String(cycle.startsAt), endsAt: String(cycle.endsAt) }
|
|
37
|
+
: null;
|
|
38
|
+
const priority = {
|
|
39
|
+
1: 'urgent',
|
|
40
|
+
2: 'high',
|
|
41
|
+
3: 'medium',
|
|
42
|
+
4: 'low',
|
|
43
|
+
};
|
|
44
|
+
const tickets = (Array.isArray(data?.issues) ? data.issues : []).map((issue) => {
|
|
45
|
+
const labels = (issue.labels?.nodes ?? []).map((label) => String(label.name));
|
|
46
|
+
const comments = (issue.comments?.nodes ?? []).map((comment) => ({
|
|
47
|
+
body: String(comment.body ?? ''),
|
|
48
|
+
createdAt: comment.createdAt ? String(comment.createdAt) : undefined,
|
|
49
|
+
author: comment.user?.name ? String(comment.user.name) : undefined,
|
|
50
|
+
}));
|
|
51
|
+
const stateType = String(issue.state?.type ?? '');
|
|
52
|
+
const status = stateType === 'started'
|
|
53
|
+
? 'in_progress'
|
|
54
|
+
: stateType === 'completed' || stateType === 'canceled'
|
|
55
|
+
? 'done'
|
|
56
|
+
: 'todo';
|
|
57
|
+
const identifier = String(issue.identifier ?? issue.id ?? '');
|
|
58
|
+
return {
|
|
59
|
+
id: `linear:${identifier}`,
|
|
60
|
+
source: 'linear',
|
|
61
|
+
title: String(issue.title ?? ''),
|
|
62
|
+
description: issue.description ? String(issue.description) : undefined,
|
|
63
|
+
status,
|
|
64
|
+
priority: priority[Number(issue.priority)],
|
|
65
|
+
metadata: {
|
|
66
|
+
identifier,
|
|
67
|
+
url: issue.url ? String(issue.url) : undefined,
|
|
68
|
+
labels,
|
|
69
|
+
assignee: issue.assignee?.name ? String(issue.assignee.name) : undefined,
|
|
70
|
+
assigneeKind: assigneeKind(issue.assignee?.name),
|
|
71
|
+
state: issue.state?.name ? String(issue.state.name) : undefined,
|
|
72
|
+
createdAt: issue.createdAt ? String(issue.createdAt) : undefined,
|
|
73
|
+
dueDate: issue.dueDate ? String(issue.dueDate) : undefined,
|
|
74
|
+
project: issue.project?.name ? String(issue.project.name) : undefined,
|
|
75
|
+
comments,
|
|
76
|
+
images: imageUrls(issue.description, ...comments.map(comment => comment.body)),
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
return { tickets, cycleInfo };
|
|
81
|
+
}
|
|
82
|
+
async function readGithub(cwd, assignedOnly) {
|
|
83
|
+
const repo = (await run('gh', ['repo', 'view', '--json', 'nameWithOwner', '-q', '.nameWithOwner'], {
|
|
84
|
+
cwd,
|
|
85
|
+
timeout: 5_000,
|
|
86
|
+
})).stdout.trim();
|
|
87
|
+
if (!repo)
|
|
88
|
+
throw new Error('No GitHub repository resolved for this workspace.');
|
|
89
|
+
const args = [
|
|
90
|
+
'issue', 'list', '--repo', repo, '--state', 'open', '--limit', '50',
|
|
91
|
+
'--json', 'number,title,state,labels,assignees,url,body,createdAt',
|
|
92
|
+
];
|
|
93
|
+
if (assignedOnly)
|
|
94
|
+
args.push('--assignee', '@me');
|
|
95
|
+
const { stdout } = await run('gh', args, { cwd, timeout: 15_000, maxBuffer: 16 * 1024 * 1024 });
|
|
96
|
+
const issues = JSON.parse(stdout);
|
|
97
|
+
return issues.map((issue) => {
|
|
98
|
+
const assignee = issue.assignees?.[0]?.login ? String(issue.assignees[0].login) : undefined;
|
|
99
|
+
const number = Number(issue.number);
|
|
100
|
+
return {
|
|
101
|
+
id: `github:${number}`,
|
|
102
|
+
source: 'github',
|
|
103
|
+
title: String(issue.title ?? ''),
|
|
104
|
+
description: issue.body ? String(issue.body) : undefined,
|
|
105
|
+
status: String(issue.state ?? '').toLowerCase() === 'closed' ? 'done' : 'todo',
|
|
106
|
+
metadata: {
|
|
107
|
+
identifier: `#${number}`,
|
|
108
|
+
url: issue.url ? String(issue.url) : undefined,
|
|
109
|
+
labels: (issue.labels ?? []).map((label) => String(label.name)),
|
|
110
|
+
assignee,
|
|
111
|
+
assigneeKind: assigneeKind(assignee),
|
|
112
|
+
state: String(issue.state ?? '').toLowerCase(),
|
|
113
|
+
createdAt: issue.createdAt ? String(issue.createdAt) : undefined,
|
|
114
|
+
repo,
|
|
115
|
+
images: imageUrls(issue.body),
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
export async function listTickets(options) {
|
|
121
|
+
const result = {
|
|
122
|
+
tickets: [],
|
|
123
|
+
cycleInfo: null,
|
|
124
|
+
sources: {
|
|
125
|
+
linear: { available: false },
|
|
126
|
+
github: { available: false },
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
const [linear, github] = await Promise.all([
|
|
130
|
+
options.linear
|
|
131
|
+
? readLinear(options.cwd).then(value => ({ ok: true, value })).catch(error => ({ ok: false, error }))
|
|
132
|
+
: Promise.resolve(null),
|
|
133
|
+
options.github
|
|
134
|
+
? readGithub(options.cwd, options.githubAssignedOnly).then(value => ({ ok: true, value })).catch(error => ({ ok: false, error }))
|
|
135
|
+
: Promise.resolve(null),
|
|
136
|
+
]);
|
|
137
|
+
if (linear?.ok) {
|
|
138
|
+
result.sources.linear.available = true;
|
|
139
|
+
result.tickets.push(...linear.value.tickets);
|
|
140
|
+
result.cycleInfo = linear.value.cycleInfo;
|
|
141
|
+
}
|
|
142
|
+
else if (linear) {
|
|
143
|
+
result.sources.linear.error = errorMessage(linear.error);
|
|
144
|
+
}
|
|
145
|
+
if (github?.ok) {
|
|
146
|
+
result.sources.github.available = true;
|
|
147
|
+
result.tickets.push(...github.value);
|
|
148
|
+
}
|
|
149
|
+
else if (github) {
|
|
150
|
+
result.sources.github.error = errorMessage(github.error);
|
|
151
|
+
}
|
|
152
|
+
return result;
|
|
153
|
+
}
|