@linxiraos/pi-ai 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/CHANGELOG.md +5066 -0
- package/README.md +1195 -0
- package/dist/types/api-registry.d.ts +30 -0
- package/dist/types/auth/sqlite-credential-store.d.ts +117 -0
- package/dist/types/auth-broker/client.d.ts +93 -0
- package/dist/types/auth-broker/discover.d.ts +39 -0
- package/dist/types/auth-broker/index.d.ts +7 -0
- package/dist/types/auth-broker/refresher.d.ts +25 -0
- package/dist/types/auth-broker/remote-store.d.ts +136 -0
- package/dist/types/auth-broker/server.d.ts +48 -0
- package/dist/types/auth-broker/snapshot-cache.d.ts +17 -0
- package/dist/types/auth-broker/types.d.ts +152 -0
- package/dist/types/auth-broker/wire-schema-resource.d.ts +53 -0
- package/dist/types/auth-broker/wire-schemas.d.ts +5 -0
- package/dist/types/auth-gateway/http.d.ts +56 -0
- package/dist/types/auth-gateway/index.d.ts +3 -0
- package/dist/types/auth-gateway/server.d.ts +36 -0
- package/dist/types/auth-gateway/types.d.ts +127 -0
- package/dist/types/auth-retry.d.ts +150 -0
- package/dist/types/auth-storage.d.ts +1258 -0
- package/dist/types/dialect/anthropic.d.ts +15 -0
- package/dist/types/dialect/catalog.d.ts +3 -0
- package/dist/types/dialect/coercion.d.ts +23 -0
- package/dist/types/dialect/deepseek.d.ts +14 -0
- package/dist/types/dialect/demotion.d.ts +30 -0
- package/dist/types/dialect/examples.d.ts +18 -0
- package/dist/types/dialect/factory.d.ts +3 -0
- package/dist/types/dialect/fenced-thinking.d.ts +53 -0
- package/dist/types/dialect/gemini.d.ts +17 -0
- package/dist/types/dialect/gemma.d.ts +15 -0
- package/dist/types/dialect/glm.d.ts +9 -0
- package/dist/types/dialect/harmony.d.ts +8 -0
- package/dist/types/dialect/hermes.d.ts +9 -0
- package/dist/types/dialect/history.d.ts +3 -0
- package/dist/types/dialect/index.d.ts +11 -0
- package/dist/types/dialect/inventory.d.ts +9 -0
- package/dist/types/dialect/kimi.d.ts +14 -0
- package/dist/types/dialect/minimax.d.ts +3 -0
- package/dist/types/dialect/owned-stream.d.ts +4 -0
- package/dist/types/dialect/qwen3.d.ts +9 -0
- package/dist/types/dialect/rendering.d.ts +54 -0
- package/dist/types/dialect/thinking.d.ts +6 -0
- package/dist/types/dialect/types.d.ts +68 -0
- package/dist/types/dialect/xml.d.ts +9 -0
- package/dist/types/error/abort.d.ts +14 -0
- package/dist/types/error/auth-classify.d.ts +20 -0
- package/dist/types/error/auth.d.ts +27 -0
- package/dist/types/error/aws.d.ts +27 -0
- package/dist/types/error/classes.d.ts +106 -0
- package/dist/types/error/finalize.d.ts +39 -0
- package/dist/types/error/flags.d.ts +94 -0
- package/dist/types/error/format.d.ts +20 -0
- package/dist/types/error/gateway.d.ts +20 -0
- package/dist/types/error/index.d.ts +14 -0
- package/dist/types/error/oauth.d.ts +43 -0
- package/dist/types/error/provider.d.ts +42 -0
- package/dist/types/error/rate-limit.d.ts +80 -0
- package/dist/types/error/retryable.d.ts +27 -0
- package/dist/types/error/validation.d.ts +32 -0
- package/dist/types/index.d.ts +51 -0
- package/dist/types/provider-details.d.ts +24 -0
- package/dist/types/providers/amazon-bedrock.d.ts +39 -0
- package/dist/types/providers/anthropic-client.d.ts +106 -0
- package/dist/types/providers/anthropic-messages-server-schema.d.ts +937 -0
- package/dist/types/providers/anthropic-messages-server.d.ts +17 -0
- package/dist/types/providers/anthropic-wire.d.ts +345 -0
- package/dist/types/providers/anthropic.d.ts +261 -0
- package/dist/types/providers/aws-credentials.d.ts +48 -0
- package/dist/types/providers/aws-eventstream.d.ts +39 -0
- package/dist/types/providers/aws-sigv4.d.ts +55 -0
- package/dist/types/providers/azure-openai-responses.d.ts +16 -0
- package/dist/types/providers/bedrock-mantle.d.ts +13 -0
- package/dist/types/providers/claude-code-fingerprint.d.ts +19 -0
- package/dist/types/providers/cowork-fetch.d.ts +3 -0
- package/dist/types/providers/cursor/exec-modern.d.ts +98 -0
- package/dist/types/providers/cursor-pi-args.d.ts +105 -0
- package/dist/types/providers/cursor.d.ts +221 -0
- package/dist/types/providers/devin.d.ts +12 -0
- package/dist/types/providers/error-message.d.ts +25 -0
- package/dist/types/providers/github-copilot-headers.d.ts +40 -0
- package/dist/types/providers/gitlab-duo-workflow.d.ts +254 -0
- package/dist/types/providers/gitlab-duo.d.ts +27 -0
- package/dist/types/providers/google-auth.d.ts +24 -0
- package/dist/types/providers/google-gemini-cli.d.ts +120 -0
- package/dist/types/providers/google-shared.d.ts +203 -0
- package/dist/types/providers/google-types.d.ts +155 -0
- package/dist/types/providers/google-vertex.d.ts +7 -0
- package/dist/types/providers/google.d.ts +4 -0
- package/dist/types/providers/grammar.d.ts +1 -0
- package/dist/types/providers/kimi.d.ts +27 -0
- package/dist/types/providers/mock.d.ts +179 -0
- package/dist/types/providers/ollama.d.ts +8 -0
- package/dist/types/providers/openai-anthropic-shim.d.ts +35 -0
- package/dist/types/providers/openai-chat-server-schema.d.ts +1311 -0
- package/dist/types/providers/openai-chat-server.d.ts +16 -0
- package/dist/types/providers/openai-chat-wire.d.ts +669 -0
- package/dist/types/providers/openai-codex/request-transformer.d.ts +109 -0
- package/dist/types/providers/openai-codex/response-handler.d.ts +26 -0
- package/dist/types/providers/openai-codex-responses.d.ts +238 -0
- package/dist/types/providers/openai-completions.d.ts +48 -0
- package/dist/types/providers/openai-reasoning-fallback.d.ts +25 -0
- package/dist/types/providers/openai-responses-server-schema.d.ts +1314 -0
- package/dist/types/providers/openai-responses-server.d.ts +17 -0
- package/dist/types/providers/openai-responses-wire.d.ts +6099 -0
- package/dist/types/providers/openai-responses.d.ts +131 -0
- package/dist/types/providers/openai-shared.d.ts +624 -0
- package/dist/types/providers/pi-native-client.d.ts +13 -0
- package/dist/types/providers/pi-native-server.d.ts +69 -0
- package/dist/types/providers/register-builtins.d.ts +37 -0
- package/dist/types/providers/synthetic.d.ts +26 -0
- package/dist/types/providers/transform-messages.d.ts +32 -0
- package/dist/types/providers/vision-guard.d.ts +20 -0
- package/dist/types/registry/aiand.d.ts +7 -0
- package/dist/types/registry/aimlapi.d.ts +4 -0
- package/dist/types/registry/alibaba-coding-plan.d.ts +8 -0
- package/dist/types/registry/alibaba-token-plan.d.ts +18 -0
- package/dist/types/registry/amazon-bedrock.d.ts +5 -0
- package/dist/types/registry/anthropic.d.ts +10 -0
- package/dist/types/registry/api-key-login.d.ts +42 -0
- package/dist/types/registry/api-key-validation.d.ts +43 -0
- package/dist/types/registry/aws.d.ts +13 -0
- package/dist/types/registry/azure.d.ts +4 -0
- package/dist/types/registry/baseten.d.ts +7 -0
- package/dist/types/registry/bedrock-mantle.d.ts +22 -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/coreweave.d.ts +7 -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/devin.d.ts +8 -0
- package/dist/types/registry/exa.d.ts +8 -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-workflow.d.ts +10 -0
- package/dist/types/registry/gitlab-duo.d.ts +9 -0
- package/dist/types/registry/gmi-cloud.d.ts +7 -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/llama-cpp.d.ts +8 -0
- package/dist/types/registry/lm-studio.d.ts +8 -0
- package/dist/types/registry/meta.d.ts +7 -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/novita.d.ts +6 -0
- package/dist/types/registry/nvidia.d.ts +7 -0
- package/dist/types/registry/oauth/anthropic-constants.d.ts +12 -0
- package/dist/types/registry/oauth/anthropic.d.ts +24 -0
- package/dist/types/registry/oauth/callback-server.d.ts +74 -0
- package/dist/types/registry/oauth/cursor.d.ts +16 -0
- package/dist/types/registry/oauth/device-code.d.ts +25 -0
- package/dist/types/registry/oauth/devin.d.ts +5 -0
- package/dist/types/registry/oauth/github-copilot.d.ts +30 -0
- package/dist/types/registry/oauth/gitlab-duo-workflow.d.ts +6 -0
- package/dist/types/registry/oauth/gitlab-duo.d.ts +3 -0
- package/dist/types/registry/oauth/google-antigravity.d.ts +11 -0
- package/dist/types/registry/oauth/google-gemini-cli.d.ts +22 -0
- package/dist/types/registry/oauth/google-oauth-shared.d.ts +56 -0
- package/dist/types/registry/oauth/index.d.ts +45 -0
- package/dist/types/registry/oauth/kimi.d.ts +21 -0
- package/dist/types/registry/oauth/minimax-code.d.ts +27 -0
- package/dist/types/registry/oauth/openai-codex.d.ts +33 -0
- package/dist/types/registry/oauth/opencode.d.ts +18 -0
- package/dist/types/registry/oauth/perplexity.d.ts +9 -0
- package/dist/types/registry/oauth/pkce.d.ts +8 -0
- package/dist/types/registry/oauth/types.d.ts +87 -0
- package/dist/types/registry/oauth/wafer.d.ts +1 -0
- package/dist/types/registry/oauth/xai-oauth.d.ts +46 -0
- package/dist/types/registry/oauth/xiaomi.d.ts +25 -0
- package/dist/types/registry/oauth/zai.d.ts +25 -0
- 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 +367 -0
- package/dist/types/registry/sakana.d.ts +7 -0
- package/dist/types/registry/siliconflow-cn.d.ts +7 -0
- package/dist/types/registry/siliconflow.d.ts +7 -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 +75 -0
- package/dist/types/registry/umans.d.ts +7 -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-serverless.d.ts +6 -0
- package/dist/types/registry/xai-oauth.d.ts +7 -0
- package/dist/types/registry/xai.d.ts +7 -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 +15 -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 +46 -0
- package/dist/types/types.d.ts +1064 -0
- package/dist/types/usage/alibaba-token-plan.d.ts +3 -0
- package/dist/types/usage/claude.d.ts +4 -0
- package/dist/types/usage/cursor.d.ts +4 -0
- package/dist/types/usage/gemini.d.ts +2 -0
- package/dist/types/usage/github-copilot.d.ts +7 -0
- package/dist/types/usage/google-antigravity.d.ts +15 -0
- package/dist/types/usage/kimi.d.ts +2 -0
- package/dist/types/usage/minimax-code.d.ts +3 -0
- package/dist/types/usage/ollama.d.ts +5 -0
- package/dist/types/usage/openai-codex-base-url.d.ts +18 -0
- package/dist/types/usage/openai-codex-reset.d.ts +88 -0
- package/dist/types/usage/openai-codex.d.ts +10 -0
- package/dist/types/usage/opencode-go.d.ts +2 -0
- package/dist/types/usage/shared.d.ts +1 -0
- package/dist/types/usage/synthetic.d.ts +2 -0
- package/dist/types/usage/umans.d.ts +2 -0
- package/dist/types/usage/xai-oauth.d.ts +12 -0
- package/dist/types/usage/zai.d.ts +3 -0
- package/dist/types/usage.d.ts +527 -0
- package/dist/types/utils/abort.d.ts +25 -0
- package/dist/types/utils/anthropic-auth.d.ts +35 -0
- package/dist/types/utils/aws-profile.d.ts +17 -0
- package/dist/types/utils/block-symbols.d.ts +62 -0
- package/dist/types/utils/deterministic-id.d.ts +16 -0
- package/dist/types/utils/empty-completion-retry.d.ts +21 -0
- package/dist/types/utils/event-stream.d.ts +39 -0
- package/dist/types/utils/foundry.d.ts +1 -0
- package/dist/types/utils/google-validation.d.ts +2 -0
- package/dist/types/utils/harmony-leak.d.ts +135 -0
- package/dist/types/utils/http-inspector.d.ts +49 -0
- package/dist/types/utils/idle-iterator.d.ts +149 -0
- package/dist/types/utils/leaked-thinking-stream.d.ts +33 -0
- package/dist/types/utils/openai-http.d.ts +48 -0
- package/dist/types/utils/openrouter-headers.d.ts +1 -0
- package/dist/types/utils/parse-bind.d.ts +23 -0
- package/dist/types/utils/provider-response.d.ts +3 -0
- package/dist/types/utils/proxy.d.ts +39 -0
- package/dist/types/utils/request-debug.d.ts +29 -0
- package/dist/types/utils/retry-after.d.ts +4 -0
- package/dist/types/utils/retry.d.ts +14 -0
- package/dist/types/utils/schema/adapt.d.ts +24 -0
- package/dist/types/utils/schema/compatibility.d.ts +30 -0
- package/dist/types/utils/schema/dereference.d.ts +11 -0
- package/dist/types/utils/schema/draft.d.ts +10 -0
- package/dist/types/utils/schema/equality.d.ts +4 -0
- package/dist/types/utils/schema/fields.d.ts +54 -0
- package/dist/types/utils/schema/index.d.ts +14 -0
- package/dist/types/utils/schema/json-schema-validator.d.ts +20 -0
- package/dist/types/utils/schema/meta-validator.d.ts +2 -0
- package/dist/types/utils/schema/normalize.d.ts +153 -0
- package/dist/types/utils/schema/spill.d.ts +8 -0
- package/dist/types/utils/schema/stamps.d.ts +17 -0
- package/dist/types/utils/schema/strict-tool-validation.d.ts +16 -0
- package/dist/types/utils/schema/types.d.ts +4 -0
- package/dist/types/utils/schema/typescript.d.ts +24 -0
- package/dist/types/utils/schema/wire.d.ts +52 -0
- package/dist/types/utils/sdk-stream-timeout.d.ts +33 -0
- package/dist/types/utils/sse-debug.d.ts +5 -0
- package/dist/types/utils/stream-markup-healing.d.ts +87 -0
- package/dist/types/utils/thinking-loop.d.ts +102 -0
- package/dist/types/utils/tool-call-loop-guard.d.ts +26 -0
- package/dist/types/utils/tool-choice.d.ts +52 -0
- package/dist/types/utils/validation.d.ts +28 -0
- package/dist/types/utils.d.ts +57 -0
- package/package.json +138 -0
- package/src/api-registry.ts +109 -0
- package/src/auth/sqlite-credential-store.ts +2066 -0
- package/src/auth-broker/client.ts +471 -0
- package/src/auth-broker/discover.ts +310 -0
- package/src/auth-broker/index.ts +7 -0
- package/src/auth-broker/refresher.ts +117 -0
- package/src/auth-broker/remote-store.ts +1332 -0
- package/src/auth-broker/server.ts +898 -0
- package/src/auth-broker/snapshot-cache.ts +200 -0
- package/src/auth-broker/types.ts +193 -0
- package/src/auth-broker/wire-schema-resource.ts +487 -0
- package/src/auth-broker/wire-schemas.ts +43 -0
- package/src/auth-gateway/http.ts +227 -0
- package/src/auth-gateway/index.ts +3 -0
- package/src/auth-gateway/server.ts +836 -0
- package/src/auth-gateway/types.ts +153 -0
- package/src/auth-retry.ts +401 -0
- package/src/auth-storage.ts +6540 -0
- package/src/dialect/anthropic.md +31 -0
- package/src/dialect/anthropic.ts +608 -0
- package/src/dialect/catalog.ts +29 -0
- package/src/dialect/coercion.ts +136 -0
- package/src/dialect/deepseek.md +24 -0
- package/src/dialect/deepseek.ts +609 -0
- package/src/dialect/demotion.ts +40 -0
- package/src/dialect/examples.ts +71 -0
- package/src/dialect/factory.ts +34 -0
- package/src/dialect/fenced-thinking.ts +184 -0
- package/src/dialect/gemini.md +44 -0
- package/src/dialect/gemini.ts +583 -0
- package/src/dialect/gemma.md +33 -0
- package/src/dialect/gemma.ts +387 -0
- package/src/dialect/glm.md +32 -0
- package/src/dialect/glm.ts +579 -0
- package/src/dialect/harmony.md +31 -0
- package/src/dialect/harmony.ts +345 -0
- package/src/dialect/hermes.md +25 -0
- package/src/dialect/hermes.ts +206 -0
- package/src/dialect/history.ts +81 -0
- package/src/dialect/index.ts +15 -0
- package/src/dialect/inventory.ts +30 -0
- package/src/dialect/kimi.md +24 -0
- package/src/dialect/kimi.ts +340 -0
- package/src/dialect/minimax.md +31 -0
- package/src/dialect/minimax.ts +95 -0
- package/src/dialect/owned-stream.ts +481 -0
- package/src/dialect/prompt-template.md +12 -0
- package/src/dialect/qwen3.md +28 -0
- package/src/dialect/qwen3.ts +240 -0
- package/src/dialect/rendering.ts +304 -0
- package/src/dialect/thinking.ts +292 -0
- package/src/dialect/types.ts +56 -0
- package/src/dialect/xml.md +22 -0
- package/src/dialect/xml.ts +90 -0
- package/src/error/abort.ts +18 -0
- package/src/error/auth-classify.ts +47 -0
- package/src/error/auth.ts +48 -0
- package/src/error/aws.ts +35 -0
- package/src/error/classes.ts +281 -0
- package/src/error/finalize.ts +69 -0
- package/src/error/flags.ts +602 -0
- package/src/error/format.ts +45 -0
- package/src/error/gateway.ts +96 -0
- package/src/error/index.ts +14 -0
- package/src/error/oauth.ts +58 -0
- package/src/error/provider.ts +63 -0
- package/src/error/rate-limit.ts +303 -0
- package/src/error/retryable.ts +70 -0
- package/src/error/validation.ts +44 -0
- package/src/index.ts +51 -0
- package/src/provider-details.ts +90 -0
- package/src/providers/amazon-bedrock.ts +1064 -0
- package/src/providers/anthropic-client.ts +317 -0
- package/src/providers/anthropic-messages-server-schema.ts +252 -0
- package/src/providers/anthropic-messages-server.ts +818 -0
- package/src/providers/anthropic-wire.ts +359 -0
- package/src/providers/anthropic.ts +4539 -0
- package/src/providers/aws-credentials.ts +772 -0
- package/src/providers/aws-eventstream.ts +181 -0
- package/src/providers/aws-sigv4.ts +218 -0
- package/src/providers/azure-openai-responses.ts +438 -0
- package/src/providers/bedrock-mantle.ts +110 -0
- package/src/providers/claude-code-fingerprint.ts +20 -0
- package/src/providers/cowork-fetch.ts +201 -0
- package/src/providers/cursor/exec-modern.ts +496 -0
- package/src/providers/cursor/proto/agent.proto +4533 -0
- package/src/providers/cursor/proto/buf.gen.yaml +6 -0
- package/src/providers/cursor/proto/buf.yaml +17 -0
- package/src/providers/cursor-pi-args.ts +165 -0
- package/src/providers/cursor.ts +4689 -0
- package/src/providers/devin/proto/buf/validate/validate.proto +468 -0
- package/src/providers/devin/proto/buf.gen.yaml +33 -0
- package/src/providers/devin/proto/buf.yaml +17 -0
- package/src/providers/devin/proto/cel/expr/checked.proto +103 -0
- package/src/providers/devin/proto/cel/expr/eval.proto +38 -0
- package/src/providers/devin/proto/cel/expr/explain.proto +15 -0
- package/src/providers/devin/proto/cel/expr/syntax.proto +113 -0
- package/src/providers/devin/proto/cel/expr/value.proto +41 -0
- package/src/providers/devin/proto/connectext/grpc/status/v1/status.proto +11 -0
- package/src/providers/devin/proto/errorspb/errors.proto +56 -0
- package/src/providers/devin/proto/errorspb/hintdetail.proto +7 -0
- package/src/providers/devin/proto/errorspb/markers.proto +10 -0
- package/src/providers/devin/proto/errorspb/tags.proto +12 -0
- package/src/providers/devin/proto/errorspb/testing.proto +6 -0
- package/src/providers/devin/proto/exa/analytics_pb/analytics.proto +188 -0
- package/src/providers/devin/proto/exa/api_server_pb/api_server.proto +2461 -0
- package/src/providers/devin/proto/exa/auth_pb/auth.proto +19 -0
- package/src/providers/devin/proto/exa/auto_cascade_common_pb/auto_cascade_common.proto +79 -0
- package/src/providers/devin/proto/exa/browser_preview_pb/browser_preview.proto +32 -0
- package/src/providers/devin/proto/exa/bug_checker_pb/bug_checker.proto +22 -0
- package/src/providers/devin/proto/exa/cascade_plugins_pb/cascade_plugins.proto +262 -0
- package/src/providers/devin/proto/exa/chat_client_server_pb/chat_client_server.proto +57 -0
- package/src/providers/devin/proto/exa/chat_pb/chat.proto +449 -0
- package/src/providers/devin/proto/exa/code_edit/code_edit_pb/code_edit.proto +186 -0
- package/src/providers/devin/proto/exa/codeium_common_pb/codeium_common.proto +4157 -0
- package/src/providers/devin/proto/exa/context_module_pb/context_module.proto +175 -0
- package/src/providers/devin/proto/exa/cortex_pb/cortex.proto +3268 -0
- package/src/providers/devin/proto/exa/dev_pb/dev.proto +26 -0
- package/src/providers/devin/proto/exa/diff_action_pb/diff_action.proto +75 -0
- package/src/providers/devin/proto/exa/eval/pr_eval/datasets_pb/datasets.proto +103 -0
- package/src/providers/devin/proto/exa/eval_pb/eval.proto +1315 -0
- package/src/providers/devin/proto/exa/extension_server_pb/extension_server.proto +556 -0
- package/src/providers/devin/proto/exa/file_system_provider_pb/file_system_provider.proto +75 -0
- package/src/providers/devin/proto/exa/index_pb/index.proto +461 -0
- package/src/providers/devin/proto/exa/knowledge_base_pb/knowledge_base.proto +144 -0
- package/src/providers/devin/proto/exa/language_server_pb/language_server.proto +2385 -0
- package/src/providers/devin/proto/exa/model_management_pb/model_management.proto +186 -0
- package/src/providers/devin/proto/exa/opensearch_clients_pb/opensearch_clients.proto +503 -0
- package/src/providers/devin/proto/exa/product_analytics_pb/product_analytics.proto +37 -0
- package/src/providers/devin/proto/exa/prompt_pb/prompt.proto +92 -0
- package/src/providers/devin/proto/exa/reactive_component_pb/reactive_component.proto +96 -0
- package/src/providers/devin/proto/exa/seat_management_pb/seat_management.proto +2680 -0
- package/src/providers/devin/proto/exa/tokenizer_pb/tokenizer.proto +37 -0
- package/src/providers/devin/proto/exa/trainer_pb/config.proto +647 -0
- package/src/providers/devin/proto/exa/tree_sitter/language_data_pb/language_data.proto +14 -0
- package/src/providers/devin/proto/exa/trust_pb/trust.proto +157 -0
- package/src/providers/devin/proto/exa/user_analytics_pb/user_analytics.proto +519 -0
- package/src/providers/devin/proto/google.golang.org/appengine/internal/base/api_base.proto +28 -0
- package/src/providers/devin/proto/google.golang.org/appengine/internal/datastore/datastore_v3.proto +484 -0
- package/src/providers/devin/proto/google.golang.org/appengine/internal/log/log_service.proto +136 -0
- package/src/providers/devin/proto/google.golang.org/appengine/internal/remote_api/remote_api.proto +42 -0
- package/src/providers/devin/proto/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto +61 -0
- package/src/providers/devin/proto/grpc/binlog/v1/binarylog.proto +84 -0
- package/src/providers/devin/proto/io/prometheus/client/metrics.proto +98 -0
- package/src/providers/devin.ts +679 -0
- package/src/providers/error-message.ts +23 -0
- package/src/providers/github-copilot-headers.ts +141 -0
- package/src/providers/gitlab-duo-workflow-chatml-note.md +1 -0
- package/src/providers/gitlab-duo-workflow.ts +3135 -0
- package/src/providers/gitlab-duo.ts +399 -0
- package/src/providers/google-auth.ts +330 -0
- package/src/providers/google-gemini-cli.ts +1370 -0
- package/src/providers/google-shared.ts +1122 -0
- package/src/providers/google-types.ts +180 -0
- package/src/providers/google-vertex.ts +135 -0
- package/src/providers/google.ts +47 -0
- package/src/providers/grammar.ts +70 -0
- package/src/providers/kimi.ts +51 -0
- package/src/providers/mock.ts +514 -0
- package/src/providers/ollama.ts +776 -0
- package/src/providers/openai-anthropic-shim.ts +166 -0
- package/src/providers/openai-chat-server-schema.ts +243 -0
- package/src/providers/openai-chat-server.ts +752 -0
- package/src/providers/openai-chat-wire.ts +859 -0
- package/src/providers/openai-codex/request-transformer.ts +491 -0
- package/src/providers/openai-codex/response-handler.ts +102 -0
- package/src/providers/openai-codex-responses.ts +4716 -0
- package/src/providers/openai-completions.ts +2389 -0
- package/src/providers/openai-reasoning-fallback.ts +269 -0
- package/src/providers/openai-responses-server-schema.ts +397 -0
- package/src/providers/openai-responses-server.ts +1466 -0
- package/src/providers/openai-responses-wire.ts +6416 -0
- package/src/providers/openai-responses.ts +1393 -0
- package/src/providers/openai-shared.ts +3500 -0
- package/src/providers/pi-native-client.ts +275 -0
- package/src/providers/pi-native-server.ts +245 -0
- package/src/providers/register-builtins.ts +503 -0
- package/src/providers/synthetic.ts +50 -0
- package/src/providers/transform-messages.ts +1083 -0
- package/src/providers/vision-guard.ts +54 -0
- package/src/registry/aiand.ts +22 -0
- package/src/registry/aimlapi.ts +6 -0
- package/src/registry/alibaba-coding-plan.ts +104 -0
- package/src/registry/alibaba-token-plan.ts +125 -0
- package/src/registry/amazon-bedrock.ts +22 -0
- package/src/registry/anthropic.ts +26 -0
- package/src/registry/api-key-login.ts +115 -0
- package/src/registry/api-key-validation.ts +145 -0
- package/src/registry/aws.ts +57 -0
- package/src/registry/azure.ts +6 -0
- package/src/registry/baseten.ts +22 -0
- package/src/registry/bedrock-mantle.ts +34 -0
- package/src/registry/cerebras.ts +23 -0
- package/src/registry/cloudflare-ai-gateway.ts +45 -0
- package/src/registry/coreweave.ts +40 -0
- package/src/registry/cursor.ts +20 -0
- package/src/registry/deepseek.ts +46 -0
- package/src/registry/derived.ts +9 -0
- package/src/registry/devin.ts +15 -0
- package/src/registry/exa.ts +19 -0
- package/src/registry/firepass.ts +32 -0
- package/src/registry/fireworks.ts +28 -0
- package/src/registry/github-copilot.ts +22 -0
- package/src/registry/gitlab-duo-workflow.ts +20 -0
- package/src/registry/gitlab-duo.ts +19 -0
- package/src/registry/gmi-cloud.ts +22 -0
- package/src/registry/google-antigravity.ts +22 -0
- package/src/registry/google-gemini-cli.ts +22 -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/registry/huggingface.ts +29 -0
- package/src/registry/index.ts +4 -0
- package/src/registry/kagi.ts +46 -0
- package/src/registry/kilo.ts +114 -0
- package/src/registry/kimi-code.ts +17 -0
- package/src/registry/litellm.ts +45 -0
- package/src/registry/llama-cpp.ts +35 -0
- package/src/registry/lm-studio.ts +31 -0
- package/src/registry/meta.ts +22 -0
- 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/registry/moonshot.ts +28 -0
- package/src/registry/nanogpt.ts +22 -0
- package/src/registry/novita.ts +25 -0
- package/src/registry/nvidia.ts +61 -0
- package/src/registry/oauth/anthropic-constants.ts +12 -0
- package/src/registry/oauth/anthropic.ts +346 -0
- package/src/registry/oauth/callback-server.ts +438 -0
- package/src/registry/oauth/cursor.ts +187 -0
- package/src/registry/oauth/device-code.ts +92 -0
- package/src/registry/oauth/devin.ts +124 -0
- package/src/registry/oauth/github-copilot.ts +369 -0
- package/src/registry/oauth/gitlab-duo-workflow.ts +146 -0
- package/src/registry/oauth/gitlab-duo.ts +222 -0
- package/src/registry/oauth/google-antigravity.ts +225 -0
- package/src/registry/oauth/google-gemini-cli.ts +297 -0
- package/src/registry/oauth/google-oauth-shared.ts +211 -0
- package/src/registry/oauth/index.ts +187 -0
- package/src/registry/oauth/kimi.ts +297 -0
- package/src/registry/oauth/minimax-code.ts +53 -0
- package/src/registry/oauth/oauth.html +317 -0
- package/src/registry/oauth/openai-codex.ts +384 -0
- package/src/registry/oauth/opencode.ts +50 -0
- package/src/registry/oauth/perplexity.ts +228 -0
- package/src/registry/oauth/pkce.ts +18 -0
- package/src/registry/oauth/types.ts +96 -0
- package/src/registry/oauth/wafer.ts +24 -0
- package/src/registry/oauth/xai-oauth.ts +559 -0
- package/src/registry/oauth/xiaomi.ts +211 -0
- package/src/registry/oauth/zai.ts +285 -0
- package/src/registry/ollama-cloud.ts +36 -0
- package/src/registry/ollama.ts +43 -0
- 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/registry/openrouter.ts +28 -0
- package/src/registry/parallel.ts +45 -0
- package/src/registry/perplexity.ts +13 -0
- package/src/registry/qianfan.ts +27 -0
- package/src/registry/qwen-portal.ts +50 -0
- package/src/registry/registry.ts +182 -0
- package/src/registry/sakana.ts +22 -0
- package/src/registry/siliconflow-cn.ts +22 -0
- package/src/registry/siliconflow.ts +22 -0
- package/src/registry/synthetic.ts +21 -0
- package/src/registry/tavily.ts +45 -0
- package/src/registry/together.ts +22 -0
- package/src/registry/types.ts +86 -0
- package/src/registry/umans.ts +23 -0
- package/src/registry/venice.ts +33 -0
- package/src/registry/vercel-ai-gateway.ts +38 -0
- package/src/registry/vllm.ts +34 -0
- package/src/registry/wafer-serverless.ts +12 -0
- package/src/registry/xai-oauth.ts +17 -0
- package/src/registry/xai.ts +22 -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/registry/zai.ts +41 -0
- package/src/registry/zenmux.ts +22 -0
- package/src/registry/zhipu-coding-plan.ts +27 -0
- package/src/stream.ts +1944 -0
- package/src/types.ts +1243 -0
- package/src/usage/alibaba-token-plan.ts +230 -0
- package/src/usage/claude.ts +830 -0
- package/src/usage/cursor.ts +335 -0
- package/src/usage/gemini.ts +258 -0
- package/src/usage/github-copilot.ts +424 -0
- package/src/usage/google-antigravity.ts +497 -0
- package/src/usage/kimi.ts +277 -0
- package/src/usage/minimax-code.ts +291 -0
- package/src/usage/ollama.ts +41 -0
- package/src/usage/openai-codex-base-url.ts +35 -0
- package/src/usage/openai-codex-reset.ts +205 -0
- package/src/usage/openai-codex.ts +627 -0
- package/src/usage/opencode-go.ts +89 -0
- package/src/usage/shared.ts +10 -0
- package/src/usage/synthetic.ts +180 -0
- package/src/usage/umans.ts +192 -0
- package/src/usage/xai-oauth.ts +414 -0
- package/src/usage/zai.ts +370 -0
- package/src/usage.ts +411 -0
- package/src/utils/abort.ts +67 -0
- package/src/utils/anthropic-auth.ts +93 -0
- package/src/utils/aws-profile.ts +88 -0
- package/src/utils/block-symbols.ts +78 -0
- package/src/utils/deterministic-id.ts +20 -0
- package/src/utils/empty-completion-retry.ts +161 -0
- package/src/utils/event-stream.ts +202 -0
- package/src/utils/foundry.ts +8 -0
- package/src/utils/google-validation.ts +25 -0
- package/src/utils/harmony-leak.ts +500 -0
- package/src/utils/http-inspector.ts +196 -0
- package/src/utils/idle-iterator.ts +531 -0
- package/src/utils/leaked-thinking-stream.ts +483 -0
- package/src/utils/openai-http.ts +119 -0
- package/src/utils/openrouter-headers.ts +12 -0
- package/src/utils/parse-bind.ts +56 -0
- package/src/utils/provider-response.ts +30 -0
- package/src/utils/proxy.ts +314 -0
- package/src/utils/request-debug.ts +351 -0
- package/src/utils/retry-after.ts +121 -0
- package/src/utils/retry.ts +77 -0
- package/src/utils/schema/CONSTRAINTS.md +168 -0
- package/src/utils/schema/adapt.ts +36 -0
- package/src/utils/schema/compatibility.ts +435 -0
- package/src/utils/schema/dereference.ts +98 -0
- package/src/utils/schema/draft.ts +341 -0
- package/src/utils/schema/equality.ts +97 -0
- package/src/utils/schema/fields.ts +210 -0
- package/src/utils/schema/index.ts +14 -0
- package/src/utils/schema/json-schema-validator.ts +595 -0
- package/src/utils/schema/meta-validator.ts +167 -0
- package/src/utils/schema/normalize.ts +2314 -0
- package/src/utils/schema/spill.ts +43 -0
- package/src/utils/schema/stamps.ts +109 -0
- package/src/utils/schema/strict-tool-validation.ts +117 -0
- package/src/utils/schema/types.ts +10 -0
- package/src/utils/schema/typescript.ts +212 -0
- package/src/utils/schema/wire.ts +662 -0
- package/src/utils/sdk-stream-timeout.ts +43 -0
- package/src/utils/sse-debug.ts +18 -0
- package/src/utils/stream-markup-healing.ts +247 -0
- package/src/utils/thinking-loop.ts +552 -0
- package/src/utils/tool-call-loop-guard.ts +107 -0
- package/src/utils/tool-choice.ts +101 -0
- package/src/utils/validation.ts +1932 -0
- package/src/utils.ts +492 -0
|
@@ -0,0 +1,1258 @@
|
|
|
1
|
+
import type { ApiKeyResolver } from "./auth-retry.js";
|
|
2
|
+
import type { OAuthAuthInfo, OAuthController, OAuthCredentials, OAuthProviderId } from "./registry/oauth/types.js";
|
|
3
|
+
import type { Provider } from "./types.js";
|
|
4
|
+
import type { ClientUsageReport, ClientUsageSummary, CredentialRankingStrategy, ObservedUsageEntry, UsageCostHistoryEntry, UsageCostHistoryQuery, UsageHistoryEntry, UsageHistoryQuery, UsageLogger, UsageProvider, UsageReport } from "./usage.js";
|
|
5
|
+
import { type CodexResetConsumeCode, type CodexResetCredit } from "./usage/openai-codex-reset.js";
|
|
6
|
+
export { isSqliteBusyError, isSqliteCorruptionError, SqliteAuthCredentialStore, } from "./auth/sqlite-credential-store.js";
|
|
7
|
+
export type ApiKeyCredential = {
|
|
8
|
+
type: "api_key";
|
|
9
|
+
key: string;
|
|
10
|
+
source?: "login";
|
|
11
|
+
};
|
|
12
|
+
export type OAuthCredential = {
|
|
13
|
+
type: "oauth";
|
|
14
|
+
} & OAuthCredentials;
|
|
15
|
+
export type AuthCredential = ApiKeyCredential | OAuthCredential;
|
|
16
|
+
export type AuthCredentialEntry = AuthCredential | AuthCredential[];
|
|
17
|
+
export type AuthStorageData = Record<string, AuthCredentialEntry>;
|
|
18
|
+
/**
|
|
19
|
+
* Cascade leg that supplies a provider's active credential, highest precedence
|
|
20
|
+
* first — mirrors {@link AuthStorage.getApiKey}'s resolution order.
|
|
21
|
+
*/
|
|
22
|
+
export type CredentialOriginKind = "runtime" | "config" | "oauth" | "api_key" | "env" | "fallback";
|
|
23
|
+
/**
|
|
24
|
+
* Structured provenance for a provider's auth, for UI that needs a machine
|
|
25
|
+
* tag (the `/login` provider list) rather than the prose of
|
|
26
|
+
* {@link AuthStorage.describeCredentialSource}.
|
|
27
|
+
*/
|
|
28
|
+
export interface CredentialOrigin {
|
|
29
|
+
kind: CredentialOriginKind;
|
|
30
|
+
/** Env var name when `kind === "env"` and a single named variable backs it. */
|
|
31
|
+
envVar?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Serialized representation of AuthStorage for passing to subagent workers.
|
|
35
|
+
* Contains only the essential credential data, not runtime state.
|
|
36
|
+
*/
|
|
37
|
+
export interface SerializedAuthStorage {
|
|
38
|
+
credentials: Record<string, Array<{
|
|
39
|
+
id: number;
|
|
40
|
+
type: "api_key" | "oauth";
|
|
41
|
+
data: Record<string, unknown>;
|
|
42
|
+
}>>;
|
|
43
|
+
runtimeOverrides?: Record<string, string>;
|
|
44
|
+
dbPath?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Auth credential with database row ID for updates/deletes.
|
|
48
|
+
* Wraps AuthCredential with storage metadata.
|
|
49
|
+
*/
|
|
50
|
+
export interface StoredAuthCredential {
|
|
51
|
+
id: number;
|
|
52
|
+
provider: string;
|
|
53
|
+
credential: AuthCredential;
|
|
54
|
+
disabledCause: string | null;
|
|
55
|
+
}
|
|
56
|
+
/** One persisted rate-limit block: credential row id + provider-type key + optional scope. */
|
|
57
|
+
export interface StoredCredentialBlock {
|
|
58
|
+
/** SQLite row id of the credential (auth_credentials.id). */
|
|
59
|
+
credentialId: number;
|
|
60
|
+
/** `${provider}:${credentialType}` — same value as AuthStorage's in-memory providerKey. */
|
|
61
|
+
providerKey: string;
|
|
62
|
+
/** Block scope (e.g. "tier:fable"); empty string = unscoped. Never NUL-delimited. */
|
|
63
|
+
blockScope: string;
|
|
64
|
+
/** Epoch milliseconds. */
|
|
65
|
+
blockedUntilMs: number;
|
|
66
|
+
/** Last row update timestamp in epoch milliseconds, when provided by the backing store. */
|
|
67
|
+
updatedAtMs?: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Identity slice of a disabled (soft-deleted) credential tombstone — cause and
|
|
71
|
+
* account identity only, never token material. Surfaced so auto-disabled
|
|
72
|
+
* accounts (e.g. an expired Anthropic OAuth grant) stay visible in `omp usage`
|
|
73
|
+
* instead of silently vanishing until the user notices missing quota.
|
|
74
|
+
*/
|
|
75
|
+
export interface DisabledCredentialSummary {
|
|
76
|
+
/** Database row id (matches {@link StoredAuthCredential.id}). */
|
|
77
|
+
id: number;
|
|
78
|
+
provider: string;
|
|
79
|
+
type: AuthCredential["type"];
|
|
80
|
+
email?: string;
|
|
81
|
+
accountId?: string;
|
|
82
|
+
/** Organization/workspace the credential was scoped to (Anthropic/ChatGPT multi-subscription). */
|
|
83
|
+
orgId?: string;
|
|
84
|
+
orgName?: string;
|
|
85
|
+
/** Verbatim disable cause captured when the row was torn down. */
|
|
86
|
+
cause: string;
|
|
87
|
+
/** Epoch ms the row was disabled (SQLite `updated_at`), when known. */
|
|
88
|
+
disabledAtMs?: number;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Per-credential health record returned by {@link AuthStorage.checkCredentials}.
|
|
92
|
+
*
|
|
93
|
+
* Use this to identify which credential in a multi-account pool is causing
|
|
94
|
+
* auth errors. `ok` is tri-state:
|
|
95
|
+
*
|
|
96
|
+
* - `true` — credential authenticated against the provider's auth-verifying
|
|
97
|
+
* probe (today: the usage endpoint). For OAuth this also exercises refresh
|
|
98
|
+
* when the access token was expired.
|
|
99
|
+
* - `false` — the probe rejected the credential (401/403/refresh failure/etc).
|
|
100
|
+
* `reason` carries the upstream error string.
|
|
101
|
+
* - `null` — no probe is configured for this provider (or the configured
|
|
102
|
+
* probe doesn't support this credential type). The credential's auth
|
|
103
|
+
* status is unverifiable from here.
|
|
104
|
+
*/
|
|
105
|
+
export interface CredentialHealthResult {
|
|
106
|
+
/** Database row id (matches {@link StoredAuthCredential.id}). */
|
|
107
|
+
id: number;
|
|
108
|
+
provider: string;
|
|
109
|
+
type: AuthCredential["type"];
|
|
110
|
+
/** OAuth email if known on the stored credential or surfaced by the probe. */
|
|
111
|
+
email?: string;
|
|
112
|
+
/** OAuth account id if known. */
|
|
113
|
+
accountId?: string;
|
|
114
|
+
/** Organization/workspace the credential is scoped to (Anthropic/ChatGPT multi-subscription). */
|
|
115
|
+
orgId?: string;
|
|
116
|
+
orgName?: string;
|
|
117
|
+
/** `true` when the refresh token lives on a remote broker (sentinel was present). */
|
|
118
|
+
remoteRefresh?: true;
|
|
119
|
+
ok: boolean | null;
|
|
120
|
+
/** Failure / unverifiable reason; absent when `ok === true`. */
|
|
121
|
+
reason?: string;
|
|
122
|
+
/** Probe usage report (raw payload stripped) when `ok === true`. */
|
|
123
|
+
report?: Omit<UsageReport, "raw">;
|
|
124
|
+
/**
|
|
125
|
+
* Result of the optional end-to-end completion probe (see
|
|
126
|
+
* {@link CheckCredentialsOptions.completionProbe}). Absent when no probe was
|
|
127
|
+
* supplied. The completion probe exercises the provider's chat-completion
|
|
128
|
+
* endpoint with the credential's bearer bytes, which is a stricter signal
|
|
129
|
+
* than the usage endpoint (some providers happily 200 a `/usage` call while
|
|
130
|
+
* the chat endpoint 401s the same bearer).
|
|
131
|
+
*/
|
|
132
|
+
completion?: CredentialCompletionResult;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Outcome of the end-to-end completion probe. `null` means the probe was
|
|
136
|
+
* skipped (no bearer bytes were available — e.g. OAuth refresh failed
|
|
137
|
+
* upstream of the probe).
|
|
138
|
+
*/
|
|
139
|
+
export interface CredentialCompletionResult {
|
|
140
|
+
ok: boolean | null;
|
|
141
|
+
/** Failure / unverifiable reason; absent when `ok === true`. */
|
|
142
|
+
reason?: string;
|
|
143
|
+
/** Probe model id used (carried back from the caller for display). */
|
|
144
|
+
modelId?: string;
|
|
145
|
+
/** Round-trip latency in milliseconds. */
|
|
146
|
+
latencyMs?: number;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Credential payload handed to {@link CompletionProbe}. For API-key
|
|
150
|
+
* credentials only the bytes are exposed; for OAuth, every identity field
|
|
151
|
+
* carried by the refreshed credential is included so the probe can compose
|
|
152
|
+
* provider-specific apiKey shapes (e.g. GitHub Copilot / Google Gemini CLI
|
|
153
|
+
* expect a JSON blob with `token` + `projectId`, not the raw access token).
|
|
154
|
+
*
|
|
155
|
+
* `refreshToken` may be {@link REMOTE_REFRESH_SENTINEL} when the credential
|
|
156
|
+
* lives behind a broker; the chat endpoint never reads it, so the probe can
|
|
157
|
+
* forward it verbatim into the structured shape without harm.
|
|
158
|
+
*/
|
|
159
|
+
export type CompletionProbeCredential = {
|
|
160
|
+
type: "api_key";
|
|
161
|
+
apiKey: string;
|
|
162
|
+
} | {
|
|
163
|
+
type: "oauth";
|
|
164
|
+
accessToken: string;
|
|
165
|
+
refreshToken?: string;
|
|
166
|
+
expiresAt?: number;
|
|
167
|
+
accountId?: string;
|
|
168
|
+
projectId?: string;
|
|
169
|
+
email?: string;
|
|
170
|
+
enterpriseUrl?: string;
|
|
171
|
+
apiEndpoint?: string;
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* Caller-supplied bearer probe. Receives the post-refresh credential for a
|
|
175
|
+
* single row and reports whether a real chat-completion round-trip succeeds.
|
|
176
|
+
* The check-credentials pipeline calls this AFTER any OAuth refresh so the
|
|
177
|
+
* bytes match what a live request would send.
|
|
178
|
+
*/
|
|
179
|
+
export interface CompletionProbeInput {
|
|
180
|
+
provider: Provider;
|
|
181
|
+
credentialId: number;
|
|
182
|
+
credential: CompletionProbeCredential;
|
|
183
|
+
signal: AbortSignal;
|
|
184
|
+
}
|
|
185
|
+
export type CompletionProbe = (input: CompletionProbeInput) => Promise<CredentialCompletionResult>;
|
|
186
|
+
export interface CheckCredentialsOptions {
|
|
187
|
+
signal?: AbortSignal;
|
|
188
|
+
/** Per-credential probe timeout (ms). Defaults to the configured usage request timeout. */
|
|
189
|
+
timeoutMs?: number;
|
|
190
|
+
/** Provider → base URL override, same shape as {@link AuthStorage.fetchUsageReports}. */
|
|
191
|
+
baseUrlResolver?: (provider: Provider) => string | undefined;
|
|
192
|
+
/**
|
|
193
|
+
* Optional end-to-end probe. When provided, `checkCredentials` invokes it
|
|
194
|
+
* for every credential where a usable bearer is available (API key, or
|
|
195
|
+
* OAuth access token after refresh-on-expiry succeeded). The result lands
|
|
196
|
+
* on {@link CredentialHealthResult.completion}.
|
|
197
|
+
*
|
|
198
|
+
* The probe runs INDEPENDENTLY of whether a {@link UsageProvider} is
|
|
199
|
+
* configured: providers without a usage endpoint still benefit from the
|
|
200
|
+
* extra signal. The probe is NOT invoked when OAuth refresh fails — the
|
|
201
|
+
* bytes would be stale anyway and the upstream failure is already captured
|
|
202
|
+
* on `reason`.
|
|
203
|
+
*/
|
|
204
|
+
completionProbe?: CompletionProbe;
|
|
205
|
+
/** Per-credential completion probe timeout (ms). Defaults to `timeoutMs`. */
|
|
206
|
+
completionTimeoutMs?: number;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Sentinel value placed in OAuth `refresh` fields when a credential is shared
|
|
210
|
+
* via {@link AuthStorage.exportSnapshot}. Refresh tokens never leave the broker;
|
|
211
|
+
* clients must call back to refresh.
|
|
212
|
+
*/
|
|
213
|
+
export declare const REMOTE_REFRESH_SENTINEL: "__remote__";
|
|
214
|
+
export type RemoteRefreshSentinel = typeof REMOTE_REFRESH_SENTINEL;
|
|
215
|
+
/** OAuth credential with refresh token replaced by the broker sentinel. */
|
|
216
|
+
export type RemoteOAuthCredential = Omit<OAuthCredential, "refresh"> & {
|
|
217
|
+
refresh: RemoteRefreshSentinel;
|
|
218
|
+
};
|
|
219
|
+
/** Discriminated credential payload as published by the broker. */
|
|
220
|
+
export type SnapshotCredential = ApiKeyCredential | RemoteOAuthCredential;
|
|
221
|
+
export interface AuthCredentialSnapshotEntry {
|
|
222
|
+
id: number;
|
|
223
|
+
provider: string;
|
|
224
|
+
credential: SnapshotCredential;
|
|
225
|
+
identityKey: string | null;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Wire-shaped snapshot exported by {@link AuthStorage.exportSnapshot} and
|
|
229
|
+
* served by the auth-broker server on `GET /v1/snapshot`.
|
|
230
|
+
*/
|
|
231
|
+
export interface AuthCredentialSnapshot {
|
|
232
|
+
generation: number;
|
|
233
|
+
generatedAt: number;
|
|
234
|
+
credentials: AuthCredentialSnapshotEntry[];
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Persistence abstraction consumed by {@link AuthStorage}.
|
|
238
|
+
*
|
|
239
|
+
* Concrete implementations:
|
|
240
|
+
* - {@link SqliteAuthCredentialStore} — local SQLite-backed store (default).
|
|
241
|
+
* - `RemoteAuthCredentialStore` from `./auth-broker` — client-side snapshot of
|
|
242
|
+
* a remote broker; mutating methods (`replace*`, `upsert*`, `delete*ForProvider`)
|
|
243
|
+
* throw because login flows route through the broker, not the client.
|
|
244
|
+
*/
|
|
245
|
+
export interface CredentialRefreshLeaseFence {
|
|
246
|
+
owner: string;
|
|
247
|
+
nowMs: number;
|
|
248
|
+
}
|
|
249
|
+
export interface AuthCredentialStore {
|
|
250
|
+
close(): void;
|
|
251
|
+
/**
|
|
252
|
+
* Stateful probe for commits made by another process to the backing store.
|
|
253
|
+
* Returns true once per observed change.
|
|
254
|
+
*/
|
|
255
|
+
pollExternalChanges?(): boolean;
|
|
256
|
+
/** Record the current auth revision after a local mutation already notified consumers. */
|
|
257
|
+
acknowledgeLocalChanges?(): void;
|
|
258
|
+
/** Optional hook to notify the underlying store that usage report cache is stale. */
|
|
259
|
+
invalidateUsageCache?(signal?: AbortSignal): Promise<void>;
|
|
260
|
+
listAuthCredentials(provider?: string): StoredAuthCredential[];
|
|
261
|
+
/**
|
|
262
|
+
* Optional store hook to re-hydrate the credential snapshot from its
|
|
263
|
+
* backing source. Remote broker stores re-fetch `GET /v1/snapshot` so a
|
|
264
|
+
* disk-cached snapshot (up to an hour stale) cannot be paired with live
|
|
265
|
+
* per-credential data; local SQLite stores omit it — their reads are
|
|
266
|
+
* always current.
|
|
267
|
+
*/
|
|
268
|
+
refreshSnapshot?(): Promise<unknown>;
|
|
269
|
+
/**
|
|
270
|
+
* Disabled credential tombstones (see {@link DisabledCredentialSummary}).
|
|
271
|
+
* Optional: remote stores forward to the broker's
|
|
272
|
+
* `GET /v1/credentials/disabled` (empty list when the broker predates the
|
|
273
|
+
* endpoint); stores without tombstones omit it.
|
|
274
|
+
*/
|
|
275
|
+
listDisabledCredentials?(provider?: string, signal?: AbortSignal): Promise<DisabledCredentialSummary[]>;
|
|
276
|
+
updateAuthCredential(id: number, credential: AuthCredential): void;
|
|
277
|
+
deleteAuthCredential(id: number, disabledCause: string): void;
|
|
278
|
+
tryDisableAuthCredentialIfMatches(id: number, expectedData: string, disabledCause: string, lease?: CredentialRefreshLeaseFence): boolean;
|
|
279
|
+
tryUpdateAuthCredentialIfMatches?(id: number, expectedData: string, credential: AuthCredential, lease?: CredentialRefreshLeaseFence): boolean;
|
|
280
|
+
replaceAuthCredentialsForProvider(provider: string, credentials: AuthCredential[]): StoredAuthCredential[];
|
|
281
|
+
upsertAuthCredentialForProvider(provider: string, credential: AuthCredential): StoredAuthCredential[];
|
|
282
|
+
deleteAuthCredentialsForProvider(provider: string, disabledCause: string): void;
|
|
283
|
+
getCache(key: string, options?: {
|
|
284
|
+
includeExpired?: boolean;
|
|
285
|
+
}): string | null;
|
|
286
|
+
setCache(key: string, value: string, expiresAtSec: number): void;
|
|
287
|
+
/** Drop all cache rows whose keys start with the supplied prefix. */
|
|
288
|
+
deleteCachePrefix?(prefix: string): void;
|
|
289
|
+
cleanExpiredCache(): void;
|
|
290
|
+
/** Non-expired block for one (credential, providerKey, scope) key, or undefined. */
|
|
291
|
+
getCredentialBlock?(credentialId: number, providerKey: string, blockScope: string): number | undefined;
|
|
292
|
+
/** Earliest time a shared-store block should be eligible for live-usage reconciliation. */
|
|
293
|
+
getCredentialBlockReconcileAfter?(credentialId: number, providerKey: string, blockScope: string): number | undefined;
|
|
294
|
+
/** Upsert with MAX semantics: keep the later blockedUntilMs on conflict. */
|
|
295
|
+
upsertCredentialBlock?(block: StoredCredentialBlock): void;
|
|
296
|
+
/** Drop one block row for a credential/provider/scope key. */
|
|
297
|
+
deleteCredentialBlock?(credentialId: number, providerKey: string, blockScope: string): void;
|
|
298
|
+
/** Drop every block row for a credential (all providerKeys/scopes). */
|
|
299
|
+
deleteCredentialBlocks?(credentialId: number): void;
|
|
300
|
+
/** Prune rows with blocked_until_ms <= nowMs. */
|
|
301
|
+
cleanExpiredCredentialBlocks?(nowMs: number): void;
|
|
302
|
+
/** List non-expired blocks for broker snapshots. */
|
|
303
|
+
listCredentialBlocks?(credentialIds: readonly number[]): StoredCredentialBlock[];
|
|
304
|
+
tryAcquireCredentialRefreshLease?(credentialId: number, owner: string, expiresAtMs: number): boolean;
|
|
305
|
+
getCredentialRefreshLeaseExpiresAt?(credentialId: number): number | undefined;
|
|
306
|
+
releaseCredentialRefreshLease?(credentialId: number, owner: string): void;
|
|
307
|
+
renewCredentialRefreshLease?(credentialId: number, owner: string, expiresAtMs: number): boolean;
|
|
308
|
+
/**
|
|
309
|
+
* Append usage-limit snapshots for trend history. Optional: stores without
|
|
310
|
+
* durable storage (e.g. the broker remote store) omit it and recording is
|
|
311
|
+
* skipped — the broker host records into its own database instead.
|
|
312
|
+
*/
|
|
313
|
+
recordUsageSnapshots?(entries: UsageHistoryEntry[]): void;
|
|
314
|
+
/** Append observed request costs for providers without upstream usage APIs. */
|
|
315
|
+
recordUsageCosts?(entries: UsageCostHistoryEntry[]): void;
|
|
316
|
+
/** Read observed request costs, oldest first. */
|
|
317
|
+
listUsageCosts?(query?: UsageCostHistoryQuery): UsageCostHistoryEntry[];
|
|
318
|
+
/** Read recorded usage-limit snapshots, oldest first. */
|
|
319
|
+
listUsageHistory?(query?: UsageHistoryQuery): UsageHistoryEntry[];
|
|
320
|
+
/**
|
|
321
|
+
* Client hook: forward locally observed request usage. Remote broker stores
|
|
322
|
+
* batch these to the broker so it can attribute token burn per install;
|
|
323
|
+
* local stores omit it and observation is skipped.
|
|
324
|
+
*/
|
|
325
|
+
recordObservedUsage?(entries: ObservedUsageEntry[]): void;
|
|
326
|
+
/** Broker host: persist one client's observed-usage report. */
|
|
327
|
+
recordClientUsage?(report: ClientUsageReport): void;
|
|
328
|
+
/** Broker host: aggregate recorded per-client usage since a timestamp. */
|
|
329
|
+
getClientUsageSummary?(sinceMs: number): ClientUsageSummary;
|
|
330
|
+
/**
|
|
331
|
+
* Optional store-supplied OAuth refresh. When present, `AuthStorage` uses
|
|
332
|
+
* it before the per-provider local refresh path. `RemoteAuthCredentialStore`
|
|
333
|
+
* implements this against the broker; SQLite stores leave it undefined.
|
|
334
|
+
*
|
|
335
|
+
* Precedence: `AuthStorageOptions.refreshOAuthCredential` > this hook > local.
|
|
336
|
+
*
|
|
337
|
+
* `signal` propagates the agent's cancel (ESC, request abort, …) all the
|
|
338
|
+
* way to the broker fetch so a hung connection can't strand the caller
|
|
339
|
+
* for `timeoutMs * (maxRetries + 1)`.
|
|
340
|
+
*/
|
|
341
|
+
refreshOAuthCredential?(provider: Provider, credentialId: number, credential: OAuthCredential, signal?: AbortSignal): Promise<OAuthCredentials>;
|
|
342
|
+
/**
|
|
343
|
+
* Optional async pre-read hook invoked after AuthStorage selects a stored
|
|
344
|
+
* credential but before it returns that credential for an outbound request.
|
|
345
|
+
* Remote broker stores use this to wait out imminent rotations and refresh
|
|
346
|
+
* their local snapshot before the caller sees a stale access token.
|
|
347
|
+
*/
|
|
348
|
+
prepareForRequest?(credentialId: number, opts?: {
|
|
349
|
+
signal?: AbortSignal;
|
|
350
|
+
}): Promise<boolean | undefined>;
|
|
351
|
+
/**
|
|
352
|
+
* Optional store-supplied aggregate usage fetch. When present, `AuthStorage`
|
|
353
|
+
* routes `fetchUsageReports()` here instead of fanning out per-credential.
|
|
354
|
+
* `RemoteAuthCredentialStore` proxies to the broker (whose datacenter IP
|
|
355
|
+
* isn't rate-limited like a heavy residential client).
|
|
356
|
+
*
|
|
357
|
+
* Precedence: `AuthStorageOptions.fetchUsageReports` > this hook > local fan-out.
|
|
358
|
+
*
|
|
359
|
+
* `signal` propagates the agent's cancel down to the broker fetch.
|
|
360
|
+
*/
|
|
361
|
+
fetchUsageReports?(signal?: AbortSignal): Promise<UsageReport[] | null>;
|
|
362
|
+
/**
|
|
363
|
+
* Optional store-supplied per-credential usage report lookup. When present,
|
|
364
|
+
* `AuthStorage` consults this before its own per-credential upstream fetch
|
|
365
|
+
* (`#getUsageReport`). `RemoteAuthCredentialStore` implements this against
|
|
366
|
+
* the broker's aggregate `/v1/usage` (one coalesced round-trip shared across
|
|
367
|
+
* all callers) so multi-credential ranking on the client never hits the
|
|
368
|
+
* upstream provider's rate-limited usage endpoint from the laptop IP.
|
|
369
|
+
*
|
|
370
|
+
* Returning `null` is authoritative — `AuthStorage` does NOT fall back to
|
|
371
|
+
* the local fetch path. The store hook owns the decision, since falling
|
|
372
|
+
* back would re-introduce the per-IP rate-limit problem the broker exists
|
|
373
|
+
* to avoid.
|
|
374
|
+
*
|
|
375
|
+
* `signal` propagates the agent's cancel down to the broker fetch.
|
|
376
|
+
*/
|
|
377
|
+
getUsageReport?(provider: Provider, credential: OAuthCredential, signal?: AbortSignal): Promise<UsageReport | null>;
|
|
378
|
+
/**
|
|
379
|
+
* Optional store hook to ingest a parsed provider usage report for one OAuth
|
|
380
|
+
* credential. Remote broker stores use this to overlay header-derived limits
|
|
381
|
+
* onto their cached aggregate `/v1/usage` response without mutating broker
|
|
382
|
+
* state.
|
|
383
|
+
*/
|
|
384
|
+
ingestUsageReport?(provider: Provider, credential: OAuthCredential, report: UsageReport): boolean;
|
|
385
|
+
/**
|
|
386
|
+
* Optional store hook to invalidate a specific credential after the upstream
|
|
387
|
+
* provider returned 401 on a supposedly-fresh key. Remote stores force the
|
|
388
|
+
* broker to re-issue the row; local stores can leave it undefined and let
|
|
389
|
+
* {@link AuthStorage.invalidateCredentialMatching} fall back to `reload()`.
|
|
390
|
+
*/
|
|
391
|
+
markCredentialSuspect?(credentialId: number, opts?: {
|
|
392
|
+
signal?: AbortSignal;
|
|
393
|
+
}): Promise<void>;
|
|
394
|
+
/**
|
|
395
|
+
* Optional async write hook for upserting a single credential. When present,
|
|
396
|
+
* `AuthStorage.#upsertOAuthCredential` routes through this instead of the
|
|
397
|
+
* sync `upsertAuthCredentialForProvider`. `RemoteAuthCredentialStore` uses
|
|
398
|
+
* it to send the upsert to the broker via `POST /v1/credential`.
|
|
399
|
+
*
|
|
400
|
+
* Implementations MUST update the in-memory snapshot before returning so the
|
|
401
|
+
* post-write read path is consistent.
|
|
402
|
+
*/
|
|
403
|
+
upsertAuthCredentialRemote?(provider: string, credential: AuthCredential): Promise<StoredAuthCredential[]>;
|
|
404
|
+
/**
|
|
405
|
+
* Optional async write hook for replace-all semantics (e.g. API-key login
|
|
406
|
+
* overwriting any previous keys for the same provider). When present,
|
|
407
|
+
* `AuthStorage.set` routes through this instead of the sync
|
|
408
|
+
* `replaceAuthCredentialsForProvider`.
|
|
409
|
+
*/
|
|
410
|
+
replaceAuthCredentialsRemote?(provider: string, credentials: AuthCredential[]): Promise<StoredAuthCredential[]>;
|
|
411
|
+
/**
|
|
412
|
+
* Optional async write hook for disabling one stored credential. Remote stores
|
|
413
|
+
* use it to await broker persistence before AuthStorage updates its snapshot.
|
|
414
|
+
*/
|
|
415
|
+
deleteAuthCredentialRemote?(id: number, disabledCause: string): Promise<boolean>;
|
|
416
|
+
/**
|
|
417
|
+
* Optional async write hook for clearing every credential for a provider
|
|
418
|
+
* (logout). When present, `AuthStorage.remove` routes through this instead
|
|
419
|
+
* of the sync `deleteAuthCredentialsForProvider`.
|
|
420
|
+
*/
|
|
421
|
+
deleteAuthCredentialsRemote?(provider: string, disabledCause: string): Promise<void>;
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Event payload describing a credential that was just soft-disabled.
|
|
425
|
+
*
|
|
426
|
+
* Today the only call site is OAuth refresh failures with a definitive cause
|
|
427
|
+
* (`invalid_grant`, `401/403` not from a network blip, etc.) — the
|
|
428
|
+
* disabled_cause string is the verbatim error captured for forensics.
|
|
429
|
+
*
|
|
430
|
+
* Subscribers can use this to surface a notification, banner, or auto-launch
|
|
431
|
+
* a re-login flow instead of letting the credential silently disappear.
|
|
432
|
+
*/
|
|
433
|
+
export interface CredentialDisabledEvent {
|
|
434
|
+
provider: string;
|
|
435
|
+
disabledCause: string;
|
|
436
|
+
}
|
|
437
|
+
export type AuthStorageOptions = {
|
|
438
|
+
usageProviderResolver?: (provider: Provider) => UsageProvider | undefined;
|
|
439
|
+
rankingStrategyResolver?: (provider: Provider) => CredentialRankingStrategy | undefined;
|
|
440
|
+
usageFetch?: typeof fetch;
|
|
441
|
+
usageRequestTimeoutMs?: number;
|
|
442
|
+
usageLogger?: UsageLogger;
|
|
443
|
+
/**
|
|
444
|
+
* Resolve a config value (API key, header value, etc.) to an actual value.
|
|
445
|
+
* - coding-agent injects its resolveConfigValue (supports "!command" syntax via pi-natives)
|
|
446
|
+
* - Default: checks environment variable first, then treats as literal
|
|
447
|
+
*/
|
|
448
|
+
configValueResolver?: (config: string) => Promise<string | undefined>;
|
|
449
|
+
/**
|
|
450
|
+
* Optional callback fired when AuthStorage automatically disables a
|
|
451
|
+
* credential because something detected it as no longer usable — today
|
|
452
|
+
* that's the OAuth refresh-failure path in `getApiKey`. NOT fired for
|
|
453
|
+
* user-initiated `remove()` (the user already knows) or dedup of
|
|
454
|
+
* duplicate credentials (uninteresting hygiene).
|
|
455
|
+
*/
|
|
456
|
+
onCredentialDisabled?: (event: CredentialDisabledEvent) => void | Promise<void>;
|
|
457
|
+
/**
|
|
458
|
+
* Override OAuth refresh. When set, `AuthStorage` calls this instead of the
|
|
459
|
+
* per-provider local refresh function. Receives the credential id so the
|
|
460
|
+
* implementation can address remote credentials.
|
|
461
|
+
*
|
|
462
|
+
* Must return updated {@link OAuthCredentials} with at least `access` and
|
|
463
|
+
* `expires`. `refresh` may be an opaque sentinel (e.g. `"__remote__"`) when
|
|
464
|
+
* the actual refresh token never leaves the broker.
|
|
465
|
+
*/
|
|
466
|
+
refreshOAuthCredential?: (provider: Provider, credentialId: number, credential: OAuthCredential, signal?: AbortSignal) => Promise<OAuthCredentials>;
|
|
467
|
+
/**
|
|
468
|
+
* Human-readable description of the credential store backing this
|
|
469
|
+
* AuthStorage instance. Surfaced through {@link AuthStorage.describeCredentialSource}
|
|
470
|
+
* so the TUI can show where a token came from (broker URL or local SQLite path).
|
|
471
|
+
*
|
|
472
|
+
* Examples:
|
|
473
|
+
* - `"local ~/.omp/agent/agent.db"`
|
|
474
|
+
* - `"broker http://omp.internal:8765"`
|
|
475
|
+
*/
|
|
476
|
+
sourceLabel?: string;
|
|
477
|
+
/**
|
|
478
|
+
* Override `fetchUsageReports`. When set, `AuthStorage.fetchUsageReports`
|
|
479
|
+
* calls this instead of fanning out per-credential. The primary use case is
|
|
480
|
+
* routing through a broker that egresses from a less-throttled IP — e.g. a
|
|
481
|
+
* residential laptop trips Anthropic's per-IP rate limit on the usage
|
|
482
|
+
* endpoint and drops 2-of-5 credentials, while the VPS broker gets all 5.
|
|
483
|
+
*
|
|
484
|
+
* Implementations may return null when no usage data is available; the
|
|
485
|
+
* AuthStorage caller surfaces that to its own consumer unchanged.
|
|
486
|
+
*/
|
|
487
|
+
fetchUsageReports?: (signal?: AbortSignal) => Promise<UsageReport[] | null>;
|
|
488
|
+
};
|
|
489
|
+
export { isDefinitiveOAuthFailure } from "./error/auth-classify.js";
|
|
490
|
+
/**
|
|
491
|
+
* Outcome of {@link AuthStorage.markUsageLimitReached}.
|
|
492
|
+
*
|
|
493
|
+
* `switched` is `true` when an unblocked same-type sibling credential is
|
|
494
|
+
* available right now, so the caller can retry immediately and the next
|
|
495
|
+
* `getApiKey` will hand it out. When `false`, `retryAtMs` (epoch ms) carries
|
|
496
|
+
* the earliest moment any same-type sibling's temporary block expires —
|
|
497
|
+
* callers should prefer waiting until then over the provider's (often
|
|
498
|
+
* multi-hour) retry-after when it is sooner. `retryAtMs` is `undefined` when
|
|
499
|
+
* no sibling credentials exist at all, or when the session has no tracked
|
|
500
|
+
* credential to rotate away from.
|
|
501
|
+
*/
|
|
502
|
+
export interface UsageLimitMarkResult {
|
|
503
|
+
switched: boolean;
|
|
504
|
+
retryAtMs?: number;
|
|
505
|
+
}
|
|
506
|
+
export type ModelUsageHealthState = "healthy" | "reserve" | "depleted" | "unknown";
|
|
507
|
+
export interface ModelUsageAccountHealth {
|
|
508
|
+
credentialId: number;
|
|
509
|
+
credentialType: AuthCredential["type"];
|
|
510
|
+
/** True when this credential is currently sticky for options.sessionId. */
|
|
511
|
+
selected?: true;
|
|
512
|
+
state: ModelUsageHealthState;
|
|
513
|
+
remainingFraction?: number;
|
|
514
|
+
resetsAt?: number;
|
|
515
|
+
}
|
|
516
|
+
export interface ModelUsageHealth {
|
|
517
|
+
state: ModelUsageHealthState;
|
|
518
|
+
accounts: ModelUsageAccountHealth[];
|
|
519
|
+
}
|
|
520
|
+
export interface ModelUsageHealthOptions {
|
|
521
|
+
modelId?: string;
|
|
522
|
+
sessionId?: string;
|
|
523
|
+
baseUrl?: string;
|
|
524
|
+
reserveFraction: number;
|
|
525
|
+
signal?: AbortSignal;
|
|
526
|
+
}
|
|
527
|
+
type AuthApiKeyOptions = {
|
|
528
|
+
baseUrl?: string;
|
|
529
|
+
modelId?: string;
|
|
530
|
+
/**
|
|
531
|
+
* Caller's cancel signal. Threaded into any broker-bound OAuth refresh so
|
|
532
|
+
* `ESC` / request abort actually kills a hung broker fetch instead of
|
|
533
|
+
* stranding the caller for `timeoutMs * (maxRetries + 1)`.
|
|
534
|
+
*/
|
|
535
|
+
signal?: AbortSignal;
|
|
536
|
+
/**
|
|
537
|
+
* Force a re-mint of the session-preferred OAuth credential's access token,
|
|
538
|
+
* bypassing the not-yet-expired short-circuit. Powers step (b) of the
|
|
539
|
+
* auth-retry policy ("refresh the SAME account") so a locally-cached token
|
|
540
|
+
* that a peer/broker rotated out from under us is replaced before retrying.
|
|
541
|
+
*/
|
|
542
|
+
forceRefresh?: boolean;
|
|
543
|
+
};
|
|
544
|
+
/**
|
|
545
|
+
* Refreshed OAuth access plus identity metadata returned by
|
|
546
|
+
* {@link AuthStorage.getOAuthAccess}. Callers that authenticate via a bearer
|
|
547
|
+
* AND need the credential's identity (Codex `chatgpt-account-id`, Google
|
|
548
|
+
* `projectId`, GitHub `enterpriseUrl`) consume this shape directly; the
|
|
549
|
+
* refresh slot is deliberately omitted because rotating refresh tokens never
|
|
550
|
+
* leave {@link AuthStorage}.
|
|
551
|
+
*/
|
|
552
|
+
export interface OAuthAccess {
|
|
553
|
+
accessToken: string;
|
|
554
|
+
credentialId?: number;
|
|
555
|
+
accountId?: string;
|
|
556
|
+
email?: string;
|
|
557
|
+
projectId?: string;
|
|
558
|
+
enterpriseUrl?: string;
|
|
559
|
+
apiEndpoint?: string;
|
|
560
|
+
/** Organization/workspace the credential is scoped to (Anthropic/ChatGPT multi-subscription). */
|
|
561
|
+
orgId?: string;
|
|
562
|
+
orgName?: string;
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Identity slice of the credential a successful {@link AuthStorage.login}
|
|
566
|
+
* stored — lets callers confirm WHICH account (and for Anthropic, which
|
|
567
|
+
* organization/subscription) was added, without exposing tokens.
|
|
568
|
+
*/
|
|
569
|
+
export interface OAuthLoginIdentity {
|
|
570
|
+
type: "oauth" | "api_key";
|
|
571
|
+
email?: string;
|
|
572
|
+
accountId?: string;
|
|
573
|
+
orgId?: string;
|
|
574
|
+
orgName?: string;
|
|
575
|
+
}
|
|
576
|
+
export interface OAuthAccessFailure {
|
|
577
|
+
credentialId?: number;
|
|
578
|
+
accountId?: string;
|
|
579
|
+
email?: string;
|
|
580
|
+
projectId?: string;
|
|
581
|
+
enterpriseUrl?: string;
|
|
582
|
+
apiEndpoint?: string;
|
|
583
|
+
/** Organization/workspace the credential is scoped to (Anthropic/ChatGPT multi-subscription). */
|
|
584
|
+
orgId?: string;
|
|
585
|
+
orgName?: string;
|
|
586
|
+
error: string;
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Identity of the OAuth credential a session is currently routed to. Read-only
|
|
590
|
+
* display/metadata shape: `accountId` is the provider's account UUID, `email`
|
|
591
|
+
* the user-facing login, `projectId` the GCP-style project for providers that
|
|
592
|
+
* key usage on it (Gemini CLI / Antigravity).
|
|
593
|
+
*/
|
|
594
|
+
export interface OAuthAccountIdentity {
|
|
595
|
+
accountId?: string;
|
|
596
|
+
email?: string;
|
|
597
|
+
projectId?: string;
|
|
598
|
+
/** Organization/workspace the credential is scoped to (Anthropic/ChatGPT multi-subscription). */
|
|
599
|
+
orgId?: string;
|
|
600
|
+
orgName?: string;
|
|
601
|
+
}
|
|
602
|
+
export type OAuthAccessResolution = ({
|
|
603
|
+
ok: true;
|
|
604
|
+
} & OAuthAccess) | ({
|
|
605
|
+
ok: false;
|
|
606
|
+
} & OAuthAccessFailure);
|
|
607
|
+
/**
|
|
608
|
+
* Read-only identity of one stored OAuth account, in stable storage order.
|
|
609
|
+
* Returned by {@link AuthStorage.listOAuthAccounts}; `position` (0-based) is the
|
|
610
|
+
* selector accepted by {@link AuthStorage.getOAuthAccessAt}.
|
|
611
|
+
*/
|
|
612
|
+
export interface OAuthAccountSummary {
|
|
613
|
+
position: number;
|
|
614
|
+
credentialId: number;
|
|
615
|
+
accountId?: string;
|
|
616
|
+
email?: string;
|
|
617
|
+
projectId?: string;
|
|
618
|
+
enterpriseUrl?: string;
|
|
619
|
+
/** Organization/workspace the credential is scoped to (Anthropic/ChatGPT multi-subscription). */
|
|
620
|
+
orgId?: string;
|
|
621
|
+
orgName?: string;
|
|
622
|
+
/** True when this account is the session-sticky OAuth credential requested by `listOAuthAccounts`. */
|
|
623
|
+
active: boolean;
|
|
624
|
+
}
|
|
625
|
+
export interface InvalidateCredentialMatchingOptions {
|
|
626
|
+
signal?: AbortSignal;
|
|
627
|
+
sessionId?: string;
|
|
628
|
+
}
|
|
629
|
+
/** Options for refreshing one stored OAuth row through durable ownership. */
|
|
630
|
+
export interface StoredOAuthRefreshOptions<T extends OAuthCredential = OAuthCredential> {
|
|
631
|
+
/** Stable row id when a provider has multiple OAuth credentials. */
|
|
632
|
+
credentialId?: number;
|
|
633
|
+
observedCredential?: T;
|
|
634
|
+
credentialFromRow: (credential: OAuthCredential) => T | undefined;
|
|
635
|
+
forceRefresh?: boolean;
|
|
636
|
+
canRefresh?: (credential: T) => boolean;
|
|
637
|
+
refreshSkewMs?: number;
|
|
638
|
+
signal?: AbortSignal;
|
|
639
|
+
keepCredentialOnRefreshFailure?: boolean | ((error: unknown) => boolean);
|
|
640
|
+
onRefreshFailure?: (error: unknown) => void;
|
|
641
|
+
refreshTimeoutMs?: number;
|
|
642
|
+
refresh: (credential: T, signal?: AbortSignal) => Promise<OAuthCredentials>;
|
|
643
|
+
mergeRefreshedCredential?: (credential: T, refreshed: OAuthCredentials) => T;
|
|
644
|
+
isDefinitiveFailure?: (error: unknown) => boolean;
|
|
645
|
+
disabledCause?: (error: unknown) => string;
|
|
646
|
+
}
|
|
647
|
+
/** Result of a stored OAuth refresh attempt. */
|
|
648
|
+
export interface StoredOAuthRefreshResult<T extends OAuthCredential = OAuthCredential> {
|
|
649
|
+
credential: T | undefined;
|
|
650
|
+
refreshed: boolean;
|
|
651
|
+
removed: boolean;
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Identifies which stored account to redeem a saved rate-limit reset for.
|
|
655
|
+
* Any one field is enough; `credentialId` is the most precise.
|
|
656
|
+
*/
|
|
657
|
+
export interface ResetCreditTarget {
|
|
658
|
+
credentialId?: number;
|
|
659
|
+
accountId?: string;
|
|
660
|
+
email?: string;
|
|
661
|
+
}
|
|
662
|
+
/** Outcome of {@link AuthStorage.redeemResetCredit}. */
|
|
663
|
+
export interface ResetCreditRedeemOutcome {
|
|
664
|
+
/** `true` only when a reset was actually applied (`code === "reset"`). */
|
|
665
|
+
ok: boolean;
|
|
666
|
+
/**
|
|
667
|
+
* Result code. Backend codes: `reset` (success), `already_redeemed`,
|
|
668
|
+
* `no_credit`, `nothing_to_reset`. Locally-synthesized: `no_account`
|
|
669
|
+
* (target not found), `account_unavailable` (token refresh failed),
|
|
670
|
+
* `credit_list_failed` (transport/auth failure while listing credits —
|
|
671
|
+
* retryable, unlike a genuine `no_credit`), `http_<status>` (unexpected
|
|
672
|
+
* HTTP).
|
|
673
|
+
*/
|
|
674
|
+
code: CodexResetConsumeCode;
|
|
675
|
+
accountId?: string;
|
|
676
|
+
email?: string;
|
|
677
|
+
/** The credit that was spent (when one was). */
|
|
678
|
+
creditId?: string;
|
|
679
|
+
}
|
|
680
|
+
/** One stored account's live saved-reset status, from {@link AuthStorage.listResetCredits}. */
|
|
681
|
+
export interface ResetCreditAccountStatus {
|
|
682
|
+
credentialId?: number;
|
|
683
|
+
accountId?: string;
|
|
684
|
+
email?: string;
|
|
685
|
+
/** Resets redeemable for this account right now (live, not cached). */
|
|
686
|
+
availableCount: number;
|
|
687
|
+
credits: CodexResetCredit[];
|
|
688
|
+
/** Whether this is the given session's active account. */
|
|
689
|
+
active: boolean;
|
|
690
|
+
/** Set when the account's token refresh or list call failed. */
|
|
691
|
+
error?: string;
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Credential storage backed by an AuthCredentialStore.
|
|
695
|
+
* Reads from storage on reload(), manages round-robin credential selection,
|
|
696
|
+
* usage limit tracking, and OAuth token refresh.
|
|
697
|
+
*/
|
|
698
|
+
export declare class AuthStorage {
|
|
699
|
+
#private;
|
|
700
|
+
constructor(store: AuthCredentialStore, options?: AuthStorageOptions);
|
|
701
|
+
/**
|
|
702
|
+
* Create an AuthStorage instance backed by a AuthCredentialStore.
|
|
703
|
+
* Convenience factory for standalone use (e.g., pi-ai CLI).
|
|
704
|
+
* @param dbPath - Path to SQLite database
|
|
705
|
+
*/
|
|
706
|
+
static create(dbPath: string, options?: AuthStorageOptions): Promise<AuthStorage>;
|
|
707
|
+
/**
|
|
708
|
+
* Close the underlying credential store.
|
|
709
|
+
*
|
|
710
|
+
* After calling this, the instance must not be reused.
|
|
711
|
+
*/
|
|
712
|
+
close(): void;
|
|
713
|
+
getGeneration(): number;
|
|
714
|
+
/**
|
|
715
|
+
* Reload state after another process commits to the backing store, then
|
|
716
|
+
* notify snapshot consumers even when only credential blocks changed.
|
|
717
|
+
*/
|
|
718
|
+
pollExternalChanges(): Promise<boolean>;
|
|
719
|
+
onGenerationChanged(listener: (generation: number) => void): () => void;
|
|
720
|
+
offGenerationChanged(listener: (generation: number) => void): void;
|
|
721
|
+
/**
|
|
722
|
+
* Subscribe to {@link CredentialDisabledEvent}s. Multiple subscribers are supported and
|
|
723
|
+
* each fires for every disable event; subscribers are invoked in registration order with
|
|
724
|
+
* exceptions and async rejections isolated per-listener so a misbehaving subscriber
|
|
725
|
+
* cannot break the disable path or starve the rest of the chain.
|
|
726
|
+
*
|
|
727
|
+
* If `credential_disabled` events were emitted while no listener was subscribed, they are
|
|
728
|
+
* replayed (in insertion order) to the listener that triggers the empty→non-empty
|
|
729
|
+
* transition. The drain is one-shot — listeners that subscribe after that no longer see
|
|
730
|
+
* past events.
|
|
731
|
+
*
|
|
732
|
+
* Returns an unsubscribe function. The function is idempotent: calling it more than once
|
|
733
|
+
* is a no-op. After every subscriber has unsubscribed, subsequent disable events buffer
|
|
734
|
+
* again until the next subscribe.
|
|
735
|
+
*
|
|
736
|
+
* @param listener Callback invoked with each disable event. May be sync or async.
|
|
737
|
+
* @returns A function that removes this listener from the subscriber set.
|
|
738
|
+
*/
|
|
739
|
+
onCredentialDisabled(listener: (event: CredentialDisabledEvent) => void | Promise<void>): () => void;
|
|
740
|
+
/**
|
|
741
|
+
* Set a runtime API key override (not persisted to disk).
|
|
742
|
+
* Used for CLI --api-key flag.
|
|
743
|
+
*/
|
|
744
|
+
setRuntimeApiKey(provider: string, apiKey: string): void;
|
|
745
|
+
/**
|
|
746
|
+
* Remove a runtime API key override.
|
|
747
|
+
*/
|
|
748
|
+
removeRuntimeApiKey(provider: string): void;
|
|
749
|
+
/**
|
|
750
|
+
* Register a per-provider API key sourced from user configuration
|
|
751
|
+
* (e.g. `models.yml` `providers.<name>.apiKey`). Higher priority than
|
|
752
|
+
* stored credentials and OAuth tokens — when the user pins a key in
|
|
753
|
+
* config, that key is what authenticates outbound requests, regardless
|
|
754
|
+
* of whatever the broker happens to have loaded for that provider.
|
|
755
|
+
*
|
|
756
|
+
* Lower priority than {@link setRuntimeApiKey} so a CLI `--api-key`
|
|
757
|
+
* still wins for the duration of a single invocation.
|
|
758
|
+
*/
|
|
759
|
+
setConfigApiKey(provider: string, apiKey: string): void;
|
|
760
|
+
/**
|
|
761
|
+
* Remove a single config-sourced API key override.
|
|
762
|
+
*/
|
|
763
|
+
removeConfigApiKey(provider: string): void;
|
|
764
|
+
/**
|
|
765
|
+
* Drop every config-sourced API key. Called by `ModelRegistry` before
|
|
766
|
+
* re-parsing `models.yml` so removed entries actually disappear.
|
|
767
|
+
*/
|
|
768
|
+
clearConfigApiKeys(): void;
|
|
769
|
+
/**
|
|
770
|
+
* Set a fallback resolver for API keys not found in storage or env vars.
|
|
771
|
+
* Used for custom provider keys from models.json.
|
|
772
|
+
*/
|
|
773
|
+
setFallbackResolver(resolver: (provider: string) => string | undefined): void;
|
|
774
|
+
/**
|
|
775
|
+
* Reload credentials from storage.
|
|
776
|
+
*/
|
|
777
|
+
reload(): Promise<void>;
|
|
778
|
+
/**
|
|
779
|
+
* Get credential for a provider (first entry if multiple).
|
|
780
|
+
*/
|
|
781
|
+
get(provider: string): AuthCredential | undefined;
|
|
782
|
+
/**
|
|
783
|
+
* Set credential for a provider.
|
|
784
|
+
*/
|
|
785
|
+
set(provider: string, credential: AuthCredentialEntry): Promise<void>;
|
|
786
|
+
/**
|
|
787
|
+
* List stored credential rows, optionally filtered by provider.
|
|
788
|
+
*/
|
|
789
|
+
listStoredCredentials(provider?: string): StoredAuthCredential[];
|
|
790
|
+
/**
|
|
791
|
+
* Refresh one stored OAuth credential under durable row ownership.
|
|
792
|
+
*/
|
|
793
|
+
refreshStoredOAuthCredential<T extends OAuthCredential = OAuthCredential>(provider: string, options: StoredOAuthRefreshOptions<T>): Promise<StoredOAuthRefreshResult<T>>;
|
|
794
|
+
/**
|
|
795
|
+
* Remove credential for a provider.
|
|
796
|
+
*/
|
|
797
|
+
remove(provider: string): Promise<void>;
|
|
798
|
+
/**
|
|
799
|
+
* Remove one stored credential for a provider.
|
|
800
|
+
*/
|
|
801
|
+
removeCredential(provider: string, credentialId: number): Promise<boolean>;
|
|
802
|
+
/**
|
|
803
|
+
* List all providers with credentials.
|
|
804
|
+
*/
|
|
805
|
+
list(): string[];
|
|
806
|
+
/**
|
|
807
|
+
* Check if credentials exist for a provider in storage.
|
|
808
|
+
*/
|
|
809
|
+
has(provider: string): boolean;
|
|
810
|
+
/**
|
|
811
|
+
* Check if any form of auth is configured for a provider.
|
|
812
|
+
* Unlike getApiKey(), this doesn't refresh OAuth tokens.
|
|
813
|
+
*/
|
|
814
|
+
hasAuth(provider: string): boolean;
|
|
815
|
+
/**
|
|
816
|
+
* True iff a dedicated, non-env credential source is configured for this
|
|
817
|
+
* provider — i.e. anything in the cascade EXCEPT `getEnvApiKey(provider)`.
|
|
818
|
+
*
|
|
819
|
+
* Mirrors `hasAuth` minus the env-fallback leg. Useful for callers that
|
|
820
|
+
* need to distinguish "the user explicitly configured this provider"
|
|
821
|
+
* from "an env var happens to alias this provider via the cross-provider
|
|
822
|
+
* fallback map" (see e.g. `xai-oauth → XAI_OAUTH_TOKEN || XAI_API_KEY` in
|
|
823
|
+
* `stream.ts`). Without that distinction, an `XAI_API_KEY`-only setup
|
|
824
|
+
* silently satisfies xai-oauth and routes around `providers.xai.baseUrl`.
|
|
825
|
+
*/
|
|
826
|
+
hasNonEnvCredential(provider: string): boolean;
|
|
827
|
+
/**
|
|
828
|
+
* Classify where a provider's auth comes from, following the same precedence
|
|
829
|
+
* as {@link AuthStorage.getApiKey}: runtime override → config override →
|
|
830
|
+
* stored OAuth → login-stored api_key → env var → stored api_key →
|
|
831
|
+
* fallback resolver. Returns undefined when no auth is configured.
|
|
832
|
+
*
|
|
833
|
+
* Compact, structured counterpart to {@link describeCredentialSource}.
|
|
834
|
+
*/
|
|
835
|
+
getCredentialOrigin(provider: string): CredentialOrigin | undefined;
|
|
836
|
+
/**
|
|
837
|
+
* Check if OAuth credentials are configured for a provider.
|
|
838
|
+
*/
|
|
839
|
+
hasOAuth(provider: string): boolean;
|
|
840
|
+
/**
|
|
841
|
+
* Get OAuth credentials for a provider.
|
|
842
|
+
*/
|
|
843
|
+
getOAuthCredential(provider: string): OAuthCredential | undefined;
|
|
844
|
+
/**
|
|
845
|
+
* Get the OAuth `accountId` for a provider, preferring the credential that is
|
|
846
|
+
* session-sticky for `sessionId` when multiple OAuth credentials are configured.
|
|
847
|
+
* Falls back to the first OAuth credential when no session preference exists (e.g.
|
|
848
|
+
* first call before any `getApiKey` has been issued, or single-credential setups).
|
|
849
|
+
* Returns `undefined` when no OAuth credential carries an `accountId`.
|
|
850
|
+
*/
|
|
851
|
+
getOAuthAccountId(provider: string, sessionId?: string): string | undefined;
|
|
852
|
+
/**
|
|
853
|
+
* Get the OAuth account identity for a provider, preferring the credential that
|
|
854
|
+
* is session-sticky for `sessionId`. This is a read-only lookup for display and
|
|
855
|
+
* metadata paths; it does not refresh tokens, rank usage, or advance selection.
|
|
856
|
+
*/
|
|
857
|
+
getOAuthAccountIdentity(provider: string, sessionId?: string): OAuthAccountIdentity | undefined;
|
|
858
|
+
/**
|
|
859
|
+
* Get all credentials.
|
|
860
|
+
*/
|
|
861
|
+
getAll(): AuthStorageData;
|
|
862
|
+
/**
|
|
863
|
+
* Login to an OAuth provider. Resolves with the stored credential's
|
|
864
|
+
* identity slice (or `undefined` when nothing was stored) so callers can
|
|
865
|
+
* surface which account — and for Anthropic, which organization — the
|
|
866
|
+
* login registered.
|
|
867
|
+
*/
|
|
868
|
+
login(provider: OAuthProviderId, ctrl: OAuthController & {
|
|
869
|
+
/** onAuth is required by auth-storage but optional in OAuthController */
|
|
870
|
+
onAuth: (info: OAuthAuthInfo) => void;
|
|
871
|
+
/** onPrompt is required for some providers (github-copilot, openai-codex) */
|
|
872
|
+
onPrompt: (prompt: {
|
|
873
|
+
message: string;
|
|
874
|
+
placeholder?: string;
|
|
875
|
+
}) => Promise<string>;
|
|
876
|
+
}): Promise<OAuthLoginIdentity | undefined>;
|
|
877
|
+
/**
|
|
878
|
+
* Logout from a provider.
|
|
879
|
+
*/
|
|
880
|
+
logout(provider: string): Promise<void>;
|
|
881
|
+
/**
|
|
882
|
+
* Recorded usage-limit snapshots, oldest first. Empty when the underlying
|
|
883
|
+
* store has no durable history (e.g. a broker-backed remote store).
|
|
884
|
+
*/
|
|
885
|
+
listUsageHistory(query?: UsageHistoryQuery): UsageHistoryEntry[];
|
|
886
|
+
/** Record one observed provider request cost for later local usage aggregation. */
|
|
887
|
+
recordUsageCost(provider: Provider, costUsd: number, options?: {
|
|
888
|
+
sessionId?: string;
|
|
889
|
+
recordedAt?: number;
|
|
890
|
+
baseUrl?: string;
|
|
891
|
+
}): boolean;
|
|
892
|
+
/**
|
|
893
|
+
* Forward one completed request's usage to the store's observer hook.
|
|
894
|
+
* Broker-backed stores batch these into per-install reports so the broker
|
|
895
|
+
* can track actual token burn per client; local stores have no hook and
|
|
896
|
+
* the call is a no-op.
|
|
897
|
+
*/
|
|
898
|
+
recordObservedUsage(entry: {
|
|
899
|
+
provider: Provider;
|
|
900
|
+
model: string;
|
|
901
|
+
usage: {
|
|
902
|
+
input: number;
|
|
903
|
+
output: number;
|
|
904
|
+
cacheRead: number;
|
|
905
|
+
cacheWrite: number;
|
|
906
|
+
};
|
|
907
|
+
costUsd?: number;
|
|
908
|
+
at?: number;
|
|
909
|
+
}): void;
|
|
910
|
+
/** Broker host: persist one client's observed-usage report (per-install token burn). */
|
|
911
|
+
recordClientUsage(report: ClientUsageReport): boolean;
|
|
912
|
+
/** Broker host: aggregate recorded per-client usage since `sinceMs`. */
|
|
913
|
+
getClientUsageSummary(sinceMs: number): ClientUsageSummary;
|
|
914
|
+
ingestUsageHeaders(provider: Provider, headers: Record<string, string>, options?: {
|
|
915
|
+
sessionId?: string;
|
|
916
|
+
baseUrl?: string;
|
|
917
|
+
}): boolean;
|
|
918
|
+
/**
|
|
919
|
+
* The {@link UsageProvider} registered for `provider`, or undefined when the
|
|
920
|
+
* provider has no usage endpoint at all. Lets callers tell "a credential we
|
|
921
|
+
* could have fetched usage for but didn't" apart from "a provider with no
|
|
922
|
+
* usage concept" (web-search keys, local/keyless servers, inference
|
|
923
|
+
* providers without a usage API) — the latter never warrants a usage row.
|
|
924
|
+
*/
|
|
925
|
+
usageProviderFor(provider: Provider): UsageProvider | undefined;
|
|
926
|
+
/**
|
|
927
|
+
* Return model ids whose live reports map to a quantitative usage scope.
|
|
928
|
+
* Provider strategies supply model/tier mapping when available; otherwise
|
|
929
|
+
* only explicitly matching model ids and account-wide shared limits count.
|
|
930
|
+
* Label-only or ambiguous tier limits are excluded rather than guessed.
|
|
931
|
+
*/
|
|
932
|
+
getUsageReportingModelIds(provider: Provider, modelIds: readonly string[], reports: readonly UsageReport[]): string[];
|
|
933
|
+
/**
|
|
934
|
+
* Inspect the credential pool that {@link getApiKey} would use for one model
|
|
935
|
+
* without advancing round-robin state or changing session stickiness.
|
|
936
|
+
*
|
|
937
|
+
* Pool aggregation is deliberately conservative: one healthy sibling makes
|
|
938
|
+
* the model healthy, while any unknown sibling prevents a depleted/reserve
|
|
939
|
+
* conclusion. Static runtime/config/env credentials return unknown because
|
|
940
|
+
* they bypass the managed account pool.
|
|
941
|
+
*/
|
|
942
|
+
getModelUsageHealth(provider: Provider, options: ModelUsageHealthOptions): Promise<ModelUsageHealth>;
|
|
943
|
+
/**
|
|
944
|
+
* Release a session's sticky credential so its next {@link getApiKey} call
|
|
945
|
+
* re-runs native pool ranking. This never blocks or penalizes the released
|
|
946
|
+
* account; usage-aware routing uses it when another sibling has more
|
|
947
|
+
* headroom, before considering a model/provider fallback.
|
|
948
|
+
*/
|
|
949
|
+
releaseSessionCredentialForReselection(provider: string, sessionId: string): boolean;
|
|
950
|
+
fetchUsageReports(options?: {
|
|
951
|
+
baseUrlResolver?: (provider: Provider) => string | undefined;
|
|
952
|
+
/** Caller's cancel signal; only rejects this caller, never the shared upstream fetch. */
|
|
953
|
+
signal?: AbortSignal;
|
|
954
|
+
}): Promise<UsageReport[] | null>;
|
|
955
|
+
/**
|
|
956
|
+
* Probe each stored credential against its provider's auth-verifying usage
|
|
957
|
+
* endpoint and report per-credential auth health.
|
|
958
|
+
*
|
|
959
|
+
* Surfaces the identity of failing credentials so callers running a
|
|
960
|
+
* multi-account pool (e.g. a broker-backed auth-gateway) can tell which
|
|
961
|
+
* row is producing 401s. The probe mirrors the per-credential fan-out
|
|
962
|
+
* inside {@link AuthStorage.fetchUsageReports} (OAuth refresh-on-expiry,
|
|
963
|
+
* then `UsageProvider.fetchUsage`) but does NOT swallow errors — every
|
|
964
|
+
* credential gets either `ok: true`, `ok: false` with `reason`, or
|
|
965
|
+
* `ok: null` when no probe is configured for the provider.
|
|
966
|
+
*
|
|
967
|
+
* Iterates sequentially to avoid synchronized N-account fan-out that
|
|
968
|
+
* upstream `/usage` rate limiters (per source IP) treat as a burst.
|
|
969
|
+
*
|
|
970
|
+
* Only inspects active rows from {@link AuthCredentialStore.listAuthCredentials};
|
|
971
|
+
* soft-disabled rows are already known-bad and don't need a network probe.
|
|
972
|
+
* Environment-variable API keys are not enumerated — the caller's intent
|
|
973
|
+
* here is "which of my stored credentials is broken".
|
|
974
|
+
*
|
|
975
|
+
* Pass {@link CheckCredentialsOptions.completionProbe} to additionally
|
|
976
|
+
* exercise each credential against the provider's chat-completion endpoint
|
|
977
|
+
* (strict mode). The result lands on
|
|
978
|
+
* {@link CredentialHealthResult.completion}; the usage `ok` field is
|
|
979
|
+
* unchanged so callers can tell the two signals apart.
|
|
980
|
+
*/
|
|
981
|
+
checkCredentials(options?: CheckCredentialsOptions): Promise<CredentialHealthResult[]>;
|
|
982
|
+
/**
|
|
983
|
+
* Marks the current session's credential as temporarily blocked due to usage limits.
|
|
984
|
+
* Uses usage reports to determine accurate reset time when available.
|
|
985
|
+
* Returns whether a sibling credential is available now; when none is, also
|
|
986
|
+
* reports the earliest time a blocked sibling becomes available again so
|
|
987
|
+
* callers can wait for the sibling instead of the provider's full window.
|
|
988
|
+
*/
|
|
989
|
+
markUsageLimitReached(provider: string, sessionId: string | undefined, options?: {
|
|
990
|
+
retryAfterMs?: number;
|
|
991
|
+
baseUrl?: string;
|
|
992
|
+
modelId?: string;
|
|
993
|
+
apiKey?: string;
|
|
994
|
+
credentialId?: number;
|
|
995
|
+
signal?: AbortSignal;
|
|
996
|
+
}): Promise<UsageLimitMarkResult>;
|
|
997
|
+
/**
|
|
998
|
+
* Peek at API key for a provider without refreshing OAuth tokens.
|
|
999
|
+
* Used for model discovery where we only need to know if credentials exist
|
|
1000
|
+
* and get a best-effort token. For GitHub Copilot we preserve enterprise
|
|
1001
|
+
* routing metadata so discovery can hit the correct host.
|
|
1002
|
+
*/
|
|
1003
|
+
peekApiKey(provider: string): Promise<string | undefined>;
|
|
1004
|
+
/**
|
|
1005
|
+
* Get API key for a provider.
|
|
1006
|
+
* Priority (first match wins):
|
|
1007
|
+
* 1. Runtime override (CLI --api-key)
|
|
1008
|
+
* 2. Config override (models.yml `providers.<name>.apiKey`)
|
|
1009
|
+
* 3. OAuth token from storage (auto-refreshed)
|
|
1010
|
+
* 4. API key persisted by a successful `/login`
|
|
1011
|
+
* 5. Environment variable
|
|
1012
|
+
* 6. Stored API key (e.g. a broker-migrated copy) — last resort, so an explicit env var wins
|
|
1013
|
+
* 7. Fallback resolver (models.yml custom providers, last-resort)
|
|
1014
|
+
*/
|
|
1015
|
+
getApiKey(provider: string, sessionId?: string, options?: AuthApiKeyOptions): Promise<string | undefined>;
|
|
1016
|
+
/**
|
|
1017
|
+
* Resolve the OAuth credential for `provider`, refreshing through the same
|
|
1018
|
+
* pipeline as {@link AuthStorage.getApiKey} but returning the refreshed
|
|
1019
|
+
* {@link OAuthAccess} (raw access token + identity metadata) instead of
|
|
1020
|
+
* the API-key bytes.
|
|
1021
|
+
*
|
|
1022
|
+
* Use this when the caller needs to inject identity headers alongside the
|
|
1023
|
+
* bearer (Codex `chatgpt-account-id`, Google `project`, GitHub
|
|
1024
|
+
* `enterpriseUrl`). For pure "give me the bytes for `Authorization`"
|
|
1025
|
+
* scenarios, prefer {@link AuthStorage.getApiKey}.
|
|
1026
|
+
*
|
|
1027
|
+
* Returns `undefined` when no OAuth credential is available, the
|
|
1028
|
+
* credential fails to refresh, or runtime/config overrides have replaced
|
|
1029
|
+
* OAuth with an explicit API key.
|
|
1030
|
+
*/
|
|
1031
|
+
getOAuthAccess(provider: string, sessionId?: string, options?: AuthApiKeyOptions): Promise<OAuthAccess | undefined>;
|
|
1032
|
+
/**
|
|
1033
|
+
* Read-only list of stored OAuth accounts for `provider` in stable storage
|
|
1034
|
+
* order, WITHOUT refreshing any token. The array position (0-based) is the
|
|
1035
|
+
* selector accepted by {@link AuthStorage.getOAuthAccessAt}; a "pick the Nth
|
|
1036
|
+
* account" UI should render `position + 1`.
|
|
1037
|
+
*
|
|
1038
|
+
* When `sessionId` is supplied, the session-sticky OAuth credential is marked
|
|
1039
|
+
* `active`. No account is active before that session has resolved or pinned a
|
|
1040
|
+
* credential.
|
|
1041
|
+
*/
|
|
1042
|
+
listOAuthAccounts(provider: string, sessionId?: string): OAuthAccountSummary[];
|
|
1043
|
+
/**
|
|
1044
|
+
* Pin one stored OAuth account as this session's preferred credential.
|
|
1045
|
+
*
|
|
1046
|
+
* The durable credential id keeps the pin stable across credential refreshes,
|
|
1047
|
+
* storage reordering, and process restarts. Normal auth retry and usage-limit
|
|
1048
|
+
* handling may still route around an unavailable account.
|
|
1049
|
+
*
|
|
1050
|
+
* `options.lastUsedAtMs` backdates the sticky's last-use timestamp so a pin
|
|
1051
|
+
* restored from a persisted session keeps the provider's warm-window
|
|
1052
|
+
* semantics: a resume inside the prompt-cache TTL reuses the account, a
|
|
1053
|
+
* stale resume still re-ranks.
|
|
1054
|
+
*/
|
|
1055
|
+
pinSessionOAuthAccount(provider: string, sessionId: string, credentialId: number, options?: {
|
|
1056
|
+
lastUsedAtMs?: number;
|
|
1057
|
+
}): boolean;
|
|
1058
|
+
/**
|
|
1059
|
+
* Resolve every stored OAuth credential for `provider` independently.
|
|
1060
|
+
*
|
|
1061
|
+
* Refreshes credentials through the same broker/local path as
|
|
1062
|
+
* {@link AuthStorage.getOAuthAccess}, but does not rank, round-robin, or
|
|
1063
|
+
* stop after the first usable account. Intended for diagnostics that must
|
|
1064
|
+
* exercise each stored account exactly once.
|
|
1065
|
+
*/
|
|
1066
|
+
getOAuthAccesses(provider: string, options?: AuthApiKeyOptions): Promise<OAuthAccessResolution[]>;
|
|
1067
|
+
/**
|
|
1068
|
+
* Resolve a single stored OAuth credential by its account position (0-based,
|
|
1069
|
+
* matching {@link AuthStorage.listOAuthAccounts}). Refreshes ONLY that
|
|
1070
|
+
* credential ({@link #resolveStoredOAuthAccess} runs with `allowFallback:
|
|
1071
|
+
* false`), so — unlike {@link AuthStorage.getOAuthAccesses} — a definitive
|
|
1072
|
+
* failure of the targeted account surfaces as a failed resolution rather than
|
|
1073
|
+
* silently rotating or rate-tripping a sibling.
|
|
1074
|
+
*
|
|
1075
|
+
* Returns `undefined` when `position` is out of range or runtime/config
|
|
1076
|
+
* overrides have replaced OAuth with an explicit API key.
|
|
1077
|
+
*/
|
|
1078
|
+
getOAuthAccessAt(provider: string, position: number, options?: AuthApiKeyOptions): Promise<OAuthAccessResolution | undefined>;
|
|
1079
|
+
/**
|
|
1080
|
+
* Resolve one stored OAuth credential by its durable storage row id.
|
|
1081
|
+
*
|
|
1082
|
+
* Unlike the normal session resolver, this method never ranks, rotates, or
|
|
1083
|
+
* falls back to sibling credentials. A forced refresh re-mints only the
|
|
1084
|
+
* requested row, preserving exact-account affinity for operations whose
|
|
1085
|
+
* provenance and policy boundary are tied to one workspace.
|
|
1086
|
+
*
|
|
1087
|
+
* Returns `undefined` when the row does not exist for `provider` or an
|
|
1088
|
+
* explicit runtime/config API-key override suppresses OAuth.
|
|
1089
|
+
*/
|
|
1090
|
+
getOAuthAccessByCredentialId(provider: string, credentialId: number, options?: AuthApiKeyOptions): Promise<OAuthAccessResolution | undefined>;
|
|
1091
|
+
/**
|
|
1092
|
+
* List saved rate-limit resets for every stored OAuth account of `provider`
|
|
1093
|
+
* (Codex), fetched LIVE from the dedicated `rate-limit-reset-credits` route.
|
|
1094
|
+
*
|
|
1095
|
+
* This deliberately bypasses the usage-report cache: `/wham/usage` is
|
|
1096
|
+
* IP-rate-limited and may serve stale (or pre-feature) snapshots when many
|
|
1097
|
+
* accounts are polled, which would hide redeemable credits. One entry per
|
|
1098
|
+
* account, with the session's active account flagged and unreachable
|
|
1099
|
+
* accounts carrying an `error`.
|
|
1100
|
+
*/
|
|
1101
|
+
listResetCredits(options?: {
|
|
1102
|
+
provider?: string;
|
|
1103
|
+
sessionId?: string;
|
|
1104
|
+
baseUrlResolver?: (provider: string) => string | undefined;
|
|
1105
|
+
signal?: AbortSignal;
|
|
1106
|
+
}): Promise<ResetCreditAccountStatus[]>;
|
|
1107
|
+
/**
|
|
1108
|
+
* Redeem one saved rate-limit reset (OpenAI Codex "saved resets") for a
|
|
1109
|
+
* specific stored account.
|
|
1110
|
+
*
|
|
1111
|
+
* Resolves a fresh access token for the target account, picks an available
|
|
1112
|
+
* credit (the given `creditId`, else the first redeemable one), spends it,
|
|
1113
|
+
* and invalidates the cached usage report so the next `/usage` reflects the
|
|
1114
|
+
* reset. Never throws for business outcomes — inspect the returned `code`.
|
|
1115
|
+
*/
|
|
1116
|
+
redeemResetCredit(options: {
|
|
1117
|
+
target: ResetCreditTarget;
|
|
1118
|
+
provider?: string;
|
|
1119
|
+
creditId?: string;
|
|
1120
|
+
baseUrlResolver?: (provider: string) => string | undefined;
|
|
1121
|
+
signal?: AbortSignal;
|
|
1122
|
+
}): Promise<ResetCreditRedeemOutcome>;
|
|
1123
|
+
/**
|
|
1124
|
+
* Force-invalidate cached usage reports so the next fetch retrieves fresh
|
|
1125
|
+
* values from upstream providers. If `provider` is specified, only that
|
|
1126
|
+
* provider's credentials are invalidated; otherwise, all credentials in the
|
|
1127
|
+
* store are invalidated.
|
|
1128
|
+
*/
|
|
1129
|
+
invalidateUsageCache(provider?: string, signal?: AbortSignal): Promise<void>;
|
|
1130
|
+
invalidateCredentialMatching(provider: string, apiKey: string, options?: InvalidateCredentialMatchingOptions): Promise<boolean>;
|
|
1131
|
+
invalidateCredentialMatching(provider: string, apiKey: string, signal?: AbortSignal): Promise<boolean>;
|
|
1132
|
+
/**
|
|
1133
|
+
* Rotate away from the credential that failed after a retryable auth error —
|
|
1134
|
+
* step (c) of the auth-retry policy. Prefer the failed stored row id supplied
|
|
1135
|
+
* in `options.credentialId`, then the failed bearer supplied in
|
|
1136
|
+
* `options.apiKey`, so overlapping requests cannot redirect rotation through
|
|
1137
|
+
* stale session stickiness. Fall back to the session-sticky credential only
|
|
1138
|
+
* when neither explicit target is available. For hard-auth errors, an explicit
|
|
1139
|
+
* target that no longer matches storage returns `false` without mutation.
|
|
1140
|
+
* Delayed usage-limit errors may instead recover the durable OAuth row from
|
|
1141
|
+
* the bearer fingerprint recorded when the request resolved.
|
|
1142
|
+
*
|
|
1143
|
+
* - usage-limit / account-rate-limit error → {@link AuthStorage.markUsageLimitReached}
|
|
1144
|
+
* (temporary block via its own backoff — default plus server usage-report
|
|
1145
|
+
* reset; sticky left intact so the next resolve re-ranks around the block).
|
|
1146
|
+
* - otherwise (hard 401 / auth failure) → mark the credential suspect (or
|
|
1147
|
+
* reload when no broker hook is wired) and block it, then drop matching
|
|
1148
|
+
* sticky state.
|
|
1149
|
+
*
|
|
1150
|
+
* Returns whether another usable credential of the same type remains.
|
|
1151
|
+
*/
|
|
1152
|
+
rotateSessionCredential(provider: string, sessionId: string | undefined, options?: {
|
|
1153
|
+
error?: unknown;
|
|
1154
|
+
modelId?: string;
|
|
1155
|
+
apiKey?: string;
|
|
1156
|
+
credentialId?: number;
|
|
1157
|
+
signal?: AbortSignal;
|
|
1158
|
+
}): Promise<boolean>;
|
|
1159
|
+
/**
|
|
1160
|
+
* Build an {@link ApiKeyResolver} backed by this storage, implementing the
|
|
1161
|
+
* central a/b/c auth-retry policy:
|
|
1162
|
+
*
|
|
1163
|
+
* - initial (`error: undefined`) → resolve the session credential.
|
|
1164
|
+
* - step (b) `!lastChance` → force-refresh the SAME session-sticky credential.
|
|
1165
|
+
* - step (c) `lastChance` → rotate to a sibling and re-resolve, unless quota exhaustion has no sibling.
|
|
1166
|
+
*
|
|
1167
|
+
* Used by web-search providers and other consumers that hold an AuthStorage
|
|
1168
|
+
* directly (no ModelRegistry in scope).
|
|
1169
|
+
*/
|
|
1170
|
+
resolver(provider: string, options?: {
|
|
1171
|
+
sessionId?: string;
|
|
1172
|
+
baseUrl?: string;
|
|
1173
|
+
modelId?: string;
|
|
1174
|
+
}): ApiKeyResolver;
|
|
1175
|
+
/**
|
|
1176
|
+
* Build a redacted snapshot of all loaded credentials for the auth-broker
|
|
1177
|
+
* wire. OAuth refresh tokens are replaced with {@link REMOTE_REFRESH_SENTINEL}
|
|
1178
|
+
* so clients never see the actual refresh token.
|
|
1179
|
+
*
|
|
1180
|
+
* Callers must {@link AuthStorage.reload} first when serving a stale snapshot
|
|
1181
|
+
* (the broker server's HTTP handler does this).
|
|
1182
|
+
*/
|
|
1183
|
+
exportSnapshot(): AuthCredentialSnapshot;
|
|
1184
|
+
/**
|
|
1185
|
+
* Disabled credential tombstones for display surfaces (`omp usage`,
|
|
1186
|
+
* broker `GET /v1/credentials/disabled`). Empty when the backing store
|
|
1187
|
+
* keeps no tombstones or the remote broker predates the endpoint.
|
|
1188
|
+
*/
|
|
1189
|
+
listDisabledCredentials(provider?: string, signal?: AbortSignal): Promise<DisabledCredentialSummary[]>;
|
|
1190
|
+
/**
|
|
1191
|
+
* Force the backing store to revalidate its credential snapshot, then
|
|
1192
|
+
* reload. Remote broker stores re-fetch the snapshot; local stores are
|
|
1193
|
+
* always current, so only the reload runs. Callers that pair live
|
|
1194
|
+
* per-credential data with stored identities (`omp usage`) use this so a
|
|
1195
|
+
* disk-cached snapshot cannot misattribute fresh reports.
|
|
1196
|
+
*/
|
|
1197
|
+
revalidateCredentials(): Promise<void>;
|
|
1198
|
+
/**
|
|
1199
|
+
* Refresh the OAuth credential with the given id through a per-credential
|
|
1200
|
+
* single-flight. Concurrent callers for the same row await the same upstream
|
|
1201
|
+
* refresh attempt, which is required for providers that rotate refresh tokens
|
|
1202
|
+
* on every successful refresh.
|
|
1203
|
+
*/
|
|
1204
|
+
refreshCredentialById(id: number, signal?: AbortSignal): Promise<AuthCredentialSnapshotEntry>;
|
|
1205
|
+
/**
|
|
1206
|
+
* Force-refresh the OAuth credential with the given id, bypassing the
|
|
1207
|
+
* not-yet-expired guard. Used by the auth-broker server to honour
|
|
1208
|
+
* `POST /v1/credential/:id/refresh`.
|
|
1209
|
+
*
|
|
1210
|
+
* Returns the redacted snapshot entry for the refreshed row.
|
|
1211
|
+
* Throws when no OAuth credential with that id is loaded.
|
|
1212
|
+
*/
|
|
1213
|
+
forceRefreshCredentialById(id: number, signal?: AbortSignal): Promise<AuthCredentialSnapshotEntry>;
|
|
1214
|
+
/**
|
|
1215
|
+
* Disable the credential with the given id and emit a
|
|
1216
|
+
* {@link CredentialDisabledEvent}. Used by the auth-broker server to honour
|
|
1217
|
+
* `POST /v1/credential/:id/disable`. Returns `false` when no such row exists.
|
|
1218
|
+
*/
|
|
1219
|
+
disableCredentialById(id: number, disabledCause: string): boolean;
|
|
1220
|
+
/**
|
|
1221
|
+
* Upsert a credential into the underlying store, refresh the in-memory
|
|
1222
|
+
* snapshot, and return the redacted snapshot entries for the provider.
|
|
1223
|
+
*
|
|
1224
|
+
* Used by the auth-broker server to honour `POST /v1/credential`. The
|
|
1225
|
+
* persistence layer (`SqliteAuthCredentialStore.upsertAuthCredentialForProvider`)
|
|
1226
|
+
* does identity-key matching, so re-uploading the same email/account replaces
|
|
1227
|
+
* the existing row instead of inserting a duplicate.
|
|
1228
|
+
*/
|
|
1229
|
+
upsertCredential(provider: string, credential: AuthCredential): AuthCredentialSnapshotEntry[];
|
|
1230
|
+
/**
|
|
1231
|
+
* Broker-server seam: list non-expired persisted blocks for snapshot entries.
|
|
1232
|
+
*/
|
|
1233
|
+
listCredentialBlocks(credentialIds: readonly number[]): StoredCredentialBlock[];
|
|
1234
|
+
/**
|
|
1235
|
+
* Broker-server seam: persist one credential block and notify snapshot waiters.
|
|
1236
|
+
*/
|
|
1237
|
+
upsertCredentialBlock(block: StoredCredentialBlock): void;
|
|
1238
|
+
/**
|
|
1239
|
+
* Broker-server seam: clear all persisted blocks for one credential and notify snapshot waiters.
|
|
1240
|
+
*/
|
|
1241
|
+
deleteCredentialBlock(credentialId: number, providerKey: string, blockScope: string): void;
|
|
1242
|
+
deleteCredentialBlocks(credentialId: number): void;
|
|
1243
|
+
/**
|
|
1244
|
+
* Describe where the active credential for a provider came from.
|
|
1245
|
+
*
|
|
1246
|
+
* Mirrors {@link AuthStorage.getApiKey} precedence, highest first:
|
|
1247
|
+
* 1. Runtime override (`--api-key`).
|
|
1248
|
+
* 2. Config override (`models.yml` `providers.<name>.apiKey`).
|
|
1249
|
+
* 3. Stored OAuth credential.
|
|
1250
|
+
* 4. API key persisted by a successful `/login`.
|
|
1251
|
+
* 5. Env var — overrides a stored static api_key (e.g. a stale broker copy).
|
|
1252
|
+
* 6. Stored api_key credential.
|
|
1253
|
+
* 7. Fallback resolver.
|
|
1254
|
+
*
|
|
1255
|
+
* The string is purely informational; consumers must not parse it.
|
|
1256
|
+
*/
|
|
1257
|
+
describeCredentialSource(provider: string, sessionId?: string): string | undefined;
|
|
1258
|
+
}
|