@cortexkit/opencode-antigravity-auth 1.1.0 → 2.0.1
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 +225 -569
- package/dist/cli.js +4017 -0
- package/dist/cli.js.map +7 -0
- package/dist/index.d.ts +1 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20742 -14586
- package/dist/index.js.map +4 -4
- package/dist/src/antigravity/oauth.d.ts +1 -1
- package/dist/src/antigravity/oauth.js +1 -1
- package/dist/src/cli.d.ts +21 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +237 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/constants.d.ts +1 -1
- package/dist/src/constants.js +1 -1
- package/dist/src/hooks/auto-update-checker/cache.d.ts.map +1 -1
- package/dist/src/hooks/auto-update-checker/cache.js +13 -13
- package/dist/src/hooks/auto-update-checker/cache.js.map +1 -1
- package/dist/src/hooks/auto-update-checker/checker.d.ts +1 -1
- package/dist/src/hooks/auto-update-checker/checker.d.ts.map +1 -1
- package/dist/src/hooks/auto-update-checker/checker.js +75 -51
- package/dist/src/hooks/auto-update-checker/checker.js.map +1 -1
- package/dist/src/hooks/auto-update-checker/constants.d.ts.map +1 -1
- package/dist/src/hooks/auto-update-checker/constants.js +12 -12
- package/dist/src/hooks/auto-update-checker/constants.js.map +1 -1
- package/dist/src/hooks/auto-update-checker/index.d.ts +6 -6
- package/dist/src/hooks/auto-update-checker/index.d.ts.map +1 -1
- package/dist/src/hooks/auto-update-checker/index.js +17 -17
- package/dist/src/hooks/auto-update-checker/index.js.map +1 -1
- package/dist/src/hooks/auto-update-checker/logging.js +2 -2
- package/dist/src/hooks/auto-update-checker/logging.js.map +1 -1
- package/dist/src/hooks/auto-update-checker/types.d.ts.map +1 -1
- package/dist/src/plugin/account-access.d.ts +99 -0
- package/dist/src/plugin/account-access.d.ts.map +1 -0
- package/dist/src/plugin/account-access.js +480 -0
- package/dist/src/plugin/account-access.js.map +1 -0
- package/dist/src/plugin/account-command-oauth.d.ts +34 -0
- package/dist/src/plugin/account-command-oauth.d.ts.map +1 -0
- package/dist/src/plugin/account-command-oauth.js +156 -0
- package/dist/src/plugin/account-command-oauth.js.map +1 -0
- package/dist/src/plugin/accounts.d.ts +7 -256
- package/dist/src/plugin/accounts.d.ts.map +1 -1
- package/dist/src/plugin/accounts.js +31 -1367
- package/dist/src/plugin/accounts.js.map +1 -1
- package/dist/src/plugin/agy-request-metadata.d.ts +1 -1
- package/dist/src/plugin/agy-request-metadata.js +1 -1
- package/dist/src/plugin/agy-transport.d.ts +1 -1
- package/dist/src/plugin/agy-transport.js +1 -1
- package/dist/src/plugin/auth-doctor.d.ts +6 -6
- package/dist/src/plugin/auth-doctor.d.ts.map +1 -1
- package/dist/src/plugin/auth-doctor.js +74 -66
- package/dist/src/plugin/auth-doctor.js.map +1 -1
- package/dist/src/plugin/auth-drift.d.ts +4 -4
- package/dist/src/plugin/auth-drift.d.ts.map +1 -1
- package/dist/src/plugin/auth-drift.js +15 -15
- package/dist/src/plugin/auth-drift.js.map +1 -1
- package/dist/src/plugin/auth-loader.d.ts +50 -0
- package/dist/src/plugin/auth-loader.d.ts.map +1 -0
- package/dist/src/plugin/auth-loader.js +225 -0
- package/dist/src/plugin/auth-loader.js.map +1 -0
- package/dist/src/plugin/auth.d.ts +1 -1
- package/dist/src/plugin/auth.js +1 -1
- package/dist/src/plugin/background-quota-refresh.d.ts +146 -0
- package/dist/src/plugin/background-quota-refresh.d.ts.map +1 -0
- package/dist/src/plugin/background-quota-refresh.js +347 -0
- package/dist/src/plugin/background-quota-refresh.js.map +1 -0
- 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 +1 -1
- package/dist/src/plugin/cache/signature-cache.d.ts.map +1 -1
- package/dist/src/plugin/cache/signature-cache.js +23 -24
- package/dist/src/plugin/cache/signature-cache.js.map +1 -1
- package/dist/src/plugin/cache.d.ts +6 -5
- package/dist/src/plugin/cache.d.ts.map +1 -1
- package/dist/src/plugin/cache.js +21 -7
- package/dist/src/plugin/cache.js.map +1 -1
- package/dist/src/plugin/catalog.d.ts +23 -0
- package/dist/src/plugin/catalog.d.ts.map +1 -0
- package/dist/src/plugin/catalog.js +60 -0
- package/dist/src/plugin/catalog.js.map +1 -0
- package/dist/src/plugin/cli.d.ts +7 -7
- package/dist/src/plugin/cli.d.ts.map +1 -1
- package/dist/src/plugin/cli.js +62 -55
- package/dist/src/plugin/cli.js.map +1 -1
- package/dist/src/plugin/command-data.d.ts +329 -0
- package/dist/src/plugin/command-data.d.ts.map +1 -0
- package/dist/src/plugin/command-data.js +517 -0
- package/dist/src/plugin/command-data.js.map +1 -0
- package/dist/src/plugin/commands.d.ts +154 -0
- package/dist/src/plugin/commands.d.ts.map +1 -0
- package/dist/src/plugin/commands.js +746 -0
- package/dist/src/plugin/commands.js.map +1 -0
- package/dist/src/plugin/config/index.d.ts +2 -2
- package/dist/src/plugin/config/index.d.ts.map +1 -1
- package/dist/src/plugin/config/index.js +2 -2
- package/dist/src/plugin/config/index.js.map +1 -1
- package/dist/src/plugin/config/loader.d.ts +1 -1
- package/dist/src/plugin/config/loader.d.ts.map +1 -1
- package/dist/src/plugin/config/loader.js +18 -16
- package/dist/src/plugin/config/loader.js.map +1 -1
- package/dist/src/plugin/config/models.d.ts +2 -2
- package/dist/src/plugin/config/models.d.ts.map +1 -1
- package/dist/src/plugin/config/models.js +1 -1
- package/dist/src/plugin/config/models.js.map +1 -1
- package/dist/src/plugin/config/operator-settings-schema.d.ts +29 -0
- package/dist/src/plugin/config/operator-settings-schema.d.ts.map +1 -0
- package/dist/src/plugin/config/operator-settings-schema.js +28 -0
- package/dist/src/plugin/config/operator-settings-schema.js.map +1 -0
- package/dist/src/plugin/config/schema.d.ts +23 -2
- package/dist/src/plugin/config/schema.d.ts.map +1 -1
- package/dist/src/plugin/config/schema.js +109 -25
- package/dist/src/plugin/config/schema.js.map +1 -1
- package/dist/src/plugin/config/updater.d.ts.map +1 -1
- package/dist/src/plugin/config/updater.js +15 -15
- package/dist/src/plugin/config/updater.js.map +1 -1
- package/dist/src/plugin/config/writer.d.ts +34 -0
- package/dist/src/plugin/config/writer.d.ts.map +1 -0
- package/dist/src/plugin/config/writer.js +81 -0
- package/dist/src/plugin/config/writer.js.map +1 -0
- package/dist/src/plugin/core/streaming/index.d.ts +1 -1
- package/dist/src/plugin/core/streaming/index.d.ts.map +1 -1
- package/dist/src/plugin/core/streaming/index.js +1 -1
- package/dist/src/plugin/core/streaming/index.js.map +1 -1
- package/dist/src/plugin/core/streaming/transformer.d.ts.map +1 -1
- package/dist/src/plugin/core/streaming/transformer.js +85 -44
- package/dist/src/plugin/core/streaming/transformer.js.map +1 -1
- package/dist/src/plugin/core/streaming/types.d.ts.map +1 -1
- package/dist/src/plugin/debug.d.ts +10 -3
- package/dist/src/plugin/debug.d.ts.map +1 -1
- package/dist/src/plugin/debug.js +110 -47
- package/dist/src/plugin/debug.js.map +1 -1
- package/dist/src/plugin/dependencies.d.ts +129 -0
- package/dist/src/plugin/dependencies.d.ts.map +1 -0
- package/dist/src/plugin/dependencies.js +107 -0
- package/dist/src/plugin/dependencies.js.map +1 -0
- package/dist/src/plugin/errors.d.ts +27 -0
- package/dist/src/plugin/errors.d.ts.map +1 -1
- package/dist/src/plugin/errors.js +29 -3
- package/dist/src/plugin/errors.js.map +1 -1
- package/dist/src/plugin/event-handler.d.ts +53 -0
- package/dist/src/plugin/event-handler.d.ts.map +1 -0
- package/dist/src/plugin/event-handler.js +101 -0
- package/dist/src/plugin/event-handler.js.map +1 -0
- package/dist/src/plugin/fetch/retry-state.d.ts +61 -0
- package/dist/src/plugin/fetch/retry-state.d.ts.map +1 -0
- package/dist/src/plugin/fetch/retry-state.js +248 -0
- package/dist/src/plugin/fetch/retry-state.js.map +1 -0
- package/dist/src/plugin/fetch/warmup.d.ts +30 -0
- package/dist/src/plugin/fetch/warmup.d.ts.map +1 -0
- package/dist/src/plugin/fetch/warmup.js +76 -0
- package/dist/src/plugin/fetch/warmup.js.map +1 -0
- package/dist/src/plugin/fetch-interceptor.d.ts +59 -0
- package/dist/src/plugin/fetch-interceptor.d.ts.map +1 -0
- package/dist/src/plugin/fetch-interceptor.js +1399 -0
- package/dist/src/plugin/fetch-interceptor.js.map +1 -0
- package/dist/src/plugin/fetch-routing.d.ts +26 -0
- package/dist/src/plugin/fetch-routing.d.ts.map +1 -0
- package/dist/src/plugin/fetch-routing.js +99 -0
- package/dist/src/plugin/fetch-routing.js.map +1 -0
- package/dist/src/plugin/fingerprint.d.ts +1 -1
- package/dist/src/plugin/fingerprint.js +1 -1
- package/dist/src/plugin/gemini-dump.d.ts +5 -5
- package/dist/src/plugin/gemini-dump.d.ts.map +1 -1
- package/dist/src/plugin/gemini-dump.js +109 -55
- package/dist/src/plugin/gemini-dump.js.map +1 -1
- package/dist/src/plugin/google-search-tool.d.ts +9 -0
- package/dist/src/plugin/google-search-tool.d.ts.map +1 -0
- package/dist/src/plugin/google-search-tool.js +56 -0
- package/dist/src/plugin/google-search-tool.js.map +1 -0
- package/dist/src/plugin/image-saver.d.ts.map +1 -1
- package/dist/src/plugin/image-saver.js +16 -16
- package/dist/src/plugin/image-saver.js.map +1 -1
- package/dist/src/plugin/index.d.ts +30 -0
- package/dist/src/plugin/index.d.ts.map +1 -0
- package/dist/src/plugin/index.js +411 -0
- package/dist/src/plugin/index.js.map +1 -0
- package/dist/src/plugin/killswitch.d.ts +94 -0
- package/dist/src/plugin/killswitch.d.ts.map +1 -0
- package/dist/src/plugin/killswitch.js +197 -0
- package/dist/src/plugin/killswitch.js.map +1 -0
- package/dist/src/plugin/lifecycle.d.ts +40 -0
- package/dist/src/plugin/lifecycle.d.ts.map +1 -0
- package/dist/src/plugin/lifecycle.js +73 -0
- package/dist/src/plugin/lifecycle.js.map +1 -0
- package/dist/src/plugin/logger.d.ts +10 -1
- package/dist/src/plugin/logger.d.ts.map +1 -1
- package/dist/src/plugin/logger.js +38 -12
- package/dist/src/plugin/logger.js.map +1 -1
- package/dist/src/plugin/logging-utils.d.ts +35 -1
- package/dist/src/plugin/logging-utils.d.ts.map +1 -1
- package/dist/src/plugin/logging-utils.js +98 -15
- package/dist/src/plugin/logging-utils.js.map +1 -1
- package/dist/src/plugin/model-registry.d.ts +1 -1
- package/dist/src/plugin/model-registry.js +1 -1
- package/dist/src/plugin/oauth-login.d.ts +22 -0
- package/dist/src/plugin/oauth-login.d.ts.map +1 -0
- package/dist/src/plugin/oauth-login.js +37 -0
- package/dist/src/plugin/oauth-login.js.map +1 -0
- package/dist/src/plugin/oauth-methods.d.ts +42 -0
- package/dist/src/plugin/oauth-methods.d.ts.map +1 -0
- package/dist/src/plugin/oauth-methods.js +1276 -0
- package/dist/src/plugin/oauth-methods.js.map +1 -0
- package/dist/src/plugin/operator-settings.d.ts +40 -0
- package/dist/src/plugin/operator-settings.d.ts.map +1 -0
- package/dist/src/plugin/operator-settings.js +148 -0
- package/dist/src/plugin/operator-settings.js.map +1 -0
- package/dist/src/plugin/persist-account-pool.d.ts +37 -0
- package/dist/src/plugin/persist-account-pool.d.ts.map +1 -0
- package/dist/src/plugin/persist-account-pool.js +142 -0
- package/dist/src/plugin/persist-account-pool.js.map +1 -0
- package/dist/src/plugin/project.d.ts +1 -1
- package/dist/src/plugin/project.js +1 -1
- package/dist/src/plugin/prompt-context.d.ts.map +1 -1
- package/dist/src/plugin/prompt-context.js +11 -11
- package/dist/src/plugin/prompt-context.js.map +1 -1
- package/dist/src/plugin/quota.d.ts +138 -41
- package/dist/src/plugin/quota.d.ts.map +1 -1
- package/dist/src/plugin/quota.js +417 -285
- package/dist/src/plugin/quota.js.map +1 -1
- package/dist/src/plugin/recovery/constants.d.ts.map +1 -1
- package/dist/src/plugin/recovery/constants.js +24 -15
- package/dist/src/plugin/recovery/constants.js.map +1 -1
- package/dist/src/plugin/recovery/index.d.ts +3 -3
- package/dist/src/plugin/recovery/index.d.ts.map +1 -1
- package/dist/src/plugin/recovery/index.js +3 -3
- package/dist/src/plugin/recovery/index.js.map +1 -1
- package/dist/src/plugin/recovery/storage.d.ts +1 -1
- package/dist/src/plugin/recovery/storage.d.ts.map +1 -1
- package/dist/src/plugin/recovery/storage.js +31 -39
- package/dist/src/plugin/recovery/storage.js.map +1 -1
- package/dist/src/plugin/recovery/types.d.ts +12 -12
- package/dist/src/plugin/recovery/types.d.ts.map +1 -1
- package/dist/src/plugin/recovery.d.ts +3 -3
- package/dist/src/plugin/recovery.d.ts.map +1 -1
- package/dist/src/plugin/recovery.js +62 -58
- package/dist/src/plugin/recovery.js.map +1 -1
- package/dist/src/plugin/refresh-queue.d.ts +5 -2
- package/dist/src/plugin/refresh-queue.d.ts.map +1 -1
- package/dist/src/plugin/refresh-queue.js +37 -15
- package/dist/src/plugin/refresh-queue.js.map +1 -1
- package/dist/src/plugin/request-helpers.d.ts +1 -1
- package/dist/src/plugin/request-helpers.d.ts.map +1 -1
- package/dist/src/plugin/request-helpers.js +451 -352
- package/dist/src/plugin/request-helpers.js.map +1 -1
- package/dist/src/plugin/request.d.ts +7 -7
- package/dist/src/plugin/request.d.ts.map +1 -1
- package/dist/src/plugin/request.js +622 -384
- package/dist/src/plugin/request.js.map +1 -1
- package/dist/src/plugin/rotation.d.ts +1 -168
- package/dist/src/plugin/rotation.d.ts.map +1 -1
- package/dist/src/plugin/rotation.js +1 -327
- package/dist/src/plugin/rotation.js.map +1 -1
- package/dist/src/plugin/search.d.ts.map +1 -1
- package/dist/src/plugin/search.js +39 -35
- package/dist/src/plugin/search.js.map +1 -1
- package/dist/src/plugin/server.d.ts +1 -1
- package/dist/src/plugin/server.d.ts.map +1 -1
- package/dist/src/plugin/server.js +42 -37
- package/dist/src/plugin/server.js.map +1 -1
- package/dist/src/plugin/session-context.d.ts +2 -1
- package/dist/src/plugin/session-context.d.ts.map +1 -1
- package/dist/src/plugin/session-context.js +11 -7
- package/dist/src/plugin/session-context.js.map +1 -1
- package/dist/src/plugin/storage.d.ts +59 -120
- package/dist/src/plugin/storage.d.ts.map +1 -1
- package/dist/src/plugin/storage.js +140 -485
- package/dist/src/plugin/storage.js.map +1 -1
- package/dist/src/plugin/stores/signature-store.d.ts.map +1 -1
- package/dist/src/plugin/stores/signature-store.js.map +1 -1
- package/dist/src/plugin/thinking-recovery.d.ts.map +1 -1
- package/dist/src/plugin/thinking-recovery.js +35 -33
- package/dist/src/plugin/thinking-recovery.js.map +1 -1
- package/dist/src/plugin/token.d.ts +2 -2
- package/dist/src/plugin/token.d.ts.map +1 -1
- package/dist/src/plugin/token.js +30 -21
- package/dist/src/plugin/token.js.map +1 -1
- package/dist/src/plugin/transform/cross-model-sanitizer.d.ts +1 -1
- package/dist/src/plugin/transform/cross-model-sanitizer.js +1 -1
- package/dist/src/plugin/transform/index.d.ts +1 -1
- package/dist/src/plugin/transform/index.js +1 -1
- package/dist/src/plugin/transform/model-resolver.d.ts +1 -1
- package/dist/src/plugin/transform/model-resolver.js +1 -1
- package/dist/src/plugin/transform/types.d.ts +1 -1
- package/dist/src/plugin/transform/types.js +1 -1
- package/dist/src/plugin/types.d.ts +25 -69
- package/dist/src/plugin/types.d.ts.map +1 -1
- package/dist/src/plugin/ui/ansi.d.ts.map +1 -1
- package/dist/src/plugin/ui/ansi.js.map +1 -1
- package/dist/src/plugin/ui/auth-menu.d.ts +1 -1
- package/dist/src/plugin/ui/auth-menu.d.ts.map +1 -1
- package/dist/src/plugin/ui/auth-menu.js +84 -35
- package/dist/src/plugin/ui/auth-menu.js.map +1 -1
- package/dist/src/plugin/ui/confirm.d.ts.map +1 -1
- package/dist/src/plugin/ui/confirm.js.map +1 -1
- package/dist/src/plugin/ui/model-status.d.ts +3 -3
- package/dist/src/plugin/ui/model-status.d.ts.map +1 -1
- package/dist/src/plugin/ui/model-status.js +3 -3
- package/dist/src/plugin/ui/model-status.js.map +1 -1
- package/dist/src/plugin/ui/quota-status.d.ts +4 -4
- package/dist/src/plugin/ui/quota-status.d.ts.map +1 -1
- package/dist/src/plugin/ui/quota-status.js +49 -49
- package/dist/src/plugin/ui/quota-status.js.map +1 -1
- package/dist/src/plugin/ui/select.d.ts.map +1 -1
- package/dist/src/plugin/ui/select.js +22 -12
- package/dist/src/plugin/ui/select.js.map +1 -1
- package/dist/src/plugin/version.d.ts +1 -1
- package/dist/src/plugin/version.js +1 -1
- package/dist/src/rpc/notifications.d.ts +6 -0
- package/dist/src/rpc/notifications.d.ts.map +1 -0
- package/dist/src/rpc/notifications.js +46 -0
- package/dist/src/rpc/notifications.js.map +1 -0
- package/dist/src/rpc/port-file.d.ts +13 -0
- package/dist/src/rpc/port-file.d.ts.map +1 -0
- package/dist/src/rpc/port-file.js +109 -0
- package/dist/src/rpc/port-file.js.map +1 -0
- package/dist/src/rpc/protocol.d.ts +22 -0
- package/dist/src/rpc/protocol.d.ts.map +1 -0
- package/dist/src/rpc/protocol.js +1 -0
- package/dist/src/rpc/protocol.js.map +1 -0
- package/dist/src/rpc/rpc-client.d.ts +10 -0
- package/dist/src/rpc/rpc-client.d.ts.map +1 -0
- package/dist/src/rpc/rpc-client.js +58 -0
- package/dist/src/rpc/rpc-client.js.map +1 -0
- package/dist/src/rpc/rpc-dir.d.ts +4 -0
- package/dist/src/rpc/rpc-dir.d.ts.map +1 -0
- package/dist/src/rpc/rpc-dir.js +19 -0
- package/dist/src/rpc/rpc-dir.js.map +1 -0
- package/dist/src/rpc/rpc-server.d.ts +13 -0
- package/dist/src/rpc/rpc-server.d.ts.map +1 -0
- package/dist/src/rpc/rpc-server.js +231 -0
- package/dist/src/rpc/rpc-server.js.map +1 -0
- package/dist/src/sidebar-state.d.ts +357 -0
- package/dist/src/sidebar-state.d.ts.map +1 -0
- package/dist/src/sidebar-state.js +680 -0
- package/dist/src/sidebar-state.js.map +1 -0
- package/dist/src/tui/command-dialogs.d.ts +61 -0
- package/dist/src/tui/command-dialogs.d.ts.map +1 -0
- package/dist/src/tui/command-dialogs.js +595 -0
- package/dist/src/tui/command-dialogs.js.map +1 -0
- package/dist/src/tui/file-logger.d.ts +41 -0
- package/dist/src/tui/file-logger.d.ts.map +1 -0
- package/dist/src/tui/file-logger.js +114 -0
- package/dist/src/tui/file-logger.js.map +1 -0
- package/dist/src/tui-preferences.d.ts +40 -0
- package/dist/src/tui-preferences.d.ts.map +1 -0
- package/dist/src/tui-preferences.js +328 -0
- package/dist/src/tui-preferences.js.map +1 -0
- package/dist/src/tui.d.ts +68 -0
- package/dist/src/tui.d.ts.map +1 -0
- package/dist/src/tui.js +697 -0
- package/dist/src/tui.js.map +1 -0
- package/package.json +46 -22
- package/src/plugin/command-data.ts +931 -0
- package/src/rpc/port-file.ts +143 -0
- package/src/rpc/protocol.ts +31 -0
- package/src/rpc/rpc-client.ts +102 -0
- package/src/rpc/rpc-dir.ts +24 -0
- package/src/sidebar-state.ts +991 -0
- package/src/tui/command-dialogs.tsx +832 -0
- package/src/tui/entry.mjs +74 -0
- package/src/tui/file-logger.ts +145 -0
- package/src/tui-compiled/plugin/command-data.ts +931 -0
- package/src/tui-compiled/rpc/port-file.ts +143 -0
- package/src/tui-compiled/rpc/protocol.ts +31 -0
- package/src/tui-compiled/rpc/rpc-client.ts +102 -0
- package/src/tui-compiled/rpc/rpc-dir.ts +24 -0
- package/src/tui-compiled/sidebar-state.ts +991 -0
- package/src/tui-compiled/tui/command-dialogs.tsx +779 -0
- package/src/tui-compiled/tui/file-logger.ts +145 -0
- package/src/tui-compiled/tui-preferences.ts +416 -0
- package/src/tui-compiled/tui.tsx +1193 -0
- package/src/tui-preferences.ts +416 -0
- package/src/tui.tsx +1171 -0
- package/dist/src/plugin.d.ts +0 -48
- package/dist/src/plugin.d.ts.map +0 -1
- package/dist/src/plugin.js +0 -3311
- package/dist/src/plugin.js.map +0 -1
package/dist/src/plugin/quota.js
CHANGED
|
@@ -1,251 +1,382 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode adapter for the harness-agnostic quota manager.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the core `QuotaManager` types and helpers so call sites in
|
|
5
|
+
* `plugin.ts` and other modules don't need to switch imports. Also wires up
|
|
6
|
+
* the host-specific fetch callback that handles:
|
|
7
|
+
* 1. Token refresh via the existing `refreshAccessToken` path.
|
|
8
|
+
* 2. Persisting rotated refresh tokens via `client.auth.set` (matching
|
|
9
|
+
* legacy behavior).
|
|
10
|
+
* 3. Resolving project context via `ensureProjectContext`.
|
|
11
|
+
*
|
|
12
|
+
* The legacy `checkAccountsQuota(accounts, client, providerId)` export is
|
|
13
|
+
* retained as a compatibility wrapper that creates a short-lived manager
|
|
14
|
+
* with `force: true` — manual quota screens must always refresh, even if
|
|
15
|
+
* the background manager has backed off.
|
|
16
|
+
*/
|
|
17
|
+
import { aggregateGeminiCliQuota, aggregateQuota, aggregateQuotaSummary, createQuotaManager, defaultKeyOf, fetchAvailableModels, fetchGeminiCliQuota, fetchQuotaSummary, getHealthTracker, } from '@cortexkit/antigravity-auth-core';
|
|
18
|
+
import { ANTIGRAVITY_ENDPOINT_FALLBACKS, ANTIGRAVITY_PROVIDER_ID, buildGeminiCliUserAgent, } from '../constants';
|
|
19
|
+
import { buildSidebarMachineStateFromAccounts, isAccountCurrent, setSidebarMachineState, } from '../sidebar-state';
|
|
20
|
+
import { accessTokenExpired, formatRefreshParts, parseRefreshParts, } from './auth';
|
|
21
|
+
import { logQuotaFetch, logQuotaStatus } from './debug';
|
|
22
|
+
import { buildAntigravityHarnessUserAgent } from './fingerprint';
|
|
23
|
+
import { createLogger } from './logger';
|
|
24
|
+
import { ensureProjectContext, loadManagedProject } from './project';
|
|
25
|
+
import { refreshAccessToken } from './token';
|
|
26
|
+
// Re-export the public surface so existing imports from `./quota` keep working.
|
|
27
|
+
const log = createLogger('quota');
|
|
28
|
+
export { classifyQuotaGroup, createQuotaManager, defaultKeyOf, } from '@cortexkit/antigravity-auth-core';
|
|
29
|
+
/**
|
|
30
|
+
* Build an OpenCode-wired quota manager.
|
|
31
|
+
*
|
|
32
|
+
* The returned manager owns its cache, in-flight dedupe, and backoff state.
|
|
33
|
+
* Register its `dispose()` with `PluginLifecycle` so refreshes abort on plugin
|
|
34
|
+
* shutdown.
|
|
35
|
+
*
|
|
36
|
+
* The wrapper observes `refreshAccount` / `refreshAccounts` and pushes a
|
|
37
|
+
* redacted sidebar snapshot after every refresh (success or backoff) so
|
|
38
|
+
* the TUI's next poll renders the freshest cached quota. The snapshot is
|
|
39
|
+
* sourced from the live AccountManager view (`getAccountsForSidebar`) so
|
|
40
|
+
* it carries the just-updated percentages; before bootstrapping it is a
|
|
41
|
+
* no-op.
|
|
42
|
+
*/
|
|
43
|
+
export function createOpenCodeQuotaManager(client, providerId = ANTIGRAVITY_PROVIDER_ID, options = {}) {
|
|
44
|
+
const fetchAccountQuota = makeFetchAccountQuota(client, providerId, options.fetchVia);
|
|
45
|
+
const manager = createQuotaManager({
|
|
46
|
+
fetchAccountQuota,
|
|
47
|
+
keyOf: options.keyOf ?? defaultKeyOf,
|
|
48
|
+
baseBackoffMs: options.baseBackoffMs,
|
|
49
|
+
maxBackoffMs: options.maxBackoffMs,
|
|
50
|
+
fetchTimeoutMs: options.fetchTimeoutMs,
|
|
51
|
+
});
|
|
52
|
+
const originalRefreshAccount = manager.refreshAccount;
|
|
53
|
+
const originalRefreshAccounts = manager.refreshAccounts;
|
|
54
|
+
const getAccountsForSidebar = options.getAccountsForSidebar;
|
|
55
|
+
const getActiveIndexByFamily = options.getActiveIndexByFamily;
|
|
56
|
+
let disposed = false;
|
|
57
|
+
const inFlight = new Set();
|
|
58
|
+
const pushAfterRefresh = async (account) => {
|
|
59
|
+
if (!getAccountsForSidebar)
|
|
60
|
+
return;
|
|
61
|
+
await pushSidebarQuotaSnapshot(getAccountsForSidebar, manager.getBackoffUntil(account), getActiveIndexByFamily).catch(() => {
|
|
62
|
+
// Sidebar persistence remains best-effort when lock contention
|
|
63
|
+
// outlives its retry budget.
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
const track = (operation) => {
|
|
67
|
+
inFlight.add(operation);
|
|
68
|
+
void operation.then(() => inFlight.delete(operation), () => inFlight.delete(operation));
|
|
69
|
+
return operation;
|
|
70
|
+
};
|
|
71
|
+
const dispose = async () => {
|
|
72
|
+
if (disposed)
|
|
73
|
+
return;
|
|
74
|
+
disposed = true;
|
|
75
|
+
await manager.dispose();
|
|
76
|
+
await Promise.allSettled(inFlight);
|
|
77
|
+
};
|
|
12
78
|
return {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
79
|
+
...manager,
|
|
80
|
+
async refreshAccount(account, refreshOptions) {
|
|
81
|
+
const shouldPush = !disposed;
|
|
82
|
+
return track((async () => {
|
|
83
|
+
const result = await originalRefreshAccount(account, refreshOptions);
|
|
84
|
+
if (shouldPush)
|
|
85
|
+
await pushAfterRefresh(account);
|
|
86
|
+
return result;
|
|
87
|
+
})());
|
|
88
|
+
},
|
|
89
|
+
async refreshAccounts(accounts, refreshOptions) {
|
|
90
|
+
const shouldPush = !disposed;
|
|
91
|
+
return track((async () => {
|
|
92
|
+
const results = await originalRefreshAccounts(accounts, refreshOptions);
|
|
93
|
+
// Push one snapshot per batch — the AccountManager's view is updated
|
|
94
|
+
// by the caller (oauth-methods / fetch-interceptor) BEFORE we read
|
|
95
|
+
// here, so a single post-batch snapshot captures the full diff.
|
|
96
|
+
const lastAccount = accounts[accounts.length - 1];
|
|
97
|
+
if (shouldPush && lastAccount)
|
|
98
|
+
await pushAfterRefresh(lastAccount);
|
|
99
|
+
return results;
|
|
100
|
+
})());
|
|
101
|
+
},
|
|
102
|
+
dispose,
|
|
21
103
|
};
|
|
22
104
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Compatibility wrapper used by code paths that want a one-shot check across
|
|
107
|
+
* the full account pool with no shared cache.
|
|
108
|
+
*
|
|
109
|
+
* Equivalent to spinning up a short-lived manager with `force: true` so
|
|
110
|
+
* manual quota dialogs always reflect the latest data even if the background
|
|
111
|
+
* manager has backed off.
|
|
112
|
+
*/
|
|
113
|
+
export async function checkAccountsQuotaWith(accounts, fetchAccountQuota) {
|
|
114
|
+
const manager = createQuotaManager({
|
|
115
|
+
fetchAccountQuota,
|
|
116
|
+
keyOf: defaultKeyOf,
|
|
117
|
+
});
|
|
118
|
+
try {
|
|
119
|
+
return await manager.refreshAccounts(accounts, {
|
|
120
|
+
indexFor: (account) => accounts.indexOf(account),
|
|
121
|
+
force: true,
|
|
122
|
+
});
|
|
27
123
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (value > 1)
|
|
31
|
-
return 1;
|
|
32
|
-
return value;
|
|
33
|
-
}
|
|
34
|
-
function parseResetTime(resetTime) {
|
|
35
|
-
if (!resetTime)
|
|
36
|
-
return null;
|
|
37
|
-
const timestamp = Date.parse(resetTime);
|
|
38
|
-
if (!Number.isFinite(timestamp)) {
|
|
39
|
-
return null;
|
|
124
|
+
finally {
|
|
125
|
+
manager.dispose();
|
|
40
126
|
}
|
|
41
|
-
return timestamp;
|
|
42
127
|
}
|
|
43
|
-
export function
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
128
|
+
export async function checkAccountsQuotaStandalone(accounts, options) {
|
|
129
|
+
if (!options.refresh) {
|
|
130
|
+
return accounts.map((account, index) => ({
|
|
131
|
+
index,
|
|
132
|
+
email: account.email,
|
|
133
|
+
status: account.enabled === false ? 'disabled' : 'ok',
|
|
134
|
+
disabled: account.enabled === false,
|
|
135
|
+
quota: {
|
|
136
|
+
groups: account.cachedQuota ?? {},
|
|
137
|
+
modelCount: Object.keys(account.cachedQuota ?? {}).length,
|
|
138
|
+
},
|
|
139
|
+
}));
|
|
47
140
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
141
|
+
return checkAccountsQuotaWith(accounts, makeFetchAccountQuota(undefined, ANTIGRAVITY_PROVIDER_ID));
|
|
142
|
+
}
|
|
143
|
+
export async function checkAccountsQuota(accounts, client, providerId = ANTIGRAVITY_PROVIDER_ID) {
|
|
144
|
+
return checkAccountsQuotaWith(accounts, makeFetchAccountQuota(client, providerId));
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Push a quota refresh into the sidebar. Called by every quota refresh
|
|
148
|
+
* call site (manual `/antigravity-quota`, the `check` menu action, and the
|
|
149
|
+
* background refresh in `fetch-interceptor`) AFTER the results have been
|
|
150
|
+
* folded back into the AccountManager's cached quota. The function reads
|
|
151
|
+
* the live account snapshot through `getAccounts` so the redacted entry
|
|
152
|
+
* carries the just-refreshed percentages — not the previous tick's stale
|
|
153
|
+
* numbers and not `undefined`.
|
|
154
|
+
*
|
|
155
|
+
* The mapping is deliberately tolerant: if `getAccounts` returns `null`
|
|
156
|
+
* (e.g. before the plugin has finished bootstrapping) the call is a no-op.
|
|
157
|
+
* On lock contention the error is logged-and-swallowed so a quota dialog
|
|
158
|
+
* never fails just because the sidebar file is busy.
|
|
159
|
+
*/
|
|
160
|
+
export async function pushSidebarQuotaSnapshot(getAccounts, backoffUntil = 0, getActiveIndexByFamily) {
|
|
161
|
+
const accounts = getAccounts();
|
|
162
|
+
if (!accounts || accounts.length === 0)
|
|
163
|
+
return;
|
|
164
|
+
const activeByFamily = getActiveIndexByFamily?.() ?? null;
|
|
165
|
+
try {
|
|
166
|
+
await setSidebarMachineState(buildSidebarMachineStateFromAccounts(accounts.map((entry) => ({
|
|
167
|
+
index: entry.index,
|
|
168
|
+
label: entry.label,
|
|
169
|
+
enabled: entry.enabled,
|
|
170
|
+
current: activeByFamily
|
|
171
|
+
? isAccountCurrent(entry.index, activeByFamily)
|
|
172
|
+
: false,
|
|
173
|
+
coolingDownUntil: entry.coolingDownUntil,
|
|
174
|
+
cachedQuota: entry.cachedQuota,
|
|
175
|
+
cachedQuotaAccountId: entry.cachedQuotaAccountId,
|
|
176
|
+
currentQuotaAccountId: entry.currentQuotaAccountId,
|
|
177
|
+
healthScore: getHealthTracker().getScore(entry.index),
|
|
178
|
+
tier: entry.tier,
|
|
179
|
+
})), {
|
|
180
|
+
checkedAt: Date.now(),
|
|
181
|
+
quotaBackoffUntil: backoffUntil > 0 ? backoffUntil : undefined,
|
|
182
|
+
}));
|
|
51
183
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return null;
|
|
184
|
+
catch (error) {
|
|
185
|
+
log.debug('sidebar-quota-write-failed', { error: String(error) });
|
|
55
186
|
}
|
|
56
|
-
const family = getModelFamily(modelName);
|
|
57
|
-
return family === "gemini-flash" ? "gemini-flash" : "gemini-pro";
|
|
58
187
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
totalCount += 1;
|
|
75
|
-
// Always preserve per-model data regardless of group classification
|
|
76
|
-
perModel.push({
|
|
77
|
-
modelId: modelName,
|
|
78
|
-
displayName: entry.displayName ?? entry.modelName,
|
|
79
|
-
group,
|
|
80
|
-
remainingFraction: remainingFraction ?? 0,
|
|
81
|
-
resetTime,
|
|
188
|
+
/**
|
|
189
|
+
* Legacy fallback: fetchAvailableModels → aggregateQuota. Used when
|
|
190
|
+
* `fetchQuotaSummary` rejects (network, 403, etc.). Extracted so the
|
|
191
|
+
* concurrent fetch path can reuse the same fallback logic without
|
|
192
|
+
* duplicating the catch chain.
|
|
193
|
+
*/
|
|
194
|
+
async function fetchLegacyModelsFallback(options) {
|
|
195
|
+
try {
|
|
196
|
+
const modelsResponse = await fetchAvailableModels({
|
|
197
|
+
accessToken: options.accessToken,
|
|
198
|
+
projectId: options.projectId,
|
|
199
|
+
endpoints: ANTIGRAVITY_ENDPOINT_FALLBACKS,
|
|
200
|
+
userAgent: buildAntigravityHarnessUserAgent(),
|
|
201
|
+
timeoutMs: 10_000,
|
|
202
|
+
...(options.fetchVia ? { fetchVia: options.fetchVia } : {}),
|
|
82
203
|
});
|
|
83
|
-
if (
|
|
84
|
-
|
|
204
|
+
if (modelsResponse.models) {
|
|
205
|
+
return aggregateQuota(modelsResponse.models);
|
|
85
206
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
: existing?.remainingFraction === undefined
|
|
91
|
-
? remainingFraction
|
|
92
|
-
: Math.min(existing.remainingFraction, remainingFraction);
|
|
93
|
-
let nextResetTime = existing?.resetTime;
|
|
94
|
-
if (resetTimestamp !== null) {
|
|
95
|
-
if (!existing?.resetTime) {
|
|
96
|
-
nextResetTime = resetTime;
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
const existingTimestamp = parseResetTime(existing.resetTime);
|
|
100
|
-
if (existingTimestamp === null || resetTimestamp < existingTimestamp) {
|
|
101
|
-
nextResetTime = resetTime;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
groups[group] = {
|
|
106
|
-
remainingFraction: nextRemaining,
|
|
107
|
-
resetTime: nextResetTime,
|
|
108
|
-
modelCount: nextCount,
|
|
207
|
+
return {
|
|
208
|
+
groups: {},
|
|
209
|
+
modelCount: 0,
|
|
210
|
+
error: 'Failed to fetch Antigravity quota (legacy fallback)',
|
|
109
211
|
};
|
|
110
212
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
118
|
-
try {
|
|
119
|
-
return await fetch(url, { ...options, signal: controller.signal });
|
|
120
|
-
}
|
|
121
|
-
finally {
|
|
122
|
-
clearTimeout(timeout);
|
|
213
|
+
catch {
|
|
214
|
+
return {
|
|
215
|
+
groups: {},
|
|
216
|
+
modelCount: 0,
|
|
217
|
+
error: 'Failed to fetch Antigravity quota',
|
|
218
|
+
};
|
|
123
219
|
}
|
|
124
220
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
221
|
+
function makeFetchAccountQuota(client, providerId, fetchVia) {
|
|
222
|
+
return async (account, signal) => {
|
|
223
|
+
const index = 0;
|
|
224
|
+
const disabled = account.enabled === false;
|
|
225
|
+
if (disabled) {
|
|
226
|
+
return {
|
|
227
|
+
index,
|
|
228
|
+
email: account.email,
|
|
229
|
+
status: 'disabled',
|
|
230
|
+
disabled: true,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
if (signal.aborted) {
|
|
234
|
+
return {
|
|
235
|
+
index,
|
|
236
|
+
email: account.email,
|
|
237
|
+
status: 'error',
|
|
238
|
+
error: signal.reason instanceof Error ? signal.reason.message : 'aborted',
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
let auth = buildAuthFromAccount(account);
|
|
242
|
+
let rotatedRefresh;
|
|
130
243
|
try {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
}, { timeoutMs: FETCH_TIMEOUT_MS });
|
|
141
|
-
if (response.ok) {
|
|
142
|
-
return (await response.json());
|
|
244
|
+
if (accessTokenExpired(auth)) {
|
|
245
|
+
const refreshed = await refreshAccessToken(auth, client, providerId);
|
|
246
|
+
if (!refreshed) {
|
|
247
|
+
throw new Error('Token refresh failed');
|
|
248
|
+
}
|
|
249
|
+
if (refreshed.refresh !== auth.refresh) {
|
|
250
|
+
rotatedRefresh = refreshed.refresh;
|
|
251
|
+
}
|
|
252
|
+
auth = refreshed;
|
|
143
253
|
}
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
254
|
+
const projectContext = await ensureProjectContext(auth);
|
|
255
|
+
auth = projectContext.auth;
|
|
256
|
+
const updatedAccount = applyAccountUpdates(account, auth, projectContext.capturedTier);
|
|
257
|
+
if (rotatedRefresh && client) {
|
|
258
|
+
await persistRotatedRefresh(client, providerId, auth).catch(() => { });
|
|
259
|
+
}
|
|
260
|
+
let quotaResult;
|
|
261
|
+
let fellBackToLegacy = false;
|
|
262
|
+
const authParts = parseRefreshParts(auth.refresh);
|
|
263
|
+
// Bare refresh tokens have no packed project IDs — fall back to the
|
|
264
|
+
// account record. The real managedProjectId lives on the persisted
|
|
265
|
+
// account, not in the packed refresh string.
|
|
266
|
+
const managedProjectId = authParts.managedProjectId ?? account.managedProjectId;
|
|
267
|
+
// Two independent payload contracts: the windowed summary
|
|
268
|
+
// (with legacy fallback) and the gemini-CLI quota. They share
|
|
269
|
+
// access + project but target different endpoints, so the
|
|
270
|
+
// two 10s timeouts ran back-to-back for ~20s per account on
|
|
271
|
+
// modal open. Run them concurrently; either rejection is
|
|
272
|
+
// handled by its own branch and the result is still merged.
|
|
273
|
+
const fetchSummaryPayload = (async () => {
|
|
147
274
|
try {
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
},
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
275
|
+
const summaryResult = await fetchQuotaSummary({
|
|
276
|
+
accessToken: auth.access ?? '',
|
|
277
|
+
managedProjectId,
|
|
278
|
+
projectId: projectContext.effectiveProjectId,
|
|
279
|
+
endpoints: ANTIGRAVITY_ENDPOINT_FALLBACKS,
|
|
280
|
+
userAgent: buildAntigravityHarnessUserAgent(),
|
|
281
|
+
timeoutMs: 10_000,
|
|
282
|
+
...(fetchVia ? { fetchVia } : {}),
|
|
283
|
+
});
|
|
284
|
+
return {
|
|
285
|
+
result: aggregateQuotaSummary(summaryResult.summary),
|
|
286
|
+
fellBackToLegacy: summaryResult.fellBackToLegacy ?? false,
|
|
287
|
+
};
|
|
161
288
|
}
|
|
162
289
|
catch {
|
|
163
|
-
|
|
290
|
+
return {
|
|
291
|
+
result: await fetchLegacyModelsFallback({
|
|
292
|
+
accessToken: auth.access ?? '',
|
|
293
|
+
projectId: projectContext.effectiveProjectId,
|
|
294
|
+
fetchVia,
|
|
295
|
+
}),
|
|
296
|
+
fellBackToLegacy: true,
|
|
297
|
+
};
|
|
164
298
|
}
|
|
165
|
-
}
|
|
166
|
-
//
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
throw new Error(errors.join("; ") || "fetchAvailableModels failed");
|
|
186
|
-
}
|
|
187
|
-
async function fetchGeminiCliQuota(accessToken, projectId) {
|
|
188
|
-
// Use Gemini CLI user-agent to get CLI quota buckets (not Antigravity buckets)
|
|
189
|
-
const geminiCliUserAgent = buildGeminiCliUserAgent();
|
|
190
|
-
for (const endpoint of ANTIGRAVITY_ENDPOINT_FALLBACKS) {
|
|
191
|
-
const body = projectId ? { project: projectId } : {};
|
|
192
|
-
try {
|
|
193
|
-
const response = await fetchWithTimeout(`${endpoint}/v1internal:retrieveUserQuota`, {
|
|
194
|
-
method: "POST",
|
|
195
|
-
headers: {
|
|
196
|
-
Authorization: `Bearer ${accessToken}`,
|
|
197
|
-
"Content-Type": "application/json",
|
|
198
|
-
"User-Agent": geminiCliUserAgent,
|
|
199
|
-
},
|
|
200
|
-
body: JSON.stringify(body),
|
|
299
|
+
})();
|
|
300
|
+
// CLI fetch is independent of the summary fetch. A CLI failure must
|
|
301
|
+
// NOT kill the summary result, but it also must not be laundered into
|
|
302
|
+
// "No Gemini CLI quota available" (a permanent-looking status) when
|
|
303
|
+
// the real cause is a transient network error. Capture the error
|
|
304
|
+
// message separately so the annotated result can carry it.
|
|
305
|
+
let geminiCliFetchError;
|
|
306
|
+
const fetchGeminiCliPayload = fetchGeminiCliQuota({
|
|
307
|
+
accessToken: auth.access ?? '',
|
|
308
|
+
projectId: projectContext.effectiveProjectId,
|
|
309
|
+
endpoints: ANTIGRAVITY_ENDPOINT_FALLBACKS,
|
|
310
|
+
userAgent: buildGeminiCliUserAgent(),
|
|
311
|
+
timeoutMs: 10_000,
|
|
312
|
+
...(fetchVia ? { fetchVia } : {}),
|
|
313
|
+
}).catch((error) => {
|
|
314
|
+
geminiCliFetchError =
|
|
315
|
+
error instanceof Error ? error.message : String(error);
|
|
316
|
+
log.debug('fetchGeminiCliQuota failed', { error: geminiCliFetchError });
|
|
317
|
+
return { buckets: undefined };
|
|
201
318
|
});
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
319
|
+
const [summary, geminiCliResponse] = await Promise.all([
|
|
320
|
+
fetchSummaryPayload,
|
|
321
|
+
fetchGeminiCliPayload,
|
|
322
|
+
]);
|
|
323
|
+
quotaResult = summary.result;
|
|
324
|
+
fellBackToLegacy = summary.fellBackToLegacy;
|
|
325
|
+
const geminiCliQuotaResult = aggregateGeminiCliQuota(geminiCliResponse);
|
|
326
|
+
const annotated = geminiCliResponse.buckets === undefined ||
|
|
327
|
+
geminiCliResponse.buckets.length === 0
|
|
328
|
+
? {
|
|
329
|
+
...geminiCliQuotaResult,
|
|
330
|
+
error:
|
|
331
|
+
// A real fetch exception is a transient failure, not a
|
|
332
|
+
// "no CLI configured" scenario — propagate the actual message.
|
|
333
|
+
geminiCliFetchError ??
|
|
334
|
+
(geminiCliQuotaResult.models.length === 0
|
|
335
|
+
? 'No Gemini CLI quota available'
|
|
336
|
+
: undefined),
|
|
337
|
+
}
|
|
338
|
+
: geminiCliQuotaResult;
|
|
339
|
+
for (const [family, groupQuota] of Object.entries(quotaResult.groups)) {
|
|
340
|
+
const remainingPercent = (groupQuota.remainingFraction ?? 0) * 100;
|
|
341
|
+
logQuotaStatus(account.email, index, remainingPercent, family);
|
|
209
342
|
}
|
|
210
|
-
|
|
211
|
-
|
|
343
|
+
const legacyTag = fellBackToLegacy ? ' legacy=1' : '';
|
|
344
|
+
logQuotaFetch('complete', 1, `ok=1 errors=0${legacyTag}`);
|
|
345
|
+
return {
|
|
346
|
+
index,
|
|
347
|
+
email: account.email,
|
|
348
|
+
status: 'ok',
|
|
349
|
+
disabled: false,
|
|
350
|
+
quota: quotaResult,
|
|
351
|
+
geminiCliQuota: annotated,
|
|
352
|
+
updatedAccount,
|
|
353
|
+
};
|
|
212
354
|
}
|
|
213
|
-
catch {
|
|
214
|
-
|
|
215
|
-
|
|
355
|
+
catch (error) {
|
|
356
|
+
logQuotaFetch('error', undefined, `account=${account.email ?? index} error=${error instanceof Error ? error.message : String(error)}`);
|
|
357
|
+
return {
|
|
358
|
+
index,
|
|
359
|
+
email: account.email,
|
|
360
|
+
status: 'error',
|
|
361
|
+
error: error instanceof Error ? error.message : String(error),
|
|
362
|
+
disabled: false,
|
|
363
|
+
};
|
|
216
364
|
}
|
|
217
|
-
}
|
|
218
|
-
// All endpoints failed
|
|
219
|
-
return { buckets: [] };
|
|
365
|
+
};
|
|
220
366
|
}
|
|
221
|
-
function
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
const isRelevantModel = modelId.startsWith("gemini-3-") ||
|
|
233
|
-
modelId.startsWith("gemini-3.") ||
|
|
234
|
-
modelId.startsWith("gemini-2.5-");
|
|
235
|
-
if (!isRelevantModel) {
|
|
236
|
-
continue;
|
|
237
|
-
}
|
|
238
|
-
models.push({
|
|
239
|
-
modelId: bucket.modelId,
|
|
240
|
-
remainingFraction: normalizeRemainingFraction(bucket.remainingFraction),
|
|
241
|
-
resetTime: bucket.resetTime,
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
// Sort by model ID for consistent display
|
|
245
|
-
models.sort((a, b) => a.modelId.localeCompare(b.modelId));
|
|
246
|
-
return { models };
|
|
367
|
+
function buildAuthFromAccount(account) {
|
|
368
|
+
return {
|
|
369
|
+
type: 'oauth',
|
|
370
|
+
refresh: formatRefreshParts({
|
|
371
|
+
refreshToken: account.refreshToken,
|
|
372
|
+
projectId: account.projectId,
|
|
373
|
+
managedProjectId: account.managedProjectId,
|
|
374
|
+
}),
|
|
375
|
+
access: undefined,
|
|
376
|
+
expires: undefined,
|
|
377
|
+
};
|
|
247
378
|
}
|
|
248
|
-
function applyAccountUpdates(account, auth) {
|
|
379
|
+
function applyAccountUpdates(account, auth, capturedTier) {
|
|
249
380
|
const parts = parseRefreshParts(auth.refresh);
|
|
250
381
|
if (!parts.refreshToken) {
|
|
251
382
|
return undefined;
|
|
@@ -255,82 +386,83 @@ function applyAccountUpdates(account, auth) {
|
|
|
255
386
|
refreshToken: parts.refreshToken,
|
|
256
387
|
projectId: parts.projectId ?? account.projectId,
|
|
257
388
|
managedProjectId: parts.managedProjectId ?? account.managedProjectId,
|
|
389
|
+
// Persist the captured tier alongside the project-context write. Only
|
|
390
|
+
// present when the loadCodeAssist payload returned a non-empty currentTier.id.
|
|
391
|
+
...(capturedTier
|
|
392
|
+
? {
|
|
393
|
+
capturedTierId: capturedTier.id,
|
|
394
|
+
...(capturedTier.paidId !== undefined
|
|
395
|
+
? { capturedPaidTierId: capturedTier.paidId }
|
|
396
|
+
: {}),
|
|
397
|
+
capturedTierAt: capturedTier.capturedAt,
|
|
398
|
+
}
|
|
399
|
+
: {}),
|
|
258
400
|
};
|
|
259
401
|
const changed = updated.refreshToken !== account.refreshToken ||
|
|
260
402
|
updated.projectId !== account.projectId ||
|
|
261
|
-
updated.managedProjectId !== account.managedProjectId
|
|
403
|
+
updated.managedProjectId !== account.managedProjectId ||
|
|
404
|
+
updated.capturedTierId !== account.capturedTierId ||
|
|
405
|
+
updated.capturedPaidTierId !== account.capturedPaidTierId ||
|
|
406
|
+
// capturedAt represents when the tier was LAST CONFIRMED, not when it
|
|
407
|
+
// changed -- always update it on a successful observation so consumers
|
|
408
|
+
// can gate staleness on that timestamp even when the id stays the same.
|
|
409
|
+
(capturedTier !== undefined &&
|
|
410
|
+
updated.capturedTierAt !== account.capturedTierAt);
|
|
262
411
|
return changed ? updated : undefined;
|
|
263
412
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
413
|
+
async function persistRotatedRefresh(client, providerId, auth) {
|
|
414
|
+
await client.auth.set({
|
|
415
|
+
path: { id: providerId },
|
|
416
|
+
body: {
|
|
417
|
+
type: 'oauth',
|
|
418
|
+
refresh: auth.refresh,
|
|
419
|
+
access: auth.access ?? '',
|
|
420
|
+
expires: auth.expires ?? 0,
|
|
421
|
+
},
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Build a per-account tier-loader callback for the background poller.
|
|
426
|
+
*
|
|
427
|
+
* Calls `loadManagedProject` (loadCodeAssist) directly, bypassing the
|
|
428
|
+
* `ensureProjectContext` cache that fast-paths on `managedProjectId` and
|
|
429
|
+
* never returns a tier for existing accounts. One call per account per 24 h.
|
|
430
|
+
*
|
|
431
|
+
* Uses the same token-refresh infrastructure as `makeFetchAccountQuota` so
|
|
432
|
+
* an expired access token does not silently fail the tier lookup.
|
|
433
|
+
*
|
|
434
|
+
* `loadManagedProject` uses the production TLS transport (`fetchWithAgyCliTransport`)
|
|
435
|
+
* and is not interceptable via `fetchVia` -- the same design constraint applies to
|
|
436
|
+
* `ensureProjectContext`. Tier lookup is best-effort; any failure resolves `null`.
|
|
437
|
+
*/
|
|
438
|
+
export function makeTierLoader(client, providerId) {
|
|
439
|
+
return async (account) => {
|
|
270
440
|
try {
|
|
441
|
+
let auth = buildAuthFromAccount(account);
|
|
271
442
|
if (accessTokenExpired(auth)) {
|
|
272
443
|
const refreshed = await refreshAccessToken(auth, client, providerId);
|
|
273
|
-
if (!refreshed)
|
|
274
|
-
|
|
275
|
-
}
|
|
444
|
+
if (!refreshed)
|
|
445
|
+
return null;
|
|
276
446
|
auth = refreshed;
|
|
277
447
|
}
|
|
278
|
-
const
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
groups: {},
|
|
293
|
-
modelCount: 0,
|
|
294
|
-
error: "Failed to fetch Antigravity quota",
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
else {
|
|
298
|
-
quotaResult = aggregateQuota(antigravityResponse.models);
|
|
299
|
-
}
|
|
300
|
-
// Process Gemini CLI quota
|
|
301
|
-
geminiCliQuotaResult = aggregateGeminiCliQuota(geminiCliResponse);
|
|
302
|
-
if (geminiCliResponse.buckets === undefined || geminiCliResponse.buckets.length === 0) {
|
|
303
|
-
geminiCliQuotaResult.error = geminiCliQuotaResult.models.length === 0
|
|
304
|
-
? "No Gemini CLI quota available"
|
|
305
|
-
: undefined;
|
|
306
|
-
}
|
|
307
|
-
results.push({
|
|
308
|
-
index,
|
|
309
|
-
email: account.email,
|
|
310
|
-
status: "ok",
|
|
311
|
-
disabled,
|
|
312
|
-
quota: quotaResult,
|
|
313
|
-
geminiCliQuota: geminiCliQuotaResult,
|
|
314
|
-
updatedAccount,
|
|
315
|
-
});
|
|
316
|
-
// Log quota status for each family
|
|
317
|
-
for (const [family, groupQuota] of Object.entries(quotaResult.groups)) {
|
|
318
|
-
const remainingPercent = (groupQuota.remainingFraction ?? 0) * 100;
|
|
319
|
-
logQuotaStatus(account.email, index, remainingPercent, family);
|
|
320
|
-
}
|
|
448
|
+
const accessToken = auth.access;
|
|
449
|
+
if (!accessToken)
|
|
450
|
+
return null;
|
|
451
|
+
const payload = await loadManagedProject(accessToken);
|
|
452
|
+
if (!payload?.currentTier?.id)
|
|
453
|
+
return null;
|
|
454
|
+
const paidTierId = typeof payload.paidTier === 'string'
|
|
455
|
+
? payload.paidTier
|
|
456
|
+
: payload.paidTier?.id;
|
|
457
|
+
return {
|
|
458
|
+
id: payload.currentTier.id,
|
|
459
|
+
...(paidTierId ? { paidId: paidTierId } : {}),
|
|
460
|
+
capturedAt: Date.now(),
|
|
461
|
+
};
|
|
321
462
|
}
|
|
322
|
-
catch
|
|
323
|
-
|
|
324
|
-
index,
|
|
325
|
-
email: account.email,
|
|
326
|
-
status: "error",
|
|
327
|
-
disabled,
|
|
328
|
-
error: error instanceof Error ? error.message : String(error),
|
|
329
|
-
});
|
|
330
|
-
logQuotaFetch("error", undefined, `account=${account.email ?? index} error=${error instanceof Error ? error.message : String(error)}`);
|
|
463
|
+
catch {
|
|
464
|
+
return null;
|
|
331
465
|
}
|
|
332
|
-
}
|
|
333
|
-
logQuotaFetch("complete", accounts.length, `ok=${results.filter(r => r.status === "ok").length} errors=${results.filter(r => r.status === "error").length}`);
|
|
334
|
-
return results;
|
|
466
|
+
};
|
|
335
467
|
}
|
|
336
468
|
//# sourceMappingURL=quota.js.map
|