@north-light/cli 0.3.561 → 0.3.563
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/dist/api/client.d.ts +27 -4
- package/dist/api/client.js +3 -3
- package/dist/api/contract.d.ts +1 -1
- package/dist/api/contract.js +1 -1
- package/dist/api/dto/bash-jobs.d.ts +5 -1
- package/dist/api/dto/broker-ops.d.ts +25 -1
- package/dist/api/dto/charges.d.ts +9 -2
- package/dist/api/dto/delivery.d.ts +26 -2
- package/dist/api/dto/execution-start.d.ts +57 -0
- package/dist/api/dto/execution-start.js +0 -0
- package/dist/api/dto/modelauth.d.ts +5 -0
- package/dist/api/dto/node-records.d.ts +16 -0
- package/dist/api/dto/objects.d.ts +1 -1
- package/dist/api/dto/reports.d.ts +0 -3
- package/dist/api/dto/run-events.d.ts +7 -1
- package/dist/api/dto/settings.d.ts +55 -0
- package/dist/api/dto/settings.js +0 -0
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.js +1 -1
- package/dist/api/routes.d.ts +11 -0
- package/dist/api/routes.js +1 -1
- package/dist/build-root.d.ts +1 -0
- package/dist/build-root.js +1 -1
- package/dist/builtin-memory/crouter-sdk/release-notes.md +4 -0
- package/dist/cli.js +7 -7
- package/dist/clients/attach/chrome/bash-jobs.d.ts +11 -1
- package/dist/clients/attach/chrome/bash-jobs.js +1 -1
- package/dist/clients/attach/chrome/canvas-panels.d.ts +1 -1
- package/dist/clients/attach/chrome/roster.js +6 -4
- package/dist/clients/attach/overlays/auth.js +2 -2
- package/dist/clients/attach/render/chat-view.js +1 -1
- package/dist/clients/attach/viewer.js +550 -567
- package/dist/commands/canvas-config.js +2 -2
- package/dist/commands/canvas-use.js +1 -1
- package/dist/commands/human.js +2 -2
- package/dist/commands/node/bash.js +3 -3
- package/dist/commands/node/create.js +2 -2
- package/dist/commands/person-settings.d.ts +1 -0
- package/dist/commands/person-settings.js +1 -0
- package/dist/commands/pkg/market-manage.d.ts +2 -2
- package/dist/commands/pkg/market-manage.js +1 -1
- package/dist/commands/pkg/plugin-manage.js +13 -13
- package/dist/commands/pkg/shared.js +1 -1
- package/dist/commands/profile/default.js +1 -1
- package/dist/commands/push.js +2 -3
- package/dist/commands/sys/config.js +1 -1
- package/dist/commands/sys/connect.js +1 -1
- package/dist/commands/sys/context/sysprompt.js +2 -2
- package/dist/commands/sys/doctor.js +1 -1
- package/dist/commands/sys/join.js +1 -1
- package/dist/commands/sys/panels/broker-limits-panel.js +1 -1
- package/dist/commands/sys/panels/keybindings-panel.js +1 -1
- package/dist/commands/sys/panels/models-panel.d.ts +8 -2
- package/dist/commands/sys/panels/models-panel.js +1 -1
- package/dist/commands/sys/panels/prefs-panel.d.ts +1 -0
- package/dist/commands/sys/panels/prefs-panel.js +1 -1
- package/dist/commands/sys/panels/profiles-panel.js +1 -1
- package/dist/commands/sys/panels/provider-panel.d.ts +4 -0
- package/dist/commands/sys/panels/provider-panel.js +1 -1
- package/dist/commands/sys/provider-login.js +5 -5
- package/dist/commands/sys/setup-core.js +3 -3
- package/dist/commands/sys/setup-settings-runner.js +1 -1
- package/dist/commands/sys/spend.js +3 -3
- package/dist/commands/sys/update.js +1 -1
- package/dist/core/auth-file.d.ts +11 -19
- package/dist/core/auth-file.js +1 -2
- package/dist/core/auto-update.d.ts +1 -1
- package/dist/core/auto-update.js +4 -4
- package/dist/core/bash-jobs.d.ts +29 -71
- package/dist/core/bash-jobs.js +9 -10
- package/dist/core/blobs/directory.d.ts +3 -0
- package/dist/core/blobs/directory.js +1 -0
- package/dist/core/blobs/fault.d.ts +3 -0
- package/dist/core/blobs/fault.js +1 -0
- package/dist/core/blobs/index.d.ts +21 -0
- package/dist/core/blobs/index.js +1 -0
- package/dist/core/blobs/r2.d.ts +9 -0
- package/dist/core/blobs/r2.js +4 -0
- package/dist/core/bootstrap.d.ts +1 -1
- package/dist/core/bootstrap.js +2 -2
- package/dist/core/canvas/canvas.d.ts +9 -7
- package/dist/core/canvas/canvas.js +8 -8
- package/dist/core/canvas/crons.d.ts +3 -2
- package/dist/core/canvas/crons.js +3 -3
- package/dist/core/canvas/daemon-owner.d.ts +5 -0
- package/dist/core/canvas/daemon-owner.js +1 -1
- package/dist/core/canvas/db.d.ts +10 -9
- package/dist/core/canvas/db.js +4 -4
- package/dist/core/canvas/executions.d.ts +100 -4
- package/dist/core/canvas/executions.js +1 -1
- package/dist/core/canvas/export-sqlite.js +1 -1
- package/dist/core/canvas/focuses.d.ts +4 -0
- package/dist/core/canvas/focuses.js +1 -1
- package/dist/core/canvas/history.js +9 -9
- package/dist/core/canvas/managed-worktree-sweep-candidates.d.ts +2 -1
- package/dist/core/canvas/managed-worktree-sweep-candidates.js +3 -2
- package/dist/core/canvas/node-tokens.d.ts +1 -4
- package/dist/core/canvas/node-tokens.js +3 -3
- package/dist/core/canvas/paths.d.ts +0 -1
- package/dist/core/canvas/paths.js +1 -1
- package/dist/core/canvas/person-state.d.ts +26 -0
- package/dist/core/canvas/person-state.js +1 -0
- package/dist/core/canvas/person.d.ts +3 -10
- package/dist/core/canvas/person.js +7 -7
- package/dist/core/canvas/reconciler-leases.d.ts +12 -0
- package/dist/core/canvas/reconciler-leases.js +8 -0
- package/dist/core/canvas/recovery.d.ts +4 -0
- package/dist/core/canvas/recovery.js +1 -1
- package/dist/core/canvas/schema-pg/003-fleet-removals.sql +1 -1
- package/dist/core/canvas/schema-pg/005-fleet-blobs.sql +13 -0
- package/dist/core/canvas/schema-pg/006-job-rows.sql +20 -0
- package/dist/core/canvas/schema-pg/007-ledger-check.sql +117 -0
- package/dist/core/canvas/schema-version.d.ts +1 -1
- package/dist/core/canvas/schema-version.js +1 -1
- package/dist/core/canvas/sessions.d.ts +8 -11
- package/dist/core/canvas/sessions.js +1 -4
- package/dist/core/canvas/tree.d.ts +4 -2
- package/dist/core/canvas/tree.js +6 -6
- package/dist/core/canvas/types.d.ts +7 -0
- package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -1
- package/dist/core/command-plugins/bundle.d.ts +1 -1
- package/dist/core/command-plugins/bundle.js +1 -1
- package/dist/core/command-plugins/compose.d.ts +1 -1
- package/dist/core/command-plugins/discovery.d.ts +0 -1
- package/dist/core/command-plugins/discovery.js +1 -1
- package/dist/core/command-plugins/help-addenda.js +1 -1
- package/dist/core/command-plugins/presence.d.ts +2 -0
- package/dist/core/command-plugins/presence.js +1 -1
- package/dist/core/config.d.ts +16 -15
- package/dist/core/config.js +1 -1
- package/dist/core/conversation-store/client-worker.js +1 -1
- package/dist/core/conversation-store/client.js +2 -2
- package/dist/core/conversation-store/index.d.ts +9 -11
- package/dist/core/conversation-store/index.js +1 -1
- package/dist/core/conversation-store/patch.js +1 -1
- package/dist/core/conversation-store/row-store.d.ts +14 -0
- package/dist/core/conversation-store/row-store.js +13 -0
- package/dist/core/directory/join.d.ts +5 -3
- package/dist/core/directory/join.js +1 -1
- package/dist/core/env-name.d.ts +1 -0
- package/dist/core/env-name.js +1 -1
- package/dist/core/environment-recipe.d.ts +15 -0
- package/dist/core/environment-recipe.js +1 -0
- package/dist/core/environments.js +1 -1
- package/dist/core/events/emit.js +2 -2
- package/dist/core/events/run-event-chunks.d.ts +25 -0
- package/dist/core/events/run-event-chunks.js +5 -0
- package/dist/core/feed/messages.js +5 -5
- package/dist/core/grants/mirror.d.ts +15 -0
- package/dist/core/grants/mirror.js +15 -3
- package/dist/core/grants/on-sync.d.ts +9 -5
- package/dist/core/grants/on-sync.js +1 -1
- package/dist/core/grants/remove.d.ts +1 -6
- package/dist/core/grants/remove.js +1 -1
- package/dist/core/grants/sync.js +1 -1
- package/dist/core/grants/watch.d.ts +15 -9
- package/dist/core/grants/watch.js +1 -1
- package/dist/core/graph/custom.js +8 -8
- package/dist/core/graph/jobs.d.ts +83 -5
- package/dist/core/graph/jobs.js +11 -2
- package/dist/core/graph/kinds/job.js +2 -2
- package/dist/core/graph/names.js +7 -7
- package/dist/core/graph/objects.d.ts +5 -1
- package/dist/core/graph/objects.js +11 -11
- package/dist/core/graph/reader.d.ts +3 -0
- package/dist/core/graph/reader.js +3 -3
- package/dist/core/graph/repo-sync/identity.d.ts +3 -1
- package/dist/core/graph/repo-sync/identity.js +1 -1
- package/dist/core/graph/repo-sync/repos.d.ts +1 -1
- package/dist/core/graph/repo-sync/repos.js +2 -2
- package/dist/core/graph/repo-sync/sync.js +2 -2
- package/dist/core/installed-plugins.js +1 -1
- package/dist/core/keybindings/persistence.d.ts +1 -1
- package/dist/core/keybindings/persistence.js +1 -1
- package/dist/core/layout-migrate/loose-keys.d.ts +1 -1
- package/dist/core/layout-migrate/loose-keys.js +1 -1
- package/dist/core/ledger/account.d.ts +12 -0
- package/dist/core/ledger/account.js +2 -0
- package/dist/core/ledger/charges.d.ts +2 -2
- package/dist/core/ledger/charges.js +1 -1
- package/dist/core/ledger/check.d.ts +5 -1
- package/dist/core/ledger/check.js +1 -7
- package/dist/core/ledger/chunks.d.ts +8 -0
- package/dist/core/ledger/chunks.js +2 -0
- package/dist/core/ledger/index.d.ts +2 -1
- package/dist/core/ledger/index.js +1 -1
- package/dist/core/ledger/infra-allowance.d.ts +9 -0
- package/dist/core/ledger/infra-allowance.js +1 -0
- package/dist/core/ledger/limits.js +3 -3
- package/dist/core/ledger/payer.d.ts +1 -1
- package/dist/core/ledger/payer.js +1 -1
- package/dist/core/ledger/read.d.ts +14 -4
- package/dist/core/ledger/read.js +2 -3
- package/dist/core/ledger/totals.d.ts +5 -16
- package/dist/core/ledger/totals.js +4 -4
- package/dist/core/ledger/types.d.ts +12 -3
- package/dist/core/llm/run.js +2 -2
- package/dist/core/managed-providers.d.ts +72 -0
- package/dist/core/managed-providers.js +1 -0
- package/dist/core/model-auth/api-credential-store.d.ts +10 -0
- package/dist/core/model-auth/api-credential-store.js +1 -0
- package/dist/core/model-auth/daemon-login.d.ts +1 -1
- package/dist/core/model-auth/daemon-login.js +1 -1
- package/dist/core/model-auth/flows.d.ts +5 -4
- package/dist/core/model-auth/flows.js +1 -1
- package/dist/core/model-auth/handoff-jti.d.ts +3 -4
- package/dist/core/model-auth/handoff-jti.js +1 -1
- package/dist/core/model-auth/readiness.js +1 -1
- package/dist/core/model-config.d.ts +1 -1
- package/dist/core/model-config.js +1 -1
- package/dist/core/model-routes-pool.d.ts +14 -0
- package/dist/core/model-routes-pool.js +1 -0
- package/dist/core/model-routes.d.ts +11 -16
- package/dist/core/model-routes.js +1 -1
- package/dist/core/peer/ingest.d.ts +2 -0
- package/dist/core/peer/ingest.js +1 -1
- package/dist/core/peer/stubs.d.ts +8 -0
- package/dist/core/peer/stubs.js +1 -1
- package/dist/core/permissions/evaluator.d.ts +7 -2
- package/dist/core/permissions/evaluator.js +2 -2
- package/dist/core/plugin-env.js +1 -1
- package/dist/core/pool-credential-store.d.ts +2 -5
- package/dist/core/pool-credential-store.js +1 -1
- package/dist/core/profiles/app-env-store.d.ts +5 -5
- package/dist/core/profiles/app-env-store.js +1 -2
- package/dist/core/profiles/default-binding.d.ts +5 -5
- package/dist/core/profiles/default-binding.js +1 -1
- package/dist/core/profiles/env-store.d.ts +10 -21
- package/dist/core/profiles/env-store.js +1 -2
- package/dist/core/profiles/manifest.d.ts +14 -18
- package/dist/core/profiles/manifest.js +1 -1
- package/dist/core/profiles/relocate.js +1 -1
- package/dist/core/profiles/select.js +21 -21
- package/dist/core/provider-credential.d.ts +1 -1
- package/dist/core/provider-credential.js +1 -1
- package/dist/core/provider-management.d.ts +3 -4
- package/dist/core/provider-management.js +1 -1
- package/dist/core/providers/bundles.js +2 -2
- package/dist/core/providers/call.d.ts +3 -34
- package/dist/core/providers/description.d.ts +34 -0
- package/dist/core/providers/description.js +0 -0
- package/dist/core/providers/token-cache.d.ts +14 -14
- package/dist/core/providers/token-cache.js +1 -1
- package/dist/core/review/companion.js +1 -1
- package/dist/core/runs/activity.d.ts +1 -1
- package/dist/core/runs/activity.js +1 -1
- package/dist/core/runs/events.d.ts +7 -5
- package/dist/core/runs/events.js +2 -6
- package/dist/core/runs/operations.d.ts +1 -1
- package/dist/core/runs/operations.js +6 -6
- package/dist/core/runtime/bearings.js +1 -1
- package/dist/core/runtime/broker/attachments-fetch.d.ts +5 -0
- package/dist/core/runtime/broker/attachments-fetch.js +1 -0
- package/dist/core/runtime/broker/bash-job-launch.d.ts +4 -2
- package/dist/core/runtime/broker/bash-job-launch.js +1 -1
- package/dist/core/runtime/broker/boot-state.d.ts +9 -0
- package/dist/core/runtime/broker/boot-state.js +1 -0
- package/dist/core/runtime/broker/cli-relay.d.ts +2 -1
- package/dist/core/runtime/broker/cli-relay.js +1 -1
- package/dist/core/runtime/broker/client-registry.d.ts +3 -3
- package/dist/core/runtime/broker/daemon-ops.d.ts +10 -1
- package/dist/core/runtime/broker/daemon-ops.js +1 -1
- package/dist/core/runtime/broker/fault-retry.d.ts +2 -0
- package/dist/core/runtime/broker/fault-retry.js +1 -1
- package/dist/core/runtime/broker/frame-engine-control.js +1 -1
- package/dist/core/runtime/broker/held-deferred-inbox.d.ts +3 -0
- package/dist/core/runtime/broker/held-deferred-inbox.js +1 -1
- package/dist/core/runtime/broker/job-reporter.d.ts +18 -0
- package/dist/core/runtime/broker/job-reporter.js +2 -0
- package/dist/core/runtime/broker/model-adapter.d.ts +3 -0
- package/dist/core/runtime/broker/model-adapter.js +3 -2
- package/dist/core/runtime/broker/signal-stream.js +1 -1
- package/dist/core/runtime/broker/spilled-body.d.ts +5 -0
- package/dist/core/runtime/broker/spilled-body.js +1 -0
- package/dist/core/runtime/broker/summaries-post.d.ts +5 -0
- package/dist/core/runtime/broker/summaries-post.js +1 -0
- package/dist/core/runtime/broker/tool-groups.d.ts +3 -0
- package/dist/core/runtime/broker/tool-groups.js +1 -1
- package/dist/core/runtime/broker/turn-replies.d.ts +1 -0
- package/dist/core/runtime/broker/turn-replies.js +1 -1
- package/dist/core/runtime/broker-persona-guidance.js +2 -2
- package/dist/core/runtime/broker.js +1 -1
- package/dist/core/runtime/deliver-live.js +1 -1
- package/dist/core/runtime/first-boot-rows.d.ts +8 -0
- package/dist/core/runtime/first-boot-rows.js +2 -0
- package/dist/core/runtime/fleet.d.ts +13 -12
- package/dist/core/runtime/front-door-login.js +1 -1
- package/dist/core/runtime/front-door.js +6 -6
- package/dist/core/runtime/headless-pi.js +1 -1
- package/dist/core/runtime/host.d.ts +14 -3
- package/dist/core/runtime/host.js +3 -3
- package/dist/core/runtime/invocation.d.ts +6 -0
- package/dist/core/runtime/kickoff.d.ts +2 -14
- package/dist/core/runtime/kickoff.js +17 -19
- package/dist/core/runtime/launch-config-worker.js +1 -1
- package/dist/core/runtime/launch.js +2 -2
- package/dist/core/runtime/model-registry.js +1 -1
- package/dist/core/runtime/node-read.d.ts +4 -6
- package/dist/core/runtime/node-read.js +3 -3
- package/dist/core/runtime/nodes.js +1 -1
- package/dist/core/runtime/outcome-document.d.ts +0 -1
- package/dist/core/runtime/outcome-document.js +1 -1
- package/dist/core/runtime/output-result.d.ts +15 -0
- package/dist/core/runtime/output-result.js +5 -0
- package/dist/core/runtime/placement.d.ts +17 -1
- package/dist/core/runtime/placement.js +1 -1
- package/dist/core/runtime/provider-credential-gate.d.ts +6 -2
- package/dist/core/runtime/provider-credential-gate.js +2 -2
- package/dist/core/runtime/recovery-hold.d.ts +21 -2
- package/dist/core/runtime/recovery-hold.js +2 -1
- package/dist/core/runtime/recycle.js +1 -1
- package/dist/core/runtime/reset.js +1 -1
- package/dist/core/runtime/revive.d.ts +2 -2
- package/dist/core/runtime/revive.js +2 -2
- package/dist/core/runtime/runner/blaxel/client.d.ts +81 -0
- package/dist/core/runtime/runner/blaxel/client.js +1 -0
- package/dist/core/runtime/runner/blaxel/image-build.d.ts +74 -0
- package/dist/core/runtime/runner/blaxel/image-build.js +5 -0
- package/dist/core/runtime/runner/blaxel/runner.d.ts +41 -0
- package/dist/core/runtime/runner/blaxel/runner.js +3 -0
- package/dist/core/runtime/runner/index.d.ts +8 -0
- package/dist/core/runtime/runner/index.js +1 -0
- package/dist/core/runtime/runner/process.d.ts +11 -0
- package/dist/core/runtime/runner/process.js +1 -0
- package/dist/core/runtime/runner/types.d.ts +95 -0
- package/dist/core/runtime/runner/types.js +0 -0
- package/dist/core/runtime/situational-context.d.ts +3 -6
- package/dist/core/runtime/situational-context.js +2 -2
- package/dist/core/runtime/situational-live.js +1 -1
- package/dist/core/runtime/spawn-env-rows.d.ts +5 -0
- package/dist/core/runtime/spawn-env-rows.js +1 -0
- package/dist/core/runtime/spawn-env.d.ts +4 -18
- package/dist/core/runtime/spawn-env.js +1 -1
- package/dist/core/runtime/spawn.js +2 -2
- package/dist/core/runtime/stop-guard.d.ts +1 -1
- package/dist/core/runtime/stop-guard.js +2 -8
- package/dist/core/runtime/structured-output.d.ts +0 -67
- package/dist/core/runtime/structured-output.js +3 -8
- package/dist/core/runtime/tmux-driver.d.ts +8 -0
- package/dist/core/runtime/tmux-driver.js +6 -6
- package/dist/core/runtime/view-socket.d.ts +20 -0
- package/dist/core/runtime/view-socket.js +3 -1
- package/dist/core/runtime/warm-pool.d.ts +13 -1
- package/dist/core/runtime/warm-pool.js +1 -1
- package/dist/core/scoped-state/legacy-profiles.d.ts +11 -0
- package/dist/core/scoped-state/legacy-profiles.js +1 -0
- package/dist/core/scoped-state/materialized-plugins.d.ts +18 -0
- package/dist/core/scoped-state/materialized-plugins.js +1 -0
- package/dist/core/scoped-state/migrate.d.ts +8 -1
- package/dist/core/scoped-state/migrate.js +3 -3
- package/dist/core/scoped-state/person-rows.d.ts +10 -0
- package/dist/core/scoped-state/person-rows.js +6 -0
- package/dist/core/scoped-state/person-store.d.ts +72 -0
- package/dist/core/scoped-state/person-store.js +1 -0
- package/dist/core/secrets/blaxel-launch.d.ts +24 -0
- package/dist/core/secrets/blaxel-launch.js +4 -0
- package/dist/core/secrets/blaxel-register.d.ts +2 -0
- package/dist/core/secrets/blaxel-register.js +1 -0
- package/dist/core/secrets/env-rows.d.ts +17 -0
- package/dist/core/secrets/env-rows.js +4 -0
- package/dist/core/secrets/environment-owner.d.ts +8 -0
- package/dist/core/secrets/environment-owner.js +1 -0
- package/dist/core/secrets/environment-secrets.d.ts +14 -0
- package/dist/core/secrets/environment-secrets.js +1 -0
- package/dist/core/secrets/index.d.ts +2 -0
- package/dist/core/secrets/index.js +1 -0
- package/dist/core/secrets/key.d.ts +3 -0
- package/dist/core/secrets/key.js +2 -0
- package/dist/core/secrets/seal.d.ts +18 -0
- package/dist/core/secrets/seal.js +1 -0
- package/dist/core/spaces/mounts.d.ts +1 -1
- package/dist/core/spaces/mounts.js +1 -1
- package/dist/core/spaces/process.d.ts +1 -1
- package/dist/core/spaces/stop.d.ts +7 -5
- package/dist/core/spaces/stop.js +2 -2
- package/dist/core/spaces/users.d.ts +2 -1
- package/dist/core/spaces/users.js +1 -1
- package/dist/core/storage/attachments.d.ts +11 -8
- package/dist/core/storage/attachments.js +1 -1
- package/dist/core/storage/tables.d.ts +4 -0
- package/dist/core/storage/tables.js +3 -3
- package/dist/core/subscription-state.d.ts +34 -72
- package/dist/core/subscription-state.js +1 -4
- package/dist/core/substrate/delivery/plan.js +1 -1
- package/dist/core/user-settings.js +1 -1
- package/dist/daemon/api/app-listener.js +10 -10
- package/dist/daemon/api/auth/person-bearer.d.ts +14 -0
- package/dist/daemon/api/auth/person-bearer.js +1 -0
- package/dist/daemon/api/bridge.js +4 -4
- package/dist/daemon/api/document-listener.js +3 -3
- package/dist/daemon/api/environment-of.d.ts +18 -0
- package/dist/daemon/api/environment-of.js +5 -0
- package/dist/daemon/api/handlers/analytics.js +1 -1
- package/dist/daemon/api/handlers/app-profiles.d.ts +2 -2
- package/dist/daemon/api/handlers/app-profiles.js +1 -1
- package/dist/daemon/api/handlers/bash-jobs.js +1 -1
- package/dist/daemon/api/handlers/bash.js +1 -1
- package/dist/daemon/api/handlers/broker-ops.d.ts +3 -0
- package/dist/daemon/api/handlers/broker-ops.js +1 -1
- package/dist/daemon/api/handlers/broker-recovery.js +1 -1
- package/dist/daemon/api/handlers/broker-signals.d.ts +0 -3
- package/dist/daemon/api/handlers/broker-signals.js +2 -2
- package/dist/daemon/api/handlers/canvas.js +4 -4
- package/dist/daemon/api/handlers/charges.d.ts +1 -1
- package/dist/daemon/api/handlers/charges.js +1 -1
- package/dist/daemon/api/handlers/conversations.d.ts +2 -0
- package/dist/daemon/api/handlers/conversations.js +3 -0
- package/dist/daemon/api/handlers/crons.js +1 -1
- package/dist/daemon/api/handlers/daemon.js +1 -1
- package/dist/daemon/api/handlers/delivery.d.ts +1 -1
- package/dist/daemon/api/handlers/delivery.js +1 -1
- package/dist/daemon/api/handlers/docs.js +1 -1
- package/dist/daemon/api/handlers/exec.js +1 -1
- package/dist/daemon/api/handlers/execution-start.d.ts +2 -0
- package/dist/daemon/api/handlers/execution-start.js +2 -0
- package/dist/daemon/api/handlers/files.js +1 -1
- package/dist/daemon/api/handlers/git-credential.d.ts +11 -0
- package/dist/daemon/api/handlers/git-credential.js +1 -0
- package/dist/daemon/api/handlers/hook-exec.d.ts +1 -1
- package/dist/daemon/api/handlers/hook-exec.js +1 -1
- package/dist/daemon/api/handlers/human-requests.js +1 -1
- package/dist/daemon/api/handlers/inbox.js +1 -1
- package/dist/daemon/api/handlers/messages.js +1 -1
- package/dist/daemon/api/handlers/model-config.js +1 -1
- package/dist/daemon/api/handlers/modelauth.d.ts +1 -1
- package/dist/daemon/api/handlers/modelauth.js +1 -1
- package/dist/daemon/api/handlers/node-events.d.ts +6 -0
- package/dist/daemon/api/handlers/node-events.js +3 -3
- package/dist/daemon/api/handlers/node-outcomes.js +1 -1
- package/dist/daemon/api/handlers/node-records.js +3 -2
- package/dist/daemon/api/handlers/nodes.js +1 -1
- package/dist/daemon/api/handlers/objects.js +3 -3
- package/dist/daemon/api/handlers/profiles.js +1 -1
- package/dist/daemon/api/handlers/providers.js +1 -1
- package/dist/daemon/api/handlers/reports.js +9 -13
- package/dist/daemon/api/handlers/reviews.js +1 -1
- package/dist/daemon/api/handlers/runs.js +1 -1
- package/dist/daemon/api/handlers/settings.d.ts +2 -0
- package/dist/daemon/api/handlers/settings.js +1 -0
- package/dist/daemon/api/handlers/structured-requests.js +1 -1
- package/dist/daemon/api/handlers/vendor-status.d.ts +1 -1
- package/dist/daemon/api/handlers/vendor-status.js +1 -1
- package/dist/daemon/api/handlers/worktree.js +1 -1
- package/dist/daemon/api/map.d.ts +2 -2
- package/dist/daemon/api/map.js +2 -2
- package/dist/daemon/api/operations.js +1 -1
- package/dist/daemon/api/reader.d.ts +8 -1
- package/dist/daemon/api/reader.js +1 -1
- package/dist/daemon/api/router.d.ts +4 -2
- package/dist/daemon/api/router.js +1 -1
- package/dist/daemon/api/server.d.ts +15 -3
- package/dist/daemon/api/server.js +1 -1
- package/dist/daemon/api/vendor-signin.d.ts +2 -1
- package/dist/daemon/api/vendor-signin.js +19 -19
- package/dist/daemon/api/viewer-presence.d.ts +20 -6
- package/dist/daemon/api/viewer-presence.js +2 -1
- package/dist/daemon/boot-settings.d.ts +3 -0
- package/dist/daemon/boot-settings.js +1 -0
- package/dist/daemon/broker-signals/bus.d.ts +48 -11
- package/dist/daemon/broker-signals/bus.js +1 -1
- package/dist/daemon/cron/armed-context.js +1 -1
- package/dist/daemon/cron/lease-recovery.js +1 -1
- package/dist/daemon/cron/live-runs.d.ts +6 -0
- package/dist/daemon/cron/live-runs.js +1 -1
- package/dist/daemon/cron/run-socket.js +1 -1
- package/dist/daemon/cron-run.js +2 -2
- package/dist/daemon/crtrd-cli.js +1 -1
- package/dist/daemon/crtrd.d.ts +10 -0
- package/dist/daemon/crtrd.js +18 -17
- package/dist/daemon/delivery/run-delivery.d.ts +1 -1
- package/dist/daemon/delivery/run-delivery.js +1 -1
- package/dist/daemon/due-sources.d.ts +1 -1
- package/dist/daemon/due-sources.js +1 -1
- package/dist/daemon/due.js +7 -6
- package/dist/daemon/fleet.d.ts +6 -6
- package/dist/daemon/fleet.js +9 -9
- package/dist/daemon/park-activity.d.ts +2 -1
- package/dist/daemon/park-activity.js +1 -1
- package/dist/daemon/park-pending.d.ts +20 -13
- package/dist/daemon/park-pending.js +3 -1
- package/dist/daemon/profile-delete.js +1 -1
- package/dist/daemon/reconcilers/bash-deadline.d.ts +15 -10
- package/dist/daemon/reconcilers/bash-deadline.js +1 -3
- package/dist/daemon/reconcilers/broker-supervision.d.ts +13 -3
- package/dist/daemon/reconcilers/broker-supervision.js +4 -4
- package/dist/daemon/reconcilers/cron-lane.d.ts +0 -1
- package/dist/daemon/reconcilers/cron-lane.js +1 -1
- package/dist/daemon/reconcilers/fault-retry-backstop.d.ts +2 -9
- package/dist/daemon/reconcilers/fault-retry-backstop.js +1 -1
- package/dist/daemon/reconcilers/grant-effects.d.ts +8 -0
- package/dist/daemon/reconcilers/grant-effects.js +1 -0
- package/dist/daemon/reconcilers/grove-instance-sweep.d.ts +1 -3
- package/dist/daemon/reconcilers/grove-instance-sweep.js +1 -1
- package/dist/daemon/reconcilers/ledger-r2.d.ts +27 -0
- package/dist/daemon/reconcilers/ledger-r2.js +7 -0
- package/dist/daemon/reconcilers/ledger-sandbox.d.ts +55 -0
- package/dist/daemon/reconcilers/ledger-sandbox.js +9 -0
- package/dist/daemon/reconcilers/ledger-storage.d.ts +22 -0
- package/dist/daemon/reconcilers/ledger-storage.js +5 -0
- package/dist/daemon/reconcilers/live-obligation.d.ts +3 -2
- package/dist/daemon/reconcilers/live-obligation.js +1 -1
- package/dist/daemon/reconcilers/managed-worktree-sweep.d.ts +0 -5
- package/dist/daemon/reconcilers/managed-worktree-sweep.js +1 -1
- package/dist/daemon/reconcilers/node-deadline.d.ts +2 -1
- package/dist/daemon/reconcilers/node-deadline.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.d.ts +1 -2
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/remote-wake.d.ts +31 -0
- package/dist/daemon/reconcilers/node-lifecycle/remote-wake.js +1 -0
- package/dist/daemon/reconcilers/node-lifecycle/requested-stops.d.ts +5 -0
- package/dist/daemon/reconcilers/node-lifecycle/requested-stops.js +2 -0
- package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
- package/dist/daemon/reconcilers/pending-review-submit.js +1 -1
- package/dist/daemon/reconcilers/recipe-image.d.ts +49 -0
- package/dist/daemon/reconcilers/recipe-image.js +7 -0
- package/dist/daemon/reconcilers/row-claim.d.ts +19 -0
- package/dist/daemon/reconcilers/row-claim.js +2 -0
- package/dist/daemon/reconcilers/storage-due-work.d.ts +18 -3
- package/dist/daemon/reconcilers/storage-due-work.js +2 -1
- package/dist/daemon/reconcilers/storage-maintenance.d.ts +5 -13
- package/dist/daemon/reconcilers/storage-maintenance.js +1 -1
- package/dist/daemon/reconcilers/structured-request-lane.js +1 -1
- package/dist/daemon/reconcilers/throttled-lane.d.ts +11 -0
- package/dist/daemon/reconcilers/throttled-lane.js +1 -0
- package/dist/daemon/review/finish.js +1 -1
- package/dist/daemon/run-notices.d.ts +3 -0
- package/dist/daemon/run-notices.js +1 -1
- package/dist/daemon/runs/append-section.d.ts +4 -1
- package/dist/daemon/runs/append-section.js +2 -2
- package/dist/daemon/runs/observer.d.ts +3 -2
- package/dist/daemon/runs/observer.js +3 -2
- package/dist/daemon/runs/view-transport.d.ts +19 -0
- package/dist/daemon/runs/view-transport.js +1 -0
- package/dist/daemon/structured-requests/boot.d.ts +2 -1
- package/dist/daemon/structured-requests/boot.js +1 -1
- package/dist/daemon/structured-requests/effects.d.ts +4 -3
- package/dist/daemon/structured-requests/effects.js +1 -1
- package/dist/daemon/structured-requests/notifier.d.ts +2 -0
- package/dist/daemon/structured-requests/notifier.js +1 -1
- package/dist/daemon/structured-requests/sidecar.d.ts +4 -3
- package/dist/daemon/structured-requests/sidecar.js +1 -1
- package/dist/launcher/validate.js +1 -1
- package/dist/migrations/004-canvas-documents/index.js +2 -2
- package/dist/pi-extensions/broker-local.d.ts +3 -3
- package/dist/pi-extensions/broker-local.js +1 -2
- package/dist/pi-extensions/canvas-bash-valve.js +6 -6
- package/dist/pi-extensions/canvas-context-intro.js +2 -2
- package/dist/pi-extensions/canvas-elapsed.js +2 -2
- package/dist/pi-extensions/canvas-goal-capture.js +1 -1
- package/dist/pi-extensions/canvas-inbox-watcher.js +2 -2
- package/dist/pi-extensions/canvas-review-boundary.d.ts +11 -1
- package/dist/pi-extensions/canvas-review-boundary.js +3 -3
- package/dist/pi-extensions/canvas-stophook.js +1 -1
- package/dist/pi-extensions/canvas-structured-output.d.ts +5 -3
- package/dist/pi-extensions/canvas-structured-output.js +6 -11
- package/dist/pi-extensions/canvas-tool-guide.d.ts +9 -2
- package/dist/pi-extensions/canvas-tool-guide.js +6 -6
- package/dist/shared/inbox-entry-body.js +7 -7
- package/dist/types.d.ts +12 -0
- package/docs/sdk/release-notes.md +4 -0
- package/package.json +7 -4
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +13 -13
- package/scripts/git-credential-crtr +33 -0
- package/scripts/sandbox-bootstrap.sh +54 -0
- package/scripts/sandbox-start.mjs +320 -0
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +0 -78
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +0 -1179
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +0 -1406
- package/dist/core/conversation-store/file-store.d.ts +0 -37
- package/dist/core/conversation-store/file-store.js +0 -9
- package/dist/core/conversation-store/listener.d.ts +0 -4
- package/dist/core/conversation-store/listener.js +0 -8
- package/dist/core/scoped-state/profiles.d.ts +0 -27
- package/dist/core/scoped-state/profiles.js +0 -1
- package/dist/core/scoped-state/providers.d.ts +0 -24
- package/dist/core/scoped-state/providers.js +0 -1
- package/dist/core/scoped-state/settings.d.ts +0 -28
- package/dist/core/scoped-state/settings.js +0 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var E=Object.defineProperty;var
|
|
2
|
-
AND NOT EXISTS (SELECT 1 FROM upload_uses x WHERE x.upload_id = u.upload_id)`).all(a)).map(
|
|
3
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'on', NULL)`).run(a.share_id,a.source_space,a.source_path,a.storage_key,a.url,a.created_by,a.created_at,a.expires_at)}
|
|
1
|
+
var E=Object.defineProperty;var r=(a,e)=>E(a,"name",{value:e,configurable:!0});import{openDb as l}from"../canvas/db.js";import{filterAsync as _}from"../async-array.js";const n=r(async a=>a??await l(),"handle"),d=r(()=>new Date().toISOString(),"now");async function w(a,e){await(await n(e)).prepare("INSERT INTO uploads (upload_id, grantee, name, media_type, size, created_at, delete_pending_since) VALUES (?, ?, ?, ?, ?, ?, NULL)").run(a.upload_id,a.grantee,a.name,a.media_type,a.size,a.created_at)}r(w,"insertUpload");async function f(a,e){return await(await n(e)).prepare("SELECT * FROM uploads WHERE upload_id = ?").get(a)??null}r(f,"getUpload");async function T(a,e){await(await n(e)).prepare("DELETE FROM uploads WHERE upload_id = ?").run(a)}r(T,"deleteUploadRow");async function L(a){return await(await n(a)).prepare("SELECT * FROM uploads WHERE delete_pending_since IS NOT NULL ORDER BY delete_pending_since, upload_id").all()}r(L,"pendingUploadDeletes");async function u(a,e,t=d()){const i=(await n(e)).prepare("UPDATE uploads SET delete_pending_since = COALESCE(delete_pending_since, ?) WHERE upload_id = ?");for(const s of a)await i.run(t,s)}r(u,"markUploadsDeletePending");async function O(a,e){const t=(await n(e)).prepare("INSERT INTO upload_uses (upload_id, run_id, path, blob_key) VALUES (?, ?, ?, ?)");for(const i of a)await t.run(i.upload_id,i.run_id,i.path,i.blob_key??null)}r(O,"insertUploadUses");async function D(a,e,t){return await(await n(t)).prepare("SELECT 1 AS used FROM upload_uses WHERE run_id = ? AND path = ?").get(a,e)!==void 0}r(D,"runUsesPath");async function y(a,e){await(await n(e)).prepare("DELETE FROM upload_uses WHERE upload_id = ? AND run_id = ? AND path = ?").run(a.upload_id,a.run_id,a.path)}r(y,"deleteUploadUse");async function U(a,e,t){await(await n(t)).prepare("UPDATE uploads SET size = ? WHERE upload_id = ?").run(e,a)}r(U,"setUploadSize");async function x(a,e){return await(await n(e)).prepare("SELECT upload_id, run_id, path FROM upload_uses WHERE path = ? ORDER BY run_id LIMIT 1").get(a)??null}r(x,"uploadUseAt");async function N(a,e){const t=await n(e);if(!a.length)return[];const i=a.map(()=>"?").join(","),s=(await t.prepareUncached(`SELECT DISTINCT upload_id FROM upload_uses WHERE run_id IN (${i})`).all(...a)).map(o=>o.upload_id);await t.prepareUncached(`DELETE FROM upload_uses WHERE run_id IN (${i})`).run(...a);const p=await _(s,async o=>!await t.prepare("SELECT 1 FROM upload_uses WHERE upload_id = ? LIMIT 1").get(o));return await u(p,t),p}r(N,"releaseRunUploads");async function g(a,e){return(await(await n(e)).prepare(`SELECT upload_id FROM uploads u WHERE delete_pending_since IS NULL AND created_at <= ?
|
|
2
|
+
AND NOT EXISTS (SELECT 1 FROM upload_uses x WHERE x.upload_id = u.upload_id)`).all(a)).map(t=>t.upload_id)}r(g,"staleUnusedUploads");async function A(a,e){await(await n(e)).prepare(`INSERT INTO shares (share_id, source_space, source_path, storage_key, url, created_by, created_at, expires_at, status, object_deleted_at)
|
|
3
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'on', NULL)`).run(a.share_id,a.source_space,a.source_path,a.storage_key,a.url,a.created_by,a.created_at,a.expires_at)}r(A,"insertShare");async function C(a,e){return await(await n(e)).prepare("SELECT * FROM shares WHERE share_id = ?").get(a)??null}r(C,"getShare");async function H(a,e){return a===null?await(await n(e)).prepare("SELECT * FROM shares ORDER BY created_at DESC, share_id").all():await(await n(e)).prepare("SELECT * FROM shares WHERE created_by = ? ORDER BY created_at DESC, share_id").all(a)}r(H,"listShares");async function c(a,e){await(await n(e)).prepare("UPDATE shares SET status = 'off' WHERE share_id = ?").run(a)}r(c,"turnShareOff");async function W(a,e){const t=await n(e),i=(await t.prepare("SELECT share_id FROM shares WHERE created_by = ? AND status = 'on'").all(a)).map(s=>s.share_id);return await t.prepare("UPDATE shares SET status = 'off' WHERE created_by = ? AND status = 'on'").run(a),i}r(W,"turnSharesOffFor");async function M(a=d(),e){const t=await n(e),i=(await t.prepare("SELECT share_id FROM shares WHERE status = 'on' AND expires_at IS NOT NULL AND expires_at <= ?").all(a)).map(s=>s.share_id);for(const s of i)await c(s,t);return i}r(M,"expireShares");async function m(a){return await(await n(a)).prepare("SELECT * FROM shares WHERE status = 'off' AND object_deleted_at IS NULL ORDER BY created_at, share_id").all()}r(m,"sharesOwingObjectDelete");async function F(a,e,t=d()){await(await n(e)).prepare("UPDATE shares SET object_deleted_at = COALESCE(object_deleted_at, ?) WHERE share_id = ?").run(t,a)}r(F,"markShareObjectDeleted");async function I(a,e,t=d()){const i=await n(e),s=(await i.prepare("SELECT upload_id FROM uploads WHERE grantee = ? AND delete_pending_since IS NULL").all(a)).map(p=>p.upload_id);return await u(s,i,t),s}r(I,"markGranteeUploadsDeletePending");export{T as deleteUploadRow,y as deleteUploadUse,M as expireShares,C as getShare,f as getUpload,A as insertShare,w as insertUpload,O as insertUploadUses,H as listShares,I as markGranteeUploadsDeletePending,F as markShareObjectDeleted,u as markUploadsDeletePending,L as pendingUploadDeletes,N as releaseRunUploads,D as runUsesPath,U as setUploadSize,m as sharesOwingObjectDelete,g as staleUnusedUploads,c as turnShareOff,W as turnSharesOffFor,x as uploadUseAt};
|
|
@@ -1,47 +1,26 @@
|
|
|
1
|
+
import { type CanvasDb } from './canvas/db.js';
|
|
1
2
|
import { type RateLimitScope } from './rate-limit-scope.js';
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export declare const INVALID_REFRESH_TOKEN_BACKOFF_MS: number;
|
|
9
|
-
export type ManagedProviderId = typeof ANTHROPIC_PROVIDER_ID | typeof OPENAI_CODEX_PROVIDER_ID | typeof OPENAI_CHATGPT_PROVIDER_ID;
|
|
10
|
-
export declare const MANAGED_PROVIDER_IDS: readonly ManagedProviderId[];
|
|
11
|
-
export type ModelStrength = 'ultra' | 'strong' | 'medium' | 'light';
|
|
12
|
-
export type RotationConfig = {
|
|
13
|
-
defaultFallbackStrength?: ModelStrength;
|
|
14
|
-
revertWhenAvailable?: boolean;
|
|
15
|
-
};
|
|
16
|
-
/** `rateLimitedUntil` cools the whole account; `modelCooldowns` cools one model family on it (family → epoch ms, stored rows including expired ones). Read both through `coolingUntilFor`. */
|
|
17
|
-
export type SubscriptionCredential = {
|
|
3
|
+
import { type ManagedProviderId, type RotationConfig, type SubscriptionCredential } from './managed-providers.js';
|
|
4
|
+
export * from './managed-providers.js';
|
|
5
|
+
/** One `model_accounts` row without its sealed tokens. */
|
|
6
|
+
type ProviderRow = {
|
|
7
|
+
providerId: string;
|
|
8
|
+
id: string;
|
|
18
9
|
label: string;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
expires: number;
|
|
22
|
-
rateLimitedUntil: number;
|
|
10
|
+
labelKey: string;
|
|
11
|
+
position: number;
|
|
23
12
|
lastAttemptAt: number;
|
|
24
13
|
lastRateLimitedAt: number;
|
|
14
|
+
rateLimitedUntil: number;
|
|
25
15
|
authFailure?: 'invalid_grant';
|
|
16
|
+
};
|
|
17
|
+
type StoredCredential = {
|
|
18
|
+
refresh: string;
|
|
19
|
+
access: string;
|
|
20
|
+
expires: number;
|
|
26
21
|
accountId?: string;
|
|
27
22
|
clientId?: string;
|
|
28
|
-
modelCooldowns?: Record<string, number>;
|
|
29
23
|
};
|
|
30
|
-
export type ProviderCandidate = {
|
|
31
|
-
providerId: string;
|
|
32
|
-
modelId: string;
|
|
33
|
-
thinkingLevel?: string;
|
|
34
|
-
registered: boolean;
|
|
35
|
-
authenticated: boolean;
|
|
36
|
-
coolingUntil?: number;
|
|
37
|
-
automaticFallback?: boolean;
|
|
38
|
-
routeId?: string;
|
|
39
|
-
credentialSource?: string;
|
|
40
|
-
family?: string;
|
|
41
|
-
strength?: ModelStrength;
|
|
42
|
-
rank?: number;
|
|
43
|
-
};
|
|
44
|
-
export type ProviderCandidateRejection = 'unregistered' | 'non-managed-fallback' | 'unauthenticated' | 'cooling';
|
|
45
24
|
/** Refreshed tokens; `clientId` is set when the vendor rotated the issued OAuth client id. */
|
|
46
25
|
export type RefreshedTokens = {
|
|
47
26
|
refresh: string;
|
|
@@ -49,39 +28,20 @@ export type RefreshedTokens = {
|
|
|
49
28
|
expires: number;
|
|
50
29
|
clientId?: string;
|
|
51
30
|
};
|
|
52
|
-
/**
|
|
53
|
-
export declare
|
|
54
|
-
/**
|
|
55
|
-
export declare
|
|
56
|
-
|
|
57
|
-
until: number;
|
|
58
|
-
}>;
|
|
59
|
-
/** Human text for an account's active cooldowns (`cooldown 12m`, `opus cooldown 3d 4h`), or undefined when it is ready. */
|
|
60
|
-
export declare function formatCooldowns(entry: Pick<SubscriptionCredential, 'rateLimitedUntil' | 'modelCooldowns'>, now?: number): string | undefined;
|
|
61
|
-
/** Whether a successful call on `modelId` has stored cooldown or auth health to clear; callers skip the write otherwise (every provider write bumps provider_revision). */
|
|
62
|
-
export declare function subscriptionNeedsSuccessWrite(entry: Pick<SubscriptionCredential, 'rateLimitedUntil' | 'authFailure' | 'modelCooldowns'>, modelId?: string): boolean;
|
|
63
|
-
export declare function isManagedProvider(providerId: string | undefined): providerId is ManagedProviderId;
|
|
64
|
-
/** Stable per-install UUID sent to OpenAI as `ext_agent_host_id=urn:uuid:<id>` during ChatGPT sign-in. The install id is not a UUID, so this is its own get-or-create secret. */
|
|
65
|
-
export declare function openAIDeviceId(): string;
|
|
66
|
-
export declare function getProviderLabel(providerId: ManagedProviderId): string;
|
|
67
|
-
export declare function resolveProviderCandidates(candidates: readonly ProviderCandidate[], now?: number, options?: {
|
|
68
|
-
pinnedToFirst?: boolean;
|
|
69
|
-
}): {
|
|
70
|
-
candidates: ProviderCandidate[];
|
|
71
|
-
rejected: Array<{
|
|
72
|
-
candidate: ProviderCandidate;
|
|
73
|
-
reason: ProviderCandidateRejection;
|
|
74
|
-
}>;
|
|
75
|
-
};
|
|
76
|
-
export declare class DuplicateSubscriptionError extends Error {
|
|
77
|
-
constructor(message: string);
|
|
31
|
+
/** Longest a refresh exchange may hold the account's row lock. */
|
|
32
|
+
export declare const REFRESH_EXCHANGE_TIMEOUT_MS = 10000;
|
|
33
|
+
/** Another process held this account's row lock for the whole lock timeout (a slow refresh exchange): the account is cooling for this call, not failed. */
|
|
34
|
+
export declare class RefreshBusyError extends Error {
|
|
35
|
+
constructor(provider: ManagedProviderId, label: string);
|
|
78
36
|
}
|
|
79
|
-
export declare function
|
|
37
|
+
export declare function insertAccount(db: CanvasDb, person: string, provider: ManagedProviderId, row: ProviderRow, entry: StoredCredential): Promise<void>;
|
|
38
|
+
export declare function upsertModelCooldown(db: CanvasDb, person: string, provider: string, accountId: string, family: string, until: number, rateLimitedAt: number): Promise<void>;
|
|
39
|
+
export declare function readSubscriptionPool(provider: ManagedProviderId): Promise<SubscriptionCredential[]>;
|
|
80
40
|
/** The pool with each account's row id: the stable handle a caller outside the process removes an account by. */
|
|
81
|
-
export declare function readSubscriptionPoolRows(provider: ManagedProviderId): Array<{
|
|
41
|
+
export declare function readSubscriptionPoolRows(provider: ManagedProviderId): Promise<Array<{
|
|
82
42
|
id: string;
|
|
83
43
|
entry: SubscriptionCredential;
|
|
84
|
-
}
|
|
44
|
+
}>>;
|
|
85
45
|
export declare function writeSubscriptionPool(provider: ManagedProviderId, next: SubscriptionCredential[]): Promise<SubscriptionCredential[]>;
|
|
86
46
|
export declare function addSubscription(provider: ManagedProviderId, entry: SubscriptionCredential): Promise<SubscriptionCredential[]>;
|
|
87
47
|
export declare function upsertSubscription(provider: ManagedProviderId, entry: SubscriptionCredential): Promise<SubscriptionCredential[]>;
|
|
@@ -99,8 +59,8 @@ export declare function markSubscriptionAttempt(provider: ManagedProviderId, ref
|
|
|
99
59
|
export declare function markSubscriptionRateLimited(provider: ManagedProviderId, ref: string, retryAfterMs: number, attemptAt?: number, rateLimitedAt?: number, scope?: RateLimitScope): Promise<SubscriptionCredential[]>;
|
|
100
60
|
/** A call on `modelId` succeeded: clear the account-wide cooldown and auth failure, and that model family's cooldown, unless a newer 429 for the same scope landed after `attemptAt` began. */
|
|
101
61
|
export declare function markSubscriptionSuccess(provider: ManagedProviderId, ref: string, attemptAt?: number, modelId?: string): Promise<SubscriptionCredential[]>;
|
|
62
|
+
/** Refresh one account's tokens under its row lock. A process that waited on the lock finds the tokens already fresh (or the account already flagged) and does not call the vendor again. */
|
|
102
63
|
export declare function refreshSubscriptionCredential(provider: ManagedProviderId, label: string, exchange: (refreshToken: string, clientId?: string) => Promise<RefreshedTokens>): Promise<SubscriptionCredential>;
|
|
103
|
-
export declare function isInvalidRefreshTokenError(error: unknown): boolean;
|
|
104
64
|
export declare function modifyElectedSubscription(provider: ManagedProviderId, elect: (pool: SubscriptionCredential[]) => SubscriptionCredential | undefined, apply: (current: SubscriptionCredential) => Promise<RefreshedTokens | undefined>): Promise<SubscriptionCredential | undefined>;
|
|
105
65
|
export type ManagedLoginIdentity = {
|
|
106
66
|
accountId?: string;
|
|
@@ -121,9 +81,11 @@ export declare function commitManagedLogin(provider: ManagedProviderId, label: s
|
|
|
121
81
|
lastRateLimitedAt: number;
|
|
122
82
|
autoLabel?: boolean;
|
|
123
83
|
}): Promise<SubscriptionCredential[]>;
|
|
124
|
-
|
|
125
|
-
export declare function
|
|
126
|
-
|
|
127
|
-
export declare function readRotationConfig(): RotationConfig
|
|
128
|
-
export declare function writeRotationConfig(next: RotationConfig): RotationConfig
|
|
129
|
-
|
|
84
|
+
/** The person's rotation settings from their `model_settings` row (defaults when there is no row), also stored for `readRotationConfig`. */
|
|
85
|
+
export declare function loadRotationConfig(): Promise<RotationConfig>;
|
|
86
|
+
/** Rotation settings for route expansion: a broker's launch snapshot (a broker never reads rows), else the person's `model_settings` row. */
|
|
87
|
+
export declare function readRotationConfig(): Promise<RotationConfig>;
|
|
88
|
+
export declare function writeRotationConfig(next: RotationConfig): Promise<RotationConfig>;
|
|
89
|
+
/** Stable per-install UUID sent to OpenAI as `ext_agent_host_id=urn:uuid:<id>` during ChatGPT sign-in: the person's get-or-create secret in `model_settings`. */
|
|
90
|
+
export declare function openAIDeviceId(): Promise<string>;
|
|
91
|
+
export declare function formatStatusLine(provider: ManagedProviderId, now?: number, modelId?: string): Promise<string>;
|
|
@@ -1,4 +1 @@
|
|
|
1
|
-
var lt=Object.defineProperty;var r=(t,n)=>lt(t,"name",{value:n,configurable:!0});import{prepared as g}from"./sqlite-statements.js";import{createHash as ut,randomUUID as N}from"node:crypto";import{mkdirSync as dt,readFileSync as mt,writeFileSync as ft}from"node:fs";import{join as G}from"node:path";import{brokerConfigSnapshot as ht}from"./config.js";import{LockedJsonFile as bt}from"./locked-file.js";import{secretsDir as pt}from"./layout.js";import{openScopedStore as At}from"./scoped-state/db.js";import{providerStore as yt}from"./scoped-state/paths.js";import{providerModelCooldowns as P,providerModelCooldownsFor as _t,providerRowByReference as j,providerRows as gt,providerWrite as A}from"./scoped-state/providers.js";import{modelCooldownFamily as W}from"./rate-limit-scope.js";const H="anthropic",z="openai-codex",J="openai",K=600*1e3,Et=720*60*60*1e3,Jt=[H,z,J],Q="strong",X={anthropic:{label:"Claude",credentials:"anthropic-credentials.json"},"openai-codex":{label:"OpenAI Codex",credentials:"openai-codex-credentials.json"},openai:{label:"ChatGPT",credentials:"openai-credentials.json"}};function I(t){return{refresh:t.refresh,access:t.access,expires:t.expires,...t.accountId?{accountId:t.accountId}:{},...t.clientId?{clientId:t.clientId}:{}}}r(I,"stored");function V(t){return typeof t=="string"&&t.trim()?t.trim():void 0}r(V,"optionalString");function f(){return pt()}r(f,"agentDir");function B(t){return G(f(),X[t].credentials)}r(B,"credentialFile");function Y(t){return t==="ultra"||t==="strong"||t==="medium"||t==="light"?t:void 0}r(Y,"normalizeStrength");function h(t){return t.toLowerCase()}r(h,"key");function Lt(t){const n=typeof t.label=="string"?t.label.trim():"",e=typeof t.refresh=="string"?t.refresh.trim():"",a=typeof t.access=="string"?t.access.trim():"",i=Number(t.expires);if(!n||!e||!a||!Number.isFinite(i))return;const o=V(t.accountId),s=V(t.clientId);return{label:n,refresh:e,access:a,expires:i,rateLimitedUntil:Number.isFinite(Number(t.rateLimitedUntil))?Number(t.rateLimitedUntil):0,lastAttemptAt:Number.isFinite(Number(t.lastAttemptAt))?Number(t.lastAttemptAt):0,lastRateLimitedAt:Number.isFinite(Number(t.lastRateLimitedAt))?Number(t.lastRateLimitedAt):0,...t.authFailure==="invalid_grant"?{authFailure:"invalid_grant"}:{},...o?{accountId:o}:{},...s?{clientId:s}:{},...Z(t.modelCooldowns)?{modelCooldowns:Z(t.modelCooldowns)}:{}}}r(Lt,"credential");function Z(t){if(!t||typeof t!="object"||Array.isArray(t))return;const n=Object.entries(t).filter(([e,a])=>e.trim()!==""&&Number.isFinite(Number(a))).map(([e,a])=>[e,Number(a)]);return n.length?Object.fromEntries(n):void 0}r(Z,"modelCooldowns");function U(t,n){if(!n.label?.trim())throw new Error(`${b(t)} subscription label cannot be empty`);const e=Lt(n);if(!e)throw new Error(`Refusing to persist incomplete ${b(t)} subscription "${n.label.trim()}"; pool rows require both OAuth tokens.`);return e}r(U,"assertCredential");function v(t,n){if(!n||n.trim()==="")return{version:1,accounts:{}};let e;try{e=JSON.parse(n)}catch(a){throw new Error(`managed credential file ${t} is corrupt: ${a instanceof Error?a.message:String(a)}`)}if(typeof e!="object"||e===null||Array.isArray(e)||e.version!==1||typeof e.accounts!="object"||e.accounts===null||Array.isArray(e.accounts))throw new Error(`managed credential file ${t} is corrupt`);return e}r(v,"parseCredentials");function xt(t,n,e=[]){const a=n.accounts[t.id];if(!a||typeof a.refresh!="string"||typeof a.access!="string"||!Number.isFinite(a.expires))throw new Error(`managed ${t.providerId} account ${t.id} has no credential record`);return{label:t.label,refresh:a.refresh,access:a.access,expires:a.expires,rateLimitedUntil:t.authFailure||!t.lastRateLimitedAt?t.rateLimitedUntil:Math.min(t.rateLimitedUntil,t.lastRateLimitedAt+K),lastAttemptAt:t.lastAttemptAt,lastRateLimitedAt:t.lastRateLimitedAt,...t.authFailure?{authFailure:t.authFailure}:{},...a.accountId?{accountId:a.accountId}:{},...a.clientId?{clientId:a.clientId}:{},...e.length?{modelCooldowns:Object.fromEntries(e.map(i=>[i.family,i.lastRateLimitedAt?Math.min(i.rateLimitedUntil,i.lastRateLimitedAt+K):i.rateLimitedUntil]))}:{}}}r(xt,"toPublic");function k(t,n){const e=_t(f(),t);return gt(f(),t).map(a=>({row:a,entry:xt(a,n,e.get(a.id))}))}r(k,"rowsWithCredentials");function tt(t){return new bt(B(t),!0,`{"version":1,"accounts":{}}
|
|
2
|
-
`)}r(tt,"managedCredentialFile");function et(t){return v(B(t),tt(t).readUnlocked())}r(et,"readFile");function nt(t,n){const e=t.accountId?.trim(),a=n.accountId?.trim();return!!(e&&a&&e!==a)}r(nt,"differentAccount");function _(t){return t.accountId?.trim()||(t.refresh.trim()?`refresh:${ut("sha256").update(t.refresh.trim()).digest("hex")}`:void 0)}r(_,"identity");function at(t,n){const e=V(n);return e?{...t,clientId:e}:t}r(at,"withClientId");function it(t,n,e){const a=e.refresh?.trim()??"",i=e.access?.trim()??"",o=Number(e.expires);if(!a||!i||!Number.isFinite(o))throw new Error(`${b(t)} subscription "${n}" returned an incomplete credential; the stored credential was left unchanged.`);return{refresh:a,access:i,expires:o}}r(it,"assertTokens");function Rt(t,n){const e=W(n);return Math.max(t.rateLimitedUntil||0,e===void 0?0:t.modelCooldowns?.[e]??0)}r(Rt,"coolingUntilFor");function wt(t,n=Date.now()){return[...(t.rateLimitedUntil||0)>n?[{scope:"account",until:t.rateLimitedUntil}]:[],...Object.entries(t.modelCooldowns??{}).filter(([,e])=>e>n).map(([e,a])=>({scope:e,until:a}))]}r(wt,"activeCooldowns");function Qt(t,n=Date.now()){const e=wt(t,n).map(({scope:a,until:i})=>`${a==="account"?"":`${a} `}cooldown ${It(i-n)}`);return e.length?e.join(", "):void 0}r(Qt,"formatCooldowns");function It(t){const n=Math.max(1,Math.ceil(t/6e4));if(n<60)return`${n}m`;const e=Math.floor(n/60);return e<24?`${e}h${n%60?` ${n%60}m`:""}`:`${Math.floor(e/24)}d${e%24?` ${e%24}h`:""}`}r(It,"formatWait");function Ft(t,n){const e=W(n);return e!==void 0&&t.modelCooldowns?.[e]!==void 0}r(Ft,"hasModelCooldownRow");function Xt(t,n){return!!(t.rateLimitedUntil||t.authFailure)||Ft(t,n)}r(Xt,"subscriptionNeedsSuccessWrite");function Yt(t){return t===H||t===z||t===J}r(Yt,"isManagedProvider");function Zt(){const t=G(f(),"openai-device-id");try{const e=mt(t,"utf8").trim();if(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(e))return e.toLowerCase()}catch{}const n=N();return dt(f(),{recursive:!0,mode:448}),ft(t,`${n}
|
|
3
|
-
`,{mode:384}),n}r(Zt,"openAIDeviceId");function b(t){return X[t].label}r(b,"getProviderLabel");function vt(t,n=Date.now(),e={}){const a=[],i=[];for(let o=0;o<t.length;o++){const s=t[o],c=s.registered?s.automaticFallback===!1?"non-managed-fallback":s.authenticated?(s.coolingUntil??0)>n?"cooling":void 0:"unauthenticated":"unregistered";if(!c)a.push(s);else if(i.push({candidate:s,reason:c}),e.pinnedToFirst&&o===0&&c!=="cooling")break}return{candidates:a,rejected:i}}r(vt,"resolveProviderCandidates");class w extends Error{static{r(this,"DuplicateSubscriptionError")}constructor(n){super(n),this.name="DuplicateSubscriptionError"}}function D(t){return k(t,et(t)).map(({entry:n})=>n)}r(D,"readSubscriptionPool");function te(t){return k(t,et(t)).map(({row:n,entry:e})=>({id:n.id,entry:e}))}r(te,"readSubscriptionPoolRows");async function E(t,n){const e=B(t);return tt(t).withLockAsync(async(a,i,o)=>{const s=v(e,a);return{result:await n(s,k(t,s),c=>o(`${JSON.stringify(c)}
|
|
4
|
-
`))}})}r(E,"locked");function O(t,n,e){g(t,"INSERT INTO managed_accounts(provider_id,id,label,label_key,position,last_attempt_at,last_rate_limited_at,rate_limited_until,auth_failure) VALUES(?,?,?,?,?,?,?,?,?)").run(n,e.id,e.label,e.labelKey,e.position,e.lastAttemptAt,e.lastRateLimitedAt,e.rateLimitedUntil,e.authFailure??null)}r(O,"insert");function L(t,n){g(t,"UPDATE managed_accounts SET label=?,label_key=?,position=?,last_attempt_at=?,last_rate_limited_at=?,rate_limited_until=?,auth_failure=? WHERE provider_id=? AND id=?").run(n.label,n.labelKey,n.position,n.lastAttemptAt,n.lastRateLimitedAt,n.rateLimitedUntil,n.authFailure??null,n.providerId,n.id)}r(L,"update");function rt(t,n,e,a,i,o){g(t,"INSERT INTO managed_account_model_cooldowns(provider_id,account_id,family,rate_limited_until,last_rate_limited_at) VALUES(?,?,?,?,?) ON CONFLICT(provider_id,account_id,family) DO UPDATE SET rate_limited_until=excluded.rate_limited_until,last_rate_limited_at=excluded.last_rate_limited_at").run(n,e,a,i,o)}r(rt,"upsertModelCooldown");function T(t,n,e){e===void 0?g(t,"DELETE FROM managed_account_model_cooldowns WHERE provider_id=?").run(n):g(t,"DELETE FROM managed_account_model_cooldowns WHERE provider_id=? AND account_id=?").run(n,e)}r(T,"deleteModelCooldowns");function x(t,n){return k(t,n).map(({entry:e})=>e)}r(x,"publicPool");function F(t,n){try{n()}catch(e){throw new Error(`managed ${b(t)} credential file was published, but its SQL membership update failed; SQL membership remains authoritative: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}r(F,"writeMembershipAfterCredentialPublish");async function ee(t,n){return E(t,async(e,a,i)=>{const o=n.map(l=>U(t,l)),s=o.map((l,u)=>({entry:l,id:a[u]?.row.id??N()})),c={};for(const{entry:l,id:u}of s)c[u]=I(l);return i({version:1,accounts:c}),F(t,()=>A(f(),l=>{const u=P(l,t);g(l,"DELETE FROM managed_accounts WHERE provider_id=?").run(t),g(l,"DELETE FROM managed_account_model_cooldowns WHERE provider_id=?").run(t),s.forEach(({entry:d,id:m},y)=>{O(l,t,{providerId:t,id:m,label:d.label,labelKey:h(d.label),position:y,lastAttemptAt:d.lastAttemptAt,lastRateLimitedAt:d.lastRateLimitedAt,rateLimitedUntil:d.rateLimitedUntil,...d.authFailure?{authFailure:d.authFailure}:{}});for(const[$,C]of Object.entries(d.modelCooldowns??{}))rt(l,t,m,$,C,u.get(m)?.find(p=>p.family===$)?.lastRateLimitedAt??d.lastRateLimitedAt)})})),o})}r(ee,"writeSubscriptionPool");function M(t,n){const e=n.trim().toLowerCase(),a=Number.parseInt(e,10);return Number.isFinite(a)&&String(a)===e&&a>=1&&a<=t.length?a-1:t.findIndex(({entry:i})=>h(i.label)===e)}r(M,"resolve");async function $t(t,n){const e=U(t,n);return E(t,async(a,i,o)=>{if(i.some(({entry:u})=>h(u.label)===h(e.label)))throw new w(`${b(t)} subscription already exists: ${e.label}`);const s=_(e),c=i.find(({entry:u})=>_(u)===s);if(s&&c)throw new w(`This ${b(t)} account is already added as \u201C${c.entry.label}\u201D \u2014 it shares the same quota, so a second slot adds no redundancy.`);const l=N();return a.accounts[l]=I(e),o(a),F(t,()=>A(f(),u=>O(u,t,{providerId:t,id:l,label:e.label,labelKey:h(e.label),position:i.length,lastAttemptAt:e.lastAttemptAt,lastRateLimitedAt:e.lastRateLimitedAt,rateLimitedUntil:e.rateLimitedUntil,...e.authFailure?{authFailure:e.authFailure}:{}}))),x(t,a)})}r($t,"addSubscription");async function ne(t,n){const e=U(t,n);return D(t).find(i=>h(i.label)===h(e.label))?St(t,e):$t(t,e)}r(ne,"upsertSubscription");async function St(t,n){const e=U(t,n);return E(t,async(a,i,o)=>{const s=i.findIndex(({entry:m})=>h(m.label)===h(e.label)),c=i[s],l=i.find(({entry:m},y)=>y!==s&&_(m)===_(e));if(_(e)&&l)throw new w(`This ${b(t)} account is already added as \u201C${l.entry.label}\u201D \u2014 it shares the same quota, so a second slot adds no redundancy.`);if(!c){const m=N();return a.accounts[m]=I(e),o(a),F(t,()=>A(f(),y=>O(y,t,{providerId:t,id:m,label:e.label,labelKey:h(e.label),position:i.length,lastAttemptAt:e.lastAttemptAt,lastRateLimitedAt:e.lastRateLimitedAt,rateLimitedUntil:e.rateLimitedUntil}))),x(t,a)}const u=c.row,d=e.lastRateLimitedAt>=u.lastRateLimitedAt;return a.accounts[u.id]=I(e),o(a),F(t,()=>A(f(),m=>{L(m,{...u,authFailure:void 0,label:e.label,labelKey:h(e.label),lastAttemptAt:Math.max(u.lastAttemptAt,e.lastAttemptAt),lastRateLimitedAt:d?e.lastRateLimitedAt:u.lastRateLimitedAt,rateLimitedUntil:d?e.rateLimitedUntil:u.rateLimitedUntil}),nt(c.entry,e)&&T(m,t,u.id)})),x(t,a)})}r(St,"upsertSubscriptionWithUniqueAccount");async function ae(t,n,e){return E(t,async(a,i)=>{const o=M(i,n);if(o<0)throw new Error(`Unknown ${b(t)} subscription: ${n}`);const s=e.trim();if(!s)throw new Error(`${b(t)} subscription label cannot be empty`);if(i.some((c,l)=>l!==o&&h(c.entry.label)===h(s)))throw new w(`${b(t)} subscription already exists: ${s}`);return A(f(),c=>L(c,{...i[o].row,label:s,labelKey:h(s)})),x(t,a)})}r(ae,"renameSubscription");async function q(t,n,e){return E(t,async(a,i,o)=>{const s=n(i);if(s<0)throw new Error(`Unknown ${b(t)} subscription: ${e}`);const c=i[s].row;return A(f(),l=>{g(l,"DELETE FROM managed_accounts WHERE provider_id=? AND id=?").run(t,c.id),T(l,t,c.id)}),delete a.accounts[c.id],o(a),x(t,a)})}r(q,"remove");async function Nt(t,n){return q(t,e=>M(e,n),n)}r(Nt,"removeManagedAccount");async function ie(t,n){return q(t,e=>e.findIndex(({row:a})=>a.id===n),n)}r(ie,"removeManagedAccountById");async function re(t,n){return q(t,e=>M(e,n),n)}r(re,"removeSubscription");async function Ut(t){return E(t,async(n,e,a)=>{A(f(),i=>{g(i,"DELETE FROM managed_accounts WHERE provider_id=?").run(t),T(i,t)});for(const{row:i}of e)delete n.accounts[i.id];return a(n),e.length})}r(Ut,"removeAllManagedAccounts");async function oe(t,n){return n===void 0?(await Ut(t),[]):Nt(t,n)}r(oe,"removeManagedProvider");async function se(t,n){return E(t,async(e,a)=>{const i=M(a,n);if(i<0)throw new Error(`Unknown ${b(t)} subscription: ${n}`);return A(f(),o=>{[a[i],...a.filter((c,l)=>l!==i)].forEach((c,l)=>L(o,{...c.row,position:l}))}),x(t,e)})}r(se,"promoteSubscription");async function ot(t,n,e){return A(f(),a=>{const i=j(a,t,n);if(!i)throw new Error(`Unknown ${b(t)} subscription: ${n}`);const o=e(i);o&&L(a,o)}),D(t)}r(ot,"mutateHealth");async function ce(t,n,e=Date.now()){return ot(t,n,a=>({...a,lastAttemptAt:Math.max(a.lastAttemptAt,e)}))}r(ce,"markSubscriptionAttempt");async function le(t,n,e,a=Date.now(),i=Date.now(),o={kind:"account"}){return e=Math.min(Math.max(0,e),K),o.kind==="account"?ot(t,n,s=>i<s.lastRateLimitedAt?null:{...s,lastAttemptAt:Math.max(s.lastAttemptAt,a),lastRateLimitedAt:i,rateLimitedUntil:i+e}):(A(f(),s=>{const c=j(s,t,n);if(!c)throw new Error(`Unknown ${b(t)} subscription: ${n}`);L(s,{...c,lastAttemptAt:Math.max(c.lastAttemptAt,a)});const l=P(s,t).get(c.id)?.find(u=>u.family===o.family);l&&i<l.lastRateLimitedAt||rt(s,t,c.id,o.family,i+e,i)}),D(t))}r(le,"markSubscriptionRateLimited");async function ue(t,n,e=Date.now(),a){const i=W(a);return A(f(),o=>{const s=j(o,t,n);if(!s)throw new Error(`Unknown ${b(t)} subscription: ${n}`);if(e>=s.lastRateLimitedAt&&L(o,{...s,authFailure:void 0,lastAttemptAt:Math.max(s.lastAttemptAt,e),rateLimitedUntil:0}),i===void 0)return;const c=P(o,t).get(s.id)?.find(l=>l.family===i);c&&e>=c.lastRateLimitedAt&&g(o,"DELETE FROM managed_account_model_cooldowns WHERE provider_id=? AND account_id=? AND family=?").run(t,s.id,i)}),D(t)}r(ue,"markSubscriptionSuccess");function st(t){const n=Date.now();A(f(),e=>L(e,{...t,authFailure:"invalid_grant",lastAttemptAt:Math.max(t.lastAttemptAt,n),rateLimitedUntil:Math.max(t.rateLimitedUntil,n+Et)}))}r(st,"recordInvalidGrant");async function de(t,n,e){return E(t,async(a,i,o)=>{const s=M(i,n);if(s<0)throw new Error(`${b(t)} subscription "${n}" no longer exists`);const c=i[s];if(c.entry.expires>Date.now())return c.entry;let l;try{l=await e(c.entry.refresh,c.entry.clientId)}catch(d){throw ct(d)&&st(c.row),d}const u=at(it(t,c.entry.label,l),l.clientId??c.entry.clientId);return a.accounts[c.row.id]={...a.accounts[c.row.id],...u},o(a),{...c.entry,...u}})}r(de,"refreshSubscriptionCredential");function ct(t){const n=t,e=[n?.errorMessage,n?.message,t instanceof Error?t.message:""].filter(i=>typeof i=="string").join(" ");return(typeof n?.status=="number"?n.status:Number(e.match(/\bstatus[=:]\s*(\d+)/i)?.[1]))===400&&/invalid_grant|refresh token .*invalid|refresh token .*not found/i.test(e)}r(ct,"isInvalidRefreshTokenError");async function me(t,n,e){return E(t,async(a,i,o)=>{const s=new Set;let c;for(;s.size<i.length;){const l=n(i.filter(({entry:d})=>!s.has(d.label)).map(({entry:d})=>d));if(!l)break;const u=i.find(({entry:d})=>d.label===l.label);s.add(u.entry.label);try{const d=await e(u.entry);if(d){const m=at(it(t,u.entry.label,d),d.clientId??u.entry.clientId);return a.accounts[u.row.id]={...a.accounts[u.row.id],...m},o(a),{...u.entry,...m}}return u.entry}catch(d){if(!ct(d))throw d;c=d,st(u.row)}}if(c)throw c})}r(me,"modifyElectedSubscription");async function Dt(t,n){const e=n.accountId?.trim(),a=n.email?.trim();if(t!==H)return{...e?{accountId:e}:{},...a?{email:a}:{}};try{const i=await fetch("https://api.anthropic.com/api/oauth/profile",{headers:{Authorization:`Bearer ${n.access}`,Accept:"application/json"},signal:AbortSignal.timeout(3e3)});if(!i.ok)return e?{accountId:e}:{};const o=await i.json(),s=typeof o.account?.uuid=="string"&&o.account.uuid.trim()?o.account.uuid.trim():void 0,c=typeof o.account?.email=="string"&&o.account.email.trim()?o.account.email.trim():void 0;return{...s?{accountId:s}:{},...c?{email:c}:{}}}catch{return e?{accountId:e}:{}}}r(Dt,"enrichManagedLoginIdentity");async function fe(t,n,e){const a=await Dt(t,e);return E(t,async(i,o,s)=>{const c=e.autoLabel?void 0:n?.trim(),l=_({refresh:e.refresh,accountId:a.accountId}),u=(c?o.find(({entry:p})=>h(p.label)===h(c)):void 0)??o.find(({entry:p})=>_(p)===l);let d=u?.entry.label??c;if(!d&&e.autoLabel){const p=a.email||n?.trim()||`Account ${o.length+1}`;d=p;for(let S=2;o.some(({entry:R})=>h(R.label)===h(d));S++)d=`${p} (${S})`}if(!d)throw new Error(`${b(t)} subscription label cannot be empty`);const m=U(t,{label:d,refresh:e.refresh,access:e.access,expires:e.expires,...a.accountId?{accountId:a.accountId}:{},...e.clientId?{clientId:e.clientId}:{},rateLimitedUntil:0,lastAttemptAt:Date.now(),lastRateLimitedAt:e.lastRateLimitedAt});if(!u){if(o.some(({entry:R})=>h(R.label)===h(m.label)))throw new w(`${b(t)} subscription already exists: ${m.label}`);const p=o.find(({entry:R})=>_(R)===_(m));if(_(m)&&p)throw new w(`This ${b(t)} account is already added as \u201C${p.entry.label}\u201D \u2014 it shares the same quota, so a second slot adds no redundancy.`);const S=N();return i.accounts[S]=I(m),s(i),F(t,()=>A(f(),R=>O(R,t,{providerId:t,id:S,label:m.label,labelKey:h(m.label),position:o.length,lastAttemptAt:m.lastAttemptAt,lastRateLimitedAt:m.lastRateLimitedAt,rateLimitedUntil:m.rateLimitedUntil}))),x(t,i)}const y=u.row,$=o.find(({entry:p})=>p.label!==u.entry.label&&_(p)===_(m));if(_(m)&&$)throw new w(`This ${b(t)} account is already added as \u201C${$.entry.label}\u201D \u2014 it shares the same quota, so a second slot adds no redundancy.`);i.accounts[y.id]=I(m),s(i);const C=m.lastRateLimitedAt>=y.lastRateLimitedAt;return F(t,()=>A(f(),p=>{L(p,{...y,authFailure:void 0,lastAttemptAt:Math.max(y.lastAttemptAt,m.lastAttemptAt),lastRateLimitedAt:C?m.lastRateLimitedAt:y.lastRateLimitedAt,rateLimitedUntil:C?0:y.rateLimitedUntil}),nt(u.entry,m)&&T(p,t,y.id)})),x(t,i)})}r(fe,"commitManagedLogin");function Mt(t,n=Date.now()){if(!t?.trim())return;const e=Number(t.trim());if(Number.isFinite(e))return Math.max(0,Math.round(e*1e3));const a=Date.parse(t);return Number.isFinite(a)?Math.max(0,a-n):void 0}r(Mt,"parseRetryAfterHeader");function Ct(t){if(!t)return;const n=r(a=>t instanceof Headers?t.get(a)??void 0:Object.entries(t).find(([i])=>i.toLowerCase()===a)?.[1],"get"),e=n("retry-after-ms");return e!==void 0&&e.trim()!==""&&Number.isFinite(Number(e))?Math.max(0,Number(e)):Mt(n("retry-after"))}r(Ct,"retryAfterMsFromHeaders");function he(t){if(!t||typeof t!="object"||!("headers"in t))return;const n=t.headers;if(!(!(n instanceof Headers)&&(!n||typeof n!="object"||Array.isArray(n))))return Ct(n)}r(he,"retryAfterMsFromError");function kt(){const t=ht();if(t)return t.rotation;const n=g(At(yt(f())),"SELECT default_fallback_strength,revert_when_available FROM rotation_settings WHERE singleton=1").get();return{defaultFallbackStrength:Y(n?.default_fallback_strength)??Q,revertWhenAvailable:n?.revert_when_available===void 0||n.revert_when_available===null?!0:!!n.revert_when_available}}r(kt,"readRotationConfig");function be(t){const n=kt(),e={defaultFallbackStrength:Y(t.defaultFallbackStrength)??n.defaultFallbackStrength??Q,revertWhenAvailable:t.revertWhenAvailable??n.revertWhenAvailable??!0};return A(f(),a=>g(a,"INSERT INTO rotation_settings(singleton,default_fallback_strength,revert_when_available) VALUES(1,?,?) ON CONFLICT(singleton) DO UPDATE SET default_fallback_strength=excluded.default_fallback_strength,revert_when_available=excluded.revert_when_available").run(e.defaultFallbackStrength,e.revertWhenAvailable?1:0)),e}r(be,"writeRotationConfig");function pe(t,n=Date.now(),e){const a=D(t),i=a.filter(s=>s.authFailure===void 0&&Rt(s,e)<=n),o=b(t);return i.length===0?`${o} pool exhausted`:`${o} ${i[0]?.label??t} (${i.length}/${a.length} ready)`}r(pe,"formatStatusLine");export{H as ANTHROPIC_PROVIDER_ID,w as DuplicateSubscriptionError,Et as INVALID_REFRESH_TOKEN_BACKOFF_MS,Jt as MANAGED_PROVIDER_IDS,K as MAX_RATE_LIMIT_COOLDOWN_MS,J as OPENAI_CHATGPT_PROVIDER_ID,z as OPENAI_CODEX_PROVIDER_ID,wt as activeCooldowns,$t as addSubscription,fe as commitManagedLogin,Rt as coolingUntilFor,Dt as enrichManagedLoginIdentity,Qt as formatCooldowns,pe as formatStatusLine,b as getProviderLabel,ct as isInvalidRefreshTokenError,Yt as isManagedProvider,ce as markSubscriptionAttempt,le as markSubscriptionRateLimited,ue as markSubscriptionSuccess,me as modifyElectedSubscription,Zt as openAIDeviceId,Mt as parseRetryAfterHeader,se as promoteSubscription,kt as readRotationConfig,D as readSubscriptionPool,te as readSubscriptionPoolRows,de as refreshSubscriptionCredential,Ut as removeAllManagedAccounts,Nt as removeManagedAccount,ie as removeManagedAccountById,oe as removeManagedProvider,re as removeSubscription,ae as renameSubscription,vt as resolveProviderCandidates,he as retryAfterMsFromError,Ct as retryAfterMsFromHeaders,Xt as subscriptionNeedsSuccessWrite,ne as upsertSubscription,St as upsertSubscriptionWithUniqueAccount,be as writeRotationConfig,ee as writeSubscriptionPool};
|
|
1
|
+
var _t=Object.defineProperty;var l=(t,a)=>_t(t,"name",{value:a,configurable:!0});import{createHash as ht,randomUUID as x}from"node:crypto";import{brokerConfigSnapshot as pt}from"./config.js";import{openDb as P,withCanvasWrite as N}from"./canvas/db.js";import{personIdAsync as y}from"./canvas/person.js";import{loadSecretsKey as K,open as X,seal as $}from"./secrets/index.js";import{modelCooldownFamily as wt}from"./rate-limit-scope.js";import{registerRotationReader as At}from"./model-routes.js";import{coolingUntilFor as bt,getProviderLabel as h,isInvalidRefreshTokenError as Y,DuplicateSubscriptionError as O,ANTHROPIC_PROVIDER_ID as yt,MAX_RATE_LIMIT_COOLDOWN_MS as B,INVALID_REFRESH_TOKEN_BACKOFF_MS as Et}from"./managed-providers.js";export*from"./managed-providers.js";const J="strong";function Q(t){return t==="ultra"||t==="strong"||t==="medium"||t==="light"?t:void 0}l(Q,"normalizeStrength");function _(t){return t.toLowerCase()}l(_,"key");function j(t){return typeof t=="string"&&t.trim()?t.trim():void 0}l(j,"optionalString");function Lt(t){const a=typeof t.label=="string"?t.label.trim():"",e=typeof t.refresh=="string"?t.refresh.trim():"",n=typeof t.access=="string"?t.access.trim():"",i=Number(t.expires);if(!a||!e||!n||!Number.isFinite(i))return;const r=j(t.accountId),s=j(t.clientId);return{label:a,refresh:e,access:n,expires:i,rateLimitedUntil:Number.isFinite(Number(t.rateLimitedUntil))?Number(t.rateLimitedUntil):0,lastAttemptAt:Number.isFinite(Number(t.lastAttemptAt))?Number(t.lastAttemptAt):0,lastRateLimitedAt:Number.isFinite(Number(t.lastRateLimitedAt))?Number(t.lastRateLimitedAt):0,...t.authFailure==="invalid_grant"?{authFailure:"invalid_grant"}:{},...r?{accountId:r}:{},...s?{clientId:s}:{},...Z(t.modelCooldowns)?{modelCooldowns:Z(t.modelCooldowns)}:{}}}l(Lt,"credential");function Z(t){if(!t||typeof t!="object"||Array.isArray(t))return;const a=Object.entries(t).filter(([e,n])=>e.trim()!==""&&Number.isFinite(Number(n))).map(([e,n])=>[e,Number(n)]);return a.length?Object.fromEntries(a):void 0}l(Z,"modelCooldowns");function F(t,a){if(!a.label?.trim())throw new Error(`${h(t)} subscription label cannot be empty`);const e=Lt(a);if(!e)throw new Error(`Refusing to persist incomplete ${h(t)} subscription "${a.label.trim()}"; pool rows require both OAuth tokens.`);return e}l(F,"assertCredential");function v(t,a){const e=t.accountId?.trim(),n=a.accountId?.trim();return!!(e&&n&&e!==n)}l(v,"differentAccount");function p(t){return t.accountId?.trim()||(t.refresh.trim()?`refresh:${ht("sha256").update(t.refresh.trim()).digest("hex")}`:void 0)}l(p,"identity");function tt(t,a){const e=j(a);return e?{...t,clientId:e}:t}l(tt,"withClientId");function et(t,a,e){const n=e.refresh?.trim()??"",i=e.access?.trim()??"",r=Number(e.expires);if(!n||!i||!Number.isFinite(r))throw new Error(`${h(t)} subscription "${a}" returned an incomplete credential; the stored credential was left unchanged.`);return{refresh:n,access:i,expires:r}}l(et,"assertTokens");const at=1e4,Rt="15s",gt="55P03";class nt extends Error{static{l(this,"RefreshBusyError")}constructor(a,e){super(`${h(a)} subscription "${e}" is being refreshed by another process; treating it as cooling for this call`),this.name="RefreshBusyError"}}const it="id,label,label_key,position,last_attempt_at,last_rate_limited_at,rate_limited_until,auth_failure,refresh_sealed,access_sealed,expires,vendor_account_id,client_id,key_id",I=l((t,a,e,n)=>`model_accounts|${t}|${a}|${e}|${n}`,"aadOf");function E(t){return{refresh:t.refresh,access:t.access,expires:t.expires,...t.accountId?{accountId:t.accountId}:{},...t.clientId?{clientId:t.clientId}:{}}}l(E,"stored");function It(t,a){return{providerId:t,id:a.id,label:a.label,labelKey:a.label_key,position:a.position,lastAttemptAt:a.last_attempt_at,lastRateLimitedAt:a.last_rate_limited_at,rateLimitedUntil:a.rate_limited_until,...a.auth_failure?{authFailure:a.auth_failure}:{}}}l(It,"rowOf");function rt(t,a,e,n=[]){if(!e.refresh_sealed||!e.access_sealed||e.expires===null||!e.key_id)throw new Error(`managed ${a} account ${e.id} has no credential record`);const i=K(),r=X(e.refresh_sealed,e.key_id,i,I(t,a,e.id,"refresh")),s=X(e.access_sealed,e.key_id,i,I(t,a,e.id,"access")),o=It(a,e),c={label:o.label,refresh:r,access:s,expires:e.expires,rateLimitedUntil:o.authFailure||!o.lastRateLimitedAt?o.rateLimitedUntil:Math.min(o.rateLimitedUntil,o.lastRateLimitedAt+B),lastAttemptAt:o.lastAttemptAt,lastRateLimitedAt:o.lastRateLimitedAt,...o.authFailure?{authFailure:o.authFailure}:{},...e.vendor_account_id?{accountId:e.vendor_account_id}:{},...e.client_id?{clientId:e.client_id}:{},...n.length?{modelCooldowns:Object.fromEntries(n.map(d=>[d.family,d.lastRateLimitedAt?Math.min(d.rateLimitedUntil,d.lastRateLimitedAt+B):d.rateLimitedUntil]))}:{}};return{row:o,entry:c}}l(rt,"toPublic");async function S(t,a,e){const n=new Map,i=await t.prepare("SELECT account_id,family,rate_limited_until,last_rate_limited_at FROM model_account_cooldowns WHERE person=? AND provider_id=? ORDER BY family").all(a,e);for(const r of i){const s=n.get(r.account_id)??[];s.push({family:r.family,rateLimitedUntil:r.rate_limited_until,lastRateLimitedAt:r.last_rate_limited_at}),n.set(r.account_id,s)}return n}l(S,"loadCooldowns");async function k(t,a,e,n=!1){const i=await t.prepare(`SELECT ${it} FROM model_accounts WHERE person=? AND provider_id=? ORDER BY position${n?" FOR UPDATE":""}`).all(a,e),r=await S(t,a,e);return i.map(s=>rt(a,e,s,r.get(s.id)))}l(k,"loadPool");async function st(t,a,e,n){const i=n.trim().toLowerCase(),r=Number.parseInt(i,10),s=Number.isFinite(r)&&String(r)===i&&r>=1,o=await t.prepare(`SELECT ${it} FROM model_accounts WHERE person=? AND provider_id=? AND ${s?"position=?":"label_key=?"} FOR UPDATE`).get(a,e,s?r-1:i);if(o)return rt(a,e,o,(await S(t,a,e)).get(o.id))}l(st,"lockedAccount");async function T(t){await t.exec(`SET LOCAL lock_timeout = '${Rt}'`)}l(T,"setLockTimeout");async function L(t,a){const e=await y();return N(async n=>(await T(n),await n.prepare("SELECT pg_advisory_xact_lock(hashtext(?))").get(`model_accounts|${e}|${t}`),a({db:n,person:e,rows:await k(n,e,t,!0)})))}l(L,"locked");async function C(t,a,e,n,i){const r=K(),s=$(i.refresh,r,I(a,e,n.id,"refresh")),o=$(i.access,r,I(a,e,n.id,"access"));await t.prepare("INSERT INTO model_accounts(person,provider_id,id,label,label_key,position,last_attempt_at,last_rate_limited_at,rate_limited_until,auth_failure,refresh_sealed,access_sealed,expires,vendor_account_id,client_id,key_id) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)").run(a,e,n.id,n.label,n.labelKey,n.position,n.lastAttemptAt,n.lastRateLimitedAt,n.rateLimitedUntil,n.authFailure??null,s.sealed,o.sealed,i.expires,i.accountId??null,i.clientId??null,s.keyId)}l(C,"insertAccount");async function M(t,a,e,n,i){const r=K(),s=$(i.refresh,r,I(a,e,n,"refresh")),o=$(i.access,r,I(a,e,n,"access"));await t.prepare("UPDATE model_accounts SET refresh_sealed=?,access_sealed=?,expires=?,vendor_account_id=?,client_id=?,key_id=? WHERE person=? AND provider_id=? AND id=?").run(s.sealed,o.sealed,i.expires,i.accountId??null,i.clientId??null,s.keyId,a,e,n)}l(M,"setCredential");async function b(t,a,e){await t.prepare("UPDATE model_accounts SET label=?,label_key=?,position=?,last_attempt_at=?,last_rate_limited_at=?,rate_limited_until=?,auth_failure=? WHERE person=? AND provider_id=? AND id=?").run(e.label,e.labelKey,e.position,e.lastAttemptAt,e.lastRateLimitedAt,e.rateLimitedUntil,e.authFailure??null,a,e.providerId,e.id)}l(b,"updateHealth");async function ot(t,a,e,n,i,r,s){await t.prepare("INSERT INTO model_account_cooldowns(person,provider_id,account_id,family,rate_limited_until,last_rate_limited_at) VALUES(?,?,?,?,?,?) ON CONFLICT(person,provider_id,account_id,family) DO UPDATE SET rate_limited_until=excluded.rate_limited_until,last_rate_limited_at=excluded.last_rate_limited_at").run(a,e,n,i,r,s)}l(ot,"upsertModelCooldown");async function D(t,a,e,n){n===void 0?await t.prepare("DELETE FROM model_account_cooldowns WHERE person=? AND provider_id=?").run(a,e):await t.prepare("DELETE FROM model_account_cooldowns WHERE person=? AND provider_id=? AND account_id=?").run(a,e,n)}l(D,"deleteModelCooldowns");const R=l(async({db:t,person:a},e)=>(await k(t,a,e)).map(({entry:n})=>n),"publicPool"),lt=l(t=>t?.code===gt,"lockWaitExpired");function ct(t,a){let e;return Promise.race([a,new Promise((n,i)=>{e=setTimeout(()=>i(new Error(`${t} did not answer within ${at} ms`)),at)})]).finally(()=>clearTimeout(e))}l(ct,"withExchangeTimeout");async function V(t){return(await xt(t)).map(({entry:a})=>a)}l(V,"readSubscriptionPool");async function xt(t){const a=await y();return(await k(await P(),a,t)).map(({row:e,entry:n})=>({id:e.id,entry:n}))}l(xt,"readSubscriptionPoolRows");async function jt(t,a){return L(t,async e=>{const{db:n,person:i,rows:r}=e,s=a.map(d=>F(t,d)),o=s.map((d,u)=>({entry:d,id:r[u]?.row.id??x()})),c=await S(n,i,t);await n.prepare("DELETE FROM model_accounts WHERE person=? AND provider_id=?").run(i,t),await D(n,i,t);for(const[d,{entry:u,id:m}]of o.entries()){await C(n,i,t,{providerId:t,id:m,label:u.label,labelKey:_(u.label),position:d,lastAttemptAt:u.lastAttemptAt,lastRateLimitedAt:u.lastRateLimitedAt,rateLimitedUntil:u.rateLimitedUntil,...u.authFailure?{authFailure:u.authFailure}:{}},E(u));for(const[f,A]of Object.entries(u.modelCooldowns??{}))await ot(n,i,t,m,f,A,c.get(m)?.find(U=>U.family===f)?.lastRateLimitedAt??u.lastRateLimitedAt)}return s})}l(jt,"writeSubscriptionPool");function W(t,a){const e=a.trim().toLowerCase(),n=Number.parseInt(e,10);return Number.isFinite(n)&&String(n)===e&&n>=1&&n<=t.length?n-1:t.findIndex(({entry:i})=>_(i.label)===e)}l(W,"resolve");const H=l((t,a)=>new O(`This ${h(t)} account is already added as \u201C${a}\u201D \u2014 it shares the same quota, so a second slot adds no redundancy.`),"duplicateAccount");async function Nt(t,a){const e=F(t,a);return L(t,async n=>{const{db:i,person:r,rows:s}=n;if(s.some(({entry:d})=>_(d.label)===_(e.label)))throw new O(`${h(t)} subscription already exists: ${e.label}`);const o=p(e),c=s.find(({entry:d})=>p(d)===o);if(o&&c)throw H(t,c.entry.label);return await C(i,r,t,{providerId:t,id:x(),label:e.label,labelKey:_(e.label),position:s.length,lastAttemptAt:e.lastAttemptAt,lastRateLimitedAt:e.lastRateLimitedAt,rateLimitedUntil:e.rateLimitedUntil,...e.authFailure?{authFailure:e.authFailure}:{}},E(e)),R(n,t)})}l(Nt,"addSubscription");async function Vt(t,a){const e=F(t,a);return(await V(t)).find(i=>_(i.label)===_(e.label))?Ft(t,e):Nt(t,e)}l(Vt,"upsertSubscription");async function Ft(t,a){const e=F(t,a);return L(t,async n=>{const{db:i,person:r,rows:s}=n,o=s.findIndex(({entry:f})=>_(f.label)===_(e.label)),c=s[o],d=s.find(({entry:f},A)=>A!==o&&p(f)===p(e));if(p(e)&&d)throw H(t,d.entry.label);if(!c)return await C(i,r,t,{providerId:t,id:x(),label:e.label,labelKey:_(e.label),position:s.length,lastAttemptAt:e.lastAttemptAt,lastRateLimitedAt:e.lastRateLimitedAt,rateLimitedUntil:e.rateLimitedUntil},E(e)),R(n,t);const u=c.row,m=e.lastRateLimitedAt>=u.lastRateLimitedAt;return await M(i,r,t,u.id,E(e)),await b(i,r,{...u,authFailure:void 0,label:e.label,labelKey:_(e.label),lastAttemptAt:Math.max(u.lastAttemptAt,e.lastAttemptAt),lastRateLimitedAt:m?e.lastRateLimitedAt:u.lastRateLimitedAt,rateLimitedUntil:m?e.rateLimitedUntil:u.rateLimitedUntil}),v(c.entry,e)&&await D(i,r,t,u.id),R(n,t)})}l(Ft,"upsertSubscriptionWithUniqueAccount");async function Gt(t,a,e){return L(t,async n=>{const{db:i,person:r,rows:s}=n,o=W(s,a);if(o<0)throw new Error(`Unknown ${h(t)} subscription: ${a}`);const c=e.trim();if(!c)throw new Error(`${h(t)} subscription label cannot be empty`);if(s.some((d,u)=>u!==o&&_(d.entry.label)===_(c)))throw new O(`${h(t)} subscription already exists: ${c}`);return await b(i,r,{...s[o].row,label:c,labelKey:_(c)}),R(n,t)})}l(Gt,"renameSubscription");async function G(t,a,e){return L(t,async n=>{const{db:i,person:r,rows:s}=n,o=a(s);if(o<0)throw new Error(`Unknown ${h(t)} subscription: ${e}`);const c=s[o].row;return await i.prepare("DELETE FROM model_accounts WHERE person=? AND provider_id=? AND id=?").run(r,t,c.id),await D(i,r,t,c.id),R(n,t)})}l(G,"remove");async function St(t,a){return G(t,e=>W(e,a),a)}l(St,"removeManagedAccount");async function zt(t,a){return G(t,e=>e.findIndex(({row:n})=>n.id===a),a)}l(zt,"removeManagedAccountById");async function qt(t,a){return G(t,e=>W(e,a),a)}l(qt,"removeSubscription");async function Tt(t){return L(t,async({db:a,person:e,rows:n})=>(await a.prepare("DELETE FROM model_accounts WHERE person=? AND provider_id=?").run(e,t),await D(a,e,t),n.length))}l(Tt,"removeAllManagedAccounts");async function Xt(t,a){return a===void 0?(await Tt(t),[]):St(t,a)}l(Xt,"removeManagedProvider");async function Yt(t,a){return L(t,async e=>{const{db:n,person:i,rows:r}=e,s=W(r,a);if(s<0)throw new Error(`Unknown ${h(t)} subscription: ${a}`);const o=[r[s],...r.filter((c,d)=>d!==s)];for(const[c,d]of o.entries())await b(n,i,{...d.row,position:c});return R(e,t)})}l(Yt,"promoteSubscription");async function z(t,a,e){const n=await y();return await N(async i=>{await T(i);const r=await st(i,n,t,a);if(!r)throw new Error(`Unknown ${h(t)} subscription: ${a}`);await e(i,n,r.row)}),V(t)}l(z,"healthWrite");async function Jt(t,a,e=Date.now()){return z(t,a,(n,i,r)=>b(n,i,{...r,lastAttemptAt:Math.max(r.lastAttemptAt,e)}))}l(Jt,"markSubscriptionAttempt");async function Qt(t,a,e,n=Date.now(),i=Date.now(),r={kind:"account"}){return e=Math.min(Math.max(0,e),B),z(t,a,async(s,o,c)=>{if(r.kind==="account"){if(i<c.lastRateLimitedAt)return;await b(s,o,{...c,lastAttemptAt:Math.max(c.lastAttemptAt,n),lastRateLimitedAt:i,rateLimitedUntil:i+e});return}await b(s,o,{...c,lastAttemptAt:Math.max(c.lastAttemptAt,n)});const d=(await S(s,o,t)).get(c.id)?.find(u=>u.family===r.family);d&&i<d.lastRateLimitedAt||await ot(s,o,t,c.id,r.family,i+e,i)})}l(Qt,"markSubscriptionRateLimited");async function Zt(t,a,e=Date.now(),n){const i=wt(n);return z(t,a,async(r,s,o)=>{if(e>=o.lastRateLimitedAt&&await b(r,s,{...o,authFailure:void 0,lastAttemptAt:Math.max(o.lastAttemptAt,e),rateLimitedUntil:0}),i===void 0)return;const c=(await S(r,s,t)).get(o.id)?.find(d=>d.family===i);c&&e>=c.lastRateLimitedAt&&await r.prepare("DELETE FROM model_account_cooldowns WHERE person=? AND provider_id=? AND account_id=? AND family=?").run(s,t,o.id,i)})}l(Zt,"markSubscriptionSuccess");async function ut(t,a,e){const n=Date.now();await b(t,a,{...e,authFailure:"invalid_grant",lastAttemptAt:Math.max(e.lastAttemptAt,n),rateLimitedUntil:Math.max(e.rateLimitedUntil,n+Et)})}l(ut,"recordInvalidGrant");async function vt(t,a,e){const n=await y();let i;try{i=await N(async r=>{await T(r);const s=await st(r,n,t,a);if(!s)throw new Error(`${h(t)} subscription "${a}" no longer exists`);if(s.entry.expires>Date.now())return{entry:s.entry};if(s.row.authFailure)throw new Error(`${h(t)} subscription "${s.entry.label}" refresh refused with status=400 invalid_grant; it needs a new sign-in`);let o;try{o=await ct(`${h(t)} refresh`,e(s.entry.refresh,s.entry.clientId))}catch(d){if(!Y(d))throw d;return await ut(r,n,s.row),{refused:d}}const c=tt(et(t,s.entry.label,o),o.clientId??s.entry.clientId);return await M(r,n,t,s.row.id,E({...s.entry,...c})),{entry:{...s.entry,...c}}})}catch(r){throw lt(r)?new nt(t,a):r}if("refused"in i)throw i.refused;return i.entry}l(vt,"refreshSubscriptionCredential");async function te(t,a,e){const n=await y();let i;try{i=await N(async r=>{await T(r);const s=await k(r,n,t,!0),o=new Set;let c;for(;o.size<s.length;){const d=a(s.filter(({entry:m})=>!o.has(m.label)).map(({entry:m})=>m));if(!d)break;const u=s.find(({entry:m})=>m.label===d.label);o.add(u.entry.label);try{const m=await ct(`${h(t)} refresh`,e(u.entry));if(!m)return{entry:u.entry};const f=tt(et(t,u.entry.label,m),m.clientId??u.entry.clientId);return await M(r,n,t,u.row.id,E({...u.entry,...f})),{entry:{...u.entry,...f}}}catch(m){if(!Y(m))throw m;c=m,await ut(r,n,u.row)}}return c?{refused:c}:{}})}catch(r){throw lt(r)?new nt(t,a([])?.label??t):r}if("refused"in i)throw i.refused;return i.entry}l(te,"modifyElectedSubscription");async function Dt(t,a){const e=a.accountId?.trim(),n=a.email?.trim();if(t!==yt)return{...e?{accountId:e}:{},...n?{email:n}:{}};try{const i=await fetch("https://api.anthropic.com/api/oauth/profile",{headers:{Authorization:`Bearer ${a.access}`,Accept:"application/json"},signal:AbortSignal.timeout(3e3)});if(!i.ok)return e?{accountId:e}:{};const r=await i.json(),s=typeof r.account?.uuid=="string"&&r.account.uuid.trim()?r.account.uuid.trim():void 0,o=typeof r.account?.email=="string"&&r.account.email.trim()?r.account.email.trim():void 0;return{...s?{accountId:s}:{},...o?{email:o}:{}}}catch{return e?{accountId:e}:{}}}l(Dt,"enrichManagedLoginIdentity");async function ee(t,a,e){const n=await Dt(t,e);return L(t,async i=>{const{db:r,person:s,rows:o}=i,c=e.autoLabel?void 0:a?.trim(),d=p({refresh:e.refresh,accountId:n.accountId}),u=(c?o.find(({entry:w})=>_(w.label)===_(c)):void 0)??o.find(({entry:w})=>p(w)===d);let m=u?.entry.label??c;if(!m&&e.autoLabel){const w=n.email||a?.trim()||`Account ${o.length+1}`;m=w;for(let g=2;o.some(({entry:ft})=>_(ft.label)===_(m));g++)m=`${w} (${g})`}if(!m)throw new Error(`${h(t)} subscription label cannot be empty`);const f=F(t,{label:m,refresh:e.refresh,access:e.access,expires:e.expires,...n.accountId?{accountId:n.accountId}:{},...e.clientId?{clientId:e.clientId}:{},rateLimitedUntil:0,lastAttemptAt:Date.now(),lastRateLimitedAt:e.lastRateLimitedAt});if(!u){if(o.some(({entry:g})=>_(g.label)===_(f.label)))throw new O(`${h(t)} subscription already exists: ${f.label}`);const w=o.find(({entry:g})=>p(g)===p(f));if(p(f)&&w)throw H(t,w.entry.label);return await C(r,s,t,{providerId:t,id:x(),label:f.label,labelKey:_(f.label),position:o.length,lastAttemptAt:f.lastAttemptAt,lastRateLimitedAt:f.lastRateLimitedAt,rateLimitedUntil:f.rateLimitedUntil},E(f)),R(i,t)}const A=u.row,U=o.find(({entry:w})=>w.label!==u.entry.label&&p(w)===p(f));if(p(f)&&U)throw H(t,U.entry.label);const q=f.lastRateLimitedAt>=A.lastRateLimitedAt;return await M(r,s,t,A.id,E(f)),await b(r,s,{...A,authFailure:void 0,lastAttemptAt:Math.max(A.lastAttemptAt,f.lastAttemptAt),lastRateLimitedAt:q?f.lastRateLimitedAt:A.lastRateLimitedAt,rateLimitedUntil:q?0:A.rateLimitedUntil}),v(u.entry,f)&&await D(r,s,t,A.id),R(i,t)})}l(ee,"commitManagedLogin");const dt=new Map;function mt(t){return{defaultFallbackStrength:Q(t?.default_fallback_strength)??J,revertWhenAvailable:t?.revert_when_available===void 0||t.revert_when_available===null?!0:!!t.revert_when_available}}l(mt,"rotationFromRow");async function Ut(){const t=await y(),a=mt(await(await P()).prepare("SELECT default_fallback_strength,revert_when_available FROM model_settings WHERE person=?").get(t));return dt.set(t,a),a}l(Ut,"loadRotationConfig"),At(()=>$t());async function $t(){const t=pt();return t?t.rotation:Ut()}l($t,"readRotationConfig");async function ae(t){const a=await y(),e=await N(async n=>{await T(n),await n.prepare("INSERT INTO model_settings(person) VALUES(?) ON CONFLICT(person) DO NOTHING").run(a);const i=mt(await n.prepare("SELECT default_fallback_strength,revert_when_available FROM model_settings WHERE person=? FOR UPDATE").get(a)),r={defaultFallbackStrength:Q(t.defaultFallbackStrength)??i.defaultFallbackStrength??J,revertWhenAvailable:t.revertWhenAvailable??i.revertWhenAvailable??!0};return await n.prepare("UPDATE model_settings SET default_fallback_strength=?,revert_when_available=?,revision=revision+1 WHERE person=?").run(r.defaultFallbackStrength,r.revertWhenAvailable?1:0,a),r});return dt.set(a,e),e}l(ae,"writeRotationConfig");async function ne(){const t=await y();return(await(await P()).prepare("INSERT INTO model_settings(person,openai_device_id) VALUES(?,?) ON CONFLICT(person) DO UPDATE SET openai_device_id=COALESCE(model_settings.openai_device_id,EXCLUDED.openai_device_id) RETURNING openai_device_id").get(t,x())).openai_device_id}l(ne,"openAIDeviceId");async function ie(t,a=Date.now(),e){const n=await V(t),i=n.filter(s=>s.authFailure===void 0&&bt(s,e)<=a),r=h(t);return i.length===0?`${r} pool exhausted`:`${r} ${i[0]?.label??t} (${i.length}/${n.length} ready)`}l(ie,"formatStatusLine");export{at as REFRESH_EXCHANGE_TIMEOUT_MS,nt as RefreshBusyError,Nt as addSubscription,ee as commitManagedLogin,Dt as enrichManagedLoginIdentity,ie as formatStatusLine,C as insertAccount,Ut as loadRotationConfig,Jt as markSubscriptionAttempt,Qt as markSubscriptionRateLimited,Zt as markSubscriptionSuccess,te as modifyElectedSubscription,ne as openAIDeviceId,Yt as promoteSubscription,$t as readRotationConfig,V as readSubscriptionPool,xt as readSubscriptionPoolRows,vt as refreshSubscriptionCredential,Tt as removeAllManagedAccounts,St as removeManagedAccount,zt as removeManagedAccountById,Xt as removeManagedProvider,qt as removeSubscription,Gt as renameSubscription,ot as upsertModelCooldown,Vt as upsertSubscription,Ft as upsertSubscriptionWithUniqueAccount,ae as writeRotationConfig,jt as writeSubscriptionPool};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
var p=Object.defineProperty;var d=(e,i)=>p(e,"name",{value:i,configurable:!0});import{dirname as h}from"node:path";import{parseFrontmatterGeneric as w}from"../../frontmatter.js";import{readText as g,realpathOrSelf as R}from"../../fs-utils.js";import{checkoutChain as b}from"../../graph/repo-sync/identity.js";import{minRung as k,rungAtLeast as N,rungRank as m}from"../schema.js";import{ruleConstraintsFit as O,ruleGate as F}from"./match.js";function E(e){return e.doc.ownNode?"knowledge":e.doc.kind}d(E,"bootPartitionOf");async function L(e,i,t,a,n,o={}){const r=await v(e,n,o),c=(n==="document-read"&&o.doc!==void 0?a.filter(u=>u.object.id!==o.doc.object.id):a).map(u=>j(u,i,n,r));return W(n,c),{on:n,subject:i,reader:t,docs:c}}d(L,"planDelivery");async function v(e,i,t){if(i!=="file-read"||t.absoluteFile===void 0)return t;const a=R(t.absoluteFile);return{...t,absoluteFile:a,readFrontmatter:t.readFrontmatter??x(a),repoRoots:await y(e,a)}}d(v,"resolvePayload");function x(e){if(!/\.(md|mdx|markdown)$/i.test(e))return{};try{return w(g(e)).data??{}}catch{return{}}}d(x,"readFileFrontmatter");async function y(e,i){const t=new Map,a=e.prepare(`SELECT o.id FROM identities i JOIN objects o ON o.id = i.object
|
|
2
|
-
WHERE o.type = 'repo' AND i.scheme = ? AND i.external_id = ?`);for(const o of b(h(i))){if(!o.ok)break;const r=await a.get(o.scheme,o.externalId);r!==void 0&&!t.has(r.id)&&t.set(r.id,o.root)}const n=await e.prepare(`SELECT o.id, i.external_id AS path FROM identities i JOIN objects o ON o.id = i.object
|
|
2
|
+
WHERE o.type = 'repo' AND i.scheme = ? AND i.external_id = ?`);for(const o of await b(h(i))){if(!o.ok)break;const r=await a.get(o.scheme,o.externalId);r!==void 0&&!t.has(r.id)&&t.set(r.id,o.root)}const n=await e.prepare(`SELECT o.id, i.external_id AS path FROM identities i JOIN objects o ON o.id = i.object
|
|
3
3
|
WHERE o.type = 'repo' AND i.scheme = 'local-path'`).all();for(const{id:o,path:r}of n)!t.has(o)&&i.startsWith(r.endsWith("/")?r:`${r}/`)&&t.set(o,r);return t}d(y,"repoRootsOf");function j(e,i,t,a){const n=e.rules.filter(s=>s.on===t).map(s=>{const f=F(s,i);return{rule:s,gate:f,matched:f.pass&&O(s,e,t,a)}});let o=null;for(const{rule:s,matched:f}of n)f&&(o===null||m(s.deliver)>m(o.deliver))&&(o=s);const r=o?.deliver??"none",l=(t==="boot"||t==="workspace-open")&&!e.ownNode?e.limit:null,c=l===null?r:k(r,l),u=t==="boot"&&e.ownNode&&n.length===0?"name":c;return{doc:e,authoredRules:n,matchedRule:o,authoredRung:r,limit:l,cappedRung:c,ruleGate:n.length===0?null:o!==null?{pass:!0}:n.find(s=>!s.gate.pass)?.gate??{pass:!0},finalRung:u,winner:!1,shadowedBy:null}}d(j,"decide");function A(e,i){if(i==="boot"){const t=e.authoredRules.length>0&&e.authoredRules.every(a=>!a.gate.pass);return e.limit!=="none"&&!t}return N(e.finalRung,"name")}d(A,"holdsName");function W(e,i){const t=e==="boot"||e==="workspace-open",a=new Map;for(const n of i){if(!A(n,e))continue;if(!t){n.winner=!0;continue}const o=e==="boot"?`${E(n)}:${n.doc.name}`:n.doc.name,r=a.get(o);r===void 0?(a.set(o,n),n.winner=!0):n.shadowedBy=r.doc}}d(W,"resolveWinners");export{E as bootPartitionOf,L as planDelivery};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var v=Object.defineProperty;var n=(e,t)=>v(e,"name",{value:t,configurable:!0});import{CONDENSED_HISTORY_MODES as u,MOUSE_MODE_DEFAULTS as p,WHIP_MESSAGE_MODES as d}from"../types.js";function i(e,t,o){const s=e.indexOf(t),a=s>=0?s:0;return e[(a+o+e.length)%e.length]}n(i,"cycleChoice");function c(e,t,o){const s=e.indexOf(t);return s>=0?e[(s+o+e.length)%e.length]:o>=0?e.find(a=>a>t)??e[0]:[...e].reverse().find(a=>a<t)??e[e.length-1]}n(c,"cycleNumber");function r(e,t){return e==="true"?!0:e==="false"?!1:`${t} must be true or false`}n(r,"booleanFromString");function f(e,t){if(!/^\d+$/.test(e))return`${t} must be an integer >= 0`;const o=Number(e);return Number.isSafeInteger(o)?o:`${t} must be an integer >= 0`}n(f,"nonNegativeIntegerFromString");function _(e,t){const o=f(e,t);return typeof o=="string"||o<1?`${t} must be an integer >= 1`:o}n(_,"positiveIntegerFromString");const m=[!1,"notify","apply"],w=[0,1,6,12,24,48,72,168],b=[1,2,3,4,5,6,8,10,12],l="openai-codex";function g(e,t){const o=e.providerOptions[t];if(o!==void 0)return o;const s={};return e.providerOptions[t]=s,s}n(g,"providerOptionsFor");const x=[1,2,3,4,5,6],h={schema_version:{surface:"specialized",owner:"internal schema migration"},marketplaces:{surface:"specialized",owner:"Plugins and pkg market commands"},plugins:{surface:"specialized",owner:"Plugins tab and pkg plugin commands"},auto_update:{surface:"settings",settings:{crtr:{key:"auto_update.crtr",label:"crouter updates",description:"Notify about crouter releases, install them automatically, or turn checks off.",valueConstraint:"true|false|notify|apply; true stores notify",applies:"Applies on the next crouter command.",group:"updates",order:70,format:n(e=>e.auto_update.crtr===!1?"off":e.auto_update.crtr,"format"),cycle:n((e,t)=>{e.auto_update.crtr=i(m,e.auto_update.crtr,t)},"cycle"),setFromString:n((e,t)=>{const o=t==="true"?"notify":t;return o!=="notify"&&o!=="apply"&&o!=="false"?"auto_update.crtr must be notify, apply, or false":(e.auto_update.crtr=o==="false"?!1:o,null)},"setFromString")},content:{key:"auto_update.content",label:"Content updates",description:"Notify about plugin and marketplace updates, apply them automatically, or turn checks off.",valueConstraint:"false|notify|apply",applies:"Applies on the next crouter command.",group:"updates",order:80,format:n(e=>e.auto_update.content===!1?"off":e.auto_update.content,"format"),cycle:n((e,t)=>{e.auto_update.content=i(m,e.auto_update.content,t)},"cycle"),setFromString:n((e,t)=>t!=="notify"&&t!=="apply"&&t!=="false"?"auto_update.content must be notify, apply, or false":(e.auto_update.content=t==="false"?!1:t,null),"setFromString")},interval_hours:{key:"auto_update.interval_hours",label:"Update interval",description:"Minimum hours between automatic update checks. Zero checks on every command.",valueConstraint:"integer >= 0",applies:"Applies on the next crouter command.",group:"updates",order:90,format:n(e=>`${e.auto_update.interval_hours}h`,"format"),cycle:n((e,t)=>{e.auto_update.interval_hours=c(w,e.auto_update.interval_hours,t)},"cycle"),setFromString:n((e,t)=>{const o=f(t,"auto_update.interval_hours");return typeof o=="string"?o:(e.auto_update.interval_hours=o,null)},"setFromString")}}},max_panes_per_window:{surface:"settings",setting:{key:"max_panes_per_window",label:"Maximum panes",description:"Maximum human-review panes placed in one tmux window before using another window.",valueConstraint:"integer >= 1",applies:"Applies to the next pane placement.",group:"panes",order:20,format:n(e=>String(e.max_panes_per_window),"format"),cycle:n((e,t)=>{e.max_panes_per_window=c(b,e.max_panes_per_window,t)},"cycle"),setFromString:n((e,t)=>{const o=_(t,"max_panes_per_window");return typeof o=="string"?o:(e.max_panes_per_window=o,null)},"setFromString")}},auto_open_child_viewers:{surface:"settings",setting:{key:"auto_open_child_viewers",label:"Open child panes",description:"Open each managed child beside its watched parent. Off keeps new children running in the background.",valueConstraint:"true|false",applies:"Applies to the next managed child created; independent roots still open their attended viewer.",group:"panes",order:10,format:n(e=>e.auto_open_child_viewers?"on":"off","format"),cycle:n(e=>{e.auto_open_child_viewers=!e.auto_open_child_viewers},"cycle"),setFromString:n((e,t)=>{const o=r(t,"auto_open_child_viewers");return typeof o=="string"?o:(e.auto_open_child_viewers=o,null)},"setFromString")}},brokerThresholds:{surface:"specialized",owner:"Broker limits tab"},lifecycle:{surface:"specialized",owner:"sys config set lifecycle.unattendedParkMs"},completion_bell:{surface:"settings",setting:{key:"completion_bell",label:"Completion bell",description:"Ring a short sound when the node in an attached viewer finishes a turn.",valueConstraint:"true|false",applies:"Applies on the next turn end.",group:"display",order:41,format:n(e=>e.completion_bell?"on":"off","format"),cycle:n(e=>{e.completion_bell=!e.completion_bell},"cycle"),setFromString:n((e,t)=>{const o=r(t,"completion_bell");return typeof o=="string"?o:(e.completion_bell=o,null)},"setFromString")}},working_gerunds:{surface:"specialized",owner:"sys config set working_gerunds"},whip_mode:{surface:"settings",setting:{key:"whip_mode",label:"Whip mode",description:"Play the whip animation when you send a prompt and when a viewer opens for an agent with an initial prompt.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:39,format:n(e=>e.whip_mode?"on":"off","format"),cycle:n(e=>{e.whip_mode=!e.whip_mode},"cycle"),setFromString:n((e,t)=>{const o=r(t,"whip_mode");return typeof o=="string"?o:(e.whip_mode=o,null)},"setFromString")}},page_surface:{surface:"settings",setting:{key:"page_surface",label:"Page human surface",description:"This host reads pages in a browser rather than a terminal. Agents are told the page module runs as written, HTML pages are offered, and document review and live display leave the command tree.",valueConstraint:"true|false",applies:"Applies when human command help is assembled.",group:"display",order:37,format:n(e=>e.page_surface?"on":"off","format"),cycle:n(e=>{e.page_surface=!e.page_surface},"cycle"),setFromString:n((e,t)=>{const o=r(t,"page_surface");return typeof o=="string"?o:(e.page_surface=o,null)},"setFromString")}},whip_messages:{surface:"specialized",owner:"sys config set whip_messages"},whip_message_mode:{surface:"settings",setting:{key:"whip_message_mode",label:"Whip message",description:"What the whip action sends: a random line from whip_messages, or the fixed \u201CGo faster\u201D.",valueConstraint:d.join("|"),applies:"Applies on the next attach.",group:"display",order:40,format:n(e=>e.whip_message_mode==="go-faster"?"go faster":"random","format"),cycle:n((e,t)=>{e.whip_message_mode=i(d,e.whip_message_mode,t)},"cycle"),setFromString:n((e,t)=>d.includes(t)?(e.whip_message_mode=t,null):`whip_message_mode must be one of: ${d.join("|")}`,"setFromString")}},mouse_mode_default:{surface:"settings",setting:{key:"mouse_mode_default",label:"Default mouse mode",description:"Initial mouse wheel scrolling for each attached viewer.",valueConstraint:p.join("|"),applies:"Applies on the next attach.",group:"display",order:38,format:n(e=>e.mouse_mode_default==="tmux"?"follow tmux":e.mouse_mode_default,"format"),cycle:n((e,t)=>{e.mouse_mode_default=i(p,e.mouse_mode_default,t)},"cycle"),setFromString:n((e,t)=>p.includes(t)?(e.mouse_mode_default=t,null):`mouse_mode_default must be one of: ${p.join("|")}`,"setFromString")}},live_cycles:{surface:"settings",setting:{key:"live_cycles",label:"Live cycles",description:"Trailing refresh cycles rendered at full fidelity; older cycles condense to text.",valueConstraint:"integer >= 1",applies:"Applies on the next attach.",group:"display",order:50,format:n(e=>String(e.live_cycles),"format"),cycle:n((e,t)=>{e.live_cycles=c(x,e.live_cycles,t)},"cycle"),setFromString:n((e,t)=>{const o=_(t,"live_cycles");return typeof o=="string"?o:(e.live_cycles=o,null)},"setFromString")}},condensed_history:{surface:"settings",setting:{key:"condensed_history",label:"Condensed history",description:"Messages retained from condensed cycles. Tool calls are never kept.",valueConstraint:u.join("|"),applies:"Applies on the next attach.",group:"display",order:60,format:n(e=>e.condensed_history,"format"),cycle:n((e,t)=>{e.condensed_history=i(u,e.condensed_history,t)},"cycle"),setFromString:n((e,t)=>u.includes(t)?(e.condensed_history=t,null):`condensed_history must be one of: ${u.join("|")}`,"setFromString")}},bash_tool_purpose:{surface:"settings",setting:{key:"bash_tool_purpose",label:"Bash purpose field",description:"Expose the optional purpose label to agents in the bash tool schema. Off removes the field without disabling the bash valve.",valueConstraint:"true|false",applies:"Applies on the next node session.",group:"display",order:25,format:n(e=>e.bash_tool_purpose?"on":"off","format"),cycle:n(e=>{e.bash_tool_purpose=!e.bash_tool_purpose},"cycle"),setFromString:n((e,t)=>{const o=r(t,"bash_tool_purpose");return typeof o=="string"?o:(e.bash_tool_purpose=o,null)},"setFromString")}},fold_finished_tools:{surface:"settings",setting:{key:"fold_finished_tools",label:"Fold finished tools",description:"Fold every settled tool call to its call line. Toggle live with /fold-tools.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:30,format:n(e=>e.fold_finished_tools?"on":"off","format"),cycle:n(e=>{e.fold_finished_tools=!e.fold_finished_tools},"cycle"),setFromString:n((e,t)=>{const o=r(t,"fold_finished_tools");return typeof o=="string"?o:(e.fold_finished_tools=o,null)},"setFromString")}},summarize_tool_calls:{surface:"settings",setting:{key:"summarize_tool_calls",label:"Summarize tool calls",description:"Replace completed folded tool-call groups with a one-line broker summary when available.",valueConstraint:"true|false",applies:"Applies when the next visible message closes a tool-call group.",group:"display",order:35,format:n(e=>e.summarize_tool_calls?"on":"off","format"),cycle:n(e=>{e.summarize_tool_calls=!e.summarize_tool_calls},"cycle"),setFromString:n((e,t)=>{const o=r(t,"summarize_tool_calls");return typeof o=="string"?o:(e.summarize_tool_calls=o,null)},"setFromString")}},document_port:{surface:"settings",setting:{key:"document_port",label:"Document browser port",description:"Fixed localhost port where crtrd serves editable document pages.",valueConstraint:"1-65535",applies:"Applies after daemon handover and on the next attach.",group:"display",order:37.5,format:n(e=>String(e.document_port),"format"),cycle:n((e,t)=>{e.document_port=Math.max(1,Math.min(65535,e.document_port+t))},"cycle"),setFromString:n((e,t)=>{const o=Number(t);return!/^\d+$/.test(t)||!Number.isInteger(o)||o<1||o>65535?"document_port must be an integer from 1 to 65535":(e.document_port=o,null)},"setFromString")}},detailed_tool_recaps:{surface:"settings",setting:{key:"detailed_tool_recaps",label:"Detailed tool recaps",description:"Show each document read and edited file in folded tool recaps. Off shows a compact count line instead.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:36,format:n(e=>e.detailed_tool_recaps?"on":"off","format"),cycle:n(e=>{e.detailed_tool_recaps=!e.detailed_tool_recaps},"cycle"),setFromString:n((e,t)=>{const o=r(t,"detailed_tool_recaps");return typeof o=="string"?o:(e.detailed_tool_recaps=o,null)},"setFromString")}},consolidate_replies:{surface:"settings",setting:{key:"consolidate_replies",label:"Consolidate replies",description:"Experiment: show one rewritten agent reply per message you type, with the working folded behind it (/show-working).",valueConstraint:"true|false",applies:"Applies on the next attach; the broker reads it per turn.",group:"display",order:36.5,format:n(e=>e.consolidate_replies?"on":"off","format"),cycle:n(e=>{e.consolidate_replies=!e.consolidate_replies},"cycle"),setFromString:n((e,t)=>{const o=r(t,"consolidate_replies");return typeof o=="string"?o:(e.consolidate_replies=o,null)},"setFromString")}},keybindings:{surface:"specialized",owner:"Keybindings tab"},tmux_passthrough:{surface:"specialized",owner:"Keybindings tab"},providerOptions:{surface:"settings",settings:{"openai-codex.fastMode":{key:`providerOptions.${l}.fastMode`,label:"Codex fast mode",description:"Serve Codex turns at the ChatGPT priority tier: about 1.5x faster generation for about 2x the credits. Displayed cost does not reflect the premium.",valueConstraint:"true|false",applies:"Applies on each node's next turn.",group:"providers",order:40,format:n(e=>e.providerOptions[l]?.fastMode?"on":"off","format"),cycle:n(e=>{const t=g(e,l);t.fastMode=!t.fastMode},"cycle"),setFromString:n((e,t)=>{const o=r(t,`providerOptions.${l}.fastMode`);return typeof o=="string"?o:(g(e,l).fastMode=o,null)},"setFromString")}}},modelLadders:{surface:"specialized",owner:"Models tab"},modelRoutes:{surface:"specialized",owner:"Models route declarations"},modelRouting:{surface:"specialized",owner:"Models route declarations"},kinds:{surface:"specialized",owner:"Models tab and kind registry"},page_components:{surface:"specialized",owner:"Page component catalog: product-registered page component kinds"},remoteCanvas:{surface:"specialized",owner:"canvas config commands"},api:{surface:"specialized",owner:"sys connect"},paths:{surface:"specialized",owner:"runtime layout"},ledger:{surface:"specialized",owner:"money ledger (take_pct)"},store:{surface:"specialized",owner:"daemon conversation store"},runtime:{surface:"specialized",owner:"app-facing listener"},spawnEnv:{surface:"specialized",owner:"spawn environment allow-list"},bin:{surface:"specialized",owner:"bare-binary contributions on every node PATH"},humanActions:{surface:"specialized",owner:"scope-configured human completion actions"}},O=Object.keys(h);function S(){const e=[];for(const t of Object.values(h))t.surface==="settings"&&("setting"in t?e.push(t.setting):e.push(...Object.values(t.settings)));return e.sort((t,o)=>t.order-o.order)}n(S,"collectUserSettings");const y=S();function A(e){return y.find(t=>t.key===e)}n(A,"findUserSetting");function z(e){return y.filter(t=>t.group===e)}n(z,"userSettingsInGroup");export{h as CONFIG_SETTINGS_COVERAGE,O as SCOPE_CONFIG_KEYS,y as USER_SETTINGS,A as findUserSetting,z as userSettingsInGroup};
|
|
1
|
+
var v=Object.defineProperty;var n=(e,t)=>v(e,"name",{value:t,configurable:!0});import{CONDENSED_HISTORY_MODES as u,MOUSE_MODE_DEFAULTS as p,WHIP_MESSAGE_MODES as d}from"../types.js";function i(e,t,o){const s=e.indexOf(t),a=s>=0?s:0;return e[(a+o+e.length)%e.length]}n(i,"cycleChoice");function c(e,t,o){const s=e.indexOf(t);return s>=0?e[(s+o+e.length)%e.length]:o>=0?e.find(a=>a>t)??e[0]:[...e].reverse().find(a=>a<t)??e[e.length-1]}n(c,"cycleNumber");function r(e,t){return e==="true"?!0:e==="false"?!1:`${t} must be true or false`}n(r,"booleanFromString");function f(e,t){if(!/^\d+$/.test(e))return`${t} must be an integer >= 0`;const o=Number(e);return Number.isSafeInteger(o)?o:`${t} must be an integer >= 0`}n(f,"nonNegativeIntegerFromString");function _(e,t){const o=f(e,t);return typeof o=="string"||o<1?`${t} must be an integer >= 1`:o}n(_,"positiveIntegerFromString");const m=[!1,"notify","apply"],w=[0,1,6,12,24,48,72,168],b=[1,2,3,4,5,6,8,10,12],l="openai-codex";function g(e,t){const o=e.providerOptions[t];if(o!==void 0)return o;const s={};return e.providerOptions[t]=s,s}n(g,"providerOptionsFor");const x=[1,2,3,4,5,6],h={schema_version:{surface:"specialized",owner:"internal schema migration"},marketplaces:{surface:"specialized",owner:"Plugins and pkg market commands"},plugins:{surface:"specialized",owner:"Plugins tab and pkg plugin commands"},auto_update:{surface:"settings",settings:{crtr:{key:"auto_update.crtr",label:"crouter updates",description:"Notify about crouter releases, install them automatically, or turn checks off.",valueConstraint:"true|false|notify|apply; true stores notify",applies:"Applies on the next crouter command.",group:"updates",order:70,format:n(e=>e.auto_update.crtr===!1?"off":e.auto_update.crtr,"format"),cycle:n((e,t)=>{e.auto_update.crtr=i(m,e.auto_update.crtr,t)},"cycle"),setFromString:n((e,t)=>{const o=t==="true"?"notify":t;return o!=="notify"&&o!=="apply"&&o!=="false"?"auto_update.crtr must be notify, apply, or false":(e.auto_update.crtr=o==="false"?!1:o,null)},"setFromString")},content:{key:"auto_update.content",label:"Content updates",description:"Notify about plugin and marketplace updates, apply them automatically, or turn checks off.",valueConstraint:"false|notify|apply",applies:"Applies on the next crouter command.",group:"updates",order:80,format:n(e=>e.auto_update.content===!1?"off":e.auto_update.content,"format"),cycle:n((e,t)=>{e.auto_update.content=i(m,e.auto_update.content,t)},"cycle"),setFromString:n((e,t)=>t!=="notify"&&t!=="apply"&&t!=="false"?"auto_update.content must be notify, apply, or false":(e.auto_update.content=t==="false"?!1:t,null),"setFromString")},interval_hours:{key:"auto_update.interval_hours",label:"Update interval",description:"Minimum hours between automatic update checks. Zero checks on every command.",valueConstraint:"integer >= 0",applies:"Applies on the next crouter command.",group:"updates",order:90,format:n(e=>`${e.auto_update.interval_hours}h`,"format"),cycle:n((e,t)=>{e.auto_update.interval_hours=c(w,e.auto_update.interval_hours,t)},"cycle"),setFromString:n((e,t)=>{const o=f(t,"auto_update.interval_hours");return typeof o=="string"?o:(e.auto_update.interval_hours=o,null)},"setFromString")}}},max_panes_per_window:{surface:"settings",setting:{key:"max_panes_per_window",label:"Maximum panes",description:"Maximum human-review panes placed in one tmux window before using another window.",valueConstraint:"integer >= 1",applies:"Applies to the next pane placement.",group:"panes",order:20,format:n(e=>String(e.max_panes_per_window),"format"),cycle:n((e,t)=>{e.max_panes_per_window=c(b,e.max_panes_per_window,t)},"cycle"),setFromString:n((e,t)=>{const o=_(t,"max_panes_per_window");return typeof o=="string"?o:(e.max_panes_per_window=o,null)},"setFromString")}},auto_open_child_viewers:{surface:"settings",setting:{key:"auto_open_child_viewers",label:"Open child panes",description:"Open each managed child beside its watched parent. Off keeps new children running in the background.",valueConstraint:"true|false",applies:"Applies to the next managed child created; independent roots still open their attended viewer.",group:"panes",order:10,format:n(e=>e.auto_open_child_viewers?"on":"off","format"),cycle:n(e=>{e.auto_open_child_viewers=!e.auto_open_child_viewers},"cycle"),setFromString:n((e,t)=>{const o=r(t,"auto_open_child_viewers");return typeof o=="string"?o:(e.auto_open_child_viewers=o,null)},"setFromString")}},brokerThresholds:{surface:"specialized",owner:"Broker limits tab"},lifecycle:{surface:"specialized",owner:"sys config set lifecycle.unattendedParkMs"},completion_bell:{surface:"settings",setting:{key:"completion_bell",label:"Completion bell",description:"Ring a short sound when the node in an attached viewer finishes a turn.",valueConstraint:"true|false",applies:"Applies on the next turn end.",group:"display",order:41,format:n(e=>e.completion_bell?"on":"off","format"),cycle:n(e=>{e.completion_bell=!e.completion_bell},"cycle"),setFromString:n((e,t)=>{const o=r(t,"completion_bell");return typeof o=="string"?o:(e.completion_bell=o,null)},"setFromString")}},working_gerunds:{surface:"specialized",owner:"sys config set working_gerunds"},whip_mode:{surface:"settings",setting:{key:"whip_mode",label:"Whip mode",description:"Play the whip animation when you send a prompt and when a viewer opens for an agent with an initial prompt.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:39,format:n(e=>e.whip_mode?"on":"off","format"),cycle:n(e=>{e.whip_mode=!e.whip_mode},"cycle"),setFromString:n((e,t)=>{const o=r(t,"whip_mode");return typeof o=="string"?o:(e.whip_mode=o,null)},"setFromString")}},page_surface:{surface:"settings",setting:{key:"page_surface",label:"Page human surface",description:"This host reads pages in a browser rather than a terminal. Agents are told the page module runs as written, HTML pages are offered, and document review and live display leave the command tree.",valueConstraint:"true|false",applies:"Applies when human command help is assembled.",group:"display",order:37,format:n(e=>e.page_surface?"on":"off","format"),cycle:n(e=>{e.page_surface=!e.page_surface},"cycle"),setFromString:n((e,t)=>{const o=r(t,"page_surface");return typeof o=="string"?o:(e.page_surface=o,null)},"setFromString")}},whip_messages:{surface:"specialized",owner:"sys config set whip_messages"},whip_message_mode:{surface:"settings",setting:{key:"whip_message_mode",label:"Whip message",description:"What the whip action sends: a random line from whip_messages, or the fixed \u201CGo faster\u201D.",valueConstraint:d.join("|"),applies:"Applies on the next attach.",group:"display",order:40,format:n(e=>e.whip_message_mode==="go-faster"?"go faster":"random","format"),cycle:n((e,t)=>{e.whip_message_mode=i(d,e.whip_message_mode,t)},"cycle"),setFromString:n((e,t)=>d.includes(t)?(e.whip_message_mode=t,null):`whip_message_mode must be one of: ${d.join("|")}`,"setFromString")}},mouse_mode_default:{surface:"settings",setting:{key:"mouse_mode_default",label:"Default mouse mode",description:"Initial mouse wheel scrolling for each attached viewer.",valueConstraint:p.join("|"),applies:"Applies on the next attach.",group:"display",order:38,format:n(e=>e.mouse_mode_default==="tmux"?"follow tmux":e.mouse_mode_default,"format"),cycle:n((e,t)=>{e.mouse_mode_default=i(p,e.mouse_mode_default,t)},"cycle"),setFromString:n((e,t)=>p.includes(t)?(e.mouse_mode_default=t,null):`mouse_mode_default must be one of: ${p.join("|")}`,"setFromString")}},live_cycles:{surface:"settings",setting:{key:"live_cycles",label:"Live cycles",description:"Trailing refresh cycles rendered at full fidelity; older cycles condense to text.",valueConstraint:"integer >= 1",applies:"Applies on the next attach.",group:"display",order:50,format:n(e=>String(e.live_cycles),"format"),cycle:n((e,t)=>{e.live_cycles=c(x,e.live_cycles,t)},"cycle"),setFromString:n((e,t)=>{const o=_(t,"live_cycles");return typeof o=="string"?o:(e.live_cycles=o,null)},"setFromString")}},condensed_history:{surface:"settings",setting:{key:"condensed_history",label:"Condensed history",description:"Messages retained from condensed cycles. Tool calls are never kept.",valueConstraint:u.join("|"),applies:"Applies on the next attach.",group:"display",order:60,format:n(e=>e.condensed_history,"format"),cycle:n((e,t)=>{e.condensed_history=i(u,e.condensed_history,t)},"cycle"),setFromString:n((e,t)=>u.includes(t)?(e.condensed_history=t,null):`condensed_history must be one of: ${u.join("|")}`,"setFromString")}},bash_tool_purpose:{surface:"settings",setting:{key:"bash_tool_purpose",label:"Bash purpose field",description:"Expose the optional purpose label to agents in the bash tool schema. Off removes the field without disabling the bash valve.",valueConstraint:"true|false",applies:"Applies on the next node session.",group:"display",order:25,format:n(e=>e.bash_tool_purpose?"on":"off","format"),cycle:n(e=>{e.bash_tool_purpose=!e.bash_tool_purpose},"cycle"),setFromString:n((e,t)=>{const o=r(t,"bash_tool_purpose");return typeof o=="string"?o:(e.bash_tool_purpose=o,null)},"setFromString")}},fold_finished_tools:{surface:"settings",setting:{key:"fold_finished_tools",label:"Fold finished tools",description:"Fold every settled tool call to its call line. Toggle live with /fold-tools.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:30,format:n(e=>e.fold_finished_tools?"on":"off","format"),cycle:n(e=>{e.fold_finished_tools=!e.fold_finished_tools},"cycle"),setFromString:n((e,t)=>{const o=r(t,"fold_finished_tools");return typeof o=="string"?o:(e.fold_finished_tools=o,null)},"setFromString")}},summarize_tool_calls:{surface:"settings",setting:{key:"summarize_tool_calls",label:"Summarize tool calls",description:"Replace completed folded tool-call groups with a one-line broker summary when available.",valueConstraint:"true|false",applies:"Applies when the next visible message closes a tool-call group.",group:"display",order:35,format:n(e=>e.summarize_tool_calls?"on":"off","format"),cycle:n(e=>{e.summarize_tool_calls=!e.summarize_tool_calls},"cycle"),setFromString:n((e,t)=>{const o=r(t,"summarize_tool_calls");return typeof o=="string"?o:(e.summarize_tool_calls=o,null)},"setFromString")}},document_port:{surface:"settings",setting:{key:"document_port",label:"Document browser port",description:"Fixed localhost port where crtrd serves editable document pages.",valueConstraint:"1-65535",applies:"Applies after daemon handover and on the next attach.",group:"display",order:37.5,format:n(e=>String(e.document_port),"format"),cycle:n((e,t)=>{e.document_port=Math.max(1,Math.min(65535,e.document_port+t))},"cycle"),setFromString:n((e,t)=>{const o=Number(t);return!/^\d+$/.test(t)||!Number.isInteger(o)||o<1||o>65535?"document_port must be an integer from 1 to 65535":(e.document_port=o,null)},"setFromString")}},detailed_tool_recaps:{surface:"settings",setting:{key:"detailed_tool_recaps",label:"Detailed tool recaps",description:"Show each document read and edited file in folded tool recaps. Off shows a compact count line instead.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:36,format:n(e=>e.detailed_tool_recaps?"on":"off","format"),cycle:n(e=>{e.detailed_tool_recaps=!e.detailed_tool_recaps},"cycle"),setFromString:n((e,t)=>{const o=r(t,"detailed_tool_recaps");return typeof o=="string"?o:(e.detailed_tool_recaps=o,null)},"setFromString")}},consolidate_replies:{surface:"settings",setting:{key:"consolidate_replies",label:"Consolidate replies",description:"Experiment: show one rewritten agent reply per message you type, with the working folded behind it (/show-working).",valueConstraint:"true|false",applies:"Applies on the next attach; the broker reads it per turn.",group:"display",order:36.5,format:n(e=>e.consolidate_replies?"on":"off","format"),cycle:n(e=>{e.consolidate_replies=!e.consolidate_replies},"cycle"),setFromString:n((e,t)=>{const o=r(t,"consolidate_replies");return typeof o=="string"?o:(e.consolidate_replies=o,null)},"setFromString")}},keybindings:{surface:"specialized",owner:"Keybindings tab"},tmux_passthrough:{surface:"specialized",owner:"Keybindings tab"},providerOptions:{surface:"settings",settings:{"openai-codex.fastMode":{key:`providerOptions.${l}.fastMode`,label:"Codex fast mode",description:"Serve Codex turns at the ChatGPT priority tier: about 1.5x faster generation for about 2x the credits. Displayed cost does not reflect the premium.",valueConstraint:"true|false",applies:"Applies on each node's next turn.",group:"providers",order:40,format:n(e=>e.providerOptions[l]?.fastMode?"on":"off","format"),cycle:n(e=>{const t=g(e,l);t.fastMode=!t.fastMode},"cycle"),setFromString:n((e,t)=>{const o=r(t,`providerOptions.${l}.fastMode`);return typeof o=="string"?o:(g(e,l).fastMode=o,null)},"setFromString")}}},modelLadders:{surface:"specialized",owner:"Models tab"},modelRoutes:{surface:"specialized",owner:"Models route declarations"},modelRouting:{surface:"specialized",owner:"Models route declarations"},kinds:{surface:"specialized",owner:"Models tab and kind registry"},page_components:{surface:"specialized",owner:"Page component catalog: product-registered page component kinds"},remoteCanvas:{surface:"specialized",owner:"canvas config commands"},api:{surface:"specialized",owner:"sys connect"},paths:{surface:"specialized",owner:"runtime layout"},ledger:{surface:"specialized",owner:"money ledger (take_pct, sandbox rates)"},store:{surface:"specialized",owner:"daemon conversation store"},runtime:{surface:"specialized",owner:"app-facing listener"},spawnEnv:{surface:"specialized",owner:"spawn environment allow-list"},bin:{surface:"specialized",owner:"bare-binary contributions on every node PATH"},humanActions:{surface:"specialized",owner:"scope-configured human completion actions"}},O=Object.keys(h);function S(){const e=[];for(const t of Object.values(h))t.surface==="settings"&&("setting"in t?e.push(t.setting):e.push(...Object.values(t.settings)));return e.sort((t,o)=>t.order-o.order)}n(S,"collectUserSettings");const y=S();function A(e){return y.find(t=>t.key===e)}n(A,"findUserSetting");function z(e){return y.filter(t=>t.group===e)}n(z,"userSettingsInGroup");export{h as CONFIG_SETTINGS_COVERAGE,O as SCOPE_CONFIG_KEYS,y as USER_SETTINGS,A as findUserSetting,z as userSettingsInGroup};
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
var Q=Object.defineProperty;var s=(e,n)=>Q(e,"name",{value:n,configurable:!0});import{
|
|
1
|
+
var Q=Object.defineProperty;var s=(e,n)=>Q(e,"name",{value:n,configurable:!0});import{AsyncResource as W}from"node:async_hooks";import{randomUUID as q}from"node:crypto";import{createServer as K}from"node:http";import{Router as V,causedByOf as Z}from"./router.js";import{toErrorBody as ee}from"./map.js";import{objectRoutes as te}from"./handlers/objects.js";import{customObjectRoutes as re}from"./handlers/custom-objects.js";import{checkRoutes as ne}from"./handlers/check.js";import{chargeRoutes as ae}from"./handlers/charges.js";import{docRoutes as oe}from"./handlers/docs.js";import{relationRoutes as ie}from"./handlers/relations.js";import{schemaRoutes as se}from"./handlers/schemas.js";import{OPERATIONS as ue}from"./operations.js";import{runtimeReadiness as ce}from"../readiness.js";import{errorCodes as X}from"../../api/error-codes.js";import{MINIMUM_RUNTIME_VERSION_HEADER as de,RUNTIME_VERSION_HEADER as le,minimumRuntimeRefusal as me}from"../../api/runtime-version.js";import{CONTRACT_HEADER as fe,CONTRACT_LEVEL as $,REQUIRED_CONTRACT_HEADER as pe,contractRefusal as he}from"../../api/contract.js";import{crtrVersion as J}from"../../shared/crtr-version.js";import{newTraceId as we,parseTraceparent as ye}from"../../shared/traceparent.js";import{AppPrincipalResolver as _e}from"./principal.js";import{isDaemonRoute as ve,runtimeOwner as ge,servePeer as z}from"../peer/ingress.js";import{applySyncNotice as Re}from"./sync-notice.js";import{ownMachineId as Oe}from"../../core/peer/directory.js";import{handleRunOperation as Ee,integer as be}from"./handlers/runs.js";import{llmCallerOf as Ae,parseLlmRequest as Te,runLlm as Se}from"../../core/llm/run.js";import{parseUsageMonth as Ne,usageFor as Ce}from"../../core/ledger/index.js";import{capFields as Ie}from"./handlers/llm.js";import{CONTROL_BODY_MAX_BYTES as Pe,MODEL_CONTEXT_BODY_MAX_BYTES as ke}from"../../core/llm/body-limits.js";import{RunError as m,runIsRunning as Me}from"../../core/runs/operations.js";import{requireRun as L}from"./router.js";import{deferHead as De}from"./deferred-head.js";import{readRunEvents as G,registerGrantStream as He,subscribeRunEvents as xe}from"../../core/runs/events.js";import{activeGrant as Y,payerOfGrant as Be}from"../../core/grants/mirror.js";async function je(e){if(await Be(e)==="app")throw new m(401,"grant_revoked","this app-paid grant is no longer active");return null}s(je,"appPaidGone");import{releaseGrantWaiters as Je}from"../../core/grants/watch.js";import{emitEvent as Le}from"../../core/events/emit.js";import{runNotices as Ue}from"../run-notices.js";import{handleVendorSignIn as Ve,isVendorSignInPath as Xe}from"./vendor-signin.js";import{listAppProfiles as $e}from"./handlers/app-profiles.js";import{handleTransferDownload as ze,handleTransferOperation as Ge,TRANSFER_OPERATIONS as Ye}from"./handlers/transfer.js";import{handleQuestionOperation as Fe,QUESTION_OPERATIONS as Qe}from"./handlers/questions.js";import{removeVendorAccount as We,vendorStatus as qe}from"./handlers/vendor-status.js";import{handleMemoryOperation as Ke,MEMORY_OPERATIONS as Ze}from"./handlers/memory.js";import{EXEC_BODY_MAX_BYTES as et,handleExec as tt}from"./handlers/exec.js";import{abortOnClose as F,callerFromApp as rt,handleProviderOperation as nt,PROVIDER_OPERATIONS as at,providerFailure as ot}from"./handlers/providers.js";function it(e){return Object.prototype.hasOwnProperty.call(X,e)?X[e]:void 0}s(it,"fixedRow");function st(e){const n=it(e);return n?n.type:e==="stream_gap"||e==="provider_error"||e==="runtime_version_unsupported"?"invalid_request_error":"server_error"}s(st,"errorType");function ut(e){if(!e||typeof e!="object"||Array.isArray(e)||!("rate_limit"in e))return e;const{rate_limit:n,...o}=e;return o}s(ut,"appDetails");function j(e,n,o){const p=ut(e.details);return{error:{code:e.code,message:e.message,...p===void 0?{}:{details:p},type:st(e.code),...e.param?{param:e.param}:{},origin:"runtime",retryable:e.retryable||e.code==="stream_dropped",request_id:n,...o?{run_id:o}:{},...e.scope?{scope:e.scope}:{},...e.code==="unauthorized"?{user_action:"reconnect"}:{},...Ie(e),...e.code==="all_routes_exhausted"?{retry_after_s:e.details.retry_after_s}:{}}}}s(j,"envelope");function ct(e,n,o,p,f){const d=n instanceof m?n:new m(500,"server_failure","runtime request failed");if(n instanceof m||console.error("[app-listener]",`trace_id=${p}`,n),e.headersSent&&!String(e.getHeader("Content-Type")??"").startsWith("text/event-stream")){e.destroy();return}if(e.headersSent){e.end(`event: error
|
|
2
2
|
data: ${JSON.stringify(j(d,o,f))}
|
|
3
3
|
|
|
4
|
-
`);return}e.writeHead(d.status,{"Content-Type":"application/json; charset=utf-8","Request-Id":o,"X-Content-Type-Options":"nosniff",...d.code==="all_routes_exhausted"?{"Retry-After":String(d.details.retry_after_s)}:{}}),e.end(JSON.stringify(j(d,o,f)))}s(
|
|
4
|
+
`);return}e.writeHead(d.status,{"Content-Type":"application/json; charset=utf-8","Request-Id":o,"X-Content-Type-Options":"nosniff",...d.code==="all_routes_exhausted"?{"Retry-After":String(d.details.retry_after_s)}:{}}),e.end(JSON.stringify(j(d,o,f)))}s(ct,"fail");function U(e){return Array.isArray(e)?e[0]:e}s(U,"headerValue");function g(e,n,o){e.writeHead(n,{"Content-Type":"application/json; charset=utf-8"}),e.end(JSON.stringify(o))}s(g,"json");async function C(e,n=Pe){const o=[];let p=0;for await(const f of e){if(p+=f.length,p>n)throw new m(400,"invalid_request","request body too large");o.push(f)}if(p)try{return JSON.parse(Buffer.concat(o).toString("utf8"))}catch{throw new m(400,"invalid_request","invalid JSON body")}}s(C,"bodyOf");function dt(e,n){const o=e.headers["last-event-id"]??n.get("after");if(Array.isArray(o))throw new m(400,"invalid_request","invalid cursor","after");return be(o??null,"after",0,Number.MAX_SAFE_INTEGER,0)}s(dt,"cursor");function lt(e){return`id: ${e.sequence_number}
|
|
5
5
|
event: ${e.type}
|
|
6
6
|
data: ${JSON.stringify(e)}
|
|
7
7
|
|
|
8
|
-
`}s(
|
|
8
|
+
`}s(lt,"frame");const mt=6e4;async function ft(e,n,o,p,f,d,b,I={},D){await L(p,o);let w=await G(o,f);if(f>w.latest_sequence)throw new m(400,"invalid_request","cursor is beyond the run","after");if(f<w.latest_sequence&&(w.earliest_sequence===null||f<w.earliest_sequence-1))throw new m(409,"stream_gap","events have expired",void 0,{earliest_sequence:w.earliest_sequence,latest_sequence:w.latest_sequence});if(n.destroyed)return n.destroy(),Promise.resolve();n.writeHead(200,{"Content-Type":b==="sse"?"text/event-stream":"application/x-ndjson","Cache-Control":"no-cache","X-Accel-Buffering":"no"}),b==="sse"?n.write(`: connected
|
|
9
9
|
|
|
10
|
-
`):n.flushHeaders();let T=f;const r=await
|
|
10
|
+
`):n.flushHeaders();let T=f;const r=await Ue().streamOpened(o);let t=!1,y=!1,E=!1,A;const P=new Promise(c=>{A=c}),v=s(()=>{t||(t=!0,r(T).catch(c=>console.error("[app-listener]",...D===void 0?[]:[`trace_id=${D}`],c)),clearInterval(N),clearInterval(O),M(),x(),n.off("close",v),n.off("drain",h),n.end(),A())},"end"),h=s(()=>{E=!1,a()},"onDrain"),R=s(c=>{t||n.write(b==="sse"?`event: error
|
|
11
11
|
data: ${JSON.stringify(j(c,d,o))}
|
|
12
12
|
|
|
13
13
|
`:`${JSON.stringify({type:"error",...j(c,d,o)})}
|
|
14
|
-
`),v()},"error"),a=s(async()=>{if(!(t||y)){y=!0;try{if(!await S()){H();return}if(await L(p,o),w=await G(o,T),w.backlog_count>1e3||w.backlog_bytes>32*1024*1024){R(new m(503,"stream_dropped","stream reader fell behind",void 0,{last_sequence:T}));return}for(const c of w.events){if(E)break;E=!n.write(b==="sse"?
|
|
15
|
-
`),T=c.sequence_number}}catch(c){R(c instanceof m?c:new m(500,"server_failure","stream failed"))}finally{y=!1}}},"flush"),H=s(()=>R(new m(401,"grant_revoked","grant is not active")),"revoked"),S=s(async()=>"class"in p||await Y(p.grant)!==null,"grantActive"),M=await
|
|
14
|
+
`),v()},"error"),a=s(async()=>{if(!(t||y)){y=!0;try{if(!await S()){H();return}if(await L(p,o),w=await G(o,T),w.backlog_count>1e3||w.backlog_bytes>32*1024*1024){R(new m(503,"stream_dropped","stream reader fell behind",void 0,{last_sequence:T}));return}for(const c of w.events){if(E)break;E=!n.write(b==="sse"?lt(c):`${JSON.stringify(c)}
|
|
15
|
+
`),T=c.sequence_number}}catch(c){R(c instanceof m?c:new m(500,"server_failure","stream failed"))}finally{y=!1}}},"flush"),H=s(()=>R(new m(401,"grant_revoked","grant is not active")),"revoked"),S=s(async()=>"class"in p||await Y(p.grant)!==null,"grantActive"),M=await xe(o,W.bind(a)),x="class"in p?()=>{}:He(p.grant,H),N=setInterval(()=>{!t&&!E&&b==="sse"&&n.write(`: keepalive
|
|
16
16
|
|
|
17
|
-
`)},15e3),u=I.idleMs??
|
|
17
|
+
`)},15e3),u=I.idleMs??mt,B=I.isRunning??Me;let i=Date.now(),_=T;const l=s(async()=>{if(t||b!=="sse")return;const c=Date.now();let k=!0;try{k=await B(o)}catch{}if(!t){if(k||T!==_){i=c,_=T;return}c-i<u||E||(n.write(`event: idle
|
|
18
18
|
data: {}
|
|
19
19
|
|
|
20
|
-
`),v())}},"checkIdle"),O=setInterval(()=>{l().catch(c=>
|
|
20
|
+
`),v())}},"checkIdle"),O=setInterval(()=>{l().catch(c=>Le({level:"error",event:"api.run_stream.idle_check_failed",error:c}))},I.idleCheckMs??1e3);return O.unref(),n.on("drain",h),n.on("close",v),await a(),P}s(ft,"streamRunEvents");async function or(e,n,o,p={}){const f=e.listener;if(!e.issuer||!e.audience||!f?.address||!Number.isInteger(f.port)||f.port<1||f.port>65535)throw new Error("runtime issuer, audience and listener address/port are required");if(["0.0.0.0","::","[::]"].includes(f.address))throw new Error("runtime listener must bind a specific address");const d=new _e(e.issuer,e.audience,o,e.jwksUrl),b=new V,I=new Map;for(const r of ue.filter(t=>t.stage!==void 0)){const t=s(()=>({status:500}),"handler");b.register({method:r.method,pattern:r.path,handler:t}),I.set(t,r)}const D=new V().registerAll(te).registerAll(re).registerAll(oe).registerAll(se).registerAll(ie).registerAll(ne).registerAll(ae),w=K((r,t)=>{(async()=>{De(r,t,p.deferHead);const y=q();t.setHeader("Request-Id",y);const E=ye(U(r.headers.traceparent))??we();t.setHeader(le,J()),t.setHeader(fe,$);let A;try{const P=U(r.headers[de.toLowerCase()]),v=me(P,J())??he(U(r.headers[pe.toLowerCase()]),$,{legacyMinimum:P,runtimeVersion:J()});if(v!==null)throw v.status===400?new m(400,v.code,v.message,v.param):new m(426,v.code,v.message,void 0,v.details);const h=new URL(r.url??"/","http://runtime.local");if(Xe(h.pathname)){await Ve(r,t,h,d);return}const R=b.match(r.method??"GET",h.pathname),a=R?I.get(R.handler):void 0,H=a?.name==="runtime.sync-notice"||a?.name==="runtime.vendor-status"||a?.name==="runtime.vendor-account-remove";let S,M;if(!H&&r.headers.authorization!==void 0)try{S=await d.verifyCall(r.headers.authorization)}catch(i){M=i}const x={issuer:e.issuer,jwks:d.jwks,audience:s(async()=>e.audience,"audience"),owner:ge,self:Oe,syncGrants:o,ready:s(async()=>d.isReady()&&await n(),"ready")};if(S?.chain[0]?.sub.startsWith("runtime:")){await z(r,t,x,S);return}if(S===void 0&&a===void 0&&await ve(r.method??"GET",h.pathname)){await z(r,t,x,{status:401,code:"unauthorized",message:M===void 0?"a machine token is required":"invalid machine token"});return}if(a?.name==="ready"){const i=await n(),_=await ce({jwksReady:d.isReady(),grantsReady:s(()=>i,"grantsReady")});g(t,_.ready?200:503,_);return}if((r.method!=="GET"||h.pathname!=="/v1/health")&&(!d.isReady()||!await n()))throw new m(503,"runtime_starting","runtime_starting");if(!R||!a)throw new m(404,"not_found","unknown operation");A=R.params.run_id;const N=Z(r.headers);if(a.name==="health"){g(t,200,{status:"ok",api_version:"2026-09-23"});return}if(a.name==="runtime.sync-notice"){await Re(await d.verifySyncNotice(r.headers.authorization),o,y),t.writeHead(204),t.end();return}if(a.name==="runtime.vendor-status"){await d.verifyDirectoryRead(r.headers.authorization,"vendor_status"),g(t,200,await qe());return}if(a.name==="runtime.vendor-account-remove"){await d.verifyDirectoryRead(r.headers.authorization,"vendor_account_remove"),g(t,200,await We(await C(r)));return}if(S===void 0)throw M??new m(401,"unauthorized","a directory access token is required");const u=await d.resolveVerified(S,a.scope);if(t.setHeader("Request-Id",y),A&&await L(u,A,["run.message","run.interrupt","run.cancel","run.rename","run.delete"].includes(a.name),a.name==="run.delete"),a.stage==="objects"){const i=D.match(a.method,h.pathname);if(!i)throw new m(404,"not_found","unknown operation");const _={...N===void 0?{}:{causedBy:N},method:a.method,path:h.pathname,params:i.params,query:h.searchParams,body:await C(r,i.maxBodyBytes),ceiling:u.resolved,principal:{class:"app",app:u.grantee,scopes:u.resolved,sub:u.sub},req:r,res:t};let l;try{l=await i.handler(_)}catch(O){const{status:c,body:k}=ee(O);throw c>=500&&console.error("[app-listener]",`trace_id=${E}`,O),new m(c,k.error.code,k.error.message,void 0,k.error.details)}if(t.headersSent)return;if(l.rawBody!==void 0||l.status===204||l.body===void 0){t.writeHead(l.status,l.headers??{}),t.end(l.rawBody);return}t.writeHead(l.status,{"Content-Type":"application/json; charset=utf-8",...l.headers??{}}),t.end(JSON.stringify(l.body));return}if(a.stream==="bytes"){await ze(r,t,u,h.searchParams);return}if(a.stream){await ft(r,t,A,u,dt(r,h.searchParams),y,"sse",p.stream,E);return}if(a.name==="llm"){const i=Te(await C(r,ke)),_=new AbortController,l=s(()=>_.abort(),"abort");t.on("close",l);try{const O=await Se(i,_.signal,i.stream?c=>{t.headersSent||t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache","X-Accel-Buffering":"no"}),t.write(`data: ${JSON.stringify(c)}
|
|
21
21
|
|
|
22
|
-
`)}:void 0,void 0,{grantee:u.grantee,sub:u.sub,spend_cap:u.spend_cap,request:y},
|
|
22
|
+
`)}:void 0,void 0,{grantee:u.grantee,sub:u.sub,spend_cap:u.spend_cap,request:y},Ae(await Y(u.grant)??await je(u.grant)),N);i.stream?(t.headersSent||t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache","X-Accel-Buffering":"no"}),t.end(`data: [DONE]
|
|
23
23
|
|
|
24
|
-
`)):g(t,200,O.completion)}finally{t.off("close",l)}return}if(a.name==="exec"){const{signal:i,release:_}=F(t);try{g(t,200,await
|
|
24
|
+
`)):g(t,200,O.completion)}finally{t.off("close",l)}return}if(a.name==="exec"){const{signal:i,release:_}=F(t);try{g(t,200,await tt(u,await C(r,et),i))}finally{_()}return}if(a.name==="usage.get"){g(t,200,await Ce(u.grantee,Ne(h.searchParams.get("month"))));return}if(a.name==="profile.list"){g(t,200,await $e(u));return}if(Qe.has(a.name)){const i=await Fe(a.name,u,R.params.question_id,a.method==="POST"?await C(r):void 0);g(t,i.status,i.body);return}if(at.has(a.name)){const{signal:i,release:_}=F(t);try{const l=await nt(a.name,rt(u),{params:R.params,body:a.method==="POST"?await C(r):void 0,query:h.searchParams},{requestId:y,traceId:E,signal:i,...N===void 0?{}:{causedBy:N}});g(t,l.status,l.body)}catch(l){const O=ot(l,y,!0);t.writeHead(O.status,{"Content-Type":"application/json; charset=utf-8","X-Content-Type-Options":"nosniff",...O.headers}),t.end(JSON.stringify(O.body))}finally{_()}return}if(Ze.has(a.name)){const i=await Ke(a.name,{class:"app",app:u.grantee,scopes:u.resolved},h.searchParams);g(t,i.status,i.body);return}if(Ye.has(a.name)){const i=await Ge(a,u,R.params,h.searchParams,await C(r));g(t,i.status,i.body);return}const B=await Ee(a,u,A,h.searchParams,await C(r),r.headers["idempotency-key"],N);g(t,B.status,B.body)}catch(P){ct(t,P,y,E,A)}})()});return{ready:new Promise((r,t)=>{w.once("error",t),w.listen(f.port,f.address,()=>{w.off("error",t),r()})}),close:s(async()=>{d.close(),Je(),w.closeAllConnections(),await new Promise((r,t)=>w.close(y=>y?t(y):r()))},"close")}}s(or,"createAppListener");export{mt as RUN_STREAM_IDLE_MS,or as createAppListener,dt as cursor,ft as streamRunEvents};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare class PersonBearerVerifier {
|
|
2
|
+
readonly issuer: string;
|
|
3
|
+
readonly audience: string;
|
|
4
|
+
private readonly jwks;
|
|
5
|
+
constructor(issuer: string, audience: string, fetcher?: typeof fetch, jwksUrl?: string);
|
|
6
|
+
/** The `user:<id>` a valid person bearer names, or null. A JWKS that cannot be fetched throws (the listener logs it and answers 401). */
|
|
7
|
+
verify(token: string): Promise<string | null>;
|
|
8
|
+
/** The `user:<id>` a valid directory token for exactly `purpose` names, or null: a token with no `user:` sub is refused. */
|
|
9
|
+
verifyPurpose(token: string, purpose: string): Promise<string | null>;
|
|
10
|
+
/** The claims of a token this directory signed for this API with no `act`, or null. */
|
|
11
|
+
private claims;
|
|
12
|
+
}
|
|
13
|
+
/** The verifier `CRTR_DIRECTORY_URL` (issuer) and `CRTR_PUBLIC_API_URL` (audience) configure, built once; null when either is unset. */
|
|
14
|
+
export declare function personBearerVerifier(): PersonBearerVerifier | null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var c=Object.defineProperty;var i=(n,e)=>c(n,"name",{value:e,configurable:!0});import{JwksCache as l}from"@north-light/identity";import{createLocalJWKSet as o,decodeProtectedHeader as d,jwtVerify as f}from"jose";const p=/^user:[a-z0-9][a-z0-9._-]*$/;class h{static{i(this,"PersonBearerVerifier")}issuer;audience;jwks;constructor(e,r,s=fetch,t){this.issuer=e,this.audience=r,this.jwks=new l(e,s,t)}async verify(e){const r=await this.claims(e);return r===null||r.purpose!==void 0?null:a(r)}async verifyPurpose(e,r){const s=await this.claims(e);return s===null||s.purpose!==r?null:a(s)}async claims(e){let r;try{r=d(e)}catch{return null}if(r.alg!=="ES256")return null;const s=await this.jwks.forKid(r.kid);let t;try{({payload:t}=await f(e,o(s),{issuer:this.issuer,audience:this.audience,algorithms:["ES256"],requiredClaims:["exp","sub"]}))}catch{return null}return t.act===void 0?t:null}}function a(n){const e=n.sub;return typeof e=="string"&&p.test(e)?e:null}i(a,"personOf");let u;function R(){if(u!==void 0)return u;const n=process.env.CRTR_DIRECTORY_URL||void 0,e=process.env.CRTR_PUBLIC_API_URL||void 0;return u=n===void 0||e===void 0?null:new h(n,e),u}i(R,"personBearerVerifier");export{h as PersonBearerVerifier,R as personBearerVerifier};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var
|
|
1
|
+
var q=Object.defineProperty;var n=(r,e)=>q(r,"name",{value:e,configurable:!0});import{WebSocketServer as z}from"ws";import{isSafeNodeId as N,viewSocketPath as K}from"../../core/canvas/paths.js";import{getNode as T}from"../../core/canvas/index.js";import{BROKER_READ_CAPS as Q,CLIENT_READ_CAPS as G,FrameDecoder as X,FrameOverflowError as Y}from"../../core/runtime/broker-protocol.js";import{emitEvent as O}from"../../core/events/emit.js";import{classify as A}from"../../core/fault-classifier.js";import{clearFault as v,markNodeRead as Z,recordFault as R}from"../../core/canvas/recovery.js";import{decideAttachRevive as I}from"../../core/runtime/revive.js";import{connectViewSocket as ee,connectWssView as re,probeViewSocket as te,waitForBrokerViewSocket as ae,waitForWssView as V}from"../../core/runtime/view-socket.js";import{liveExecutionForNode as ne}from"../../core/canvas/executions.js";import{runnerForExecution as oe}from"../../core/runtime/runner/index.js";import{isBeneathRefusal as ie}from"../../core/spaces/open-beneath.js";import{attachViewer as F,detachViewer as ce,holdViewerForRedial as se,presentViewer as le}from"./viewer-presence.js";const fe=new z({noServer:!0,maxPayload:Q.maxLineBytes}),ue=25e3,me=6e4;function de(r,e=ue,l=me){let a=!0,d=!1,o=Date.now();const i=n(()=>{a=!0},"acknowledge"),p=n(()=>{d||(d=!0,clearInterval(c),r.off("pong",i))},"stop");r.on("pong",i);const c=setInterval(()=>{if(Date.now()-o>l){a=!0;return}if(!a){p(),r.terminate();return}a=!1;try{r.ping()}catch{p(),r.terminate()}},e);return c.unref(),{stop:p,noteActivity:n(()=>{o=Date.now()},"noteActivity")}}n(de,"startRemoteAttachHeartbeat");function $(r){const e=Buffer.from(r,"utf8");return e.byteLength<=123?r:e.subarray(0,123).toString("utf8")}n($,"clampReason");function h(r,e,l,a,d){const o=JSON.stringify({error:{code:a,message:d,origin:"runtime"}}),i=`HTTP/1.1 ${e} ${l}\r
|
|
2
2
|
content-type: application/json; charset=utf-8\r
|
|
3
3
|
content-length: ${Buffer.byteLength(o)}\r
|
|
4
4
|
connection: close\r
|
|
5
5
|
\r
|
|
6
|
-
`+o;try{r.end(i)}catch{try{r.destroy()}catch{}}}n(
|
|
7
|
-
`)?
|
|
8
|
-
`,
|
|
6
|
+
`+o;try{r.end(i)}catch{try{r.destroy()}catch{}}}n(h,"refuseUpgrade");function ye(r){if(new URL(r.url??"/","http://127.0.0.1").searchParams.get("revive")==="0")return!0;const l=r.headers["x-crtr-attach-revive"];return(Array.isArray(l)?l[0]:l)==="0"}n(ye,"reviveOptedOut");function he(r){return new URL(r.url??"/","http://127.0.0.1").searchParams.get("wakeParked")==="1"}n(he,"wakeParkedRequested");function P(r){return r===1e3||r===1001||r===1005}n(P,"isCleanViewerClose");function m(r,e,l){l.catch(a=>O({level:"error",event:e,node_id:r,error:a}))}n(m,"detach");async function D(r){const e=await ne(r);return e===null||e.runner==="process"?{kind:"unix",path:K(r)}:oe(e.runner).viewerAddress(e)}n(D,"brokerViewAddress");function pe(r,e){return e.kind==="wss"?re(e.url,e.headers):ee(r)}n(pe,"connectBrokerView");function we(r,e,l){return e.kind==="wss"?V(e.url,e.headers,void 0,l):te(r,l)}n(we,"probeBrokerView");async function ve(r,e,l,a){const d=[];let o=n(t=>{d.push(t)},"relayMessage");if(r.on("message",t=>o(t)),!N(e)){try{r.close(1008,$(`invalid node id: ${e}`))}catch{}return}if(await T(e)===null){try{r.close(1011,$(`no node ${e}`))}catch{}return}await v(e,{link:"viewer\u2194crtrd"});const i=pe(e,l),p=new X(G);let c=!1,w=!1,k,x=!1,C=!1,b="controller",B=Promise.resolve(),g=!1;const _=[];let E=!1;i.on("connect",()=>{x=!0,!c&&g&&m(e,"daemon.bridge.presence_failed",F(e,r)),m(e,"daemon.bridge.connect_failed",v(e,{link:"relay\u2194broker"}))});const y=n((t,f,s=!1)=>{if(!c){if(c=!0,m(e,"daemon.bridge.presence_failed",s?se(e,r):ce(e,r)),k?.stop(),!i.destroyed)try{i.destroy()}catch{}try{r.close(t,$(f))}catch{}}},"teardown");k=de(r);const U=n(async t=>{k?.noteActivity();let f;try{f=p.push(t)}catch(s){const u=s instanceof Y?`broker sent an oversized frame (${s.message})`:`failed to decode a broker frame for ${e}`;y(1009,u);return}_.push(...f),E||await L()},"onData"),L=n(async()=>{E=!0;try{for(;_.length>0&&!c;){const t=_.splice(0);let f;try{f=await a(b)}catch{y(1011,"revoked");return}if(c)return;if(!f){y(1008,"revoked");return}let s=!1;for(const u of t)r.readyState===r.OPEN&&(r.send(JSON.stringify(u)),u?.type==="welcome"&&(s=!0));if(g&&s)try{await le(e,r)&&await Z(e)}catch(u){O({level:"warn",event:"daemon.bridge.present_failed",node_id:e,error:u})}}}finally{E=!1}},"drainOutbound");i.on("data",t=>m(e,"daemon.bridge.data_failed",U(t)));const W=n(async t=>{const f=A("relay\u2194broker",t);await R(e,{link:"relay\u2194broker",op:"bridge socket",kind:f.kind,retry:{disposition:"manual"},message:t.message});const s=t.code==="ECONNREFUSED"||t.code==="ENOENT"?`no running broker for ${e}`:`view socket error for ${e}: ${t.message}`;y(1011,s,!0)},"onSocketError");i.on("error",t=>m(e,"daemon.bridge.socket_error_failed",W(t)));const H=n(async t=>{c||t||(await v(e,{link:"relay\u2194broker"}),y(1e3,"broker socket closed",!0))},"onSocketClose");i.on("close",t=>m(e,"daemon.bridge.socket_close_failed",H(t)));const J=n(async(t,f)=>{const s=f.toString("utf8");if(c){P(t)&&await v(e,{link:"viewer\u2194crtrd"});return}if(P(t))await v(e,{link:"viewer\u2194crtrd"});else if(!w){w=!0;const u=A("viewer\u2194crtrd",{code:t,reason:s});await R(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:u.kind,retry:{disposition:"auto"},message:s||`remote attach closed (${t})`})}y(t,s||`remote attach closed (${t})`)},"onWsClose");r.on("close",(t,f)=>m(e,"daemon.bridge.ws_close_failed",J(t,f)));const M=n(async()=>{if(!w){w=!0;const t=A("viewer\u2194crtrd",{code:1006,reason:"remote attach websocket error"});await R(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:t.kind,retry:{disposition:"auto"},message:"remote attach websocket error"})}y(1011,"remote attach websocket error")},"onWsError");r.on("error",()=>m(e,"daemon.bridge.ws_error_failed",M())),o=n(t=>{if(c||i.destroyed)return;k?.noteActivity();const s=(Array.isArray(t)?Buffer.concat(t):Buffer.isBuffer(t)?t:Buffer.from(new Uint8Array(t))).toString("utf8");if(!C)try{const S=JSON.parse(s);S?.type==="hello"&&(C=!0,b=S.role==="observer"?"observer":"controller",g=S.attends!==!1,g&&x&&m(e,"daemon.bridge.presence_failed",F(e,r)))}catch{}const u=s.endsWith(`
|
|
7
|
+
`)?s:s+`
|
|
8
|
+
`,j=n(()=>{try{i.write(u)}catch{}},"write");B=B.then(async()=>{c||(await a(b)?j():y(1008,"revoked"))}).catch(()=>y(1011,"revoked"))},"relayMessage");for(const t of d.splice(0))o(t)}n(ve,"bridgeConnection");async function Oe(r,e,l,a,d){e.on("error",()=>{});try{if(!N(a)){h(e,400,"Bad Request","invalid_node_id",`invalid node id: ${a}`);return}if(await T(a)===null){h(e,404,"Not Found","node_not_found",`no node ${a}`);return}let o;if(ye(r)){if(o=await D(a),!await we(a,o,250)){h(e,409,"Conflict","node_dormant",`node ${a} is dormant and revive was opted out (?revive=0)`);return}}else{let i;try{const c=await I(a,{resume:!0,capacity:"refuse"},he(r));if(c.parked){h(e,409,"Conflict","node_dormant",`node ${a} is parked; attach with ?wakeParked=1 to wake it`);return}i=c.result.launch?.exited}catch(c){const w=c instanceof Error?c.message:String(c);h(e,409,"Conflict","attach_revive_failed",`attach revive failed: ${w}`);return}if(o=await D(a),!(o.kind==="wss"?await V(o.url,o.headers,i):await ae(a,i))){h(e,409,"Conflict","broker_not_ready",`broker view socket for ${a} did not become listenable after revive`);return}}if(e.destroyed)return;fe.handleUpgrade(r,e,l,i=>m(a,"daemon.bridge.connection_failed",ve(i,a,o,d)))}catch(o){const i=o instanceof Error?o.message:String(o);if(ie(o)){h(e,400,"Bad Request","invalid_request",i);return}h(e,500,"Internal Server Error","internal",`attach upgrade failed: ${i}`)}}n(Oe,"handleAttachUpgrade");export{ue as REMOTE_ATTACH_HEARTBEAT_MS,me as REMOTE_ATTACH_QUIET_MS,Oe as handleAttachUpgrade,P as isCleanViewerClose,h as refuseUpgrade,de as startRemoteAttachHeartbeat};
|