@bitkyc08/opencodex 2.84.0 → 2.87.0
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/README.md +0 -4
- package/bin/ocx.mjs +61 -3
- package/gui/dist/assets/App-ZfYbLHkB.js +58 -0
- package/gui/dist/assets/App-wT3mXqFz.css +1 -0
- package/gui/dist/assets/{Tray-C9TGtwad.js → Tray-DCd-A1az.js} +1 -1
- package/gui/dist/assets/index-CfYDMj34.js +94 -0
- package/gui/dist/assets/index-DPeB9HpV.css +1 -0
- package/gui/dist/assets/quota-summary-ChvmKGOk.js +1 -0
- package/gui/dist/index.html +2 -2
- package/package.json +1 -2
- package/src/adapters/anthropic/beta-allowlist.ts +91 -11
- package/src/adapters/anthropic/beta-body-pairs.ts +93 -0
- package/src/adapters/anthropic/client-identity.ts +1 -1
- package/src/adapters/anthropic/passthrough.ts +16 -3
- package/src/adapters/anthropic-progress.ts +84 -0
- package/src/adapters/anthropic.ts +108 -21
- package/src/adapters/azure.ts +19 -1
- package/src/adapters/base.ts +2 -0
- package/src/adapters/claude-cli/adapter.ts +111 -23
- package/src/adapters/claude-cli/profiles.ts +2 -1
- package/src/adapters/claude-cli/stable-replay.ts +108 -0
- package/src/adapters/claude-cli/usage-admission.ts +230 -0
- package/src/adapters/client-fingerprint.ts +24 -0
- package/src/adapters/coding-agent/protocol.ts +1 -1
- package/src/adapters/coding-agent/turn.ts +40 -11
- package/src/adapters/cursor/arg-codec.ts +17 -5
- package/src/adapters/cursor/catalog.ts +8 -0
- package/src/adapters/cursor/effort-map.ts +3 -0
- package/src/adapters/cursor/freeform-args.ts +75 -0
- package/src/adapters/cursor/protobuf-events.ts +36 -23
- package/src/adapters/dsh-account.ts +97 -0
- package/src/adapters/google-antigravity-wire.ts +22 -1
- package/src/adapters/google.ts +37 -10
- package/src/adapters/openai-chat/messages.ts +4 -3
- package/src/adapters/openai-chat/passthrough.ts +8 -2
- package/src/adapters/openai-chat/reasoning-replay.ts +52 -0
- package/src/adapters/openai-chat/response-events.ts +59 -1
- package/src/adapters/openai-chat.ts +8 -5
- package/src/adapters/openai-responses/compaction-search-history.ts +14 -7
- package/src/adapters/openai-responses/passthrough.ts +57 -125
- package/src/adapters/openai-responses/request-strips.ts +25 -3
- package/src/adapters/openai-responses/transport.ts +81 -0
- package/src/adapters/qoder/adapter.ts +44 -3
- package/src/adapters/registry.ts +5 -0
- package/src/adapters/zed.ts +26 -1
- package/src/advisor/activity.ts +55 -0
- package/src/advisor/budget.ts +62 -0
- package/src/advisor/consult.ts +223 -0
- package/src/advisor/context.ts +238 -0
- package/src/advisor/disclosure.ts +20 -0
- package/src/advisor/evidence-tool.ts +21 -0
- package/src/advisor/evidence.ts +117 -0
- package/src/advisor/runtime.ts +353 -0
- package/src/advisor/settings.ts +144 -0
- package/src/advisor/state.ts +369 -0
- package/src/advisor/synthetic-tool.ts +33 -0
- package/src/bridge/errors.ts +24 -1
- package/src/bridge/internal.ts +3 -1
- package/src/bridge/response-json.ts +18 -3
- package/src/bridge/sse.ts +58 -8
- package/src/bridge/terminal-refusal.ts +59 -0
- package/src/chat/inbound.ts +30 -6
- package/src/chat/outbound.ts +5 -0
- package/src/claude/desktop-3p-library.ts +72 -7
- package/src/claude/desktop-3p.ts +75 -19
- package/src/claude/desktop-first-party.ts +1 -1
- package/src/claude/desktop-picker-platform.ts +4 -0
- package/src/claude/desktop-picker-profile.ts +11 -4
- package/src/claude/desktop-picker.ts +15 -8
- package/src/claude/desktop-profile.ts +10 -1
- package/src/claude/desktop-remote-store-io.ts +5 -3
- package/src/claude/desktop-system-proxy.ts +50 -4
- package/src/claude/inbound-content-options.ts +11 -0
- package/src/claude/inbound.ts +154 -50
- package/src/claude/intercept/local-ca.ts +8 -1
- package/src/claude/intercept/picker-ca-startup.ts +2 -1
- package/src/claude/intercept/picker-runtime.ts +6 -5
- package/src/claude/intercept/picker-trust-windows.ts +338 -0
- package/src/claude/intercept/picker-trust.ts +19 -0
- package/src/claude/intercept/port-policy.ts +30 -0
- package/src/claude/intercept/runtime.ts +97 -94
- package/src/claude/model-default-settings.ts +154 -0
- package/src/claude/model-info.ts +7 -7
- package/src/claude/outbound.ts +51 -19
- package/src/cli/account-api.ts +1 -0
- package/src/cli/account-policy-dto.ts +6 -0
- package/src/cli/account-policy.ts +34 -5
- package/src/cli/account-preservation.ts +44 -0
- package/src/cli/account.ts +8 -2
- package/src/cli/advisor.ts +165 -0
- package/src/cli/auxiliary-listener-preflight.ts +37 -0
- package/src/cli/capabilities-accounts.ts +20 -1
- package/src/cli/capabilities-agents-routing.ts +23 -2
- package/src/cli/capabilities-base.ts +39 -11
- package/src/cli/capabilities-observe-system.ts +63 -3
- package/src/cli/capabilities-provider-models.ts +11 -0
- package/src/cli/chatgpt-command.ts +35 -14
- package/src/cli/claude.ts +46 -6
- package/src/cli/codex-cli-update.ts +151 -41
- package/src/cli/codex-provider.ts +44 -0
- package/src/cli/combo-input.ts +10 -1
- package/src/cli/combo-result.ts +1 -1
- package/src/cli/combo.ts +2 -1
- package/src/cli/cross-home-owner.ts +17 -14
- package/src/cli/dispatch.ts +30 -5
- package/src/cli/doctor.ts +15 -1
- package/src/cli/ensure-desktop-cold-start.ts +382 -0
- package/src/cli/export-command.ts +1 -1
- package/src/cli/help.ts +4 -2
- package/src/cli/index.ts +14 -5
- package/src/cli/integration-plan-dto.ts +3 -0
- package/src/cli/log-history.ts +172 -0
- package/src/cli/models-runtime-subcommands.ts +1 -0
- package/src/cli/models-runtime.ts +72 -8
- package/src/cli/observe-stream.ts +2 -0
- package/src/cli/observe.ts +16 -4
- package/src/cli/provider.ts +27 -5
- package/src/cli/registry.ts +41 -9
- package/src/cli/restart-scope.ts +3 -1
- package/src/cli/runtime-api.ts +5 -3
- package/src/cli/system-command.ts +40 -8
- package/src/cli/uninstall-client-state.ts +32 -0
- package/src/cli/usage-compare.ts +309 -0
- package/src/cli/usage-model-search.ts +4 -4
- package/src/cli/usage-report.ts +2 -2
- package/src/cli/v2.ts +1 -1
- package/src/client/machine-listener.ts +1 -3
- package/src/client/runtime.ts +1 -0
- package/src/clients/client-path.ts +51 -0
- package/src/clients/config-export/contracts.ts +3 -1
- package/src/clients/config-export/model-metadata.ts +3 -2
- package/src/clients/config-export/qoder.ts +93 -0
- package/src/clients/config-export.ts +35 -48
- package/src/clients/gentle-shell-path.ts +87 -0
- package/src/codex/account-auto-switch.ts +2 -0
- package/src/codex/account-identity.ts +29 -0
- package/src/codex/account-label.ts +1 -1
- package/src/codex/account-lifecycle.ts +21 -5
- package/src/codex/account-preservation.ts +28 -0
- package/src/codex/account-use-remaining.ts +23 -0
- package/src/codex/app-server-processes.ts +97 -7
- package/src/codex/app-server-restart-service.ts +55 -4
- package/src/codex/auth-api/account-list.ts +4 -0
- package/src/codex/auth-api/account-pause-group.ts +6 -50
- package/src/codex/auth-api/account-preservation.ts +57 -0
- package/src/codex/auth-api/pool-mode-gate.ts +5 -2
- package/src/codex/auth-api/routes.ts +8 -0
- package/src/codex/auth-api/use-remaining-route.ts +36 -0
- package/src/codex/auth-api.ts +0 -1
- package/src/codex/auth-context.ts +81 -7
- package/src/codex/autostart-health.ts +4 -0
- package/src/codex/catalog/auto-review.ts +20 -3
- package/src/codex/catalog/build-entries.ts +19 -2
- package/src/codex/catalog/combo-member.ts +14 -5
- package/src/codex/catalog/configured-tiers.ts +50 -0
- package/src/codex/catalog/effort.ts +4 -1
- package/src/codex/catalog/gather-capture.ts +2 -0
- package/src/codex/catalog/metadata.ts +11 -9
- package/src/codex/catalog/model-hints.ts +42 -19
- package/src/codex/catalog/model-visibility.ts +3 -1
- package/src/codex/catalog/native-ultrafast.ts +106 -0
- package/src/codex/catalog/parsing.ts +35 -86
- package/src/codex/catalog/provider-models.ts +40 -34
- package/src/codex/catalog/retained-sync.ts +2 -0
- package/src/codex/catalog/routed-gather.ts +33 -16
- package/src/codex/catalog/vendor-context.ts +82 -0
- package/src/codex/cli-install-provenance.ts +105 -17
- package/src/codex/cli-update-plan.ts +545 -0
- package/src/codex/config-write-lock.ts +63 -4
- package/src/codex/convergence.ts +2 -0
- package/src/codex/desktop-app/picker-freshness.ts +96 -0
- package/src/codex/desktop-app/types.ts +2 -0
- package/src/codex/desktop-app/windows.ts +29 -16
- package/src/codex/desktop-app-restart.ts +25 -2
- package/src/codex/desktop-compatibility/certificate-service.ts +99 -0
- package/src/codex/desktop-compatibility/certificate-store.ts +193 -0
- package/src/codex/desktop-compatibility/connection-store.ts +87 -0
- package/src/codex/desktop-compatibility/installed-build.ts +73 -0
- package/src/codex/desktop-compatibility/json-body.ts +29 -0
- package/src/codex/desktop-compatibility/native-identity.ts +62 -0
- package/src/codex/desktop-compatibility/relay-listener.ts +93 -0
- package/src/codex/desktop-compatibility/routing-binding.ts +10 -0
- package/src/codex/desktop-compatibility/routing-preflight.ts +69 -0
- package/src/codex/desktop-compatibility/runtime-ownership.ts +28 -0
- package/src/codex/desktop-compatibility/runtime.ts +182 -0
- package/src/codex/desktop-compatibility/service.ts +30 -0
- package/src/codex/desktop-compatibility/startup-settings.ts +50 -0
- package/src/codex/desktop-compatibility/usage-activation.ts +86 -0
- package/src/codex/desktop-compatibility/usage-controlled-fetch.ts +59 -0
- package/src/codex/desktop-compatibility/usage-controller.ts +107 -0
- package/src/codex/desktop-compatibility/usage-policy.ts +59 -0
- package/src/codex/desktop-compatibility/usage-refresh.ts +33 -0
- package/src/codex/desktop-compatibility/usage-sse-controller.ts +86 -0
- package/src/codex/desktop-compatibility/windows-activation-source.ts +44 -0
- package/src/codex/desktop-compatibility/windows-certificate-trust.ts +81 -0
- package/src/codex/desktop-compatibility/windows-key-protection.ts +165 -0
- package/src/codex/desktop-compatibility/windows-package-command.ts +86 -0
- package/src/codex/desktop-compatibility/windows-package-launch.ts +28 -0
- package/src/codex/features.ts +85 -45
- package/src/codex/history-provider.ts +1 -1
- package/src/codex/inject/config-write-section.ts +4 -1
- package/src/codex/inject/history-failure.ts +27 -0
- package/src/codex/inject/remove.ts +18 -6
- package/src/codex/inject/restore.ts +24 -2
- package/src/codex/inject/routing-classify.ts +4 -3
- package/src/codex/inject.ts +18 -27
- package/src/codex/journal.ts +16 -1
- package/src/codex/main-account-hard-lock.ts +30 -1
- package/src/codex/main-account.ts +99 -15
- package/src/codex/native-main-refresh-mode.ts +217 -0
- package/src/codex/native-profile-startup.ts +1 -1
- package/src/codex/ocx-compaction-history.ts +12 -10
- package/src/codex/paths.ts +86 -1
- package/src/codex/provider-routing.ts +174 -0
- package/src/codex/refresh.ts +2 -2
- package/src/codex/routing/health-store.ts +2 -2
- package/src/codex/routing/pool-recovery.ts +79 -0
- package/src/codex/routing/selection.ts +4 -3
- package/src/codex/routing/thread-affinity.ts +1 -1
- package/src/codex/shim-diagnostics.ts +6 -0
- package/src/codex/shim-overlay.ts +7 -2
- package/src/codex/signed-in-identity.ts +43 -0
- package/src/codex/subagent-model-fallback.ts +1 -1
- package/src/codex/sync.ts +6 -1
- package/src/codex/user-identity.ts +16 -5
- package/src/codex/windows-local-appdata.ts +84 -0
- package/src/combos/failover.ts +6 -1
- package/src/combos/index.ts +1 -0
- package/src/combos/resolve.ts +46 -10
- package/src/combos/types.ts +15 -0
- package/src/config/diagnostics.ts +35 -7
- package/src/config/live-reconcile.ts +51 -2
- package/src/config/load-degrade.ts +23 -1
- package/src/config/opencode-wire-upgrade.ts +54 -0
- package/src/config/opencode-zen-upgrade.ts +52 -0
- package/src/config/owner-registry.ts +22 -17
- package/src/config/paths.ts +10 -3
- package/src/config/provider-validation.ts +45 -2
- package/src/config/schema/config-schema.ts +39 -0
- package/src/config/schema/desktop-compatibility.ts +9 -0
- package/src/config/schema/leaf-validators.ts +39 -9
- package/src/config/schema/main-account-hard-lock-fallback.ts +26 -0
- package/src/config/schema/native-reasoning-retention.ts +26 -0
- package/src/config.ts +2 -0
- package/src/generated/compatibility-version.json +962 -350
- package/src/generated/model-metadata.ts +1 -1
- package/src/grok/sync.ts +1 -1
- package/src/images/loop.ts +46 -8
- package/src/integrations/catalog-refresh.ts +1 -1
- package/src/integrations/config-io.ts +20 -2
- package/src/integrations/journal.ts +15 -1
- package/src/integrations/mutation-plan.ts +2 -0
- package/src/integrations/registry.ts +15 -0
- package/src/integrations/store.ts +3 -0
- package/src/integrations/writer.ts +10 -1
- package/src/lib/advisor-activation.ts +16 -0
- package/src/lib/background-work.ts +65 -0
- package/src/lib/bounded-file-read.ts +58 -0
- package/src/lib/bun-path-runtime.d.mts +10 -1
- package/src/lib/bun-path-runtime.mjs +62 -3
- package/src/lib/codex-restart-contract.ts +15 -0
- package/src/lib/desktop-proxy-route.ts +30 -0
- package/src/lib/desktop-upstream-tunnel.ts +72 -0
- package/src/lib/empty-tool-catalog.ts +62 -0
- package/src/lib/errors.ts +26 -3
- package/src/lib/gcp-adc.ts +96 -9
- package/src/lib/gcp-credential-input.ts +12 -0
- package/src/lib/lab-live-route-production.ts +5 -0
- package/src/lib/local-internal-call-capability.ts +55 -0
- package/src/lib/opaque-proxy-tunnel.ts +217 -0
- package/src/lib/package-tree-integrity.ts +2 -2
- package/src/lib/redact.ts +2 -2
- package/src/lib/socks5-fetch.ts +48 -71
- package/src/lib/socks5-handshake.ts +112 -0
- package/src/lib/translator-budget.ts +7 -1
- package/src/oauth/account-quota-rank.ts +69 -2
- package/src/oauth/anthropic-account-refusal.ts +20 -2
- package/src/oauth/anthropic-oauth-definitions.ts +3 -1
- package/src/oauth/anthropic-routing.ts +1 -21
- package/src/oauth/anthropic.ts +38 -7
- package/src/oauth/callback-server.ts +27 -1
- package/src/oauth/chatgpt-device.ts +1 -1
- package/src/oauth/chatgpt-shared.ts +83 -0
- package/src/oauth/chatgpt.ts +8 -72
- package/src/oauth/dsh.ts +203 -0
- package/src/oauth/generic-account-failover.ts +62 -12
- package/src/oauth/generic-session-affinity.ts +125 -0
- package/src/oauth/index.ts +188 -111
- package/src/oauth/kiro-device-login.ts +2 -1
- package/src/oauth/kiro.ts +7 -1
- package/src/oauth/local-token-detect.ts +21 -1
- package/src/oauth/login-cli-errors.ts +44 -0
- package/src/oauth/login-cli.ts +69 -7
- package/src/oauth/login-flow-state.ts +371 -23
- package/src/oauth/meta-muse-errors.ts +41 -0
- package/src/oauth/meta-muse-keychain.ts +52 -0
- package/src/oauth/meta-muse.ts +51 -84
- package/src/oauth/model-discovery-auth.ts +3 -0
- package/src/oauth/pool-settings-capability.ts +4 -2
- package/src/oauth/refresh-flight-retirement.ts +48 -0
- package/src/oauth/session-affinity-key.ts +23 -0
- package/src/oauth/store-anthropic-instance.ts +9 -2
- package/src/oauth/store.ts +12 -5
- package/src/protocols/codecs/chat-ir.ts +467 -0
- package/src/protocols/codecs/chat.ts +10 -1
- package/src/protocols/codecs/messages-ir.ts +500 -0
- package/src/protocols/encoders/adapter-events.ts +5 -4
- package/src/protocols/encoders/messages.ts +9 -6
- package/src/protocols/features.ts +10 -2
- package/src/protocols/path.ts +11 -1
- package/src/protocols/plan-snapshot.ts +39 -16
- package/src/protocols/plan.ts +9 -1
- package/src/protocols/provider-summary.ts +2 -1
- package/src/protocols/settings.ts +8 -0
- package/src/providers/antigravity-account-roster.ts +102 -0
- package/src/providers/antigravity-models.ts +85 -7
- package/src/providers/api-key-cooldowns.ts +49 -0
- package/src/providers/api-key-resolve.ts +11 -6
- package/src/providers/api-key-response-ownership.ts +57 -0
- package/src/providers/api-key-selection.ts +31 -6
- package/src/providers/api-keys.ts +214 -3
- package/src/providers/claude-cli-usage.ts +96 -0
- package/src/providers/dsh-account-destination.ts +31 -0
- package/src/providers/dsh-account-models.ts +41 -0
- package/src/providers/gcp-credential-cleanup.ts +59 -0
- package/src/providers/key-failover.ts +54 -50
- package/src/providers/key-store.ts +7 -2
- package/src/providers/model-rename-fields.ts +5 -0
- package/src/providers/model-rename-migration.ts +7 -5
- package/src/providers/openai-tiers-destination.ts +11 -2
- package/src/providers/openai-tiers.ts +5 -12
- package/src/providers/opencode-go-transport.ts +3 -1
- package/src/providers/quota/account-cache.ts +6 -5
- package/src/providers/quota/account-row.ts +34 -0
- package/src/providers/quota/antigravity.ts +28 -7
- package/src/providers/quota/dsh-account.ts +70 -0
- package/src/providers/quota/vendor-probes-oauth.ts +1 -93
- package/src/providers/quota-types.ts +2 -0
- package/src/providers/quota.ts +14 -20
- package/src/providers/registry/entries-core.ts +44 -14
- package/src/providers/registry/entries-extended.ts +19 -0
- package/src/providers/registry/types.ts +1 -1
- package/src/providers/request-pacing.ts +77 -19
- package/src/providers/routed-config.ts +339 -0
- package/src/providers/service-tier.ts +2 -1
- package/src/quota/window-mapping.ts +5 -2
- package/src/responses/anthropic-progress.ts +34 -0
- package/src/responses/assistant-replay.ts +35 -0
- package/src/responses/compaction-history-framing.ts +65 -0
- package/src/responses/compaction.ts +6 -1
- package/src/responses/incomplete-reason.ts +31 -0
- package/src/responses/parser.ts +78 -22
- package/src/responses/reasoning-envelope.ts +4 -0
- package/src/responses/reasoning-replay-cache.ts +24 -2
- package/src/responses/reasoning-retention.ts +173 -0
- package/src/responses/retained-compaction.ts +46 -0
- package/src/responses/schema.ts +23 -0
- package/src/responses/state.ts +32 -29
- package/src/router.ts +8 -321
- package/src/routing/health.ts +37 -22
- package/src/routing/history/build-file.ts +92 -0
- package/src/routing/history/indexer.ts +254 -221
- package/src/routing/history/ingest.ts +242 -0
- package/src/routing/history/rebuild-job.ts +111 -0
- package/src/routing/history/rebuild-protocol.ts +15 -0
- package/src/routing/history/rebuild-worker.ts +34 -0
- package/src/routing/profile.ts +1 -1
- package/src/server/admission-model-scope.ts +21 -1
- package/src/server/antigravity-direct-eligibility.ts +208 -0
- package/src/server/auth-cors.ts +15 -0
- package/src/server/chat-completions.ts +82 -10
- package/src/server/chat-native-reasoning.ts +123 -0
- package/src/server/chat-native-sse.ts +110 -7
- package/src/server/chat-native.ts +76 -17
- package/src/server/claude-messages.ts +164 -433
- package/src/server/effort-policy.ts +1 -1
- package/src/server/images.ts +15 -2
- package/src/server/index/desktop-compatibility-startup.ts +56 -0
- package/src/server/index/model-alias-id.ts +36 -0
- package/src/server/index/optional-listeners.ts +2 -0
- package/src/server/index/serve-options.ts +11 -3
- package/src/server/index/startup-warnings.ts +11 -0
- package/src/server/index/websocket-handler.ts +9 -0
- package/src/server/index.ts +14 -11
- package/src/server/inference/advisor-diagnostics.ts +31 -0
- package/src/server/inference/client-encoder-delivery.ts +6 -5
- package/src/server/login-shell-path.ts +146 -0
- package/src/server/management/advisor-routes.ts +202 -0
- package/src/server/management/agent-settings-routes.ts +22 -4
- package/src/server/management/claude-desktop-picker-routes.ts +1 -1
- package/src/server/management/combo-routes.ts +176 -50
- package/src/server/management/companion-routes.ts +4 -0
- package/src/server/management/config-routes.ts +77 -6
- package/src/server/management/context.ts +4 -0
- package/src/server/management/cursor-integration-routes.ts +1 -1
- package/src/server/management/desktop-compatibility-routes.ts +46 -0
- package/src/server/management/desktop-compatibility-runtime-routes.ts +46 -0
- package/src/server/management/desktop-compatibility-settings-routes.ts +27 -0
- package/src/server/management/model-routes.ts +13 -8
- package/src/server/management/model-rows.ts +14 -0
- package/src/server/management/native-integration-routes.ts +2 -7
- package/src/server/management/native-reasoning-retention-routes.ts +41 -0
- package/src/server/management/oauth-account-routes.ts +87 -14
- package/src/server/management/protocol-settings-patch.ts +1 -0
- package/src/server/management/provider-gcp-credential-routes.ts +29 -0
- package/src/server/management/provider-key-pacing-routes.ts +31 -0
- package/src/server/management/provider-overwrite-carry.ts +7 -0
- package/src/server/management/provider-routes.ts +25 -30
- package/src/server/management/route-registry.ts +21 -1
- package/src/server/management/sibling-guard.ts +1 -0
- package/src/server/management-api.ts +9 -1
- package/src/server/messages-antigravity-direct.ts +195 -0
- package/src/server/messages-native-tool-guard.ts +185 -0
- package/src/server/messages-native.ts +106 -22
- package/src/server/messages-shared.ts +431 -0
- package/src/server/relay.ts +1 -1
- package/src/server/request-log-terminal-status.ts +1 -1
- package/src/server/request-log.ts +13 -1
- package/src/server/responses/account-change-state.ts +8 -2
- package/src/server/responses/adapter-continuation.ts +48 -19
- package/src/server/responses/adapter-delivery.ts +43 -8
- package/src/server/responses/adapter-dispatch.ts +48 -4
- package/src/server/responses/advisor-plan-slot.ts +27 -0
- package/src/server/responses/advisor-retention.ts +117 -0
- package/src/server/responses/advisor-slot.ts +368 -0
- package/src/server/responses/code-mode-collab-surface.ts +116 -8
- package/src/server/responses/codex-ws-wire.ts +15 -8
- package/src/server/responses/compact.ts +303 -125
- package/src/server/responses/compaction-recovery.ts +18 -10
- package/src/server/responses/compaction-retention.ts +61 -0
- package/src/server/responses/context-overflow.ts +11 -6
- package/src/server/responses/core-auth.ts +6 -0
- package/src/server/responses/core-codex-account.ts +11 -1
- package/src/server/responses/core-combo-failure.ts +12 -1
- package/src/server/responses/core-combo.ts +141 -36
- package/src/server/responses/core-errors.ts +3 -3
- package/src/server/responses/core-lifetime.ts +7 -2
- package/src/server/responses/core-normalize.ts +11 -0
- package/src/server/responses/core-opaque-recovery.ts +35 -0
- package/src/server/responses/core-options.ts +51 -0
- package/src/server/responses/core-pipeline.ts +141 -0
- package/src/server/responses/core-replay.ts +25 -6
- package/src/server/responses/core.ts +3 -116
- package/src/server/responses/fetch-helpers.ts +73 -19
- package/src/server/responses/main-hard-lock-routing.ts +109 -0
- package/src/server/responses/native-response-control.ts +4 -2
- package/src/server/responses/passthrough-delivery.ts +19 -11
- package/src/server/responses/passthrough-dispatch.ts +29 -16
- package/src/server/responses/request-prepare.ts +144 -17
- package/src/server/responses/request-sidecar-auth.ts +2 -2
- package/src/server/responses/request-transport.ts +120 -27
- package/src/server/responses/response-effects.ts +1 -0
- package/src/server/responses/run-turn-execution.ts +166 -38
- package/src/server/responses/sidecar-execution.ts +98 -5
- package/src/server/responses/terminal-guard.ts +4 -17
- package/src/server/responses-undeclared-tool-guard.ts +30 -9
- package/src/server/startup-action-control.ts +16 -2
- package/src/server/startup-health-cache.ts +1 -0
- package/src/service/auth-preflight.ts +71 -0
- package/src/service/cli.ts +4 -2
- package/src/service/definition.ts +97 -0
- package/src/service/desktop-startup.ts +14 -0
- package/src/service/guards.ts +1 -61
- package/src/service/health-sentinel-linux.ts +112 -0
- package/src/service/health-sentinel-main.ts +99 -61
- package/src/service/health-sentinel-probe.ts +24 -7
- package/src/service/health.ts +5 -89
- package/src/service/launchd.ts +27 -7
- package/src/service/logging.ts +135 -0
- package/src/service/repair.ts +2 -1
- package/src/service/state.ts +7 -8
- package/src/service/systemd.ts +1 -1
- package/src/service/windows-guarded-manager.ts +2 -1
- package/src/service/windows-ops.ts +1 -1
- package/src/service/windows-scheduler.ts +2 -7
- package/src/service/windows-taskxml.ts +2 -2
- package/src/service/windows-wscript.ts +14 -0
- package/src/service.ts +4 -2
- package/src/sidecar/auth.ts +2 -0
- package/src/tray/windows-tray.ps1 +43 -24
- package/src/types/config.ts +124 -6
- package/src/types/opencode-go.ts +61 -0
- package/src/types/opencode-zen.ts +29 -0
- package/src/types/provider.ts +39 -6
- package/src/types/request.ts +38 -2
- package/src/types/tools.ts +2 -0
- package/src/types/wire.ts +29 -37
- package/src/types.ts +1 -0
- package/src/update/async-check.ts +1 -1
- package/src/update/badge.ts +2 -2
- package/src/update/index.ts +88 -15
- package/src/update/job-supervised-restart.ts +107 -0
- package/src/update/job.ts +32 -32
- package/src/update/notify.ts +1 -1
- package/src/update/npm-invocation.mjs +12 -2
- package/src/update/refresh-scheduler.ts +2 -2
- package/src/update/supervised-recovery.d.mts +27 -0
- package/src/update/supervised-recovery.mjs +157 -0
- package/src/usage/cache-diagnostic.ts +2 -0
- package/src/usage/cost.ts +48 -12
- package/src/usage/expected-prices.ts +15 -0
- package/src/usage/ledger-retention.ts +2 -1
- package/src/usage/ledger-scanner.ts +6 -5
- package/src/usage/log.ts +17 -8
- package/src/usage/summary.ts +22 -9
- package/src/usage/user-cost-overlays.ts +14 -19
- package/src/usage/user-cost-validation.ts +38 -0
- package/src/vision/eligibility.ts +13 -0
- package/src/web-search/gemini-executor.ts +2 -2
- package/src/web-search/loop.ts +55 -5
- package/src/web-search/progress-stream.ts +4 -1
- package/src/web-search/run-turn-loop.ts +9 -1
- package/assets/sponsors/packycode.png +0 -0
- package/gui/dist/assets/App-CSJvmjNs.css +0 -1
- package/gui/dist/assets/App-CZtqiGcw.js +0 -56
- package/gui/dist/assets/index-BB6uK6tU.css +0 -1
- package/gui/dist/assets/index-CTm4l-HQ.js +0 -94
- package/gui/dist/assets/quota-summary-BbEeRfPY.js +0 -1
|
@@ -18,8 +18,10 @@
|
|
|
18
18
|
*
|
|
19
19
|
* Display-time estimation only — these rows never affect billing.
|
|
20
20
|
*/
|
|
21
|
-
import type { OcxConfig, OcxProviderConfig, ProviderCostOverlay } from "../types";
|
|
22
|
-
import {
|
|
21
|
+
import type { OcxConfig, OcxProviderConfig, ProviderCostOverlay, PromptLengthPricing } from "../types";
|
|
22
|
+
import type { ExpectedPriceOverlay } from "./expected-prices";
|
|
23
|
+
import { validCost4 } from "./user-cost-validation";
|
|
24
|
+
export { COST4_RATE_KEYS, isValidCost4Rate, validCost4, isValidPromptLengthPricing } from "./user-cost-validation";
|
|
23
25
|
import { redactSecretString } from "../lib/redact";
|
|
24
26
|
import { isSelectableCodexPoolAccount, MAIN_CODEX_ACCOUNT_ID } from "../codex/account-id";
|
|
25
27
|
import { codexAccountLogLabel } from "../codex/account-label";
|
|
@@ -236,22 +238,13 @@ export function resetPreservedDiskOnlyProvidersForTests(): void {
|
|
|
236
238
|
preservationOwnerStates.clear();
|
|
237
239
|
}
|
|
238
240
|
|
|
239
|
-
/**
|
|
240
|
-
export
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
return
|
|
245
|
-
|
|
246
|
-
&& rate >= 0
|
|
247
|
-
&& rate <= MAX_COST4_RATE;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/** True when `value` is a complete cost entry: all four rates are non-negative finite numbers. */
|
|
251
|
-
function validCost4(value: unknown): value is ProviderCostOverlay {
|
|
252
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
253
|
-
const entry = value as Record<string, unknown>;
|
|
254
|
-
return COST4_RATE_KEYS.every(key => isValidCost4Rate(entry[key]));
|
|
241
|
+
/** Copy a validated override; automatic is represented by absence. */
|
|
242
|
+
export function copyPromptLengthPricing(policy: PromptLengthPricing): PromptLengthPricing | undefined {
|
|
243
|
+
if (policy.mode === "automatic") return undefined;
|
|
244
|
+
if (policy.mode !== "custom") return { mode: policy.mode };
|
|
245
|
+
const { input, output, cacheRead, cacheWrite } = policy.rates;
|
|
246
|
+
return { mode: "custom", thresholdTokens: policy.thresholdTokens, comparison: policy.comparison,
|
|
247
|
+
rates: { input, output, cacheRead, cacheWrite } };
|
|
255
248
|
}
|
|
256
249
|
|
|
257
250
|
/**
|
|
@@ -273,10 +266,11 @@ export function refreshUserCostOverlays(config: OcxConfig): void {
|
|
|
273
266
|
if (!costs || typeof costs !== "object" || Array.isArray(costs)) continue;
|
|
274
267
|
for (const [modelId, cost4] of Object.entries(costs)) {
|
|
275
268
|
if (!modelId.trim() || !validCost4(cost4)) continue;
|
|
269
|
+
const policy = cost4.promptLengthPricing && copyPromptLengthPricing(cost4.promptLengthPricing);
|
|
276
270
|
rows.push({
|
|
277
271
|
provider: providerName,
|
|
278
272
|
modelId,
|
|
279
|
-
// Copy
|
|
273
|
+
// Copy only validated rates and policy: a hand-edited row may
|
|
280
274
|
// carry extra properties (e.g. a misplaced apiKey) that must never
|
|
281
275
|
// reach display estimates or /api/logs through the registry.
|
|
282
276
|
cost4: {
|
|
@@ -285,6 +279,7 @@ export function refreshUserCostOverlays(config: OcxConfig): void {
|
|
|
285
279
|
cacheRead: cost4.cacheRead,
|
|
286
280
|
cacheWrite: cost4.cacheWrite,
|
|
287
281
|
},
|
|
282
|
+
...(policy ? { promptLengthPricing: policy } : {}),
|
|
288
283
|
// Display provenance only: redact token-shaped provider/model ids so
|
|
289
284
|
// the source string can never echo a pasted key. Matching still uses
|
|
290
285
|
// the raw fields, and the change-detection signature below MUST keep
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Pure model-cost validation shared by config, migration, and display lifting. */
|
|
2
|
+
import type { ProviderCostOverlay, PromptLengthPricing } from "../types";
|
|
3
|
+
import { MAX_COST4_RATE } from "./expected-prices";
|
|
4
|
+
|
|
5
|
+
/** Exact four fields accepted for a user-configured cost tuple. */
|
|
6
|
+
export const COST4_RATE_KEYS = ["input", "output", "cacheRead", "cacheWrite"] as const;
|
|
7
|
+
|
|
8
|
+
/** Shared per-rate predicate used by config validation, display sanitization, and runtime lifting. */
|
|
9
|
+
export function isValidCost4Rate(rate: unknown): rate is number {
|
|
10
|
+
return typeof rate === "number"
|
|
11
|
+
&& Number.isFinite(rate)
|
|
12
|
+
&& rate >= 0
|
|
13
|
+
&& rate <= MAX_COST4_RATE;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Complete base rates with a valid optional policy; extra top-level fields are never copied. */
|
|
17
|
+
export function validCost4(value: unknown): value is ProviderCostOverlay {
|
|
18
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
19
|
+
const entry = value as Record<string, unknown>;
|
|
20
|
+
return COST4_RATE_KEYS.every(key => Object.hasOwn(entry, key) && isValidCost4Rate(entry[key]))
|
|
21
|
+
&& (!Object.hasOwn(entry, "promptLengthPricing") || isValidPromptLengthPricing(entry.promptLengthPricing));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Strict nested policy boundary; diagnostics never echo untrusted policy fields. */
|
|
25
|
+
export function isValidPromptLengthPricing(value: unknown): value is PromptLengthPricing {
|
|
26
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
27
|
+
const policy = value as Record<string, unknown>;
|
|
28
|
+
if (!Object.hasOwn(policy, "mode")) return false;
|
|
29
|
+
if (policy.mode === "automatic" || policy.mode === "flat") return Object.keys(policy).length === 1;
|
|
30
|
+
if (policy.mode !== "custom" || Object.keys(policy).length !== 4
|
|
31
|
+
|| !["mode", "thresholdTokens", "comparison", "rates"].every(key => Object.hasOwn(policy, key))
|
|
32
|
+
|| typeof policy.thresholdTokens !== "number" || !Number.isSafeInteger(policy.thresholdTokens)
|
|
33
|
+
|| policy.thresholdTokens <= 0 || (policy.comparison !== "gt" && policy.comparison !== "gte")) return false;
|
|
34
|
+
const rates = policy.rates;
|
|
35
|
+
return !!rates && typeof rates === "object" && !Array.isArray(rates)
|
|
36
|
+
&& Object.keys(rates).length === COST4_RATE_KEYS.length
|
|
37
|
+
&& COST4_RATE_KEYS.every(key => Object.hasOwn(rates, key) && isValidCost4Rate((rates as Record<string, unknown>)[key]));
|
|
38
|
+
}
|
|
@@ -226,6 +226,19 @@ export function isVisionSidecarConsumer(config: VisionCapabilityConfig, provider
|
|
|
226
226
|
return isVisionSidecarConsumerWithCache(config, providerName, modelId, new Map());
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
+
/**
|
|
230
|
+
* `isVisionSidecarConsumer` for many rows of one config. Rows of the same provider share one
|
|
231
|
+
* registry enrichment instead of rebuilding it per row, which matters for `/api/models`
|
|
232
|
+
* listings with thousands of rows. Bind it to a single config snapshot; it does not observe
|
|
233
|
+
* provider changes made after the first lookup.
|
|
234
|
+
*/
|
|
235
|
+
export function visionSidecarConsumerClassifier(
|
|
236
|
+
config: VisionCapabilityConfig,
|
|
237
|
+
): (providerName: string, modelId: string) => boolean {
|
|
238
|
+
const cache: EnrichedProviderCache = new Map();
|
|
239
|
+
return (providerName, modelId) => isVisionSidecarConsumerWithCache(config, providerName, modelId, cache);
|
|
240
|
+
}
|
|
241
|
+
|
|
229
242
|
/**
|
|
230
243
|
* Can this model accept an image on the wire? Sources are consulted in descending
|
|
231
244
|
* trustworthiness; the first that speaks wins. `undefined` means nothing knows,
|
|
@@ -15,7 +15,7 @@ import { cancelBodyOnAbort, signalWithTimeout } from "../lib/abort";
|
|
|
15
15
|
import { readBoundedResponseBytes } from "../lib/bounded-body";
|
|
16
16
|
import { sidecarEnter } from "../lib/sidecar-tracker";
|
|
17
17
|
import { redactSecretString } from "../lib/redact";
|
|
18
|
-
import {
|
|
18
|
+
import { antigravityUserAgentForWireModel } from "../adapters/google-antigravity-wire";
|
|
19
19
|
import { resolveAntigravityEffortWireModel } from "../providers/antigravity-models";
|
|
20
20
|
import { getProviderRegistryEntry } from "../providers/registry";
|
|
21
21
|
import { MAX_SIDECAR_RESPONSE_BYTES, type WebSearchSource } from "./parse";
|
|
@@ -74,7 +74,7 @@ export async function runGeminiWebSearch(
|
|
|
74
74
|
headers: {
|
|
75
75
|
"Content-Type": "application/json",
|
|
76
76
|
"Authorization": `Bearer ${token}`,
|
|
77
|
-
"User-Agent":
|
|
77
|
+
"User-Agent": antigravityUserAgentForWireModel(wireModelId),
|
|
78
78
|
},
|
|
79
79
|
body: JSON.stringify(envelope),
|
|
80
80
|
signal: linkedSignal.signal,
|
package/src/web-search/loop.ts
CHANGED
|
@@ -6,6 +6,9 @@ import { cloneProviderOpaqueToolCallMetadata } from "../responses/provider-opaqu
|
|
|
6
6
|
import type { AttemptRecoveryKind } from "../usage/log";
|
|
7
7
|
import { isTruncatedStopReason } from "../responses/truncated-stop-reason";
|
|
8
8
|
import { bridgeToResponsesSSE } from "../bridge";
|
|
9
|
+
import { isTerminalRefusalIncomplete } from "../bridge/terminal-refusal";
|
|
10
|
+
import { guardEmptyToolCatalogStream, type ClientToolCatalogRestriction } from "../lib/empty-tool-catalog";
|
|
11
|
+
import { mergeUsage } from "../server/responses/empty-completion-guard";
|
|
9
12
|
import { runWebSearch, type SidecarOutcome, type SidecarOutcomeRecorder, type SidecarSettings } from "./executor";
|
|
10
13
|
import { runAnthropicWebSearch } from "./anthropic-executor";
|
|
11
14
|
import { runXaiWebSearch, type XaiSearchOptions } from "./xai-executor";
|
|
@@ -143,6 +146,18 @@ async function* replay(events: AdapterEvent[]): AsyncGenerator<AdapterEvent> {
|
|
|
143
146
|
for (const e of events) yield e;
|
|
144
147
|
}
|
|
145
148
|
|
|
149
|
+
function terminalUsage(events: AdapterEvent[]): OcxUsage | undefined {
|
|
150
|
+
for (const e of events) if (e.type === "done" || e.type === "incomplete") return e.usage;
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Hidden iterations add counters only: their checkpoint and raw wire usage are not the final terminal's. */
|
|
155
|
+
function countersOnly(usage: OcxUsage | undefined): OcxUsage | undefined {
|
|
156
|
+
if (!usage) return undefined;
|
|
157
|
+
const { contextTotalTokens: _context, rawUsage: _raw, ...counters } = usage;
|
|
158
|
+
return counters;
|
|
159
|
+
}
|
|
160
|
+
|
|
146
161
|
/**
|
|
147
162
|
* Collect the thinking block that preceded a web_search call in this iteration's events, so the
|
|
148
163
|
* replayed assistant turn can carry it. Anthropic extended thinking REQUIRES the assistant
|
|
@@ -189,7 +204,11 @@ function extractIterationThinking(events: AdapterEvent[]): OcxThinkingContent[]
|
|
|
189
204
|
};
|
|
190
205
|
|
|
191
206
|
for (const e of events) {
|
|
192
|
-
if (e.type === "
|
|
207
|
+
if (e.type === "text_delta" && e.anthropicThinkingSignature) {
|
|
208
|
+
flushVisible();
|
|
209
|
+
flushRaw();
|
|
210
|
+
parts.push({ type: "thinking", thinking: e.text, signature: e.anthropicThinkingSignature });
|
|
211
|
+
} else if (e.type === "thinking_delta") {
|
|
193
212
|
flushRaw();
|
|
194
213
|
thinking += e.thinking;
|
|
195
214
|
} else if (e.type === "reasoning_raw_delta") {
|
|
@@ -272,6 +291,7 @@ class LoopError extends Error {
|
|
|
272
291
|
*/
|
|
273
292
|
export interface WebSearchLoopDeps {
|
|
274
293
|
parsed: OcxParsedRequest;
|
|
294
|
+
clientToolCatalogRestriction?: ClientToolCatalogRestriction;
|
|
275
295
|
adapter: ProviderAdapter;
|
|
276
296
|
incomingMeta: IncomingMeta;
|
|
277
297
|
/**
|
|
@@ -297,6 +317,8 @@ export interface WebSearchLoopDeps {
|
|
|
297
317
|
settings: SidecarSettings;
|
|
298
318
|
maxSearches: number;
|
|
299
319
|
forceEmptyResponseId?: boolean;
|
|
320
|
+
/** Responses inbound only: deliver a non-retryable upstream refusal as `response.failed`. */
|
|
321
|
+
terminalRefusalAsFailed?: boolean;
|
|
300
322
|
abortSignal?: AbortSignal;
|
|
301
323
|
recordSidecarOutcome?: SidecarOutcomeRecorder;
|
|
302
324
|
beforeSidecarDispatch?: () => void;
|
|
@@ -320,6 +342,12 @@ export interface WebSearchLoopDeps {
|
|
|
320
342
|
onFirstOutput?: () => void;
|
|
321
343
|
/** Raw adapter usage at the terminal event, pre wire-normalization (see bridgeToResponsesSSE onUsage). */
|
|
322
344
|
onUsage?: (usage: OcxUsage | undefined) => void;
|
|
345
|
+
/**
|
|
346
|
+
* After an `on429` rotation, offered the usage of the hidden iterations the left credential
|
|
347
|
+
* served. Returning true means it was billed to that credential's attempt, so `onUsage` will not
|
|
348
|
+
* report it again.
|
|
349
|
+
*/
|
|
350
|
+
onRotatedUsage?: (usage: OcxUsage) => boolean;
|
|
323
351
|
/** Observe the exact adapter request selected for each routed-model iteration. */
|
|
324
352
|
onRequestBuilt?: (request: AdapterRequest) => void;
|
|
325
353
|
/** Request-scoped executor retains the core's selection binding across loop retries. */
|
|
@@ -407,6 +435,12 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
407
435
|
// One iteration beyond the forced answer is reserved for its empty-answer recovery below.
|
|
408
436
|
const HARD_CAP = maxSearches + 3;
|
|
409
437
|
let emptyAnswerRetries = 0;
|
|
438
|
+
// Every iteration re-sends the full context, but only the last one's terminal reaches the bridge.
|
|
439
|
+
// Search-calling passes and the discarded empty forced answer are summed here and added to what
|
|
440
|
+
// onUsage reports, so the request log meters what was actually sent. The client-facing terminal
|
|
441
|
+
// keeps the last iteration's usage: Codex and Claude Code size the context window from it, and
|
|
442
|
+
// a sum would read as a context several times larger and trigger early auto-compaction.
|
|
443
|
+
let hiddenUsage: OcxUsage | undefined;
|
|
410
444
|
let accountRefusalOutputStarted = false;
|
|
411
445
|
const connectTimeoutMs = deps.connectTimeoutMs ?? 200_000;
|
|
412
446
|
const routedModelStallTimeoutMs = deps.routedModelStallTimeoutMs ?? 200_000;
|
|
@@ -586,6 +620,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
586
620
|
const rotated = await deps.on429(prepared.response.headers.get("retry-after"), prepared.response.headers,
|
|
587
621
|
iterParsed, prepared.response);
|
|
588
622
|
if (!rotated) break;
|
|
623
|
+
if (hiddenUsage && deps.onRotatedUsage?.(hiddenUsage)) hiddenUsage = undefined;
|
|
589
624
|
const retainRefusal = prepared.response.status === 403
|
|
590
625
|
&& deps.incomingMeta?.providerName === "google-antigravity" && rotated.recoveryKind === "oauth-account-403";
|
|
591
626
|
// Keep the bounded refusal readable until the sibling actually returns headers.
|
|
@@ -681,6 +716,8 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
681
716
|
signal,
|
|
682
717
|
inactivityTimeoutMs: routedModelStallTimeoutMs,
|
|
683
718
|
translatorBudget,
|
|
719
|
+
// A pass that fails was still billed; the error path reports it with the hidden passes.
|
|
720
|
+
onErrorUsage: usage => { hiddenUsage = mergeUsage(hiddenUsage, usage); },
|
|
684
721
|
})) {
|
|
685
722
|
if (event.type === "heartbeat") yield event;
|
|
686
723
|
// Kiro's explicit-completion protocol marks ordinary assistant text as commentary while
|
|
@@ -689,7 +726,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
689
726
|
// Codex show only `Working` until both Kiro attempts had finished (often 30-40 seconds).
|
|
690
727
|
// Tool events remain buffered below, so the decision to invoke the hosted sidecar is still
|
|
691
728
|
// atomic and no search call can escape before its stream has validated successfully.
|
|
692
|
-
else if (event.type === "text_delta" && event.phase === "commentary") { accountRefusalOutputStarted = true; yield event; }
|
|
729
|
+
else if (event.type === "text_delta" && event.phase === "commentary" && !event.anthropicThinkingSignature) { accountRefusalOutputStarted = true; yield event; }
|
|
693
730
|
else if (liveWindowOpen && LIVE_STREAMABLE.has(event.type)) {
|
|
694
731
|
// Live events are ALSO buffered: the scanner still needs them for thinking extraction
|
|
695
732
|
// and the forced-answer output check; only the terminal replay skips them (by count).
|
|
@@ -914,7 +951,10 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
914
951
|
// limit-reached result instead of failing the turn (#6464: stripping
|
|
915
952
|
// the declaration makes some models emit the raw call as visible
|
|
916
953
|
// text).
|
|
917
|
-
|
|
954
|
+
// A refused iteration ends the turn even when it carried a search call: running the
|
|
955
|
+
// search would send the refused context back to the model (#7148).
|
|
956
|
+
const shouldLoop = split.calls.length > 0 && !split.hasRealToolCall
|
|
957
|
+
&& !split.passthrough.some(isTerminalRefusalIncomplete);
|
|
918
958
|
if (!shouldLoop) {
|
|
919
959
|
// #1001: a forced-answer pass that ends `done` must have produced
|
|
920
960
|
// usable output — never a malformed tool call, and never silence.
|
|
@@ -944,6 +984,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
944
984
|
stopReason: terminalEvent.stopReason,
|
|
945
985
|
eventTypes: [...new Set(split.passthrough.map(event => event.type))],
|
|
946
986
|
}));
|
|
987
|
+
hiddenUsage = mergeUsage(hiddenUsage, terminalEvent.usage);
|
|
947
988
|
if (!split.hasMalformedToolCall && !split.hasRealToolCall && emptyAnswerRetries === 0) {
|
|
948
989
|
emptyAnswerRetries++;
|
|
949
990
|
console.warn("[web-search-loop] empty forced answer — retrying once without tools");
|
|
@@ -966,13 +1007,19 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
966
1007
|
yield* replay(split.passthrough.slice(split.streamedPassthroughCount));
|
|
967
1008
|
return;
|
|
968
1009
|
}
|
|
1010
|
+
hiddenUsage = mergeUsage(hiddenUsage, terminalUsage(split.passthrough));
|
|
969
1011
|
// The thinking that led to the search belongs to the FIRST call's assistant replay turn.
|
|
1012
|
+
for (const event of split.passthrough.slice(split.streamedPassthroughCount)) {
|
|
1013
|
+
if (event.type === "text_delta" && event.anthropicThinkingSignature) yield event;
|
|
1014
|
+
}
|
|
970
1015
|
const iterationThinking = extractIterationThinking(split.passthrough);
|
|
971
1016
|
for (const [callIndex, call] of split.calls.entries()) {
|
|
972
1017
|
accountRefusalOutputStarted = true;
|
|
973
1018
|
yield* runSearchCall(call, callIndex === 0 ? iterationThinking : []);
|
|
974
1019
|
}
|
|
975
1020
|
} catch (e) {
|
|
1021
|
+
// The bridge reports no usage for either error; the iterations already sent still count.
|
|
1022
|
+
if (hiddenUsage) deps.onUsage?.(hiddenUsage);
|
|
976
1023
|
if (isTranslatorBudgetExceededError(e)) {
|
|
977
1024
|
yield {
|
|
978
1025
|
type: "error",
|
|
@@ -987,6 +1034,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
987
1034
|
return;
|
|
988
1035
|
}
|
|
989
1036
|
}
|
|
1037
|
+
if (hiddenUsage) deps.onUsage?.(hiddenUsage);
|
|
990
1038
|
yield { type: "error", message: "web-search loop exceeded its iteration cap" };
|
|
991
1039
|
} finally {
|
|
992
1040
|
if (abortSignal) abortSignal.removeEventListener("abort", linkAbort);
|
|
@@ -994,7 +1042,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
994
1042
|
}
|
|
995
1043
|
|
|
996
1044
|
const sse = bridgeToResponsesSSE(
|
|
997
|
-
produce(), parsed._responseModelId ?? parsed.modelId, toolNsMap, freeform, toolSearch, () => {
|
|
1045
|
+
guardEmptyToolCatalogStream(produce(), deps.clientToolCatalogRestriction, translatorBudget), parsed._responseModelId ?? parsed.modelId, toolNsMap, freeform, toolSearch, () => {
|
|
998
1046
|
const elapsed = Date.now() - loopT0;
|
|
999
1047
|
if (executedSearchCount > 0 || searchesExecuted > 0) {
|
|
1000
1048
|
console.warn(`[web-search-loop] cancelled — ${executedSearchCount} real searches, ${searchesExecuted - executedSearchCount} placeholders, ${elapsed}ms`);
|
|
@@ -1004,12 +1052,14 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
1004
1052
|
{
|
|
1005
1053
|
translatorBudget,
|
|
1006
1054
|
replayCacheScope: parsed._reasoningReplayScope,
|
|
1055
|
+
...(deps.clientToolCatalogRestriction ? { ...deps.clientToolCatalogRestriction, enforceDeclaredToolNames: false } : {}),
|
|
1007
1056
|
...(deps.forceEmptyResponseId ? { responseId: "" } : {}),
|
|
1057
|
+
...(deps.terminalRefusalAsFailed ? { terminalRefusalAsFailed: true } : {}),
|
|
1008
1058
|
hideThinkingSummary: parsed.options.hideThinkingSummary,
|
|
1009
1059
|
hideRawReasoning: parsed.options.hideRawReasoning,
|
|
1010
1060
|
...(deps.stallTimeoutSec !== undefined ? { stallTimeoutSec: deps.stallTimeoutSec } : {}),
|
|
1011
1061
|
...(deps.onFirstOutput ? { onFirstOutput: deps.onFirstOutput } : {}),
|
|
1012
|
-
...(deps.onUsage ? { onUsage: deps.onUsage } : {}),
|
|
1062
|
+
...(deps.onUsage ? { onUsage: (usage: OcxUsage | undefined) => deps.onUsage?.(mergeUsage(countersOnly(hiddenUsage), usage)) } : {}),
|
|
1013
1063
|
...(deps.onCompletedResponse ? { onCompletedResponse: deps.onCompletedResponse } : {}),
|
|
1014
1064
|
},
|
|
1015
1065
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ProviderAdapter } from "../adapters/base";
|
|
2
|
-
import type { AdapterEvent } from "../types";
|
|
2
|
+
import type { AdapterEvent, OcxUsage } from "../types";
|
|
3
3
|
import {
|
|
4
4
|
isTranslatorBudgetExceededError,
|
|
5
5
|
TRANSLATOR_MAX_TURN_BYTES,
|
|
@@ -32,6 +32,8 @@ export interface ParseStreamWithProgressOptions {
|
|
|
32
32
|
signal?: AbortSignal;
|
|
33
33
|
/** Kept configurable for focused tests; production callers should use the 5 second default. */
|
|
34
34
|
postTerminalDrainTimeoutMs?: number;
|
|
35
|
+
/** Receives the usage an adapter `error` event carries before the stream fails on it. */
|
|
36
|
+
onErrorUsage?: (usage: OcxUsage) => void;
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
type ParseStream = ProviderAdapter["parseStream"];
|
|
@@ -296,6 +298,7 @@ export async function* parseStreamWithProgress(
|
|
|
296
298
|
);
|
|
297
299
|
}
|
|
298
300
|
if (event.type === "error") {
|
|
301
|
+
if (event.usage) options.onErrorUsage?.(event.usage);
|
|
299
302
|
fail(event.code === "translation_buffer_limit"
|
|
300
303
|
? new TranslatorBudgetExceededError("live_transient", TRANSLATOR_MAX_TURN_BYTES)
|
|
301
304
|
: new Error(event.message));
|
|
@@ -124,7 +124,12 @@ function extractIterationContent(events: AdapterEvent[]): OcxAssistantContentPar
|
|
|
124
124
|
rawReasoning = "";
|
|
125
125
|
};
|
|
126
126
|
for (const e of events) {
|
|
127
|
-
if (e.type === "
|
|
127
|
+
if (e.type === "text_delta" && e.anthropicThinkingSignature) {
|
|
128
|
+
flushText();
|
|
129
|
+
flushVisible();
|
|
130
|
+
flushRaw();
|
|
131
|
+
parts.push({ type: "thinking", thinking: e.text, signature: e.anthropicThinkingSignature });
|
|
132
|
+
} else if (e.type === "thinking_delta") {
|
|
128
133
|
flushText();
|
|
129
134
|
flushRaw();
|
|
130
135
|
thinking += e.thinking;
|
|
@@ -533,6 +538,9 @@ export async function* runTurnWebSearchLoop(
|
|
|
533
538
|
return;
|
|
534
539
|
}
|
|
535
540
|
|
|
541
|
+
for (const event of replayEvents) {
|
|
542
|
+
if (event.type === "text_delta" && event.anthropicThinkingSignature) yield event;
|
|
543
|
+
}
|
|
536
544
|
const iterationContent = extractIterationContent(split.passthrough);
|
|
537
545
|
for (const [callIndex, call] of split.calls.entries()) {
|
|
538
546
|
if (abortSignal?.aborted) { yield abortEvent(); return; }
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.codex-account-controls{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:12px;min-width:0;display:flex}.codex-account-auto-switch{flex:none;align-items:center;gap:7px;min-width:0;display:flex}.codex-account-auto-switch-label{font-size:var(--text-label);color:var(--muted);font-weight:var(--weight-medium);white-space:nowrap}.codex-account-auto-switch-input-wrap{align-items:stretch;display:inline-flex;position:relative}.codex-account-auto-switch-input{width:76px;height:30px;font-size:var(--text-label);text-align:right;padding:4px 38px 4px 8px}.codex-account-auto-switch-unit{color:var(--muted);font-size:var(--text-label);pointer-events:none;position:absolute;top:50%;right:25px;transform:translateY(-50%)}.codex-account-auto-switch-input-wrap .ocx-stepper{width:22px}.codex-account-auto-switch-toggle{transform-origin:50%;margin-inline:-3px;transform:scale(.8)}.quota-row--codex-credits .quota-val{white-space:nowrap}.quota-compact:has(>.quota-row--codex-credits){grid-template-columns:minmax(34px,max-content) max-content minmax(34px,max-content) minmax(38px,max-content) minmax(58px,1fr) minmax(30px,max-content);column-gap:8px}.quota-compact:has(>.quota-row--codex-credits)>*{grid-column:1/-1}.quota-compact:has(>.quota-row--codex-credits)>.quota-row:not(.quota-row--credits){grid-template-columns:subgrid}.codex-auth-credits-toggle{align-items:center;gap:var(--space-2);white-space:nowrap;display:inline-flex}.codex-auth-credits-toggle__label{font-size:var(--text-label);color:var(--muted)}.codex-credit-spend{align-items:center;gap:var(--space-2);white-space:nowrap;display:inline-flex}.codex-credit-spend .toggle[aria-pressed=mixed] .toggle-knob{transform:translate(8px,-50%)}.codex-account-credits{align-items:center;gap:7px;display:inline-flex}.codex-account-credits__label{font-size:var(--text-label);color:var(--muted);font-weight:var(--weight-medium);white-space:nowrap}.codex-account-credits__toggle{transform-origin:50%;margin-inline:-3px;transform:scale(.8)}.anthropic-pool-card__native-messages{align-items:flex-start;gap:var(--space-2);margin-top:var(--space-3);cursor:pointer;display:flex}.anthropic-pool-card__native-messages>input{margin:var(--space-0-5) 0 0;accent-color:var(--accent)}.anthropic-pool-card__native-messages>input:focus-visible{outline:var(--space-0-5) solid var(--accent);outline-offset:var(--space-0-5)}.anthropic-pool-card__native-messages-copy{gap:var(--space-1);max-width:var(--prose-measure);display:grid}.anthropic-pool-card__native-messages:has(input:disabled){cursor:default}.anthropic-pool-card__save-warning{margin:var(--space-2) var(--space-4);color:var(--amber);font-size:var(--text-label);line-height:var(--leading-body)}.kiro-device-dialog{max-width:var(--prose-measure);border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--surface);width:100%;color:var(--text);padding:var(--space-6)}.kiro-device-dialog::backdrop{background:var(--glass-rail)}.kiro-login-choices{gap:var(--space-2);margin-block:var(--space-4);display:grid}.kiro-login-choices .btn{min-height:var(--control-touch);justify-content:flex-start}.kiro-device-code{align-items:center;gap:var(--space-3);margin-block:var(--space-4);flex-wrap:wrap;display:flex}.kiro-device-code-value{font-family:var(--font-code);font-size:var(--text-title);font-weight:var(--weight-semibold);letter-spacing:var(--tracking-wide)}.kiro-device-destination{overflow-wrap:anywhere;-webkit-user-select:all;user-select:all}.kiro-device-actions{justify-content:flex-end;gap:var(--space-2);margin-top:var(--space-4);display:flex}.logs-stack-end.logs-decode-rate{white-space:normal;display:flex}.logs-decode-rate>span:first-child{white-space:nowrap}.logs-decode-rate .text-caption{font-family:var(--font-ui);overflow-wrap:break-word}.log-detail-grid.log-detail-performance-grid{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}.log-detail-performance-grid>span{overflow-wrap:break-word;min-width:0}.logs-decode-basis-hint{grid-column:1/-1}.main-inner:has(.claude-page .claudecode-workspace-shell){max-width:980px}.claude-panel-lead{color:var(--muted);font-size:var(--text-label);line-height:var(--leading-body);max-width:var(--prose-measure);margin:0}.claudecode-connection-card{margin-bottom:var(--space-4)}.claudecode-workspace-shell .setting-controls>.custom-select{text-align:right}.claude-page .claude-status-bar{z-index:8;box-shadow:var(--shadow-sm);flex-wrap:wrap;padding:6px 8px 6px 14px;position:sticky;top:12px}.claude-page .claude-status-bar>.claude-status-health{margin-left:0}.claude-status-actions{align-items:center;gap:var(--space-3);margin-left:auto;display:flex}.claude-desktop-roles{margin-bottom:var(--space-4);overflow:hidden}.claude-desktop-section-title{font-size:var(--text-control);font-weight:var(--weight-semibold);line-height:var(--leading-ui);color:var(--text);align-items:baseline;gap:8px;margin:0;display:flex}.claude-desktop-section-title .count{color:var(--muted);font-weight:var(--weight-medium);font-family:var(--font-code);font-size:var(--text-label)}.claude-desktop-roles>.claude-desktop-section-title{padding:12px 16px 4px}.claude-desktop-roles-scope{color:var(--muted);font-size:var(--text-label);margin:0;padding:0 16px 8px}.claude-desktop-roles .setting-controls>.custom-select{text-align:right}.claude-desktop-roles .setting-label{flex:12rem}.claude-desktop-roles .setting-controls{flex:0 auto;min-width:0;max-width:min(60%,28rem)}.claude-desktop-roles .setting-controls>.custom-select,.claude-desktop-roles .select-trigger{max-width:100%}.claude-desktop-roles .select-trigger>span:first-child{text-overflow:ellipsis;min-width:0;overflow:hidden}.claude-desktop-roles .select-trigger>svg{flex:none}.claude-role-option{vertical-align:bottom;min-width:0;max-width:100%;display:inline-flex}.claude-role-option__route{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.claude-role-option__status{white-space:pre;color:var(--muted);flex:none}@media (width<=760px){.claude-desktop-roles .setting-controls{max-width:100%}.claude-desktop-roles .setting-controls>.custom-select,.claude-desktop-roles .select-trigger{width:100%}.claude-desktop-roles .select-trigger{justify-content:space-between}}.claude-desktop-list{gap:var(--space-2);margin-bottom:var(--space-4);flex-direction:column;display:flex}.claude-desktop-list-head{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;display:flex}.claude-desktop-list-hint{color:var(--muted);font-size:var(--text-label);margin:0}.claude-desktop-list-rows{margin:0;padding:0;list-style:none;overflow:hidden}.claude-desktop-list-row{border-top:1px solid var(--border-soft,var(--border));align-items:center;gap:10px;min-width:0;padding:8px 14px;display:flex}.claude-desktop-list-row:first-child{border-top:none}.claude-desktop-list-names{flex:1;align-items:baseline;gap:8px;min-width:0;display:flex}.claude-desktop-list-names strong,.claude-desktop-list-names code{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.claude-desktop-list-names strong{font-weight:var(--weight-medium)}.claude-desktop-list-names code{color:var(--muted);font-size:11px}.claude-row-quick{color:var(--accent)}.claude-desktop-advanced{margin-bottom:var(--space-4);border:1px solid var(--border);border-radius:var(--radius);background:var(--surface)}.claude-desktop-advanced>summary{cursor:pointer;flex-direction:column;gap:8px;padding:12px 14px;list-style:none;display:flex}.claude-desktop-advanced>summary::-webkit-details-marker{display:none}.claude-desktop-advanced-title{font-weight:var(--weight-semibold);color:var(--text);align-items:center;gap:6px;display:flex}.claude-desktop-advanced-chips{flex-wrap:wrap;gap:6px;display:flex}.claude-desktop-advanced-chip{border-radius:var(--radius-pill);background:var(--raised);max-width:100%;color:var(--muted);font-size:var(--text-label);align-items:baseline;gap:6px;padding:2px 10px;display:inline-flex}.claude-desktop-advanced-chip b{color:var(--text);font-weight:var(--weight-medium)}.claude-desktop-advanced-chip code{text-overflow:ellipsis;white-space:nowrap;max-width:220px;font-size:11px;overflow:hidden}.claude-desktop-advanced-count{font-family:var(--font-code);color:var(--faint);font-size:11px}.claude-desktop-advanced-desc{color:var(--muted);font-size:var(--text-label);margin:0;padding:0 14px 10px}.claude-desktop-advanced>.ocx-group-stack{padding:0 10px 10px}.remote-link-page{gap:var(--space-4);display:grid}.remote-link-page .page-head{align-items:flex-start}.remote-link-page .page-sub{max-width:var(--prose-measure);margin:0}.remote-link-panel{gap:var(--space-4);display:grid}.remote-link-off-preview{min-height:260px;position:relative;overflow:hidden}.remote-link-off-preview:after{content:"";pointer-events:none;-webkit-backdrop-filter:blur(7px);backdrop-filter:blur(7px);background:color-mix(in srgb, var(--bg) 24%, transparent);position:absolute;inset:0}.remote-link-preview-content{gap:var(--space-3);filter:grayscale();opacity:.64;-webkit-user-select:none;user-select:none;display:grid}.remote-link-preview-row{justify-content:space-between;align-items:center;gap:var(--space-3);padding:var(--space-3);border:1px solid var(--border-soft);border-radius:var(--radius-sm);background:var(--raised);display:flex}.remote-link-preview-lines{gap:var(--space-2);width:min(55%,300px);display:grid}.remote-link-preview-lines span{border-radius:var(--radius-pill);background:var(--border);height:8px;display:block}.remote-link-switch-row{z-index:1;justify-content:space-between;align-items:center;gap:var(--space-4);display:flex;position:relative}.remote-link-switch{width:var(--control-touch);height:var(--control-md);border:1px solid var(--border);border-radius:var(--radius-pill);background:var(--toggle-off-bg);cursor:pointer;padding:3px}.remote-link-switch:after{content:"";background:var(--toggle-dot-color);width:24px;height:24px;transition:transform var(--motion-fast) ease;border-radius:50%;display:block}.remote-link-switch[aria-checked=true]{background:var(--toggle-on-bg)}.remote-link-switch[aria-checked=true]:after{transform:translate(16px)}.remote-link-switch:focus-visible,.remote-link-role-card:focus-visible,.remote-link-sheet button:focus-visible,.remote-link-sheet a:focus-visible,.remote-link-row button:focus-visible{outline:2px solid var(--accent-ring);outline-offset:2px}.remote-link-role-grid{gap:var(--space-3);grid-template-columns:repeat(2,minmax(0,1fr));display:grid}.remote-link-role-card{min-height:132px;padding:var(--space-4);border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--raised);color:var(--text);text-align:left;cursor:pointer}.remote-link-role-card:hover{background:var(--raised-hover)}.remote-link-role-card[aria-disabled=true]{color:var(--muted);cursor:not-allowed;opacity:.72}.remote-link-role-card[aria-disabled=true]:hover{background:var(--raised)}.remote-link-role-card[aria-checked=true]{border-color:var(--text);box-shadow:0 0 0 1px var(--text)}.remote-link-role-card strong,.remote-link-role-card span{display:block}.remote-link-role-card span{margin-top:var(--space-2);color:var(--muted);font-size:var(--text-label)}.remote-link-toolbar{justify-content:space-between;align-items:center;gap:var(--space-3);display:flex}.remote-link-status{align-items:center;gap:var(--space-2);color:var(--muted);font-size:var(--text-label);display:inline-flex}.remote-link-status:before{content:"";background:var(--faint);border-radius:50%;flex:none;width:8px;height:8px}.remote-link-status[data-state=connected]:before{background:var(--green)}.remote-link-status[data-state=reconnecting]:before{background:var(--amber)}.remote-link-status[data-state=failed]:before{background:var(--red)}.remote-link-status[data-state=connecting]:before{background:var(--amber)}.remote-link-children{gap:var(--space-2);display:grid}.remote-link-row{gap:var(--space-3);padding:var(--space-3);border:1px solid var(--border-soft);border-radius:var(--radius-sm);background:var(--raised);grid-template-columns:minmax(0,1fr) auto;align-items:center;display:grid}.remote-link-row-main{gap:var(--space-2);min-width:0;display:grid}.remote-link-row-meta{gap:var(--space-3);color:var(--muted);font-size:var(--text-caption);flex-wrap:wrap;display:flex}.remote-link-row .btn{min-height:var(--control-touch)}.remote-link-error{color:var(--red)}.remote-link-hint{margin-top:var(--space-1);color:var(--muted);font-size:var(--text-label);overflow-wrap:anywhere;display:block}.remote-link-info{color:var(--muted);font-size:var(--text-label)}.remote-link-restart{gap:var(--space-2);padding:var(--space-4);border:1px solid var(--border-soft);border-radius:var(--radius-sm);background:var(--raised);display:grid}.remote-link-restart p{color:var(--muted);margin:0}.remote-link-fingerprint{padding:var(--space-3);overflow-wrap:anywhere;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--raised);font-family:var(--font-code);font-size:var(--text-label);margin:0}.remote-link-workspace-card{justify-content:space-between;align-items:center;gap:var(--space-4);display:flex}.remote-link-workspace-card p{margin:var(--space-1) 0 0;color:var(--muted);font-size:var(--text-label)}.remote-link-sheet{width:min(620px, calc(100vw - var(--space-4)));max-height:min(760px, calc(100dvh - var(--space-4)));padding:var(--space-6);border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--bg);color:var(--text);box-shadow:var(--shadow);margin:auto;overflow:auto}.remote-link-sheet::backdrop{background:color-mix(in srgb, var(--text) 24%, transparent)}.remote-link-sheet-head{justify-content:space-between;align-items:flex-start;gap:var(--space-3);display:flex}.remote-link-sheet-head h3{font-size:var(--text-title);margin:0}.remote-link-sheet-body{gap:var(--space-4);margin-top:var(--space-5);display:grid}.remote-link-sheet pre{white-space:pre-wrap;overflow-wrap:anywhere;font-family:var(--font-code);font-size:var(--text-label)}.remote-link-candidates{gap:var(--space-2);display:grid}.remote-link-candidate{justify-content:space-between;align-items:center;gap:var(--space-3);min-height:var(--control-touch);padding:var(--space-2) var(--space-3);border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--raised);color:var(--text);cursor:pointer;text-align:left;display:flex}.remote-link-candidate:hover{background:var(--raised-hover)}.remote-link-form{gap:var(--space-2);display:grid}.remote-link-form .field-label{margin-bottom:0}.remote-link-sheet-actions{justify-content:flex-end;gap:var(--space-2);flex-wrap:wrap;display:flex}.remote-link-confirm-dialog{width:min(460px, calc(100vw - var(--space-4)));padding:var(--space-5);border:1px solid var(--border);border-radius:var(--radius);background:var(--bg);color:var(--text);box-shadow:var(--shadow);margin:auto}.remote-link-confirm-dialog::backdrop{background:color-mix(in srgb, var(--text) 24%, transparent)}.remote-link-confirm-dialog h3{font-size:var(--text-subtitle);margin:0}.remote-link-confirm-dialog p{color:var(--muted)}@media (width<=620px){.remote-link-role-grid{grid-template-columns:1fr}.remote-link-workspace-card,.remote-link-switch-row{flex-direction:column;align-items:stretch}.remote-link-switch{align-self:flex-start}.remote-link-sheet{width:calc(100vw - var(--space-2));border-radius:var(--radius-lg) var(--radius-lg) 0 0;max-height:88dvh;margin:auto auto 0}}@media (prefers-reduced-motion:reduce){.remote-link-page *,.remote-link-page :before,.remote-link-page :after{scroll-behavior:auto!important;transition:none!important;animation:none!important}}.quota-summary-bar{z-index:var(--z-sticky);border-bottom:1px solid var(--border);background:var(--bg);min-height:34px;font-size:var(--text-label);align-items:center;gap:12px;padding:4px 16px;display:flex;position:sticky;top:0}.quota-summary-scroller{flex:1;align-items:center;gap:2px;min-width:0;display:flex}.quota-summary-list{overscroll-behavior-x:contain;scrollbar-width:none;flex-wrap:nowrap;flex:auto;align-items:center;gap:4px;min-width:0;margin:0;padding:3px;list-style:none;display:flex;overflow:auto hidden}.quota-summary-list::-webkit-scrollbar{display:none}.quota-summary-item{flex:none}.quota-summary-scroll{border:1px solid var(--border);background:var(--surface);width:22px;height:22px;color:var(--text);font:inherit;cursor:pointer;border-radius:999px;flex:none;place-items:center;padding:0;font-weight:600;line-height:1;display:inline-grid}.quota-summary-scroll:hover:not([aria-disabled=true]){background:var(--bg)}.quota-summary-scroll[aria-disabled=true]{color:var(--muted);opacity:.45;cursor:default}.quota-summary-scroll:focus-visible{outline:2px solid var(--text);outline-offset:1px}.quota-summary-chip{color:var(--text);font:inherit;white-space:nowrap;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:999px;align-items:center;gap:6px;padding:3px 8px;text-decoration:none;display:inline-flex}.quota-summary-chip:hover,.quota-summary-chip--open{border-color:var(--border)}.quota-summary-chip:focus-visible{outline:2px solid var(--text);outline-offset:1px}.quota-summary-name{color:var(--muted)}.quota-summary-pct{font-variant-numeric:tabular-nums;font-weight:600}.quota-summary-flag{width:14px;height:14px;color:var(--bg);font-size:var(--text-micro);border-radius:50%;place-items:center;font-weight:700;display:inline-grid}.quota-summary-item--warn .quota-summary-chip{background:var(--amber-soft)}.quota-summary-item--warn .quota-summary-pct{color:var(--amber)}.quota-summary-item--warn .quota-summary-flag{background:var(--amber)}.quota-summary-item--critical .quota-summary-chip{border-color:var(--red);background:var(--red-soft)}.quota-summary-item--critical .quota-summary-pct{color:var(--red)}.quota-summary-item--critical .quota-summary-flag{background:var(--red)}.quota-summary-popover{top:calc(var(--qs-pop-top,0) * 1px);left:calc(var(--qs-pop-left,0) * 1px);z-index:var(--z-popover);border:1px solid var(--border);background:var(--surface);border-radius:8px;min-width:260px;max-width:calc(100% - 16px);padding:10px 12px;position:fixed;box-shadow:0 8px 24px #00000024}.quota-summary-popover:before{content:"";left:calc(var(--qs-bridge-left,0) * 1px - 1px);right:calc(var(--qs-bridge-right,0) * 1px - 1px);height:calc((var(--qs-pop-gap,4) + 1) * 1px);position:absolute;bottom:100%}.quota-summary-popover-head{justify-content:space-between;align-items:center;gap:12px;margin-bottom:6px;display:flex}.quota-summary-badge{font-size:var(--text-caption);border-radius:999px;padding:1px 6px}.quota-summary-badge--warn{color:var(--amber);background:var(--amber-soft)}.quota-summary-badge--critical{color:var(--red);background:var(--red-soft)}.quota-summary-table{border-collapse:collapse;width:100%}.quota-summary-table th,.quota-summary-table td{text-align:left;white-space:nowrap;padding:3px 0;font-weight:400}.quota-summary-table td.quota-summary-row-pct{font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap;padding:3px 12px;font-weight:600}.quota-summary-row-reset{color:var(--muted);white-space:nowrap}.quota-summary-table th[scope=row]{white-space:normal;overflow-wrap:anywhere}.quota-summary-row--warn .quota-summary-row-pct{color:var(--amber)}.quota-summary-row--critical .quota-summary-row-pct{color:var(--red)}.quota-summary-popover-foot{color:var(--muted);font-size:var(--text-caption);flex-wrap:wrap;justify-content:space-between;gap:4px 12px;margin-top:6px;display:flex}.quota-summary-updated{color:var(--muted);font-size:var(--text-caption);white-space:nowrap;flex-shrink:0}.quota-summary-popover-link{color:var(--text);text-underline-offset:2px;text-decoration:underline}.quota-summary-popover-link:focus-visible{outline:2px solid var(--text);outline-offset:1px}.quota-summary-updated--stale{color:var(--amber)}.main:has(>.quota-summary-bar):has(>.main-inner--combos .combos-workspace-shell){flex-direction:column;height:100dvh;display:flex}.main:has(>.quota-summary-bar)>.main-inner.main-inner--combos:has(.combos-workspace-shell){flex:auto;height:auto;min-height:0}@media (width<=760px){.quota-summary-bar{padding:4px 10px;position:static}.quota-summary-popover{top:calc(var(--qs-pop-top,0) * 1px);min-width:0;left:8px;right:8px}.main:has(>.quota-summary-bar):has(>.main-inner--combos .combos-workspace-shell){height:100%;min-height:0}}.section-switcher{border:1px solid var(--border);border-radius:var(--radius-pill);background:var(--surface);flex-wrap:wrap;gap:2px;max-width:100%;margin:0 0 16px;padding:2px;display:inline-flex}.section-switcher-btn{appearance:none;color:var(--muted);border-radius:var(--radius-pill);cursor:pointer;font:inherit;font-size:var(--text-control);white-space:nowrap;background:0 0;border:none;align-items:center;padding:5px 14px;display:inline-flex}.section-switcher-btn:hover{color:var(--text)}.section-switcher-btn[aria-current=page]{background:var(--raised);color:var(--text);font-weight:var(--weight-semibold)}.section-switcher-btn:focus-visible{outline:2px solid var(--accent-ring);outline-offset:1px}@media (width<=760px){.section-switcher{display:flex}.section-switcher-btn{min-height:var(--control-touch);flex:auto;justify-content:center}}.app{--titlebar-h:40px;--tl-inset:80px;--chrome-clear:52px}.app--macos{--chrome-clear:124px;--sidebar-column:max(232px, calc(var(--tl-inset) + 52px))}.sidebar-top{z-index:calc(var(--z-overlay,30) + 1);width:232px;height:var(--titlebar-h,40px);border-bottom:1px solid var(--border);background:var(--glass-rail);-webkit-backdrop-filter:var(--glass-blur);-webkit-user-select:none;user-select:none;align-items:center;padding:0 10px 0 14px;display:flex;position:fixed;top:0;left:0}.app--macos .sidebar-top{width:var(--sidebar-column);padding-left:var(--tl-inset,80px)}.sidebar{padding-top:calc(var(--titlebar-h,40px) + 18px)}.sidebar-collapse{border-radius:var(--radius-sm);width:28px;height:28px;color:var(--muted);cursor:pointer;transition:background var(--motion-fast), color var(--motion-fast);background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.sidebar-collapse:hover{background:var(--accent-soft);color:var(--text)}.sidebar-collapse:focus-visible{outline:2px solid var(--accent-ring);outline-offset:2px}.sidebar-collapse svg{width:18px;height:18px}.main-top{z-index:var(--z-sticky);height:var(--titlebar-h,40px);background:var(--bg);border-bottom:1px solid var(--border);-webkit-user-select:none;user-select:none;align-items:stretch;display:flex;position:sticky;top:0}.main-top>.quota-summary-bar{border-bottom:none;flex:auto;min-width:0;min-height:0;padding:0 16px;position:static}.main:has(>.main-top):has(>.main-inner--combos .combos-workspace-shell){flex-direction:column;height:100dvh;display:flex}.main:has(>.main-top)>.main-inner.main-inner--combos:has(.combos-workspace-shell){flex:auto;height:auto;min-height:0}@media (width>=761px){.app{transition:grid-template-columns .16s}.app--macos.app--reduced-zoom{transition:none}.app--macos:not(.app--nav-collapsed){grid-template-columns:var(--sidebar-column) minmax(0, 1fr)}.app.app--nav-collapsed{grid-template-columns:0 1fr}.app--nav-collapsed .sidebar{display:none}.app--nav-collapsed .main{grid-column:2}.app--nav-collapsed .sidebar-top{-webkit-backdrop-filter:none;background:0 0;border-bottom:none;width:auto;margin:0;padding:0 12px}.app--macos.app--nav-collapsed .sidebar-top{padding-left:var(--tl-inset,80px)}.app--nav-collapsed .main-top,.app--nav-collapsed .main>.quota-summary-bar{padding-left:var(--chrome-clear,52px)}}@media (width<=760px){.sidebar-top{display:none}.main-top{z-index:auto;position:static}.main:has(>.main-top):has(>.main-inner--combos .combos-workspace-shell){height:100%;min-height:0}.app--macos .mobile-topbar{padding-left:var(--tl-inset,80px)}.app--macos .sidebar.open{padding-top:calc(var(--titlebar-h,40px) + 18px)}}@media (width<=320px){.app--macos .mobile-topbar{flex-wrap:wrap}.app--macos .mobile-topbar-actions{width:calc(100% + var(--tl-inset,80px));margin-left:calc(-1 * var(--tl-inset,80px));justify-content:flex-end}}
|