@phnx-labs/agents-cli 1.22.34 → 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 +672 -2
- package/README.md +82 -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 +85 -0
- package/dist/commands/share.js +379 -8
- 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/codex-policy.d.ts +9 -1
- package/dist/lib/codex-policy.js +17 -2
- 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 +220 -122
- 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-key.d.ts +17 -0
- package/dist/lib/project-key.js +26 -0
- 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/delete.d.ts +93 -0
- package/dist/lib/share/delete.js +127 -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 +136 -27
- 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 +14 -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
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// lifecycle, uploads the Worker (with an R2 binding), sets the WRITE_TOKEN secret,
|
|
4
4
|
// enables the free `*.workers.dev` subdomain, and — when the token owns the zone —
|
|
5
5
|
// maps a custom domain.
|
|
6
|
+
import { createHash } from 'node:crypto';
|
|
6
7
|
const CF_API = 'https://api.cloudflare.com/client/v4';
|
|
7
8
|
export const SHARE_LIFECYCLE_RULE_ID = 'agents-share-expire-objects';
|
|
8
9
|
export const SHARE_LIFECYCLE_RETENTION_DAYS = 366;
|
|
@@ -95,6 +96,55 @@ export async function deployWorker(apiToken, accountId, workerName, script, buck
|
|
|
95
96
|
form,
|
|
96
97
|
});
|
|
97
98
|
}
|
|
99
|
+
/** sha256 of the rendered Worker script, so a deployed endpoint can be compared
|
|
100
|
+
* against the current `worker-template.ts` without redeploying to find out. */
|
|
101
|
+
export function hashWorkerScript(script) {
|
|
102
|
+
return createHash('sha256').update(script, 'utf8').digest('hex');
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Re-deploy the Worker script against an ALREADY-provisioned endpoint (same
|
|
106
|
+
* account/worker/bucket `deployWorker` was first called with) and idempotently
|
|
107
|
+
* no-op when the template hasn't changed.
|
|
108
|
+
*
|
|
109
|
+
* Cloudflare's script-upload endpoint (`deployWorker`, above) replaces the
|
|
110
|
+
* Worker's bindings/secrets wholesale on every call — there is no documented,
|
|
111
|
+
* reliable way to tell it "keep the existing secret" (the `keep_bindings`
|
|
112
|
+
* metadata field some third-party guides mention is absent from Cloudflare's
|
|
113
|
+
* current Multipart upload metadata reference, and the community has reported
|
|
114
|
+
* it not preventing binding loss even when present:
|
|
115
|
+
* https://developers.cloudflare.com/workers/configuration/multipart-upload-metadata/,
|
|
116
|
+
* https://community.cloudflare.com/t/upload-worker-module-endpoint-removes-existing-bindings-despite-keep-bindings/766447).
|
|
117
|
+
* So instead this immediately re-applies WRITE_TOKEN via the documented Secrets
|
|
118
|
+
* API right after the upload — the same two-call sequence first-time
|
|
119
|
+
* provisioning already uses (`deployWorker` then `setWorkerSecret`), except
|
|
120
|
+
* `writeToken` here is the caller's EXISTING token, never a freshly generated
|
|
121
|
+
* one. Cloudflare's own docs describe exactly this "secrets survive a
|
|
122
|
+
* subsequent write" contract for the sibling `wrangler versions upload
|
|
123
|
+
* --secrets-file` flow ("Secrets not included in the file are preserved from
|
|
124
|
+
* the previous version" —
|
|
125
|
+
* https://developers.cloudflare.com/workers/configuration/secrets/#upload-secrets-alongside-code);
|
|
126
|
+
* re-setting the secret to its own value after every deploy gets the same
|
|
127
|
+
* outcome without depending on an unverified upload-time flag.
|
|
128
|
+
*/
|
|
129
|
+
export async function updateWorker(apiToken, accountId, workerName, bucketName, script, writeToken, previousHash, opts = {}) {
|
|
130
|
+
const templateHash = hashWorkerScript(script);
|
|
131
|
+
if (!opts.force && previousHash === templateHash) {
|
|
132
|
+
return { templateHash, skipped: true };
|
|
133
|
+
}
|
|
134
|
+
await deployWorker(apiToken, accountId, workerName, script, bucketName, opts);
|
|
135
|
+
// Script upload clears bindings/secrets (see JSDoc above). If re-applying
|
|
136
|
+
// WRITE_TOKEN fails here, the live Worker has no write token — every
|
|
137
|
+
// `agents share` publish/delete 401s until a re-run of `agents share update`
|
|
138
|
+
// completes both steps. Surface that explicitly instead of the raw CF error.
|
|
139
|
+
try {
|
|
140
|
+
await setWorkerSecret(apiToken, accountId, workerName, writeToken, opts);
|
|
141
|
+
}
|
|
142
|
+
catch (e) {
|
|
143
|
+
const detail = e instanceof Error ? e.message : String(e);
|
|
144
|
+
throw new Error(`Worker deployed but the write token failed to re-apply — re-run \`agents share update\` to fix this before publishing/deleting anything. (${detail})`);
|
|
145
|
+
}
|
|
146
|
+
return { templateHash, skipped: false };
|
|
147
|
+
}
|
|
98
148
|
/** Add/update the WRITE_TOKEN binding using Cloudflare's Workers Secrets API. */
|
|
99
149
|
export async function setWorkerSecret(apiToken, accountId, workerName, writeToken, opts = {}) {
|
|
100
150
|
const request = opts.request ?? defaultCloudflareRequester;
|
|
@@ -10,9 +10,25 @@ export interface PublishEndpoint {
|
|
|
10
10
|
}
|
|
11
11
|
export interface PublishOptions {
|
|
12
12
|
slug?: string;
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Auto-expire window. Relative (`30d`, `12h`), absolute (`2026-08-01`), or
|
|
15
|
+
* `never` / `none` / `permanent` for no expiry. When omitted, publishes default
|
|
16
|
+
* to {@link DEFAULT_SHARE_EXPIRE} so an accidental share decays instead of
|
|
17
|
+
* living forever (RUSH-2443).
|
|
18
|
+
*/
|
|
14
19
|
expire?: string;
|
|
15
20
|
contentType?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Hide this page from the public `/<user>` gallery and `agents share list`
|
|
23
|
+
* (metadata `visibility=unlisted`). The direct URL is still world-readable —
|
|
24
|
+
* unlisted, not secret (RUSH-2443). Alias of `--private` on the CLI.
|
|
25
|
+
*/
|
|
26
|
+
unlisted?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Bypass the pre-publish sensitive-content scan (emails / credential-shaped
|
|
29
|
+
* strings). Required when the page intentionally carries those patterns.
|
|
30
|
+
*/
|
|
31
|
+
force?: boolean;
|
|
16
32
|
/** Generate + attach an OG cover for HTML pages (default true). */
|
|
17
33
|
cover?: boolean;
|
|
18
34
|
/** Inject the Cloudflare Web Analytics beacon (default true for HTML). */
|
|
@@ -34,9 +50,32 @@ export interface PublishResult {
|
|
|
34
50
|
url: string;
|
|
35
51
|
expiresAt?: string;
|
|
36
52
|
coverUrl?: string;
|
|
53
|
+
/** True when the page was published with `visibility=unlisted`. */
|
|
54
|
+
unlisted?: boolean;
|
|
37
55
|
}
|
|
56
|
+
/** Default auto-expire for unflagged publishes — accidental links decay (RUSH-2443). */
|
|
57
|
+
export declare const DEFAULT_SHARE_EXPIRE = "30d";
|
|
38
58
|
/** `30d` / `12h` / `2026-08-01` → an absolute ISO timestamp (or undefined). */
|
|
39
59
|
export declare function parseExpire(spec: string | undefined): string | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* Resolve the publish expiry. Omitted → {@link DEFAULT_SHARE_EXPIRE}. Explicit
|
|
62
|
+
* `never` / `none` / `permanent` → no expiry. Anything else → {@link parseExpire}.
|
|
63
|
+
*/
|
|
64
|
+
export declare function resolveExpire(spec: string | undefined): string | undefined;
|
|
65
|
+
export type SensitiveHitKind = 'email' | 'credential';
|
|
66
|
+
export interface SensitiveHit {
|
|
67
|
+
kind: SensitiveHitKind;
|
|
68
|
+
/** Short redacted sample so the error names *what* was found without dumping it. */
|
|
69
|
+
sample: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Scan a text body for email addresses and credential-shaped strings. Returns
|
|
73
|
+
* the first few hits (deduped by kind+sample). Binary / non-text bodies yield
|
|
74
|
+
* nothing — the gate is for HTML/text reports, not screenshots.
|
|
75
|
+
*/
|
|
76
|
+
export declare function scanShareContent(body: string | Buffer): SensitiveHit[];
|
|
77
|
+
/** Build the refuse message when the pre-publish scan finds sensitive content. */
|
|
78
|
+
export declare function formatSensitiveContentError(hits: SensitiveHit[]): string;
|
|
40
79
|
/** Derive a URL-safe slug from a filename (or pass one through). */
|
|
41
80
|
export declare function slugify(name: string): string;
|
|
42
81
|
/** The project the file belongs to — git repo name, else the cwd's basename. */
|
|
@@ -14,6 +14,8 @@ import { resolveGitHubUsername } from '../git.js';
|
|
|
14
14
|
import { captureCover, OG_WIDTH, OG_HEIGHT, OG_SCALE } from './capture.js';
|
|
15
15
|
import { deriveMeta, injectOgMeta } from './og.js';
|
|
16
16
|
import { injectAnalyticsBeacon } from './analytics.js';
|
|
17
|
+
/** Default auto-expire for unflagged publishes — accidental links decay (RUSH-2443). */
|
|
18
|
+
export const DEFAULT_SHARE_EXPIRE = '30d';
|
|
17
19
|
const UNIT_MS = { s: 1e3, m: 6e4, h: 36e5, d: 864e5, w: 6048e5 };
|
|
18
20
|
/** `30d` / `12h` / `2026-08-01` → an absolute ISO timestamp (or undefined). */
|
|
19
21
|
export function parseExpire(spec) {
|
|
@@ -26,7 +28,99 @@ export function parseExpire(spec) {
|
|
|
26
28
|
const d = new Date(spec);
|
|
27
29
|
if (!Number.isNaN(d.getTime()))
|
|
28
30
|
return d.toISOString();
|
|
29
|
-
throw new Error(`Bad --expire '${spec}'. Use e.g. 30d, 12h,
|
|
31
|
+
throw new Error(`Bad --expire '${spec}'. Use e.g. 30d, 12h, an absolute date like 2026-08-01, or 'never' for no expiry.`);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Resolve the publish expiry. Omitted → {@link DEFAULT_SHARE_EXPIRE}. Explicit
|
|
35
|
+
* `never` / `none` / `permanent` → no expiry. Anything else → {@link parseExpire}.
|
|
36
|
+
*/
|
|
37
|
+
export function resolveExpire(spec) {
|
|
38
|
+
if (spec === undefined)
|
|
39
|
+
return parseExpire(DEFAULT_SHARE_EXPIRE);
|
|
40
|
+
const trimmed = spec.trim().toLowerCase();
|
|
41
|
+
if (trimmed === 'never' || trimmed === 'none' || trimmed === 'permanent')
|
|
42
|
+
return undefined;
|
|
43
|
+
return parseExpire(spec);
|
|
44
|
+
}
|
|
45
|
+
/** Email addresses — the RUSH-2428 incident page carried seven of these. */
|
|
46
|
+
const EMAIL_RE = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
|
|
47
|
+
/**
|
|
48
|
+
* Credential-shaped strings that an agent routinely dumps into reports: GitHub
|
|
49
|
+
* PATs, OpenAI/Anthropic/etc. API keys, AWS access keys, Slack tokens, and a
|
|
50
|
+
* generic long `sk-…` / `Bearer …` form. Keep the set tight — false positives
|
|
51
|
+
* force `--force` and train agents to bypass the gate.
|
|
52
|
+
*/
|
|
53
|
+
const CREDENTIAL_PATTERNS = [
|
|
54
|
+
{ re: /\bghp_[A-Za-z0-9_]{20,}\b/g, label: 'ghp_…' },
|
|
55
|
+
{ re: /\bgho_[A-Za-z0-9_]{20,}\b/g, label: 'gho_…' },
|
|
56
|
+
{ re: /\bghu_[A-Za-z0-9_]{20,}\b/g, label: 'ghu_…' },
|
|
57
|
+
{ re: /\bghs_[A-Za-z0-9_]{20,}\b/g, label: 'ghs_…' },
|
|
58
|
+
{ re: /\bghr_[A-Za-z0-9_]{20,}\b/g, label: 'ghr_…' },
|
|
59
|
+
{ re: /\bgithub_pat_[A-Za-z0-9_]{20,}\b/g, label: 'github_pat_…' },
|
|
60
|
+
{ re: /\bsk-(?:ant|proj|live|test)?[_-]?[A-Za-z0-9]{16,}\b/g, label: 'sk-…' },
|
|
61
|
+
{ re: /\bAKIA[0-9A-Z]{16}\b/g, label: 'AKIA…' },
|
|
62
|
+
{ re: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g, label: 'xox…' },
|
|
63
|
+
{ re: /\bBearer\s+[A-Za-z0-9._\-+/=]{20,}\b/gi, label: 'Bearer …' },
|
|
64
|
+
];
|
|
65
|
+
function redactSample(raw, max = 12) {
|
|
66
|
+
if (raw.length <= max)
|
|
67
|
+
return raw.slice(0, 4) + '…';
|
|
68
|
+
return raw.slice(0, Math.min(6, max)) + '…';
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Scan a text body for email addresses and credential-shaped strings. Returns
|
|
72
|
+
* the first few hits (deduped by kind+sample). Binary / non-text bodies yield
|
|
73
|
+
* nothing — the gate is for HTML/text reports, not screenshots.
|
|
74
|
+
*/
|
|
75
|
+
export function scanShareContent(body) {
|
|
76
|
+
// Skip clearly-binary content (null bytes in the first 1KB) so a PNG/MP4
|
|
77
|
+
// publish never false-positives on binary noise.
|
|
78
|
+
if (Buffer.isBuffer(body)) {
|
|
79
|
+
const head = body.subarray(0, Math.min(body.length, 1024));
|
|
80
|
+
if (head.includes(0))
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
const text = typeof body === 'string' ? body : body.toString('utf8');
|
|
84
|
+
const hits = [];
|
|
85
|
+
const seen = new Set();
|
|
86
|
+
for (const m of text.matchAll(EMAIL_RE)) {
|
|
87
|
+
const sample = redactSample(m[0]);
|
|
88
|
+
const key = `email:${sample}`;
|
|
89
|
+
if (seen.has(key))
|
|
90
|
+
continue;
|
|
91
|
+
seen.add(key);
|
|
92
|
+
hits.push({ kind: 'email', sample });
|
|
93
|
+
if (hits.length >= 5)
|
|
94
|
+
return hits;
|
|
95
|
+
}
|
|
96
|
+
for (const { re, label } of CREDENTIAL_PATTERNS) {
|
|
97
|
+
re.lastIndex = 0;
|
|
98
|
+
const m = re.exec(text);
|
|
99
|
+
if (!m)
|
|
100
|
+
continue;
|
|
101
|
+
const sample = label;
|
|
102
|
+
const key = `credential:${sample}`;
|
|
103
|
+
if (seen.has(key))
|
|
104
|
+
continue;
|
|
105
|
+
seen.add(key);
|
|
106
|
+
hits.push({ kind: 'credential', sample });
|
|
107
|
+
if (hits.length >= 5)
|
|
108
|
+
return hits;
|
|
109
|
+
}
|
|
110
|
+
return hits;
|
|
111
|
+
}
|
|
112
|
+
/** Build the refuse message when the pre-publish scan finds sensitive content. */
|
|
113
|
+
export function formatSensitiveContentError(hits) {
|
|
114
|
+
const kinds = Array.from(new Set(hits.map((h) => h.kind)));
|
|
115
|
+
const samples = hits.map((h) => h.sample).join(', ');
|
|
116
|
+
const what = kinds.length === 2
|
|
117
|
+
? 'email addresses and credential-shaped strings'
|
|
118
|
+
: kinds[0] === 'email'
|
|
119
|
+
? 'email addresses'
|
|
120
|
+
: 'credential-shaped strings';
|
|
121
|
+
return (`Refusing to publish: the file contains ${what} (${samples}). ` +
|
|
122
|
+
`Shares are world-readable by URL — pass --force to publish anyway, ` +
|
|
123
|
+
`or --unlisted --expire 12h to bound the blast radius.`);
|
|
30
124
|
}
|
|
31
125
|
/** Derive a URL-safe slug from a filename (or pass one through). */
|
|
32
126
|
export function slugify(name) {
|
|
@@ -176,7 +270,8 @@ export async function publishToEndpoint(filePath, endpoint, opts = {}) {
|
|
|
176
270
|
const username = await resolveShareUsername(opts);
|
|
177
271
|
const slugPart = (opts.slug ?? defaultSlug(filePath)).replace(/^\/+/, '');
|
|
178
272
|
const key = buildShareKey(username, slugPart);
|
|
179
|
-
const expiresAt =
|
|
273
|
+
const expiresAt = resolveExpire(opts.expire);
|
|
274
|
+
const unlisted = opts.unlisted === true;
|
|
180
275
|
const pageUrl = `${endpoint.baseUrl.replace(/\/+$/, '')}/${key}`;
|
|
181
276
|
const put = opts.uploader ??
|
|
182
277
|
(async (u, b, h) => {
|
|
@@ -187,16 +282,29 @@ export async function publishToEndpoint(filePath, endpoint, opts = {}) {
|
|
|
187
282
|
const h = { authorization: `Bearer ${endpoint.token}`, 'content-type': contentType };
|
|
188
283
|
if (expiresAt)
|
|
189
284
|
h['x-share-expires-at'] = expiresAt;
|
|
285
|
+
if (unlisted)
|
|
286
|
+
h['x-share-visibility'] = 'unlisted';
|
|
190
287
|
return h;
|
|
191
288
|
};
|
|
192
289
|
let body = readFileSync(filePath);
|
|
193
290
|
let coverUrl;
|
|
194
291
|
const isHtml = /\.html?$/i.test(filePath);
|
|
292
|
+
// Pre-publish scan (RUSH-2443): refuse emails / credential-shaped strings
|
|
293
|
+
// unless --force. Runs on the raw file before analytics/cover mutation so a
|
|
294
|
+
// beacon injection never triggers a false positive. Binary media is a no-op.
|
|
295
|
+
if (opts.force !== true) {
|
|
296
|
+
const hits = scanShareContent(body);
|
|
297
|
+
if (hits.length > 0) {
|
|
298
|
+
throw new Error(formatSensitiveContentError(hits));
|
|
299
|
+
}
|
|
300
|
+
}
|
|
195
301
|
// Analytics: cookieless CF Web Analytics beacon, injected for HTML by default.
|
|
196
302
|
if (isHtml && opts.analytics !== false && opts.analyticsToken) {
|
|
197
303
|
body = Buffer.from(injectAnalyticsBeacon(body.toString('utf8'), opts.analyticsToken), 'utf8');
|
|
198
304
|
}
|
|
199
305
|
// Cover: screenshot the page's hero → upload <slug>.png → inject og:image meta.
|
|
306
|
+
// Unlisted pages still get a cover (the direct URL is the capability), but the
|
|
307
|
+
// cover inherits visibility=unlisted so it is also omitted from the gallery.
|
|
200
308
|
if (isHtml && opts.cover !== false) {
|
|
201
309
|
const res = await attachOgCover(filePath, body, {
|
|
202
310
|
pngUrl: `${pageUrl}.png`,
|
|
@@ -212,5 +320,10 @@ export async function publishToEndpoint(filePath, endpoint, opts = {}) {
|
|
|
212
320
|
if (!r.ok) {
|
|
213
321
|
throw new Error(`Publish failed (${r.status}) for ${pageUrl}. Check the write token, or that 'agents share setup' completed.`);
|
|
214
322
|
}
|
|
215
|
-
return {
|
|
323
|
+
return {
|
|
324
|
+
url: r.url ?? pageUrl,
|
|
325
|
+
expiresAt,
|
|
326
|
+
coverUrl,
|
|
327
|
+
...(unlisted ? { unlisted: true } : {}),
|
|
328
|
+
};
|
|
216
329
|
}
|
|
@@ -7,7 +7,12 @@
|
|
|
7
7
|
// - GET /<username>/<slug> — public; streams the object from R2, 410s (and lazily
|
|
8
8
|
// deletes) once its expiry has passed. A bucket lifecycle rule is the durable
|
|
9
9
|
// sweeper; this is the immediate gate.
|
|
10
|
-
// - GET /<username> — public gallery of that user's shares.
|
|
10
|
+
// - GET /<username> — public gallery of that user's shares (HTML).
|
|
11
|
+
// - GET /<username>?format=json — public machine-readable listing of that user's
|
|
12
|
+
// ACTIVE shares (`agents share list`). Same single-segment path as the HTML
|
|
13
|
+
// gallery and gated on the SAME "does <username>/ hold any object" check, so it
|
|
14
|
+
// only intercepts a genuine namespace — a legacy flat slug with ?format=json
|
|
15
|
+
// still serves its real content, never a fake empty listing.
|
|
11
16
|
// - GET /<slug> — backward-compat flat slug (legacy shares before
|
|
12
17
|
// per-user namespaces).
|
|
13
18
|
//
|
|
@@ -35,22 +40,41 @@ export default {
|
|
|
35
40
|
return json({ error: 'unauthorized' }, 401);
|
|
36
41
|
}
|
|
37
42
|
const expiresAt = request.headers.get('x-share-expires-at') || '';
|
|
43
|
+
// 'unlisted' hides the page from the public gallery + JSON listing while
|
|
44
|
+
// keeping the direct URL world-readable (capability URL, not secret).
|
|
45
|
+
const visibility = (request.headers.get('x-share-visibility') || '').toLowerCase();
|
|
38
46
|
const contentType = request.headers.get('content-type') || 'text/html; charset=utf-8';
|
|
47
|
+
const customMetadata = {};
|
|
48
|
+
if (expiresAt) customMetadata['expires-at'] = expiresAt;
|
|
49
|
+
if (visibility === 'unlisted') customMetadata['visibility'] = 'unlisted';
|
|
39
50
|
await env.BUCKET.put(path, request.body, {
|
|
40
51
|
httpMetadata: { contentType },
|
|
41
|
-
customMetadata
|
|
52
|
+
customMetadata,
|
|
42
53
|
});
|
|
43
|
-
return json({ ok: true, url: url.origin + '/' + path, expiresAt: expiresAt || null }, 200);
|
|
54
|
+
return json({ ok: true, url: url.origin + '/' + path, expiresAt: expiresAt || null, unlisted: visibility === 'unlisted' }, 200);
|
|
44
55
|
}
|
|
45
56
|
|
|
46
57
|
if (request.method === 'GET' || request.method === 'HEAD') {
|
|
47
|
-
// Single-segment path may be a user gallery OR a legacy flat slug.
|
|
58
|
+
// Single-segment path may be a user gallery/listing OR a legacy flat slug.
|
|
59
|
+
// The disambiguator is whether the <seg>/ prefix holds any object: only a
|
|
60
|
+
// genuine per-user namespace does. BOTH the HTML gallery and the
|
|
61
|
+
// machine-readable listing gate on it, so ?format=json on a legacy flat
|
|
62
|
+
// slug (an object stored at the bare key, before per-user namespaces) does
|
|
63
|
+
// NOT hijack it into a fake empty listing — it falls through to the object
|
|
64
|
+
// GET below and serves its real content, exactly as before.
|
|
48
65
|
const segments = path.split('/').filter(Boolean);
|
|
49
66
|
if (segments.length === 1) {
|
|
50
67
|
const list = await env.BUCKET.list({ prefix: segments[0] + '/', limit: 1 });
|
|
51
|
-
|
|
52
|
-
|
|
68
|
+
const isNamespace = list.objects && list.objects.length > 0;
|
|
69
|
+
if (isNamespace) {
|
|
70
|
+
return url.searchParams.get('format') === 'json'
|
|
71
|
+
? renderListing(env.BUCKET, url.origin, segments[0], request.method)
|
|
72
|
+
: renderGallery(env.BUCKET, url.origin, segments[0], request.method);
|
|
53
73
|
}
|
|
74
|
+
// Not a namespace: fall through. A legacy flat-slug object resolves to its
|
|
75
|
+
// real content; anything else 404s (an empty/nonexistent namespace, which
|
|
76
|
+
// agents share list reads as "nothing published" via the template-hash
|
|
77
|
+
// signal rather than a missing route).
|
|
54
78
|
}
|
|
55
79
|
|
|
56
80
|
const obj = await env.BUCKET.get(path);
|
|
@@ -90,6 +114,8 @@ async function renderGallery(bucket, origin, user, method) {
|
|
|
90
114
|
|
|
91
115
|
const activeObjects = objects.filter(o => {
|
|
92
116
|
if (o.key.endsWith('.png')) return false;
|
|
117
|
+
// Unlisted pages are reachable by direct URL only — never on the gallery.
|
|
118
|
+
if (o.customMetadata && o.customMetadata.visibility === 'unlisted') return false;
|
|
93
119
|
const expiresAt = o.customMetadata && o.customMetadata['expires-at'];
|
|
94
120
|
return !(expiresAt && Date.now() > Date.parse(expiresAt));
|
|
95
121
|
});
|
|
@@ -124,6 +150,45 @@ async function renderGallery(bucket, origin, user, method) {
|
|
|
124
150
|
return new Response(html, { status: 200, headers: { 'content-type': 'text/html; charset=utf-8', 'cache-control': 'public, max-age=60' } });
|
|
125
151
|
}
|
|
126
152
|
|
|
153
|
+
async function renderListing(bucket, origin, user, method) {
|
|
154
|
+
const objects = [];
|
|
155
|
+
let cursor;
|
|
156
|
+
do {
|
|
157
|
+
const list = await bucket.list({ prefix: user + '/', limit: 1000, cursor, include: ['httpMetadata', 'customMetadata'] });
|
|
158
|
+
objects.push(...(list.objects || []));
|
|
159
|
+
cursor = list.truncated ? list.cursor : undefined;
|
|
160
|
+
} while (cursor);
|
|
161
|
+
|
|
162
|
+
const now = Date.now();
|
|
163
|
+
const items = objects
|
|
164
|
+
.filter(o => {
|
|
165
|
+
// Mirror the gallery: hide sibling .png OG covers, expired pages, and
|
|
166
|
+
// unlisted pages — the listing is the machine-readable public surface.
|
|
167
|
+
if (o.key.endsWith('.png')) return false;
|
|
168
|
+
if (o.customMetadata && o.customMetadata.visibility === 'unlisted') return false;
|
|
169
|
+
const expiresAt = o.customMetadata && o.customMetadata['expires-at'];
|
|
170
|
+
return !(expiresAt && now > Date.parse(expiresAt));
|
|
171
|
+
})
|
|
172
|
+
.map(o => ({
|
|
173
|
+
slug: o.key.slice(o.key.indexOf('/') + 1),
|
|
174
|
+
url: origin + '/' + o.key,
|
|
175
|
+
size: typeof o.size === 'number' ? o.size : 0,
|
|
176
|
+
contentType: (o.httpMetadata && o.httpMetadata.contentType) || null,
|
|
177
|
+
publishedAt: new Date(o.uploaded).toISOString(),
|
|
178
|
+
expiresAt: (o.customMetadata && o.customMetadata['expires-at']) || null,
|
|
179
|
+
}));
|
|
180
|
+
// Newest first, so the human table and any script reads the freshest share top.
|
|
181
|
+
items.sort((a, b) => (a.publishedAt < b.publishedAt ? 1 : a.publishedAt > b.publishedAt ? -1 : 0));
|
|
182
|
+
|
|
183
|
+
if (method === 'HEAD') {
|
|
184
|
+
return new Response(null, { status: 200, headers: { 'content-type': 'application/json; charset=utf-8' } });
|
|
185
|
+
}
|
|
186
|
+
return new Response(JSON.stringify({ user, count: items.length, objects: items }), {
|
|
187
|
+
status: 200,
|
|
188
|
+
headers: { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'public, max-age=30' },
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
127
192
|
function escapeHtml(s) {
|
|
128
193
|
return String(s)
|
|
129
194
|
.replace(/&/g, '&')
|
package/dist/lib/shims.d.ts
CHANGED
|
@@ -77,7 +77,7 @@ export interface ConflictInfo {
|
|
|
77
77
|
* top-level entry add/remove — deep edits to plugin contents won't
|
|
78
78
|
* trigger auto-resync, run `agents sync` for that.
|
|
79
79
|
*/
|
|
80
|
-
export declare const SHIM_SCHEMA_VERSION =
|
|
80
|
+
export declare const SHIM_SCHEMA_VERSION = 30;
|
|
81
81
|
/**
|
|
82
82
|
* Generate the full bash shim script for the given agent. The returned string
|
|
83
83
|
* is written to ~/.agents/shims/{cliCommand} and made executable.
|
|
@@ -159,8 +159,22 @@ export declare function removeShim(agent: AgentId): boolean;
|
|
|
159
159
|
* alias failed with "not installed" whenever the binary was staged into
|
|
160
160
|
* the versioned home (installer run with GROK_HOME set, or grok
|
|
161
161
|
* self-update under the shim).
|
|
162
|
-
|
|
163
|
-
|
|
162
|
+
* v16 — RUSH-2459: two compounding grok binary-resolution bugs fixed. (1) The
|
|
163
|
+
* "exact version match" grep ran against `ls`'s FULL PATH output, and
|
|
164
|
+
* the versioned home's own path always contains the version string
|
|
165
|
+
* (.../versions/grok/<version>/...), so it matched every candidate
|
|
166
|
+
* unconditionally and silently degraded to "whatever ls sorts first" —
|
|
167
|
+
* now matched against each candidate's basename instead. (2) When no
|
|
168
|
+
* filename genuinely carries the version, the fallback no longer
|
|
169
|
+
* trusts whatever sorts first: it rejects any grok-* candidate under
|
|
170
|
+
* 1MB (real grok binaries are ~100MB+; a stray wrapper/alias script is
|
|
171
|
+
* a few hundred bytes) and prefers the most recently modified
|
|
172
|
+
* survivor. On yosemite-s0 both bugs fired together: a stale, unrelated
|
|
173
|
+
* grok-0.2.118-* file — a 99-byte wrapper that exec'd cursor-agent —
|
|
174
|
+
* sorted alphabetically before the real self-updated grok binary and
|
|
175
|
+
* was silently launched instead.
|
|
176
|
+
*/
|
|
177
|
+
export declare const VERSIONED_ALIAS_SCHEMA_VERSION = 16;
|
|
164
178
|
/**
|
|
165
179
|
* Agents whose config directory can be relocated by an environment variable
|
|
166
180
|
* (the per-agent `managedEnv` block in `generateVersionedAliasScript` below).
|