@thevinci/web 1.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 +197 -0
- package/bin/cli-entry.js +55 -0
- package/bin/cli-output.js +145 -0
- package/bin/cli.js +4887 -0
- package/bin/cli.test.js +64 -0
- package/dist/apple-touch-icon-120x120.png +0 -0
- package/dist/apple-touch-icon-152x152.png +0 -0
- package/dist/apple-touch-icon-167x167.png +0 -0
- package/dist/apple-touch-icon-180x180.png +0 -0
- package/dist/apple-touch-icon.png +0 -0
- package/dist/apple-touch-icon.svg +528 -0
- package/dist/assets/JsonTreeView-CSm9OzXG.js +1 -0
- package/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/dist/assets/MarkdownRendererImpl-DensKOLc.js +6 -0
- package/dist/assets/MultiRunWindow-Bo7THayo.js +1 -0
- package/dist/assets/OnboardingScreen-BDqmzTVR.js +2 -0
- package/dist/assets/SettingsWindow-coz__Ykw.js +1 -0
- package/dist/assets/TerminalView-DrZ-i3Dr.js +1 -0
- package/dist/assets/ToolOutputDialog-Eglzslt3.js +16 -0
- package/dist/assets/es-4o9ciP61.js +15 -0
- package/dist/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
- package/dist/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
- package/dist/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
- package/dist/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
- package/dist/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
- package/dist/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
- package/dist/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
- package/dist/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
- package/dist/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
- package/dist/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
- package/dist/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
- package/dist/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
- package/dist/assets/index-DLTDToSP.css +1 -0
- package/dist/assets/index-DgiFEKGN.js +1 -0
- package/dist/assets/ko-B20imCHE.js +15 -0
- package/dist/assets/main-BV3KOtdA.css +1 -0
- package/dist/assets/main-CDKJj0sH.js +226 -0
- package/dist/assets/main-LC-PSNVM.js +2 -0
- package/dist/assets/miniChat-CQUiG_cr.js +2 -0
- package/dist/assets/modelPrefsAutoSave-Dm799vzR.js +6986 -0
- package/dist/assets/pl-DQJ7LSzj.js +15 -0
- package/dist/assets/pt-BR-OmjHUz9y.js +15 -0
- package/dist/assets/renderElectronMiniChatApp-CARbeW0G.js +2 -0
- package/dist/assets/uk-BNFxOlO4.js +15 -0
- package/dist/assets/vendor--DBfsbEis.css +1 -0
- package/dist/assets/vendor-.bun-B9l0ZNi2.js +4094 -0
- package/dist/assets/wasm-CG6Dc4jp.js +1 -0
- package/dist/assets/wasmSttWorker-Dtlxac_K.js +1 -0
- package/dist/assets/wasmSttWorker-oo7Dm_jy.js +1806 -0
- package/dist/assets/worker-CbT6TVo7.js +155 -0
- package/dist/assets/zh-CN-C6T-Ac7F.js +15 -0
- package/dist/favicon-16.png +0 -0
- package/dist/favicon-32.png +0 -0
- package/dist/favicon.png +0 -0
- package/dist/favicon.svg +528 -0
- package/dist/index.html +607 -0
- package/dist/logo-dark-192x192.png +0 -0
- package/dist/logo-dark-512x512.png +0 -0
- package/dist/logo-dark-512x512.svg +528 -0
- package/dist/logo-light-192x192.png +0 -0
- package/dist/logo-light-512x512.png +0 -0
- package/dist/logo-light-512x512.svg +528 -0
- package/dist/mini-chat.html +16 -0
- package/dist/pwa-192.png +0 -0
- package/dist/pwa-512.png +0 -0
- package/dist/pwa-maskable-192.png +0 -0
- package/dist/pwa-maskable-512.png +0 -0
- package/dist/site.webmanifest +21 -0
- package/dist/sw.js +1 -0
- package/package.json +118 -0
- package/public/apple-touch-icon-120x120.png +0 -0
- package/public/apple-touch-icon-152x152.png +0 -0
- package/public/apple-touch-icon-167x167.png +0 -0
- package/public/apple-touch-icon-180x180.png +0 -0
- package/public/apple-touch-icon.png +0 -0
- package/public/apple-touch-icon.svg +528 -0
- package/public/favicon-16.png +0 -0
- package/public/favicon-32.png +0 -0
- package/public/favicon.png +0 -0
- package/public/favicon.svg +528 -0
- package/public/logo-dark-192x192.png +0 -0
- package/public/logo-dark-512x512.png +0 -0
- package/public/logo-dark-512x512.svg +528 -0
- package/public/logo-light-192x192.png +0 -0
- package/public/logo-light-512x512.png +0 -0
- package/public/logo-light-512x512.svg +528 -0
- package/public/pwa-192.png +0 -0
- package/public/pwa-512.png +0 -0
- package/public/pwa-maskable-192.png +0 -0
- package/public/pwa-maskable-512.png +0 -0
- package/public/site.webmanifest +21 -0
- package/server/TERMINAL_WS_PROTOCOL.md +48 -0
- package/server/index.d.ts +39 -0
- package/server/index.js +1311 -0
- package/server/lib/cloudflare-tunnel.js +650 -0
- package/server/lib/event-stream/DOCUMENTATION.md +61 -0
- package/server/lib/event-stream/directory-ws-bridge.js +185 -0
- package/server/lib/event-stream/global-hub.js +158 -0
- package/server/lib/event-stream/global-hub.test.js +140 -0
- package/server/lib/event-stream/global-ws-bridge.js +206 -0
- package/server/lib/event-stream/index.js +25 -0
- package/server/lib/event-stream/protocol.js +131 -0
- package/server/lib/event-stream/protocol.test.js +182 -0
- package/server/lib/event-stream/runtime.js +180 -0
- package/server/lib/event-stream/runtime.test.js +512 -0
- package/server/lib/event-stream/upstream-reader.js +226 -0
- package/server/lib/event-stream/upstream-reader.test.js +276 -0
- package/server/lib/fs/DOCUMENTATION.md +36 -0
- package/server/lib/fs/routes.js +1040 -0
- package/server/lib/fs/search.js +238 -0
- package/server/lib/git/DOCUMENTATION.md +152 -0
- package/server/lib/git/credentials.js +74 -0
- package/server/lib/git/identity-storage.js +112 -0
- package/server/lib/git/index.js +6 -0
- package/server/lib/git/routes.js +972 -0
- package/server/lib/git/service.js +3432 -0
- package/server/lib/git/service.test.js +39 -0
- package/server/lib/github/DOCUMENTATION.md +171 -0
- package/server/lib/github/auth.js +307 -0
- package/server/lib/github/device-flow.js +50 -0
- package/server/lib/github/index.js +24 -0
- package/server/lib/github/octokit.js +10 -0
- package/server/lib/github/pr-status.js +519 -0
- package/server/lib/github/repo/fork-detection.js +102 -0
- package/server/lib/github/repo/index.js +55 -0
- package/server/lib/github/routes.js +1560 -0
- package/server/lib/magic-prompts/routes.js +63 -0
- package/server/lib/magic-prompts/runtime.js +119 -0
- package/server/lib/notifications/DOCUMENTATION.md +122 -0
- package/server/lib/notifications/emitter-runtime.js +102 -0
- package/server/lib/notifications/index.js +4 -0
- package/server/lib/notifications/message.js +52 -0
- package/server/lib/notifications/message.test.js +34 -0
- package/server/lib/notifications/push-runtime.js +304 -0
- package/server/lib/notifications/routes.js +315 -0
- package/server/lib/notifications/runtime.js +566 -0
- package/server/lib/notifications/template-runtime.js +349 -0
- package/server/lib/notifications/template-runtime.test.js +26 -0
- package/server/lib/opencode/DOCUMENTATION.md +362 -0
- package/server/lib/opencode/agents.js +634 -0
- package/server/lib/opencode/auth-state-runtime.js +88 -0
- package/server/lib/opencode/auth.js +83 -0
- package/server/lib/opencode/bootstrap-runtime.js +131 -0
- package/server/lib/opencode/cli-entry-runtime.js +43 -0
- package/server/lib/opencode/cli-options.js +128 -0
- package/server/lib/opencode/commands.js +339 -0
- package/server/lib/opencode/config-entity-routes.js +370 -0
- package/server/lib/opencode/core-routes.js +500 -0
- package/server/lib/opencode/core-routes.test.js +26 -0
- package/server/lib/opencode/env-config.js +74 -0
- package/server/lib/opencode/env-keys.js +68 -0
- package/server/lib/opencode/env-runtime.js +1162 -0
- package/server/lib/opencode/env-runtime.test.js +116 -0
- package/server/lib/opencode/feature-routes-runtime.js +244 -0
- package/server/lib/opencode/hmr-state-runtime.js +85 -0
- package/server/lib/opencode/index.js +66 -0
- package/server/lib/opencode/lifecycle.js +1019 -0
- package/server/lib/opencode/lifecycle.test.js +240 -0
- package/server/lib/opencode/mcp.js +278 -0
- package/server/lib/opencode/network-runtime.js +104 -0
- package/server/lib/opencode/network-runtime.test.js +37 -0
- package/server/lib/opencode/opencode-resolution-runtime.js +71 -0
- package/server/lib/opencode/path-utils.js +100 -0
- package/server/lib/opencode/path-utils.test.js +71 -0
- package/server/lib/opencode/project-directory-runtime.js +124 -0
- package/server/lib/opencode/project-icon-routes.js +399 -0
- package/server/lib/opencode/project-icon-routes.test.js +107 -0
- package/server/lib/opencode/providers.js +96 -0
- package/server/lib/opencode/proxy.js +445 -0
- package/server/lib/opencode/pwa-manifest-routes.js +257 -0
- package/server/lib/opencode/pwa-manifest-routes.test.js +133 -0
- package/server/lib/opencode/routes.js +541 -0
- package/server/lib/opencode/server-startup-runtime.js +156 -0
- package/server/lib/opencode/server-utils-runtime.js +168 -0
- package/server/lib/opencode/server-utils-runtime.test.js +135 -0
- package/server/lib/opencode/session-runtime.js +356 -0
- package/server/lib/opencode/session-runtime.test.js +151 -0
- package/server/lib/opencode/settings-helpers.js +770 -0
- package/server/lib/opencode/settings-helpers.test.js +109 -0
- package/server/lib/opencode/settings-normalization-runtime.js +428 -0
- package/server/lib/opencode/settings-runtime.js +826 -0
- package/server/lib/opencode/settings-runtime.test.js +85 -0
- package/server/lib/opencode/shared.js +615 -0
- package/server/lib/opencode/shutdown-runtime.js +139 -0
- package/server/lib/opencode/shutdown-runtime.test.js +58 -0
- package/server/lib/opencode/skill-routes.js +701 -0
- package/server/lib/opencode/skills.js +548 -0
- package/server/lib/opencode/startup-pipeline-runtime.js +130 -0
- package/server/lib/opencode/static-routes-runtime.js +65 -0
- package/server/lib/opencode/theme-runtime.js +167 -0
- package/server/lib/opencode/tunnel-auth.js +591 -0
- package/server/lib/opencode/tunnel-wiring-runtime.js +94 -0
- package/server/lib/opencode/vinci-routes.js +76 -0
- package/server/lib/opencode/watcher.js +115 -0
- package/server/lib/opencode/watcher.test.js +239 -0
- package/server/lib/preview/proxy-runtime.js +1333 -0
- package/server/lib/preview/proxy-runtime.test.js +144 -0
- package/server/lib/projects/project-config.js +567 -0
- package/server/lib/projects/project-config.test.js +175 -0
- package/server/lib/projects/project-id.js +13 -0
- package/server/lib/quota/DOCUMENTATION.md +58 -0
- package/server/lib/quota/index.js +25 -0
- package/server/lib/quota/providers/claude.js +107 -0
- package/server/lib/quota/providers/codex.js +113 -0
- package/server/lib/quota/providers/copilot.js +165 -0
- package/server/lib/quota/providers/google/api.js +92 -0
- package/server/lib/quota/providers/google/auth.js +108 -0
- package/server/lib/quota/providers/google/index.js +124 -0
- package/server/lib/quota/providers/google/transforms.js +109 -0
- package/server/lib/quota/providers/index.js +168 -0
- package/server/lib/quota/providers/interface.js +55 -0
- package/server/lib/quota/providers/kimi.js +108 -0
- package/server/lib/quota/providers/minimax-cn-coding-plan.js +140 -0
- package/server/lib/quota/providers/minimax-coding-plan.js +139 -0
- package/server/lib/quota/providers/nanogpt.js +124 -0
- package/server/lib/quota/providers/ollama-cloud.js +112 -0
- package/server/lib/quota/providers/openai.js +91 -0
- package/server/lib/quota/providers/openrouter.js +92 -0
- package/server/lib/quota/providers/zai.js +91 -0
- package/server/lib/quota/providers/zhipuai-coding-plan.js +133 -0
- package/server/lib/quota/providers/zhipuai.js +114 -0
- package/server/lib/quota/routes.js +27 -0
- package/server/lib/quota/utils/auth.js +50 -0
- package/server/lib/quota/utils/formatters.js +85 -0
- package/server/lib/quota/utils/formatters.test.js +54 -0
- package/server/lib/quota/utils/index.js +10 -0
- package/server/lib/quota/utils/transformers.js +55 -0
- package/server/lib/scheduled-tasks/DOCUMENTATION.md +44 -0
- package/server/lib/scheduled-tasks/routes.js +235 -0
- package/server/lib/scheduled-tasks/runtime.js +773 -0
- package/server/lib/scheduled-tasks/runtime.test.js +100 -0
- package/server/lib/security/request-security.js +115 -0
- package/server/lib/session-folders/routes.js +63 -0
- package/server/lib/session-folders/routes.test.js +102 -0
- package/server/lib/skills-catalog/DOCUMENTATION.md +178 -0
- package/server/lib/skills-catalog/cache.js +29 -0
- package/server/lib/skills-catalog/clawdhub/api.js +158 -0
- package/server/lib/skills-catalog/clawdhub/index.js +30 -0
- package/server/lib/skills-catalog/clawdhub/install.js +238 -0
- package/server/lib/skills-catalog/clawdhub/scan.js +113 -0
- package/server/lib/skills-catalog/curated-sources.js +21 -0
- package/server/lib/skills-catalog/git.js +77 -0
- package/server/lib/skills-catalog/index.js +42 -0
- package/server/lib/skills-catalog/install.js +294 -0
- package/server/lib/skills-catalog/scan.js +221 -0
- package/server/lib/skills-catalog/source.js +87 -0
- package/server/lib/terminal/DOCUMENTATION.md +76 -0
- package/server/lib/terminal/index.js +31 -0
- package/server/lib/terminal/output-replay-buffer.js +78 -0
- package/server/lib/terminal/output-replay-buffer.test.js +75 -0
- package/server/lib/terminal/runtime.js +850 -0
- package/server/lib/terminal/runtime.test.js +96 -0
- package/server/lib/terminal/terminal-ws-protocol.js +68 -0
- package/server/lib/terminal/terminal-ws-protocol.test.js +145 -0
- package/server/lib/text/DOCUMENTATION.md +35 -0
- package/server/lib/text/summarization.js +138 -0
- package/server/lib/text/summarization.test.js +34 -0
- package/server/lib/tts/DOCUMENTATION.md +146 -0
- package/server/lib/tts/base-url.js +62 -0
- package/server/lib/tts/capability-runtime.js +31 -0
- package/server/lib/tts/index.js +19 -0
- package/server/lib/tts/routes.js +261 -0
- package/server/lib/tts/routes.test.js +53 -0
- package/server/lib/tts/service.js +178 -0
- package/server/lib/tts/stt.js +75 -0
- package/server/lib/tunnels/DOCUMENTATION.md +18 -0
- package/server/lib/tunnels/index.js +166 -0
- package/server/lib/tunnels/managed-config.js +201 -0
- package/server/lib/tunnels/providers/cloudflare.js +260 -0
- package/server/lib/tunnels/registry.js +51 -0
- package/server/lib/tunnels/routes.js +605 -0
- package/server/lib/tunnels/types.js +219 -0
- package/server/lib/ui-auth/DOCUMENTATION.md +38 -0
- package/server/lib/ui-auth/ui-auth.js +673 -0
- package/server/lib/ui-auth/ui-passkeys.js +545 -0
- package/server/opencode-proxy.test.js +151 -0
- package/server/proxy-headers.js +61 -0
- package/server/proxy-headers.test.js +58 -0
- package/server/sse-routes.test.js +152 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Provider - API
|
|
3
|
+
*
|
|
4
|
+
* API calls for Google quota providers.
|
|
5
|
+
* @module quota/providers/google/api
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const GOOGLE_PRIMARY_ENDPOINT = 'https://cloudcode-pa.googleapis.com';
|
|
9
|
+
|
|
10
|
+
const GOOGLE_ENDPOINTS = [
|
|
11
|
+
'https://daily-cloudcode-pa.sandbox.googleapis.com',
|
|
12
|
+
'https://autopush-cloudcode-pa.sandbox.googleapis.com',
|
|
13
|
+
GOOGLE_PRIMARY_ENDPOINT
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
const GOOGLE_HEADERS = {
|
|
17
|
+
'User-Agent': 'antigravity/1.11.5 windows/amd64',
|
|
18
|
+
'X-Goog-Api-Client': 'google-cloud-sdk vscode_cloudshelleditor/0.1',
|
|
19
|
+
'Client-Metadata':
|
|
20
|
+
'{"ideType":"IDE_UNSPECIFIED","platform":"PLATFORM_UNSPECIFIED","pluginType":"GEMINI"}'
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const refreshGoogleAccessToken = async (refreshToken, clientId, clientSecret) => {
|
|
24
|
+
const response = await fetch('https://oauth2.googleapis.com/token', {
|
|
25
|
+
method: 'POST',
|
|
26
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
27
|
+
body: new URLSearchParams({
|
|
28
|
+
client_id: clientId,
|
|
29
|
+
client_secret: clientSecret,
|
|
30
|
+
refresh_token: refreshToken,
|
|
31
|
+
grant_type: 'refresh_token'
|
|
32
|
+
})
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
if (!response.ok) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const data = await response.json();
|
|
40
|
+
return typeof data?.access_token === 'string' ? data.access_token : null;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const fetchGoogleQuotaBuckets = async (accessToken, projectId) => {
|
|
44
|
+
const body = projectId ? { project: projectId } : {};
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const response = await fetch(`${GOOGLE_PRIMARY_ENDPOINT}/v1internal:retrieveUserQuota`, {
|
|
48
|
+
method: 'POST',
|
|
49
|
+
headers: {
|
|
50
|
+
Authorization: `Bearer ${accessToken}`,
|
|
51
|
+
'Content-Type': 'application/json'
|
|
52
|
+
},
|
|
53
|
+
body: JSON.stringify(body),
|
|
54
|
+
signal: AbortSignal.timeout(15000)
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
if (!response.ok) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return await response.json();
|
|
62
|
+
} catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const fetchGoogleModels = async (accessToken, projectId) => {
|
|
68
|
+
const body = projectId ? { project: projectId } : {};
|
|
69
|
+
|
|
70
|
+
for (const endpoint of GOOGLE_ENDPOINTS) {
|
|
71
|
+
try {
|
|
72
|
+
const response = await fetch(`${endpoint}/v1internal:fetchAvailableModels`, {
|
|
73
|
+
method: 'POST',
|
|
74
|
+
headers: {
|
|
75
|
+
Authorization: `Bearer ${accessToken}`,
|
|
76
|
+
'Content-Type': 'application/json',
|
|
77
|
+
...GOOGLE_HEADERS
|
|
78
|
+
},
|
|
79
|
+
body: JSON.stringify(body),
|
|
80
|
+
signal: AbortSignal.timeout(15000)
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
if (response.ok) {
|
|
84
|
+
return await response.json();
|
|
85
|
+
}
|
|
86
|
+
} catch {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return null;
|
|
92
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Provider - Auth
|
|
3
|
+
*
|
|
4
|
+
* Authentication resolution logic for Google quota providers.
|
|
5
|
+
* @module quota/providers/google/auth
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
ANTIGRAVITY_ACCOUNTS_PATHS,
|
|
10
|
+
readJsonFile,
|
|
11
|
+
getAuthEntry,
|
|
12
|
+
normalizeAuthEntry,
|
|
13
|
+
asObject,
|
|
14
|
+
asNonEmptyString,
|
|
15
|
+
toTimestamp
|
|
16
|
+
} from '../../utils/index.js';
|
|
17
|
+
import { readAuthFile } from '../../../opencode/auth.js';
|
|
18
|
+
import { parseGoogleRefreshToken } from './transforms.js';
|
|
19
|
+
|
|
20
|
+
const ANTIGRAVITY_GOOGLE_CLIENT_ID =
|
|
21
|
+
'1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com';
|
|
22
|
+
const ANTIGRAVITY_GOOGLE_CLIENT_SECRET = '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';
|
|
23
|
+
const GEMINI_GOOGLE_CLIENT_ID =
|
|
24
|
+
'681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com';
|
|
25
|
+
const GEMINI_GOOGLE_CLIENT_SECRET = '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';
|
|
26
|
+
export const DEFAULT_PROJECT_ID = 'rising-fact-p41fc';
|
|
27
|
+
|
|
28
|
+
export const resolveGoogleOAuthClient = (sourceId) => {
|
|
29
|
+
if (sourceId === 'gemini') {
|
|
30
|
+
return {
|
|
31
|
+
clientId: GEMINI_GOOGLE_CLIENT_ID,
|
|
32
|
+
clientSecret: GEMINI_GOOGLE_CLIENT_SECRET
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
clientId: ANTIGRAVITY_GOOGLE_CLIENT_ID,
|
|
38
|
+
clientSecret: ANTIGRAVITY_GOOGLE_CLIENT_SECRET
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const resolveGeminiCliAuth = (auth) => {
|
|
43
|
+
const entry = normalizeAuthEntry(getAuthEntry(auth, ['google', 'google.oauth']));
|
|
44
|
+
const entryObject = asObject(entry);
|
|
45
|
+
if (!entryObject) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const oauthObject = asObject(entryObject.oauth) ?? entryObject;
|
|
50
|
+
const accessToken = asNonEmptyString(oauthObject.access) ?? asNonEmptyString(oauthObject.token);
|
|
51
|
+
const refreshParts = parseGoogleRefreshToken(oauthObject.refresh);
|
|
52
|
+
|
|
53
|
+
if (!accessToken && !refreshParts.refreshToken) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
sourceId: 'gemini',
|
|
59
|
+
sourceLabel: 'Gemini',
|
|
60
|
+
accessToken,
|
|
61
|
+
refreshToken: refreshParts.refreshToken,
|
|
62
|
+
projectId: refreshParts.projectId ?? refreshParts.managedProjectId,
|
|
63
|
+
expires: toTimestamp(oauthObject.expires)
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const resolveAntigravityAuth = () => {
|
|
68
|
+
for (const filePath of ANTIGRAVITY_ACCOUNTS_PATHS) {
|
|
69
|
+
const data = readJsonFile(filePath);
|
|
70
|
+
const accounts = data?.accounts;
|
|
71
|
+
if (Array.isArray(accounts) && accounts.length > 0) {
|
|
72
|
+
const index = typeof data.activeIndex === 'number' ? data.activeIndex : 0;
|
|
73
|
+
const account = accounts[index] ?? accounts[0];
|
|
74
|
+
if (account?.refreshToken) {
|
|
75
|
+
const refreshParts = parseGoogleRefreshToken(account.refreshToken);
|
|
76
|
+
return {
|
|
77
|
+
sourceId: 'antigravity',
|
|
78
|
+
sourceLabel: 'Antigravity',
|
|
79
|
+
refreshToken: refreshParts.refreshToken,
|
|
80
|
+
projectId: asNonEmptyString(account.projectId)
|
|
81
|
+
?? asNonEmptyString(account.managedProjectId)
|
|
82
|
+
?? refreshParts.projectId
|
|
83
|
+
?? refreshParts.managedProjectId,
|
|
84
|
+
email: account.email
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return null;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export const resolveGoogleAuthSources = () => {
|
|
94
|
+
const auth = readAuthFile();
|
|
95
|
+
const sources = [];
|
|
96
|
+
|
|
97
|
+
const geminiAuth = resolveGeminiCliAuth(auth);
|
|
98
|
+
if (geminiAuth) {
|
|
99
|
+
sources.push(geminiAuth);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const antigravityAuth = resolveAntigravityAuth();
|
|
103
|
+
if (antigravityAuth) {
|
|
104
|
+
sources.push(antigravityAuth);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return sources;
|
|
108
|
+
};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Provider
|
|
3
|
+
*
|
|
4
|
+
* Google quota provider implementation.
|
|
5
|
+
* @module quota/providers/google
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
resolveGoogleOAuthClient,
|
|
10
|
+
resolveGeminiCliAuth,
|
|
11
|
+
resolveAntigravityAuth,
|
|
12
|
+
resolveGoogleAuthSources,
|
|
13
|
+
DEFAULT_PROJECT_ID
|
|
14
|
+
} from './auth.js';
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
resolveGoogleWindow,
|
|
18
|
+
transformQuotaBucket,
|
|
19
|
+
transformModelData
|
|
20
|
+
} from './transforms.js';
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
refreshGoogleAccessToken,
|
|
24
|
+
fetchGoogleQuotaBuckets,
|
|
25
|
+
fetchGoogleModels
|
|
26
|
+
} from './api.js';
|
|
27
|
+
|
|
28
|
+
import { buildResult } from '../../utils/index.js';
|
|
29
|
+
import {
|
|
30
|
+
resolveGoogleAuthSources,
|
|
31
|
+
resolveGoogleOAuthClient,
|
|
32
|
+
DEFAULT_PROJECT_ID
|
|
33
|
+
} from './auth.js';
|
|
34
|
+
import { transformQuotaBucket, transformModelData } from './transforms.js';
|
|
35
|
+
import {
|
|
36
|
+
refreshGoogleAccessToken,
|
|
37
|
+
fetchGoogleQuotaBuckets,
|
|
38
|
+
fetchGoogleModels
|
|
39
|
+
} from './api.js';
|
|
40
|
+
|
|
41
|
+
export const fetchGoogleQuota = async () => {
|
|
42
|
+
const authSources = resolveGoogleAuthSources();
|
|
43
|
+
if (!authSources.length) {
|
|
44
|
+
return buildResult({
|
|
45
|
+
providerId: 'google',
|
|
46
|
+
providerName: 'Google',
|
|
47
|
+
ok: false,
|
|
48
|
+
configured: false,
|
|
49
|
+
error: 'Not configured'
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const models = {};
|
|
54
|
+
const sourceErrors = [];
|
|
55
|
+
|
|
56
|
+
for (const source of authSources) {
|
|
57
|
+
const now = Date.now();
|
|
58
|
+
let accessToken = source.accessToken;
|
|
59
|
+
|
|
60
|
+
if (!accessToken || (typeof source.expires === 'number' && source.expires <= now)) {
|
|
61
|
+
if (!source.refreshToken) {
|
|
62
|
+
sourceErrors.push(`${source.sourceLabel}: Missing refresh token`);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const { clientId, clientSecret } = resolveGoogleOAuthClient(source.sourceId);
|
|
66
|
+
accessToken = await refreshGoogleAccessToken(source.refreshToken, clientId, clientSecret);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!accessToken) {
|
|
70
|
+
sourceErrors.push(`${source.sourceLabel}: Failed to refresh OAuth token`);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const projectId = source.projectId ?? DEFAULT_PROJECT_ID;
|
|
75
|
+
let mergedAnyModel = false;
|
|
76
|
+
|
|
77
|
+
if (source.sourceId === 'gemini') {
|
|
78
|
+
const quotaPayload = await fetchGoogleQuotaBuckets(accessToken, projectId);
|
|
79
|
+
const buckets = Array.isArray(quotaPayload?.buckets) ? quotaPayload.buckets : [];
|
|
80
|
+
|
|
81
|
+
for (const bucket of buckets) {
|
|
82
|
+
const transformed = transformQuotaBucket(bucket, source.sourceId);
|
|
83
|
+
if (transformed) {
|
|
84
|
+
Object.assign(models, transformed);
|
|
85
|
+
mergedAnyModel = true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const payload = await fetchGoogleModels(accessToken, projectId);
|
|
91
|
+
if (payload) {
|
|
92
|
+
for (const [modelName, modelData] of Object.entries(payload.models ?? {})) {
|
|
93
|
+
const transformed = transformModelData(modelName, modelData, source.sourceId);
|
|
94
|
+
Object.assign(models, transformed);
|
|
95
|
+
mergedAnyModel = true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!mergedAnyModel) {
|
|
100
|
+
sourceErrors.push(`${source.sourceLabel}: Failed to fetch models`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (!Object.keys(models).length) {
|
|
105
|
+
return buildResult({
|
|
106
|
+
providerId: 'google',
|
|
107
|
+
providerName: 'Google',
|
|
108
|
+
ok: false,
|
|
109
|
+
configured: true,
|
|
110
|
+
error: sourceErrors[0] ?? 'Failed to fetch models'
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return buildResult({
|
|
115
|
+
providerId: 'google',
|
|
116
|
+
providerName: 'Google',
|
|
117
|
+
ok: true,
|
|
118
|
+
configured: true,
|
|
119
|
+
usage: {
|
|
120
|
+
windows: {},
|
|
121
|
+
models: Object.keys(models).length ? models : undefined
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Provider - Transforms
|
|
3
|
+
*
|
|
4
|
+
* Data transformation functions for Google quota responses.
|
|
5
|
+
* @module quota/providers/google/transforms
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
asNonEmptyString,
|
|
10
|
+
toNumber,
|
|
11
|
+
toTimestamp,
|
|
12
|
+
toUsageWindow
|
|
13
|
+
} from '../../utils/index.js';
|
|
14
|
+
|
|
15
|
+
const GOOGLE_FIVE_HOUR_WINDOW_SECONDS = 5 * 60 * 60;
|
|
16
|
+
const GOOGLE_DAILY_WINDOW_SECONDS = 24 * 60 * 60;
|
|
17
|
+
|
|
18
|
+
export const parseGoogleRefreshToken = (rawRefreshToken) => {
|
|
19
|
+
const refreshToken = asNonEmptyString(rawRefreshToken);
|
|
20
|
+
if (!refreshToken) {
|
|
21
|
+
return { refreshToken: null, projectId: null, managedProjectId: null };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const [rawToken = '', rawProject = '', rawManagedProject = ''] = refreshToken.split('|');
|
|
25
|
+
return {
|
|
26
|
+
refreshToken: asNonEmptyString(rawToken),
|
|
27
|
+
projectId: asNonEmptyString(rawProject),
|
|
28
|
+
managedProjectId: asNonEmptyString(rawManagedProject)
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const resolveGoogleWindow = (sourceId, resetAt) => {
|
|
33
|
+
if (sourceId === 'gemini') {
|
|
34
|
+
return { label: 'daily', seconds: GOOGLE_DAILY_WINDOW_SECONDS };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (sourceId === 'antigravity') {
|
|
38
|
+
const remainingSeconds = typeof resetAt === 'number'
|
|
39
|
+
? Math.max(0, Math.round((resetAt - Date.now()) / 1000))
|
|
40
|
+
: null;
|
|
41
|
+
|
|
42
|
+
if (remainingSeconds !== null && remainingSeconds > 10 * 60 * 60) {
|
|
43
|
+
return { label: 'daily', seconds: GOOGLE_DAILY_WINDOW_SECONDS };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return { label: '5h', seconds: GOOGLE_FIVE_HOUR_WINDOW_SECONDS };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return { label: 'daily', seconds: GOOGLE_DAILY_WINDOW_SECONDS };
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const transformQuotaBucket = (bucket, sourceId) => {
|
|
53
|
+
const modelId = asNonEmptyString(bucket?.modelId);
|
|
54
|
+
if (!modelId) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const scopedName = modelId.startsWith(`${sourceId}/`)
|
|
59
|
+
? modelId
|
|
60
|
+
: `${sourceId}/${modelId}`;
|
|
61
|
+
|
|
62
|
+
const remainingFraction = toNumber(bucket?.remainingFraction);
|
|
63
|
+
const remainingPercent = remainingFraction !== null
|
|
64
|
+
? Math.round(remainingFraction * 100)
|
|
65
|
+
: null;
|
|
66
|
+
const usedPercent = remainingPercent !== null ? Math.max(0, 100 - remainingPercent) : null;
|
|
67
|
+
const resetAt = toTimestamp(bucket?.resetTime);
|
|
68
|
+
const window = resolveGoogleWindow(sourceId, resetAt);
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
[scopedName]: {
|
|
72
|
+
windows: {
|
|
73
|
+
[window.label]: toUsageWindow({
|
|
74
|
+
usedPercent,
|
|
75
|
+
windowSeconds: window.seconds,
|
|
76
|
+
resetAt
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const transformModelData = (modelName, modelData, sourceId) => {
|
|
84
|
+
const scopedName = modelName.startsWith(`${sourceId}/`)
|
|
85
|
+
? modelName
|
|
86
|
+
: `${sourceId}/${modelName}`;
|
|
87
|
+
|
|
88
|
+
const remainingFraction = modelData?.quotaInfo?.remainingFraction;
|
|
89
|
+
const remainingPercent = typeof remainingFraction === 'number'
|
|
90
|
+
? Math.round(remainingFraction * 100)
|
|
91
|
+
: null;
|
|
92
|
+
const usedPercent = remainingPercent !== null ? Math.max(0, 100 - remainingPercent) : null;
|
|
93
|
+
const resetAt = modelData?.quotaInfo?.resetTime
|
|
94
|
+
? new Date(modelData.quotaInfo.resetTime).getTime()
|
|
95
|
+
: null;
|
|
96
|
+
const window = resolveGoogleWindow(sourceId, resetAt);
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
[scopedName]: {
|
|
100
|
+
windows: {
|
|
101
|
+
[window.label]: toUsageWindow({
|
|
102
|
+
usedPercent,
|
|
103
|
+
windowSeconds: window.seconds,
|
|
104
|
+
resetAt
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quota Providers Registry
|
|
3
|
+
*
|
|
4
|
+
* Implements quota fetching for various AI providers using a registry pattern.
|
|
5
|
+
* @module quota/providers
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { buildResult } from '../utils/index.js';
|
|
9
|
+
|
|
10
|
+
import * as claude from './claude.js';
|
|
11
|
+
import * as codex from './codex.js';
|
|
12
|
+
import * as copilot from './copilot.js';
|
|
13
|
+
import * as google from './google/index.js';
|
|
14
|
+
import * as kimi from './kimi.js';
|
|
15
|
+
import * as nanogpt from './nanogpt.js';
|
|
16
|
+
import * as openai from './openai.js';
|
|
17
|
+
import * as openrouter from './openrouter.js';
|
|
18
|
+
import * as zai from './zai.js';
|
|
19
|
+
import * as zhipuaiCodingPlan from './zhipuai-coding-plan.js';
|
|
20
|
+
import * as minimaxCodingPlan from './minimax-coding-plan.js';
|
|
21
|
+
import * as minimaxCnCodingPlan from './minimax-cn-coding-plan.js';
|
|
22
|
+
import * as ollamaCloud from './ollama-cloud.js';
|
|
23
|
+
import * as zhipuai from './zhipuai.js';
|
|
24
|
+
|
|
25
|
+
const registry = {
|
|
26
|
+
claude: {
|
|
27
|
+
providerId: claude.providerId,
|
|
28
|
+
providerName: claude.providerName,
|
|
29
|
+
isConfigured: claude.isConfigured,
|
|
30
|
+
fetchQuota: claude.fetchQuota
|
|
31
|
+
},
|
|
32
|
+
codex: {
|
|
33
|
+
providerId: codex.providerId,
|
|
34
|
+
providerName: codex.providerName,
|
|
35
|
+
isConfigured: codex.isConfigured,
|
|
36
|
+
fetchQuota: codex.fetchQuota
|
|
37
|
+
},
|
|
38
|
+
google: {
|
|
39
|
+
providerId: 'google',
|
|
40
|
+
providerName: 'Google',
|
|
41
|
+
isConfigured: () => google.resolveGoogleAuthSources().length > 0,
|
|
42
|
+
fetchQuota: google.fetchGoogleQuota
|
|
43
|
+
},
|
|
44
|
+
'zai-coding-plan': {
|
|
45
|
+
providerId: zai.providerId,
|
|
46
|
+
providerName: zai.providerName,
|
|
47
|
+
isConfigured: zai.isConfigured,
|
|
48
|
+
fetchQuota: zai.fetchQuota
|
|
49
|
+
},
|
|
50
|
+
'zhipuai-coding-plan': {
|
|
51
|
+
providerId: zhipuaiCodingPlan.providerId,
|
|
52
|
+
providerName: zhipuaiCodingPlan.providerName,
|
|
53
|
+
isConfigured: zhipuaiCodingPlan.isConfigured,
|
|
54
|
+
fetchQuota: zhipuaiCodingPlan.fetchQuota
|
|
55
|
+
},
|
|
56
|
+
'kimi-for-coding': {
|
|
57
|
+
providerId: kimi.providerId,
|
|
58
|
+
providerName: kimi.providerName,
|
|
59
|
+
isConfigured: kimi.isConfigured,
|
|
60
|
+
fetchQuota: kimi.fetchQuota
|
|
61
|
+
},
|
|
62
|
+
openrouter: {
|
|
63
|
+
providerId: openrouter.providerId,
|
|
64
|
+
providerName: openrouter.providerName,
|
|
65
|
+
isConfigured: openrouter.isConfigured,
|
|
66
|
+
fetchQuota: openrouter.fetchQuota
|
|
67
|
+
},
|
|
68
|
+
'nano-gpt': {
|
|
69
|
+
providerId: nanogpt.providerId,
|
|
70
|
+
providerName: nanogpt.providerName,
|
|
71
|
+
isConfigured: nanogpt.isConfigured,
|
|
72
|
+
fetchQuota: nanogpt.fetchQuota
|
|
73
|
+
},
|
|
74
|
+
'github-copilot': {
|
|
75
|
+
providerId: copilot.providerId,
|
|
76
|
+
providerName: copilot.providerName,
|
|
77
|
+
isConfigured: copilot.isConfigured,
|
|
78
|
+
fetchQuota: copilot.fetchQuota
|
|
79
|
+
},
|
|
80
|
+
'github-copilot-addon': {
|
|
81
|
+
providerId: copilot.providerIdAddon,
|
|
82
|
+
providerName: copilot.providerNameAddon,
|
|
83
|
+
isConfigured: copilot.isConfigured,
|
|
84
|
+
fetchQuota: copilot.fetchQuotaAddon
|
|
85
|
+
},
|
|
86
|
+
'minimax-coding-plan': {
|
|
87
|
+
providerId: minimaxCodingPlan.providerId,
|
|
88
|
+
providerName: minimaxCodingPlan.providerName,
|
|
89
|
+
isConfigured: minimaxCodingPlan.isConfigured,
|
|
90
|
+
fetchQuota: minimaxCodingPlan.fetchQuota
|
|
91
|
+
},
|
|
92
|
+
'minimax-cn-coding-plan': {
|
|
93
|
+
providerId: minimaxCnCodingPlan.providerId,
|
|
94
|
+
providerName: minimaxCnCodingPlan.providerName,
|
|
95
|
+
isConfigured: minimaxCnCodingPlan.isConfigured,
|
|
96
|
+
fetchQuota: minimaxCnCodingPlan.fetchQuota
|
|
97
|
+
},
|
|
98
|
+
'ollama-cloud': {
|
|
99
|
+
providerId: ollamaCloud.providerId,
|
|
100
|
+
providerName: ollamaCloud.providerName,
|
|
101
|
+
isConfigured: ollamaCloud.isConfigured,
|
|
102
|
+
fetchQuota: ollamaCloud.fetchQuota
|
|
103
|
+
},
|
|
104
|
+
'zhipuai-coding-plan': {
|
|
105
|
+
providerId: zhipuai.providerId,
|
|
106
|
+
providerName: zhipuai.providerName,
|
|
107
|
+
isConfigured: zhipuai.isConfigured,
|
|
108
|
+
fetchQuota: zhipuai.fetchQuota
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export const listConfiguredQuotaProviders = () => {
|
|
113
|
+
const configured = [];
|
|
114
|
+
|
|
115
|
+
for (const [id, provider] of Object.entries(registry)) {
|
|
116
|
+
try {
|
|
117
|
+
if (provider.isConfigured()) {
|
|
118
|
+
configured.push(id);
|
|
119
|
+
}
|
|
120
|
+
} catch {
|
|
121
|
+
// Ignore provider-specific config errors in list API.
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return configured;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export const fetchQuotaForProvider = async (providerId) => {
|
|
129
|
+
const provider = registry[providerId];
|
|
130
|
+
|
|
131
|
+
if (!provider) {
|
|
132
|
+
return buildResult({
|
|
133
|
+
providerId,
|
|
134
|
+
providerName: providerId,
|
|
135
|
+
ok: false,
|
|
136
|
+
configured: false,
|
|
137
|
+
error: 'Unsupported provider'
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
return await provider.fetchQuota();
|
|
143
|
+
} catch (error) {
|
|
144
|
+
return buildResult({
|
|
145
|
+
providerId: provider.providerId,
|
|
146
|
+
providerName: provider.providerName,
|
|
147
|
+
ok: false,
|
|
148
|
+
configured: true,
|
|
149
|
+
error: error instanceof Error ? error.message : 'Request failed'
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
export const fetchClaudeQuota = claude.fetchQuota;
|
|
155
|
+
export const fetchOpenaiQuota = openai.fetchQuota;
|
|
156
|
+
export const fetchGoogleQuota = google.fetchGoogleQuota;
|
|
157
|
+
export const fetchCodexQuota = codex.fetchQuota;
|
|
158
|
+
export const fetchCopilotQuota = copilot.fetchQuota;
|
|
159
|
+
export const fetchCopilotAddonQuota = copilot.fetchQuotaAddon;
|
|
160
|
+
export const fetchKimiQuota = kimi.fetchQuota;
|
|
161
|
+
export const fetchOpenRouterQuota = openrouter.fetchQuota;
|
|
162
|
+
export const fetchZaiQuota = zai.fetchQuota;
|
|
163
|
+
export const fetchZhipuaiCodingPlanQuota = zhipuaiCodingPlan.fetchQuota;
|
|
164
|
+
export const fetchNanoGptQuota = nanogpt.fetchQuota;
|
|
165
|
+
export const fetchMinimaxCodingPlanQuota = minimaxCodingPlan.fetchQuota;
|
|
166
|
+
export const fetchMinimaxCnCodingPlanQuota = minimaxCnCodingPlan.fetchQuota;
|
|
167
|
+
export const fetchOllamaCloudQuota = ollamaCloud.fetchQuota;
|
|
168
|
+
export const fetchZhipuaiQuota = zhipuai.fetchQuota;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quota Provider Interface
|
|
3
|
+
*
|
|
4
|
+
* Defines the contract for implementing quota providers.
|
|
5
|
+
* @module quota/providers
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {Object} UsageWindow
|
|
10
|
+
* @property {number|null} usedPercent - Percentage of usage (0-100)
|
|
11
|
+
* @property {number|null} remainingPercent - Percentage remaining (0-100)
|
|
12
|
+
* @property {number|null} windowSeconds - Window duration in seconds
|
|
13
|
+
* @property {number|null} resetAfterSeconds - Seconds until reset
|
|
14
|
+
* @property {number|null} resetAt - Unix timestamp when quota resets
|
|
15
|
+
* @property {string|null} resetAtFormatted - Human-readable reset time
|
|
16
|
+
* @property {string|null} resetAfterFormatted - Human-readable time until reset
|
|
17
|
+
* @property {string|null} valueLabel - Optional label for display (e.g., "$10.00 remaining")
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {Object} ProviderUsage
|
|
22
|
+
* @property {Object.<string, UsageWindow>} windows - Usage windows by key (e.g., '5h', '7d', 'daily')
|
|
23
|
+
* @property {Object.<string, Object>} [models] - Model-specific usage (provider-specific)
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @typedef {Object} QuotaProviderResult
|
|
28
|
+
* @property {string} providerId - Unique identifier for the provider
|
|
29
|
+
* @property {string} providerName - Display name for the provider
|
|
30
|
+
* @property {boolean} ok - Whether the fetch was successful
|
|
31
|
+
* @property {boolean} configured - Whether the provider is configured
|
|
32
|
+
* @property {ProviderUsage|null} usage - Usage data if successful
|
|
33
|
+
* @property {string|null} [error] - Error message if not successful
|
|
34
|
+
* @property {number} fetchedAt - Unix timestamp when the result was fetched
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @typedef {Function} ProviderQuotaFetcher
|
|
39
|
+
* @returns {Promise<QuotaProviderResult>}
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @typedef {Function} ProviderConfigurationChecker
|
|
44
|
+
* @param {Object.<string, unknown>} [auth]
|
|
45
|
+
* @returns {boolean}
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @typedef {Object} QuotaProvider
|
|
50
|
+
* @property {string} providerId
|
|
51
|
+
* @property {string} providerName
|
|
52
|
+
* @property {string[]} aliases
|
|
53
|
+
* @property {ProviderConfigurationChecker} isConfigured
|
|
54
|
+
* @property {ProviderQuotaFetcher} fetchQuota
|
|
55
|
+
*/
|