@prometheus-ai/ai 0.5.3 → 0.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/types/auth-broker/remote-store.d.ts +2 -1
- package/dist/types/auth-broker/wire-schemas.d.ts +4 -1
- package/dist/types/auth-gateway/server.d.ts +19 -0
- package/dist/types/auth-gateway/types.d.ts +9 -3
- package/dist/types/auth-retry.d.ts +119 -0
- package/dist/types/auth-storage.d.ts +217 -8
- package/dist/types/errors.d.ts +24 -0
- package/dist/types/index.d.ts +5 -9
- package/dist/types/provider-details.d.ts +1 -1
- package/dist/types/providers/amazon-bedrock.d.ts +12 -6
- package/dist/types/providers/anthropic-client.d.ts +10 -3
- package/dist/types/providers/anthropic-messages-server-schema.d.ts +2 -2
- package/dist/types/providers/anthropic-messages-server.d.ts +3 -3
- package/dist/types/providers/anthropic-wire.d.ts +3 -3
- package/dist/types/providers/anthropic.d.ts +41 -34
- package/dist/types/providers/aws-credentials.d.ts +8 -0
- package/dist/types/providers/azure-openai-responses.d.ts +1 -0
- package/dist/types/providers/google-gemini-cli.d.ts +22 -1
- package/dist/types/providers/google-shared.d.ts +22 -0
- package/dist/types/providers/google-types.d.ts +13 -1
- package/dist/types/providers/mock.d.ts +8 -3
- package/dist/types/providers/ollama.d.ts +6 -0
- package/dist/types/providers/openai-chat-server-schema.d.ts +6 -3
- package/dist/types/providers/openai-chat-server.d.ts +3 -3
- package/dist/types/providers/openai-chat-wire.d.ts +644 -0
- package/dist/types/providers/openai-codex/request-transformer.d.ts +8 -0
- package/dist/types/providers/openai-codex/response-handler.d.ts +9 -0
- package/dist/types/providers/openai-codex-responses.d.ts +31 -2
- package/dist/types/providers/openai-completions-compat.d.ts +2 -25
- package/dist/types/providers/openai-completions.d.ts +2 -10
- package/dist/types/providers/openai-responses-server-schema.d.ts +4 -4
- package/dist/types/providers/openai-responses-server.d.ts +2 -2
- package/dist/types/providers/openai-responses-shared.d.ts +49 -9
- package/dist/types/providers/openai-responses-wire.d.ts +6065 -0
- package/dist/types/providers/openai-responses.d.ts +13 -4
- package/dist/types/providers/prometheus-native-client.d.ts +9 -0
- package/dist/types/providers/prometheus-native-server.d.ts +4 -3
- package/dist/types/providers/transform-messages.d.ts +1 -2
- package/dist/types/rate-limit-utils.d.ts +3 -2
- package/dist/types/registry/aimlapi.d.ts +4 -0
- package/dist/types/registry/alibaba-coding-plan.d.ts +7 -0
- package/dist/types/registry/amazon-bedrock.d.ts +5 -0
- package/dist/types/registry/anthropic.d.ts +10 -0
- package/dist/types/{utils/oauth → registry}/api-key-login.d.ts +8 -2
- package/dist/types/{utils/oauth → registry}/api-key-validation.d.ts +15 -0
- package/dist/types/registry/cerebras.d.ts +7 -0
- package/dist/types/registry/cloudflare-ai-gateway.d.ts +13 -0
- package/dist/types/registry/cursor.d.ts +7 -0
- package/dist/types/registry/deepseek.d.ts +8 -0
- package/dist/types/registry/derived.d.ts +5 -0
- package/dist/types/registry/firepass.d.ts +16 -0
- package/dist/types/registry/fireworks.d.ts +7 -0
- package/dist/types/registry/github-copilot.d.ts +7 -0
- package/dist/types/registry/gitlab-duo.d.ts +9 -0
- package/dist/types/registry/google-antigravity.d.ts +9 -0
- package/dist/types/registry/google-gemini-cli.d.ts +9 -0
- package/dist/types/registry/google-vertex.d.ts +5 -0
- package/dist/types/registry/google.d.ts +4 -0
- package/dist/types/registry/groq.d.ts +4 -0
- package/dist/types/registry/huggingface.d.ts +7 -0
- package/dist/types/registry/index.d.ts +4 -0
- package/dist/types/registry/kagi.d.ts +14 -0
- package/dist/types/registry/kilo.d.ts +7 -0
- package/dist/types/registry/kimi-code.d.ts +7 -0
- package/dist/types/registry/litellm.d.ts +13 -0
- package/dist/types/registry/lm-studio.d.ts +8 -0
- package/dist/types/registry/minimax-code-cn.d.ts +6 -0
- package/dist/types/registry/minimax-code.d.ts +6 -0
- package/dist/types/registry/minimax.d.ts +4 -0
- package/dist/types/registry/mistral.d.ts +4 -0
- package/dist/types/registry/moonshot.d.ts +7 -0
- package/dist/types/registry/nanogpt.d.ts +7 -0
- package/dist/types/registry/nvidia.d.ts +7 -0
- package/dist/types/registry/oauth/__tests__/xai-oauth.test.d.ts +1 -0
- package/dist/types/{utils → registry}/oauth/anthropic.d.ts +2 -1
- package/dist/types/{utils → registry}/oauth/github-copilot.d.ts +15 -23
- package/dist/types/{utils → registry}/oauth/index.d.ts +1 -0
- package/dist/types/{utils → registry}/oauth/minimax-code.d.ts +5 -5
- package/dist/types/{utils → registry}/oauth/types.d.ts +6 -1
- package/dist/types/{utils → registry}/oauth/xai-oauth.d.ts +2 -1
- package/dist/types/registry/ollama-cloud.d.ts +7 -0
- package/dist/types/registry/ollama.d.ts +12 -0
- package/dist/types/registry/openai-codex-device.d.ts +8 -0
- package/dist/types/registry/openai-codex.d.ts +9 -0
- package/dist/types/registry/openai.d.ts +4 -0
- package/dist/types/registry/opencode-go.d.ts +6 -0
- package/dist/types/registry/opencode-zen.d.ts +6 -0
- package/dist/types/registry/openrouter.d.ts +13 -0
- package/dist/types/registry/parallel.d.ts +14 -0
- package/dist/types/registry/perplexity.d.ts +7 -0
- package/dist/types/registry/qianfan.d.ts +7 -0
- package/dist/types/registry/qwen-portal.d.ts +7 -0
- package/dist/types/registry/registry.d.ts +272 -0
- package/dist/types/registry/synthetic.d.ts +6 -0
- package/dist/types/registry/tavily.d.ts +14 -0
- package/dist/types/registry/together.d.ts +6 -0
- package/dist/types/registry/types.d.ts +51 -0
- package/dist/types/registry/venice.d.ts +13 -0
- package/dist/types/registry/vercel-ai-gateway.d.ts +7 -0
- package/dist/types/registry/vllm.d.ts +7 -0
- package/dist/types/registry/wafer-pass.d.ts +6 -0
- package/dist/types/registry/wafer-serverless.d.ts +6 -0
- package/dist/types/registry/xai-oauth.d.ts +7 -0
- package/dist/types/registry/xai.d.ts +4 -0
- package/dist/types/registry/xiaomi-token-plan-ams.d.ts +6 -0
- package/dist/types/registry/xiaomi-token-plan-cn.d.ts +6 -0
- package/dist/types/registry/xiaomi-token-plan-sgp.d.ts +6 -0
- package/dist/types/registry/xiaomi.d.ts +6 -0
- package/dist/types/registry/zai.d.ts +7 -0
- package/dist/types/registry/zenmux.d.ts +7 -0
- package/dist/types/registry/zhipu-coding-plan.d.ts +7 -0
- package/dist/types/stream.d.ts +9 -1
- package/dist/types/types.d.ts +56 -295
- package/dist/types/usage/google-antigravity.d.ts +15 -1
- package/dist/types/usage/openai-codex-reset.d.ts +79 -0
- package/dist/types/usage/openai-codex.d.ts +1 -0
- package/dist/types/usage.d.ts +77 -4
- package/dist/types/utils/abort.d.ts +6 -0
- package/dist/types/utils/event-stream.d.ts +2 -0
- package/dist/types/utils/http-inspector.d.ts +0 -1
- package/dist/types/utils/idle-iterator.d.ts +35 -0
- package/dist/types/utils/openai-http.d.ts +58 -0
- package/dist/types/utils/request-debug.d.ts +3 -0
- package/dist/types/utils/retry-after.d.ts +1 -0
- package/dist/types/utils/schema/fields.d.ts +5 -0
- package/dist/types/utils/schema/json-schema-validator.d.ts +8 -0
- package/dist/types/utils/schema/stamps.d.ts +7 -15
- package/dist/types/utils/sse-debug.d.ts +0 -5
- package/dist/types/utils/stream-markup-healing.d.ts +2 -0
- package/dist/types/utils.d.ts +1 -5
- package/package.json +17 -29
- package/src/auth-broker/remote-store.ts +10 -1
- package/src/auth-broker/snapshot-cache.ts +1 -1
- package/src/auth-broker/wire-schemas.ts +1 -1
- package/src/auth-gateway/http.ts +1 -1
- package/src/auth-gateway/server.ts +95 -30
- package/src/auth-gateway/types.ts +10 -2
- package/src/auth-retry.ts +238 -0
- package/src/auth-storage.ts +935 -430
- package/src/errors.ts +32 -0
- package/src/index.ts +9 -14
- package/src/provider-details.ts +1 -1
- package/src/providers/__tests__/google-auth.test.ts +144 -0
- package/src/providers/amazon-bedrock.ts +70 -40
- package/src/providers/anthropic-client.ts +15 -13
- package/src/providers/anthropic-messages-server-schema.ts +17 -7
- package/src/providers/anthropic-messages-server.ts +88 -20
- package/src/providers/anthropic-wire.ts +4 -3
- package/src/providers/anthropic.ts +1234 -621
- package/src/providers/aws-credentials.ts +47 -5
- package/src/providers/aws-eventstream.ts +5 -0
- package/src/providers/azure-openai-responses.ts +117 -67
- package/src/providers/cursor.ts +30 -30
- package/src/providers/github-copilot-headers.ts +1 -1
- package/src/providers/gitlab-duo.ts +36 -29
- package/src/providers/google-auth.ts +71 -8
- package/src/providers/google-gemini-cli.ts +118 -22
- package/src/providers/google-shared.ts +163 -43
- package/src/providers/google-types.ts +10 -1
- package/src/providers/kimi.ts +1 -1
- package/src/providers/mock.ts +11 -3
- package/src/providers/ollama.ts +64 -7
- package/src/providers/openai-anthropic-shim.ts +17 -8
- package/src/providers/openai-chat-server-schema.ts +9 -3
- package/src/providers/openai-chat-server.ts +82 -16
- package/src/providers/openai-chat-wire.ts +847 -0
- package/src/providers/openai-codex/request-transformer.ts +129 -34
- package/src/providers/openai-codex/response-handler.ts +22 -1
- package/src/providers/openai-codex-responses.ts +699 -247
- package/src/providers/openai-completions-compat.ts +8 -308
- package/src/providers/openai-completions.ts +416 -267
- package/src/providers/openai-responses-server-schema.ts +15 -9
- package/src/providers/openai-responses-server.ts +162 -114
- package/src/providers/openai-responses-shared.ts +320 -82
- package/src/providers/openai-responses-wire.ts +6391 -0
- package/src/providers/openai-responses.ts +382 -176
- package/src/providers/prometheus-native-client.ts +27 -11
- package/src/providers/prometheus-native-server.ts +44 -17
- package/src/providers/transform-messages.ts +311 -120
- package/src/providers/vision-guard.ts +5 -3
- package/src/rate-limit-utils.ts +13 -3
- package/src/registry/aimlapi.ts +6 -0
- package/src/{utils/oauth → registry}/alibaba-coding-plan.ts +8 -18
- package/src/registry/amazon-bedrock.ts +22 -0
- package/src/registry/anthropic.ts +26 -0
- package/src/{utils/oauth → registry}/api-key-login.ts +25 -3
- package/src/{utils/oauth → registry}/api-key-validation.ts +62 -2
- package/src/{utils/oauth → registry}/cerebras.ts +8 -1
- package/src/{utils/oauth → registry}/cloudflare-ai-gateway.ts +8 -12
- package/src/registry/cursor.ts +20 -0
- package/src/{utils/oauth → registry}/deepseek.ts +9 -17
- package/src/registry/derived.ts +9 -0
- package/src/{utils/oauth → registry}/firepass.ts +10 -2
- package/src/{utils/oauth → registry}/fireworks.ts +8 -1
- package/src/registry/github-copilot.ts +22 -0
- package/src/registry/gitlab-duo.ts +19 -0
- package/src/registry/google-antigravity.ts +21 -0
- package/src/registry/google-gemini-cli.ts +21 -0
- package/src/registry/google-vertex.ts +38 -0
- package/src/registry/google.ts +6 -0
- package/src/registry/groq.ts +6 -0
- package/src/{utils/oauth → registry}/huggingface.ts +8 -19
- package/src/registry/index.ts +4 -0
- package/src/{utils/oauth → registry}/kagi.ts +9 -11
- package/src/{utils/oauth → registry}/kilo.ts +11 -6
- package/src/registry/kimi-code.ts +17 -0
- package/src/{utils/oauth → registry}/litellm.ts +8 -12
- package/src/{utils/oauth → registry}/lm-studio.ts +9 -17
- package/src/registry/minimax-code-cn.ts +12 -0
- package/src/registry/minimax-code.ts +12 -0
- package/src/registry/minimax.ts +6 -0
- package/src/registry/mistral.ts +6 -0
- package/src/{utils/oauth → registry}/moonshot.ts +8 -9
- package/src/{utils/oauth → registry}/nanogpt.ts +8 -1
- package/src/{utils/oauth → registry}/nvidia.ts +8 -18
- package/src/{utils → registry}/oauth/__tests__/xai-oauth.test.ts +4 -7
- package/src/{utils → registry}/oauth/anthropic.ts +38 -17
- package/src/{utils → registry}/oauth/github-copilot.ts +79 -115
- package/src/registry/oauth/gitlab-duo.ts +198 -0
- package/src/{utils → registry}/oauth/google-antigravity.ts +1 -4
- package/src/{utils → registry}/oauth/google-gemini-cli.ts +1 -4
- package/src/registry/oauth/index.ts +164 -0
- package/src/{utils → registry}/oauth/minimax-code.ts +16 -14
- package/src/{utils → registry}/oauth/types.ts +7 -51
- package/src/{utils → registry}/oauth/wafer.ts +1 -1
- package/src/{utils → registry}/oauth/xai-oauth.ts +16 -8
- package/src/{utils → registry}/oauth/xiaomi.ts +9 -4
- package/src/{utils/oauth → registry}/ollama-cloud.ts +8 -1
- package/src/{utils/oauth → registry}/ollama.ts +8 -13
- package/src/registry/openai-codex-device.ts +18 -0
- package/src/registry/openai-codex.ts +19 -0
- package/src/registry/openai.ts +6 -0
- package/src/registry/opencode-go.ts +12 -0
- package/src/registry/opencode-zen.ts +12 -0
- package/src/{utils/oauth → registry}/openrouter.ts +10 -2
- package/src/{utils/oauth → registry}/parallel.ts +9 -11
- package/src/registry/perplexity.ts +13 -0
- package/src/{utils/oauth → registry}/qianfan.ts +8 -17
- package/src/{utils/oauth → registry}/qwen-portal.ts +8 -19
- package/src/registry/registry.ts +149 -0
- package/src/{utils/oauth → registry}/synthetic.ts +7 -1
- package/src/{utils/oauth → registry}/tavily.ts +10 -12
- package/src/{utils/oauth → registry}/together.ts +7 -1
- package/src/registry/types.ts +56 -0
- package/src/{utils/oauth → registry}/venice.ts +8 -12
- package/src/{utils/oauth → registry}/vercel-ai-gateway.ts +8 -18
- package/src/{utils/oauth → registry}/vllm.ts +9 -16
- package/src/registry/wafer-pass.ts +12 -0
- package/src/registry/wafer-serverless.ts +12 -0
- package/src/registry/xai-oauth.ts +17 -0
- package/src/registry/xai.ts +6 -0
- package/src/registry/xiaomi-token-plan-ams.ts +12 -0
- package/src/registry/xiaomi-token-plan-cn.ts +12 -0
- package/src/registry/xiaomi-token-plan-sgp.ts +12 -0
- package/src/registry/xiaomi.ts +12 -0
- package/src/{utils/oauth → registry}/zai.ts +10 -22
- package/src/{utils/oauth → registry}/zenmux.ts +8 -1
- package/src/{utils/oauth/zhipu.ts → registry/zhipu-coding-plan.ts} +9 -21
- package/src/stream.ts +229 -199
- package/src/types.ts +63 -384
- package/src/usage/claude.ts +4 -2
- package/src/usage/github-copilot.ts +4 -2
- package/src/usage/google-antigravity.ts +196 -28
- package/src/usage/kimi.ts +1 -1
- package/src/usage/minimax-code.ts +5 -6
- package/src/usage/openai-codex-reset.ts +174 -0
- package/src/usage/openai-codex.ts +19 -2
- package/src/usage/zai.ts +2 -1
- package/src/usage.ts +93 -4
- package/src/utils/abort.ts +14 -0
- package/src/utils/event-stream.ts +17 -0
- package/src/utils/http-inspector.ts +4 -12
- package/src/utils/idle-iterator.ts +250 -79
- package/src/utils/openai-http.ts +157 -0
- package/src/utils/request-debug.ts +67 -19
- package/src/utils/retry-after.ts +1 -1
- package/src/utils/retry.ts +23 -2
- package/src/utils/schema/CONSTRAINTS.md +4 -2
- package/src/utils/schema/fields.ts +16 -0
- package/src/utils/schema/json-schema-validator.ts +19 -1
- package/src/utils/schema/normalize.ts +80 -8
- package/src/utils/schema/stamps.ts +22 -10
- package/src/utils/schema/wire.ts +2 -2
- package/src/utils/sse-debug.ts +0 -271
- package/src/utils/stream-markup-healing.ts +50 -8
- package/src/utils/validation.ts +49 -13
- package/src/utils.ts +2 -26
- package/dist/types/model-cache.d.ts +0 -17
- package/dist/types/model-manager.d.ts +0 -64
- package/dist/types/model-thinking.d.ts +0 -100
- package/dist/types/models.d.ts +0 -12
- package/dist/types/provider-models/bundled-references.d.ts +0 -4
- package/dist/types/provider-models/descriptors.d.ts +0 -50
- package/dist/types/provider-models/google.d.ts +0 -24
- package/dist/types/provider-models/index.d.ts +0 -5
- package/dist/types/provider-models/ollama.d.ts +0 -7
- package/dist/types/provider-models/openai-compat.d.ts +0 -323
- package/dist/types/provider-models/special.d.ts +0 -16
- package/dist/types/utils/discovery/antigravity.d.ts +0 -61
- package/dist/types/utils/discovery/codex.d.ts +0 -38
- package/dist/types/utils/discovery/cursor.d.ts +0 -23
- package/dist/types/utils/discovery/gemini.d.ts +0 -25
- package/dist/types/utils/discovery/index.d.ts +0 -4
- package/dist/types/utils/discovery/openai-compatible.d.ts +0 -72
- package/dist/types/utils/oauth/alibaba-coding-plan.d.ts +0 -18
- package/dist/types/utils/oauth/cerebras.d.ts +0 -1
- package/dist/types/utils/oauth/cloudflare-ai-gateway.d.ts +0 -18
- package/dist/types/utils/oauth/deepseek.d.ts +0 -10
- package/dist/types/utils/oauth/firepass.d.ts +0 -1
- package/dist/types/utils/oauth/fireworks.d.ts +0 -1
- package/dist/types/utils/oauth/huggingface.d.ts +0 -19
- package/dist/types/utils/oauth/kagi.d.ts +0 -17
- package/dist/types/utils/oauth/kilo.d.ts +0 -5
- package/dist/types/utils/oauth/litellm.d.ts +0 -18
- package/dist/types/utils/oauth/lm-studio.d.ts +0 -17
- package/dist/types/utils/oauth/moonshot.d.ts +0 -1
- package/dist/types/utils/oauth/nanogpt.d.ts +0 -1
- package/dist/types/utils/oauth/nvidia.d.ts +0 -18
- package/dist/types/utils/oauth/ollama-cloud.d.ts +0 -2
- package/dist/types/utils/oauth/ollama.d.ts +0 -18
- package/dist/types/utils/oauth/openrouter.d.ts +0 -1
- package/dist/types/utils/oauth/parallel.d.ts +0 -17
- package/dist/types/utils/oauth/qianfan.d.ts +0 -17
- package/dist/types/utils/oauth/qwen-portal.d.ts +0 -19
- package/dist/types/utils/oauth/synthetic.d.ts +0 -1
- package/dist/types/utils/oauth/tavily.d.ts +0 -17
- package/dist/types/utils/oauth/together.d.ts +0 -1
- package/dist/types/utils/oauth/venice.d.ts +0 -18
- package/dist/types/utils/oauth/vercel-ai-gateway.d.ts +0 -18
- package/dist/types/utils/oauth/vllm.d.ts +0 -16
- package/dist/types/utils/oauth/zai.d.ts +0 -18
- package/dist/types/utils/oauth/zenmux.d.ts +0 -1
- package/dist/types/utils/oauth/zhipu.d.ts +0 -18
- package/src/model-cache.ts +0 -129
- package/src/model-manager.ts +0 -469
- package/src/model-thinking.ts +0 -756
- package/src/models.json +0 -60287
- package/src/models.json.d.ts +0 -9
- package/src/models.ts +0 -56
- package/src/provider-models/bundled-references.ts +0 -38
- package/src/provider-models/descriptors.ts +0 -364
- package/src/provider-models/google.ts +0 -88
- package/src/provider-models/index.ts +0 -5
- package/src/provider-models/ollama.ts +0 -153
- package/src/provider-models/openai-compat.ts +0 -2904
- package/src/provider-models/special.ts +0 -67
- package/src/utils/discovery/antigravity.ts +0 -261
- package/src/utils/discovery/codex.ts +0 -371
- package/src/utils/discovery/cursor.ts +0 -306
- package/src/utils/discovery/gemini.ts +0 -248
- package/src/utils/discovery/index.ts +0 -4
- package/src/utils/discovery/openai-compatible.ts +0 -224
- package/src/utils/oauth/gitlab-duo.ts +0 -123
- package/src/utils/oauth/index.ts +0 -502
- /package/dist/types/{utils/oauth/__tests__/xai-oauth.test.d.ts → providers/__tests__/google-auth.test.d.ts} +0 -0
- /package/dist/types/{utils → registry}/oauth/callback-server.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/cursor.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/gitlab-duo.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/google-antigravity.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/google-gemini-cli.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/google-oauth-shared.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/kimi.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/openai-codex.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/opencode.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/perplexity.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/pkce.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/wafer.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/xiaomi.d.ts +0 -0
- /package/src/{utils → registry}/oauth/callback-server.ts +0 -0
- /package/src/{utils → registry}/oauth/cursor.ts +0 -0
- /package/src/{utils → registry}/oauth/google-oauth-shared.ts +0 -0
- /package/src/{utils → registry}/oauth/kimi.ts +0 -0
- /package/src/{utils → registry}/oauth/oauth.html +0 -0
- /package/src/{utils → registry}/oauth/openai-codex.ts +0 -0
- /package/src/{utils → registry}/oauth/opencode.ts +0 -0
- /package/src/{utils → registry}/oauth/perplexity.ts +0 -0
- /package/src/{utils → registry}/oauth/pkce.ts +0 -0
|
@@ -23,6 +23,7 @@ import * as fs from "node:fs";
|
|
|
23
23
|
import * as os from "node:os";
|
|
24
24
|
import * as path from "node:path";
|
|
25
25
|
import { $env, isEnoent, logger } from "@prometheus-ai/utils";
|
|
26
|
+
import { raceWithSignal } from "../utils/abort";
|
|
26
27
|
import type { AwsCredentials } from "./aws-sigv4";
|
|
27
28
|
|
|
28
29
|
export interface ResolvedCredentials extends AwsCredentials {
|
|
@@ -39,6 +40,17 @@ export interface CredentialResolveOptions {
|
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
const REFRESH_SKEW_MS = 60_000;
|
|
43
|
+
/**
|
|
44
|
+
* TTL for file-sourced credentials that carry a session token but no expiry.
|
|
45
|
+
* Tools like aws-vault/saml2aws rewrite ~/.aws/credentials with short-lived STS
|
|
46
|
+
* session keys; caching them forever serves stale creds after rotation.
|
|
47
|
+
*/
|
|
48
|
+
const FILE_SESSION_CREDS_TTL_MS = 5 * 60_000;
|
|
49
|
+
/**
|
|
50
|
+
* Bound for the detached (signal-free) shared resolution: a hung
|
|
51
|
+
* credential_process/SSO/IMDS fetch must not pin the inflight slot forever.
|
|
52
|
+
*/
|
|
53
|
+
const SHARED_RESOLVE_TIMEOUT_MS = 30_000;
|
|
42
54
|
|
|
43
55
|
interface CacheEntry {
|
|
44
56
|
creds: ResolvedCredentials;
|
|
@@ -46,6 +58,7 @@ interface CacheEntry {
|
|
|
46
58
|
}
|
|
47
59
|
|
|
48
60
|
const cache: Map<string, CacheEntry> = new Map();
|
|
61
|
+
const inflight: Map<string, Promise<ResolvedCredentials>> = new Map();
|
|
49
62
|
|
|
50
63
|
export async function resolveAwsCredentials(opts: CredentialResolveOptions = {}): Promise<ResolvedCredentials> {
|
|
51
64
|
const profile = opts.profile || $env.AWS_PROFILE || "default";
|
|
@@ -55,9 +68,24 @@ export async function resolveAwsCredentials(opts: CredentialResolveOptions = {})
|
|
|
55
68
|
const hit = cache.get(cacheKey);
|
|
56
69
|
if (hit && hit.expiresAt - REFRESH_SKEW_MS > Date.now()) return hit.creds;
|
|
57
70
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
71
|
+
// Single-flight: N concurrent cold calls must not each spawn credential_process/SSO/IMDS fetches.
|
|
72
|
+
// The shared resolution is deliberately detached from any caller's signal — aborting one
|
|
73
|
+
// request must not fail every waiter — and bounded by its own timeout instead; each caller
|
|
74
|
+
// races its own signal against the shared promise.
|
|
75
|
+
const existing = inflight.get(cacheKey);
|
|
76
|
+
if (existing) return raceWithSignal(existing, opts.signal);
|
|
77
|
+
|
|
78
|
+
const promise = (async () => {
|
|
79
|
+
try {
|
|
80
|
+
const creds = await resolveFresh(profile, region, AbortSignal.timeout(SHARED_RESOLVE_TIMEOUT_MS));
|
|
81
|
+
cache.set(cacheKey, { creds, expiresAt: creds.expiresAt ?? Number.POSITIVE_INFINITY });
|
|
82
|
+
return creds;
|
|
83
|
+
} finally {
|
|
84
|
+
inflight.delete(cacheKey);
|
|
85
|
+
}
|
|
86
|
+
})();
|
|
87
|
+
inflight.set(cacheKey, promise);
|
|
88
|
+
return raceWithSignal(promise, opts.signal);
|
|
61
89
|
}
|
|
62
90
|
|
|
63
91
|
async function resolveFresh(profile: string, region: string, signal?: AbortSignal): Promise<ResolvedCredentials> {
|
|
@@ -157,7 +185,12 @@ async function readProfileCredentials(
|
|
|
157
185
|
accessKeyId: merged.aws_access_key_id,
|
|
158
186
|
secretAccessKey: merged.aws_secret_access_key,
|
|
159
187
|
};
|
|
160
|
-
if (merged.aws_session_token)
|
|
188
|
+
if (merged.aws_session_token) {
|
|
189
|
+
out.sessionToken = merged.aws_session_token;
|
|
190
|
+
// Session-token creds in the credentials file are short-lived STS keys that
|
|
191
|
+
// external tools rotate in place; cap the cache so rotations are picked up.
|
|
192
|
+
out.expiresAt = Date.now() + FILE_SESSION_CREDS_TTL_MS;
|
|
193
|
+
}
|
|
161
194
|
return out;
|
|
162
195
|
}
|
|
163
196
|
|
|
@@ -302,7 +335,6 @@ async function readCredentialProcess(
|
|
|
302
335
|
signal: AbortSignal | undefined,
|
|
303
336
|
): Promise<ResolvedCredentials> {
|
|
304
337
|
const argv = buildCredentialProcessArgv(profile, command);
|
|
305
|
-
|
|
306
338
|
const child = Bun.spawn(argv, {
|
|
307
339
|
stdin: "ignore",
|
|
308
340
|
stdout: "pipe",
|
|
@@ -499,3 +531,13 @@ async function readImdsCredentials(parentSignal: AbortSignal | undefined): Promi
|
|
|
499
531
|
export function clearAwsCredentialCache(): void {
|
|
500
532
|
cache.clear();
|
|
501
533
|
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Drop the cache entry for one profile/region. Called by the Bedrock provider on
|
|
537
|
+
* 401/403 responses so stale credentials are re-resolved instead of served until restart.
|
|
538
|
+
*/
|
|
539
|
+
export function invalidateAwsCredentialCache(opts: { profile?: string; region?: string } = {}): void {
|
|
540
|
+
const profile = opts.profile || $env.AWS_PROFILE || "default";
|
|
541
|
+
const region = opts.region || $env.AWS_REGION || $env.AWS_DEFAULT_REGION || "us-east-1";
|
|
542
|
+
cache.delete(`${profile}\x00${region}`);
|
|
543
|
+
}
|
|
@@ -161,6 +161,7 @@ export async function* decodeEventStream(source: ReadableStream<Uint8Array>): As
|
|
|
161
161
|
// Single growable buffer; we slide a read cursor along it and compact when a
|
|
162
162
|
// complete prefix has been consumed. Avoids per-message Uint8Array copies.
|
|
163
163
|
let buf: Uint8Array<ArrayBufferLike> = new Uint8Array(0);
|
|
164
|
+
let completed = false;
|
|
164
165
|
try {
|
|
165
166
|
while (true) {
|
|
166
167
|
const { value, done } = await reader.read();
|
|
@@ -179,7 +180,11 @@ export async function* decodeEventStream(source: ReadableStream<Uint8Array>): As
|
|
|
179
180
|
if (done) break;
|
|
180
181
|
}
|
|
181
182
|
if (buf.length > 0) throw new Error("eventstream: truncated message at end of stream");
|
|
183
|
+
completed = true;
|
|
182
184
|
} finally {
|
|
185
|
+
// On abnormal exit (consumer threw/broke, decode error) cancel the body so the
|
|
186
|
+
// HTTP connection is released instead of draining until GC.
|
|
187
|
+
if (!completed) await reader.cancel().catch(() => {});
|
|
183
188
|
reader.releaseLock();
|
|
184
189
|
}
|
|
185
190
|
}
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import { $env, extractHttpStatusFromError } from "@prometheus-ai/utils";
|
|
2
|
-
import { AzureOpenAI, APIConnectionTimeoutError as OpenAIConnectionTimeoutError } from "openai";
|
|
3
|
-
import type {
|
|
4
|
-
Tool as OpenAITool,
|
|
5
|
-
ResponseCreateParamsStreaming,
|
|
6
|
-
ResponseInput,
|
|
7
|
-
ResponseStreamEvent,
|
|
8
|
-
} from "openai/resources/responses/responses";
|
|
9
2
|
import { getEnvApiKey } from "../stream";
|
|
10
3
|
import type {
|
|
11
4
|
AssistantMessage,
|
|
12
5
|
Context,
|
|
13
6
|
Model,
|
|
7
|
+
RawSseEvent,
|
|
14
8
|
ServiceTier,
|
|
15
9
|
StreamFunction,
|
|
16
10
|
StreamOptions,
|
|
@@ -26,10 +20,10 @@ import {
|
|
|
26
20
|
getOpenAIStreamIdleTimeoutMs,
|
|
27
21
|
iterateWithIdleTimeout,
|
|
28
22
|
} from "../utils/idle-iterator";
|
|
23
|
+
import { postOpenAIStream } from "../utils/openai-http";
|
|
29
24
|
import { sanitizeSchemaForOpenAIResponses, toolWireSchema } from "../utils/schema";
|
|
30
|
-
import { wrapFetchForSseDebug } from "../utils/sse-debug";
|
|
31
25
|
import { mapToOpenAIResponsesToolChoice } from "../utils/tool-choice";
|
|
32
|
-
import {
|
|
26
|
+
import { getOpenAIResponsesCacheSessionId } from "./openai-responses";
|
|
33
27
|
import {
|
|
34
28
|
appendResponsesToolResultMessages,
|
|
35
29
|
applyCommonResponsesSamplingParams,
|
|
@@ -40,14 +34,21 @@ import {
|
|
|
40
34
|
isOpenAIResponsesProgressEvent,
|
|
41
35
|
normalizeResponsesToolCallIdForTransform,
|
|
42
36
|
processResponsesStream,
|
|
37
|
+
repairOrphanResponsesToolCalls,
|
|
43
38
|
} from "./openai-responses-shared";
|
|
39
|
+
import type {
|
|
40
|
+
Tool as OpenAITool,
|
|
41
|
+
ResponseCreateParamsStreaming,
|
|
42
|
+
ResponseInput,
|
|
43
|
+
ResponseStreamEvent,
|
|
44
|
+
} from "./openai-responses-wire";
|
|
44
45
|
import { transformMessages } from "./transform-messages";
|
|
45
46
|
|
|
46
47
|
const DEFAULT_AZURE_API_VERSION = "v1";
|
|
47
48
|
const AZURE_OPENAI_RESPONSES_FIRST_EVENT_TIMEOUT_MESSAGE =
|
|
48
49
|
"Azure OpenAI responses stream timed out while waiting for the first event";
|
|
49
50
|
|
|
50
|
-
function
|
|
51
|
+
export function parseAzureDeploymentNameMap(value: string | undefined): Map<string, string> {
|
|
51
52
|
const map = new Map<string, string>();
|
|
52
53
|
if (!value) return map;
|
|
53
54
|
for (const entry of value.split(",")) {
|
|
@@ -64,7 +65,7 @@ function resolveDeploymentName(model: Model<"azure-openai-responses">, options?:
|
|
|
64
65
|
if (options?.azureDeploymentName) {
|
|
65
66
|
return options.azureDeploymentName;
|
|
66
67
|
}
|
|
67
|
-
const mappedDeployment =
|
|
68
|
+
const mappedDeployment = parseAzureDeploymentNameMap($env.AZURE_OPENAI_DEPLOYMENT_NAME_MAP).get(model.id);
|
|
68
69
|
return mappedDeployment ?? model.id;
|
|
69
70
|
}
|
|
70
71
|
|
|
@@ -113,13 +114,32 @@ export const streamAzureOpenAIResponses: StreamFunction<"azure-openai-responses"
|
|
|
113
114
|
const abortTracker = createAbortSourceTracker(options?.signal);
|
|
114
115
|
const firstEventTimeoutAbortError = new Error(AZURE_OPENAI_RESPONSES_FIRST_EVENT_TIMEOUT_MESSAGE);
|
|
115
116
|
const { requestAbortController, requestSignal } = abortTracker;
|
|
117
|
+
const onSseEvent = options?.onSseEvent;
|
|
118
|
+
const rawSseObserver = onSseEvent
|
|
119
|
+
? (event: RawSseEvent) => {
|
|
120
|
+
if (!event.event && event.data && event.data !== "[DONE]") {
|
|
121
|
+
try {
|
|
122
|
+
const parsed = JSON.parse(event.data);
|
|
123
|
+
const resolvedEvent =
|
|
124
|
+
typeof parsed.type === "string"
|
|
125
|
+
? parsed.type
|
|
126
|
+
: typeof parsed.object === "string"
|
|
127
|
+
? parsed.object
|
|
128
|
+
: null;
|
|
129
|
+
if (resolvedEvent) {
|
|
130
|
+
event.event = resolvedEvent;
|
|
131
|
+
event.raw = [`event: ${resolvedEvent}`, ...event.raw];
|
|
132
|
+
}
|
|
133
|
+
} catch {}
|
|
134
|
+
}
|
|
135
|
+
onSseEvent(event, model);
|
|
136
|
+
}
|
|
137
|
+
: undefined;
|
|
116
138
|
|
|
117
139
|
try {
|
|
118
|
-
// Create Azure OpenAI client
|
|
119
140
|
const apiKey = options?.apiKey || getEnvApiKey(model.provider) || "";
|
|
120
|
-
const
|
|
121
|
-
const
|
|
122
|
-
const params = buildParams(model, context, options, deploymentName, baseUrl);
|
|
141
|
+
const { url, headers } = buildAzureResponsesRequest(model, apiKey, options);
|
|
142
|
+
const params = buildParams(model, context, options, deploymentName);
|
|
123
143
|
options?.onPayload?.(params);
|
|
124
144
|
const idleTimeoutMs = options?.streamIdleTimeoutMs ?? getOpenAIStreamIdleTimeoutMs();
|
|
125
145
|
const firstEventTimeoutMs =
|
|
@@ -131,7 +151,7 @@ export const streamAzureOpenAIResponses: StreamFunction<"azure-openai-responses"
|
|
|
131
151
|
api: output.api,
|
|
132
152
|
model: model.id,
|
|
133
153
|
method: "POST",
|
|
134
|
-
url
|
|
154
|
+
url,
|
|
135
155
|
body: params,
|
|
136
156
|
};
|
|
137
157
|
let requestTimeout: NodeJS.Timeout | undefined;
|
|
@@ -140,41 +160,45 @@ export const streamAzureOpenAIResponses: StreamFunction<"azure-openai-responses"
|
|
|
140
160
|
}
|
|
141
161
|
let openaiStream: AsyncIterable<ResponseStreamEvent>;
|
|
142
162
|
try {
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
: { signal: requestSignal, timeout: requestTimeoutMs };
|
|
147
|
-
openaiStream = await client.responses.create(params, requestOptions);
|
|
148
|
-
} catch (error) {
|
|
149
|
-
if (error instanceof OpenAIConnectionTimeoutError && !abortTracker.wasCallerAbort()) {
|
|
150
|
-
throw firstEventTimeoutAbortError;
|
|
163
|
+
const headersWithTimeout = { ...headers };
|
|
164
|
+
if (requestTimeoutMs !== undefined) {
|
|
165
|
+
headersWithTimeout["X-Stainless-Timeout"] = Math.floor(requestTimeoutMs / 1000).toString();
|
|
151
166
|
}
|
|
152
|
-
|
|
167
|
+
const handle = await postOpenAIStream<ResponseStreamEvent>({
|
|
168
|
+
url,
|
|
169
|
+
headers: headersWithTimeout,
|
|
170
|
+
body: params,
|
|
171
|
+
signal: requestSignal,
|
|
172
|
+
fetch: options?.fetch,
|
|
173
|
+
// Watchdog armed → no retries, so they cannot silently extend the deadline.
|
|
174
|
+
maxAttempts: requestTimeoutMs !== undefined ? 1 : undefined,
|
|
175
|
+
onSseEvent: rawSseObserver,
|
|
176
|
+
});
|
|
177
|
+
openaiStream = handle.events;
|
|
153
178
|
} finally {
|
|
154
179
|
if (requestTimeout !== undefined) clearTimeout(requestTimeout);
|
|
155
180
|
}
|
|
156
181
|
stream.push({ type: "start", partial: output });
|
|
157
182
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
{
|
|
173
|
-
onFirstToken: () => {
|
|
174
|
-
if (!firstTokenTime) firstTokenTime = Date.now();
|
|
175
|
-
},
|
|
183
|
+
const timedOpenaiStream = iterateWithIdleTimeout(openaiStream, {
|
|
184
|
+
idleTimeoutMs,
|
|
185
|
+
firstItemTimeoutMs: firstEventTimeoutMs,
|
|
186
|
+
firstItemErrorMessage: AZURE_OPENAI_RESPONSES_FIRST_EVENT_TIMEOUT_MESSAGE,
|
|
187
|
+
errorMessage: "Azure OpenAI responses stream stalled while waiting for the next event",
|
|
188
|
+
onIdle: () => requestAbortController.abort(),
|
|
189
|
+
onFirstItemTimeout: () => abortTracker.abortLocally(firstEventTimeoutAbortError),
|
|
190
|
+
abortSignal: options?.signal,
|
|
191
|
+
isProgressItem: isOpenAIResponsesProgressEvent,
|
|
192
|
+
});
|
|
193
|
+
let sawCompleted = false;
|
|
194
|
+
await processResponsesStream(timedOpenaiStream, output, stream, model, {
|
|
195
|
+
onFirstToken: () => {
|
|
196
|
+
if (!firstTokenTime) firstTokenTime = Date.now();
|
|
176
197
|
},
|
|
177
|
-
|
|
198
|
+
onCompleted: () => {
|
|
199
|
+
sawCompleted = true;
|
|
200
|
+
},
|
|
201
|
+
});
|
|
178
202
|
|
|
179
203
|
const firstEventTimeoutError = abortTracker.getLocalAbortReason();
|
|
180
204
|
if (firstEventTimeoutError) {
|
|
@@ -185,6 +209,10 @@ export const streamAzureOpenAIResponses: StreamFunction<"azure-openai-responses"
|
|
|
185
209
|
throw new Error("Request was aborted");
|
|
186
210
|
}
|
|
187
211
|
|
|
212
|
+
if (!sawCompleted) {
|
|
213
|
+
throw new Error("Azure OpenAI responses stream closed before response.completed was received");
|
|
214
|
+
}
|
|
215
|
+
|
|
188
216
|
if (output.stopReason === "aborted" || output.stopReason === "error") {
|
|
189
217
|
throw new Error(output.errorMessage ?? "An unknown error occurred");
|
|
190
218
|
}
|
|
@@ -248,7 +276,20 @@ function resolveAzureConfig(
|
|
|
248
276
|
};
|
|
249
277
|
}
|
|
250
278
|
|
|
251
|
-
|
|
279
|
+
/**
|
|
280
|
+
* Replicates the `AzureOpenAI` SDK client's request shape for `/responses`:
|
|
281
|
+
* a string api key becomes a single `api-key` header (azure.mjs `authHeaders`;
|
|
282
|
+
* never `Authorization: Bearer`), `api-version` rides as a query parameter
|
|
283
|
+
* (azure.mjs constructor `defaultQuery`), and `/responses` is not a
|
|
284
|
+
* deployment-scoped path, so no `/deployments/{model}` URL rewriting applies.
|
|
285
|
+
* Custom model/options headers may override the auth header, matching the SDK's
|
|
286
|
+
* `buildHeaders` precedence.
|
|
287
|
+
*/
|
|
288
|
+
function buildAzureResponsesRequest(
|
|
289
|
+
model: Model<"azure-openai-responses">,
|
|
290
|
+
apiKey: string,
|
|
291
|
+
options?: AzureOpenAIResponsesOptions,
|
|
292
|
+
): { url: string; headers: Record<string, string> } {
|
|
252
293
|
if (!apiKey) {
|
|
253
294
|
const envKey = $env.AZURE_OPENAI_API_KEY;
|
|
254
295
|
if (!envKey) {
|
|
@@ -259,25 +300,17 @@ function createClient(model: Model<"azure-openai-responses">, apiKey: string, op
|
|
|
259
300
|
apiKey = envKey;
|
|
260
301
|
}
|
|
261
302
|
|
|
262
|
-
const headers = { ...(model.headers ?? {}) };
|
|
263
|
-
|
|
303
|
+
const headers: Record<string, string> = { "api-key": apiKey, ...(model.headers ?? {}) };
|
|
264
304
|
if (options?.headers) {
|
|
265
305
|
Object.assign(headers, options.headers);
|
|
266
306
|
}
|
|
267
307
|
|
|
268
308
|
const { baseUrl, apiVersion } = resolveAzureConfig(model, options);
|
|
269
309
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
apiVersion,
|
|
275
|
-
dangerouslyAllowBrowser: true,
|
|
276
|
-
maxRetries: 5,
|
|
277
|
-
defaultHeaders: headers,
|
|
278
|
-
baseURL: baseUrl,
|
|
279
|
-
fetch: onSseEvent ? wrapFetchForSseDebug(baseFetch, event => onSseEvent(event, model)) : baseFetch,
|
|
280
|
-
});
|
|
310
|
+
return {
|
|
311
|
+
url: `${baseUrl}/responses?api-version=${encodeURIComponent(apiVersion)}`,
|
|
312
|
+
headers,
|
|
313
|
+
};
|
|
281
314
|
}
|
|
282
315
|
|
|
283
316
|
function buildParams(
|
|
@@ -285,15 +318,17 @@ function buildParams(
|
|
|
285
318
|
context: Context,
|
|
286
319
|
options: AzureOpenAIResponsesOptions | undefined,
|
|
287
320
|
deploymentName: string,
|
|
288
|
-
resolvedBaseUrl?: string,
|
|
289
321
|
) {
|
|
290
|
-
const messages = convertMessages(model, context, true
|
|
322
|
+
const messages = convertMessages(model, context, true);
|
|
291
323
|
|
|
292
324
|
const params: AzureOpenAIResponsesSamplingParams = {
|
|
293
325
|
model: deploymentName,
|
|
294
326
|
input: messages,
|
|
295
327
|
stream: true,
|
|
296
|
-
prompt_cache_key:
|
|
328
|
+
prompt_cache_key: getOpenAIResponsesCacheSessionId(options),
|
|
329
|
+
// Encrypted reasoning replay (applyResponsesReasoningParams) requires
|
|
330
|
+
// stateless responses, matching the openai provider.
|
|
331
|
+
store: false,
|
|
297
332
|
};
|
|
298
333
|
|
|
299
334
|
applyCommonResponsesSamplingParams(params, options, model);
|
|
@@ -301,7 +336,15 @@ function buildParams(
|
|
|
301
336
|
if (context.tools) {
|
|
302
337
|
params.tools = convertTools(context.tools);
|
|
303
338
|
if (options?.toolChoice) {
|
|
304
|
-
|
|
339
|
+
const toolChoice = mapToOpenAIResponsesToolChoice(options.toolChoice);
|
|
340
|
+
if (
|
|
341
|
+
toolChoice &&
|
|
342
|
+
(typeof toolChoice === "string" ||
|
|
343
|
+
toolChoice.type !== "function" ||
|
|
344
|
+
context.tools.some(tool => tool.name === toolChoice.name))
|
|
345
|
+
) {
|
|
346
|
+
params.tool_choice = toolChoice;
|
|
347
|
+
}
|
|
305
348
|
}
|
|
306
349
|
}
|
|
307
350
|
|
|
@@ -314,15 +357,15 @@ function convertMessages(
|
|
|
314
357
|
model: Model<"azure-openai-responses">,
|
|
315
358
|
context: Context,
|
|
316
359
|
strictResponsesPairing: boolean,
|
|
317
|
-
resolvedBaseUrl?: string,
|
|
318
360
|
): ResponseInput {
|
|
319
361
|
const messages: ResponseInput = [];
|
|
320
362
|
const transformedMessages = transformMessages(context.messages, model, normalizeResponsesToolCallIdForTransform);
|
|
321
363
|
const knownCallIds = new Set<string>();
|
|
364
|
+
const customCallIds = new Set<string>();
|
|
322
365
|
|
|
323
366
|
const systemPrompts = normalizeSystemPrompts(context.systemPrompt);
|
|
324
367
|
if (systemPrompts.length > 0) {
|
|
325
|
-
const role = model.reasoning && supportsDeveloperRole
|
|
368
|
+
const role = model.reasoning && model.compat.supportsDeveloperRole ? "developer" : "system";
|
|
326
369
|
for (const systemPrompt of systemPrompts) {
|
|
327
370
|
messages.push({ role, content: systemPrompt });
|
|
328
371
|
}
|
|
@@ -338,16 +381,23 @@ function convertMessages(
|
|
|
338
381
|
content: msg.role === "developer" && typeof msg.content === "string" ? msg.content.toWellFormed() : content,
|
|
339
382
|
});
|
|
340
383
|
} else if (msg.role === "assistant") {
|
|
341
|
-
const outputItems = convertResponsesAssistantMessage(
|
|
384
|
+
const outputItems = convertResponsesAssistantMessage(
|
|
385
|
+
msg as AssistantMessage,
|
|
386
|
+
model,
|
|
387
|
+
msgIndex,
|
|
388
|
+
knownCallIds,
|
|
389
|
+
true,
|
|
390
|
+
customCallIds,
|
|
391
|
+
);
|
|
342
392
|
if (outputItems.length === 0) continue;
|
|
343
393
|
messages.push(...outputItems);
|
|
344
394
|
} else if (msg.role === "toolResult") {
|
|
345
|
-
appendResponsesToolResultMessages(messages, msg, model, strictResponsesPairing, knownCallIds);
|
|
395
|
+
appendResponsesToolResultMessages(messages, msg, model, strictResponsesPairing, knownCallIds, customCallIds);
|
|
346
396
|
}
|
|
347
397
|
msgIndex++;
|
|
348
398
|
}
|
|
349
399
|
|
|
350
|
-
return messages;
|
|
400
|
+
return repairOrphanResponsesToolCalls(messages);
|
|
351
401
|
}
|
|
352
402
|
|
|
353
403
|
function convertTools(tools: Tool[]): OpenAITool[] {
|
package/src/providers/cursor.ts
CHANGED
|
@@ -3,35 +3,7 @@ import * as fs from "node:fs/promises";
|
|
|
3
3
|
import http2 from "node:http2";
|
|
4
4
|
import { create, fromBinary, fromJson, type JsonValue, toBinary, toJson } from "@bufbuild/protobuf";
|
|
5
5
|
import { ValueSchema } from "@bufbuild/protobuf/wkt";
|
|
6
|
-
import {
|
|
7
|
-
import { calculateCost } from "../models";
|
|
8
|
-
import type {
|
|
9
|
-
Api,
|
|
10
|
-
AssistantMessage,
|
|
11
|
-
Context,
|
|
12
|
-
CursorExecHandlerResult,
|
|
13
|
-
CursorExecHandlers,
|
|
14
|
-
CursorMcpCall,
|
|
15
|
-
CursorShellStreamCallbacks,
|
|
16
|
-
CursorToolResultHandler,
|
|
17
|
-
ImageContent,
|
|
18
|
-
Message,
|
|
19
|
-
Model,
|
|
20
|
-
StreamFunction,
|
|
21
|
-
StreamOptions,
|
|
22
|
-
TextContent,
|
|
23
|
-
ThinkingContent,
|
|
24
|
-
Tool,
|
|
25
|
-
ToolCall,
|
|
26
|
-
ToolResultMessage,
|
|
27
|
-
} from "../types";
|
|
28
|
-
import { normalizeSystemPrompts } from "../utils";
|
|
29
|
-
import { AssistantMessageEventStream } from "../utils/event-stream";
|
|
30
|
-
import { parseStreamingJson } from "../utils/json-parse";
|
|
31
|
-
import { createRequestDebugSession, isRequestDebugEnabled, type RequestDebugResponseLog } from "../utils/request-debug";
|
|
32
|
-
import { formatErrorMessageWithRetryAfter } from "../utils/retry-after";
|
|
33
|
-
import { toolWireSchema } from "../utils/schema/wire";
|
|
34
|
-
import type { McpToolDefinition } from "./cursor/gen/agent_pb";
|
|
6
|
+
import type { McpToolDefinition } from "@prometheus-ai/catalog/discovery/cursor-gen/agent_pb";
|
|
35
7
|
import {
|
|
36
8
|
AgentClientMessageSchema,
|
|
37
9
|
AgentConversationTurnStructureSchema,
|
|
@@ -128,7 +100,35 @@ import {
|
|
|
128
100
|
WriteShellStdinErrorSchema,
|
|
129
101
|
WriteShellStdinResultSchema,
|
|
130
102
|
WriteSuccessSchema,
|
|
131
|
-
} from "
|
|
103
|
+
} from "@prometheus-ai/catalog/discovery/cursor-gen/agent_pb";
|
|
104
|
+
import { calculateCost } from "@prometheus-ai/catalog/models";
|
|
105
|
+
import { $env, extractHttpStatusFromError, sanitizeText } from "@prometheus-ai/utils";
|
|
106
|
+
import type {
|
|
107
|
+
Api,
|
|
108
|
+
AssistantMessage,
|
|
109
|
+
Context,
|
|
110
|
+
CursorExecHandlerResult,
|
|
111
|
+
CursorExecHandlers,
|
|
112
|
+
CursorMcpCall,
|
|
113
|
+
CursorShellStreamCallbacks,
|
|
114
|
+
CursorToolResultHandler,
|
|
115
|
+
ImageContent,
|
|
116
|
+
Message,
|
|
117
|
+
Model,
|
|
118
|
+
StreamFunction,
|
|
119
|
+
StreamOptions,
|
|
120
|
+
TextContent,
|
|
121
|
+
ThinkingContent,
|
|
122
|
+
Tool,
|
|
123
|
+
ToolCall,
|
|
124
|
+
ToolResultMessage,
|
|
125
|
+
} from "../types";
|
|
126
|
+
import { normalizeSystemPrompts } from "../utils";
|
|
127
|
+
import { AssistantMessageEventStream } from "../utils/event-stream";
|
|
128
|
+
import { parseStreamingJson } from "../utils/json-parse";
|
|
129
|
+
import { createRequestDebugSession, isRequestDebugEnabled, type RequestDebugResponseLog } from "../utils/request-debug";
|
|
130
|
+
import { formatErrorMessageWithRetryAfter } from "../utils/retry-after";
|
|
131
|
+
import { toolWireSchema } from "../utils/schema/wire";
|
|
132
132
|
|
|
133
133
|
export const CURSOR_API_URL = "https://api2.cursor.sh";
|
|
134
134
|
export const CURSOR_CLIENT_VERSION = "cli-2026.01.09-231024f";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { getGitHubCopilotBaseUrl, parseGitHubCopilotApiKey } from "@prometheus-ai/catalog/wire/github-copilot";
|
|
1
2
|
import type { Message } from "../types";
|
|
2
|
-
import { getGitHubCopilotBaseUrl, parseGitHubCopilotApiKey } from "../utils/oauth/github-copilot";
|
|
3
3
|
/**
|
|
4
4
|
* Infer whether the current request to Copilot is user-initiated or agent-initiated.
|
|
5
5
|
* Accepts `unknown[]` because providers may pass pre-converted message shapes.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { buildModel } from "@prometheus-ai/catalog/build";
|
|
1
2
|
import { ANTHROPIC_THINKING, mapAnthropicToolChoice } from "../stream";
|
|
2
|
-
import type { Api, Context, FetchImpl, Model, SimpleStreamOptions } from "../types";
|
|
3
|
+
import type { Api, Context, FetchImpl, Model, ModelSpec, SimpleStreamOptions } from "../types";
|
|
3
4
|
import { AssistantMessageEventStream } from "../utils/event-stream";
|
|
4
5
|
import { createProviderErrorMessage } from "./error-message";
|
|
5
6
|
import type { OpenAICompletionsOptions } from "./openai-completions";
|
|
@@ -145,23 +146,25 @@ export function getModelMapping(modelId: string): GitLabModelMapping | undefined
|
|
|
145
146
|
}
|
|
146
147
|
|
|
147
148
|
export function getGitLabDuoModels(): Model<Api>[] {
|
|
148
|
-
return Object.entries(MODEL_MAPPINGS).map(([id, mapping]) =>
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
149
|
+
return Object.entries(MODEL_MAPPINGS).map(([id, mapping]) =>
|
|
150
|
+
buildModel({
|
|
151
|
+
id,
|
|
152
|
+
name: mapping.name,
|
|
153
|
+
api:
|
|
154
|
+
mapping.provider === "anthropic"
|
|
155
|
+
? "anthropic-messages"
|
|
156
|
+
: mapping.openaiApiType === "responses"
|
|
157
|
+
? "openai-responses"
|
|
158
|
+
: "openai-completions",
|
|
159
|
+
provider: "gitlab-duo",
|
|
160
|
+
baseUrl: mapping.provider === "anthropic" ? ANTHROPIC_PROXY_URL : OPENAI_PROXY_URL,
|
|
161
|
+
reasoning: mapping.reasoning,
|
|
162
|
+
input: [...mapping.input],
|
|
163
|
+
cost: { ...mapping.cost },
|
|
164
|
+
contextWindow: mapping.contextWindow,
|
|
165
|
+
maxTokens: mapping.maxTokens,
|
|
166
|
+
} as ModelSpec<Api>),
|
|
167
|
+
);
|
|
165
168
|
}
|
|
166
169
|
|
|
167
170
|
interface DirectAccessToken {
|
|
@@ -234,7 +237,8 @@ export function streamGitLabDuo(
|
|
|
234
237
|
|
|
235
238
|
(async () => {
|
|
236
239
|
try {
|
|
237
|
-
|
|
240
|
+
const apiKey = typeof options?.apiKey === "string" ? options.apiKey : undefined;
|
|
241
|
+
if (!apiKey || !options) {
|
|
238
242
|
throw new Error("Missing GitLab access token. Run /login gitlab-duo or set GITLAB_TOKEN.");
|
|
239
243
|
}
|
|
240
244
|
|
|
@@ -243,7 +247,7 @@ export function streamGitLabDuo(
|
|
|
243
247
|
throw new Error(`Unsupported GitLab Duo model: ${model.id}`);
|
|
244
248
|
}
|
|
245
249
|
|
|
246
|
-
const directAccess = await getDirectAccessToken(
|
|
250
|
+
const directAccess = await getDirectAccessToken(apiKey, options.fetch);
|
|
247
251
|
const headers = {
|
|
248
252
|
...directAccess.headers,
|
|
249
253
|
...options.headers,
|
|
@@ -254,12 +258,13 @@ export function streamGitLabDuo(
|
|
|
254
258
|
const inner =
|
|
255
259
|
mapping.provider === "anthropic"
|
|
256
260
|
? streamAnthropic(
|
|
257
|
-
{
|
|
261
|
+
buildModel({
|
|
258
262
|
...model,
|
|
259
263
|
id: mapping.model,
|
|
260
264
|
api: "anthropic-messages",
|
|
261
265
|
baseUrl: ANTHROPIC_PROXY_URL,
|
|
262
|
-
|
|
266
|
+
compat: model.compatConfig,
|
|
267
|
+
} as ModelSpec<"anthropic-messages">),
|
|
263
268
|
context,
|
|
264
269
|
{
|
|
265
270
|
apiKey: directAccess.token,
|
|
@@ -270,7 +275,7 @@ export function streamGitLabDuo(
|
|
|
270
275
|
minP: options.minP,
|
|
271
276
|
presencePenalty: options.presencePenalty,
|
|
272
277
|
repetitionPenalty: options.repetitionPenalty,
|
|
273
|
-
maxTokens: options.maxTokens ?? model.maxTokens,
|
|
278
|
+
maxTokens: options.maxTokens ?? model.maxTokens ?? undefined,
|
|
274
279
|
signal: options.signal,
|
|
275
280
|
cacheRetention: options.cacheRetention,
|
|
276
281
|
headers,
|
|
@@ -292,12 +297,13 @@ export function streamGitLabDuo(
|
|
|
292
297
|
)
|
|
293
298
|
: mapping.openaiApiType === "responses"
|
|
294
299
|
? streamOpenAIResponses(
|
|
295
|
-
{
|
|
300
|
+
buildModel({
|
|
296
301
|
...model,
|
|
297
302
|
id: mapping.model,
|
|
298
303
|
api: "openai-responses",
|
|
299
304
|
baseUrl: OPENAI_PROXY_URL,
|
|
300
|
-
|
|
305
|
+
compat: model.compatConfig,
|
|
306
|
+
} as ModelSpec<"openai-responses">),
|
|
301
307
|
context,
|
|
302
308
|
{
|
|
303
309
|
apiKey: directAccess.token,
|
|
@@ -307,7 +313,7 @@ export function streamGitLabDuo(
|
|
|
307
313
|
minP: options.minP,
|
|
308
314
|
presencePenalty: options.presencePenalty,
|
|
309
315
|
repetitionPenalty: options.repetitionPenalty,
|
|
310
|
-
maxTokens: options.maxTokens ?? model.maxTokens,
|
|
316
|
+
maxTokens: options.maxTokens ?? model.maxTokens ?? undefined,
|
|
311
317
|
signal: options.signal,
|
|
312
318
|
cacheRetention: options.cacheRetention,
|
|
313
319
|
headers,
|
|
@@ -324,12 +330,13 @@ export function streamGitLabDuo(
|
|
|
324
330
|
} satisfies OpenAIResponsesOptions,
|
|
325
331
|
)
|
|
326
332
|
: streamOpenAICompletions(
|
|
327
|
-
{
|
|
333
|
+
buildModel({
|
|
328
334
|
...model,
|
|
329
335
|
id: mapping.model,
|
|
330
336
|
api: "openai-completions",
|
|
331
337
|
baseUrl: OPENAI_PROXY_URL,
|
|
332
|
-
|
|
338
|
+
compat: model.compatConfig,
|
|
339
|
+
} as ModelSpec<"openai-completions">),
|
|
333
340
|
context,
|
|
334
341
|
{
|
|
335
342
|
apiKey: directAccess.token,
|
|
@@ -339,7 +346,7 @@ export function streamGitLabDuo(
|
|
|
339
346
|
minP: options.minP,
|
|
340
347
|
presencePenalty: options.presencePenalty,
|
|
341
348
|
repetitionPenalty: options.repetitionPenalty,
|
|
342
|
-
maxTokens: options.maxTokens ?? model.maxTokens,
|
|
349
|
+
maxTokens: options.maxTokens ?? model.maxTokens ?? undefined,
|
|
343
350
|
signal: options.signal,
|
|
344
351
|
cacheRetention: options.cacheRetention,
|
|
345
352
|
headers,
|