@cortexkit/opencode-antigravity-auth 2.2.0 → 3.0.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 +95 -89
- package/dist/cli.js +18469 -810
- package/dist/cli.js.map +4 -4
- package/dist/cli.meta.json +4079 -0
- package/dist/index.js +40923 -16450
- package/dist/index.js.map +4 -4
- package/dist/index.meta.json +6949 -0
- package/dist/server.js +50948 -0
- package/dist/server.js.map +7 -0
- package/dist/server.meta.json +7284 -0
- package/dist/src/cli.d.ts +46 -1
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +207 -2
- package/dist/src/cli.js.map +1 -1
- package/dist/src/common-auth-embedded/NOTICE.txt +21 -0
- package/dist/src/common-auth-embedded/auth-menu/accounts.d.ts +97 -0
- package/dist/src/common-auth-embedded/auth-menu/accounts.js +387 -0
- package/dist/src/common-auth-embedded/auth-menu/ansi.d.ts +26 -0
- package/dist/src/common-auth-embedded/auth-menu/ansi.js +98 -0
- package/dist/src/common-auth-embedded/auth-menu/confirm.d.ts +7 -0
- package/dist/src/common-auth-embedded/auth-menu/confirm.js +21 -0
- package/dist/src/common-auth-embedded/auth-menu/doctor.d.ts +52 -0
- package/dist/src/common-auth-embedded/auth-menu/doctor.js +81 -0
- package/dist/src/common-auth-embedded/auth-menu/index.d.ts +17 -0
- package/dist/src/common-auth-embedded/auth-menu/index.js +12 -0
- package/dist/src/common-auth-embedded/auth-menu/login.d.ts +55 -0
- package/dist/src/common-auth-embedded/auth-menu/login.js +83 -0
- package/dist/src/common-auth-embedded/auth-menu/menu.d.ts +59 -0
- package/dist/src/common-auth-embedded/auth-menu/menu.js +73 -0
- package/dist/src/common-auth-embedded/auth-menu/opencode-v1.d.ts +49 -0
- package/dist/src/common-auth-embedded/auth-menu/opencode-v1.js +47 -0
- package/dist/src/common-auth-embedded/auth-menu/select.d.ts +21 -0
- package/dist/src/common-auth-embedded/auth-menu/select.js +159 -0
- package/dist/src/common-auth-embedded/auth-menu/terminal.d.ts +43 -0
- package/dist/src/common-auth-embedded/auth-menu/terminal.js +19 -0
- package/dist/src/common-auth-embedded/claustrum/consumer.d.ts +102 -0
- package/dist/src/common-auth-embedded/claustrum/consumer.js +298 -0
- package/dist/src/common-auth-embedded/claustrum/custody.d.ts +175 -0
- package/dist/src/common-auth-embedded/claustrum/custody.js +354 -0
- package/dist/src/common-auth-embedded/claustrum/enrollment.d.ts +158 -0
- package/dist/src/common-auth-embedded/claustrum/enrollment.js +759 -0
- package/dist/src/common-auth-embedded/claustrum/errors.d.ts +16 -0
- package/dist/src/common-auth-embedded/claustrum/errors.js +8 -0
- package/dist/src/common-auth-embedded/claustrum/host-slot.d.ts +39 -0
- package/dist/src/common-auth-embedded/claustrum/host-slot.js +72 -0
- package/dist/src/common-auth-embedded/claustrum/index.d.ts +18 -0
- package/dist/src/common-auth-embedded/claustrum/index.js +22 -0
- package/dist/src/common-auth-embedded/claustrum/interlock.d.ts +27 -0
- package/dist/src/common-auth-embedded/claustrum/interlock.js +29 -0
- package/dist/src/common-auth-embedded/claustrum/roster.d.ts +208 -0
- package/dist/src/common-auth-embedded/claustrum/roster.js +536 -0
- package/dist/src/common-auth-embedded/commands/builtins.d.ts +71 -0
- package/dist/src/common-auth-embedded/commands/builtins.js +534 -0
- package/dist/src/common-auth-embedded/commands/index.d.ts +10 -0
- package/dist/src/common-auth-embedded/commands/index.js +5 -0
- package/dist/src/common-auth-embedded/commands/menu.d.ts +61 -0
- package/dist/src/common-auth-embedded/commands/menu.js +300 -0
- package/dist/src/common-auth-embedded/commands/model.d.ts +238 -0
- package/dist/src/common-auth-embedded/commands/model.js +16 -0
- package/dist/src/common-auth-embedded/commands/pi.d.ts +23 -0
- package/dist/src/common-auth-embedded/commands/pi.js +206 -0
- package/dist/src/common-auth-embedded/commands/seam.d.ts +72 -0
- package/dist/src/common-auth-embedded/commands/seam.js +301 -0
- package/dist/src/common-auth-embedded/fs/atomic-write.d.ts +20 -0
- package/dist/src/common-auth-embedded/fs/atomic-write.js +80 -0
- package/dist/src/common-auth-embedded/fs/index.d.ts +7 -0
- package/dist/src/common-auth-embedded/fs/index.js +6 -0
- package/dist/src/common-auth-embedded/fs/lock-constants.d.ts +14 -0
- package/dist/src/common-auth-embedded/fs/lock-constants.js +14 -0
- package/dist/src/common-auth-embedded/fs/refresh-file-lock.d.ts +33 -0
- package/dist/src/common-auth-embedded/fs/refresh-file-lock.js +501 -0
- package/dist/src/common-auth-embedded/fs/with-lock.d.ts +33 -0
- package/dist/src/common-auth-embedded/fs/with-lock.js +48 -0
- package/dist/src/common-auth-embedded/logger/capture-sink.d.ts +14 -0
- package/dist/src/common-auth-embedded/logger/capture-sink.js +13 -0
- package/dist/src/common-auth-embedded/logger/engine.d.ts +100 -0
- package/dist/src/common-auth-embedded/logger/engine.js +246 -0
- package/dist/src/common-auth-embedded/logger/index.d.ts +6 -0
- package/dist/src/common-auth-embedded/logger/index.js +3 -0
- package/dist/src/common-auth-embedded/logger/redact.d.ts +11 -0
- package/dist/src/common-auth-embedded/logger/redact.js +83 -0
- package/dist/src/common-auth-embedded/opencode2/errors.d.ts +25 -0
- package/dist/src/common-auth-embedded/opencode2/errors.js +15 -0
- package/dist/src/common-auth-embedded/opencode2/index.d.ts +8 -0
- package/dist/src/common-auth-embedded/opencode2/index.js +4 -0
- package/dist/src/common-auth-embedded/opencode2/install.d.ts +55 -0
- package/dist/src/common-auth-embedded/opencode2/install.js +886 -0
- package/dist/src/common-auth-embedded/opencode2/integration.d.ts +112 -0
- package/dist/src/common-auth-embedded/opencode2/integration.js +143 -0
- package/dist/src/common-auth-embedded/opencode2/sse.d.ts +12 -0
- package/dist/src/common-auth-embedded/opencode2/sse.js +60 -0
- package/dist/src/common-auth-embedded/opencode2/types.d.ts +413 -0
- package/dist/src/common-auth-embedded/pi-slot/index.d.ts +3 -0
- package/dist/src/common-auth-embedded/pi-slot/index.js +2 -0
- package/dist/src/common-auth-embedded/pi-slot/lock.js +212 -0
- package/dist/src/common-auth-embedded/pi-slot/slot.d.ts +49 -0
- package/dist/src/common-auth-embedded/pi-slot/slot.js +383 -0
- package/dist/src/common-auth-embedded/quota/codec.d.ts +11 -0
- package/dist/src/common-auth-embedded/quota/codec.js +12 -0
- package/dist/src/common-auth-embedded/quota/format.d.ts +46 -0
- package/dist/src/common-auth-embedded/quota/format.js +138 -0
- package/dist/src/common-auth-embedded/quota/index.d.ts +10 -0
- package/dist/src/common-auth-embedded/quota/index.js +5 -0
- package/dist/src/common-auth-embedded/quota/map.d.ts +63 -0
- package/dist/src/common-auth-embedded/quota/map.js +105 -0
- package/dist/src/common-auth-embedded/quota/merge.d.ts +48 -0
- package/dist/src/common-auth-embedded/quota/merge.js +162 -0
- package/dist/src/common-auth-embedded/quota/projection.d.ts +64 -0
- package/dist/src/common-auth-embedded/quota/projection.js +134 -0
- package/dist/src/common-auth-embedded/routing/admission.d.ts +93 -0
- package/dist/src/common-auth-embedded/routing/admission.js +142 -0
- package/dist/src/common-auth-embedded/routing/index.d.ts +8 -0
- package/dist/src/common-auth-embedded/routing/index.js +4 -0
- package/dist/src/common-auth-embedded/routing/ordered.d.ts +47 -0
- package/dist/src/common-auth-embedded/routing/ordered.js +58 -0
- package/dist/src/common-auth-embedded/routing/pins.d.ts +22 -0
- package/dist/src/common-auth-embedded/routing/pins.js +34 -0
- package/dist/src/common-auth-embedded/routing/sticky.d.ts +158 -0
- package/dist/src/common-auth-embedded/routing/sticky.js +339 -0
- package/dist/src/common-auth-embedded/rpc/client.d.ts +3 -0
- package/dist/src/common-auth-embedded/rpc/client.js +2 -0
- package/dist/src/common-auth-embedded/rpc/index.d.ts +10 -0
- package/dist/src/common-auth-embedded/rpc/index.js +5 -0
- package/dist/src/common-auth-embedded/rpc/notifications.d.ts +73 -0
- package/dist/src/common-auth-embedded/rpc/notifications.js +100 -0
- package/dist/src/common-auth-embedded/rpc/port-file.d.ts +33 -0
- package/dist/src/common-auth-embedded/rpc/port-file.js +217 -0
- package/dist/src/common-auth-embedded/rpc/rpc-client.d.ts +30 -0
- package/dist/src/common-auth-embedded/rpc/rpc-client.js +253 -0
- package/dist/src/common-auth-embedded/rpc/rpc-server.d.ts +58 -0
- package/dist/src/common-auth-embedded/rpc/rpc-server.js +311 -0
- package/dist/src/common-auth-embedded/rpc/server-registry.d.ts +11 -0
- package/dist/src/common-auth-embedded/rpc/server-registry.js +47 -0
- package/dist/src/common-auth-embedded/source-output.json +1326 -0
- package/dist/src/common-auth-embedded/store/attribution.d.ts +28 -0
- package/dist/src/common-auth-embedded/store/attribution.js +60 -0
- package/dist/src/common-auth-embedded/store/errors.d.ts +55 -0
- package/dist/src/common-auth-embedded/store/errors.js +38 -0
- package/dist/src/common-auth-embedded/store/hooks.d.ts +12 -0
- package/dist/src/common-auth-embedded/store/hooks.js +34 -0
- package/dist/src/common-auth-embedded/store/identity.d.ts +39 -0
- package/dist/src/common-auth-embedded/store/identity.js +79 -0
- package/dist/src/common-auth-embedded/store/index.d.ts +21 -0
- package/dist/src/common-auth-embedded/store/index.js +7 -0
- package/dist/src/common-auth-embedded/store/mutate.d.ts +189 -0
- package/dist/src/common-auth-embedded/store/mutate.js +500 -0
- package/dist/src/common-auth-embedded/store/pool.d.ts +196 -0
- package/dist/src/common-auth-embedded/store/pool.js +120 -0
- package/dist/src/common-auth-embedded/store/provider-state.d.ts +131 -0
- package/dist/src/common-auth-embedded/store/provider-state.js +226 -0
- package/dist/src/common-auth-embedded/store/publication.d.ts +47 -0
- package/dist/src/common-auth-embedded/store/publication.js +304 -0
- package/dist/src/common-auth-embedded/store/pull.d.ts +36 -0
- package/dist/src/common-auth-embedded/store/pull.js +143 -0
- package/dist/src/common-auth-embedded/store/refresh-lock.d.ts +63 -0
- package/dist/src/common-auth-embedded/store/refresh-lock.js +136 -0
- package/dist/src/common-auth-embedded/store/refresh.d.ts +72 -0
- package/dist/src/common-auth-embedded/store/refresh.js +225 -0
- package/dist/src/common-auth-embedded/store/reserved.js +13 -0
- package/dist/src/common-auth-embedded/store/rows.d.ts +313 -0
- package/dist/src/common-auth-embedded/store/rows.js +1258 -0
- package/dist/src/common-auth-embedded/store/runtime.d.ts +36 -0
- package/dist/src/common-auth-embedded/store/runtime.js +68 -0
- package/dist/src/common-auth-embedded/store/schema.d.ts +443 -0
- package/dist/src/common-auth-embedded/store/schema.js +754 -0
- package/dist/src/common-auth-embedded/store/settings.d.ts +63 -0
- package/dist/src/common-auth-embedded/store/settings.js +120 -0
- package/dist/src/common-auth-embedded/store/torn.d.ts +78 -0
- package/dist/src/common-auth-embedded/store/torn.js +294 -0
- package/dist/src/common-auth-embedded/tui/index.d.ts +8 -0
- package/dist/src/common-auth-embedded/tui/index.js +21 -0
- package/dist/src/common-auth-embedded/util/any-signal.js +42 -0
- package/dist/src/constants.d.ts +1 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +4 -0
- package/dist/src/constants.js.map +1 -1
- package/dist/src/ga/proxy-guard.d.ts +120 -0
- package/dist/src/ga/proxy-guard.d.ts.map +1 -0
- package/dist/src/ga/proxy-guard.js +269 -0
- package/dist/src/ga/proxy-guard.js.map +1 -0
- package/dist/src/ga/rpc/protocol.d.ts +504 -0
- package/dist/src/ga/rpc/protocol.d.ts.map +1 -0
- package/dist/src/ga/rpc/protocol.js +1278 -0
- package/dist/src/ga/rpc/protocol.js.map +1 -0
- package/dist/src/ga/server/auth.d.ts +9 -0
- package/dist/src/ga/server/auth.d.ts.map +1 -0
- package/dist/src/ga/server/auth.js +37 -0
- package/dist/src/ga/server/auth.js.map +1 -0
- package/dist/src/ga/server/index.d.ts +576 -0
- package/dist/src/ga/server/index.d.ts.map +1 -0
- package/dist/src/ga/server/index.js +1012 -0
- package/dist/src/ga/server/index.js.map +1 -0
- package/dist/src/ga/tui/host-ga.d.ts +350 -0
- package/dist/src/ga/tui/host-ga.d.ts.map +1 -0
- package/dist/src/ga/tui/host-ga.js +1242 -0
- package/dist/src/ga/tui/host-ga.js.map +1 -0
- package/dist/src/logging/provider-key-policy.d.ts +9 -0
- package/dist/src/logging/provider-key-policy.d.ts.map +1 -0
- package/dist/src/logging/provider-key-policy.js +11 -0
- package/dist/src/logging/provider-key-policy.js.map +1 -0
- package/dist/src/plugin/account-access.d.ts +130 -15
- package/dist/src/plugin/account-access.d.ts.map +1 -1
- package/dist/src/plugin/account-access.js +331 -129
- package/dist/src/plugin/account-access.js.map +1 -1
- package/dist/src/plugin/account-blocks.d.ts +102 -0
- package/dist/src/plugin/account-blocks.d.ts.map +1 -0
- package/dist/src/plugin/account-blocks.js +196 -0
- package/dist/src/plugin/account-blocks.js.map +1 -0
- package/dist/src/plugin/accounts.d.ts +85 -1
- package/dist/src/plugin/accounts.d.ts.map +1 -1
- package/dist/src/plugin/accounts.js +127 -3
- package/dist/src/plugin/accounts.js.map +1 -1
- package/dist/src/plugin/auth-loader.d.ts +69 -5
- package/dist/src/plugin/auth-loader.d.ts.map +1 -1
- package/dist/src/plugin/auth-loader.js +355 -52
- package/dist/src/plugin/auth-loader.js.map +1 -1
- package/dist/src/plugin/background-quota-refresh.d.ts +54 -8
- package/dist/src/plugin/background-quota-refresh.d.ts.map +1 -1
- package/dist/src/plugin/background-quota-refresh.js +81 -24
- package/dist/src/plugin/background-quota-refresh.js.map +1 -1
- package/dist/src/plugin/cache/index.d.ts +1 -1
- package/dist/src/plugin/cache/index.d.ts.map +1 -1
- package/dist/src/plugin/cache/index.js +1 -1
- package/dist/src/plugin/cache/index.js.map +1 -1
- package/dist/src/plugin/cache/signature-cache.d.ts +55 -10
- package/dist/src/plugin/cache/signature-cache.d.ts.map +1 -1
- package/dist/src/plugin/cache/signature-cache.js +100 -41
- package/dist/src/plugin/cache/signature-cache.js.map +1 -1
- package/dist/src/plugin/cache.d.ts +80 -16
- package/dist/src/plugin/cache.d.ts.map +1 -1
- package/dist/src/plugin/cache.js +339 -200
- package/dist/src/plugin/cache.js.map +1 -1
- package/dist/src/plugin/catalog.d.ts +4 -18
- package/dist/src/plugin/catalog.d.ts.map +1 -1
- package/dist/src/plugin/catalog.js +11 -41
- package/dist/src/plugin/catalog.js.map +1 -1
- package/dist/src/plugin/command-apply.d.ts +58 -0
- package/dist/src/plugin/command-apply.d.ts.map +1 -0
- package/dist/src/plugin/command-apply.js +168 -0
- package/dist/src/plugin/command-apply.js.map +1 -0
- package/dist/src/plugin/command-data.d.ts +1 -0
- package/dist/src/plugin/command-data.d.ts.map +1 -1
- package/dist/src/plugin/command-data.js +2 -0
- package/dist/src/plugin/command-data.js.map +1 -1
- package/dist/src/plugin/commands.d.ts +142 -132
- package/dist/src/plugin/commands.d.ts.map +1 -1
- package/dist/src/plugin/commands.js +214 -686
- package/dist/src/plugin/commands.js.map +1 -1
- package/dist/src/plugin/config/index.d.ts +1 -1
- package/dist/src/plugin/config/index.d.ts.map +1 -1
- package/dist/src/plugin/config/index.js +1 -1
- package/dist/src/plugin/config/index.js.map +1 -1
- package/dist/src/plugin/config/loader.d.ts +37 -1
- package/dist/src/plugin/config/loader.d.ts.map +1 -1
- package/dist/src/plugin/config/loader.js +64 -9
- package/dist/src/plugin/config/loader.js.map +1 -1
- package/dist/src/plugin/config/operator-settings-schema.d.ts +2 -2
- package/dist/src/plugin/config/schema.d.ts +2 -2
- package/dist/src/plugin/config/writer.d.ts +7 -0
- package/dist/src/plugin/config/writer.d.ts.map +1 -1
- package/dist/src/plugin/config/writer.js +10 -1
- package/dist/src/plugin/config/writer.js.map +1 -1
- package/dist/src/plugin/debug.d.ts +72 -29
- package/dist/src/plugin/debug.d.ts.map +1 -1
- package/dist/src/plugin/debug.js +353 -239
- package/dist/src/plugin/debug.js.map +1 -1
- package/dist/src/plugin/fetch/retry-state.d.ts +1 -1
- package/dist/src/plugin/fetch/retry-state.d.ts.map +1 -1
- package/dist/src/plugin/fetch/retry-state.js.map +1 -1
- package/dist/src/plugin/fetch-interceptor.d.ts +66 -11
- package/dist/src/plugin/fetch-interceptor.d.ts.map +1 -1
- package/dist/src/plugin/fetch-interceptor.js +228 -1347
- package/dist/src/plugin/fetch-interceptor.js.map +1 -1
- package/dist/src/plugin/fetch-routing.d.ts +7 -2
- package/dist/src/plugin/fetch-routing.d.ts.map +1 -1
- package/dist/src/plugin/fetch-routing.js +7 -4
- package/dist/src/plugin/fetch-routing.js.map +1 -1
- package/dist/src/plugin/ga-location-services.d.ts +389 -0
- package/dist/src/plugin/ga-location-services.d.ts.map +1 -0
- package/dist/src/plugin/ga-location-services.js +1838 -0
- package/dist/src/plugin/ga-location-services.js.map +1 -0
- package/dist/src/plugin/gemini-dump.d.ts +37 -12
- package/dist/src/plugin/gemini-dump.d.ts.map +1 -1
- package/dist/src/plugin/gemini-dump.js +42 -21
- package/dist/src/plugin/gemini-dump.js.map +1 -1
- package/dist/src/plugin/google-search-tool.d.ts +2 -1
- package/dist/src/plugin/google-search-tool.d.ts.map +1 -1
- package/dist/src/plugin/google-search-tool.js +4 -1
- package/dist/src/plugin/google-search-tool.js.map +1 -1
- package/dist/src/plugin/index.d.ts.map +1 -1
- package/dist/src/plugin/index.js +505 -141
- package/dist/src/plugin/index.js.map +1 -1
- package/dist/src/plugin/killswitch.d.ts +1 -2
- package/dist/src/plugin/killswitch.d.ts.map +1 -1
- package/dist/src/plugin/lifecycle.d.ts +24 -1
- package/dist/src/plugin/lifecycle.d.ts.map +1 -1
- package/dist/src/plugin/lifecycle.js +95 -8
- package/dist/src/plugin/lifecycle.js.map +1 -1
- package/dist/src/plugin/logger.d.ts +61 -10
- package/dist/src/plugin/logger.d.ts.map +1 -1
- package/dist/src/plugin/logger.js +134 -63
- package/dist/src/plugin/logger.js.map +1 -1
- package/dist/src/plugin/neutral-types.d.ts +42 -0
- package/dist/src/plugin/neutral-types.d.ts.map +1 -0
- package/dist/src/plugin/neutral-types.js +12 -0
- package/dist/src/plugin/neutral-types.js.map +1 -0
- package/dist/src/plugin/oauth-methods.d.ts +2 -1
- package/dist/src/plugin/oauth-methods.d.ts.map +1 -1
- package/dist/src/plugin/oauth-methods.js +173 -88
- package/dist/src/plugin/oauth-methods.js.map +1 -1
- package/dist/src/plugin/operator-settings.d.ts +34 -0
- package/dist/src/plugin/operator-settings.d.ts.map +1 -1
- package/dist/src/plugin/operator-settings.js +105 -2
- package/dist/src/plugin/operator-settings.js.map +1 -1
- package/dist/src/plugin/persist-account-pool.d.ts +63 -2
- package/dist/src/plugin/persist-account-pool.d.ts.map +1 -1
- package/dist/src/plugin/persist-account-pool.js +125 -2
- package/dist/src/plugin/persist-account-pool.js.map +1 -1
- package/dist/src/plugin/quota.d.ts +335 -35
- package/dist/src/plugin/quota.d.ts.map +1 -1
- package/dist/src/plugin/quota.js +825 -95
- package/dist/src/plugin/quota.js.map +1 -1
- package/dist/src/plugin/refresh-queue.d.ts +35 -5
- package/dist/src/plugin/refresh-queue.d.ts.map +1 -1
- package/dist/src/plugin/refresh-queue.js +50 -16
- package/dist/src/plugin/refresh-queue.js.map +1 -1
- package/dist/src/plugin/request-helpers.d.ts +30 -5
- package/dist/src/plugin/request-helpers.d.ts.map +1 -1
- package/dist/src/plugin/request-helpers.js +82 -17
- package/dist/src/plugin/request-helpers.js.map +1 -1
- package/dist/src/plugin/request.d.ts +63 -15
- package/dist/src/plugin/request.d.ts.map +1 -1
- package/dist/src/plugin/request.js +190 -60
- package/dist/src/plugin/request.js.map +1 -1
- package/dist/src/plugin/session-context.d.ts.map +1 -1
- package/dist/src/plugin/session-context.js +5 -2
- package/dist/src/plugin/session-context.js.map +1 -1
- package/dist/src/plugin/shared/local-grant.d.ts +26 -0
- package/dist/src/plugin/shared/local-grant.d.ts.map +1 -0
- package/dist/src/plugin/shared/local-grant.js +19 -0
- package/dist/src/plugin/shared/local-grant.js.map +1 -0
- package/dist/src/plugin/shared/request-cancellation.d.ts +12 -0
- package/dist/src/plugin/shared/request-cancellation.d.ts.map +1 -0
- package/dist/src/plugin/shared/request-cancellation.js +118 -0
- package/dist/src/plugin/shared/request-cancellation.js.map +1 -0
- package/dist/src/plugin/shared/request-services.d.ts +375 -0
- package/dist/src/plugin/shared/request-services.d.ts.map +1 -0
- package/dist/src/plugin/shared/request-services.js +1743 -0
- package/dist/src/plugin/shared/request-services.js.map +1 -0
- package/dist/src/plugin/shared/runtime.d.ts +217 -0
- package/dist/src/plugin/shared/runtime.d.ts.map +1 -0
- package/dist/src/plugin/shared/runtime.js +345 -0
- package/dist/src/plugin/shared/runtime.js.map +1 -0
- package/dist/src/plugin/shared/source-sidebar.d.ts +15 -0
- package/dist/src/plugin/shared/source-sidebar.d.ts.map +1 -0
- package/dist/src/plugin/shared/source-sidebar.js +41 -0
- package/dist/src/plugin/shared/source-sidebar.js.map +1 -0
- package/dist/src/plugin/shared/vault-menu.d.ts +5 -0
- package/dist/src/plugin/shared/vault-menu.d.ts.map +1 -0
- package/dist/src/plugin/shared/vault-menu.js +49 -0
- package/dist/src/plugin/shared/vault-menu.js.map +1 -0
- package/dist/src/plugin/shared/vault-request-credentials.d.ts +168 -0
- package/dist/src/plugin/shared/vault-request-credentials.d.ts.map +1 -0
- package/dist/src/plugin/shared/vault-request-credentials.js +485 -0
- package/dist/src/plugin/shared/vault-request-credentials.js.map +1 -0
- package/dist/src/plugin/storage.d.ts +127 -1
- package/dist/src/plugin/storage.d.ts.map +1 -1
- package/dist/src/plugin/storage.js +188 -3
- package/dist/src/plugin/storage.js.map +1 -1
- package/dist/src/plugin/token.d.ts +23 -1
- package/dist/src/plugin/token.d.ts.map +1 -1
- package/dist/src/plugin/token.js +117 -58
- package/dist/src/plugin/token.js.map +1 -1
- package/dist/src/plugin/ui/quota-status.d.ts +1 -10
- package/dist/src/plugin/ui/quota-status.d.ts.map +1 -1
- package/dist/src/plugin/ui/quota-status.js +6 -42
- package/dist/src/plugin/ui/quota-status.js.map +1 -1
- package/dist/src/plugin/vault-activation.d.ts +11 -0
- package/dist/src/plugin/vault-activation.d.ts.map +1 -0
- package/dist/src/plugin/vault-activation.js +53 -0
- package/dist/src/plugin/vault-activation.js.map +1 -0
- package/dist/src/plugin/vault-custody.d.ts +131 -0
- package/dist/src/plugin/vault-custody.d.ts.map +1 -0
- package/dist/src/plugin/vault-custody.js +381 -0
- package/dist/src/plugin/vault-custody.js.map +1 -0
- package/dist/src/quota-presentation.d.ts +18 -0
- package/dist/src/quota-presentation.d.ts.map +1 -0
- package/dist/src/quota-presentation.js +58 -0
- package/dist/src/quota-presentation.js.map +1 -0
- package/dist/src/rpc/notifications.d.ts +2 -2
- package/dist/src/rpc/notifications.d.ts.map +1 -1
- package/dist/src/rpc/notifications.js +1 -1
- package/dist/src/rpc/notifications.js.map +1 -1
- package/dist/src/rpc/port-file.d.ts +2 -12
- package/dist/src/rpc/port-file.d.ts.map +1 -1
- package/dist/src/rpc/port-file.js +5 -107
- package/dist/src/rpc/port-file.js.map +1 -1
- package/dist/src/rpc/protocol.d.ts +47 -16
- package/dist/src/rpc/protocol.d.ts.map +1 -1
- package/dist/src/rpc/rpc-client.d.ts +27 -3
- package/dist/src/rpc/rpc-client.d.ts.map +1 -1
- package/dist/src/rpc/rpc-client.js +55 -45
- package/dist/src/rpc/rpc-client.js.map +1 -1
- package/dist/src/rpc/rpc-server.d.ts +13 -2
- package/dist/src/rpc/rpc-server.d.ts.map +1 -1
- package/dist/src/rpc/rpc-server.js +38 -212
- package/dist/src/rpc/rpc-server.js.map +1 -1
- package/dist/src/server.d.ts +30 -0
- package/dist/src/server.d.ts.map +1 -0
- package/dist/src/server.js +29 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/sidebar-projection.d.ts +102 -0
- package/dist/src/sidebar-projection.d.ts.map +1 -0
- package/dist/src/sidebar-projection.js +146 -0
- package/dist/src/sidebar-projection.js.map +1 -0
- package/dist/src/sidebar-state.d.ts +13 -5
- package/dist/src/sidebar-state.d.ts.map +1 -1
- package/dist/src/sidebar-state.js +49 -16
- package/dist/src/sidebar-state.js.map +1 -1
- package/dist/src/tui/command-dialogs.d.ts +58 -52
- package/dist/src/tui/command-dialogs.d.ts.map +1 -1
- package/dist/src/tui/command-dialogs.js +379 -571
- package/dist/src/tui/command-dialogs.js.map +1 -1
- package/dist/src/tui/file-logger.d.ts +2 -3
- package/dist/src/tui/file-logger.d.ts.map +1 -1
- package/dist/src/tui/file-logger.js +21 -7
- package/dist/src/tui/file-logger.js.map +1 -1
- package/dist/src/tui/host-api.d.ts +196 -0
- package/dist/src/tui/host-api.d.ts.map +1 -0
- package/dist/src/tui/host-api.js +357 -0
- package/dist/src/tui/host-api.js.map +1 -0
- package/dist/src/tui/host-v1.d.ts +60 -0
- package/dist/src/tui/host-v1.d.ts.map +1 -0
- package/dist/src/tui/host-v1.js +147 -0
- package/dist/src/tui/host-v1.js.map +1 -0
- package/dist/src/tui/vault-setup.d.ts +98 -0
- package/dist/src/tui/vault-setup.d.ts.map +1 -0
- package/dist/src/tui/vault-setup.js +198 -0
- package/dist/src/tui/vault-setup.js.map +1 -0
- package/dist/src/tui.d.ts +4 -11
- package/dist/src/tui.d.ts.map +1 -1
- package/dist/src/tui.js +33 -75
- package/dist/src/tui.js.map +1 -1
- package/dist/tui-build-map.json +380 -0
- package/dist/tui-ga-build-map.json +187 -0
- package/dist/types/src/antigravity/oauth.d.ts +2 -0
- package/dist/types/src/antigravity/oauth.d.ts.map +1 -0
- package/dist/types/src/cli.d.ts +66 -0
- package/dist/types/src/cli.d.ts.map +1 -0
- package/dist/types/src/common-auth-embedded/commands/builtins.d.ts +71 -0
- package/dist/types/src/common-auth-embedded/commands/index.d.ts +10 -0
- package/dist/types/src/common-auth-embedded/commands/menu.d.ts +61 -0
- package/dist/types/src/common-auth-embedded/commands/model.d.ts +238 -0
- package/dist/types/src/common-auth-embedded/commands/pi.d.ts +23 -0
- package/dist/types/src/common-auth-embedded/commands/seam.d.ts +72 -0
- package/dist/types/src/common-auth-embedded/fs/refresh-file-lock.d.ts +33 -0
- package/dist/types/src/common-auth-embedded/logger/capture-sink.d.ts +14 -0
- package/dist/types/src/common-auth-embedded/logger/engine.d.ts +100 -0
- package/dist/types/src/common-auth-embedded/logger/index.d.ts +6 -0
- package/dist/types/src/common-auth-embedded/logger/redact.d.ts +11 -0
- package/dist/types/src/common-auth-embedded/quota/codec.d.ts +11 -0
- package/dist/types/src/common-auth-embedded/quota/format.d.ts +46 -0
- package/dist/types/src/common-auth-embedded/quota/index.d.ts +10 -0
- package/dist/types/src/common-auth-embedded/quota/map.d.ts +63 -0
- package/dist/types/src/common-auth-embedded/quota/merge.d.ts +48 -0
- package/dist/types/src/common-auth-embedded/quota/projection.d.ts +64 -0
- package/dist/types/src/common-auth-embedded/store/attribution.d.ts +28 -0
- package/dist/types/src/common-auth-embedded/store/errors.d.ts +55 -0
- package/dist/types/src/common-auth-embedded/store/hooks.d.ts +12 -0
- package/dist/types/src/common-auth-embedded/store/identity.d.ts +39 -0
- package/dist/types/src/common-auth-embedded/store/index.d.ts +21 -0
- package/dist/types/src/common-auth-embedded/store/mutate.d.ts +189 -0
- package/dist/types/src/common-auth-embedded/store/pool.d.ts +196 -0
- package/dist/types/src/common-auth-embedded/store/provider-state.d.ts +131 -0
- package/dist/types/src/common-auth-embedded/store/publication.d.ts +47 -0
- package/dist/types/src/common-auth-embedded/store/pull.d.ts +36 -0
- package/dist/types/src/common-auth-embedded/store/refresh-lock.d.ts +63 -0
- package/dist/types/src/common-auth-embedded/store/refresh.d.ts +72 -0
- package/dist/types/src/common-auth-embedded/store/rows.d.ts +313 -0
- package/dist/types/src/common-auth-embedded/store/runtime.d.ts +36 -0
- package/dist/types/src/common-auth-embedded/store/schema.d.ts +443 -0
- package/dist/types/src/common-auth-embedded/store/settings.d.ts +63 -0
- package/dist/types/src/common-auth-embedded/store/torn.d.ts +78 -0
- package/dist/types/src/constants.d.ts +3 -0
- package/dist/types/src/constants.d.ts.map +1 -0
- package/dist/types/src/ga/proxy-guard.d.ts +120 -0
- package/dist/types/src/ga/proxy-guard.d.ts.map +1 -0
- package/dist/types/src/ga/rpc/protocol.d.ts +504 -0
- package/dist/types/src/ga/rpc/protocol.d.ts.map +1 -0
- package/dist/types/src/ga/server/auth.d.ts +9 -0
- package/dist/types/src/ga/server/auth.d.ts.map +1 -0
- package/dist/types/src/ga/server/index.d.ts +576 -0
- package/dist/types/src/ga/server/index.d.ts.map +1 -0
- package/dist/types/src/hooks/auto-update-checker/cache.d.ts +3 -0
- package/dist/types/src/hooks/auto-update-checker/cache.d.ts.map +1 -0
- package/dist/types/src/hooks/auto-update-checker/checker.d.ts +16 -0
- package/dist/types/src/hooks/auto-update-checker/checker.d.ts.map +1 -0
- package/dist/types/src/hooks/auto-update-checker/constants.d.ts +9 -0
- package/dist/types/src/hooks/auto-update-checker/constants.d.ts.map +1 -0
- package/dist/types/src/hooks/auto-update-checker/index.d.ts +34 -0
- package/dist/types/src/hooks/auto-update-checker/index.d.ts.map +1 -0
- package/dist/types/src/hooks/auto-update-checker/logging.d.ts +3 -0
- package/dist/types/src/hooks/auto-update-checker/logging.d.ts.map +1 -0
- package/dist/types/src/hooks/auto-update-checker/types.d.ts +25 -0
- package/dist/types/src/hooks/auto-update-checker/types.d.ts.map +1 -0
- package/dist/types/src/logging/provider-key-policy.d.ts +9 -0
- package/dist/types/src/logging/provider-key-policy.d.ts.map +1 -0
- package/dist/types/src/plugin/account-access.d.ts +214 -0
- package/dist/types/src/plugin/account-access.d.ts.map +1 -0
- package/dist/types/src/plugin/account-blocks.d.ts +102 -0
- package/dist/types/src/plugin/account-blocks.d.ts.map +1 -0
- package/dist/types/src/plugin/account-command-oauth.d.ts +34 -0
- package/dist/types/src/plugin/account-command-oauth.d.ts.map +1 -0
- package/dist/types/src/plugin/accounts.d.ts +94 -0
- package/dist/types/src/plugin/accounts.d.ts.map +1 -0
- package/dist/types/src/plugin/agy-request-metadata.d.ts +2 -0
- package/dist/types/src/plugin/agy-request-metadata.d.ts.map +1 -0
- package/dist/types/src/plugin/agy-transport.d.ts +2 -0
- package/dist/types/src/plugin/agy-transport.d.ts.map +1 -0
- package/dist/types/src/plugin/auth-doctor.d.ts +30 -0
- package/dist/types/src/plugin/auth-doctor.d.ts.map +1 -0
- package/dist/types/src/plugin/auth-drift.d.ts +13 -0
- package/dist/types/src/plugin/auth-drift.d.ts.map +1 -0
- package/dist/types/src/plugin/auth-loader.d.ts +114 -0
- package/dist/types/src/plugin/auth-loader.d.ts.map +1 -0
- package/dist/types/src/plugin/auth.d.ts +2 -0
- package/dist/types/src/plugin/auth.d.ts.map +1 -0
- package/dist/types/src/plugin/background-quota-refresh.d.ts +192 -0
- package/dist/types/src/plugin/background-quota-refresh.d.ts.map +1 -0
- package/dist/types/src/plugin/cache/signature-cache.d.ts +156 -0
- package/dist/types/src/plugin/cache/signature-cache.d.ts.map +1 -0
- package/dist/types/src/plugin/cache.d.ts +109 -0
- package/dist/types/src/plugin/cache.d.ts.map +1 -0
- package/dist/types/src/plugin/catalog.d.ts +9 -0
- package/dist/types/src/plugin/catalog.d.ts.map +1 -0
- package/dist/types/src/plugin/cli.d.ts +44 -0
- package/dist/types/src/plugin/cli.d.ts.map +1 -0
- package/dist/types/src/plugin/command-apply.d.ts +58 -0
- package/dist/types/src/plugin/command-apply.d.ts.map +1 -0
- package/dist/types/src/plugin/command-data.d.ts +330 -0
- package/dist/types/src/plugin/command-data.d.ts.map +1 -0
- package/dist/types/src/plugin/commands.d.ts +164 -0
- package/dist/types/src/plugin/commands.d.ts.map +1 -0
- package/dist/types/src/plugin/config/index.d.ts +16 -0
- package/dist/types/src/plugin/config/index.d.ts.map +1 -0
- package/dist/types/src/plugin/config/loader.d.ts +72 -0
- package/dist/types/src/plugin/config/loader.d.ts.map +1 -0
- package/dist/types/src/plugin/config/models.d.ts +3 -0
- package/dist/types/src/plugin/config/models.d.ts.map +1 -0
- package/dist/types/src/plugin/config/operator-settings-schema.d.ts +29 -0
- package/dist/types/src/plugin/config/operator-settings-schema.d.ts.map +1 -0
- package/dist/types/src/plugin/config/schema.d.ts +162 -0
- package/dist/types/src/plugin/config/schema.d.ts.map +1 -0
- package/dist/types/src/plugin/config/updater.d.ts +55 -0
- package/dist/types/src/plugin/config/updater.d.ts.map +1 -0
- package/dist/types/src/plugin/config/writer.d.ts +41 -0
- package/dist/types/src/plugin/config/writer.d.ts.map +1 -0
- package/dist/types/src/plugin/core/streaming/index.d.ts +3 -0
- package/dist/types/src/plugin/core/streaming/index.d.ts.map +1 -0
- package/dist/types/src/plugin/core/streaming/transformer.d.ts +12 -0
- package/dist/types/src/plugin/core/streaming/transformer.d.ts.map +1 -0
- package/dist/types/src/plugin/core/streaming/types.d.ts +34 -0
- package/dist/types/src/plugin/core/streaming/types.d.ts.map +1 -0
- package/dist/types/src/plugin/debug.d.ts +144 -0
- package/dist/types/src/plugin/debug.d.ts.map +1 -0
- package/dist/types/src/plugin/dependencies.d.ts +129 -0
- package/dist/types/src/plugin/dependencies.d.ts.map +1 -0
- package/dist/types/src/plugin/errors.d.ts +55 -0
- package/dist/types/src/plugin/errors.d.ts.map +1 -0
- package/dist/types/src/plugin/event-handler.d.ts +53 -0
- package/dist/types/src/plugin/event-handler.d.ts.map +1 -0
- package/dist/types/src/plugin/fetch/retry-state.d.ts +61 -0
- package/dist/types/src/plugin/fetch/retry-state.d.ts.map +1 -0
- package/dist/types/src/plugin/fetch/warmup.d.ts +30 -0
- package/dist/types/src/plugin/fetch/warmup.d.ts.map +1 -0
- package/dist/types/src/plugin/fetch-interceptor.d.ts +114 -0
- package/dist/types/src/plugin/fetch-interceptor.d.ts.map +1 -0
- package/dist/types/src/plugin/fetch-routing.d.ts +31 -0
- package/dist/types/src/plugin/fetch-routing.d.ts.map +1 -0
- package/dist/types/src/plugin/fingerprint.d.ts +2 -0
- package/dist/types/src/plugin/fingerprint.d.ts.map +1 -0
- package/dist/types/src/plugin/ga-location-services.d.ts +389 -0
- package/dist/types/src/plugin/ga-location-services.d.ts.map +1 -0
- package/dist/types/src/plugin/gemini-dump.d.ts +72 -0
- package/dist/types/src/plugin/gemini-dump.d.ts.map +1 -0
- package/dist/types/src/plugin/google-search-tool.d.ts +10 -0
- package/dist/types/src/plugin/google-search-tool.d.ts.map +1 -0
- package/dist/types/src/plugin/image-saver.d.ts +6 -0
- package/dist/types/src/plugin/image-saver.d.ts.map +1 -0
- package/dist/types/src/plugin/index.d.ts +30 -0
- package/dist/types/src/plugin/index.d.ts.map +1 -0
- package/dist/types/src/plugin/killswitch.d.ts +93 -0
- package/dist/types/src/plugin/killswitch.d.ts.map +1 -0
- package/dist/types/src/plugin/lifecycle.d.ts +63 -0
- package/dist/types/src/plugin/lifecycle.d.ts.map +1 -0
- package/dist/types/src/plugin/logger.d.ts +83 -0
- package/dist/types/src/plugin/logger.d.ts.map +1 -0
- package/dist/types/src/plugin/logging-utils.d.ts +57 -0
- package/dist/types/src/plugin/logging-utils.d.ts.map +1 -0
- package/dist/types/src/plugin/model-registry.d.ts +2 -0
- package/dist/types/src/plugin/model-registry.d.ts.map +1 -0
- package/dist/types/src/plugin/neutral-types.d.ts +42 -0
- package/dist/types/src/plugin/neutral-types.d.ts.map +1 -0
- package/dist/types/src/plugin/oauth-login.d.ts +22 -0
- package/dist/types/src/plugin/oauth-login.d.ts.map +1 -0
- package/dist/types/src/plugin/oauth-methods.d.ts +43 -0
- package/dist/types/src/plugin/oauth-methods.d.ts.map +1 -0
- package/dist/types/src/plugin/operator-settings.d.ts +74 -0
- package/dist/types/src/plugin/operator-settings.d.ts.map +1 -0
- package/dist/types/src/plugin/persist-account-pool.d.ts +98 -0
- package/dist/types/src/plugin/persist-account-pool.d.ts.map +1 -0
- package/dist/types/src/plugin/project.d.ts +2 -0
- package/dist/types/src/plugin/project.d.ts.map +1 -0
- package/dist/types/src/plugin/prompt-context.d.ts +18 -0
- package/dist/types/src/plugin/prompt-context.d.ts.map +1 -0
- package/dist/types/src/plugin/quota.d.ts +441 -0
- package/dist/types/src/plugin/quota.d.ts.map +1 -0
- package/dist/types/src/plugin/recovery/constants.d.ts +22 -0
- package/dist/types/src/plugin/recovery/constants.d.ts.map +1 -0
- package/dist/types/src/plugin/recovery/storage.d.ts +24 -0
- package/dist/types/src/plugin/recovery/storage.d.ts.map +1 -0
- package/dist/types/src/plugin/recovery/types.d.ts +116 -0
- package/dist/types/src/plugin/recovery/types.d.ts.map +1 -0
- package/dist/types/src/plugin/recovery.d.ts +61 -0
- package/dist/types/src/plugin/recovery.d.ts.map +1 -0
- package/dist/types/src/plugin/refresh-queue.d.ts +133 -0
- package/dist/types/src/plugin/refresh-queue.d.ts.map +1 -0
- package/dist/types/src/plugin/request-helpers.d.ts +304 -0
- package/dist/types/src/plugin/request-helpers.d.ts.map +1 -0
- package/dist/types/src/plugin/request.d.ts +161 -0
- package/dist/types/src/plugin/request.d.ts.map +1 -0
- package/dist/types/src/plugin/rotation.d.ts +2 -0
- package/dist/types/src/plugin/rotation.d.ts.map +1 -0
- package/dist/types/src/plugin/search.d.ts +25 -0
- package/dist/types/src/plugin/search.d.ts.map +1 -0
- package/dist/types/src/plugin/server.d.ts +23 -0
- package/dist/types/src/plugin/server.d.ts.map +1 -0
- package/dist/types/src/plugin/session-context.d.ts +22 -0
- package/dist/types/src/plugin/session-context.d.ts.map +1 -0
- package/dist/types/src/plugin/shared/local-grant.d.ts +26 -0
- package/dist/types/src/plugin/shared/local-grant.d.ts.map +1 -0
- package/dist/types/src/plugin/shared/request-cancellation.d.ts +12 -0
- package/dist/types/src/plugin/shared/request-cancellation.d.ts.map +1 -0
- package/dist/types/src/plugin/shared/request-services.d.ts +375 -0
- package/dist/types/src/plugin/shared/request-services.d.ts.map +1 -0
- package/dist/types/src/plugin/shared/runtime.d.ts +217 -0
- package/dist/types/src/plugin/shared/runtime.d.ts.map +1 -0
- package/dist/types/src/plugin/shared/source-sidebar.d.ts +15 -0
- package/dist/types/src/plugin/shared/source-sidebar.d.ts.map +1 -0
- package/dist/types/src/plugin/shared/vault-menu.d.ts +5 -0
- package/dist/types/src/plugin/shared/vault-menu.d.ts.map +1 -0
- package/dist/types/src/plugin/shared/vault-request-credentials.d.ts +168 -0
- package/dist/types/src/plugin/shared/vault-request-credentials.d.ts.map +1 -0
- package/dist/types/src/plugin/storage.d.ts +221 -0
- package/dist/types/src/plugin/storage.d.ts.map +1 -0
- package/dist/types/src/plugin/stores/signature-store.d.ts +5 -0
- package/dist/types/src/plugin/stores/signature-store.d.ts.map +1 -0
- package/dist/types/src/plugin/thinking-recovery.d.ts +90 -0
- package/dist/types/src/plugin/thinking-recovery.d.ts.map +1 -0
- package/dist/types/src/plugin/token.d.ts +41 -0
- package/dist/types/src/plugin/token.d.ts.map +1 -0
- package/dist/types/src/plugin/transform/cross-model-sanitizer.d.ts +2 -0
- package/dist/types/src/plugin/transform/cross-model-sanitizer.d.ts.map +1 -0
- package/dist/types/src/plugin/transform/index.d.ts +2 -0
- package/dist/types/src/plugin/transform/index.d.ts.map +1 -0
- package/dist/types/src/plugin/transform/model-resolver.d.ts +2 -0
- package/dist/types/src/plugin/transform/model-resolver.d.ts.map +1 -0
- package/dist/types/src/plugin/transform/types.d.ts +2 -0
- package/dist/types/src/plugin/transform/types.d.ts.map +1 -0
- package/dist/types/src/plugin/types.d.ts +36 -0
- package/dist/types/src/plugin/types.d.ts.map +1 -0
- package/dist/types/src/plugin/ui/ansi.d.ts +32 -0
- package/dist/types/src/plugin/ui/ansi.d.ts.map +1 -0
- package/dist/types/src/plugin/ui/auth-menu.d.ts +59 -0
- package/dist/types/src/plugin/ui/auth-menu.d.ts.map +1 -0
- package/dist/types/src/plugin/ui/confirm.d.ts +2 -0
- package/dist/types/src/plugin/ui/confirm.d.ts.map +1 -0
- package/dist/types/src/plugin/ui/quota-status.d.ts +73 -0
- package/dist/types/src/plugin/ui/quota-status.d.ts.map +1 -0
- package/dist/types/src/plugin/ui/select.d.ts +23 -0
- package/dist/types/src/plugin/ui/select.d.ts.map +1 -0
- package/dist/types/src/plugin/vault-activation.d.ts +11 -0
- package/dist/types/src/plugin/vault-activation.d.ts.map +1 -0
- package/dist/types/src/plugin/vault-custody.d.ts +131 -0
- package/dist/types/src/plugin/vault-custody.d.ts.map +1 -0
- package/dist/types/src/plugin/version.d.ts +2 -0
- package/dist/types/src/plugin/version.d.ts.map +1 -0
- package/dist/types/src/quota-presentation.d.ts +18 -0
- package/dist/types/src/quota-presentation.d.ts.map +1 -0
- package/dist/types/src/rpc/notifications.d.ts +6 -0
- package/dist/types/src/rpc/notifications.d.ts.map +1 -0
- package/dist/types/src/rpc/protocol.d.ts +53 -0
- package/dist/types/src/rpc/protocol.d.ts.map +1 -0
- package/dist/types/src/rpc/rpc-dir.d.ts +4 -0
- package/dist/types/src/rpc/rpc-dir.d.ts.map +1 -0
- package/dist/types/src/rpc/rpc-server.d.ts +24 -0
- package/dist/types/src/rpc/rpc-server.d.ts.map +1 -0
- package/dist/types/src/server.d.ts +30 -0
- package/dist/types/src/server.d.ts.map +1 -0
- package/dist/types/src/sidebar-state.d.ts +365 -0
- package/dist/types/src/sidebar-state.d.ts.map +1 -0
- package/dist/types/src/tui/host-api.d.ts +196 -0
- package/dist/types/src/tui/host-api.d.ts.map +1 -0
- package/package.json +45 -18
- package/server.js +6 -0
- package/src/common-auth-embedded/NOTICE.txt +21 -0
- package/src/common-auth-embedded/auth-menu/accounts.d.ts +97 -0
- package/src/common-auth-embedded/auth-menu/accounts.js +387 -0
- package/src/common-auth-embedded/auth-menu/ansi.d.ts +26 -0
- package/src/common-auth-embedded/auth-menu/ansi.js +98 -0
- package/src/common-auth-embedded/auth-menu/confirm.d.ts +7 -0
- package/src/common-auth-embedded/auth-menu/confirm.js +21 -0
- package/src/common-auth-embedded/auth-menu/doctor.d.ts +52 -0
- package/src/common-auth-embedded/auth-menu/doctor.js +81 -0
- package/src/common-auth-embedded/auth-menu/index.d.ts +17 -0
- package/src/common-auth-embedded/auth-menu/index.js +12 -0
- package/src/common-auth-embedded/auth-menu/login.d.ts +55 -0
- package/src/common-auth-embedded/auth-menu/login.js +83 -0
- package/src/common-auth-embedded/auth-menu/menu.d.ts +59 -0
- package/src/common-auth-embedded/auth-menu/menu.js +73 -0
- package/src/common-auth-embedded/auth-menu/opencode-v1.d.ts +49 -0
- package/src/common-auth-embedded/auth-menu/opencode-v1.js +47 -0
- package/src/common-auth-embedded/auth-menu/select.d.ts +21 -0
- package/src/common-auth-embedded/auth-menu/select.js +159 -0
- package/src/common-auth-embedded/auth-menu/terminal.d.ts +43 -0
- package/src/common-auth-embedded/auth-menu/terminal.js +19 -0
- package/src/common-auth-embedded/claustrum/consumer.d.ts +102 -0
- package/src/common-auth-embedded/claustrum/consumer.js +298 -0
- package/src/common-auth-embedded/claustrum/custody.d.ts +175 -0
- package/src/common-auth-embedded/claustrum/custody.js +354 -0
- package/src/common-auth-embedded/claustrum/enrollment.d.ts +158 -0
- package/src/common-auth-embedded/claustrum/enrollment.js +759 -0
- package/src/common-auth-embedded/claustrum/errors.d.ts +16 -0
- package/src/common-auth-embedded/claustrum/errors.js +8 -0
- package/src/common-auth-embedded/claustrum/host-slot.d.ts +39 -0
- package/src/common-auth-embedded/claustrum/host-slot.js +72 -0
- package/src/common-auth-embedded/claustrum/index.d.ts +18 -0
- package/src/common-auth-embedded/claustrum/index.js +22 -0
- package/src/common-auth-embedded/claustrum/interlock.d.ts +27 -0
- package/src/common-auth-embedded/claustrum/interlock.js +29 -0
- package/src/common-auth-embedded/claustrum/roster.d.ts +208 -0
- package/src/common-auth-embedded/claustrum/roster.js +536 -0
- package/src/common-auth-embedded/commands/builtins.d.ts +71 -0
- package/src/common-auth-embedded/commands/builtins.js +534 -0
- package/src/common-auth-embedded/commands/index.d.ts +10 -0
- package/src/common-auth-embedded/commands/index.js +5 -0
- package/src/common-auth-embedded/commands/menu.d.ts +61 -0
- package/src/common-auth-embedded/commands/menu.js +300 -0
- package/src/common-auth-embedded/commands/model.d.ts +238 -0
- package/src/common-auth-embedded/commands/model.js +16 -0
- package/src/common-auth-embedded/commands/pi.d.ts +23 -0
- package/src/common-auth-embedded/commands/pi.js +206 -0
- package/src/common-auth-embedded/commands/seam.d.ts +72 -0
- package/src/common-auth-embedded/commands/seam.js +301 -0
- package/src/common-auth-embedded/fs/atomic-write.d.ts +20 -0
- package/src/common-auth-embedded/fs/atomic-write.js +80 -0
- package/src/common-auth-embedded/fs/index.d.ts +7 -0
- package/src/common-auth-embedded/fs/index.js +6 -0
- package/src/common-auth-embedded/fs/lock-constants.d.ts +14 -0
- package/src/common-auth-embedded/fs/lock-constants.js +14 -0
- package/src/common-auth-embedded/fs/refresh-file-lock.d.ts +33 -0
- package/src/common-auth-embedded/fs/refresh-file-lock.js +501 -0
- package/src/common-auth-embedded/fs/with-lock.d.ts +33 -0
- package/src/common-auth-embedded/fs/with-lock.js +48 -0
- package/src/common-auth-embedded/logger/capture-sink.d.ts +14 -0
- package/src/common-auth-embedded/logger/capture-sink.js +13 -0
- package/src/common-auth-embedded/logger/engine.d.ts +100 -0
- package/src/common-auth-embedded/logger/engine.js +246 -0
- package/src/common-auth-embedded/logger/index.d.ts +6 -0
- package/src/common-auth-embedded/logger/index.js +3 -0
- package/src/common-auth-embedded/logger/redact.d.ts +11 -0
- package/src/common-auth-embedded/logger/redact.js +83 -0
- package/src/common-auth-embedded/opencode2/errors.d.ts +25 -0
- package/src/common-auth-embedded/opencode2/errors.js +15 -0
- package/src/common-auth-embedded/opencode2/index.d.ts +8 -0
- package/src/common-auth-embedded/opencode2/index.js +4 -0
- package/src/common-auth-embedded/opencode2/install.d.ts +55 -0
- package/src/common-auth-embedded/opencode2/install.js +886 -0
- package/src/common-auth-embedded/opencode2/integration.d.ts +112 -0
- package/src/common-auth-embedded/opencode2/integration.js +143 -0
- package/src/common-auth-embedded/opencode2/sse.d.ts +12 -0
- package/src/common-auth-embedded/opencode2/sse.js +60 -0
- package/src/common-auth-embedded/opencode2/types.d.ts +413 -0
- package/src/common-auth-embedded/pi-slot/index.d.ts +3 -0
- package/src/common-auth-embedded/pi-slot/index.js +2 -0
- package/src/common-auth-embedded/pi-slot/lock.js +212 -0
- package/src/common-auth-embedded/pi-slot/slot.d.ts +49 -0
- package/src/common-auth-embedded/pi-slot/slot.js +383 -0
- package/src/common-auth-embedded/quota/codec.d.ts +11 -0
- package/src/common-auth-embedded/quota/codec.js +12 -0
- package/src/common-auth-embedded/quota/format.d.ts +46 -0
- package/src/common-auth-embedded/quota/format.js +138 -0
- package/src/common-auth-embedded/quota/index.d.ts +10 -0
- package/src/common-auth-embedded/quota/index.js +5 -0
- package/src/common-auth-embedded/quota/map.d.ts +63 -0
- package/src/common-auth-embedded/quota/map.js +105 -0
- package/src/common-auth-embedded/quota/merge.d.ts +48 -0
- package/src/common-auth-embedded/quota/merge.js +162 -0
- package/src/common-auth-embedded/quota/projection.d.ts +64 -0
- package/src/common-auth-embedded/quota/projection.js +134 -0
- package/src/common-auth-embedded/routing/admission.d.ts +93 -0
- package/src/common-auth-embedded/routing/admission.js +142 -0
- package/src/common-auth-embedded/routing/index.d.ts +8 -0
- package/src/common-auth-embedded/routing/index.js +4 -0
- package/src/common-auth-embedded/routing/ordered.d.ts +47 -0
- package/src/common-auth-embedded/routing/ordered.js +58 -0
- package/src/common-auth-embedded/routing/pins.d.ts +22 -0
- package/src/common-auth-embedded/routing/pins.js +34 -0
- package/src/common-auth-embedded/routing/sticky.d.ts +158 -0
- package/src/common-auth-embedded/routing/sticky.js +339 -0
- package/src/common-auth-embedded/rpc/client.d.ts +3 -0
- package/src/common-auth-embedded/rpc/client.js +2 -0
- package/src/common-auth-embedded/rpc/index.d.ts +10 -0
- package/src/common-auth-embedded/rpc/index.js +5 -0
- package/src/common-auth-embedded/rpc/notifications.d.ts +73 -0
- package/src/common-auth-embedded/rpc/notifications.js +100 -0
- package/src/common-auth-embedded/rpc/port-file.d.ts +33 -0
- package/src/common-auth-embedded/rpc/port-file.js +217 -0
- package/src/common-auth-embedded/rpc/rpc-client.d.ts +30 -0
- package/src/common-auth-embedded/rpc/rpc-client.js +253 -0
- package/src/common-auth-embedded/rpc/rpc-server.d.ts +58 -0
- package/src/common-auth-embedded/rpc/rpc-server.js +311 -0
- package/src/common-auth-embedded/rpc/server-registry.d.ts +11 -0
- package/src/common-auth-embedded/rpc/server-registry.js +47 -0
- package/src/common-auth-embedded/source-output.json +1326 -0
- package/src/common-auth-embedded/store/attribution.d.ts +28 -0
- package/src/common-auth-embedded/store/attribution.js +60 -0
- package/src/common-auth-embedded/store/errors.d.ts +55 -0
- package/src/common-auth-embedded/store/errors.js +38 -0
- package/src/common-auth-embedded/store/hooks.d.ts +12 -0
- package/src/common-auth-embedded/store/hooks.js +34 -0
- package/src/common-auth-embedded/store/identity.d.ts +39 -0
- package/src/common-auth-embedded/store/identity.js +79 -0
- package/src/common-auth-embedded/store/index.d.ts +21 -0
- package/src/common-auth-embedded/store/index.js +7 -0
- package/src/common-auth-embedded/store/mutate.d.ts +189 -0
- package/src/common-auth-embedded/store/mutate.js +500 -0
- package/src/common-auth-embedded/store/pool.d.ts +196 -0
- package/src/common-auth-embedded/store/pool.js +120 -0
- package/src/common-auth-embedded/store/provider-state.d.ts +131 -0
- package/src/common-auth-embedded/store/provider-state.js +226 -0
- package/src/common-auth-embedded/store/publication.d.ts +47 -0
- package/src/common-auth-embedded/store/publication.js +304 -0
- package/src/common-auth-embedded/store/pull.d.ts +36 -0
- package/src/common-auth-embedded/store/pull.js +143 -0
- package/src/common-auth-embedded/store/refresh-lock.d.ts +63 -0
- package/src/common-auth-embedded/store/refresh-lock.js +136 -0
- package/src/common-auth-embedded/store/refresh.d.ts +72 -0
- package/src/common-auth-embedded/store/refresh.js +225 -0
- package/src/common-auth-embedded/store/reserved.js +13 -0
- package/src/common-auth-embedded/store/rows.d.ts +313 -0
- package/src/common-auth-embedded/store/rows.js +1258 -0
- package/src/common-auth-embedded/store/runtime.d.ts +36 -0
- package/src/common-auth-embedded/store/runtime.js +68 -0
- package/src/common-auth-embedded/store/schema.d.ts +443 -0
- package/src/common-auth-embedded/store/schema.js +754 -0
- package/src/common-auth-embedded/store/settings.d.ts +63 -0
- package/src/common-auth-embedded/store/settings.js +120 -0
- package/src/common-auth-embedded/store/torn.d.ts +78 -0
- package/src/common-auth-embedded/store/torn.js +294 -0
- package/src/common-auth-embedded/tui/index.d.ts +8 -0
- package/src/common-auth-embedded/tui/index.js +21 -0
- package/src/common-auth-embedded/util/any-signal.js +42 -0
- package/src/plugin/command-data.ts +3 -0
- package/src/rpc/port-file.ts +6 -140
- package/src/rpc/protocol.ts +59 -24
- package/src/rpc/rpc-client.ts +101 -71
- package/src/sidebar-state.ts +82 -24
- package/src/tui/command-dialogs.tsx +412 -776
- package/src/tui/entry.d.mts +17 -0
- package/src/tui/entry.mjs +34 -66
- package/src/tui/file-logger.ts +22 -7
- package/src/tui-compiled/common-auth-embedded/logger/capture-sink.js +13 -0
- package/src/tui-compiled/common-auth-embedded/logger/engine.js +246 -0
- package/src/tui-compiled/common-auth-embedded/logger/index.js +3 -0
- package/src/tui-compiled/common-auth-embedded/logger/redact.js +83 -0
- package/src/tui-compiled/common-auth-embedded/quota/codec.js +12 -0
- package/src/tui-compiled/common-auth-embedded/quota/format.js +138 -0
- package/src/tui-compiled/common-auth-embedded/quota/index.js +5 -0
- package/src/tui-compiled/common-auth-embedded/quota/map.js +105 -0
- package/src/tui-compiled/common-auth-embedded/quota/merge.js +162 -0
- package/src/tui-compiled/common-auth-embedded/quota/projection.js +134 -0
- package/src/tui-compiled/common-auth-embedded/rpc/client.js +2 -0
- package/src/tui-compiled/common-auth-embedded/rpc/port-file.js +217 -0
- package/src/tui-compiled/common-auth-embedded/rpc/rpc-client.js +253 -0
- package/src/tui-compiled/logging/provider-key-policy.js +3 -0
- package/src/tui-compiled/quota-presentation.js +42 -0
- package/src/tui-compiled/rpc/rpc-client.js +35 -0
- package/src/tui-compiled/rpc/rpc-dir.js +13 -0
- package/src/tui-compiled/selector.js +21 -0
- package/src/tui-compiled/sidebar-state.js +401 -0
- package/src/tui-compiled/tui/command-dialogs.js +424 -0
- package/src/tui-compiled/tui/file-logger.js +73 -0
- package/src/tui-compiled/tui/host-api.js +269 -0
- package/src/tui-compiled/tui/host-v1.js +228 -0
- package/src/tui-compiled/tui-preferences.js +230 -0
- package/src/tui-compiled/{tui.tsx → tui.js} +140 -231
- package/src/tui-ga-compiled/host-ga.js +1304 -0
- package/src/tui-ga-compiled/selector.js +21 -0
- package/src/tui-ga-compiled/shared/07365a7d2ccade4c-host-api.js +269 -0
- package/src/tui-ga-compiled/shared/0e19a88ff3535906-command-dialogs.js +424 -0
- package/src/tui-ga-compiled/shared/1ff34afa7c42d196-projection.js +134 -0
- package/src/tui-ga-compiled/shared/77138df80c7ae006-map.js +105 -0
- package/src/tui-ga-compiled/shared/8ae1927e5910ea81-sidebar-projection.js +112 -0
- package/src/tui-ga-compiled/shared/98cc0c186c46c42d-quota-presentation.js +42 -0
- package/src/tui-ga-compiled/shared/aef2402f8fc342f0-format.js +138 -0
- package/src/tui-ga-compiled/shared/bf17cbee28e58197-index.js +5 -0
- package/src/tui-ga-compiled/shared/ca21dc417b36dc5d-codec.js +12 -0
- package/src/tui-ga-compiled/shared/ecc214300932dfb6-merge.js +162 -0
- package/src/tui-ga-raw/host-ga.tsx +1740 -0
- package/src/tui-ga-raw/selector.js +21 -0
- package/src/tui-ga-raw/shared/07365a7d2ccade4c-host-api.js +269 -0
- package/src/tui-ga-raw/shared/0e19a88ff3535906-command-dialogs.tsx +468 -0
- package/src/tui-ga-raw/shared/1ff34afa7c42d196-projection.js +134 -0
- package/src/tui-ga-raw/shared/77138df80c7ae006-map.js +105 -0
- package/src/tui-ga-raw/shared/8ae1927e5910ea81-sidebar-projection.js +112 -0
- package/src/tui-ga-raw/shared/98cc0c186c46c42d-quota-presentation.js +42 -0
- package/src/tui-ga-raw/shared/aef2402f8fc342f0-format.js +138 -0
- package/src/tui-ga-raw/shared/bf17cbee28e58197-index.js +5 -0
- package/src/tui-ga-raw/shared/ca21dc417b36dc5d-codec.js +12 -0
- package/src/tui-ga-raw/shared/ecc214300932dfb6-merge.js +162 -0
- package/src/tui-raw/common-auth-embedded/logger/capture-sink.js +13 -0
- package/src/tui-raw/common-auth-embedded/logger/engine.js +246 -0
- package/src/tui-raw/common-auth-embedded/logger/index.js +3 -0
- package/src/tui-raw/common-auth-embedded/logger/redact.js +83 -0
- package/src/tui-raw/common-auth-embedded/quota/codec.js +12 -0
- package/src/tui-raw/common-auth-embedded/quota/format.js +138 -0
- package/src/tui-raw/common-auth-embedded/quota/index.js +5 -0
- package/src/tui-raw/common-auth-embedded/quota/map.js +105 -0
- package/src/tui-raw/common-auth-embedded/quota/merge.js +162 -0
- package/src/tui-raw/common-auth-embedded/quota/projection.js +134 -0
- package/src/tui-raw/common-auth-embedded/rpc/client.js +2 -0
- package/src/tui-raw/common-auth-embedded/rpc/port-file.js +217 -0
- package/src/tui-raw/common-auth-embedded/rpc/rpc-client.js +253 -0
- package/src/tui-raw/logging/provider-key-policy.js +3 -0
- package/src/tui-raw/quota-presentation.js +42 -0
- package/src/tui-raw/rpc/rpc-client.js +35 -0
- package/src/tui-raw/rpc/rpc-dir.js +13 -0
- package/src/tui-raw/selector.js +21 -0
- package/src/tui-raw/sidebar-state.js +401 -0
- package/src/tui-raw/tui/command-dialogs.tsx +468 -0
- package/src/tui-raw/tui/file-logger.js +73 -0
- package/src/tui-raw/tui/host-api.js +269 -0
- package/src/tui-raw/tui/host-v1.tsx +249 -0
- package/src/tui-raw/tui-preferences.js +230 -0
- package/src/tui-raw/tui.tsx +1088 -0
- package/src/tui.tsx +58 -141
- package/tui.js +6 -0
- package/src/tui-compiled/plugin/command-data.ts +0 -931
- package/src/tui-compiled/rpc/port-file.ts +0 -143
- package/src/tui-compiled/rpc/protocol.ts +0 -31
- package/src/tui-compiled/rpc/rpc-client.ts +0 -102
- package/src/tui-compiled/rpc/rpc-dir.ts +0 -24
- package/src/tui-compiled/sidebar-state.ts +0 -991
- package/src/tui-compiled/tui/command-dialogs.tsx +0 -779
- package/src/tui-compiled/tui/file-logger.ts +0 -145
- package/src/tui-compiled/tui-preferences.ts +0 -416
|
@@ -0,0 +1,1743 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Antigravity request engine: account selection, retries, endpoint
|
|
3
|
+
* and quota fallback, warmups and response handling for one plugin location.
|
|
4
|
+
*
|
|
5
|
+
* OpenCode 1's `createFetchInterceptor` and the GA location services both
|
|
6
|
+
* call `createRequestExecutor`, so there is exactly one retry loop. Every
|
|
7
|
+
* collaborator with state (accounts, credentials, session metadata, operator
|
|
8
|
+
* settings, wire state, debug log, dump switch, logger, health and token
|
|
9
|
+
* trackers) arrives through `RequestServicesDeps`; this module never reads a
|
|
10
|
+
* module-level OpenCode 1 binding or a host SDK client. Host-only effects
|
|
11
|
+
* (toasts, the sidebar routing file, clearing host-stored OAuth credentials)
|
|
12
|
+
* are optional or explicit callbacks the host binding supplies.
|
|
13
|
+
*
|
|
14
|
+
* The wire rules themselves (payload transformation, header and envelope
|
|
15
|
+
* order, SSE handling) stay in `../request`. The engine receives them as
|
|
16
|
+
* `RequestWire`, which `createRequestWire` binds to one location's signature
|
|
17
|
+
* cache, debug log and logger; the raw sender is called unchanged.
|
|
18
|
+
*/
|
|
19
|
+
import { accessTokenExpired, calculateBackoffMs, computeSoftQuotaCacheTtlMs, getPublicModelDefinitions, getResolverAliasMap, isImageGenerationModel, parseRateLimitReason, preserveResponseMetadata, redactCredentialError, redactCredentialResponse, redactCredentialText, resolveQuotaGroup, VAULT_ACCOUNT_REMEDY, } from '@cortexkit/antigravity-auth-core';
|
|
20
|
+
import { ANTIGRAVITY_ENDPOINT_FALLBACKS, } from '../../constants';
|
|
21
|
+
import { AntigravityKillswitchError } from '../errors';
|
|
22
|
+
import { createRetryState, } from '../fetch/retry-state';
|
|
23
|
+
import { createWarmupState } from '../fetch/warmup';
|
|
24
|
+
import { extractModelFromUrl, getModelFamilyFromUrl, isCapacityRetryBudgetExhausted, MAX_TOTAL_CAPACITY_RETRIES, resolveHeaderRoutingDecision, resolveQuotaFallbackHeaderStyle, toUrlString, toWarmupStreamUrl, } from '../fetch-routing';
|
|
25
|
+
import { noteGeminiDumpResponse } from '../gemini-dump';
|
|
26
|
+
import { evaluateKillswitchForAccount, throwIfAllKilled } from '../killswitch';
|
|
27
|
+
import { createNativeGoogleErrorResponse, createSyntheticTextResponse, isEmptyResponseBody, } from '../request-helpers';
|
|
28
|
+
import { extractOpenCodeSessionIdentity, } from '../session-context';
|
|
29
|
+
import { isLocalGrantError, LocalGrantSupersededError, } from './local-grant';
|
|
30
|
+
import { createRequestCancellation, retainResponseLifetime, } from './request-cancellation';
|
|
31
|
+
/**
|
|
32
|
+
* Wait before retrying the same selection after its first 429.
|
|
33
|
+
*/
|
|
34
|
+
const FIRST_RETRY_DELAY_MS = 1000;
|
|
35
|
+
/**
|
|
36
|
+
* Prepares one upstream Antigravity request: payload transforms, AGY
|
|
37
|
+
* metadata and envelope, header order and the endpoint URL. It is the single
|
|
38
|
+
* entry point the engine uses for every send, and the rules are exactly
|
|
39
|
+
* `RequestWire.prepare`'s.
|
|
40
|
+
*/
|
|
41
|
+
export function prepareAgyWireRequest(wire, request) {
|
|
42
|
+
return wire.prepare(request.input, request.init, request.accessToken, request.projectId, request.endpoint, request.headerStyle, request.forceThinkingRecovery ?? false, request.options);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The model a title request is sent to when the host selected one this
|
|
46
|
+
* plugin does not serve as text: an unregistered model or an image model.
|
|
47
|
+
*/
|
|
48
|
+
export const TITLE_FALLBACK_MODEL = 'gemini-3.5-flash-low';
|
|
49
|
+
/**
|
|
50
|
+
* Routes a title request: a registered text model is kept; any other model
|
|
51
|
+
* (unregistered, or an image model) is replaced in the URL by
|
|
52
|
+
* `TITLE_FALLBACK_MODEL`. Everything else in the URL is unchanged.
|
|
53
|
+
*/
|
|
54
|
+
export function routeTitleModel(url) {
|
|
55
|
+
const model = extractModelFromUrl(url);
|
|
56
|
+
if (model === null)
|
|
57
|
+
return url;
|
|
58
|
+
const registered = Object.hasOwn(getPublicModelDefinitions(), model) ||
|
|
59
|
+
Object.hasOwn(getResolverAliasMap(), model);
|
|
60
|
+
if (registered && !isImageGenerationModel(model))
|
|
61
|
+
return url;
|
|
62
|
+
return url.replace(`/models/${model}`, `/models/${TITLE_FALLBACK_MODEL}`);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The AGY metadata key for a request: the host session for primary (and
|
|
66
|
+
* kind-less) requests, a separate per-kind key for every other kind.
|
|
67
|
+
*/
|
|
68
|
+
function agyMetadataIdentity(identity, kind) {
|
|
69
|
+
if (kind === undefined || kind === 'primary' || !identity.sessionId) {
|
|
70
|
+
return identity;
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
sessionId: `${identity.sessionId}#${kind}`,
|
|
74
|
+
parentSessionId: identity.parentSessionId,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Builds a Google-style 401 envelope describing a missing-account failure.
|
|
79
|
+
*
|
|
80
|
+
* A synthetic 200 SSE body pretending to be a Gemini stream hid the underlying
|
|
81
|
+
* misconfiguration from any caller that inspected `response.status`. Callers
|
|
82
|
+
* (notably OpenCode's HTTP layer) treat 200 as success and silently swallow
|
|
83
|
+
* the payload, so the user sees nothing. Surfacing a real 401 with the
|
|
84
|
+
* standard Google error envelope makes the failure actionable.
|
|
85
|
+
*/
|
|
86
|
+
function createNoAccountResponse(message, model) {
|
|
87
|
+
const body = {
|
|
88
|
+
error: {
|
|
89
|
+
code: 401,
|
|
90
|
+
message,
|
|
91
|
+
status: 'UNAUTHENTICATED',
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
return new Response(JSON.stringify(body), {
|
|
95
|
+
status: 401,
|
|
96
|
+
headers: {
|
|
97
|
+
'Content-Type': 'application/json',
|
|
98
|
+
'X-Antigravity-Error-Type': 'no_accounts',
|
|
99
|
+
'X-Antigravity-Requested-Model': model,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function terminalFetchError(lastError, fallbackMessage) {
|
|
104
|
+
// A synthetic HTTP 200 is parsed as successful assistant text, bypassing the
|
|
105
|
+
// host's retry and error pipeline. Preserve the original exception rather
|
|
106
|
+
// than replacing it with a message-only synthetic response.
|
|
107
|
+
return lastError ?? new Error(fallbackMessage);
|
|
108
|
+
}
|
|
109
|
+
/** Reads `retry-after-ms` / `retry-after` headers, in that order. */
|
|
110
|
+
function retryAfterMsFromResponse(response, defaultRetryMs = 60_000) {
|
|
111
|
+
const retryAfterMsHeader = response.headers.get('retry-after-ms');
|
|
112
|
+
if (retryAfterMsHeader) {
|
|
113
|
+
const parsed = Number.parseInt(retryAfterMsHeader, 10);
|
|
114
|
+
if (!Number.isNaN(parsed) && parsed > 0) {
|
|
115
|
+
return parsed;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const retryAfterHeader = response.headers.get('retry-after');
|
|
119
|
+
if (retryAfterHeader) {
|
|
120
|
+
const parsed = Number.parseInt(retryAfterHeader, 10);
|
|
121
|
+
if (!Number.isNaN(parsed) && parsed > 0) {
|
|
122
|
+
return parsed * 1000;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return defaultRetryMs;
|
|
126
|
+
}
|
|
127
|
+
/** Formats a millisecond duration for human-readable wait/status messages. */
|
|
128
|
+
function formatWaitTime(ms) {
|
|
129
|
+
if (ms < 1000)
|
|
130
|
+
return `${ms}ms`;
|
|
131
|
+
const seconds = Math.ceil(ms / 1000);
|
|
132
|
+
if (seconds < 60)
|
|
133
|
+
return `${seconds}s`;
|
|
134
|
+
const minutes = Math.floor(seconds / 60);
|
|
135
|
+
const remainingSeconds = seconds % 60;
|
|
136
|
+
if (minutes < 60) {
|
|
137
|
+
return remainingSeconds > 0
|
|
138
|
+
? `${minutes}m ${remainingSeconds}s`
|
|
139
|
+
: `${minutes}m`;
|
|
140
|
+
}
|
|
141
|
+
const hours = Math.floor(minutes / 60);
|
|
142
|
+
const remainingMinutes = minutes % 60;
|
|
143
|
+
return remainingMinutes > 0 ? `${hours}h ${remainingMinutes}m` : `${hours}h`;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Sleep for `ms` milliseconds, rejecting with the abort reason when the
|
|
147
|
+
* supplied signal fires before the timer elapses.
|
|
148
|
+
*/
|
|
149
|
+
function sleep(ms, signal) {
|
|
150
|
+
return new Promise((resolve, reject) => {
|
|
151
|
+
if (signal?.aborted) {
|
|
152
|
+
reject(signal.reason instanceof Error ? signal.reason : new Error('Aborted'));
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const timeout = setTimeout(() => {
|
|
156
|
+
cleanup();
|
|
157
|
+
resolve();
|
|
158
|
+
}, ms);
|
|
159
|
+
const onAbort = () => {
|
|
160
|
+
cleanup();
|
|
161
|
+
reject(signal?.reason instanceof Error ? signal.reason : new Error('Aborted'));
|
|
162
|
+
};
|
|
163
|
+
const cleanup = () => {
|
|
164
|
+
clearTimeout(timeout);
|
|
165
|
+
signal?.removeEventListener('abort', onAbort);
|
|
166
|
+
};
|
|
167
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Background quota refresh after a successful send, for rows held in a core
|
|
172
|
+
* account manager. It reads the row's refresh token, so it applies to local
|
|
173
|
+
* credentials only. A reading for a row removed or replaced meanwhile is
|
|
174
|
+
* dropped.
|
|
175
|
+
*/
|
|
176
|
+
export function createLocalQuotaRefresh(accountManager, quotaManager, log) {
|
|
177
|
+
return async function refreshQuotaAfterSuccess(account, intervalMinutes) {
|
|
178
|
+
if (intervalMinutes <= 0)
|
|
179
|
+
return;
|
|
180
|
+
const accountIndex = accountManager.getAccounts().indexOf(account);
|
|
181
|
+
if (accountIndex === -1 || account.enabled === false)
|
|
182
|
+
return;
|
|
183
|
+
const intervalMs = intervalMinutes * 60 * 1000;
|
|
184
|
+
const age = account.cachedQuotaUpdatedAt != null
|
|
185
|
+
? Date.now() - account.cachedQuotaUpdatedAt
|
|
186
|
+
: Infinity;
|
|
187
|
+
if (age < intervalMs)
|
|
188
|
+
return;
|
|
189
|
+
let singleAccount;
|
|
190
|
+
try {
|
|
191
|
+
const accountsForCheck = accountManager.getAccountsForQuotaCheck();
|
|
192
|
+
singleAccount = accountsForCheck[accountIndex];
|
|
193
|
+
if (!singleAccount)
|
|
194
|
+
return;
|
|
195
|
+
// The core quota cache write is attributed to the refresh token the
|
|
196
|
+
// reading was taken with, so a reading never lands on a successor.
|
|
197
|
+
const expectedRefreshToken = singleAccount.refreshToken;
|
|
198
|
+
const result = await quotaManager.refreshAccount(singleAccount, {
|
|
199
|
+
index: accountIndex,
|
|
200
|
+
});
|
|
201
|
+
if (result.status === 'ok' && result.quota?.groups) {
|
|
202
|
+
// Re-resolve the selected row itself. If it was removed meanwhile,
|
|
203
|
+
// drop the reading rather than writing onto whichever row shifted
|
|
204
|
+
// into its slot.
|
|
205
|
+
const currentIndex = accountManager.getAccounts().indexOf(account);
|
|
206
|
+
if (currentIndex === -1)
|
|
207
|
+
return;
|
|
208
|
+
accountManager.updateQuotaCache(currentIndex, result.quota.groups, expectedRefreshToken);
|
|
209
|
+
accountManager.requestSaveToDisk();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
log.debug(`quota-refresh-failed ${singleAccount ? quotaManager.hashedLogLabel('account', singleAccount) : `idx-${accountIndex}`}`, { error: String(err) });
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Builds one location's request engine. Each executor owns its retry and
|
|
219
|
+
* warmup bookkeeping, so disposing it releases every counter.
|
|
220
|
+
*/
|
|
221
|
+
export function createRequestExecutor(deps) {
|
|
222
|
+
const { config, accounts: accountManager, credentials, sessions: agySessionRegistry, operatorSettings, transport: defaultTransport, fetchImpl: upstreamFetch, wire, debug, dump, logger: log, trackers, classifyAccessError, notify, onRouting, } = deps;
|
|
223
|
+
const retryState = createRetryState();
|
|
224
|
+
const warmupState = createWarmupState();
|
|
225
|
+
const shutdown = new AbortController();
|
|
226
|
+
const inFlight = new Set();
|
|
227
|
+
const bufferedOverflow = new WeakMap();
|
|
228
|
+
let retired = false;
|
|
229
|
+
let drainPromise;
|
|
230
|
+
let disposePromise;
|
|
231
|
+
/** Reports a 401 served to an auxiliary send against its admission. */
|
|
232
|
+
const reportVault401 = (admission, status) => {
|
|
233
|
+
if (!admission || status !== 401)
|
|
234
|
+
return;
|
|
235
|
+
void Promise.resolve()
|
|
236
|
+
.then(() => admission.report401(status))
|
|
237
|
+
.catch((error) => {
|
|
238
|
+
log.debug('send-admission-401-report-failed', { error: String(error) });
|
|
239
|
+
});
|
|
240
|
+
};
|
|
241
|
+
const reportRouting = (sessionId, entry) => {
|
|
242
|
+
if (!onRouting)
|
|
243
|
+
return;
|
|
244
|
+
try {
|
|
245
|
+
onRouting(sessionId, entry);
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
log.debug('routing-report-failed', { sessionId, error: String(error) });
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
async function execute(input, init, options = {}, selectedCredentials = new Set()) {
|
|
252
|
+
const assertAdmission = async () => {
|
|
253
|
+
init?.signal?.throwIfAborted();
|
|
254
|
+
await deps.assertAdmission?.();
|
|
255
|
+
init?.signal?.throwIfAborted();
|
|
256
|
+
};
|
|
257
|
+
await assertAdmission();
|
|
258
|
+
// Normalize Request/URL inputs to (urlString, init) so the string-based
|
|
259
|
+
// transform pipeline sees the real method/headers/body. Without this,
|
|
260
|
+
// fetch(new Request(...)) would carry its payload on the Request object
|
|
261
|
+
// where our string path can't read it.
|
|
262
|
+
if (typeof input !== 'string') {
|
|
263
|
+
if (input instanceof Request) {
|
|
264
|
+
const req = input;
|
|
265
|
+
const headers = new Headers(req.headers);
|
|
266
|
+
if (init?.headers) {
|
|
267
|
+
new Headers(init.headers).forEach((v, k) => {
|
|
268
|
+
headers.set(k, v);
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
const bodyBuffer = req.body
|
|
272
|
+
? await req.clone().arrayBuffer()
|
|
273
|
+
: undefined;
|
|
274
|
+
init = {
|
|
275
|
+
method: init?.method ?? req.method,
|
|
276
|
+
headers,
|
|
277
|
+
body: init?.body ?? (bodyBuffer ? Buffer.from(bodyBuffer) : undefined),
|
|
278
|
+
signal: init?.signal ?? req.signal,
|
|
279
|
+
};
|
|
280
|
+
input = req.url;
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
input = String(input.href ?? input);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
// A host that names the request kind (OpenCode 2) routes titles by that
|
|
287
|
+
// kind only. Without a kind (OpenCode 1) the title prompt itself is
|
|
288
|
+
// recognised, as before.
|
|
289
|
+
const kind = options.kind;
|
|
290
|
+
if (kind === undefined || kind === 'title') {
|
|
291
|
+
const localImageTitle = wire.getImageModelLocalTitle(input, init);
|
|
292
|
+
if (localImageTitle !== undefined) {
|
|
293
|
+
return createSyntheticTextResponse(localImageTitle, {
|
|
294
|
+
'X-Antigravity-Response-Type': 'local_title',
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (kind === 'title') {
|
|
299
|
+
input = routeTitleModel(input);
|
|
300
|
+
}
|
|
301
|
+
// A host that sends each request through its own raw sender (the GA
|
|
302
|
+
// loopback bridge) supplies it per request; every send of this request,
|
|
303
|
+
// warmups included, then goes through it with the same AbortSignal.
|
|
304
|
+
const transport = options.transport ?? defaultTransport;
|
|
305
|
+
const requestSessionIdentity = options.session ?? extractOpenCodeSessionIdentity(init?.headers);
|
|
306
|
+
// AGY conversation/trajectory/step metadata is kept per session and
|
|
307
|
+
// request kind: a title or compaction request never advances the
|
|
308
|
+
// primary conversation's step counter or shares its trajectory.
|
|
309
|
+
const agyRequestScope = agySessionRegistry.beginRequest(agyMetadataIdentity(requestSessionIdentity, kind));
|
|
310
|
+
const agyRequestSession = agyRequestScope.session;
|
|
311
|
+
const accountSessionIdentity = requestSessionIdentity.sessionId
|
|
312
|
+
? {
|
|
313
|
+
id: requestSessionIdentity.sessionId,
|
|
314
|
+
parentId: requestSessionIdentity.parentSessionId,
|
|
315
|
+
}
|
|
316
|
+
: undefined;
|
|
317
|
+
const isChildRequest = requestSessionIdentity.parentSessionId !== null;
|
|
318
|
+
if (accountManager.getAccountCount() === 0) {
|
|
319
|
+
// Surface a real 401 with the Google error envelope instead of a
|
|
320
|
+
// 200 SSE body — OpenCode's HTTP layer treats 200 as success and
|
|
321
|
+
// would otherwise swallow the misconfiguration silently.
|
|
322
|
+
const urlString = typeof input === 'string' ? input : toUrlString(input);
|
|
323
|
+
const modelFromUrl = extractModelFromUrl(urlString) ?? 'unknown';
|
|
324
|
+
return createNoAccountResponse(credentials.domain === 'vault'
|
|
325
|
+
? VAULT_ACCOUNT_REMEDY
|
|
326
|
+
: 'No Antigravity accounts configured. Run `opencode auth login`.', modelFromUrl);
|
|
327
|
+
}
|
|
328
|
+
const urlString = toUrlString(input);
|
|
329
|
+
const family = getModelFamilyFromUrl(urlString, debug);
|
|
330
|
+
const model = extractModelFromUrl(urlString);
|
|
331
|
+
const debugLines = [];
|
|
332
|
+
const pushDebug = (line) => {
|
|
333
|
+
if (!debug.isDebugEnabled())
|
|
334
|
+
return;
|
|
335
|
+
debugLines.push(redactCredentialText(line, [...selectedCredentials]));
|
|
336
|
+
};
|
|
337
|
+
pushDebug(`request=${urlString}`);
|
|
338
|
+
if (requestSessionIdentity.sessionId) {
|
|
339
|
+
pushDebug(`[Session] id=${requestSessionIdentity.sessionId}` +
|
|
340
|
+
` parent=${requestSessionIdentity.parentSessionId ?? 'none'}` +
|
|
341
|
+
` child=${isChildRequest}`);
|
|
342
|
+
}
|
|
343
|
+
const cachedStats = wire.getLastCacheStats();
|
|
344
|
+
if (cachedStats) {
|
|
345
|
+
const label = cachedStats.hitRate > 0 ? 'HIT' : 'MISS';
|
|
346
|
+
pushDebug(`[Cache] ${label} model=${cachedStats.model} read=${cachedStats.read} total=${cachedStats.total} hitRate=${cachedStats.hitRate}%`);
|
|
347
|
+
}
|
|
348
|
+
let lastFailure = null;
|
|
349
|
+
let lastError = null;
|
|
350
|
+
const abortSignal = init?.signal ?? undefined;
|
|
351
|
+
const checkAborted = () => {
|
|
352
|
+
if (abortSignal?.aborted) {
|
|
353
|
+
throw abortSignal.reason instanceof Error
|
|
354
|
+
? abortSignal.reason
|
|
355
|
+
: new Error('Aborted');
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
const quietMode = config.quiet_mode;
|
|
359
|
+
const toastScope = config.toast_scope;
|
|
360
|
+
// Apply operator-controlled routing overrides live. The slash
|
|
361
|
+
// commands mutate these values through `applyCommand`; reading
|
|
362
|
+
// them per-request means a runtime flip takes effect on the next
|
|
363
|
+
// dispatched call without restarting the plugin.
|
|
364
|
+
const operatorRouting = operatorSettings?.get().routing;
|
|
365
|
+
const effectiveConfig = {
|
|
366
|
+
...config,
|
|
367
|
+
cli_first: operatorRouting?.cli_first ?? config.cli_first,
|
|
368
|
+
quota_style_fallback: operatorRouting?.quota_style_fallback ?? config.quota_style_fallback,
|
|
369
|
+
};
|
|
370
|
+
const showToast = async (message, variant) => {
|
|
371
|
+
log.debug('toast', {
|
|
372
|
+
message,
|
|
373
|
+
variant,
|
|
374
|
+
isChildSession: isChildRequest,
|
|
375
|
+
toastScope,
|
|
376
|
+
});
|
|
377
|
+
if (quietMode)
|
|
378
|
+
return;
|
|
379
|
+
if (abortSignal?.aborted)
|
|
380
|
+
return;
|
|
381
|
+
if (toastScope === 'root_only' && isChildRequest) {
|
|
382
|
+
log.debug('toast-suppressed-child-session', {
|
|
383
|
+
message,
|
|
384
|
+
variant,
|
|
385
|
+
parentID: requestSessionIdentity.parentSessionId,
|
|
386
|
+
});
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
if (variant === 'warning' && message.toLowerCase().includes('rate')) {
|
|
390
|
+
if (!retryState.shouldShowRateLimitToast(message)) {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
try {
|
|
395
|
+
await notify?.(message, variant);
|
|
396
|
+
}
|
|
397
|
+
catch {
|
|
398
|
+
// TUI may not be available
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
const hasOtherAccountWithAntigravity = (currentAccount) => {
|
|
402
|
+
if (family !== 'gemini')
|
|
403
|
+
return false;
|
|
404
|
+
return accountManager.hasOtherAccountWithAntigravityAvailable(currentAccount.index, family, model);
|
|
405
|
+
};
|
|
406
|
+
let accountSwitchCount = 0;
|
|
407
|
+
const maxAccountSwitches = config.max_account_switches ?? 2;
|
|
408
|
+
let previousAccountIndex = -1;
|
|
409
|
+
let needsCacheWarmup = false;
|
|
410
|
+
let localRecaptureUsed = false;
|
|
411
|
+
while (true) {
|
|
412
|
+
await assertAdmission();
|
|
413
|
+
checkAborted();
|
|
414
|
+
const accountCount = accountManager.getAccountCount();
|
|
415
|
+
const routingDecision = resolveHeaderRoutingDecision(urlString, family, effectiveConfig);
|
|
416
|
+
const { preferredHeaderStyle, explicitQuota, allowQuotaFallback } = routingDecision;
|
|
417
|
+
if (accountCount === 0) {
|
|
418
|
+
// Mirror the no-account short-circuit inside the retry loop so callers
|
|
419
|
+
// that race with account removal still get a proper 401 instead of a
|
|
420
|
+
// hang or a synthetic 200.
|
|
421
|
+
return createNoAccountResponse('No Antigravity accounts available. Run `opencode auth login`.', model ?? 'unknown');
|
|
422
|
+
}
|
|
423
|
+
const softQuotaCacheTtlMs = computeSoftQuotaCacheTtlMs(config.soft_quota_cache_ttl_minutes, config.quota_refresh_interval_minutes);
|
|
424
|
+
// Operator killswitch: an account whose cached remaining quota for
|
|
425
|
+
// this model's quota group is below the configured floor is not
|
|
426
|
+
// eligible. Missing or stale quota counts as eligible, so a cold
|
|
427
|
+
// start cannot block every account.
|
|
428
|
+
const operatorKillswitch = operatorSettings?.get().killswitch;
|
|
429
|
+
const eligibleIndexes = operatorKillswitch?.enabled
|
|
430
|
+
? new Set(accountManager
|
|
431
|
+
.getAccounts()
|
|
432
|
+
.filter((entry) => {
|
|
433
|
+
const decision = evaluateKillswitchForAccount(entry, family, {
|
|
434
|
+
routing: effectiveConfig.cli_first !== undefined
|
|
435
|
+
? {
|
|
436
|
+
cli_first: effectiveConfig.cli_first,
|
|
437
|
+
quota_style_fallback: !!effectiveConfig.quota_style_fallback,
|
|
438
|
+
}
|
|
439
|
+
: { cli_first: false, quota_style_fallback: false },
|
|
440
|
+
killswitch: operatorKillswitch,
|
|
441
|
+
log_level: 'info',
|
|
442
|
+
}, { now: Date.now(), model });
|
|
443
|
+
return decision.allowed;
|
|
444
|
+
})
|
|
445
|
+
.map((entry) => entry.index))
|
|
446
|
+
: null;
|
|
447
|
+
if (eligibleIndexes !== null &&
|
|
448
|
+
eligibleIndexes.size === 0 &&
|
|
449
|
+
accountCount > 0) {
|
|
450
|
+
try {
|
|
451
|
+
throwIfAllKilled({
|
|
452
|
+
family,
|
|
453
|
+
model: model ?? 'unknown',
|
|
454
|
+
accounts: accountManager.getAccounts(),
|
|
455
|
+
settings: {
|
|
456
|
+
routing: { cli_first: false, quota_style_fallback: false },
|
|
457
|
+
killswitch: operatorKillswitch ?? {
|
|
458
|
+
enabled: false,
|
|
459
|
+
minimum_remaining_percent: 0,
|
|
460
|
+
},
|
|
461
|
+
log_level: 'info',
|
|
462
|
+
},
|
|
463
|
+
quotaModel: model,
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
catch (error) {
|
|
467
|
+
if (error instanceof AntigravityKillswitchError) {
|
|
468
|
+
log.warn('killswitch-all-excluded', {
|
|
469
|
+
family,
|
|
470
|
+
model,
|
|
471
|
+
threshold: error.thresholdPercent,
|
|
472
|
+
summaries: error.summaries,
|
|
473
|
+
});
|
|
474
|
+
return createNativeGoogleErrorResponse({
|
|
475
|
+
status: 412,
|
|
476
|
+
reason: 'operator_policy',
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
throw error;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
// The eligibility mask above is computed once for this selection
|
|
483
|
+
// pass and applies to both the initial selection and the header-style
|
|
484
|
+
// fallback below. Selection does not re-evaluate quota, so a killed
|
|
485
|
+
// current account falls through to the next eligible account.
|
|
486
|
+
const killedIndexes = eligibleIndexes === null
|
|
487
|
+
? undefined
|
|
488
|
+
: new Set(accountManager
|
|
489
|
+
.getAccounts()
|
|
490
|
+
.map((entry) => entry.index)
|
|
491
|
+
.filter((index) => !eligibleIndexes.has(index)));
|
|
492
|
+
let account = accountManager.getCurrentOrNextForFamily(family, model, config.account_selection_strategy, preferredHeaderStyle, config.pid_offset_enabled, config.soft_quota_threshold_percent, softQuotaCacheTtlMs, accountSessionIdentity, killedIndexes);
|
|
493
|
+
// The selected account must be inside the eligibility mask.
|
|
494
|
+
if (account &&
|
|
495
|
+
eligibleIndexes !== null &&
|
|
496
|
+
!eligibleIndexes.has(account.index)) {
|
|
497
|
+
pushDebug(`killswitch-excluded idx=${account.index} (precomputed eligible set)`);
|
|
498
|
+
account = null;
|
|
499
|
+
}
|
|
500
|
+
if (!account && allowQuotaFallback) {
|
|
501
|
+
const alternateHeaderStyle = preferredHeaderStyle === 'antigravity' ? 'gemini-cli' : 'antigravity';
|
|
502
|
+
account = accountManager.getCurrentOrNextForFamily(family, model, config.account_selection_strategy, alternateHeaderStyle, config.pid_offset_enabled, config.soft_quota_threshold_percent, softQuotaCacheTtlMs, accountSessionIdentity, killedIndexes);
|
|
503
|
+
if (account) {
|
|
504
|
+
pushDebug(`selected-by-fallback idx=${account.index} preferred=${preferredHeaderStyle} alternate=${alternateHeaderStyle}`);
|
|
505
|
+
}
|
|
506
|
+
// The header-style fallback may not select an account outside the
|
|
507
|
+
// eligibility mask.
|
|
508
|
+
if (account &&
|
|
509
|
+
eligibleIndexes !== null &&
|
|
510
|
+
!eligibleIndexes.has(account.index)) {
|
|
511
|
+
pushDebug(`killswitch-excluded idx=${account.index} after fallback (precomputed eligible set)`);
|
|
512
|
+
account = null;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
if (!account) {
|
|
516
|
+
if (accountManager.areAllAccountsOverSoftQuota(family, config.soft_quota_threshold_percent, softQuotaCacheTtlMs, model)) {
|
|
517
|
+
const threshold = config.soft_quota_threshold_percent;
|
|
518
|
+
const softQuotaWaitMs = accountManager.getMinWaitTimeForSoftQuota(family, threshold, softQuotaCacheTtlMs, model);
|
|
519
|
+
const maxWaitMs = (config.max_rate_limit_wait_seconds ?? 300) * 1000;
|
|
520
|
+
if (softQuotaWaitMs === null ||
|
|
521
|
+
(maxWaitMs > 0 && softQuotaWaitMs > maxWaitMs)) {
|
|
522
|
+
const waitTimeFormatted = softQuotaWaitMs
|
|
523
|
+
? formatWaitTime(softQuotaWaitMs)
|
|
524
|
+
: 'unknown';
|
|
525
|
+
await showToast(`All accounts over ${threshold}% quota threshold. Resets in ${waitTimeFormatted}.`, 'error');
|
|
526
|
+
return createNativeGoogleErrorResponse({
|
|
527
|
+
status: 412,
|
|
528
|
+
reason: 'soft_quota',
|
|
529
|
+
resetAfterMs: softQuotaWaitMs,
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
pushDebug(`all-over-soft-quota family=${family} accounts=${accountCount} waitMs=${softQuotaWaitMs}`);
|
|
533
|
+
if (!retryState.softQuotaToastShown()) {
|
|
534
|
+
await showToast(`All ${accountCount} account(s) over ${threshold}% quota. Waiting ${formatWaitTime(softQuotaWaitMs)}...`, 'warning');
|
|
535
|
+
retryState.markSoftQuotaToastShown();
|
|
536
|
+
}
|
|
537
|
+
await sleep(softQuotaWaitMs, abortSignal);
|
|
538
|
+
continue;
|
|
539
|
+
}
|
|
540
|
+
const strictWait = !allowQuotaFallback;
|
|
541
|
+
const minWaitMs = accountManager.getMinWaitTimeForFamily(family, model, preferredHeaderStyle, strictWait);
|
|
542
|
+
const waitMs = minWaitMs || 60_000;
|
|
543
|
+
pushDebug(`all-rate-limited family=${family} accounts=${accountCount} waitMs=${waitMs}`);
|
|
544
|
+
if (debug.isDebugEnabled()) {
|
|
545
|
+
debug.logAccountContext('All accounts rate-limited', {
|
|
546
|
+
index: -1,
|
|
547
|
+
family,
|
|
548
|
+
totalAccounts: accountCount,
|
|
549
|
+
});
|
|
550
|
+
debug.logRateLimitSnapshot(family, accountManager.getAccountsSnapshot());
|
|
551
|
+
}
|
|
552
|
+
const maxWaitMs = (config.max_rate_limit_wait_seconds ?? 300) * 1000;
|
|
553
|
+
if (maxWaitMs > 0 && waitMs > maxWaitMs) {
|
|
554
|
+
const waitTimeFormatted = formatWaitTime(waitMs);
|
|
555
|
+
await showToast(`Rate limited for ${waitTimeFormatted}. Try again later or add another account.`, 'error');
|
|
556
|
+
return createNativeGoogleErrorResponse({
|
|
557
|
+
status: 412,
|
|
558
|
+
reason: 'pool_unavailable',
|
|
559
|
+
// Zero means the account manager has no future reset to report.
|
|
560
|
+
// The fallback sleep duration above is not a quota reset estimate.
|
|
561
|
+
resetAfterMs: minWaitMs > 0 ? minWaitMs : undefined,
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
if (!retryState.rateLimitToastShown()) {
|
|
565
|
+
const waitSecValue = Math.max(1, Math.ceil(waitMs / 1000));
|
|
566
|
+
await showToast(`All ${accountCount} account(s) rate-limited for ${family}. Waiting ${waitSecValue}s...`, 'warning');
|
|
567
|
+
retryState.markRateLimitToastShown();
|
|
568
|
+
}
|
|
569
|
+
await sleep(waitMs, abortSignal);
|
|
570
|
+
continue;
|
|
571
|
+
}
|
|
572
|
+
// Account is available - reset the toast flag
|
|
573
|
+
retryState.resetAllAccountsBlockedToasts();
|
|
574
|
+
pushDebug(`selected idx=${account.index} email=${account.email ?? ''} family=${family} accounts=${accountCount} strategy=${config.account_selection_strategy}`);
|
|
575
|
+
if (previousAccountIndex >= 0 && previousAccountIndex !== account.index) {
|
|
576
|
+
needsCacheWarmup = config.cache_warmup_on_switch;
|
|
577
|
+
pushDebug(`account-switch: ${previousAccountIndex} → ${account.index}, warmup=${needsCacheWarmup}`);
|
|
578
|
+
}
|
|
579
|
+
previousAccountIndex = account.index;
|
|
580
|
+
accountManager.recordSessionUsage(account.index, accountSessionIdentity);
|
|
581
|
+
if (debug.isDebugEnabled()) {
|
|
582
|
+
debug.logAccountContext('Selected', {
|
|
583
|
+
index: account.index,
|
|
584
|
+
email: account.email,
|
|
585
|
+
family,
|
|
586
|
+
totalAccounts: accountCount,
|
|
587
|
+
rateLimitState: account.rateLimitResetTimes,
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
if (accountCount > 1 &&
|
|
591
|
+
accountManager.shouldShowAccountToast(account.index)) {
|
|
592
|
+
const accountLabel = account.email || `Account ${account.index + 1}`;
|
|
593
|
+
const enabledAccounts = accountManager.getEnabledAccounts();
|
|
594
|
+
const enabledPosition = enabledAccounts.findIndex((a) => a.index === account.index) + 1;
|
|
595
|
+
await showToast(`Using ${accountLabel} (${enabledPosition}/${accountCount})`, 'info');
|
|
596
|
+
accountManager.markToastShown(account.index);
|
|
597
|
+
}
|
|
598
|
+
accountManager.requestSaveToDisk();
|
|
599
|
+
// Local credentials only: refresh the row's stored token when it has
|
|
600
|
+
// expired, resolve its project and write both back to the pool; that
|
|
601
|
+
// token and project serve the sends of this selection. The vault
|
|
602
|
+
// domain skips this entirely: it has no stored token, no refresh and
|
|
603
|
+
// no project cache, and takes a fresh admission for every physical
|
|
604
|
+
// send below.
|
|
605
|
+
let localGrant = null;
|
|
606
|
+
const prepareLocalGrant = async (auth, captured, persistProject = true) => {
|
|
607
|
+
if (credentials.domain !== 'local' || !auth.access)
|
|
608
|
+
throw new Error('Local credentials were not resolved');
|
|
609
|
+
await assertAdmission();
|
|
610
|
+
// Project resolution can use this bearer before the main model send.
|
|
611
|
+
if (auth.access)
|
|
612
|
+
selectedCredentials.add(auth.access);
|
|
613
|
+
const context = await credentials
|
|
614
|
+
.ensureProject(auth)
|
|
615
|
+
.catch((error) => {
|
|
616
|
+
throw redactCredentialError(error, [...selectedCredentials]);
|
|
617
|
+
});
|
|
618
|
+
await assertAdmission();
|
|
619
|
+
// A project cache may carry an older bearer. Only the token fixed
|
|
620
|
+
// before this await belongs to the newly prepared request.
|
|
621
|
+
const projectAuth = {
|
|
622
|
+
...context.auth,
|
|
623
|
+
access: auth.access,
|
|
624
|
+
expires: auth.expires,
|
|
625
|
+
};
|
|
626
|
+
if (persistProject && projectAuth.refresh !== auth.refresh) {
|
|
627
|
+
credentials.updateFromAuth(account, projectAuth);
|
|
628
|
+
try {
|
|
629
|
+
await credentials.saveToDisk();
|
|
630
|
+
}
|
|
631
|
+
catch (error) {
|
|
632
|
+
log.error('Failed to persist project context', {
|
|
633
|
+
error: String(error),
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
return {
|
|
638
|
+
accessToken: auth.access,
|
|
639
|
+
projectId: context.effectiveProjectId,
|
|
640
|
+
captured,
|
|
641
|
+
};
|
|
642
|
+
};
|
|
643
|
+
if (credentials.domain === 'local') {
|
|
644
|
+
let authRecord = credentials.toAuthDetails(account);
|
|
645
|
+
// The grant is captured synchronously the moment its token is fixed
|
|
646
|
+
// (the stored token, or the refresh's successor), before any later
|
|
647
|
+
// await such as the save or project resolution. Its check therefore
|
|
648
|
+
// judges every send against the row this token was resolved for,
|
|
649
|
+
// even if the account object changes during those waits.
|
|
650
|
+
const captureFor = (auth) => auth.access
|
|
651
|
+
? credentials.captureGrant({ account, accessToken: auth.access })
|
|
652
|
+
: undefined;
|
|
653
|
+
let grantCheck = accessTokenExpired(authRecord)
|
|
654
|
+
? undefined
|
|
655
|
+
: captureFor(authRecord);
|
|
656
|
+
if (accessTokenExpired(authRecord)) {
|
|
657
|
+
try {
|
|
658
|
+
await assertAdmission();
|
|
659
|
+
const refreshed = await credentials.refresh(account);
|
|
660
|
+
if (!refreshed) {
|
|
661
|
+
const { failures, shouldCooldown, cooldownMs } = retryState.trackAccountFailure(account.index);
|
|
662
|
+
trackers.health.recordFailure(account.index);
|
|
663
|
+
lastError = new Error('Antigravity token refresh failed');
|
|
664
|
+
// A refresh that yields no credential is an authentication
|
|
665
|
+
// failure. With no other account to try, answer the native 401
|
|
666
|
+
// the missing-token check below gives, rather than retrying
|
|
667
|
+
// until the cooldown turns it into a pool-unavailable 412.
|
|
668
|
+
if (accountCount <= 1) {
|
|
669
|
+
return createNativeGoogleErrorResponse({
|
|
670
|
+
status: 401,
|
|
671
|
+
reason: 'missing_access_token',
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
if (shouldCooldown) {
|
|
675
|
+
accountManager.markAccountCoolingDown(account, cooldownMs, 'auth-failure');
|
|
676
|
+
accountManager.markRateLimited(account, cooldownMs, family, 'antigravity', model);
|
|
677
|
+
pushDebug(`token-refresh-failed: cooldown ${cooldownMs}ms after ${failures} failures`);
|
|
678
|
+
}
|
|
679
|
+
continue;
|
|
680
|
+
}
|
|
681
|
+
retryState.resetAccountFailureState(account.index);
|
|
682
|
+
credentials.updateFromAuth(account, refreshed);
|
|
683
|
+
authRecord = refreshed;
|
|
684
|
+
grantCheck = captureFor(authRecord);
|
|
685
|
+
try {
|
|
686
|
+
await credentials.saveToDisk();
|
|
687
|
+
}
|
|
688
|
+
catch (error) {
|
|
689
|
+
log.error('Failed to persist refreshed auth', {
|
|
690
|
+
error: String(error),
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
catch (error) {
|
|
695
|
+
if (credentials.isInvalidGrant(error)) {
|
|
696
|
+
const removed = credentials.removeAccount(account);
|
|
697
|
+
if (removed) {
|
|
698
|
+
log.warn('Removed revoked account from pool - reauthenticate via `opencode auth login`');
|
|
699
|
+
try {
|
|
700
|
+
await credentials.saveToDiskReplace();
|
|
701
|
+
}
|
|
702
|
+
catch (persistError) {
|
|
703
|
+
log.error('Failed to persist revoked account removal', {
|
|
704
|
+
error: String(persistError),
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
if (accountManager.getAccountCount() === 0) {
|
|
709
|
+
try {
|
|
710
|
+
await credentials.clearStoredAuth();
|
|
711
|
+
}
|
|
712
|
+
catch (storeError) {
|
|
713
|
+
log.error('Failed to clear stored Antigravity OAuth credentials', {
|
|
714
|
+
error: String(storeError),
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
return createNoAccountResponse('All Antigravity accounts have invalid refresh tokens. Run `opencode auth login` and reauthenticate.', model ?? 'unknown');
|
|
718
|
+
}
|
|
719
|
+
lastError =
|
|
720
|
+
error instanceof Error ? error : new Error(String(error));
|
|
721
|
+
continue;
|
|
722
|
+
}
|
|
723
|
+
const { failures, shouldCooldown, cooldownMs } = retryState.trackAccountFailure(account.index);
|
|
724
|
+
trackers.health.recordFailure(account.index);
|
|
725
|
+
lastError =
|
|
726
|
+
error instanceof Error ? error : new Error(String(error));
|
|
727
|
+
if (shouldCooldown) {
|
|
728
|
+
accountManager.markAccountCoolingDown(account, cooldownMs, 'auth-failure');
|
|
729
|
+
accountManager.markRateLimited(account, cooldownMs, family, 'antigravity', model);
|
|
730
|
+
pushDebug(`token-refresh-error: cooldown ${cooldownMs}ms after ${failures} failures`);
|
|
731
|
+
}
|
|
732
|
+
continue;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
const accessToken = authRecord.access;
|
|
736
|
+
// Require the account-identity check captured with this access token
|
|
737
|
+
// before dispatch.
|
|
738
|
+
if (!accessToken || grantCheck === undefined) {
|
|
739
|
+
lastError = new Error('Missing access token');
|
|
740
|
+
if (accountCount <= 1) {
|
|
741
|
+
return createNativeGoogleErrorResponse({
|
|
742
|
+
status: 401,
|
|
743
|
+
reason: 'missing_access_token',
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
continue;
|
|
747
|
+
}
|
|
748
|
+
try {
|
|
749
|
+
localGrant = await prepareLocalGrant(authRecord, grantCheck);
|
|
750
|
+
retryState.resetAccountFailureState(account.index);
|
|
751
|
+
}
|
|
752
|
+
catch (error) {
|
|
753
|
+
const { failures, shouldCooldown, cooldownMs } = retryState.trackAccountFailure(account.index);
|
|
754
|
+
trackers.health.recordFailure(account.index);
|
|
755
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
756
|
+
if (shouldCooldown) {
|
|
757
|
+
accountManager.markAccountCoolingDown(account, cooldownMs, 'project-error');
|
|
758
|
+
accountManager.markRateLimited(account, cooldownMs, family, 'antigravity', model);
|
|
759
|
+
pushDebug(`project-context-error: cooldown ${cooldownMs}ms after ${failures} failures`);
|
|
760
|
+
}
|
|
761
|
+
continue;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
const selected = account;
|
|
765
|
+
// Credentials for one auxiliary physical send (thinking warmup or cache
|
|
766
|
+
// probe) built from a prepared request. Local: the selection's grant
|
|
767
|
+
// must still be the row's current credential. Vault: a fresh admission
|
|
768
|
+
// for this send alone; its token replaces the prepared one, and its
|
|
769
|
+
// project must be the prepared request's, otherwise the send is
|
|
770
|
+
// skipped rather than sent under a project from another receipt.
|
|
771
|
+
const credentialForAuxiliarySend = async (sendInit, preparedProjectId) => {
|
|
772
|
+
await assertAdmission();
|
|
773
|
+
if (credentials.domain === 'vault') {
|
|
774
|
+
const admission = await credentials.admit({
|
|
775
|
+
account: selected,
|
|
776
|
+
signal: abortSignal,
|
|
777
|
+
});
|
|
778
|
+
selectedCredentials.add(admission.accessToken);
|
|
779
|
+
if (admission.projectId !== preparedProjectId) {
|
|
780
|
+
throw new Error('The vault served another project for this send; skipping it');
|
|
781
|
+
}
|
|
782
|
+
const headers = new Headers(sendInit.headers);
|
|
783
|
+
headers.set('Authorization', `Bearer ${admission.accessToken}`);
|
|
784
|
+
return { init: { ...sendInit, headers }, admission };
|
|
785
|
+
}
|
|
786
|
+
if (!localGrant) {
|
|
787
|
+
throw new Error('Local credentials were not resolved for the selected account');
|
|
788
|
+
}
|
|
789
|
+
await localGrant.captured.check();
|
|
790
|
+
await assertAdmission();
|
|
791
|
+
return { init: sendInit };
|
|
792
|
+
};
|
|
793
|
+
const runThinkingWarmup = async (prepared, projectId) => {
|
|
794
|
+
if (!config.thinking_warmup)
|
|
795
|
+
return;
|
|
796
|
+
if (!prepared.needsSignedThinkingWarmup || !prepared.sessionId)
|
|
797
|
+
return;
|
|
798
|
+
if (!warmupState.trackAttempt(prepared.sessionId))
|
|
799
|
+
return;
|
|
800
|
+
const warmupBody = wire.buildThinkingWarmupBody(typeof prepared.init.body === 'string'
|
|
801
|
+
? prepared.init.body
|
|
802
|
+
: undefined, Boolean(prepared.effectiveModel?.toLowerCase().includes('claude') &&
|
|
803
|
+
prepared.effectiveModel?.toLowerCase().includes('thinking')));
|
|
804
|
+
if (!warmupBody)
|
|
805
|
+
return;
|
|
806
|
+
const warmupUrl = toWarmupStreamUrl(prepared.request);
|
|
807
|
+
const warmupHeaders = new Headers(prepared.init.headers ?? {});
|
|
808
|
+
warmupHeaders.set('accept', 'text/event-stream');
|
|
809
|
+
const warmupInit = {
|
|
810
|
+
...prepared.init,
|
|
811
|
+
method: prepared.init.method ?? 'POST',
|
|
812
|
+
headers: warmupHeaders,
|
|
813
|
+
body: warmupBody,
|
|
814
|
+
};
|
|
815
|
+
const warmupDebugContext = debug.startAntigravityDebugRequest({
|
|
816
|
+
originalUrl: warmupUrl,
|
|
817
|
+
resolvedUrl: warmupUrl,
|
|
818
|
+
method: warmupInit.method,
|
|
819
|
+
headers: warmupHeaders,
|
|
820
|
+
body: warmupBody,
|
|
821
|
+
streaming: true,
|
|
822
|
+
projectId,
|
|
823
|
+
});
|
|
824
|
+
try {
|
|
825
|
+
pushDebug('thinking-warmup: start');
|
|
826
|
+
const warmupSend = await credentialForAuxiliarySend(warmupInit, projectId);
|
|
827
|
+
const warmupResponse = prepared.headerStyle === 'antigravity'
|
|
828
|
+
? await transport(warmupUrl, warmupSend.init, {
|
|
829
|
+
signal: abortSignal,
|
|
830
|
+
onDebug: pushDebug,
|
|
831
|
+
})
|
|
832
|
+
: await upstreamFetch(warmupUrl, warmupSend.init);
|
|
833
|
+
reportVault401(warmupSend.admission, warmupResponse.status);
|
|
834
|
+
const transformed = await wire.transformResponse(warmupResponse, true, warmupDebugContext, prepared.requestedModel, projectId, warmupUrl, prepared.effectiveModel, prepared.sessionId);
|
|
835
|
+
await transformed.text();
|
|
836
|
+
warmupState.markSuccess(prepared.sessionId);
|
|
837
|
+
pushDebug('thinking-warmup: done');
|
|
838
|
+
}
|
|
839
|
+
catch (error) {
|
|
840
|
+
warmupState.clearWarmupAttempt(prepared.sessionId);
|
|
841
|
+
if (isLocalGrantError(error))
|
|
842
|
+
throw error;
|
|
843
|
+
pushDebug(`thinking-warmup: failed ${error instanceof Error ? error.message : String(error)}`);
|
|
844
|
+
}
|
|
845
|
+
};
|
|
846
|
+
const runCacheWarmupProbe = async (prepared) => {
|
|
847
|
+
if (!needsCacheWarmup)
|
|
848
|
+
return;
|
|
849
|
+
needsCacheWarmup = false;
|
|
850
|
+
const bodyStr = typeof prepared.init.body === 'string'
|
|
851
|
+
? prepared.init.body
|
|
852
|
+
: undefined;
|
|
853
|
+
if (!bodyStr)
|
|
854
|
+
return;
|
|
855
|
+
try {
|
|
856
|
+
pushDebug('cache-warmup-probe: start');
|
|
857
|
+
const probeSend = await credentialForAuxiliarySend({ ...prepared.init, method: 'POST', body: bodyStr }, prepared.projectId ?? '');
|
|
858
|
+
const probeResponse = prepared.headerStyle === 'antigravity'
|
|
859
|
+
? await transport(toUrlString(prepared.request), probeSend.init, {
|
|
860
|
+
signal: abortSignal,
|
|
861
|
+
onDebug: pushDebug,
|
|
862
|
+
})
|
|
863
|
+
: await upstreamFetch(toUrlString(prepared.request), probeSend.init);
|
|
864
|
+
reportVault401(probeSend.admission, probeResponse.status);
|
|
865
|
+
if (probeResponse.body) {
|
|
866
|
+
const reader = probeResponse.body.getReader();
|
|
867
|
+
await reader.read();
|
|
868
|
+
await reader.cancel();
|
|
869
|
+
}
|
|
870
|
+
const status = probeResponse.status;
|
|
871
|
+
if (status >= 400) {
|
|
872
|
+
let errorSnippet = '';
|
|
873
|
+
try {
|
|
874
|
+
const errText = await probeResponse.text().catch(() => '');
|
|
875
|
+
errorSnippet = errText.slice(0, 200);
|
|
876
|
+
}
|
|
877
|
+
catch {
|
|
878
|
+
/* ignore */
|
|
879
|
+
}
|
|
880
|
+
pushDebug(`cache-warmup-probe: done status=${status}${errorSnippet ? ` error=${errorSnippet}` : ''}`);
|
|
881
|
+
}
|
|
882
|
+
else {
|
|
883
|
+
pushDebug(`cache-warmup-probe: done status=${status} (aborted after first chunk)`);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
catch (error) {
|
|
887
|
+
if (isLocalGrantError(error)) {
|
|
888
|
+
needsCacheWarmup = true;
|
|
889
|
+
throw error;
|
|
890
|
+
}
|
|
891
|
+
pushDebug(`cache-warmup-probe: failed ${error instanceof Error ? error.message : String(error)}`);
|
|
892
|
+
}
|
|
893
|
+
};
|
|
894
|
+
let apiRequestCount = 0;
|
|
895
|
+
let shouldSwitchAccount = false;
|
|
896
|
+
let headerStyle = preferredHeaderStyle;
|
|
897
|
+
pushDebug(`headerStyle=${headerStyle} explicit=${explicitQuota}`);
|
|
898
|
+
if (account.fingerprint) {
|
|
899
|
+
pushDebug(`fingerprint: deviceId=${account.fingerprint.deviceId.slice(0, 8)}...`);
|
|
900
|
+
}
|
|
901
|
+
if (accountManager.isRateLimitedForHeaderStyle(account, family, headerStyle, model)) {
|
|
902
|
+
if (allowQuotaFallback &&
|
|
903
|
+
family === 'gemini' &&
|
|
904
|
+
headerStyle === 'antigravity') {
|
|
905
|
+
if (accountManager.hasOtherAccountWithAntigravityAvailable(account.index, family, model)) {
|
|
906
|
+
pushDebug(`antigravity rate-limited on account ${account.index}, but available on other accounts. Switching.`);
|
|
907
|
+
shouldSwitchAccount = true;
|
|
908
|
+
}
|
|
909
|
+
else {
|
|
910
|
+
const alternateStyle = accountManager.getAvailableHeaderStyle(account, family, model);
|
|
911
|
+
const fallbackStyle = resolveQuotaFallbackHeaderStyle({
|
|
912
|
+
family,
|
|
913
|
+
headerStyle,
|
|
914
|
+
alternateStyle,
|
|
915
|
+
});
|
|
916
|
+
if (fallbackStyle) {
|
|
917
|
+
await showToast(`Antigravity quota exhausted on all accounts. Using Gemini CLI quota.`, 'warning');
|
|
918
|
+
headerStyle = fallbackStyle;
|
|
919
|
+
pushDebug(`all-accounts antigravity exhausted, quota fallback: ${headerStyle}`);
|
|
920
|
+
}
|
|
921
|
+
else {
|
|
922
|
+
shouldSwitchAccount = true;
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
else if (allowQuotaFallback && family === 'gemini') {
|
|
927
|
+
const alternateStyle = accountManager.getAvailableHeaderStyle(account, family, model);
|
|
928
|
+
const fallbackStyle = resolveQuotaFallbackHeaderStyle({
|
|
929
|
+
family,
|
|
930
|
+
headerStyle,
|
|
931
|
+
alternateStyle,
|
|
932
|
+
});
|
|
933
|
+
if (fallbackStyle) {
|
|
934
|
+
const quotaName = headerStyle === 'gemini-cli' ? 'Gemini CLI' : 'Antigravity';
|
|
935
|
+
const altQuotaName = fallbackStyle === 'gemini-cli' ? 'Gemini CLI' : 'Antigravity';
|
|
936
|
+
await showToast(`${quotaName} quota exhausted, using ${altQuotaName} quota`, 'warning');
|
|
937
|
+
headerStyle = fallbackStyle;
|
|
938
|
+
pushDebug(`quota fallback: ${headerStyle}`);
|
|
939
|
+
}
|
|
940
|
+
else {
|
|
941
|
+
shouldSwitchAccount = true;
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
else {
|
|
945
|
+
shouldSwitchAccount = true;
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
let totalCapacityRetries = 0;
|
|
949
|
+
while (!shouldSwitchAccount) {
|
|
950
|
+
await assertAdmission();
|
|
951
|
+
let forceThinkingRecovery = false;
|
|
952
|
+
let capacityRetryCount = 0;
|
|
953
|
+
let lastEndpointIndex = -1;
|
|
954
|
+
// At most one vault 401 retry per selection, on a rotated admission.
|
|
955
|
+
let rotatedAdmission;
|
|
956
|
+
let vault401Retried = false;
|
|
957
|
+
for (let i = 0; i < ANTIGRAVITY_ENDPOINT_FALLBACKS.length; i++) {
|
|
958
|
+
if (i !== lastEndpointIndex) {
|
|
959
|
+
capacityRetryCount = 0;
|
|
960
|
+
lastEndpointIndex = i;
|
|
961
|
+
}
|
|
962
|
+
const currentEndpoint = ANTIGRAVITY_ENDPOINT_FALLBACKS[i];
|
|
963
|
+
if (headerStyle === 'gemini-cli' &&
|
|
964
|
+
currentEndpoint !== 'https://cloudcode-pa.googleapis.com') {
|
|
965
|
+
pushDebug(`Skipping sandbox endpoint ${currentEndpoint} for gemini-cli headerStyle`);
|
|
966
|
+
continue;
|
|
967
|
+
}
|
|
968
|
+
let tokenConsumed = false;
|
|
969
|
+
let physicalAttemptStarted = false;
|
|
970
|
+
try {
|
|
971
|
+
// One credential grant per physical send, chosen by domain. Vault:
|
|
972
|
+
// a fresh admission for this send only; its token and project come
|
|
973
|
+
// from that one receipt, and a 401 is reported against its record
|
|
974
|
+
// version. Local: the grant resolved above for this selection.
|
|
975
|
+
let sendAdmission;
|
|
976
|
+
let sendAccessToken;
|
|
977
|
+
let sendProjectId;
|
|
978
|
+
if (credentials.domain === 'vault') {
|
|
979
|
+
// A rotated admission taken after a 401 serves exactly the
|
|
980
|
+
// retry it was taken for, then is gone.
|
|
981
|
+
sendAdmission =
|
|
982
|
+
rotatedAdmission ??
|
|
983
|
+
(await credentials.admit({
|
|
984
|
+
account,
|
|
985
|
+
signal: abortSignal,
|
|
986
|
+
}));
|
|
987
|
+
rotatedAdmission = undefined;
|
|
988
|
+
sendAccessToken = sendAdmission.accessToken;
|
|
989
|
+
sendProjectId = sendAdmission.projectId;
|
|
990
|
+
}
|
|
991
|
+
else if (localGrant) {
|
|
992
|
+
sendAccessToken = localGrant.accessToken;
|
|
993
|
+
sendProjectId = localGrant.projectId;
|
|
994
|
+
}
|
|
995
|
+
else {
|
|
996
|
+
throw new Error('Local credentials were not resolved for the selected account');
|
|
997
|
+
}
|
|
998
|
+
selectedCredentials.add(sendAccessToken);
|
|
999
|
+
const prepared = prepareAgyWireRequest(wire, {
|
|
1000
|
+
input,
|
|
1001
|
+
init,
|
|
1002
|
+
accessToken: sendAccessToken,
|
|
1003
|
+
projectId: sendProjectId,
|
|
1004
|
+
endpoint: currentEndpoint,
|
|
1005
|
+
headerStyle,
|
|
1006
|
+
forceThinkingRecovery,
|
|
1007
|
+
options: {
|
|
1008
|
+
claudeToolHardening: config.claude_tool_hardening,
|
|
1009
|
+
claudePromptAutoCaching: config.claude_prompt_auto_caching,
|
|
1010
|
+
fingerprint: account.fingerprint,
|
|
1011
|
+
agySession: agyRequestSession,
|
|
1012
|
+
agyRequestTimestamp: agyRequestScope.timestamp,
|
|
1013
|
+
},
|
|
1014
|
+
});
|
|
1015
|
+
const originalUrl = toUrlString(input);
|
|
1016
|
+
const resolvedUrl = toUrlString(prepared.request);
|
|
1017
|
+
pushDebug(`endpoint=${currentEndpoint}`);
|
|
1018
|
+
pushDebug(`resolved=${resolvedUrl}`);
|
|
1019
|
+
const debugContext = debug.startAntigravityDebugRequest({
|
|
1020
|
+
originalUrl,
|
|
1021
|
+
resolvedUrl,
|
|
1022
|
+
method: prepared.init.method,
|
|
1023
|
+
headers: prepared.init.headers,
|
|
1024
|
+
body: prepared.init.body,
|
|
1025
|
+
streaming: prepared.streaming,
|
|
1026
|
+
projectId: sendProjectId,
|
|
1027
|
+
});
|
|
1028
|
+
const dumpContext = dump.dumpRequest({
|
|
1029
|
+
originalUrl,
|
|
1030
|
+
resolvedUrl,
|
|
1031
|
+
method: prepared.init.method,
|
|
1032
|
+
headers: prepared.init.headers,
|
|
1033
|
+
body: prepared.init.body,
|
|
1034
|
+
streaming: prepared.streaming,
|
|
1035
|
+
requestedModel: prepared.requestedModel,
|
|
1036
|
+
effectiveModel: prepared.effectiveModel,
|
|
1037
|
+
sessionId: prepared.sessionId,
|
|
1038
|
+
projectId: sendProjectId,
|
|
1039
|
+
});
|
|
1040
|
+
const createFailureContext = (failureResponse) => ({
|
|
1041
|
+
response: failureResponse,
|
|
1042
|
+
streaming: prepared.streaming,
|
|
1043
|
+
debugContext,
|
|
1044
|
+
requestedModel: prepared.requestedModel,
|
|
1045
|
+
projectId: prepared.projectId,
|
|
1046
|
+
endpoint: prepared.endpoint,
|
|
1047
|
+
effectiveModel: prepared.effectiveModel,
|
|
1048
|
+
sessionId: prepared.sessionId,
|
|
1049
|
+
toolDebugMissing: prepared.toolDebugMissing,
|
|
1050
|
+
toolDebugSummary: prepared.toolDebugSummary,
|
|
1051
|
+
toolDebugPayload: prepared.toolDebugPayload,
|
|
1052
|
+
dumpContext,
|
|
1053
|
+
});
|
|
1054
|
+
await runThinkingWarmup(prepared, sendProjectId);
|
|
1055
|
+
await runCacheWarmupProbe(prepared);
|
|
1056
|
+
if (config.request_jitter_max_ms > 0) {
|
|
1057
|
+
const jitterMs = Math.floor(Math.random() * config.request_jitter_max_ms);
|
|
1058
|
+
if (jitterMs > 0) {
|
|
1059
|
+
await sleep(jitterMs, abortSignal);
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
await assertAdmission();
|
|
1063
|
+
if (config.account_selection_strategy === 'hybrid') {
|
|
1064
|
+
tokenConsumed = trackers.token.consume(account.index);
|
|
1065
|
+
}
|
|
1066
|
+
if (credentials.domain === 'local') {
|
|
1067
|
+
if (!localGrant) {
|
|
1068
|
+
throw new Error('Local credentials were not resolved for the selected account');
|
|
1069
|
+
}
|
|
1070
|
+
await localGrant.captured.check();
|
|
1071
|
+
await assertAdmission();
|
|
1072
|
+
}
|
|
1073
|
+
pushDebug(`dispatching request via ${prepared.headerStyle} transport`);
|
|
1074
|
+
physicalAttemptStarted = true;
|
|
1075
|
+
const response = prepared.headerStyle === 'antigravity'
|
|
1076
|
+
? await transport(toUrlString(prepared.request), prepared.init, { signal: abortSignal, onDebug: pushDebug })
|
|
1077
|
+
: await upstreamFetch(prepared.request, prepared.init);
|
|
1078
|
+
apiRequestCount++;
|
|
1079
|
+
accountManager.recordRequest(account.index, family);
|
|
1080
|
+
const requestCounts = accountManager.getDailyRequestCounts(account.index);
|
|
1081
|
+
if (requestCounts) {
|
|
1082
|
+
pushDebug(`[Quota] account=${account.index} ${family}_today=${requestCounts[family]} total_${family}_today=${accountManager.getTotalDailyRequests(family)}`);
|
|
1083
|
+
}
|
|
1084
|
+
pushDebug(`status=${response.status} ${response.statusText} (api_request #${apiRequestCount})`);
|
|
1085
|
+
noteGeminiDumpResponse(dumpContext, response);
|
|
1086
|
+
if (credentials.domain === 'vault' &&
|
|
1087
|
+
sendAdmission &&
|
|
1088
|
+
response.status === 401) {
|
|
1089
|
+
// Report the 401 against the exact record version this send's
|
|
1090
|
+
// admission carried, then take a fresh admission. Only a newer
|
|
1091
|
+
// version of the same credential and account may retry this
|
|
1092
|
+
// endpoint, once; otherwise the 401 stands.
|
|
1093
|
+
try {
|
|
1094
|
+
await sendAdmission.report401(response.status);
|
|
1095
|
+
}
|
|
1096
|
+
catch (error) {
|
|
1097
|
+
log.debug('send-admission-401-report-failed', {
|
|
1098
|
+
error: String(error),
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
if (!vault401Retried) {
|
|
1102
|
+
const next = await credentials.admit({
|
|
1103
|
+
account,
|
|
1104
|
+
signal: abortSignal,
|
|
1105
|
+
});
|
|
1106
|
+
if (next.credentialId === sendAdmission.credentialId &&
|
|
1107
|
+
next.accountIdentity === sendAdmission.accountIdentity &&
|
|
1108
|
+
next.recordVersion > sendAdmission.recordVersion) {
|
|
1109
|
+
vault401Retried = true;
|
|
1110
|
+
rotatedAdmission = next;
|
|
1111
|
+
void response.body?.cancel().catch(() => { });
|
|
1112
|
+
pushDebug(`vault-401: retrying with record version ${next.recordVersion}`);
|
|
1113
|
+
i -= 1;
|
|
1114
|
+
continue;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
// Record the final route selection so the sidebar renders the
|
|
1119
|
+
// actual account/header-style used by this request. Fire-and-
|
|
1120
|
+
// forget — the dispatch path must not wait on a state write.
|
|
1121
|
+
const sessionKey = requestSessionIdentity.sessionId;
|
|
1122
|
+
if (sessionKey) {
|
|
1123
|
+
const routingEntry = {
|
|
1124
|
+
accountId: `acct-${account.index}`,
|
|
1125
|
+
modelFamily: family,
|
|
1126
|
+
headerStyle: prepared.headerStyle,
|
|
1127
|
+
strategy: config.account_selection_strategy,
|
|
1128
|
+
updatedAt: Date.now(),
|
|
1129
|
+
};
|
|
1130
|
+
reportRouting(sessionKey, routingEntry);
|
|
1131
|
+
}
|
|
1132
|
+
if (response.status === 429 ||
|
|
1133
|
+
response.status === 503 ||
|
|
1134
|
+
response.status === 529) {
|
|
1135
|
+
if (tokenConsumed) {
|
|
1136
|
+
trackers.token.refund(account.index);
|
|
1137
|
+
tokenConsumed = false;
|
|
1138
|
+
}
|
|
1139
|
+
const defaultRetryMs = (config.default_retry_after_seconds ?? 60) * 1000;
|
|
1140
|
+
const _maxBackoffMs = (config.max_backoff_seconds ?? 60) * 1000;
|
|
1141
|
+
const headerRetryMs = retryAfterMsFromResponse(response, defaultRetryMs);
|
|
1142
|
+
const bodyInfo = await (async () => {
|
|
1143
|
+
try {
|
|
1144
|
+
const text = await response.clone().text();
|
|
1145
|
+
try {
|
|
1146
|
+
return JSON.parse(text);
|
|
1147
|
+
}
|
|
1148
|
+
catch {
|
|
1149
|
+
return null;
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
catch {
|
|
1153
|
+
return null;
|
|
1154
|
+
}
|
|
1155
|
+
})();
|
|
1156
|
+
const reasonInfo = bodyInfo
|
|
1157
|
+
? extractRateLimitBodyInfo(bodyInfo)
|
|
1158
|
+
: { retryDelayMs: null };
|
|
1159
|
+
const serverRetryMs = reasonInfo.retryDelayMs ?? headerRetryMs;
|
|
1160
|
+
const rateLimitReason = parseRateLimitReason(reasonInfo.reason, reasonInfo.message, response.status);
|
|
1161
|
+
if (rateLimitReason === 'MODEL_CAPACITY_EXHAUSTED' ||
|
|
1162
|
+
rateLimitReason === 'SERVER_ERROR') {
|
|
1163
|
+
totalCapacityRetries++;
|
|
1164
|
+
if (isCapacityRetryBudgetExhausted(totalCapacityRetries)) {
|
|
1165
|
+
pushDebug(`Total capacity retries (${MAX_TOTAL_CAPACITY_RETRIES}) exhausted, switching account`);
|
|
1166
|
+
lastFailure = createFailureContext(response);
|
|
1167
|
+
shouldSwitchAccount = true;
|
|
1168
|
+
break;
|
|
1169
|
+
}
|
|
1170
|
+
const baseDelayMs = 1000;
|
|
1171
|
+
const maxDelayMs = 8000;
|
|
1172
|
+
const exponentialDelay = Math.min(baseDelayMs * 2 ** capacityRetryCount, maxDelayMs);
|
|
1173
|
+
const jitter = exponentialDelay * (0.9 + Math.random() * 0.2);
|
|
1174
|
+
const waitMs = Math.round(jitter);
|
|
1175
|
+
const waitSec = Math.round(waitMs / 1000);
|
|
1176
|
+
pushDebug(`Server busy (${rateLimitReason}) on account ${account.index}, exponential backoff ${waitMs}ms (attempt ${capacityRetryCount + 1}, total ${totalCapacityRetries}/${MAX_TOTAL_CAPACITY_RETRIES})`);
|
|
1177
|
+
await showToast(`⏳ Server busy (${response.status}). Retrying in ${waitSec}s...`, 'warning');
|
|
1178
|
+
await sleep(waitMs, abortSignal);
|
|
1179
|
+
if (capacityRetryCount < 1) {
|
|
1180
|
+
capacityRetryCount++;
|
|
1181
|
+
i -= 1;
|
|
1182
|
+
continue;
|
|
1183
|
+
}
|
|
1184
|
+
else {
|
|
1185
|
+
pushDebug(`Max capacity retries (1) exhausted for endpoint ${currentEndpoint}, regenerating fingerprint...`);
|
|
1186
|
+
const newFingerprint = accountManager.regenerateAccountFingerprint(account.index);
|
|
1187
|
+
if (newFingerprint) {
|
|
1188
|
+
pushDebug(`Fingerprint regenerated for account ${account.index}`);
|
|
1189
|
+
}
|
|
1190
|
+
continue;
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
const quotaKey = retryState.headerStyleToQuotaKey(headerStyle, family);
|
|
1194
|
+
const backoff = retryState.getRateLimitBackoff(account.index, quotaKey, serverRetryMs);
|
|
1195
|
+
const smartBackoffMs = calculateBackoffMs(rateLimitReason, account.consecutiveFailures ?? 0, serverRetryMs);
|
|
1196
|
+
const effectiveDelayMs = Math.max(backoff.delayMs, smartBackoffMs);
|
|
1197
|
+
pushDebug(`429 idx=${account.index} email=${account.email ?? ''} family=${family} delayMs=${effectiveDelayMs} attempt=${backoff.attempt} reason=${rateLimitReason}`);
|
|
1198
|
+
if (reasonInfo.message)
|
|
1199
|
+
pushDebug(`429 message=${reasonInfo.message}`);
|
|
1200
|
+
if (reasonInfo.quotaResetTime)
|
|
1201
|
+
pushDebug(`429 quotaResetTime=${reasonInfo.quotaResetTime}`);
|
|
1202
|
+
if (reasonInfo.reason)
|
|
1203
|
+
pushDebug(`429 reason=${reasonInfo.reason}`);
|
|
1204
|
+
debug.logRateLimitEvent(account.index, account.email, family, response.status, effectiveDelayMs, reasonInfo);
|
|
1205
|
+
await debug.logResponseBody(debugContext, response, 429);
|
|
1206
|
+
trackers.health.recordRateLimit(account.index);
|
|
1207
|
+
const _accountLabel = account.email || `Account ${account.index + 1}`;
|
|
1208
|
+
if (backoff.attempt === 1 &&
|
|
1209
|
+
rateLimitReason !== 'QUOTA_EXHAUSTED') {
|
|
1210
|
+
await showToast(`Rate limited. Quick retry in 1s...`, 'warning');
|
|
1211
|
+
await sleep(FIRST_RETRY_DELAY_MS, abortSignal);
|
|
1212
|
+
if (config.scheduling_mode === 'cache_first') {
|
|
1213
|
+
const maxCacheFirstWaitMs = config.max_cache_first_wait_seconds * 1000;
|
|
1214
|
+
if (effectiveDelayMs <= maxCacheFirstWaitMs) {
|
|
1215
|
+
pushDebug(`cache_first: waiting ${effectiveDelayMs}ms for same account to recover`);
|
|
1216
|
+
await showToast(`⏳ Waiting ${Math.ceil(effectiveDelayMs / 1000)}s for same account (prompt cache preserved)...`, 'info');
|
|
1217
|
+
accountManager.markRateLimitedWithReason(account, family, headerStyle, model, rateLimitReason, serverRetryMs);
|
|
1218
|
+
await sleep(effectiveDelayMs, abortSignal);
|
|
1219
|
+
i -= 1;
|
|
1220
|
+
continue;
|
|
1221
|
+
}
|
|
1222
|
+
pushDebug(`cache_first: wait ${effectiveDelayMs}ms exceeds max ${maxCacheFirstWaitMs}ms, switching account`);
|
|
1223
|
+
}
|
|
1224
|
+
if (config.switch_on_first_rate_limit && accountCount > 1) {
|
|
1225
|
+
accountManager.markRateLimitedWithReason(account, family, headerStyle, model, rateLimitReason, serverRetryMs, config.failure_ttl_seconds * 1000);
|
|
1226
|
+
shouldSwitchAccount = true;
|
|
1227
|
+
break;
|
|
1228
|
+
}
|
|
1229
|
+
i -= 1;
|
|
1230
|
+
continue;
|
|
1231
|
+
}
|
|
1232
|
+
accountManager.markRateLimitedWithReason(account, family, headerStyle, model, rateLimitReason, serverRetryMs, config.failure_ttl_seconds * 1000);
|
|
1233
|
+
accountManager.requestSaveToDisk();
|
|
1234
|
+
const switchAccountDelayMs = config.switch_account_delay_ms ?? 500;
|
|
1235
|
+
if (family === 'gemini') {
|
|
1236
|
+
if (headerStyle === 'antigravity') {
|
|
1237
|
+
if (hasOtherAccountWithAntigravity(account)) {
|
|
1238
|
+
pushDebug(`antigravity exhausted on account ${account.index}, but available on others. Switching account.`);
|
|
1239
|
+
await showToast(`Rate limited again. Switching account in ${formatWaitTime(switchAccountDelayMs)}...`, 'warning');
|
|
1240
|
+
await sleep(switchAccountDelayMs, abortSignal);
|
|
1241
|
+
shouldSwitchAccount = true;
|
|
1242
|
+
break;
|
|
1243
|
+
}
|
|
1244
|
+
if (allowQuotaFallback) {
|
|
1245
|
+
const alternateStyle = accountManager.getAvailableHeaderStyle(account, family, model);
|
|
1246
|
+
const fallbackStyle = resolveQuotaFallbackHeaderStyle({
|
|
1247
|
+
family,
|
|
1248
|
+
headerStyle,
|
|
1249
|
+
alternateStyle,
|
|
1250
|
+
});
|
|
1251
|
+
if (fallbackStyle) {
|
|
1252
|
+
const safeModelName = model || 'this model';
|
|
1253
|
+
await showToast(`Antigravity quota exhausted for ${safeModelName}. Switching to Gemini CLI quota...`, 'warning');
|
|
1254
|
+
headerStyle = fallbackStyle;
|
|
1255
|
+
pushDebug(`quota fallback: ${headerStyle}`);
|
|
1256
|
+
continue;
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
else if (headerStyle === 'gemini-cli') {
|
|
1261
|
+
if (allowQuotaFallback) {
|
|
1262
|
+
const alternateStyle = accountManager.getAvailableHeaderStyle(account, family, model);
|
|
1263
|
+
const fallbackStyle = resolveQuotaFallbackHeaderStyle({
|
|
1264
|
+
family,
|
|
1265
|
+
headerStyle,
|
|
1266
|
+
alternateStyle,
|
|
1267
|
+
});
|
|
1268
|
+
if (fallbackStyle) {
|
|
1269
|
+
const safeModelName = model || 'this model';
|
|
1270
|
+
await showToast(`Gemini CLI quota exhausted for ${safeModelName}. Switching to Antigravity quota...`, 'warning');
|
|
1271
|
+
headerStyle = fallbackStyle;
|
|
1272
|
+
pushDebug(`quota fallback: ${headerStyle}`);
|
|
1273
|
+
continue;
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
if (accountCount > 1) {
|
|
1279
|
+
const quotaMsg = reasonInfo.quotaResetTime
|
|
1280
|
+
? ` (quota resets ${reasonInfo.quotaResetTime})`
|
|
1281
|
+
: ``;
|
|
1282
|
+
await showToast(`Rate limited again. Switching account in ${formatWaitTime(switchAccountDelayMs)}...${quotaMsg}`, 'warning');
|
|
1283
|
+
await sleep(switchAccountDelayMs, abortSignal);
|
|
1284
|
+
}
|
|
1285
|
+
else {
|
|
1286
|
+
const expBackoffMs = Math.min(FIRST_RETRY_DELAY_MS * 2 ** (backoff.attempt - 1), 60000);
|
|
1287
|
+
const expBackoffFormatted = expBackoffMs >= 1000
|
|
1288
|
+
? `${Math.round(expBackoffMs / 1000)}s`
|
|
1289
|
+
: `${expBackoffMs}ms`;
|
|
1290
|
+
await showToast(`Rate limited. Retrying in ${expBackoffFormatted} (attempt ${backoff.attempt})...`, 'warning');
|
|
1291
|
+
await sleep(expBackoffMs, abortSignal);
|
|
1292
|
+
}
|
|
1293
|
+
lastFailure = createFailureContext(response);
|
|
1294
|
+
shouldSwitchAccount = true;
|
|
1295
|
+
break;
|
|
1296
|
+
}
|
|
1297
|
+
const quotaKey = retryState.headerStyleToQuotaKey(headerStyle, family);
|
|
1298
|
+
retryState.resetRateLimitState(account.index, quotaKey);
|
|
1299
|
+
retryState.resetAccountFailureState(account.index);
|
|
1300
|
+
if (response.status === 403) {
|
|
1301
|
+
const errorBodyText = await response
|
|
1302
|
+
.clone()
|
|
1303
|
+
.text()
|
|
1304
|
+
.catch(() => '');
|
|
1305
|
+
const extracted = classifyAccessError(errorBodyText);
|
|
1306
|
+
if (extracted.accountIneligible) {
|
|
1307
|
+
const ineligibleReason = extracted.message ??
|
|
1308
|
+
'Google marked this account as ineligible for Antigravity.';
|
|
1309
|
+
accountManager.markAccountIneligible(account.index, ineligibleReason);
|
|
1310
|
+
const label = account.email || `Account ${account.index + 1}`;
|
|
1311
|
+
if (accountManager.shouldShowAccountToast(account.index, 60000)) {
|
|
1312
|
+
await showToast(`${label} is not eligible for Antigravity and has been disabled. ` +
|
|
1313
|
+
'Recheck it from opencode auth login > Verify accounts.', 'warning');
|
|
1314
|
+
accountManager.markToastShown(account.index);
|
|
1315
|
+
}
|
|
1316
|
+
pushDebug(`account-ineligible: disabled account ${account.index}`);
|
|
1317
|
+
trackers.health.recordFailure(account.index);
|
|
1318
|
+
lastFailure = createFailureContext(response);
|
|
1319
|
+
shouldSwitchAccount = true;
|
|
1320
|
+
break;
|
|
1321
|
+
}
|
|
1322
|
+
if (extracted.validationRequired) {
|
|
1323
|
+
const verificationReason = extracted.message ?? 'Google requires account verification.';
|
|
1324
|
+
const cooldownMs = 10 * 60 * 1000;
|
|
1325
|
+
accountManager.markAccountVerificationRequired(account.index, verificationReason, extracted.verifyUrl);
|
|
1326
|
+
accountManager.markAccountCoolingDown(account, cooldownMs, 'validation-required');
|
|
1327
|
+
accountManager.markRateLimited(account, cooldownMs, family, headerStyle, model);
|
|
1328
|
+
const label = account.email || `Account ${account.index + 1}`;
|
|
1329
|
+
if (accountManager.shouldShowAccountToast(account.index, 60000)) {
|
|
1330
|
+
await showToast(`⚠ ${label} needs verification. Run 'opencode auth login' and use Verify accounts.`, 'warning');
|
|
1331
|
+
accountManager.markToastShown(account.index);
|
|
1332
|
+
}
|
|
1333
|
+
pushDebug(`verification-required: disabled account ${account.index}`);
|
|
1334
|
+
trackers.health.recordFailure(account.index);
|
|
1335
|
+
lastFailure = createFailureContext(response);
|
|
1336
|
+
shouldSwitchAccount = true;
|
|
1337
|
+
break;
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
const shouldRetryEndpoint = response.status === 403 ||
|
|
1341
|
+
response.status === 404 ||
|
|
1342
|
+
response.status >= 500;
|
|
1343
|
+
if (shouldRetryEndpoint &&
|
|
1344
|
+
i < ANTIGRAVITY_ENDPOINT_FALLBACKS.length - 1) {
|
|
1345
|
+
await debug.logResponseBody(debugContext, response, response.status);
|
|
1346
|
+
lastFailure = createFailureContext(response);
|
|
1347
|
+
continue;
|
|
1348
|
+
}
|
|
1349
|
+
if (response.ok) {
|
|
1350
|
+
account.consecutiveFailures = 0;
|
|
1351
|
+
trackers.health.recordSuccess(account.index);
|
|
1352
|
+
accountManager.markAccountUsed(account.index);
|
|
1353
|
+
if (credentials.domain === 'local' &&
|
|
1354
|
+
credentials.refreshQuotaAfterSuccess) {
|
|
1355
|
+
void credentials
|
|
1356
|
+
.refreshQuotaAfterSuccess(account, config.quota_refresh_interval_minutes)
|
|
1357
|
+
.catch(() => { });
|
|
1358
|
+
}
|
|
1359
|
+
const proactiveThreshold = config.proactive_rotation_threshold_percent ?? 20;
|
|
1360
|
+
if (proactiveThreshold > 0 &&
|
|
1361
|
+
accountManager.shouldProactivelyRotate(family, model, proactiveThreshold, softQuotaCacheTtlMs, accountSessionIdentity)) {
|
|
1362
|
+
const rotated = accountManager.proactivelyRotateForFamily(family, model, headerStyle, config.soft_quota_threshold_percent, softQuotaCacheTtlMs, accountSessionIdentity);
|
|
1363
|
+
if (rotated) {
|
|
1364
|
+
const remaining = account.cachedQuota?.[resolveQuotaGroup(family, model)]
|
|
1365
|
+
?.remainingFraction;
|
|
1366
|
+
const remainingPct = remaining != null ? `${(remaining * 100).toFixed(1)}%` : '?';
|
|
1367
|
+
pushDebug(`[ProactiveRotation] account ${account.index} quota ${remainingPct} < ${proactiveThreshold}%, pre-switched to account ${rotated.index} for next request`);
|
|
1368
|
+
pushDebug(`[ProactiveRotation] ${account.index} → ${rotated.index}` +
|
|
1369
|
+
` (warm=${accountManager.wasUsedInSession(rotated.index, accountSessionIdentity)})`);
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
debug.logAntigravityDebugResponse(debugContext, response, {
|
|
1374
|
+
note: response.ok ? 'Success' : `Error ${response.status}`,
|
|
1375
|
+
});
|
|
1376
|
+
if (response.ok && !prepared.streaming) {
|
|
1377
|
+
await debug.logResponseBody(debugContext, response, response.status);
|
|
1378
|
+
}
|
|
1379
|
+
if (!response.ok) {
|
|
1380
|
+
await debug.logResponseBody(debugContext, response, response.status);
|
|
1381
|
+
if (response.status === 400) {
|
|
1382
|
+
const cloned = response.clone();
|
|
1383
|
+
const bodyText = await cloned.text();
|
|
1384
|
+
if (bodyText.includes('Prompt is too long') ||
|
|
1385
|
+
bodyText.includes('prompt_too_long')) {
|
|
1386
|
+
await showToast('Context too long - use /compact to reduce size', 'warning');
|
|
1387
|
+
// Classification reads only a clone. Retain the original
|
|
1388
|
+
// response unless its buffered diagnostics need secret redaction.
|
|
1389
|
+
bufferedOverflow.set(response, bodyText);
|
|
1390
|
+
return response;
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
if (response.ok && !prepared.streaming) {
|
|
1395
|
+
const maxAttempts = config.empty_response_max_attempts ?? 4;
|
|
1396
|
+
const retryDelayMs = config.empty_response_retry_delay_ms ?? 2000;
|
|
1397
|
+
const clonedForCheck = response.clone();
|
|
1398
|
+
const bodyText = await clonedForCheck.text();
|
|
1399
|
+
if (isEmptyResponseBody(bodyText)) {
|
|
1400
|
+
const emptyAttemptKey = `${prepared.sessionId ?? 'none'}:${prepared.effectiveModel ?? 'unknown'}`;
|
|
1401
|
+
const currentAttempts = retryState.recordEmptyResponseAttempt(emptyAttemptKey);
|
|
1402
|
+
pushDebug(`empty-response: attempt ${currentAttempts}/${maxAttempts}`);
|
|
1403
|
+
if (currentAttempts < maxAttempts) {
|
|
1404
|
+
await showToast(`Empty response received. Retrying (${currentAttempts}/${maxAttempts})...`, 'warning');
|
|
1405
|
+
await sleep(retryDelayMs, abortSignal);
|
|
1406
|
+
continue;
|
|
1407
|
+
}
|
|
1408
|
+
retryState.clearEmptyResponseAttempts();
|
|
1409
|
+
return createNativeGoogleErrorResponse({
|
|
1410
|
+
status: 502,
|
|
1411
|
+
reason: 'empty_response',
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1414
|
+
const _emptyAttemptKeyClean = `${prepared.sessionId ?? 'none'}:${prepared.effectiveModel ?? 'unknown'}`;
|
|
1415
|
+
retryState.clearEmptyResponseAttempts();
|
|
1416
|
+
}
|
|
1417
|
+
const transformedResponse = await wire.transformResponse(response, prepared.streaming, debugContext, prepared.requestedModel, prepared.projectId, prepared.endpoint, prepared.effectiveModel, prepared.sessionId, prepared.toolDebugMissing, prepared.toolDebugSummary, prepared.toolDebugPayload, debugLines, dumpContext);
|
|
1418
|
+
const contextError = transformedResponse.headers.get('x-antigravity-context-error');
|
|
1419
|
+
if (contextError) {
|
|
1420
|
+
if (contextError === 'prompt_too_long') {
|
|
1421
|
+
await showToast('Context too long - use /compact to reduce size, or trim your request', 'warning');
|
|
1422
|
+
}
|
|
1423
|
+
else if (contextError === 'tool_pairing') {
|
|
1424
|
+
await showToast('Tool call/result mismatch - use /compact to fix, or /undo last message', 'warning');
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
if (apiRequestCount > 1) {
|
|
1428
|
+
pushDebug(`[Quota] Total API requests for this user message: ${apiRequestCount} (${apiRequestCount - 1} retries)`);
|
|
1429
|
+
}
|
|
1430
|
+
const dailyCounts = accountManager.getDailyRequestCounts(account.index);
|
|
1431
|
+
if (dailyCounts) {
|
|
1432
|
+
pushDebug(`[Quota] Account ${account.index} (${account.email ?? 'unknown'}) today: claude=${dailyCounts.claude} gemini=${dailyCounts.gemini}`);
|
|
1433
|
+
}
|
|
1434
|
+
const totalToday = accountManager.getTotalDailyRequests(family);
|
|
1435
|
+
pushDebug(`[Quota] Total ${family} requests today (all accounts): ${totalToday}`);
|
|
1436
|
+
const cachedQuota = account.cachedQuota;
|
|
1437
|
+
if (cachedQuota) {
|
|
1438
|
+
const quotaFamily = resolveQuotaGroup(family, model);
|
|
1439
|
+
const groupQuota = cachedQuota[quotaFamily];
|
|
1440
|
+
if (groupQuota?.remainingFraction != null) {
|
|
1441
|
+
const pct = Math.round(groupQuota.remainingFraction * 100);
|
|
1442
|
+
pushDebug(`[Quota] Account ${account.index} cached ${quotaFamily} remaining: ${pct}%${groupQuota.resetTime ? ` (resets ${groupQuota.resetTime})` : ''}`);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
const sessionSummary = accountManager.getSessionSummary();
|
|
1446
|
+
if (sessionSummary.durationMinutes >= 1) {
|
|
1447
|
+
const familyTotal = family === 'claude'
|
|
1448
|
+
? sessionSummary.totalClaude
|
|
1449
|
+
: sessionSummary.totalGemini;
|
|
1450
|
+
if (familyTotal > 0) {
|
|
1451
|
+
const ratePerHour = sessionSummary.requestsPerHour;
|
|
1452
|
+
pushDebug(`[Quota] Session: ${sessionSummary.durationMinutes}min, ${familyTotal} ${family} reqs, ~${ratePerHour} reqs/hr, ${sessionSummary.accountsUsed} accounts used`);
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
return transformedResponse;
|
|
1456
|
+
}
|
|
1457
|
+
catch (error) {
|
|
1458
|
+
if (tokenConsumed &&
|
|
1459
|
+
(!isLocalGrantError(error) || !physicalAttemptStarted)) {
|
|
1460
|
+
trackers.token.refund(account.index);
|
|
1461
|
+
tokenConsumed = false;
|
|
1462
|
+
}
|
|
1463
|
+
if (credentials.domain === 'local' &&
|
|
1464
|
+
localGrant?.captured.source === 'store' &&
|
|
1465
|
+
isLocalGrantError(error)) {
|
|
1466
|
+
// The one-recapture limit covers main requests, warmups and probes. A
|
|
1467
|
+
// superseded unsent preparation is rebuilt on the same selection
|
|
1468
|
+
// and request scope, without failure penalties or endpoint retry.
|
|
1469
|
+
if (error instanceof LocalGrantSupersededError &&
|
|
1470
|
+
!localRecaptureUsed) {
|
|
1471
|
+
localRecaptureUsed = true;
|
|
1472
|
+
try {
|
|
1473
|
+
await localGrant.captured.resolveCurrent();
|
|
1474
|
+
const auth = credentials.toAuthDetails(account);
|
|
1475
|
+
if (!auth.access || accessTokenExpired(auth))
|
|
1476
|
+
return createNativeGoogleErrorResponse({
|
|
1477
|
+
status: 412,
|
|
1478
|
+
reason: 'pool_unavailable',
|
|
1479
|
+
});
|
|
1480
|
+
const captured = credentials.captureGrant({
|
|
1481
|
+
account,
|
|
1482
|
+
accessToken: auth.access,
|
|
1483
|
+
});
|
|
1484
|
+
localGrant = await prepareLocalGrant(auth, captured, false);
|
|
1485
|
+
i = -1;
|
|
1486
|
+
continue;
|
|
1487
|
+
}
|
|
1488
|
+
catch {
|
|
1489
|
+
checkAborted();
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
return createNativeGoogleErrorResponse({
|
|
1493
|
+
status: 412,
|
|
1494
|
+
reason: 'pool_unavailable',
|
|
1495
|
+
});
|
|
1496
|
+
}
|
|
1497
|
+
if (error instanceof Error &&
|
|
1498
|
+
error.message === 'THINKING_RECOVERY_NEEDED') {
|
|
1499
|
+
if (!forceThinkingRecovery) {
|
|
1500
|
+
pushDebug('thinking-recovery: API error detected, retrying with forced recovery');
|
|
1501
|
+
forceThinkingRecovery = true;
|
|
1502
|
+
i = -1;
|
|
1503
|
+
continue;
|
|
1504
|
+
}
|
|
1505
|
+
const recoveryError = error;
|
|
1506
|
+
const originalError = recoveryError.originalError || {
|
|
1507
|
+
error: { message: 'Thinking recovery triggered' },
|
|
1508
|
+
};
|
|
1509
|
+
const recoveryMessage = `${originalError.error?.message || 'Session recovery failed'}\n\n[RECOVERY] Thinking block corruption could not be resolved. Try starting a new session.`;
|
|
1510
|
+
return new Response(JSON.stringify({
|
|
1511
|
+
type: 'error',
|
|
1512
|
+
error: {
|
|
1513
|
+
type: 'unrecoverable_error',
|
|
1514
|
+
message: recoveryMessage,
|
|
1515
|
+
},
|
|
1516
|
+
}), {
|
|
1517
|
+
status: 400,
|
|
1518
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1519
|
+
});
|
|
1520
|
+
}
|
|
1521
|
+
if (i < ANTIGRAVITY_ENDPOINT_FALLBACKS.length - 1) {
|
|
1522
|
+
lastError =
|
|
1523
|
+
error instanceof Error ? error : new Error(String(error));
|
|
1524
|
+
continue;
|
|
1525
|
+
}
|
|
1526
|
+
const { failures, shouldCooldown, cooldownMs } = retryState.trackAccountFailure(account.index);
|
|
1527
|
+
lastError =
|
|
1528
|
+
error instanceof Error ? error : new Error(String(error));
|
|
1529
|
+
if (shouldCooldown) {
|
|
1530
|
+
accountManager.markAccountCoolingDown(account, cooldownMs, 'network-error');
|
|
1531
|
+
accountManager.markRateLimited(account, cooldownMs, family, headerStyle, model);
|
|
1532
|
+
pushDebug(`endpoint-error: cooldown ${cooldownMs}ms after ${failures} failures`);
|
|
1533
|
+
}
|
|
1534
|
+
shouldSwitchAccount = true;
|
|
1535
|
+
break;
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
if (shouldSwitchAccount) {
|
|
1540
|
+
accountSwitchCount++;
|
|
1541
|
+
if (accountSwitchCount > maxAccountSwitches) {
|
|
1542
|
+
pushDebug(`account-switch-cap: exceeded max_account_switches=${maxAccountSwitches}, giving up`);
|
|
1543
|
+
if (lastFailure) {
|
|
1544
|
+
return wire.transformResponse(lastFailure.response, lastFailure.streaming, lastFailure.debugContext, lastFailure.requestedModel, lastFailure.projectId, lastFailure.endpoint, lastFailure.effectiveModel, lastFailure.sessionId, lastFailure.toolDebugMissing, lastFailure.toolDebugSummary, lastFailure.toolDebugPayload, debugLines, lastFailure.dumpContext);
|
|
1545
|
+
}
|
|
1546
|
+
throw terminalFetchError(lastError, `Exceeded max account switches (${maxAccountSwitches}). All accounts rate-limited.`);
|
|
1547
|
+
}
|
|
1548
|
+
if (accountCount <= 1) {
|
|
1549
|
+
if (lastFailure) {
|
|
1550
|
+
return wire.transformResponse(lastFailure.response, lastFailure.streaming, lastFailure.debugContext, lastFailure.requestedModel, lastFailure.projectId, lastFailure.endpoint, lastFailure.effectiveModel, lastFailure.sessionId, lastFailure.toolDebugMissing, lastFailure.toolDebugSummary, lastFailure.toolDebugPayload, debugLines, lastFailure.dumpContext);
|
|
1551
|
+
}
|
|
1552
|
+
throw terminalFetchError(lastError, 'All Antigravity endpoints failed');
|
|
1553
|
+
}
|
|
1554
|
+
continue;
|
|
1555
|
+
}
|
|
1556
|
+
if (lastFailure) {
|
|
1557
|
+
return wire.transformResponse(lastFailure.response, lastFailure.streaming, lastFailure.debugContext, lastFailure.requestedModel, lastFailure.projectId, lastFailure.endpoint, lastFailure.effectiveModel, lastFailure.sessionId, lastFailure.toolDebugMissing, lastFailure.toolDebugSummary, lastFailure.toolDebugPayload, debugLines, lastFailure.dumpContext);
|
|
1558
|
+
}
|
|
1559
|
+
throw terminalFetchError(lastError, 'All Antigravity accounts failed');
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
// Waits for every admitted request and retained body, then releases the
|
|
1563
|
+
// bookkeeping they use. Runs once, whether `retire` or `dispose` asks first.
|
|
1564
|
+
function drain() {
|
|
1565
|
+
drainPromise ??= (async () => {
|
|
1566
|
+
// A refresh that already exchanged tokens must finish its owned store write.
|
|
1567
|
+
while (inFlight.size > 0)
|
|
1568
|
+
await Promise.allSettled([...inFlight]);
|
|
1569
|
+
retryState.dispose();
|
|
1570
|
+
warmupState.dispose();
|
|
1571
|
+
})();
|
|
1572
|
+
return drainPromise;
|
|
1573
|
+
}
|
|
1574
|
+
function retire() {
|
|
1575
|
+
retired = true;
|
|
1576
|
+
return drain();
|
|
1577
|
+
}
|
|
1578
|
+
function dispose() {
|
|
1579
|
+
disposePromise ??= (async () => {
|
|
1580
|
+
retired = true;
|
|
1581
|
+
shutdown.abort(new Error('The Antigravity request executor is disposed'));
|
|
1582
|
+
await drain();
|
|
1583
|
+
})();
|
|
1584
|
+
return disposePromise;
|
|
1585
|
+
}
|
|
1586
|
+
return {
|
|
1587
|
+
execute(input, init, requestOptions) {
|
|
1588
|
+
if (shutdown.signal.aborted)
|
|
1589
|
+
return Promise.reject(new Error('The Antigravity request executor is disposed'));
|
|
1590
|
+
if (retired)
|
|
1591
|
+
return Promise.reject(new Error('The Antigravity request executor is retired'));
|
|
1592
|
+
const requestedSignal = init?.signal ?? (input instanceof Request ? input.signal : undefined);
|
|
1593
|
+
const cancellation = createRequestCancellation(requestedSignal
|
|
1594
|
+
? [requestedSignal, shutdown.signal]
|
|
1595
|
+
: [shutdown.signal]);
|
|
1596
|
+
const selectedCredentials = new Set();
|
|
1597
|
+
const pending = execute(input, { ...init, signal: cancellation.signal }, requestOptions, selectedCredentials)
|
|
1598
|
+
.then(async (response) => {
|
|
1599
|
+
// Overflow classification read a clone to EOF. Reuse that text
|
|
1600
|
+
// for redaction; safe diagnostics retain the original unread response.
|
|
1601
|
+
if (bufferedOverflow.has(response)) {
|
|
1602
|
+
cancellation.release();
|
|
1603
|
+
return redactCredentialResponse(response, [...selectedCredentials], bufferedOverflow.get(response));
|
|
1604
|
+
}
|
|
1605
|
+
const retained = await retainResponseLifetime(response, cancellation);
|
|
1606
|
+
inFlight.add(retained.settled);
|
|
1607
|
+
void retained.settled.then(() => inFlight.delete(retained.settled));
|
|
1608
|
+
return redactCredentialResponse(preserveResponseMetadata(retained.response, response), [...selectedCredentials]);
|
|
1609
|
+
}, (error) => {
|
|
1610
|
+
cancellation.release();
|
|
1611
|
+
throw redactCredentialError(error, [...selectedCredentials]);
|
|
1612
|
+
})
|
|
1613
|
+
.catch((error) => {
|
|
1614
|
+
cancellation.release();
|
|
1615
|
+
throw redactCredentialError(error, [...selectedCredentials]);
|
|
1616
|
+
});
|
|
1617
|
+
inFlight.add(pending);
|
|
1618
|
+
void pending.then(() => inFlight.delete(pending), () => inFlight.delete(pending));
|
|
1619
|
+
return pending;
|
|
1620
|
+
},
|
|
1621
|
+
retire,
|
|
1622
|
+
dispose,
|
|
1623
|
+
};
|
|
1624
|
+
}
|
|
1625
|
+
function extractRateLimitBodyInfo(body) {
|
|
1626
|
+
if (!body || typeof body !== 'object')
|
|
1627
|
+
return { retryDelayMs: null };
|
|
1628
|
+
const error = body.error;
|
|
1629
|
+
const message = error && typeof error === 'object'
|
|
1630
|
+
? error.message
|
|
1631
|
+
: undefined;
|
|
1632
|
+
const details = error && typeof error === 'object'
|
|
1633
|
+
? error.details
|
|
1634
|
+
: undefined;
|
|
1635
|
+
let reason;
|
|
1636
|
+
if (Array.isArray(details)) {
|
|
1637
|
+
for (const detail of details) {
|
|
1638
|
+
if (!detail || typeof detail !== 'object')
|
|
1639
|
+
continue;
|
|
1640
|
+
const type = detail['@type'];
|
|
1641
|
+
if (typeof type === 'string' && type.includes('google.rpc.ErrorInfo')) {
|
|
1642
|
+
const detailReason = detail.reason;
|
|
1643
|
+
if (typeof detailReason === 'string') {
|
|
1644
|
+
reason = detailReason;
|
|
1645
|
+
break;
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
for (const detail of details) {
|
|
1650
|
+
if (!detail || typeof detail !== 'object')
|
|
1651
|
+
continue;
|
|
1652
|
+
const type = detail['@type'];
|
|
1653
|
+
if (typeof type === 'string' && type.includes('google.rpc.RetryInfo')) {
|
|
1654
|
+
const retryDelay = detail.retryDelay;
|
|
1655
|
+
if (typeof retryDelay === 'string') {
|
|
1656
|
+
const retryDelayMs = parseDurationToMs(retryDelay);
|
|
1657
|
+
if (retryDelayMs !== null) {
|
|
1658
|
+
return { retryDelayMs, message, reason };
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
for (const detail of details) {
|
|
1664
|
+
if (!detail || typeof detail !== 'object')
|
|
1665
|
+
continue;
|
|
1666
|
+
const metadata = detail
|
|
1667
|
+
.metadata;
|
|
1668
|
+
if (metadata && typeof metadata === 'object') {
|
|
1669
|
+
const quotaResetDelay = metadata.quotaResetDelay;
|
|
1670
|
+
const quotaResetTime = metadata.quotaResetTimeStamp;
|
|
1671
|
+
if (typeof quotaResetDelay === 'string') {
|
|
1672
|
+
const quotaResetDelayMs = parseDurationToMs(quotaResetDelay);
|
|
1673
|
+
if (quotaResetDelayMs !== null) {
|
|
1674
|
+
return {
|
|
1675
|
+
retryDelayMs: quotaResetDelayMs,
|
|
1676
|
+
message,
|
|
1677
|
+
quotaResetTime,
|
|
1678
|
+
reason,
|
|
1679
|
+
};
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
if (message) {
|
|
1686
|
+
const afterMatch = message.match(/reset after\s+([0-9hms.]+)/i);
|
|
1687
|
+
const rawDuration = afterMatch?.[1];
|
|
1688
|
+
if (rawDuration) {
|
|
1689
|
+
const parsed = parseDurationToMs(rawDuration);
|
|
1690
|
+
if (parsed !== null) {
|
|
1691
|
+
return { retryDelayMs: parsed, message, reason };
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
return { retryDelayMs: null, message, reason };
|
|
1696
|
+
}
|
|
1697
|
+
function parseDurationToMs(duration) {
|
|
1698
|
+
const simpleMatch = duration.match(/^(\d+(?:\.\d+)?)(ms|s|m|h)?$/i);
|
|
1699
|
+
if (simpleMatch) {
|
|
1700
|
+
const value = parseFloat(simpleMatch[1]);
|
|
1701
|
+
const unit = (simpleMatch[2] || 's').toLowerCase();
|
|
1702
|
+
switch (unit) {
|
|
1703
|
+
case 'h':
|
|
1704
|
+
return value * 3600 * 1000;
|
|
1705
|
+
case 'm':
|
|
1706
|
+
return value * 60 * 1000;
|
|
1707
|
+
case 's':
|
|
1708
|
+
return value * 1000;
|
|
1709
|
+
case 'ms':
|
|
1710
|
+
return value;
|
|
1711
|
+
default:
|
|
1712
|
+
return value * 1000;
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
const compoundRegex = /(\d+(?:\.\d+)?)(h|m(?!s)|s|ms)/gi;
|
|
1716
|
+
let totalMs = 0;
|
|
1717
|
+
let matchFound = false;
|
|
1718
|
+
let match = null;
|
|
1719
|
+
while (true) {
|
|
1720
|
+
match = compoundRegex.exec(duration);
|
|
1721
|
+
if (match === null)
|
|
1722
|
+
break;
|
|
1723
|
+
matchFound = true;
|
|
1724
|
+
const value = parseFloat(match[1]);
|
|
1725
|
+
const unit = match[2]?.toLowerCase();
|
|
1726
|
+
switch (unit) {
|
|
1727
|
+
case 'h':
|
|
1728
|
+
totalMs += value * 3600 * 1000;
|
|
1729
|
+
break;
|
|
1730
|
+
case 'm':
|
|
1731
|
+
totalMs += value * 60 * 1000;
|
|
1732
|
+
break;
|
|
1733
|
+
case 's':
|
|
1734
|
+
totalMs += value * 1000;
|
|
1735
|
+
break;
|
|
1736
|
+
case 'ms':
|
|
1737
|
+
totalMs += value;
|
|
1738
|
+
break;
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
return matchFound ? totalMs : null;
|
|
1742
|
+
}
|
|
1743
|
+
//# sourceMappingURL=request-services.js.map
|