@fudrouter/fsrouter 0.6.61 → 0.6.63
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/bin/copyJs.js +13 -9
- package/open-sse/AGENTS.md +39 -0
- package/open-sse/config/anthropicHeaders.js +87 -0
- package/open-sse/config/appConstants.js +238 -0
- package/open-sse/config/audioRegistry.js +506 -0
- package/open-sse/config/cliFingerprints.js +304 -0
- package/open-sse/config/codexInstructions.js +119 -0
- package/open-sse/config/codexQuotaScopes.js +42 -0
- package/open-sse/config/constants.js +4 -0
- package/open-sse/config/contextEditing.js +68 -0
- package/open-sse/config/credentialLoader.js +83 -0
- package/open-sse/config/defaultThinkingSignature.js +12 -0
- package/open-sse/config/embeddingRegistry.js +264 -0
- package/open-sse/config/errorConfig.js +96 -0
- package/open-sse/config/freeModelCatalog.data.js +121 -0
- package/open-sse/config/freeModelCatalog.js +90 -0
- package/open-sse/config/freeTierCatalog.js +81 -0
- package/open-sse/config/googleTtsLanguages.js +62 -0
- package/open-sse/config/imageParamDefs.js +360 -0
- package/open-sse/config/imageRegistry.js +493 -0
- package/open-sse/config/kiroConstants.js +268 -0
- package/open-sse/config/mediaConfig.js +27 -0
- package/open-sse/config/mediaServiceKinds.js +71 -0
- package/open-sse/config/models.js +13 -0
- package/open-sse/config/moderationRegistry.js +71 -0
- package/open-sse/config/musicRegistry.js +99 -0
- package/open-sse/config/ocrRegistry.js +61 -0
- package/open-sse/config/ollamaModels.js +19 -0
- package/open-sse/config/providerErrorRules.js +114 -0
- package/open-sse/config/providerFieldStrips.js +35 -0
- package/open-sse/config/providerHeaderProfiles.js +191 -0
- package/open-sse/config/providerModels.js +106 -0
- package/open-sse/config/providerRegistry.js +16 -0
- package/open-sse/config/providers.js +19 -0
- package/open-sse/config/registryUtils.js +106 -0
- package/open-sse/config/rerankRegistry.js +177 -0
- package/open-sse/config/runtimeConfig.js +96 -0
- package/open-sse/config/runway.js +39 -0
- package/open-sse/config/searchRegistry.js +153 -0
- package/open-sse/config/toolCloaking.js +199 -0
- package/open-sse/config/ttsModels.js +129 -0
- package/open-sse/config/videoRegistry.js +207 -0
- package/open-sse/executors/adapta-web.js +435 -0
- package/open-sse/executors/antigravity.js +534 -0
- package/open-sse/executors/antigravityUpstreamError.js +13 -0
- package/open-sse/executors/auggie.js +437 -0
- package/open-sse/executors/azure-openai.js +32 -0
- package/open-sse/executors/azure.js +57 -0
- package/open-sse/executors/base.js +181 -0
- package/open-sse/executors/bedrock.js +633 -0
- package/open-sse/executors/blackbox-web.js +578 -0
- package/open-sse/executors/chatgpt-web.js +2042 -0
- package/open-sse/executors/chipotle.js +357 -0
- package/open-sse/executors/claude-web-with-auto-refresh.js +73 -0
- package/open-sse/executors/claude-web.js +586 -0
- package/open-sse/executors/cliproxyapi.js +296 -0
- package/open-sse/executors/cloudflare-ai.js +46 -0
- package/open-sse/executors/codebuddy-cn.js +40 -0
- package/open-sse/executors/codex.js +1324 -0
- package/open-sse/executors/commandCode.js +558 -0
- package/open-sse/executors/commandcode.js +88 -0
- package/open-sse/executors/copilot-m365-connection.js +176 -0
- package/open-sse/executors/copilot-m365-frames.js +192 -0
- package/open-sse/executors/copilot-m365-web.js +299 -0
- package/open-sse/executors/copilot-web.js +580 -0
- package/open-sse/executors/cursor.js +795 -0
- package/open-sse/executors/deepseek-web-with-auto-refresh.js +150 -0
- package/open-sse/executors/deepseek-web.js +875 -0
- package/open-sse/executors/default.js +430 -0
- package/open-sse/executors/devin-cli.js +351 -0
- package/open-sse/executors/doubao-web.js +550 -0
- package/open-sse/executors/duckduckgo-web.js +629 -0
- package/open-sse/executors/forceResponsesUpstream.js +33 -0
- package/open-sse/executors/gemini-business.js +320 -0
- package/open-sse/executors/gemini-cli.js +89 -0
- package/open-sse/executors/gemini-web.js +297 -0
- package/open-sse/executors/github.js +379 -0
- package/open-sse/executors/gitlab.js +569 -0
- package/open-sse/executors/glm.js +361 -0
- package/open-sse/executors/grok-cli.js +119 -0
- package/open-sse/executors/grok-web.js +345 -0
- package/open-sse/executors/huggingchat.js +467 -0
- package/open-sse/executors/iflow.js +108 -0
- package/open-sse/executors/index.js +78 -0
- package/open-sse/executors/inner-ai.js +527 -0
- package/open-sse/executors/kimchi.js +123 -0
- package/open-sse/executors/kimi-web.js +325 -0
- package/open-sse/executors/kimi.js +97 -0
- package/open-sse/executors/kiro.js +503 -0
- package/open-sse/executors/kiroThinking.js +44 -0
- package/open-sse/executors/lmarena.js +395 -0
- package/open-sse/executors/mimo-free.js +167 -0
- package/open-sse/executors/mimocode.js +392 -0
- package/open-sse/executors/ninerouter.js +155 -0
- package/open-sse/executors/nlpcloud.js +438 -0
- package/open-sse/executors/ollama-local.js +14 -0
- package/open-sse/executors/opencode-go.js +41 -0
- package/open-sse/executors/opencode.js +32 -0
- package/open-sse/executors/perplexity-web.js +581 -0
- package/open-sse/executors/poe-web.js +133 -0
- package/open-sse/executors/pollinations.js +95 -0
- package/open-sse/executors/puter.js +31 -0
- package/open-sse/executors/qoder.js +448 -0
- package/open-sse/executors/qwen-web.js +372 -0
- package/open-sse/executors/qwen.js +129 -0
- package/open-sse/executors/t3-chat-web.js +417 -0
- package/open-sse/executors/theoldllm.js +290 -0
- package/open-sse/executors/trae.js +418 -0
- package/open-sse/executors/v0-vercel-web.js +141 -0
- package/open-sse/executors/venice-web.js +142 -0
- package/open-sse/executors/vertex.js +131 -0
- package/open-sse/executors/vertexMedia.js +236 -0
- package/open-sse/executors/windsurf.js +560 -0
- package/open-sse/executors/xai.js +46 -0
- package/open-sse/executors/xiaomi-tokenplan.js +19 -0
- package/open-sse/executors/yuanbao-web.js +385 -0
- package/open-sse/executors/zed-hosted.js +281 -0
- package/open-sse/executors/zenmux-free.js +247 -0
- package/open-sse/handlers/audioSpeech.js +759 -0
- package/open-sse/handlers/audioTranscription.js +395 -0
- package/open-sse/handlers/audioTranslation.js +181 -0
- package/open-sse/handlers/chatCore/nonStreamingHandler.js +300 -0
- package/open-sse/handlers/chatCore/requestDetail.js +102 -0
- package/open-sse/handlers/chatCore/sseToJsonHandler.js +231 -0
- package/open-sse/handlers/chatCore/streamingHandler.js +95 -0
- package/open-sse/handlers/chatCore.js +404 -0
- package/open-sse/handlers/embeddingProviders/_base.js +4 -0
- package/open-sse/handlers/embeddingProviders/gemini.js +54 -0
- package/open-sse/handlers/embeddingProviders/index.js +23 -0
- package/open-sse/handlers/embeddingProviders/openai.js +39 -0
- package/open-sse/handlers/embeddingProviders/openaiCompatNode.js +13 -0
- package/open-sse/handlers/embeddingsCore.js +126 -0
- package/open-sse/handlers/fetch/index.js +237 -0
- package/open-sse/handlers/imageGenerationCore.js +230 -0
- package/open-sse/handlers/imageProviders/_base.js +31 -0
- package/open-sse/handlers/imageProviders/antigravity.js +73 -0
- package/open-sse/handlers/imageProviders/blackForestLabs.js +63 -0
- package/open-sse/handlers/imageProviders/cloudflareAi.js +207 -0
- package/open-sse/handlers/imageProviders/codex.js +217 -0
- package/open-sse/handlers/imageProviders/comfyui.js +25 -0
- package/open-sse/handlers/imageProviders/falAi.js +62 -0
- package/open-sse/handlers/imageProviders/gemini.js +40 -0
- package/open-sse/handlers/imageProviders/huggingface.js +38 -0
- package/open-sse/handlers/imageProviders/index.js +44 -0
- package/open-sse/handlers/imageProviders/leonardo.js +435 -0
- package/open-sse/handlers/imageProviders/nanobanana.js +79 -0
- package/open-sse/handlers/imageProviders/openai.js +61 -0
- package/open-sse/handlers/imageProviders/runwayml.js +72 -0
- package/open-sse/handlers/imageProviders/sdwebui.js +36 -0
- package/open-sse/handlers/imageProviders/stabilityAi.js +59 -0
- package/open-sse/handlers/imageProviders/weavy.js +222 -0
- package/open-sse/handlers/moderations.js +92 -0
- package/open-sse/handlers/ocr.js +89 -0
- package/open-sse/handlers/rerank.js +223 -0
- package/open-sse/handlers/responseSanitizer/reasoning.js +144 -0
- package/open-sse/handlers/responsesHandler.js +99 -0
- package/open-sse/handlers/search/callers.js +371 -0
- package/open-sse/handlers/search/chatSearch.js +409 -0
- package/open-sse/handlers/search/index.js +201 -0
- package/open-sse/handlers/search/normalizers.js +223 -0
- package/open-sse/handlers/search.js +1056 -0
- package/open-sse/handlers/sseParser.js +469 -0
- package/open-sse/handlers/sttCore.js +193 -0
- package/open-sse/handlers/ttsCore.js +74 -0
- package/open-sse/handlers/ttsProviders/_base.js +39 -0
- package/open-sse/handlers/ttsProviders/edgeTts.js +89 -0
- package/open-sse/handlers/ttsProviders/elevenlabs.js +48 -0
- package/open-sse/handlers/ttsProviders/gemini.js +117 -0
- package/open-sse/handlers/ttsProviders/genericFormats.js +169 -0
- package/open-sse/handlers/ttsProviders/googleTts.js +54 -0
- package/open-sse/handlers/ttsProviders/index.js +50 -0
- package/open-sse/handlers/ttsProviders/localDevice.js +87 -0
- package/open-sse/handlers/ttsProviders/minimax.js +59 -0
- package/open-sse/handlers/ttsProviders/openai.js +30 -0
- package/open-sse/handlers/ttsProviders/openrouter.js +70 -0
- package/open-sse/handlers/usageExtractor.js +93 -0
- package/open-sse/handlers/videoGenerationCore.js +119 -0
- package/open-sse/handlers/videoProviders/index.js +22 -0
- package/open-sse/handlers/videoProviders/leonardo.js +511 -0
- package/open-sse/handlers/videoProviders/weavy.js +198 -0
- package/open-sse/handlers/webFetch.js +200 -0
- package/open-sse/index.js +79 -0
- package/open-sse/mcp-server/audit.js +283 -0
- package/open-sse/mcp-server/catalog.js +184 -0
- package/open-sse/mcp-server/descriptionCompressor.js +175 -0
- package/open-sse/mcp-server/httpAuthContext.js +32 -0
- package/open-sse/mcp-server/httpTransport.js +229 -0
- package/open-sse/mcp-server/index.js +33 -0
- package/open-sse/mcp-server/mcpCallerIdentity.js +21 -0
- package/open-sse/mcp-server/runtimeHeartbeat.js +110 -0
- package/open-sse/mcp-server/schemas/a2a.js +153 -0
- package/open-sse/mcp-server/schemas/audit.js +17 -0
- package/open-sse/mcp-server/schemas/index.js +166 -0
- package/open-sse/mcp-server/schemas/pickFastestModel.js +90 -0
- package/open-sse/mcp-server/schemas/toolDefinition.js +0 -0
- package/open-sse/mcp-server/schemas/toolSearch.js +32 -0
- package/open-sse/mcp-server/schemas/tools.js +1219 -0
- package/open-sse/mcp-server/scopeEnforcement.js +80 -0
- package/open-sse/mcp-server/server.js +1168 -0
- package/open-sse/mcp-server/toolCardinality.js +78 -0
- package/open-sse/mcp-server/toolSearch/catalog.js +66 -0
- package/open-sse/mcp-server/toolSearch/handler.js +20 -0
- package/open-sse/mcp-server/toolSearch/index.js +10 -0
- package/open-sse/mcp-server/toolSearch/register.js +21 -0
- package/open-sse/mcp-server/toolSearch/search.js +55 -0
- package/open-sse/mcp-server/toolSearch/signature.js +67 -0
- package/open-sse/mcp-server/tools/advancedTools.js +893 -0
- package/open-sse/mcp-server/tools/agentSkillTools.js +69 -0
- package/open-sse/mcp-server/tools/compressionTools.js +309 -0
- package/open-sse/mcp-server/tools/gamificationTools.js +134 -0
- package/open-sse/mcp-server/tools/githubSkillTools.js +102 -0
- package/open-sse/mcp-server/tools/memoryTools.js +118 -0
- package/open-sse/mcp-server/tools/notionTools.js +101 -0
- package/open-sse/mcp-server/tools/obsidianTools.js +307 -0
- package/open-sse/mcp-server/tools/pickFastestModel.js +223 -0
- package/open-sse/mcp-server/tools/pluginTools.js +181 -0
- package/open-sse/mcp-server/tools/poolTools.js +139 -0
- package/open-sse/mcp-server/tools/skillTools.js +113 -0
- package/open-sse/package.json +10 -0
- package/open-sse/providers/REGISTRY_TEMPLATE.js +98 -0
- package/open-sse/providers/capabilities.js +293 -0
- package/open-sse/providers/index.js +51 -0
- package/open-sse/providers/models/helpers.js +20 -0
- package/open-sse/providers/models/namePatterns.js +33 -0
- package/open-sse/providers/models/schema.js +40 -0
- package/open-sse/providers/pricing.js +308 -0
- package/open-sse/providers/registry/alicode-intl.js +30 -0
- package/open-sse/providers/registry/alicode.js +31 -0
- package/open-sse/providers/registry/anthropic.js +37 -0
- package/open-sse/providers/registry/antigravity.js +81 -0
- package/open-sse/providers/registry/assemblyai.js +38 -0
- package/open-sse/providers/registry/aws-polly.js +45 -0
- package/open-sse/providers/registry/azure.js +21 -0
- package/open-sse/providers/registry/black-forest-labs.js +32 -0
- package/open-sse/providers/registry/blackbox.js +41 -0
- package/open-sse/providers/registry/brave-search.js +35 -0
- package/open-sse/providers/registry/byteplus.js +35 -0
- package/open-sse/providers/registry/cartesia.js +36 -0
- package/open-sse/providers/registry/cerebras.js +31 -0
- package/open-sse/providers/registry/chutes.js +24 -0
- package/open-sse/providers/registry/claude.js +87 -0
- package/open-sse/providers/registry/cline.js +51 -0
- package/open-sse/providers/registry/clinepass.js +57 -0
- package/open-sse/providers/registry/cloudflare-ai.js +55 -0
- package/open-sse/providers/registry/codebuddy-cn.js +77 -0
- package/open-sse/providers/registry/codex.js +100 -0
- package/open-sse/providers/registry/cohere.js +27 -0
- package/open-sse/providers/registry/comfyui.js +20 -0
- package/open-sse/providers/registry/commandcode.js +43 -0
- package/open-sse/providers/registry/coqui.js +30 -0
- package/open-sse/providers/registry/cursor.js +58 -0
- package/open-sse/providers/registry/deepgram.js +33 -0
- package/open-sse/providers/registry/deepseek.js +51 -0
- package/open-sse/providers/registry/digitalocean.js +92 -0
- package/open-sse/providers/registry/edge-tts.js +24 -0
- package/open-sse/providers/registry/elevenlabs.js +35 -0
- package/open-sse/providers/registry/exa.js +50 -0
- package/open-sse/providers/registry/fal-ai.js +34 -0
- package/open-sse/providers/registry/featherless.js +34 -0
- package/open-sse/providers/registry/firecrawl.js +34 -0
- package/open-sse/providers/registry/fireworks.js +29 -0
- package/open-sse/providers/registry/gemini-cli.js +58 -0
- package/open-sse/providers/registry/gemini.js +83 -0
- package/open-sse/providers/registry/github.js +88 -0
- package/open-sse/providers/registry/gitlab.js +32 -0
- package/open-sse/providers/registry/glm-cn.js +35 -0
- package/open-sse/providers/registry/glm.js +58 -0
- package/open-sse/providers/registry/google-pse.js +35 -0
- package/open-sse/providers/registry/google-tts.js +24 -0
- package/open-sse/providers/registry/grok-cli.js +86 -0
- package/open-sse/providers/registry/grok-web.js +39 -0
- package/open-sse/providers/registry/groq.js +37 -0
- package/open-sse/providers/registry/huggingface.js +34 -0
- package/open-sse/providers/registry/hyperbolic.js +35 -0
- package/open-sse/providers/registry/ibm-bob.js +27 -0
- package/open-sse/providers/registry/iflow.js +52 -0
- package/open-sse/providers/registry/index.js +210 -0
- package/open-sse/providers/registry/inworld.js +36 -0
- package/open-sse/providers/registry/jina-ai.js +42 -0
- package/open-sse/providers/registry/jina-reader.js +34 -0
- package/open-sse/providers/registry/kilocode.js +51 -0
- package/open-sse/providers/registry/kimchi.js +49 -0
- package/open-sse/providers/registry/kimi-coding.js +65 -0
- package/open-sse/providers/registry/kimi.js +56 -0
- package/open-sse/providers/registry/kiro.js +115 -0
- package/open-sse/providers/registry/linkup.js +34 -0
- package/open-sse/providers/registry/local-device.js +24 -0
- package/open-sse/providers/registry/mimo-free.js +24 -0
- package/open-sse/providers/registry/minimax-cn.js +76 -0
- package/open-sse/providers/registry/minimax.js +83 -0
- package/open-sse/providers/registry/mistral.js +34 -0
- package/open-sse/providers/registry/mmf.js +19 -0
- package/open-sse/providers/registry/nanobanana.js +35 -0
- package/open-sse/providers/registry/nebius.js +27 -0
- package/open-sse/providers/registry/nvidia.js +43 -0
- package/open-sse/providers/registry/ollama-local.js +19 -0
- package/open-sse/providers/registry/ollama.js +36 -0
- package/open-sse/providers/registry/openai.js +84 -0
- package/open-sse/providers/registry/opencode-go.js +41 -0
- package/open-sse/providers/registry/opencode.js +25 -0
- package/open-sse/providers/registry/openrouter.js +60 -0
- package/open-sse/providers/registry/perplexity-agent.js +49 -0
- package/open-sse/providers/registry/perplexity-web.js +33 -0
- package/open-sse/providers/registry/perplexity.js +37 -0
- package/open-sse/providers/registry/playht.js +36 -0
- package/open-sse/providers/registry/qoder.js +54 -0
- package/open-sse/providers/registry/qwen.js +33 -0
- package/open-sse/providers/registry/recraft.js +24 -0
- package/open-sse/providers/registry/runwayml.js +30 -0
- package/open-sse/providers/registry/sdwebui.js +20 -0
- package/open-sse/providers/registry/searchapi.js +35 -0
- package/open-sse/providers/registry/searxng.js +35 -0
- package/open-sse/providers/registry/serper.js +35 -0
- package/open-sse/providers/registry/siliconflow.js +39 -0
- package/open-sse/providers/registry/stability-ai.js +31 -0
- package/open-sse/providers/registry/tavily.js +50 -0
- package/open-sse/providers/registry/together.js +31 -0
- package/open-sse/providers/registry/topaz.js +19 -0
- package/open-sse/providers/registry/tortoise.js +30 -0
- package/open-sse/providers/registry/venice.js +56 -0
- package/open-sse/providers/registry/vercel-ai-gateway.js +41 -0
- package/open-sse/providers/registry/vertex-partner.js +29 -0
- package/open-sse/providers/registry/vertex.js +32 -0
- package/open-sse/providers/registry/volcengine-ark.js +35 -0
- package/open-sse/providers/registry/voyage-ai.js +30 -0
- package/open-sse/providers/registry/xai.js +45 -0
- package/open-sse/providers/registry/xiaomi-mimo.js +46 -0
- package/open-sse/providers/registry/xiaomi-tokenplan.js +63 -0
- package/open-sse/providers/registry/youcom.js +35 -0
- package/open-sse/providers/schema.js +76 -0
- package/open-sse/providers/shared.js +74 -0
- package/open-sse/providers/thinkingLevels.js +48 -0
- package/open-sse/rtk/applyFilter.js +15 -0
- package/open-sse/rtk/autodetect.js +111 -0
- package/open-sse/rtk/caveman.js +100 -0
- package/open-sse/rtk/cavemanPrompts.js +78 -0
- package/open-sse/rtk/constants.js +55 -0
- package/open-sse/rtk/filters/buildOutput.js +127 -0
- package/open-sse/rtk/filters/dedupLog.js +44 -0
- package/open-sse/rtk/filters/find.js +50 -0
- package/open-sse/rtk/filters/gitDiff.js +92 -0
- package/open-sse/rtk/filters/gitLog.js +99 -0
- package/open-sse/rtk/filters/gitStatus.js +117 -0
- package/open-sse/rtk/filters/grep.js +48 -0
- package/open-sse/rtk/filters/ls.js +79 -0
- package/open-sse/rtk/filters/readNumbered.js +27 -0
- package/open-sse/rtk/filters/searchList.js +52 -0
- package/open-sse/rtk/filters/smartTruncate.js +15 -0
- package/open-sse/rtk/filters/tree.js +32 -0
- package/open-sse/rtk/headroom.js +215 -0
- package/open-sse/rtk/index.js +155 -0
- package/open-sse/rtk/paleo.js +47 -0
- package/open-sse/rtk/ponytail.js +9 -0
- package/open-sse/rtk/ponytailPrompt.js +52 -0
- package/open-sse/rtk/ponytailPrompts.js +76 -0
- package/open-sse/rtk/pxpipe.js +104 -0
- package/open-sse/rtk/registry.js +38 -0
- package/open-sse/rtk/systemInject.js +98 -0
- package/open-sse/services/accountFallback.js +323 -0
- package/open-sse/services/antigravityHeaders.js +91 -0
- package/open-sse/services/antigravityVersion.js +154 -0
- package/open-sse/services/clinepassModels.js +63 -0
- package/open-sse/services/codexQuotaFetcher.js +312 -0
- package/open-sse/services/codexVerbosity.js +30 -0
- package/open-sse/services/combo/context.js +12 -0
- package/open-sse/services/combo/fingerprintExpansion.js +51 -0
- package/open-sse/services/combo/headroomRanking.js +28 -0
- package/open-sse/services/combo/quotaExhaustionCutoff.js +87 -0
- package/open-sse/services/combo/quotaScoring.js +226 -0
- package/open-sse/services/combo/quotaShareConcurrency.js +25 -0
- package/open-sse/services/combo/quotaShareInflight.js +50 -0
- package/open-sse/services/combo/quotaShareStrategy.js +130 -0
- package/open-sse/services/combo/resolveAutoStrategy.js +231 -0
- package/open-sse/services/combo/responseValidation.js +140 -0
- package/open-sse/services/combo/runtimeUnits.js +195 -0
- package/open-sse/services/combo/sessionStickiness.js +128 -0
- package/open-sse/services/combo/shadowRouting.js +131 -0
- package/open-sse/services/combo/targetExhaustion.js +75 -0
- package/open-sse/services/combo/targetSorters.js +126 -0
- package/open-sse/services/combo/targetTimeoutRunner.js +65 -0
- package/open-sse/services/combo/validateQuality.js +271 -0
- package/open-sse/services/combo.js +571 -0
- package/open-sse/services/comboAgentMiddleware.js +91 -0
- package/open-sse/services/comboConfig.js +153 -0
- package/open-sse/services/comboManifestMetrics.js +10 -0
- package/open-sse/services/comboMetrics.js +278 -0
- package/open-sse/services/compact.js +71 -0
- package/open-sse/services/copilotModels.js +155 -0
- package/open-sse/services/emergencyFallback.js +109 -0
- package/open-sse/services/errorClassifier.js +190 -0
- package/open-sse/services/evalRouting.js +201 -0
- package/open-sse/services/freeWebSearch.js +4 -0
- package/open-sse/services/fusion.js +223 -0
- package/open-sse/services/intentClassifier.js +631 -0
- package/open-sse/services/kimchiModels.js +176 -0
- package/open-sse/services/kiroModels.js +332 -0
- package/open-sse/services/model.js +136 -0
- package/open-sse/services/modelCapabilities.js +5 -0
- package/open-sse/services/modelDeprecation.js +101 -0
- package/open-sse/services/modelFamilyFallback.js +166 -0
- package/open-sse/services/oauthCredentialManager.js +156 -0
- package/open-sse/services/pipeline.js +107 -0
- package/open-sse/services/projectId.js +306 -0
- package/open-sse/services/provider.js +169 -0
- package/open-sse/services/providerCooldownTracker.js +94 -0
- package/open-sse/services/providerDefaultRateLimit.js +11 -0
- package/open-sse/services/proxyAutoSelector.js +24 -0
- package/open-sse/services/qoderModels.js +214 -0
- package/open-sse/services/quotaFetchThrottle.js +103 -0
- package/open-sse/services/quotaMonitor.js +310 -0
- package/open-sse/services/quotaPreflight.js +266 -0
- package/open-sse/services/rateLimitManager/headers.js +56 -0
- package/open-sse/services/rateLimitManager.js +616 -0
- package/open-sse/services/rateLimitSemaphore.js +112 -0
- package/open-sse/services/responsesInputSanitizer.js +99 -0
- package/open-sse/services/slidingWindowLimiter.js +44 -0
- package/open-sse/services/streamRecovery.js +355 -0
- package/open-sse/services/taskAwareRouter.js +227 -0
- package/open-sse/services/taskAwareRouting.js +332 -0
- package/open-sse/services/thinkingBudget.js +247 -0
- package/open-sse/services/tokenRefresh/dedup.js +31 -0
- package/open-sse/services/tokenRefresh/providers.js +624 -0
- package/open-sse/services/tokenRefresh.js +254 -0
- package/open-sse/services/usage/claude.js +147 -0
- package/open-sse/services/usage/codebuddy-cn.js +138 -0
- package/open-sse/services/usage/codex.js +267 -0
- package/open-sse/services/usage/github.js +100 -0
- package/open-sse/services/usage/google.js +241 -0
- package/open-sse/services/usage/grok-cli.js +274 -0
- package/open-sse/services/usage/kiro.js +188 -0
- package/open-sse/services/usage/minimax.js +234 -0
- package/open-sse/services/usage/misc.js +288 -0
- package/open-sse/services/usage/shared.js +70 -0
- package/open-sse/services/usage.js +62 -0
- package/open-sse/services/usageDb.js +2 -0
- package/open-sse/services/webSearchRouting.js +25 -0
- package/open-sse/services/wildcardRouter.js +59 -0
- package/open-sse/shared/clineAuth.js +37 -0
- package/open-sse/shared/machineId.js +19 -0
- package/open-sse/shared/qoder/constants.js +64 -0
- package/open-sse/shared/qoder/cosy.js +175 -0
- package/open-sse/shared/qoder/encoding.js +55 -0
- package/open-sse/transformer/responsesTransformer.js +439 -0
- package/open-sse/transformer/streamToJsonConverter.js +103 -0
- package/open-sse/translator/concerns/chunk.js +11 -0
- package/open-sse/translator/concerns/finishReason.js +63 -0
- package/open-sse/translator/concerns/image.js +124 -0
- package/open-sse/translator/concerns/json.js +5 -0
- package/open-sse/translator/concerns/message.js +7 -0
- package/open-sse/translator/concerns/modality.js +155 -0
- package/open-sse/translator/concerns/paramSupport.js +75 -0
- package/open-sse/translator/concerns/prefetch.js +96 -0
- package/open-sse/translator/concerns/reasoning.js +24 -0
- package/open-sse/translator/concerns/thinking.js +53 -0
- package/open-sse/translator/concerns/thinkingUnified.js +329 -0
- package/open-sse/translator/concerns/toolCall.js +153 -0
- package/open-sse/translator/concerns/usage.js +69 -0
- package/open-sse/translator/formats/claude.js +368 -0
- package/open-sse/translator/formats/gemini.js +380 -0
- package/open-sse/translator/formats/maxTokens.js +34 -0
- package/open-sse/translator/formats/openai.js +134 -0
- package/open-sse/translator/formats/responsesApi.js +141 -0
- package/open-sse/translator/formats.js +36 -0
- package/open-sse/translator/helpers/claudeHelper.js +216 -0
- package/open-sse/translator/helpers/geminiHelper.js +372 -0
- package/open-sse/translator/helpers/imageHelper.js +34 -0
- package/open-sse/translator/helpers/maxTokensHelper.js +27 -0
- package/open-sse/translator/helpers/openaiHelper.js +130 -0
- package/open-sse/translator/helpers/responsesApiHelper.js +139 -0
- package/open-sse/translator/helpers/toolCallHelper.js +148 -0
- package/open-sse/translator/index.js +252 -0
- package/open-sse/translator/request/antigravity-to-openai.js +242 -0
- package/open-sse/translator/request/claude-to-kiro.js +478 -0
- package/open-sse/translator/request/claude-to-openai.js +263 -0
- package/open-sse/translator/request/gemini-to-openai.js +152 -0
- package/open-sse/translator/request/openai-responses.js +385 -0
- package/open-sse/translator/request/openai-to-claude.js +383 -0
- package/open-sse/translator/request/openai-to-commandcode.js +176 -0
- package/open-sse/translator/request/openai-to-cursor.js +185 -0
- package/open-sse/translator/request/openai-to-gemini.js +442 -0
- package/open-sse/translator/request/openai-to-kiro.js +607 -0
- package/open-sse/translator/request/openai-to-kiro.old.js +278 -0
- package/open-sse/translator/request/openai-to-ollama.js +195 -0
- package/open-sse/translator/request/openai-to-vertex.js +42 -0
- package/open-sse/translator/response/claude-to-openai.js +195 -0
- package/open-sse/translator/response/commandcode-to-openai.js +188 -0
- package/open-sse/translator/response/cursor-to-openai.js +30 -0
- package/open-sse/translator/response/gemini-to-openai.js +147 -0
- package/open-sse/translator/response/kiro-to-claude.js +261 -0
- package/open-sse/translator/response/kiro-to-openai.js +160 -0
- package/open-sse/translator/response/ollama-to-openai.js +134 -0
- package/open-sse/translator/response/openai-responses.js +535 -0
- package/open-sse/translator/response/openai-to-antigravity.js +123 -0
- package/open-sse/translator/response/openai-to-claude.js +265 -0
- package/open-sse/translator/schema/blocks.js +43 -0
- package/open-sse/translator/schema/defaults.js +7 -0
- package/open-sse/translator/schema/finishReasons.js +27 -0
- package/open-sse/translator/schema/index.js +8 -0
- package/open-sse/translator/schema/roles.js +16 -0
- package/open-sse/utils/agentGoalPolicy.js +85 -0
- package/open-sse/utils/aiSdkCompat.js +75 -0
- package/open-sse/utils/bypassHandler.js +298 -0
- package/open-sse/utils/cacheControlPolicy.js +189 -0
- package/open-sse/utils/claudeCloaking.js +155 -0
- package/open-sse/utils/claudeHeaderCache.js +70 -0
- package/open-sse/utils/claudeSignature.js +41 -0
- package/open-sse/utils/clientDetector.js +63 -0
- package/open-sse/utils/codebuddySanitizer.js +96 -0
- package/open-sse/utils/composerToolCalls.js +158 -0
- package/open-sse/utils/cors.js +13 -0
- package/open-sse/utils/cursorChecksum.js +149 -0
- package/open-sse/utils/cursorImages.js +224 -0
- package/open-sse/utils/cursorProtobuf.js +904 -0
- package/open-sse/utils/cursorVersionDetector.js +55 -0
- package/open-sse/utils/debugLog.js +14 -0
- package/open-sse/utils/diagnostics.js +143 -0
- package/open-sse/utils/error.js +164 -0
- package/open-sse/utils/estimateSize.js +33 -0
- package/open-sse/utils/finishReason.js +32 -0
- package/open-sse/utils/flattenToolHistory.js +68 -0
- package/open-sse/utils/headers.js +36 -0
- package/open-sse/utils/heapPressure.js +35 -0
- package/open-sse/utils/jsonToSse.js +125 -0
- package/open-sse/utils/keepaliveThreshold.js +40 -0
- package/open-sse/utils/logger.js +104 -0
- package/open-sse/utils/noThinkingAlias.js +74 -0
- package/open-sse/utils/number.js +7 -0
- package/open-sse/utils/ollamaTransform.js +85 -0
- package/open-sse/utils/opencodeHeaders.js +47 -0
- package/open-sse/utils/progressTracker.js +81 -0
- package/open-sse/utils/providerRequestLogging.js +219 -0
- package/open-sse/utils/proxyFetch.js +369 -0
- package/open-sse/utils/reasoningContentInjector.js +79 -0
- package/open-sse/utils/reasoningFields.js +70 -0
- package/open-sse/utils/requestLogger.js +260 -0
- package/open-sse/utils/responsesInputNormalization.js +92 -0
- package/open-sse/utils/responsesStatePolicy.js +52 -0
- package/open-sse/utils/responsesStreamHelpers.js +49 -0
- package/open-sse/utils/sessionManager.js +240 -0
- package/open-sse/utils/sleep.js +6 -0
- package/open-sse/utils/sse.js +14 -0
- package/open-sse/utils/sseConstants.js +23 -0
- package/open-sse/utils/sseHeartbeat.js +104 -0
- package/open-sse/utils/stream.js +517 -0
- package/open-sse/utils/streamFailureFinalization.js +134 -0
- package/open-sse/utils/streamHandler.js +250 -0
- package/open-sse/utils/streamHelpers.js +137 -0
- package/open-sse/utils/textualToolCall.js +104 -0
- package/open-sse/utils/thinkCloseMarker.js +72 -0
- package/open-sse/utils/thinkTagParser.js +146 -0
- package/open-sse/utils/toolCallArguments.js +12 -0
- package/open-sse/utils/toolDeduper.js +49 -0
- package/open-sse/utils/toolSources.js +31 -0
- package/open-sse/utils/upstreamResponseHeaders.js +25 -0
- package/open-sse/utils/urlSanitize.js +15 -0
- package/open-sse/utils/usageTracking.js +347 -0
- package/package.json +1 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Concern: reasoning_effort ↔ provider-native thinking config.
|
|
2
|
+
// Central source of truth for level↔budget maps (web-standard values).
|
|
3
|
+
// Provider-specific application lives in thinkingUnified.js; this file is maps-only.
|
|
4
|
+
|
|
5
|
+
// Discrete effort levels, ordered low→high.
|
|
6
|
+
export const EFFORT_LEVELS = ["minimal", "low", "medium", "high", "xhigh", "max"];
|
|
7
|
+
|
|
8
|
+
// Web-standard level → budget_tokens (Anthropic/Gemini docs).
|
|
9
|
+
export const LEVEL_TO_BUDGET = {
|
|
10
|
+
none: 0,
|
|
11
|
+
minimal: 512,
|
|
12
|
+
low: 1024,
|
|
13
|
+
medium: 8192,
|
|
14
|
+
high: 24576,
|
|
15
|
+
xhigh: 32768,
|
|
16
|
+
max: 128000,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// Returns budget_tokens for an effort level, or undefined if unknown.
|
|
20
|
+
// 0 means "no thinking"; undefined means "effort not recognized".
|
|
21
|
+
export function effortToBudget(effort) {
|
|
22
|
+
if (!effort) return undefined;
|
|
23
|
+
return LEVEL_TO_BUDGET[String(effort).toLowerCase()];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// OpenAI reasoning_effort → Gemini thinkingLevel (gemini-3 enum: minimal|low|medium|high).
|
|
27
|
+
// Gemini 3 cannot fully disable thinking; "none"/"off" map to "minimal".
|
|
28
|
+
export function effortToThinkingLevel(effort) {
|
|
29
|
+
const e = String(effort).toLowerCase().trim();
|
|
30
|
+
if (e === "none" || e === "off") return "minimal";
|
|
31
|
+
if (e === "xhigh" || e === "max") return "high";
|
|
32
|
+
return e;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Numeric budget → nearest discrete level (reverse map via thresholds).
|
|
36
|
+
// Returns null when budget <= 0 (no reasoning).
|
|
37
|
+
export function budgetToLevel(budget) {
|
|
38
|
+
const b = Number(budget);
|
|
39
|
+
if (!b || b <= 0) return null;
|
|
40
|
+
if (b <= 768) return "minimal";
|
|
41
|
+
if (b <= 4096) return "low";
|
|
42
|
+
if (b <= 16384) return "medium";
|
|
43
|
+
if (b <= 28672) return "high";
|
|
44
|
+
return "xhigh";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Gemini thinkingBudget (numeric) → OpenAI reasoning_effort (antigravity reverse map).
|
|
48
|
+
export function budgetToEffort(budget) {
|
|
49
|
+
if (!budget || budget <= 0) return null;
|
|
50
|
+
if (budget <= 2048) return "low";
|
|
51
|
+
if (budget <= 16384) return "medium";
|
|
52
|
+
return "high";
|
|
53
|
+
}
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
// Unified thinking normalization: extract client intent → apply provider-native format.
|
|
2
|
+
// Config-driven: thinking format/limits come from capabilities.js + registry transport,
|
|
3
|
+
// never hardcoded per-model here. See .docs/thinking/plan.md MATRIX VI-A.
|
|
4
|
+
|
|
5
|
+
import { getCapabilitiesForModel } from "../../providers/capabilities.js";
|
|
6
|
+
import { PROVIDERS } from "../../providers/index.js";
|
|
7
|
+
import { LEVEL_TO_BUDGET, budgetToLevel, effortToBudget, effortToThinkingLevel } from "./thinking.js";
|
|
8
|
+
|
|
9
|
+
// Map a target wire-format to its native thinking format (when capability has none).
|
|
10
|
+
const FORMAT_TO_NATIVE = {
|
|
11
|
+
openai: "openai",
|
|
12
|
+
"openai-responses": "openai",
|
|
13
|
+
"openai-response": "openai",
|
|
14
|
+
codex: "openai",
|
|
15
|
+
claude: "claude-budget",
|
|
16
|
+
gemini: "gemini-budget",
|
|
17
|
+
"gemini-cli": "gemini-budget",
|
|
18
|
+
vertex: "gemini-budget",
|
|
19
|
+
antigravity: "gemini-budget",
|
|
20
|
+
kiro: "kiro",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Strip a trailing thinking suffix "model(value)" → "model" (no-op when absent).
|
|
24
|
+
export function stripThinkingSuffix(model) {
|
|
25
|
+
if (typeof model !== "string") return model;
|
|
26
|
+
const m = model.match(/^(.*)\([^()]+\)\s*$/);
|
|
27
|
+
return m ? m[1].trim() : model;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Parse model-name suffix "model(value)" → { cleanModel, override }.
|
|
31
|
+
// value: level name (high) | number (8192) | auto | none. null override when absent.
|
|
32
|
+
export function parseSuffix(model) {
|
|
33
|
+
if (typeof model !== "string") return { cleanModel: model, override: null };
|
|
34
|
+
const m = model.match(/^(.*)\(([^()]+)\)\s*$/);
|
|
35
|
+
if (!m) return { cleanModel: model, override: null };
|
|
36
|
+
const cleanModel = m[1].trim();
|
|
37
|
+
const raw = m[2].trim().toLowerCase();
|
|
38
|
+
if (raw === "none" || raw === "off") return { cleanModel, override: { mode: "none" } };
|
|
39
|
+
if (raw === "auto") return { cleanModel, override: { mode: "auto" } };
|
|
40
|
+
if (/^\d+$/.test(raw)) return { cleanModel, override: { mode: "budget", budget: Number(raw) } };
|
|
41
|
+
if (LEVEL_TO_BUDGET[raw] !== undefined) return { cleanModel, override: { mode: "level", level: raw } };
|
|
42
|
+
return { cleanModel, override: null };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Extract unified thinking intent from a request body (post-translation, mixed shapes).
|
|
46
|
+
// Returns { mode, budget?, level? } or null when no thinking intent present.
|
|
47
|
+
export function extractThinking(body) {
|
|
48
|
+
if (!body || typeof body !== "object") return null;
|
|
49
|
+
|
|
50
|
+
// Claude output_config.effort (explicit) — priority over adaptive thinking
|
|
51
|
+
const oc = body.output_config?.effort;
|
|
52
|
+
if (typeof oc === "string" && oc) {
|
|
53
|
+
const e = oc.toLowerCase();
|
|
54
|
+
if (e === "none" || e === "off") return { mode: "none" };
|
|
55
|
+
if (e === "auto") return { mode: "auto" };
|
|
56
|
+
return { mode: "level", level: e };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Claude shape
|
|
60
|
+
const t = body.thinking;
|
|
61
|
+
if (t && typeof t === "object") {
|
|
62
|
+
if (t.type === "disabled") return { mode: "none" };
|
|
63
|
+
if (t.type === "adaptive" || t.type === "enabled") {
|
|
64
|
+
const budget = Number(t.budget_tokens);
|
|
65
|
+
if (Number.isFinite(budget) && budget > 0) return { mode: "budget", budget };
|
|
66
|
+
return { mode: "auto" };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// OpenAI chat / Responses shape
|
|
71
|
+
const effort = body.reasoning_effort ?? (typeof body.reasoning === "object" ? body.reasoning?.effort : null);
|
|
72
|
+
if (typeof effort === "string" && effort) {
|
|
73
|
+
const e = effort.toLowerCase();
|
|
74
|
+
if (e === "none" || e === "off") return { mode: "none" };
|
|
75
|
+
if (e === "auto") return { mode: "auto" };
|
|
76
|
+
return { mode: "level", level: e };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Gemini shape (top-level, generationConfig, or request envelope)
|
|
80
|
+
const tc = body.thinkingConfig || body.generationConfig?.thinkingConfig || body.request?.generationConfig?.thinkingConfig;
|
|
81
|
+
if (tc && typeof tc === "object") {
|
|
82
|
+
if (typeof tc.thinkingLevel === "string") return { mode: "level", level: tc.thinkingLevel.toLowerCase() };
|
|
83
|
+
const tb = Number(tc.thinkingBudget);
|
|
84
|
+
if (Number.isFinite(tb)) {
|
|
85
|
+
if (tb === 0) return { mode: "none" };
|
|
86
|
+
if (tb < 0) return { mode: "auto" };
|
|
87
|
+
return { mode: "budget", budget: tb };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Qwen shape
|
|
92
|
+
if (body.enable_thinking === false) return { mode: "none" };
|
|
93
|
+
if (body.enable_thinking === true) {
|
|
94
|
+
const tb = Number(body.thinking_budget);
|
|
95
|
+
if (Number.isFinite(tb) && tb > 0) return { mode: "budget", budget: tb };
|
|
96
|
+
return { mode: "auto" };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Capture thinking intent from a body. Alias of extractThinking, named for clarity
|
|
103
|
+
// at the call-site where intent is snapshotted before format translation.
|
|
104
|
+
export const captureThinking = extractThinking;
|
|
105
|
+
|
|
106
|
+
// Resolve thinking format: provider override > capability > derive(targetFormat).
|
|
107
|
+
function resolveFormat(targetFormat, model, provider) {
|
|
108
|
+
const providerFmt = provider ? PROVIDERS[provider]?.thinkingFormat : null;
|
|
109
|
+
if (providerFmt) return providerFmt;
|
|
110
|
+
const caps = getCapabilitiesForModel(provider, model);
|
|
111
|
+
if (caps.thinkingFormat) return caps.thinkingFormat;
|
|
112
|
+
return FORMAT_TO_NATIVE[targetFormat] || "openai";
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Convert unified config to a budget number (for budget-based formats).
|
|
116
|
+
function toBudget(cfg, range) {
|
|
117
|
+
let budget;
|
|
118
|
+
if (cfg.mode === "budget") budget = cfg.budget;
|
|
119
|
+
else if (cfg.mode === "level") budget = effortToBudget(cfg.level);
|
|
120
|
+
else if (cfg.mode === "auto") return -1;
|
|
121
|
+
if (!Number.isFinite(budget)) return undefined;
|
|
122
|
+
if (range) {
|
|
123
|
+
if (range.min != null && budget < range.min) budget = range.min;
|
|
124
|
+
if (range.max != null && budget > range.max) budget = range.max;
|
|
125
|
+
}
|
|
126
|
+
return budget;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Convert unified config to a discrete level string.
|
|
130
|
+
function toLevel(cfg) {
|
|
131
|
+
if (cfg.mode === "level") return cfg.level;
|
|
132
|
+
if (cfg.mode === "budget") return budgetToLevel(cfg.budget) || "medium";
|
|
133
|
+
if (cfg.mode === "auto") return "auto";
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function toGeminiThinkingLevel(cfg) {
|
|
138
|
+
const raw = cfg.mode === "auto" ? "high" : (toLevel(cfg) || "high");
|
|
139
|
+
return effortToThinkingLevel(raw);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function toKimiReasoningEffort(cfg) {
|
|
143
|
+
const level = toLevel(cfg);
|
|
144
|
+
if (level === "auto") return "high";
|
|
145
|
+
if (level === "minimal") return "low";
|
|
146
|
+
if (level === "xhigh") return "max";
|
|
147
|
+
if (["low", "medium", "high", "max"].includes(level)) return level;
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const GEMINI_LEVEL_OUTPUT_FLOOR = {
|
|
152
|
+
minimal: 4096,
|
|
153
|
+
low: 8192,
|
|
154
|
+
medium: 16384,
|
|
155
|
+
high: 65535,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
function geminiBudgetOutputFloor(budget) {
|
|
159
|
+
if (budget === -1) return 32768;
|
|
160
|
+
if (!Number.isFinite(budget)) return 32768;
|
|
161
|
+
if (budget <= 1024) return 8192;
|
|
162
|
+
if (budget <= 8192) return 16384;
|
|
163
|
+
if (budget <= 24576) return 32768;
|
|
164
|
+
return 65535;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function geminiLevelOutputFloor(level) {
|
|
168
|
+
return GEMINI_LEVEL_OUTPUT_FLOOR[level] || GEMINI_LEVEL_OUTPUT_FLOOR.high;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Gemini nests thinkingConfig under generationConfig. gemini-cli / antigravity wrap
|
|
172
|
+
// the whole request in a { request: { generationConfig } } envelope — target the
|
|
173
|
+
// envelope's generationConfig when present, else the top-level one.
|
|
174
|
+
function getGeminiGenerationConfig(body) {
|
|
175
|
+
if (body.request && typeof body.request === "object") {
|
|
176
|
+
if (!body.request.generationConfig || typeof body.request.generationConfig !== "object") {
|
|
177
|
+
body.request.generationConfig = {};
|
|
178
|
+
}
|
|
179
|
+
return body.request.generationConfig;
|
|
180
|
+
}
|
|
181
|
+
if (!body.generationConfig || typeof body.generationConfig !== "object") {
|
|
182
|
+
body.generationConfig = {};
|
|
183
|
+
}
|
|
184
|
+
return body.generationConfig;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function setGeminiThinking(body, tc) {
|
|
188
|
+
const gc = getGeminiGenerationConfig(body);
|
|
189
|
+
gc.thinkingConfig = tc;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function ensureGeminiOutputFloor(body, floor, caps) {
|
|
193
|
+
const cap = Number.isFinite(caps?.maxOutput) ? caps.maxOutput : floor;
|
|
194
|
+
const target = Math.min(floor, cap);
|
|
195
|
+
const gc = getGeminiGenerationConfig(body);
|
|
196
|
+
const current = Number(gc.maxOutputTokens);
|
|
197
|
+
if (!Number.isFinite(current) || current < target) {
|
|
198
|
+
gc.maxOutputTokens = target;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Strip every known thinking field from a body (used before re-applying / when unsupported).
|
|
203
|
+
function stripAll(body) {
|
|
204
|
+
delete body.thinking;
|
|
205
|
+
delete body.reasoning_effort;
|
|
206
|
+
delete body.reasoning;
|
|
207
|
+
delete body.thinkingConfig;
|
|
208
|
+
delete body.enable_thinking;
|
|
209
|
+
delete body.thinking_budget;
|
|
210
|
+
delete body.output_config;
|
|
211
|
+
if (body.generationConfig) delete body.generationConfig.thinkingConfig;
|
|
212
|
+
if (body.request?.generationConfig) delete body.request.generationConfig.thinkingConfig;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Apply unified thinking config to body in the resolved provider-native format.
|
|
216
|
+
function applyFormat(fmt, body, cfg, caps) {
|
|
217
|
+
const none = cfg.mode === "none";
|
|
218
|
+
const canDisable = caps.thinkingCanDisable !== false;
|
|
219
|
+
// Model cannot disable thinking → clamp "none" to minimal effort instead.
|
|
220
|
+
const eff = none && !canDisable ? { mode: "level", level: "minimal" } : cfg;
|
|
221
|
+
|
|
222
|
+
switch (fmt) {
|
|
223
|
+
case "openai": {
|
|
224
|
+
if (none && canDisable) { body.reasoning_effort = "none"; break; }
|
|
225
|
+
const level = toLevel(eff);
|
|
226
|
+
// OpenAI reasoning_effort enum caps at "xhigh" (no "max"); clamp Claude Code's "max".
|
|
227
|
+
if (level) body.reasoning_effort = level === "max" ? "xhigh" : level;
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
case "claude-adaptive": {
|
|
231
|
+
if (none && canDisable) { body.thinking = { type: "disabled" }; break; }
|
|
232
|
+
const level = toLevel(eff);
|
|
233
|
+
body.output_config = { effort: level === "xhigh" ? "high" : level };
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
case "claude-budget": {
|
|
237
|
+
if (none && canDisable) { body.thinking = { type: "disabled" }; break; }
|
|
238
|
+
const budget = toBudget(eff, caps.thinkingRange);
|
|
239
|
+
body.thinking = budget === -1 ? { type: "enabled" } : { type: "enabled", budget_tokens: budget || 8192 };
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
case "gemini-level": {
|
|
243
|
+
const level = none ? "minimal" : toGeminiThinkingLevel(eff);
|
|
244
|
+
setGeminiThinking(body, { thinkingLevel: level, includeThoughts: level !== "minimal" });
|
|
245
|
+
ensureGeminiOutputFloor(body, geminiLevelOutputFloor(level), caps);
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
case "gemini-budget": {
|
|
249
|
+
if (none && canDisable) { setGeminiThinking(body, { thinkingBudget: 0, includeThoughts: false }); break; }
|
|
250
|
+
const budget = toBudget(eff, caps.thinkingRange);
|
|
251
|
+
setGeminiThinking(body, { thinkingBudget: budget ?? -1, includeThoughts: true });
|
|
252
|
+
ensureGeminiOutputFloor(body, geminiBudgetOutputFloor(budget ?? -1), caps);
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
case "zai": {
|
|
256
|
+
// Z.ai ignores thinking.disabled → must use enable_thinking:false to turn off.
|
|
257
|
+
if (none && canDisable) { body.enable_thinking = false; delete body.thinking; break; }
|
|
258
|
+
body.thinking = { type: "enabled" };
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
case "qwen": {
|
|
262
|
+
if (none && canDisable) { body.enable_thinking = false; break; }
|
|
263
|
+
body.enable_thinking = true;
|
|
264
|
+
const budget = toBudget(eff, caps.thinkingRange);
|
|
265
|
+
if (Number.isFinite(budget) && budget > 0) body.thinking_budget = budget;
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
case "deepseek": {
|
|
269
|
+
if (none && canDisable) { body.thinking = { type: "disabled" }; break; }
|
|
270
|
+
body.thinking = { type: "enabled" };
|
|
271
|
+
// DeepSeek: low/medium→high, xhigh/max→max.
|
|
272
|
+
const level = toLevel(eff);
|
|
273
|
+
body.reasoning_effort = level === "xhigh" || level === "max" ? "max" : "high";
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
case "kimi": {
|
|
277
|
+
if (none && canDisable) { body.thinking = { type: "disabled" }; break; }
|
|
278
|
+
const effort = toKimiReasoningEffort(eff);
|
|
279
|
+
if (effort) body.reasoning_effort = effort;
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
case "minimax": {
|
|
283
|
+
// M3 adaptive; M2.x cannot disable (handled via canDisable clamp).
|
|
284
|
+
body.thinking = { type: none && canDisable ? "disabled" : "adaptive" };
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
case "hunyuan": {
|
|
288
|
+
if (none && canDisable) { body.thinking = { type: "disabled" }; break; }
|
|
289
|
+
const budget = toBudget(eff, caps.thinkingRange);
|
|
290
|
+
body.thinking = budget === -1 ? { type: "enabled" } : { type: "enabled", budget_tokens: budget || 8192 };
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
case "step": {
|
|
294
|
+
if (none && canDisable) break;
|
|
295
|
+
const level = toLevel(eff);
|
|
296
|
+
if (level) body.reasoning_effort = level === "xhigh" || level === "max" ? "high" : level;
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
case "kiro":
|
|
300
|
+
// Kiro thinking handled via system-tag injection in openai-to-kiro.js; no body field here.
|
|
301
|
+
break;
|
|
302
|
+
default:
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Public entry: normalize thinking for the resolved target format.
|
|
308
|
+
// Mutates and returns body. No-op when model has no reasoning capability.
|
|
309
|
+
// `intent` is a pre-captured config (from captureThinking on the original body);
|
|
310
|
+
// falls back to extracting from the current body when omitted.
|
|
311
|
+
export function applyThinking(targetFormat, model, body, provider = null, intent = undefined) {
|
|
312
|
+
if (!body || typeof body !== "object") return body;
|
|
313
|
+
|
|
314
|
+
const { cleanModel, override } = parseSuffix(model);
|
|
315
|
+
const cfg = override || intent || extractThinking(body);
|
|
316
|
+
const caps = getCapabilitiesForModel(provider, cleanModel);
|
|
317
|
+
|
|
318
|
+
// Model cannot reason → strip any stray thinking fields.
|
|
319
|
+
if (!caps.reasoning) {
|
|
320
|
+
stripAll(body);
|
|
321
|
+
return body;
|
|
322
|
+
}
|
|
323
|
+
if (!cfg) return body;
|
|
324
|
+
|
|
325
|
+
const fmt = resolveFormat(targetFormat, cleanModel, provider);
|
|
326
|
+
stripAll(body);
|
|
327
|
+
applyFormat(fmt, body, cfg, caps);
|
|
328
|
+
return body;
|
|
329
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// Tool call helper functions for translator
|
|
2
|
+
|
|
3
|
+
// Anthropic tool_use.id must match: ^[a-zA-Z0-9_-]+$
|
|
4
|
+
const TOOL_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
5
|
+
|
|
6
|
+
// Fallback streaming tool_call id when provider omits one (index optional)
|
|
7
|
+
export function fallbackToolCallId(index) {
|
|
8
|
+
return index === undefined ? `call_${Date.now()}` : `call_${index}_${Date.now()}`;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Generate deterministic tool call ID from position + tool name (cache-friendly)
|
|
12
|
+
export function generateToolCallId(msgIndex = 0, tcIndex = 0, toolName = "") {
|
|
13
|
+
const name = toolName ? `_${toolName.replace(/[^a-zA-Z0-9_-]/g, "")}` : "";
|
|
14
|
+
return `call_msg${msgIndex}_tc${tcIndex}${name}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Sanitize ID to match Anthropic pattern: keep only alphanumeric, underscore, hyphen
|
|
18
|
+
function sanitizeToolId(id) {
|
|
19
|
+
if (!id || typeof id !== "string") return null;
|
|
20
|
+
const sanitized = id.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
21
|
+
return sanitized.length > 0 ? sanitized : null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Ensure all tool_calls have valid id field and arguments is string (some providers require it)
|
|
25
|
+
export function ensureToolCallIds(body) {
|
|
26
|
+
if (!body.messages || !Array.isArray(body.messages)) return body;
|
|
27
|
+
|
|
28
|
+
for (let i = 0; i < body.messages.length; i++) {
|
|
29
|
+
const msg = body.messages[i];
|
|
30
|
+
if (msg.role === "assistant" && msg.tool_calls && Array.isArray(msg.tool_calls)) {
|
|
31
|
+
for (let j = 0; j < msg.tool_calls.length; j++) {
|
|
32
|
+
const tc = msg.tool_calls[j];
|
|
33
|
+
// Validate or regenerate ID for Anthropic compatibility
|
|
34
|
+
if (!tc.id || !TOOL_ID_PATTERN.test(tc.id)) {
|
|
35
|
+
const sanitized = sanitizeToolId(tc.id);
|
|
36
|
+
tc.id = sanitized || generateToolCallId(i, j, tc.function?.name);
|
|
37
|
+
}
|
|
38
|
+
if (!tc.type) {
|
|
39
|
+
tc.type = "function";
|
|
40
|
+
}
|
|
41
|
+
// Ensure arguments is JSON string, not object
|
|
42
|
+
if (tc.function?.arguments && typeof tc.function.arguments !== "string") {
|
|
43
|
+
tc.function.arguments = JSON.stringify(tc.function.arguments);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Validate tool_call_id in tool messages (role: "tool")
|
|
49
|
+
if (msg.role === "tool" && msg.tool_call_id && !TOOL_ID_PATTERN.test(msg.tool_call_id)) {
|
|
50
|
+
const sanitized = sanitizeToolId(msg.tool_call_id);
|
|
51
|
+
msg.tool_call_id = sanitized || generateToolCallId(i, 0);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Also validate tool_use blocks in content (Claude format)
|
|
55
|
+
if (Array.isArray(msg.content)) {
|
|
56
|
+
for (let k = 0; k < msg.content.length; k++) {
|
|
57
|
+
const block = msg.content[k];
|
|
58
|
+
if (block.type === "tool_use" && block.id && !TOOL_ID_PATTERN.test(block.id)) {
|
|
59
|
+
const sanitized = sanitizeToolId(block.id);
|
|
60
|
+
block.id = sanitized || generateToolCallId(i, k, block.name);
|
|
61
|
+
}
|
|
62
|
+
// Validate tool_use_id in tool_result blocks
|
|
63
|
+
if (block.type === "tool_result" && block.tool_use_id && !TOOL_ID_PATTERN.test(block.tool_use_id)) {
|
|
64
|
+
const sanitized = sanitizeToolId(block.tool_use_id);
|
|
65
|
+
block.tool_use_id = sanitized || generateToolCallId(i, k);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return body;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Get tool_call ids from assistant message (OpenAI format: tool_calls, Claude format: tool_use in content)
|
|
75
|
+
export function getToolCallIds(msg) {
|
|
76
|
+
if (msg.role !== "assistant") return [];
|
|
77
|
+
|
|
78
|
+
const ids = [];
|
|
79
|
+
|
|
80
|
+
// OpenAI format: tool_calls array
|
|
81
|
+
if (msg.tool_calls && Array.isArray(msg.tool_calls)) {
|
|
82
|
+
for (const tc of msg.tool_calls) {
|
|
83
|
+
if (tc.id) ids.push(tc.id);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Claude format: tool_use blocks in content
|
|
88
|
+
if (Array.isArray(msg.content)) {
|
|
89
|
+
for (const block of msg.content) {
|
|
90
|
+
if (block.type === "tool_use" && block.id) {
|
|
91
|
+
ids.push(block.id);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return ids;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Check if user message has tool_result for given ids (OpenAI format: role=tool, Claude format: tool_result in content)
|
|
100
|
+
export function hasToolResults(msg, toolCallIds) {
|
|
101
|
+
if (!msg || !toolCallIds.length) return false;
|
|
102
|
+
|
|
103
|
+
// OpenAI format: role = "tool" with tool_call_id
|
|
104
|
+
if (msg.role === "tool" && msg.tool_call_id) {
|
|
105
|
+
return toolCallIds.includes(msg.tool_call_id);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Claude format: tool_result blocks in user message content
|
|
109
|
+
if (msg.role === "user" && Array.isArray(msg.content)) {
|
|
110
|
+
for (const block of msg.content) {
|
|
111
|
+
if (block.type === "tool_result" && toolCallIds.includes(block.tool_use_id)) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Fix missing tool responses - insert empty tool_result if assistant has tool_use but next message has no tool_result
|
|
121
|
+
export function fixMissingToolResponses(body) {
|
|
122
|
+
if (!body.messages || !Array.isArray(body.messages)) return body;
|
|
123
|
+
|
|
124
|
+
const newMessages = [];
|
|
125
|
+
|
|
126
|
+
for (let i = 0; i < body.messages.length; i++) {
|
|
127
|
+
const msg = body.messages[i];
|
|
128
|
+
const nextMsg = body.messages[i + 1];
|
|
129
|
+
|
|
130
|
+
newMessages.push(msg);
|
|
131
|
+
|
|
132
|
+
// Check if this is assistant with tool_calls/tool_use
|
|
133
|
+
const toolCallIds = getToolCallIds(msg);
|
|
134
|
+
if (toolCallIds.length === 0) continue;
|
|
135
|
+
|
|
136
|
+
// Check if next message has tool_result
|
|
137
|
+
if (nextMsg && !hasToolResults(nextMsg, toolCallIds)) {
|
|
138
|
+
// Insert tool responses for each tool_call
|
|
139
|
+
for (const id of toolCallIds) {
|
|
140
|
+
// OpenAI format: role = "tool"
|
|
141
|
+
newMessages.push({
|
|
142
|
+
role: "tool",
|
|
143
|
+
tool_call_id: id,
|
|
144
|
+
content: ""
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
body.messages = newMessages;
|
|
151
|
+
return body;
|
|
152
|
+
}
|
|
153
|
+
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Build OpenAI usage object. Caller computes prompt/completion/total (provider math).
|
|
2
|
+
// Optional details added only when > 0 (matches existing claude/gemini/codex behavior).
|
|
3
|
+
export function buildUsage({ promptTokens, completionTokens, totalTokens, cachedTokens = 0, cacheCreationTokens = 0, reasoningTokens = 0 }) {
|
|
4
|
+
const usage = { prompt_tokens: promptTokens, completion_tokens: completionTokens, total_tokens: totalTokens };
|
|
5
|
+
if (cachedTokens > 0 || cacheCreationTokens > 0) {
|
|
6
|
+
usage.prompt_tokens_details = {};
|
|
7
|
+
if (cachedTokens > 0) usage.prompt_tokens_details.cached_tokens = cachedTokens;
|
|
8
|
+
if (cacheCreationTokens > 0) usage.prompt_tokens_details.cache_creation_tokens = cacheCreationTokens;
|
|
9
|
+
}
|
|
10
|
+
if (reasoningTokens > 0) {
|
|
11
|
+
usage.completion_tokens_details = { reasoning_tokens: reasoningTokens };
|
|
12
|
+
}
|
|
13
|
+
return usage;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const n = (v) => (typeof v === "number" ? v : 0);
|
|
17
|
+
|
|
18
|
+
// Per-provider raw token field-map + math. Returns buildUsage() args (NOT the usage object).
|
|
19
|
+
// Keeps each provider's exact semantics: claude/gemini fold cache+reasoning, others don't.
|
|
20
|
+
const USAGE_EXTRACTORS = {
|
|
21
|
+
claude(raw) {
|
|
22
|
+
const input = n(raw.input_tokens), output = n(raw.output_tokens);
|
|
23
|
+
const cacheRead = n(raw.cache_read_input_tokens), cacheCreate = n(raw.cache_creation_input_tokens);
|
|
24
|
+
const prompt = input + cacheRead + cacheCreate;
|
|
25
|
+
return { promptTokens: prompt, completionTokens: output, totalTokens: prompt + output, cachedTokens: cacheRead, cacheCreationTokens: cacheCreate };
|
|
26
|
+
},
|
|
27
|
+
gemini(raw) {
|
|
28
|
+
const cached = n(raw.cachedContentTokenCount);
|
|
29
|
+
const prompt = n(raw.promptTokenCount);
|
|
30
|
+
const thoughts = n(raw.thoughtsTokenCount);
|
|
31
|
+
const total = n(raw.totalTokenCount);
|
|
32
|
+
let candidates = n(raw.candidatesTokenCount);
|
|
33
|
+
// Fallback: derive candidates from total when upstream omits it
|
|
34
|
+
if (candidates === 0 && total > 0) {
|
|
35
|
+
candidates = total - prompt - thoughts;
|
|
36
|
+
if (candidates < 0) candidates = 0;
|
|
37
|
+
}
|
|
38
|
+
return { promptTokens: prompt, completionTokens: candidates + thoughts, totalTokens: total, cachedTokens: cached, reasoningTokens: thoughts };
|
|
39
|
+
},
|
|
40
|
+
kiro(raw) {
|
|
41
|
+
const input = n(raw.inputTokens), output = n(raw.outputTokens);
|
|
42
|
+
// ponytail: Amazon Q (Kiro upstream) does not expose cache fields today,
|
|
43
|
+
// but pass through any cache_read/cache_creation/cached_tokens if the
|
|
44
|
+
// event shape grows them later so cost tracking keeps working without
|
|
45
|
+
// a second pass.
|
|
46
|
+
const cached = n(raw.cache_read_input_tokens) || n(raw.cachedTokens) || n(raw.cached_tokens);
|
|
47
|
+
const cacheCreation = n(raw.cache_creation_input_tokens);
|
|
48
|
+
const out = { promptTokens: input, completionTokens: output, totalTokens: input + output };
|
|
49
|
+
if (cached > 0) out.cachedTokens = cached;
|
|
50
|
+
if (cacheCreation > 0) out.cacheCreationTokens = cacheCreation;
|
|
51
|
+
return out;
|
|
52
|
+
},
|
|
53
|
+
ollama(raw) {
|
|
54
|
+
const input = n(raw.prompt_eval_count), output = n(raw.eval_count);
|
|
55
|
+
return { promptTokens: input, completionTokens: output, totalTokens: input + output };
|
|
56
|
+
},
|
|
57
|
+
commandcode(raw) {
|
|
58
|
+
const input = n(raw.inputTokens), output = n(raw.outputTokens);
|
|
59
|
+
const total = typeof raw.totalTokens === "number" ? raw.totalTokens : input + output;
|
|
60
|
+
return { promptTokens: input, completionTokens: output, totalTokens: total };
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Convert provider-native usage object → OpenAI usage. Returns null if no extractor/raw.
|
|
65
|
+
export function toOpenAIUsage(raw, kind) {
|
|
66
|
+
const extract = USAGE_EXTRACTORS[kind];
|
|
67
|
+
if (!extract || !raw || typeof raw !== "object") return null;
|
|
68
|
+
return buildUsage(extract(raw));
|
|
69
|
+
}
|