@prometheus-ai/ai 0.5.4 → 0.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/types/auth-broker/remote-store.d.ts +2 -1
- package/dist/types/auth-broker/wire-schemas.d.ts +4 -1
- package/dist/types/auth-gateway/server.d.ts +19 -0
- package/dist/types/auth-gateway/types.d.ts +9 -3
- package/dist/types/auth-retry.d.ts +119 -0
- package/dist/types/auth-storage.d.ts +217 -8
- package/dist/types/errors.d.ts +24 -0
- package/dist/types/index.d.ts +5 -9
- package/dist/types/provider-details.d.ts +1 -1
- package/dist/types/providers/amazon-bedrock.d.ts +12 -6
- package/dist/types/providers/anthropic-client.d.ts +10 -3
- package/dist/types/providers/anthropic-messages-server-schema.d.ts +2 -2
- package/dist/types/providers/anthropic-messages-server.d.ts +3 -3
- package/dist/types/providers/anthropic-wire.d.ts +3 -3
- package/dist/types/providers/anthropic.d.ts +41 -34
- package/dist/types/providers/aws-credentials.d.ts +8 -0
- package/dist/types/providers/azure-openai-responses.d.ts +1 -0
- package/dist/types/providers/google-gemini-cli.d.ts +22 -1
- package/dist/types/providers/google-shared.d.ts +22 -0
- package/dist/types/providers/google-types.d.ts +13 -1
- package/dist/types/providers/mock.d.ts +8 -3
- package/dist/types/providers/ollama.d.ts +6 -0
- package/dist/types/providers/openai-chat-server-schema.d.ts +6 -3
- package/dist/types/providers/openai-chat-server.d.ts +3 -3
- package/dist/types/providers/openai-chat-wire.d.ts +644 -0
- package/dist/types/providers/openai-codex/request-transformer.d.ts +8 -0
- package/dist/types/providers/openai-codex/response-handler.d.ts +9 -0
- package/dist/types/providers/openai-codex-responses.d.ts +31 -2
- package/dist/types/providers/openai-completions-compat.d.ts +2 -25
- package/dist/types/providers/openai-completions.d.ts +2 -10
- package/dist/types/providers/openai-responses-server-schema.d.ts +4 -4
- package/dist/types/providers/openai-responses-server.d.ts +2 -2
- package/dist/types/providers/openai-responses-shared.d.ts +49 -9
- package/dist/types/providers/openai-responses-wire.d.ts +6065 -0
- package/dist/types/providers/openai-responses.d.ts +13 -4
- package/dist/types/providers/prometheus-native-client.d.ts +9 -0
- package/dist/types/providers/prometheus-native-server.d.ts +4 -3
- package/dist/types/providers/transform-messages.d.ts +1 -2
- package/dist/types/rate-limit-utils.d.ts +3 -2
- package/dist/types/registry/aimlapi.d.ts +4 -0
- package/dist/types/registry/alibaba-coding-plan.d.ts +7 -0
- package/dist/types/registry/amazon-bedrock.d.ts +5 -0
- package/dist/types/registry/anthropic.d.ts +10 -0
- package/dist/types/{utils/oauth → registry}/api-key-login.d.ts +8 -2
- package/dist/types/{utils/oauth → registry}/api-key-validation.d.ts +15 -0
- package/dist/types/registry/cerebras.d.ts +7 -0
- package/dist/types/registry/cloudflare-ai-gateway.d.ts +13 -0
- package/dist/types/registry/cursor.d.ts +7 -0
- package/dist/types/registry/deepseek.d.ts +8 -0
- package/dist/types/registry/derived.d.ts +5 -0
- package/dist/types/registry/firepass.d.ts +16 -0
- package/dist/types/registry/fireworks.d.ts +7 -0
- package/dist/types/registry/github-copilot.d.ts +7 -0
- package/dist/types/registry/gitlab-duo.d.ts +9 -0
- package/dist/types/registry/google-antigravity.d.ts +9 -0
- package/dist/types/registry/google-gemini-cli.d.ts +9 -0
- package/dist/types/registry/google-vertex.d.ts +5 -0
- package/dist/types/registry/google.d.ts +4 -0
- package/dist/types/registry/groq.d.ts +4 -0
- package/dist/types/registry/huggingface.d.ts +7 -0
- package/dist/types/registry/index.d.ts +4 -0
- package/dist/types/registry/kagi.d.ts +14 -0
- package/dist/types/registry/kilo.d.ts +7 -0
- package/dist/types/registry/kimi-code.d.ts +7 -0
- package/dist/types/registry/litellm.d.ts +13 -0
- package/dist/types/registry/lm-studio.d.ts +8 -0
- package/dist/types/registry/minimax-code-cn.d.ts +6 -0
- package/dist/types/registry/minimax-code.d.ts +6 -0
- package/dist/types/registry/minimax.d.ts +4 -0
- package/dist/types/registry/mistral.d.ts +4 -0
- package/dist/types/registry/moonshot.d.ts +7 -0
- package/dist/types/registry/nanogpt.d.ts +7 -0
- package/dist/types/registry/nvidia.d.ts +7 -0
- package/dist/types/registry/oauth/__tests__/xai-oauth.test.d.ts +1 -0
- package/dist/types/{utils → registry}/oauth/anthropic.d.ts +2 -1
- package/dist/types/{utils → registry}/oauth/github-copilot.d.ts +15 -23
- package/dist/types/{utils → registry}/oauth/index.d.ts +1 -0
- package/dist/types/{utils → registry}/oauth/minimax-code.d.ts +5 -5
- package/dist/types/{utils → registry}/oauth/types.d.ts +6 -1
- package/dist/types/{utils → registry}/oauth/xai-oauth.d.ts +2 -1
- package/dist/types/registry/ollama-cloud.d.ts +7 -0
- package/dist/types/registry/ollama.d.ts +12 -0
- package/dist/types/registry/openai-codex-device.d.ts +8 -0
- package/dist/types/registry/openai-codex.d.ts +9 -0
- package/dist/types/registry/openai.d.ts +4 -0
- package/dist/types/registry/opencode-go.d.ts +6 -0
- package/dist/types/registry/opencode-zen.d.ts +6 -0
- package/dist/types/registry/openrouter.d.ts +13 -0
- package/dist/types/registry/parallel.d.ts +14 -0
- package/dist/types/registry/perplexity.d.ts +7 -0
- package/dist/types/registry/qianfan.d.ts +7 -0
- package/dist/types/registry/qwen-portal.d.ts +7 -0
- package/dist/types/registry/registry.d.ts +272 -0
- package/dist/types/registry/synthetic.d.ts +6 -0
- package/dist/types/registry/tavily.d.ts +14 -0
- package/dist/types/registry/together.d.ts +6 -0
- package/dist/types/registry/types.d.ts +51 -0
- package/dist/types/registry/venice.d.ts +13 -0
- package/dist/types/registry/vercel-ai-gateway.d.ts +7 -0
- package/dist/types/registry/vllm.d.ts +7 -0
- package/dist/types/registry/wafer-pass.d.ts +6 -0
- package/dist/types/registry/wafer-serverless.d.ts +6 -0
- package/dist/types/registry/xai-oauth.d.ts +7 -0
- package/dist/types/registry/xai.d.ts +4 -0
- package/dist/types/registry/xiaomi-token-plan-ams.d.ts +6 -0
- package/dist/types/registry/xiaomi-token-plan-cn.d.ts +6 -0
- package/dist/types/registry/xiaomi-token-plan-sgp.d.ts +6 -0
- package/dist/types/registry/xiaomi.d.ts +6 -0
- package/dist/types/registry/zai.d.ts +7 -0
- package/dist/types/registry/zenmux.d.ts +7 -0
- package/dist/types/registry/zhipu-coding-plan.d.ts +7 -0
- package/dist/types/stream.d.ts +9 -1
- package/dist/types/types.d.ts +56 -295
- package/dist/types/usage/google-antigravity.d.ts +15 -1
- package/dist/types/usage/openai-codex-reset.d.ts +79 -0
- package/dist/types/usage/openai-codex.d.ts +1 -0
- package/dist/types/usage.d.ts +77 -4
- package/dist/types/utils/abort.d.ts +6 -0
- package/dist/types/utils/event-stream.d.ts +2 -0
- package/dist/types/utils/http-inspector.d.ts +0 -1
- package/dist/types/utils/idle-iterator.d.ts +35 -0
- package/dist/types/utils/openai-http.d.ts +58 -0
- package/dist/types/utils/request-debug.d.ts +3 -0
- package/dist/types/utils/retry-after.d.ts +1 -0
- package/dist/types/utils/schema/fields.d.ts +5 -0
- package/dist/types/utils/schema/json-schema-validator.d.ts +8 -0
- package/dist/types/utils/schema/stamps.d.ts +7 -15
- package/dist/types/utils/sse-debug.d.ts +0 -5
- package/dist/types/utils/stream-markup-healing.d.ts +2 -0
- package/dist/types/utils.d.ts +1 -5
- package/package.json +17 -29
- package/src/auth-broker/remote-store.ts +10 -1
- package/src/auth-broker/snapshot-cache.ts +1 -1
- package/src/auth-broker/wire-schemas.ts +1 -1
- package/src/auth-gateway/http.ts +1 -1
- package/src/auth-gateway/server.ts +95 -30
- package/src/auth-gateway/types.ts +10 -2
- package/src/auth-retry.ts +238 -0
- package/src/auth-storage.ts +935 -430
- package/src/errors.ts +32 -0
- package/src/index.ts +9 -14
- package/src/provider-details.ts +1 -1
- package/src/providers/__tests__/google-auth.test.ts +144 -0
- package/src/providers/amazon-bedrock.ts +70 -40
- package/src/providers/anthropic-client.ts +15 -13
- package/src/providers/anthropic-messages-server-schema.ts +17 -7
- package/src/providers/anthropic-messages-server.ts +88 -20
- package/src/providers/anthropic-wire.ts +4 -3
- package/src/providers/anthropic.ts +1234 -621
- package/src/providers/aws-credentials.ts +47 -5
- package/src/providers/aws-eventstream.ts +5 -0
- package/src/providers/azure-openai-responses.ts +117 -67
- package/src/providers/cursor.ts +30 -30
- package/src/providers/github-copilot-headers.ts +1 -1
- package/src/providers/gitlab-duo.ts +36 -29
- package/src/providers/google-auth.ts +71 -8
- package/src/providers/google-gemini-cli.ts +118 -22
- package/src/providers/google-shared.ts +163 -43
- package/src/providers/google-types.ts +10 -1
- package/src/providers/kimi.ts +1 -1
- package/src/providers/mock.ts +11 -3
- package/src/providers/ollama.ts +64 -7
- package/src/providers/openai-anthropic-shim.ts +17 -8
- package/src/providers/openai-chat-server-schema.ts +9 -3
- package/src/providers/openai-chat-server.ts +82 -16
- package/src/providers/openai-chat-wire.ts +847 -0
- package/src/providers/openai-codex/request-transformer.ts +129 -34
- package/src/providers/openai-codex/response-handler.ts +22 -1
- package/src/providers/openai-codex-responses.ts +699 -247
- package/src/providers/openai-completions-compat.ts +8 -308
- package/src/providers/openai-completions.ts +416 -267
- package/src/providers/openai-responses-server-schema.ts +15 -9
- package/src/providers/openai-responses-server.ts +162 -114
- package/src/providers/openai-responses-shared.ts +320 -82
- package/src/providers/openai-responses-wire.ts +6391 -0
- package/src/providers/openai-responses.ts +382 -176
- package/src/providers/prometheus-native-client.ts +27 -11
- package/src/providers/prometheus-native-server.ts +44 -17
- package/src/providers/transform-messages.ts +311 -120
- package/src/providers/vision-guard.ts +5 -3
- package/src/rate-limit-utils.ts +13 -3
- package/src/registry/aimlapi.ts +6 -0
- package/src/{utils/oauth → registry}/alibaba-coding-plan.ts +8 -18
- package/src/registry/amazon-bedrock.ts +22 -0
- package/src/registry/anthropic.ts +26 -0
- package/src/{utils/oauth → registry}/api-key-login.ts +25 -3
- package/src/{utils/oauth → registry}/api-key-validation.ts +62 -2
- package/src/{utils/oauth → registry}/cerebras.ts +8 -1
- package/src/{utils/oauth → registry}/cloudflare-ai-gateway.ts +8 -12
- package/src/registry/cursor.ts +20 -0
- package/src/{utils/oauth → registry}/deepseek.ts +9 -17
- package/src/registry/derived.ts +9 -0
- package/src/{utils/oauth → registry}/firepass.ts +10 -2
- package/src/{utils/oauth → registry}/fireworks.ts +8 -1
- package/src/registry/github-copilot.ts +22 -0
- package/src/registry/gitlab-duo.ts +19 -0
- package/src/registry/google-antigravity.ts +21 -0
- package/src/registry/google-gemini-cli.ts +21 -0
- package/src/registry/google-vertex.ts +38 -0
- package/src/registry/google.ts +6 -0
- package/src/registry/groq.ts +6 -0
- package/src/{utils/oauth → registry}/huggingface.ts +8 -19
- package/src/registry/index.ts +4 -0
- package/src/{utils/oauth → registry}/kagi.ts +9 -11
- package/src/{utils/oauth → registry}/kilo.ts +11 -6
- package/src/registry/kimi-code.ts +17 -0
- package/src/{utils/oauth → registry}/litellm.ts +8 -12
- package/src/{utils/oauth → registry}/lm-studio.ts +9 -17
- package/src/registry/minimax-code-cn.ts +12 -0
- package/src/registry/minimax-code.ts +12 -0
- package/src/registry/minimax.ts +6 -0
- package/src/registry/mistral.ts +6 -0
- package/src/{utils/oauth → registry}/moonshot.ts +8 -9
- package/src/{utils/oauth → registry}/nanogpt.ts +8 -1
- package/src/{utils/oauth → registry}/nvidia.ts +8 -18
- package/src/{utils → registry}/oauth/__tests__/xai-oauth.test.ts +4 -7
- package/src/{utils → registry}/oauth/anthropic.ts +38 -17
- package/src/{utils → registry}/oauth/github-copilot.ts +79 -115
- package/src/registry/oauth/gitlab-duo.ts +198 -0
- package/src/{utils → registry}/oauth/google-antigravity.ts +1 -4
- package/src/{utils → registry}/oauth/google-gemini-cli.ts +1 -4
- package/src/registry/oauth/index.ts +164 -0
- package/src/{utils → registry}/oauth/minimax-code.ts +16 -14
- package/src/{utils → registry}/oauth/types.ts +7 -51
- package/src/{utils → registry}/oauth/wafer.ts +1 -1
- package/src/{utils → registry}/oauth/xai-oauth.ts +16 -8
- package/src/{utils → registry}/oauth/xiaomi.ts +9 -4
- package/src/{utils/oauth → registry}/ollama-cloud.ts +8 -1
- package/src/{utils/oauth → registry}/ollama.ts +8 -13
- package/src/registry/openai-codex-device.ts +18 -0
- package/src/registry/openai-codex.ts +19 -0
- package/src/registry/openai.ts +6 -0
- package/src/registry/opencode-go.ts +12 -0
- package/src/registry/opencode-zen.ts +12 -0
- package/src/{utils/oauth → registry}/openrouter.ts +10 -2
- package/src/{utils/oauth → registry}/parallel.ts +9 -11
- package/src/registry/perplexity.ts +13 -0
- package/src/{utils/oauth → registry}/qianfan.ts +8 -17
- package/src/{utils/oauth → registry}/qwen-portal.ts +8 -19
- package/src/registry/registry.ts +149 -0
- package/src/{utils/oauth → registry}/synthetic.ts +7 -1
- package/src/{utils/oauth → registry}/tavily.ts +10 -12
- package/src/{utils/oauth → registry}/together.ts +7 -1
- package/src/registry/types.ts +56 -0
- package/src/{utils/oauth → registry}/venice.ts +8 -12
- package/src/{utils/oauth → registry}/vercel-ai-gateway.ts +8 -18
- package/src/{utils/oauth → registry}/vllm.ts +9 -16
- package/src/registry/wafer-pass.ts +12 -0
- package/src/registry/wafer-serverless.ts +12 -0
- package/src/registry/xai-oauth.ts +17 -0
- package/src/registry/xai.ts +6 -0
- package/src/registry/xiaomi-token-plan-ams.ts +12 -0
- package/src/registry/xiaomi-token-plan-cn.ts +12 -0
- package/src/registry/xiaomi-token-plan-sgp.ts +12 -0
- package/src/registry/xiaomi.ts +12 -0
- package/src/{utils/oauth → registry}/zai.ts +10 -22
- package/src/{utils/oauth → registry}/zenmux.ts +8 -1
- package/src/{utils/oauth/zhipu.ts → registry/zhipu-coding-plan.ts} +9 -21
- package/src/stream.ts +229 -199
- package/src/types.ts +63 -384
- package/src/usage/claude.ts +4 -2
- package/src/usage/github-copilot.ts +4 -2
- package/src/usage/google-antigravity.ts +196 -28
- package/src/usage/kimi.ts +1 -1
- package/src/usage/minimax-code.ts +5 -6
- package/src/usage/openai-codex-reset.ts +174 -0
- package/src/usage/openai-codex.ts +19 -2
- package/src/usage/zai.ts +2 -1
- package/src/usage.ts +93 -4
- package/src/utils/abort.ts +14 -0
- package/src/utils/event-stream.ts +17 -0
- package/src/utils/http-inspector.ts +4 -12
- package/src/utils/idle-iterator.ts +250 -79
- package/src/utils/openai-http.ts +157 -0
- package/src/utils/request-debug.ts +67 -19
- package/src/utils/retry-after.ts +1 -1
- package/src/utils/retry.ts +23 -2
- package/src/utils/schema/CONSTRAINTS.md +4 -2
- package/src/utils/schema/fields.ts +16 -0
- package/src/utils/schema/json-schema-validator.ts +19 -1
- package/src/utils/schema/normalize.ts +80 -8
- package/src/utils/schema/stamps.ts +22 -10
- package/src/utils/schema/wire.ts +2 -2
- package/src/utils/sse-debug.ts +0 -271
- package/src/utils/stream-markup-healing.ts +50 -8
- package/src/utils/validation.ts +49 -13
- package/src/utils.ts +2 -26
- package/dist/types/model-cache.d.ts +0 -17
- package/dist/types/model-manager.d.ts +0 -64
- package/dist/types/model-thinking.d.ts +0 -100
- package/dist/types/models.d.ts +0 -12
- package/dist/types/provider-models/bundled-references.d.ts +0 -4
- package/dist/types/provider-models/descriptors.d.ts +0 -50
- package/dist/types/provider-models/google.d.ts +0 -24
- package/dist/types/provider-models/index.d.ts +0 -5
- package/dist/types/provider-models/ollama.d.ts +0 -7
- package/dist/types/provider-models/openai-compat.d.ts +0 -323
- package/dist/types/provider-models/special.d.ts +0 -16
- package/dist/types/utils/discovery/antigravity.d.ts +0 -61
- package/dist/types/utils/discovery/codex.d.ts +0 -38
- package/dist/types/utils/discovery/cursor.d.ts +0 -23
- package/dist/types/utils/discovery/gemini.d.ts +0 -25
- package/dist/types/utils/discovery/index.d.ts +0 -4
- package/dist/types/utils/discovery/openai-compatible.d.ts +0 -72
- package/dist/types/utils/oauth/alibaba-coding-plan.d.ts +0 -18
- package/dist/types/utils/oauth/cerebras.d.ts +0 -1
- package/dist/types/utils/oauth/cloudflare-ai-gateway.d.ts +0 -18
- package/dist/types/utils/oauth/deepseek.d.ts +0 -10
- package/dist/types/utils/oauth/firepass.d.ts +0 -1
- package/dist/types/utils/oauth/fireworks.d.ts +0 -1
- package/dist/types/utils/oauth/huggingface.d.ts +0 -19
- package/dist/types/utils/oauth/kagi.d.ts +0 -17
- package/dist/types/utils/oauth/kilo.d.ts +0 -5
- package/dist/types/utils/oauth/litellm.d.ts +0 -18
- package/dist/types/utils/oauth/lm-studio.d.ts +0 -17
- package/dist/types/utils/oauth/moonshot.d.ts +0 -1
- package/dist/types/utils/oauth/nanogpt.d.ts +0 -1
- package/dist/types/utils/oauth/nvidia.d.ts +0 -18
- package/dist/types/utils/oauth/ollama-cloud.d.ts +0 -2
- package/dist/types/utils/oauth/ollama.d.ts +0 -18
- package/dist/types/utils/oauth/openrouter.d.ts +0 -1
- package/dist/types/utils/oauth/parallel.d.ts +0 -17
- package/dist/types/utils/oauth/qianfan.d.ts +0 -17
- package/dist/types/utils/oauth/qwen-portal.d.ts +0 -19
- package/dist/types/utils/oauth/synthetic.d.ts +0 -1
- package/dist/types/utils/oauth/tavily.d.ts +0 -17
- package/dist/types/utils/oauth/together.d.ts +0 -1
- package/dist/types/utils/oauth/venice.d.ts +0 -18
- package/dist/types/utils/oauth/vercel-ai-gateway.d.ts +0 -18
- package/dist/types/utils/oauth/vllm.d.ts +0 -16
- package/dist/types/utils/oauth/zai.d.ts +0 -18
- package/dist/types/utils/oauth/zenmux.d.ts +0 -1
- package/dist/types/utils/oauth/zhipu.d.ts +0 -18
- package/src/model-cache.ts +0 -129
- package/src/model-manager.ts +0 -469
- package/src/model-thinking.ts +0 -756
- package/src/models.json +0 -60287
- package/src/models.json.d.ts +0 -9
- package/src/models.ts +0 -56
- package/src/provider-models/bundled-references.ts +0 -38
- package/src/provider-models/descriptors.ts +0 -364
- package/src/provider-models/google.ts +0 -88
- package/src/provider-models/index.ts +0 -5
- package/src/provider-models/ollama.ts +0 -153
- package/src/provider-models/openai-compat.ts +0 -2904
- package/src/provider-models/special.ts +0 -67
- package/src/utils/discovery/antigravity.ts +0 -261
- package/src/utils/discovery/codex.ts +0 -371
- package/src/utils/discovery/cursor.ts +0 -306
- package/src/utils/discovery/gemini.ts +0 -248
- package/src/utils/discovery/index.ts +0 -4
- package/src/utils/discovery/openai-compatible.ts +0 -224
- package/src/utils/oauth/gitlab-duo.ts +0 -123
- package/src/utils/oauth/index.ts +0 -502
- /package/dist/types/{utils/oauth/__tests__/xai-oauth.test.d.ts → providers/__tests__/google-auth.test.d.ts} +0 -0
- /package/dist/types/{utils → registry}/oauth/callback-server.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/cursor.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/gitlab-duo.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/google-antigravity.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/google-gemini-cli.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/google-oauth-shared.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/kimi.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/openai-codex.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/opencode.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/perplexity.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/pkce.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/wafer.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/xiaomi.d.ts +0 -0
- /package/src/{utils → registry}/oauth/callback-server.ts +0 -0
- /package/src/{utils → registry}/oauth/cursor.ts +0 -0
- /package/src/{utils → registry}/oauth/google-oauth-shared.ts +0 -0
- /package/src/{utils → registry}/oauth/kimi.ts +0 -0
- /package/src/{utils → registry}/oauth/oauth.html +0 -0
- /package/src/{utils → registry}/oauth/openai-codex.ts +0 -0
- /package/src/{utils → registry}/oauth/opencode.ts +0 -0
- /package/src/{utils → registry}/oauth/perplexity.ts +0 -0
- /package/src/{utils → registry}/oauth/pkce.ts +0 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { getAntigravityUserAgent } from "
|
|
1
|
+
import { getAntigravityUserAgent } from "@prometheus-ai/catalog/wire/gemini-headers";
|
|
2
2
|
import type {
|
|
3
|
+
CredentialRankingContext,
|
|
4
|
+
CredentialRankingStrategy,
|
|
3
5
|
UsageAmount,
|
|
4
6
|
UsageFetchContext,
|
|
5
7
|
UsageFetchParams,
|
|
@@ -18,6 +20,8 @@ interface AntigravityQuotaInfo {
|
|
|
18
20
|
tier?: string;
|
|
19
21
|
windowId?: string;
|
|
20
22
|
windowLabel?: string;
|
|
23
|
+
apiProvider?: string;
|
|
24
|
+
modelProvider?: string;
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
interface AntigravityModelInfo {
|
|
@@ -25,6 +29,8 @@ interface AntigravityModelInfo {
|
|
|
25
29
|
quotaInfo?: AntigravityQuotaInfo | AntigravityQuotaInfo[];
|
|
26
30
|
quotaInfos?: AntigravityQuotaInfo[];
|
|
27
31
|
quotaInfoByTier?: Record<string, AntigravityQuotaInfo | AntigravityQuotaInfo[]>;
|
|
32
|
+
apiProvider?: string;
|
|
33
|
+
modelProvider?: string;
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
interface AntigravityUsageResponse {
|
|
@@ -60,22 +66,47 @@ function parseWindow(info: AntigravityQuotaInfo): UsageWindow | undefined {
|
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
function buildAmount(info: AntigravityQuotaInfo): UsageAmount {
|
|
63
|
-
const
|
|
69
|
+
const apiRemainingFraction = clampFraction(info.remainingFraction);
|
|
70
|
+
// Observed Antigravity responses omit remainingFraction for exhausted
|
|
71
|
+
// Google/Gemini counters and keep only resetTime. Treat that shape as
|
|
72
|
+
// "blocked until reset" rather than unknown so a healthy sibling backend
|
|
73
|
+
// counter cannot mask it during dedupe.
|
|
74
|
+
const remainingFraction = apiRemainingFraction ?? (info.resetTime ? 0 : undefined);
|
|
64
75
|
const amount: UsageAmount = { unit: "percent" };
|
|
65
76
|
if (remainingFraction === undefined) return amount;
|
|
66
|
-
const usedFraction =
|
|
77
|
+
const usedFraction = 1 - remainingFraction;
|
|
67
78
|
amount.remainingFraction = remainingFraction;
|
|
68
79
|
amount.usedFraction = usedFraction;
|
|
69
80
|
amount.remaining = remainingFraction * 100;
|
|
70
|
-
amount.used = usedFraction
|
|
81
|
+
amount.used = usedFraction * 100;
|
|
71
82
|
amount.limit = 100;
|
|
72
83
|
return amount;
|
|
73
84
|
}
|
|
74
85
|
|
|
86
|
+
function formatCounterName(info: AntigravityQuotaInfo): string | undefined {
|
|
87
|
+
switch (info.modelProvider ?? info.apiProvider) {
|
|
88
|
+
case "MODEL_PROVIDER_ANTHROPIC":
|
|
89
|
+
case "API_PROVIDER_ANTHROPIC_VERTEX":
|
|
90
|
+
return "Anthropic";
|
|
91
|
+
case "MODEL_PROVIDER_GOOGLE":
|
|
92
|
+
case "API_PROVIDER_GOOGLE_GEMINI":
|
|
93
|
+
return "Google";
|
|
94
|
+
case "MODEL_PROVIDER_OPENAI":
|
|
95
|
+
case "API_PROVIDER_OPENAI_VERTEX":
|
|
96
|
+
return "OpenAI";
|
|
97
|
+
default:
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
75
102
|
function normalizeQuotaInfos(info: AntigravityModelInfo): AntigravityQuotaInfo[] {
|
|
76
103
|
const results: AntigravityQuotaInfo[] = [];
|
|
104
|
+
const source = {
|
|
105
|
+
...(info.apiProvider ? { apiProvider: info.apiProvider } : {}),
|
|
106
|
+
...(info.modelProvider ? { modelProvider: info.modelProvider } : {}),
|
|
107
|
+
};
|
|
77
108
|
const addInfo = (value: AntigravityQuotaInfo, tier?: string) => {
|
|
78
|
-
results.push({ ...value, ...(tier ? { tier } : {}) });
|
|
109
|
+
results.push({ ...source, ...value, ...(tier ? { tier } : {}) });
|
|
79
110
|
};
|
|
80
111
|
const addArray = (values?: AntigravityQuotaInfo[]) => {
|
|
81
112
|
if (!values) return;
|
|
@@ -148,10 +179,26 @@ async function fetchAntigravityUsage(params: UsageFetchParams, ctx: UsageFetchCo
|
|
|
148
179
|
}
|
|
149
180
|
|
|
150
181
|
const data = (await response.json()) as AntigravityUsageResponse;
|
|
151
|
-
|
|
182
|
+
|
|
183
|
+
// The API returns per-model quota entries, but quota is shared across
|
|
184
|
+
// models within the same backend counter, tier, and reset window. Keep
|
|
185
|
+
// Google and Anthropic-backed Antigravity models separate so a healthy
|
|
186
|
+
// Claude counter cannot mask an exhausted Gemini counter.
|
|
187
|
+
const deduped = new Map<
|
|
188
|
+
string,
|
|
189
|
+
{
|
|
190
|
+
amount: UsageAmount;
|
|
191
|
+
window: UsageWindow | undefined;
|
|
192
|
+
tier: string | undefined;
|
|
193
|
+
tierKey: string;
|
|
194
|
+
windowId: string;
|
|
195
|
+
counterName: string | undefined;
|
|
196
|
+
counterKey: string;
|
|
197
|
+
}
|
|
198
|
+
>();
|
|
152
199
|
let earliestReset: number | undefined;
|
|
153
200
|
|
|
154
|
-
for (const [
|
|
201
|
+
for (const [_modelId, modelInfo] of Object.entries(data.models ?? {})) {
|
|
155
202
|
const quotaInfos = normalizeQuotaInfos(modelInfo);
|
|
156
203
|
for (const quotaInfo of quotaInfos) {
|
|
157
204
|
const amount = buildAmount(quotaInfo);
|
|
@@ -159,35 +206,90 @@ async function fetchAntigravityUsage(params: UsageFetchParams, ctx: UsageFetchCo
|
|
|
159
206
|
if (window?.resetsAt) {
|
|
160
207
|
earliestReset = earliestReset ? Math.min(earliestReset, window.resetsAt) : window.resetsAt;
|
|
161
208
|
}
|
|
162
|
-
const
|
|
163
|
-
const
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
209
|
+
const tierKey = (quotaInfo.tier ?? "default").toLowerCase();
|
|
210
|
+
const counterName = formatCounterName(quotaInfo);
|
|
211
|
+
const counterKey = counterName?.toLowerCase() ?? "default";
|
|
212
|
+
// Use quotaInfo.windowId even when parseWindow returns undefined
|
|
213
|
+
// (no resetTime) — separate windows must not collapse to "default".
|
|
214
|
+
const windowId = quotaInfo.windowId ?? window?.id ?? "default";
|
|
215
|
+
const key = `${counterKey}|${tierKey}|${windowId}`;
|
|
216
|
+
const existing = deduped.get(key);
|
|
217
|
+
if (!existing) {
|
|
218
|
+
deduped.set(key, { amount, window, tier: quotaInfo.tier, tierKey, windowId, counterName, counterKey });
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
// Merge: keep the entry with fraction data for the bar, but
|
|
222
|
+
// also keep any window with a reset time so "resets in…" survives.
|
|
223
|
+
const eFrac = existing.amount.remainingFraction;
|
|
224
|
+
const cFrac = amount.remainingFraction;
|
|
225
|
+
const eHasFrac = eFrac !== undefined;
|
|
226
|
+
const cHasFrac = cFrac !== undefined;
|
|
227
|
+
|
|
228
|
+
let bestAmount = existing.amount;
|
|
229
|
+
let bestWindow = existing.window?.resetsAt ? existing.window : (window ?? existing.window);
|
|
230
|
+
let bestTier = existing.tier ?? quotaInfo.tier;
|
|
231
|
+
|
|
232
|
+
if (!eHasFrac && cHasFrac) {
|
|
233
|
+
bestAmount = amount;
|
|
234
|
+
bestTier = quotaInfo.tier ?? existing.tier;
|
|
235
|
+
} else if (eFrac !== undefined && cFrac !== undefined && cFrac < eFrac) {
|
|
236
|
+
bestAmount = amount;
|
|
237
|
+
bestTier = quotaInfo.tier ?? existing.tier;
|
|
238
|
+
}
|
|
239
|
+
// Always merge in window with reset time if the current
|
|
240
|
+
// best doesn't have one.
|
|
241
|
+
if (!bestWindow?.resetsAt && window?.resetsAt) {
|
|
242
|
+
bestWindow = window;
|
|
243
|
+
}
|
|
244
|
+
deduped.set(key, {
|
|
245
|
+
amount: bestAmount,
|
|
246
|
+
window: bestWindow,
|
|
247
|
+
tier: bestTier,
|
|
248
|
+
tierKey: existing.tierKey,
|
|
249
|
+
windowId: existing.windowId,
|
|
250
|
+
counterName: existing.counterName,
|
|
251
|
+
counterKey: existing.counterKey,
|
|
179
252
|
});
|
|
180
253
|
}
|
|
181
254
|
}
|
|
182
255
|
|
|
256
|
+
const limits: UsageLimit[] = [];
|
|
257
|
+
for (const entry of deduped.values()) {
|
|
258
|
+
const label = entry.counterName ? `Usage (${entry.counterName})` : "Usage";
|
|
259
|
+
limits.push({
|
|
260
|
+
id: `${params.provider}:${entry.counterKey}:${entry.tierKey}:${entry.windowId}`,
|
|
261
|
+
label,
|
|
262
|
+
scope: {
|
|
263
|
+
provider: params.provider,
|
|
264
|
+
accountId: credential.accountId,
|
|
265
|
+
projectId: credential.projectId,
|
|
266
|
+
tier: entry.tier,
|
|
267
|
+
windowId: entry.windowId,
|
|
268
|
+
},
|
|
269
|
+
window: entry.window,
|
|
270
|
+
amount: entry.amount,
|
|
271
|
+
status: getUsageStatus(entry.amount.remainingFraction),
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
limits.sort((a, b) => {
|
|
276
|
+
const aFraction = a.amount.remainingFraction ?? 1;
|
|
277
|
+
const bFraction = b.amount.remainingFraction ?? 1;
|
|
278
|
+
return aFraction - bFraction;
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
const metadata: UsageReport["metadata"] = {
|
|
282
|
+
endpoint: url,
|
|
283
|
+
projectId: credential.projectId,
|
|
284
|
+
};
|
|
285
|
+
if (credential.email) metadata.email = credential.email;
|
|
286
|
+
if (credential.accountId) metadata.accountId = credential.accountId;
|
|
287
|
+
|
|
183
288
|
const report: UsageReport = {
|
|
184
289
|
provider: params.provider,
|
|
185
290
|
fetchedAt: nowMs,
|
|
186
291
|
limits,
|
|
187
|
-
metadata
|
|
188
|
-
endpoint: url,
|
|
189
|
-
projectId: credential.projectId,
|
|
190
|
-
},
|
|
292
|
+
metadata,
|
|
191
293
|
raw: data,
|
|
192
294
|
};
|
|
193
295
|
|
|
@@ -199,3 +301,69 @@ export const antigravityUsageProvider: UsageProvider = {
|
|
|
199
301
|
fetchUsage: fetchAntigravityUsage,
|
|
200
302
|
supports: params => params.provider === "google-antigravity",
|
|
201
303
|
};
|
|
304
|
+
|
|
305
|
+
const ONE_DAY_MS = 24 * 60 * 60 * 1000;
|
|
306
|
+
|
|
307
|
+
function getAntigravityCounterKeyForModel(context: CredentialRankingContext | undefined): string | undefined {
|
|
308
|
+
const modelId = context?.modelId?.toLowerCase();
|
|
309
|
+
if (!modelId) return undefined;
|
|
310
|
+
if (modelId.startsWith("claude-")) return "anthropic";
|
|
311
|
+
if (modelId.startsWith("gemini-") || modelId.startsWith("gemma-")) return "google";
|
|
312
|
+
if (modelId.startsWith("gpt-") || modelId.startsWith("openai/")) return "openai";
|
|
313
|
+
return undefined;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function getAntigravityCounterLimits(report: UsageReport, counterKey: string): UsageLimit[] {
|
|
317
|
+
const prefix = `${report.provider}:${counterKey}:`;
|
|
318
|
+
return report.limits.filter(limit => limit.id.toLowerCase().startsWith(prefix));
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Exhaustion checks are only safe with a concrete backend counter. A no-model
|
|
322
|
+
// Antigravity credential lookup (for example image-provider discovery) must
|
|
323
|
+
// not turn one exhausted family into a provider-wide block.
|
|
324
|
+
function scopeAntigravityLimitsForModel(
|
|
325
|
+
report: UsageReport,
|
|
326
|
+
context: CredentialRankingContext | undefined,
|
|
327
|
+
): UsageLimit[] {
|
|
328
|
+
const counterKey = getAntigravityCounterKeyForModel(context);
|
|
329
|
+
if (!counterKey) return [];
|
|
330
|
+
const backendLimits = getAntigravityCounterLimits(report, counterKey);
|
|
331
|
+
if (backendLimits.length > 0) return backendLimits;
|
|
332
|
+
return getAntigravityCounterLimits(report, "default");
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function rankAntigravityLimits(report: UsageReport, context: CredentialRankingContext | undefined): UsageLimit[] {
|
|
336
|
+
const counterKey = getAntigravityCounterKeyForModel(context);
|
|
337
|
+
if (!counterKey) return report.limits;
|
|
338
|
+
return scopeAntigravityLimitsForModel(report, context);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Antigravity quotas reset daily and are returned per backend counter
|
|
343
|
+
* (Anthropic / Google / OpenAI) without a fixed "primary vs secondary"
|
|
344
|
+
* split. `fetchAntigravityUsage` already sorts `limits` ascending by
|
|
345
|
+
* `remainingFraction`; after model-family scoping, the most-pressured
|
|
346
|
+
* relevant counter is index 0.
|
|
347
|
+
*
|
|
348
|
+
* Leave `secondary` unset: AuthStorage compares secondary metrics before
|
|
349
|
+
* primary metrics, which is correct for providers with explicit long-window
|
|
350
|
+
* limits but wrong here. Ranking Antigravity by the bottleneck counter first
|
|
351
|
+
* avoids preferring an account at 95% Gemini / 0% Claude over one at
|
|
352
|
+
* 80% Gemini / 70% Claude.
|
|
353
|
+
*/
|
|
354
|
+
export const antigravityRankingStrategy: CredentialRankingStrategy = {
|
|
355
|
+
findWindowLimits(report, context) {
|
|
356
|
+
return { primary: rankAntigravityLimits(report, context)[0] };
|
|
357
|
+
},
|
|
358
|
+
scopeLimits: scopeAntigravityLimitsForModel,
|
|
359
|
+
// Always return a scope for Antigravity so missing/unknown model context
|
|
360
|
+
// cannot fall through to AuthStorage's provider-wide block bucket.
|
|
361
|
+
blockScope(context) {
|
|
362
|
+
const counterKey = getAntigravityCounterKeyForModel(context);
|
|
363
|
+
return `counter:${counterKey ?? "unknown"}`;
|
|
364
|
+
},
|
|
365
|
+
// Antigravity windows omit `durationMs`; the endpoint is
|
|
366
|
+
// `daily-cloudcode-pa.googleapis.com`, so fall back to 24h when computing
|
|
367
|
+
// drain rate.
|
|
368
|
+
windowDefaults: { primaryMs: ONE_DAY_MS, secondaryMs: ONE_DAY_MS },
|
|
369
|
+
};
|
package/src/usage/kimi.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { $env } from "@prometheus-ai/utils";
|
|
2
|
+
import { getKimiCommonHeaders } from "../registry/oauth/kimi";
|
|
2
3
|
import type {
|
|
3
4
|
UsageAmount,
|
|
4
5
|
UsageFetchContext,
|
|
@@ -10,7 +11,6 @@ import type {
|
|
|
10
11
|
UsageWindow,
|
|
11
12
|
} from "../usage";
|
|
12
13
|
import { isRecord } from "../utils";
|
|
13
|
-
import { getKimiCommonHeaders } from "../utils/oauth/kimi";
|
|
14
14
|
// (Refresh is the sole responsibility of AuthStorage; no provider-direct refresh here.)
|
|
15
15
|
import { toNumber } from "./shared";
|
|
16
16
|
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import type { UsageFetchContext, UsageFetchParams, UsageProvider, UsageReport } from "../usage";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* MiniMax
|
|
4
|
+
* MiniMax Token Plan usage provider.
|
|
5
5
|
*
|
|
6
|
-
* MiniMax
|
|
7
|
-
* quota system. The quota resets automatically based on a rolling window.
|
|
6
|
+
* MiniMax Token Plan is a subscription-based service with a rolling quota system.
|
|
8
7
|
*
|
|
9
|
-
* Currently, MiniMax does not expose a usage/quota API endpoint for the
|
|
10
|
-
* Usage is tracked via the web dashboard at https://platform.minimax.io/user-center/payment/
|
|
8
|
+
* Currently, MiniMax does not expose a usage/quota API endpoint for the Token Plan.
|
|
9
|
+
* Usage is tracked via the web dashboard at https://platform.minimax.io/user-center/payment/token-plan
|
|
11
10
|
*
|
|
12
11
|
* This provider exists to register support for the minimax-code provider in the
|
|
13
12
|
* usage system. When MiniMax adds a usage API, this can be implemented.
|
|
@@ -17,7 +16,7 @@ async function fetchMiniMaxCodeUsage(params: UsageFetchParams, _ctx: UsageFetchC
|
|
|
17
16
|
return null;
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
// MiniMax
|
|
19
|
+
// MiniMax Token Plan does not currently expose a usage API
|
|
21
20
|
// Users can check their usage via the web dashboard
|
|
22
21
|
return null;
|
|
23
22
|
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI Codex "saved rate limit reset" redemption client.
|
|
3
|
+
*
|
|
4
|
+
* OpenAI lets paid Codex accounts bank a usage-window reset and spend it on
|
|
5
|
+
* demand (announced 2026-06-11). The count is surfaced on `/wham/usage` as
|
|
6
|
+
* `rate_limit_reset_credits.available_count` (see `./openai-codex.ts`), but the
|
|
7
|
+
* actual credit objects and the redeem action live on two dedicated routes:
|
|
8
|
+
*
|
|
9
|
+
* GET /wham/rate-limit-reset-credits → list redeemable credits
|
|
10
|
+
* POST /wham/rate-limit-reset-credits/consume → spend one credit
|
|
11
|
+
* body: { credit_id, redeem_request_id }
|
|
12
|
+
*
|
|
13
|
+
* `redeem_request_id` is a client-generated idempotency key (UUID). The consume
|
|
14
|
+
* response carries a `code`: `"reset"` on success, otherwise a business reason
|
|
15
|
+
* (`already_redeemed`, `no_credit`, `nothing_to_reset`).
|
|
16
|
+
*
|
|
17
|
+
* These are thin, dependency-light functions so both the interactive session
|
|
18
|
+
* (the `/usage reset` command + auto-redeem) and any out-of-band tooling can
|
|
19
|
+
* share one wire contract.
|
|
20
|
+
*/
|
|
21
|
+
import type { FetchImpl } from "../types";
|
|
22
|
+
import { isRecord } from "../utils";
|
|
23
|
+
import { normalizeCodexBaseUrl } from "./openai-codex";
|
|
24
|
+
import { toNumber } from "./shared";
|
|
25
|
+
|
|
26
|
+
const RESET_CREDITS_PATH = "wham/rate-limit-reset-credits";
|
|
27
|
+
const RESET_CREDITS_CONSUME_PATH = "wham/rate-limit-reset-credits/consume";
|
|
28
|
+
|
|
29
|
+
/** A single redeemable (or already-spent) saved reset. */
|
|
30
|
+
export interface CodexResetCredit {
|
|
31
|
+
/** Opaque credit id, e.g. `RateLimitResetCredit_…`. Pass to {@link consumeCodexResetCredit}. */
|
|
32
|
+
id: string;
|
|
33
|
+
/** Backend reset family, e.g. `codex_rate_limits`. */
|
|
34
|
+
resetType?: string;
|
|
35
|
+
/** `available`, `redeemed`, … */
|
|
36
|
+
status?: string;
|
|
37
|
+
grantedAt?: string;
|
|
38
|
+
expiresAt?: string;
|
|
39
|
+
redeemStartedAt?: string | null;
|
|
40
|
+
redeemedAt?: string | null;
|
|
41
|
+
/** Human-facing card title, e.g. "One free rate limit reset". */
|
|
42
|
+
title?: string;
|
|
43
|
+
description?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Result of listing an account's saved resets. */
|
|
47
|
+
export interface CodexResetCreditList {
|
|
48
|
+
credits: CodexResetCredit[];
|
|
49
|
+
/** Backend-reported count of credits redeemable right now. */
|
|
50
|
+
availableCount: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Consume outcome `code`. `reset` means a window was actually reset; the others
|
|
55
|
+
* are no-op business outcomes the caller should surface verbatim-ish to the user.
|
|
56
|
+
*/
|
|
57
|
+
export type CodexResetConsumeCode =
|
|
58
|
+
| "reset"
|
|
59
|
+
| "already_redeemed"
|
|
60
|
+
| "no_credit"
|
|
61
|
+
| "nothing_to_reset"
|
|
62
|
+
// Forward-compatible: unknown future codes pass through.
|
|
63
|
+
| (string & {});
|
|
64
|
+
|
|
65
|
+
export interface CodexResetConsumeResult {
|
|
66
|
+
/** `true` only when `code === "reset"` (a reset was applied). */
|
|
67
|
+
ok: boolean;
|
|
68
|
+
code: CodexResetConsumeCode;
|
|
69
|
+
/** HTTP status of the consume call (for diagnostics). */
|
|
70
|
+
status: number;
|
|
71
|
+
raw?: unknown;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface CodexResetAuth {
|
|
75
|
+
accessToken: string;
|
|
76
|
+
accountId?: string;
|
|
77
|
+
/** Provider base URL override; defaults to the Codex backend. */
|
|
78
|
+
baseUrl?: string;
|
|
79
|
+
fetch: FetchImpl;
|
|
80
|
+
signal?: AbortSignal;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function buildUrl(baseUrl: string | undefined, routePath: string): string {
|
|
84
|
+
const base = normalizeCodexBaseUrl(baseUrl);
|
|
85
|
+
const normalized = base.endsWith("/") ? base : `${base}/`;
|
|
86
|
+
return `${normalized}${routePath}`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function buildHeaders(auth: CodexResetAuth, json: boolean): Record<string, string> {
|
|
90
|
+
const headers: Record<string, string> = {
|
|
91
|
+
Authorization: `Bearer ${auth.accessToken}`,
|
|
92
|
+
"User-Agent": "OpenCode-Status-Plugin/1.0",
|
|
93
|
+
};
|
|
94
|
+
if (auth.accountId) headers["ChatGPT-Account-Id"] = auth.accountId;
|
|
95
|
+
if (json) headers["Content-Type"] = "application/json";
|
|
96
|
+
return headers;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function parseCredit(value: unknown): CodexResetCredit | null {
|
|
100
|
+
if (!isRecord(value)) return null;
|
|
101
|
+
const id = typeof value.id === "string" ? value.id : undefined;
|
|
102
|
+
if (!id) return null;
|
|
103
|
+
const str = (key: string): string | undefined =>
|
|
104
|
+
typeof value[key] === "string" ? (value[key] as string) : undefined;
|
|
105
|
+
const nullableStr = (key: string): string | null | undefined => {
|
|
106
|
+
const raw = value[key];
|
|
107
|
+
if (raw === null) return null;
|
|
108
|
+
return typeof raw === "string" ? raw : undefined;
|
|
109
|
+
};
|
|
110
|
+
return {
|
|
111
|
+
id,
|
|
112
|
+
resetType: str("reset_type"),
|
|
113
|
+
status: str("status"),
|
|
114
|
+
grantedAt: str("granted_at"),
|
|
115
|
+
expiresAt: str("expires_at"),
|
|
116
|
+
redeemStartedAt: nullableStr("redeem_started_at"),
|
|
117
|
+
redeemedAt: nullableStr("redeemed_at"),
|
|
118
|
+
title: str("title"),
|
|
119
|
+
description: str("description"),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* List the account's saved rate-limit resets. Returns `null` on transport/auth
|
|
125
|
+
* failure (non-2xx or thrown), letting callers treat it the same as "no data".
|
|
126
|
+
*/
|
|
127
|
+
export async function listCodexResetCredits(auth: CodexResetAuth): Promise<CodexResetCreditList | null> {
|
|
128
|
+
const url = buildUrl(auth.baseUrl, RESET_CREDITS_PATH);
|
|
129
|
+
let payload: unknown;
|
|
130
|
+
try {
|
|
131
|
+
const response = await auth.fetch(url, { headers: buildHeaders(auth, false), signal: auth.signal });
|
|
132
|
+
if (!response.ok) return null;
|
|
133
|
+
payload = await response.json();
|
|
134
|
+
} catch {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
if (!isRecord(payload)) return null;
|
|
138
|
+
const credits = Array.isArray(payload.credits)
|
|
139
|
+
? payload.credits.map(parseCredit).filter((c): c is CodexResetCredit => c !== null)
|
|
140
|
+
: [];
|
|
141
|
+
const reported = toNumber(payload.available_count);
|
|
142
|
+
const availableCount =
|
|
143
|
+
reported !== undefined
|
|
144
|
+
? Math.max(0, Math.trunc(reported))
|
|
145
|
+
: credits.filter(c => (c.status ?? "available") === "available").length;
|
|
146
|
+
return { credits, availableCount };
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Spend one saved reset. `redeemRequestId` is the idempotency key; one is
|
|
151
|
+
* generated when omitted, so retrying with the SAME id is safe and won't
|
|
152
|
+
* double-spend. The returned `code` is `"reset"` on success.
|
|
153
|
+
*/
|
|
154
|
+
export async function consumeCodexResetCredit(
|
|
155
|
+
auth: CodexResetAuth & { creditId: string; redeemRequestId?: string },
|
|
156
|
+
): Promise<CodexResetConsumeResult> {
|
|
157
|
+
const redeemRequestId = auth.redeemRequestId ?? crypto.randomUUID();
|
|
158
|
+
const url = buildUrl(auth.baseUrl, RESET_CREDITS_CONSUME_PATH);
|
|
159
|
+
const response = await auth.fetch(url, {
|
|
160
|
+
method: "POST",
|
|
161
|
+
headers: buildHeaders(auth, true),
|
|
162
|
+
body: JSON.stringify({ credit_id: auth.creditId, redeem_request_id: redeemRequestId }),
|
|
163
|
+
signal: auth.signal,
|
|
164
|
+
});
|
|
165
|
+
let body: unknown;
|
|
166
|
+
try {
|
|
167
|
+
body = await response.json();
|
|
168
|
+
} catch {
|
|
169
|
+
body = undefined;
|
|
170
|
+
}
|
|
171
|
+
const code =
|
|
172
|
+
isRecord(body) && typeof body.code === "string" ? body.code : response.ok ? "reset" : `http_${response.status}`;
|
|
173
|
+
return { ok: code === "reset", code, status: response.status, raw: body };
|
|
174
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Buffer } from "node:buffer";
|
|
2
|
-
import { CODEX_BASE_URL } from "
|
|
2
|
+
import { CODEX_BASE_URL } from "@prometheus-ai/catalog/wire/codex";
|
|
3
3
|
import type {
|
|
4
4
|
CredentialRankingStrategy,
|
|
5
5
|
UsageAmount,
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
UsageLimit,
|
|
9
9
|
UsageProvider,
|
|
10
10
|
UsageReport,
|
|
11
|
+
UsageResetCredits,
|
|
11
12
|
UsageWindow,
|
|
12
13
|
} from "../usage";
|
|
13
14
|
import { isRecord } from "../utils";
|
|
@@ -185,7 +186,21 @@ function parseUsagePayload(payload: unknown): ParsedUsage | null {
|
|
|
185
186
|
return parsed;
|
|
186
187
|
}
|
|
187
188
|
|
|
188
|
-
|
|
189
|
+
/**
|
|
190
|
+
* Parse the `rate_limit_reset_credits` block from `/wham/usage`. OpenAI Codex
|
|
191
|
+
* reports the count of saved rate-limit resets the account can redeem here; the
|
|
192
|
+
* redeem action itself lives in `./openai-codex-reset`.
|
|
193
|
+
*/
|
|
194
|
+
function parseResetCredits(payload: unknown): UsageResetCredits | undefined {
|
|
195
|
+
if (!isRecord(payload)) return undefined;
|
|
196
|
+
const block = payload.rate_limit_reset_credits;
|
|
197
|
+
if (!isRecord(block)) return undefined;
|
|
198
|
+
const availableCount = toNumber(block.available_count);
|
|
199
|
+
if (availableCount === undefined) return undefined;
|
|
200
|
+
return { availableCount: Math.max(0, Math.trunc(availableCount)) };
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function normalizeCodexBaseUrl(baseUrl?: string): string {
|
|
189
204
|
const fallback = CODEX_BASE_URL;
|
|
190
205
|
const trimmed = baseUrl?.trim() ? baseUrl.trim() : fallback;
|
|
191
206
|
const base = trimmed.replace(/\/+$/, "");
|
|
@@ -454,10 +469,12 @@ export const openaiCodexUsageProvider: UsageProvider = {
|
|
|
454
469
|
}
|
|
455
470
|
}
|
|
456
471
|
|
|
472
|
+
const resetCredits = parseResetCredits(payload);
|
|
457
473
|
const report: UsageReport = {
|
|
458
474
|
provider: "openai-codex",
|
|
459
475
|
fetchedAt: nowMs,
|
|
460
476
|
limits,
|
|
477
|
+
...(resetCredits ? { resetCredits } : {}),
|
|
461
478
|
metadata: {
|
|
462
479
|
planType,
|
|
463
480
|
allowed: parsed?.allowed,
|
package/src/usage/zai.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { toNumber } from "@prometheus-ai/catalog/utils";
|
|
1
2
|
import type {
|
|
2
3
|
UsageAmount,
|
|
3
4
|
UsageFetchContext,
|
|
@@ -8,7 +9,7 @@ import type {
|
|
|
8
9
|
UsageStatus,
|
|
9
10
|
UsageWindow,
|
|
10
11
|
} from "../usage";
|
|
11
|
-
import { isRecord
|
|
12
|
+
import { isRecord } from "../utils";
|
|
12
13
|
|
|
13
14
|
const DEFAULT_ENDPOINT = "https://api.z.ai";
|
|
14
15
|
const QUOTA_PATH = "/api/monitor/usage/quota/limit";
|