@fudrouter/fsrouter 0.6.72 → 0.6.74
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/lib/headroom/detect.js +97 -7
- package/dist/lib/headroom/process.js +136 -4
- package/dist/open-sse/config/appConstants.js +23 -79
- package/dist/open-sse/config/cliFingerprints.js +1 -1
- package/dist/open-sse/config/errorConfig.js +0 -11
- package/dist/open-sse/config/grokCli.js +10 -0
- package/dist/open-sse/config/kiroConstants.js +99 -46
- package/dist/open-sse/config/runtimeConfig.js +2 -0
- package/dist/open-sse/config/ttsModels.js +2 -0
- package/dist/open-sse/executors/antigravity.js +250 -164
- package/dist/open-sse/executors/base.js +16 -11
- package/dist/open-sse/executors/codex.js +269 -1108
- package/dist/open-sse/executors/commandCode.js +1 -1
- package/dist/open-sse/executors/commandcode.js +10 -4
- package/dist/open-sse/executors/cursor.js +96 -203
- package/dist/open-sse/executors/default.js +146 -244
- package/dist/open-sse/executors/github.js +128 -73
- package/dist/open-sse/executors/grok-cli.js +527 -94
- package/dist/open-sse/executors/grok-web.js +5 -7
- package/dist/open-sse/executors/index.js +12 -0
- package/dist/open-sse/executors/kiro.js +150 -61
- package/dist/open-sse/executors/opencode-go.js +12 -4
- package/dist/open-sse/executors/opencode.js +1 -1
- package/dist/open-sse/executors/perplexity-web.js +20 -96
- package/dist/open-sse/executors/qoder.js +28 -18
- package/dist/open-sse/executors/vertex.js +53 -7
- package/dist/open-sse/executors/xiaomi-tokenplan.js +6 -5
- package/dist/open-sse/handlers/chatCore/nonStreamingHandler.js +97 -85
- package/dist/open-sse/handlers/chatCore/requestDetail.js +32 -8
- package/dist/open-sse/handlers/chatCore/sseToJsonHandler.js +13 -7
- package/dist/open-sse/handlers/chatCore/streamingHandler.js +74 -25
- package/dist/open-sse/handlers/chatCore.js +35 -41
- package/dist/open-sse/handlers/embeddingProviders/index.js +1 -0
- package/dist/open-sse/handlers/embeddingProviders/openai.js +8 -16
- package/dist/open-sse/handlers/imageProviders/blackForestLabs.js +2 -21
- package/dist/open-sse/handlers/imageProviders/cloudflareAi.js +2 -30
- package/dist/open-sse/handlers/imageProviders/codex.js +2 -20
- package/dist/open-sse/handlers/imageProviders/comfyui.js +5 -18
- package/dist/open-sse/handlers/imageProviders/falAi.js +2 -22
- package/dist/open-sse/handlers/imageProviders/gemini.js +2 -16
- package/dist/open-sse/handlers/imageProviders/huggingface.js +2 -17
- package/dist/open-sse/handlers/imageProviders/index.js +3 -4
- package/dist/open-sse/handlers/imageProviders/leonardo.js +1 -1
- package/dist/open-sse/handlers/imageProviders/nanobanana.js +4 -23
- package/dist/open-sse/handlers/imageProviders/openai.js +15 -43
- package/dist/open-sse/handlers/imageProviders/runwayml.js +2 -26
- package/dist/open-sse/handlers/imageProviders/sdwebui.js +4 -20
- package/dist/open-sse/handlers/imageProviders/stabilityAi.js +2 -26
- package/dist/open-sse/handlers/imageProviders/weavy.js +1 -1
- package/dist/open-sse/handlers/search/chatSearch.js +60 -14
- package/dist/open-sse/handlers/ttsProviders/gemini.js +14 -3
- package/dist/open-sse/handlers/ttsProviders/index.js +4 -2
- package/dist/open-sse/handlers/ttsProviders/openai.js +4 -1
- package/dist/open-sse/handlers/ttsProviders/openrouter.js +7 -4
- package/dist/open-sse/handlers/videoCore.js +166 -0
- package/dist/open-sse/handlers/videoProviders/weavy.js +1 -1
- package/dist/open-sse/mcp-server/catalog.js +1 -1
- package/dist/open-sse/mcp-server/server.js +2 -2
- package/dist/open-sse/mcp-server/tools/advancedTools.js +2 -2
- package/dist/open-sse/mcp-server/tools/agentSkillTools.js +1 -1
- package/dist/open-sse/mcp-server/tools/compressionTools.js +4 -4
- package/dist/open-sse/mcp-server/tools/gamificationTools.js +10 -10
- package/dist/open-sse/mcp-server/tools/githubSkillTools.js +1 -1
- package/dist/open-sse/mcp-server/tools/memoryTools.js +3 -3
- package/dist/open-sse/mcp-server/tools/notionTools.js +2 -2
- package/dist/open-sse/mcp-server/tools/obsidianTools.js +2 -2
- package/dist/open-sse/mcp-server/tools/pickFastestModel.js +1 -1
- package/dist/open-sse/mcp-server/tools/pluginTools.js +4 -4
- package/dist/open-sse/mcp-server/tools/skillTools.js +2 -2
- package/dist/open-sse/providers/capabilities.js +24 -4
- package/dist/open-sse/providers/registry/alicode-intl.js +1 -1
- package/dist/open-sse/providers/registry/anthropic.js +1 -8
- package/dist/open-sse/providers/registry/codex.js +0 -9
- package/dist/open-sse/providers/registry/cohere.js +0 -2
- package/dist/open-sse/providers/registry/gemini.js +0 -2
- package/dist/open-sse/providers/registry/github.js +9 -6
- package/dist/open-sse/providers/registry/grok-cli.js +28 -18
- package/dist/open-sse/providers/registry/index.js +74 -80
- package/dist/open-sse/providers/registry/kiro.js +12 -0
- package/dist/open-sse/providers/registry/mistral.js +0 -3
- package/dist/open-sse/providers/registry/openai.js +0 -3
- package/dist/open-sse/providers/registry/perplexity.js +0 -2
- package/dist/open-sse/providers/registry/xai.js +5 -3
- package/dist/open-sse/rtk/autodetect.js +10 -2
- package/dist/open-sse/rtk/caveman.js +2 -93
- package/dist/open-sse/rtk/cavemanPrompts.js +34 -2
- package/dist/open-sse/rtk/constants.js +7 -2
- package/dist/open-sse/rtk/headroom.js +133 -0
- package/dist/open-sse/rtk/ponytail.js +1 -1
- package/dist/open-sse/rtk/registry.js +2 -0
- package/dist/open-sse/services/accountFallback.js +0 -108
- package/dist/open-sse/services/combo/quotaExhaustionCutoff.js +2 -2
- package/dist/open-sse/services/combo/quotaShareStrategy.js +1 -1
- package/dist/open-sse/services/combo/resolveAutoStrategy.js +1 -1
- package/dist/open-sse/services/combo/sessionStickiness.js +1 -1
- package/dist/open-sse/services/combo/targetSorters.js +2 -2
- package/dist/open-sse/services/combo/validateQuality.js +1 -1
- package/dist/open-sse/services/comboConfig.js +1 -1
- package/dist/open-sse/services/emergencyFallback.js +1 -1
- package/dist/open-sse/services/grokCliModels.js +127 -0
- package/dist/open-sse/services/model.js +7 -1
- package/dist/open-sse/services/provider.js +1 -1
- package/dist/open-sse/services/proxyAutoSelector.js +1 -1
- package/dist/open-sse/services/tokenRefresh/providers.js +3 -3
- package/dist/open-sse/services/usage/codex.js +148 -214
- package/dist/open-sse/services/usage/grok-cli.js +61 -7
- package/dist/open-sse/services/usage/misc.js +0 -19
- package/dist/open-sse/services/usage.js +0 -2
- package/dist/open-sse/translator/concerns/paramSupport.js +2 -2
- package/dist/open-sse/translator/concerns/thinkingUnified.js +6 -0
- package/dist/open-sse/translator/index.js +97 -59
- package/dist/open-sse/translator/request/claude-to-kiro.js +67 -40
- package/dist/open-sse/translator/request/openai-responses.js +1 -0
- package/dist/open-sse/translator/request/openai-to-commandcode.js +0 -4
- package/dist/open-sse/translator/request/openai-to-kiro.js +49 -20
- package/dist/open-sse/translator/response/commandcode-to-openai.js +0 -4
- package/dist/open-sse/utils/bypassHandler.js +18 -3
- package/dist/open-sse/utils/claudeCloaking.js +15 -5
- package/dist/open-sse/utils/cursorImages.js +1 -1
- package/dist/open-sse/utils/error.js +0 -17
- package/dist/open-sse/utils/keepaliveThreshold.js +4 -4
- package/dist/open-sse/utils/kiroSessionReplay.js +125 -0
- package/dist/open-sse/utils/noThinkingAlias.js +1 -1
- package/dist/open-sse/utils/proxyFetch.js +0 -1
- package/dist/open-sse/utils/reasoningContentInjector.js +4 -7
- package/dist/open-sse/utils/responsesStatePolicy.js +1 -1
- package/dist/open-sse/utils/responsesStreamHelpers.js +1 -0
- package/dist/open-sse/utils/sessionManager.js +49 -22
- package/dist/open-sse/utils/stream.js +54 -77
- package/dist/open-sse/utils/streamHandler.js +19 -15
- package/dist/open-sse/utils/streamHelpers.js +2 -17
- package/dist/open-sse/utils/usageTracking.js +103 -12
- package/dist/routes/headroom/extras/route.js +58 -0
- package/dist/routes/headroom/restart/route.js +33 -0
- package/open-sse/config/appConstants.js +23 -79
- package/open-sse/config/errorConfig.js +0 -11
- package/open-sse/config/grokCli.js +10 -0
- package/open-sse/config/kiroConstants.js +99 -46
- package/open-sse/config/runtimeConfig.js +2 -0
- package/open-sse/config/ttsModels.js +2 -0
- package/open-sse/executors/antigravity.js +250 -164
- package/open-sse/executors/base.js +16 -11
- package/open-sse/executors/codex.js +269 -1108
- package/open-sse/executors/commandcode.js +10 -4
- package/open-sse/executors/cursor.js +96 -203
- package/open-sse/executors/default.js +146 -244
- package/open-sse/executors/github.js +128 -73
- package/open-sse/executors/grok-cli.js +527 -94
- package/open-sse/executors/grok-web.js +5 -7
- package/open-sse/executors/index.js +12 -0
- package/open-sse/executors/kiro.js +150 -61
- package/open-sse/executors/opencode-go.js +12 -4
- package/open-sse/executors/opencode.js +1 -1
- package/open-sse/executors/perplexity-web.js +20 -96
- package/open-sse/executors/qoder.js +28 -18
- package/open-sse/executors/vertex.js +53 -7
- package/open-sse/executors/xiaomi-tokenplan.js +6 -5
- package/open-sse/handlers/chatCore/nonStreamingHandler.js +97 -85
- package/open-sse/handlers/chatCore/requestDetail.js +32 -8
- package/open-sse/handlers/chatCore/sseToJsonHandler.js +13 -7
- package/open-sse/handlers/chatCore/streamingHandler.js +74 -25
- package/open-sse/handlers/chatCore.js +35 -41
- package/open-sse/handlers/embeddingProviders/index.js +1 -0
- package/open-sse/handlers/embeddingProviders/openai.js +8 -16
- package/open-sse/handlers/imageProviders/blackForestLabs.js +2 -21
- package/open-sse/handlers/imageProviders/cloudflareAi.js +2 -30
- package/open-sse/handlers/imageProviders/codex.js +2 -20
- package/open-sse/handlers/imageProviders/comfyui.js +5 -18
- package/open-sse/handlers/imageProviders/falAi.js +2 -22
- package/open-sse/handlers/imageProviders/gemini.js +2 -16
- package/open-sse/handlers/imageProviders/huggingface.js +2 -17
- package/open-sse/handlers/imageProviders/index.js +3 -4
- package/open-sse/handlers/imageProviders/leonardo.js +1 -1
- package/open-sse/handlers/imageProviders/nanobanana.js +4 -23
- package/open-sse/handlers/imageProviders/openai.js +15 -43
- package/open-sse/handlers/imageProviders/runwayml.js +2 -26
- package/open-sse/handlers/imageProviders/sdwebui.js +4 -20
- package/open-sse/handlers/imageProviders/stabilityAi.js +2 -26
- package/open-sse/handlers/imageProviders/weavy.js +1 -1
- package/open-sse/handlers/search/chatSearch.js +60 -14
- package/open-sse/handlers/ttsProviders/gemini.js +14 -3
- package/open-sse/handlers/ttsProviders/index.js +4 -2
- package/open-sse/handlers/ttsProviders/openai.js +4 -1
- package/open-sse/handlers/ttsProviders/openrouter.js +7 -4
- package/open-sse/handlers/videoCore.js +166 -0
- package/open-sse/handlers/videoProviders/weavy.js +1 -1
- package/open-sse/mcp-server/audit.js +1 -1
- package/open-sse/mcp-server/catalog.js +2 -2
- package/open-sse/mcp-server/descriptionCompressor.js +1 -1
- package/open-sse/mcp-server/mcpCallerIdentity.js +1 -1
- package/open-sse/mcp-server/schemas/tools.js +1 -1
- package/open-sse/mcp-server/server.js +4 -4
- package/open-sse/mcp-server/tools/advancedTools.js +5 -5
- package/open-sse/mcp-server/tools/agentSkillTools.js +1 -1
- package/open-sse/mcp-server/tools/compressionTools.js +4 -4
- package/open-sse/mcp-server/tools/gamificationTools.js +10 -10
- package/open-sse/mcp-server/tools/githubSkillTools.js +1 -1
- package/open-sse/mcp-server/tools/memoryTools.js +3 -3
- package/open-sse/mcp-server/tools/notionTools.js +2 -2
- package/open-sse/mcp-server/tools/obsidianTools.js +2 -2
- package/open-sse/mcp-server/tools/pickFastestModel.js +3 -3
- package/open-sse/mcp-server/tools/pluginTools.js +4 -4
- package/open-sse/mcp-server/tools/skillTools.js +2 -2
- package/open-sse/providers/capabilities.js +24 -4
- package/open-sse/providers/registry/alicode-intl.js +1 -1
- package/open-sse/providers/registry/anthropic.js +1 -8
- package/open-sse/providers/registry/codex.js +0 -9
- package/open-sse/providers/registry/cohere.js +0 -2
- package/open-sse/providers/registry/gemini.js +0 -2
- package/open-sse/providers/registry/github.js +9 -6
- package/open-sse/providers/registry/grok-cli.js +28 -18
- package/open-sse/providers/registry/index.js +74 -80
- package/open-sse/providers/registry/kiro.js +12 -0
- package/open-sse/providers/registry/mistral.js +0 -3
- package/open-sse/providers/registry/openai.js +0 -3
- package/open-sse/providers/registry/perplexity.js +0 -2
- package/open-sse/providers/registry/xai.js +5 -3
- package/open-sse/rtk/autodetect.js +10 -2
- package/open-sse/rtk/caveman.js +2 -93
- package/open-sse/rtk/cavemanPrompts.js +34 -2
- package/open-sse/rtk/constants.js +7 -2
- package/open-sse/rtk/headroom.js +133 -0
- package/open-sse/rtk/ponytail.js +1 -1
- package/open-sse/rtk/registry.js +2 -0
- package/open-sse/services/accountFallback.js +0 -108
- package/open-sse/services/combo/quotaExhaustionCutoff.js +2 -2
- package/open-sse/services/combo/quotaShareStrategy.js +1 -1
- package/open-sse/services/combo/resolveAutoStrategy.js +1 -1
- package/open-sse/services/combo/sessionStickiness.js +1 -1
- package/open-sse/services/combo/shadowRouting.js +1 -1
- package/open-sse/services/combo/targetSorters.js +4 -4
- package/open-sse/services/combo/validateQuality.js +1 -1
- package/open-sse/services/evalRouting.js +1 -1
- package/open-sse/services/grokCliModels.js +127 -0
- package/open-sse/services/model.js +7 -1
- package/open-sse/services/modelCapabilities.js +1 -1
- package/open-sse/services/modelFamilyFallback.js +1 -1
- package/open-sse/services/provider.js +1 -1
- package/open-sse/services/providerCooldownTracker.js +1 -1
- package/open-sse/services/rateLimitManager.js +1 -1
- package/open-sse/services/tokenRefresh/providers.js +3 -3
- package/open-sse/services/usage/codex.js +148 -214
- package/open-sse/services/usage/grok-cli.js +61 -7
- package/open-sse/services/usage/misc.js +0 -19
- package/open-sse/services/usage.js +0 -2
- package/open-sse/translator/concerns/paramSupport.js +2 -2
- package/open-sse/translator/concerns/thinkingUnified.js +6 -0
- package/open-sse/translator/index.js +97 -59
- package/open-sse/translator/request/claude-to-kiro.js +67 -40
- package/open-sse/translator/request/openai-responses.js +1 -0
- package/open-sse/translator/request/openai-to-commandcode.js +0 -4
- package/open-sse/translator/request/openai-to-kiro.js +49 -20
- package/open-sse/translator/response/commandcode-to-openai.js +0 -4
- package/open-sse/utils/bypassHandler.js +18 -3
- package/open-sse/utils/claudeCloaking.js +15 -5
- package/open-sse/utils/error.js +0 -17
- package/open-sse/utils/kiroSessionReplay.js +125 -0
- package/open-sse/utils/logger.js +1 -1
- package/open-sse/utils/proxyFetch.js +0 -1
- package/open-sse/utils/reasoningContentInjector.js +4 -7
- package/open-sse/utils/responsesStreamHelpers.js +1 -0
- package/open-sse/utils/sessionManager.js +49 -22
- package/open-sse/utils/stream.js +54 -77
- package/open-sse/utils/streamHandler.js +19 -15
- package/open-sse/utils/streamHelpers.js +2 -17
- package/open-sse/utils/usageTracking.js +103 -12
- package/package.json +4 -7
- package/public/assets/EndpointPageClient.C2WMTYy0.js +6 -0
- package/public/assets/{Loading.Bj-WGl4k.js → Loading.BHPtQ9vj.js} +1 -1
- package/public/assets/{NoAuthProxyCard.qAv57b-0.js → NoAuthProxyCard.BDcXaWvM.js} +1 -1
- package/public/assets/index.Be3gbrBl.js +89 -0
- package/public/assets/index.COMgQZYj.css +1 -0
- package/public/assets/{page.CbkENBd5.js → page.-lpNgYAw.js} +1 -1
- package/public/assets/{page.CssmrzTT.js → page.11hpNKmq.js} +1 -1
- package/public/assets/{page.C72FTTJr.js → page.B-LxsnqU.js} +1 -1
- package/public/assets/{page.sOFOrxqq.js → page.B-dzeIUC.js} +1 -1
- package/public/assets/{page.CsxWmPoI.js → page.B-nBR75u.js} +1 -1
- package/public/assets/{page.Dx_GRRdT.js → page.B3QqvLep.js} +1 -1
- package/public/assets/{page.DPyOkPVo.js → page.B8xdkCWA.js} +1 -1
- package/public/assets/{page.DUI8kqOY.js → page.BFb7yUd8.js} +1 -1
- package/public/assets/page.BbPPdoas.js +1 -0
- package/public/assets/page.BdS20a1O.js +1 -0
- package/public/assets/{page.DibhF7f-.js → page.BfmI9KYe.js} +1 -1
- package/public/assets/{page.DX4Nno6M.js → page.BgGJovOg.js} +1 -1
- package/public/assets/{page.BnmTC5jG.js → page.C0gBvR4O.js} +1 -1
- package/public/assets/{page.D5gj98Oe.js → page.C6bYizL7.js} +1 -1
- package/public/assets/{page.vla5Mzki.js → page.C8sLEMa6.js} +1 -1
- package/public/assets/{page.CXd_R9yU.js → page.CCNsZBXp.js} +1 -1
- package/public/assets/{page.CQlVGoXg.js → page.CF_YSLwP.js} +1 -1
- package/public/assets/{page.BbO1pspY.js → page.CPTtRDxw.js} +1 -1
- package/public/assets/{page.D1oKew1j.js → page.CdMmlUEm.js} +1 -1
- package/public/assets/{page.DxMDTbSx.js → page.Cged1bOZ.js} +1 -1
- package/public/assets/{page.Cj5h09Zo.js → page.Ch647dVk.js} +1 -1
- package/public/assets/{page.DVIHRbxB.js → page.CpvXDkQF.js} +1 -1
- package/public/assets/{page.i4KDuWcM.js → page.CrBl7f8N.js} +1 -1
- package/public/assets/{page.BSLJ4tx5.js → page.CrP7niA2.js} +1 -1
- package/public/assets/{page.CnTop8Zt.js → page.CvUFZzXr.js} +1 -1
- package/public/assets/{page.O2ddJYoT.js → page.CyUqJPmx.js} +1 -1
- package/public/assets/{page.DBhu4Arl.js → page.D8Rp8fFR.js} +1 -1
- package/public/assets/{page.CPZav1_c.js → page.Df9qtrdG.js} +1 -1
- package/public/assets/{page.Qkkv8roc.js → page.DiL4Gwqe.js} +1 -1
- package/public/assets/{page.BdmJ3yY3.js → page.Dl1apZE2.js} +1 -1
- package/public/assets/{page.1qjqvrwX.js → page.HV0w1d5C.js} +1 -1
- package/public/assets/{page.ChX1NqmC.js → page.N1x4YL8_.js} +1 -1
- package/public/assets/{page.Dh5f0XJC.js → page.P2Ny5veR.js} +1 -1
- package/public/assets/{page.CSs3-gdt.js → page.fOOCr18J.js} +1 -1
- package/public/assets/{page.Ir7KvKcF.js → page.sUIPWIiF.js} +1 -1
- package/public/assets/{page.CzlQTyAL.js → page.tE7PpWYW.js} +1 -1
- package/public/assets/{page.DzZLqI5Q.js → page.uziaGZsT.js} +1 -1
- package/public/index.html +2 -2
- package/public/assets/EndpointPageClient.LyNNvZ4z.js +0 -6
- package/public/assets/index.BuPfZebu.css +0 -1
- package/public/assets/index.CShjRV_B.js +0 -89
- package/public/assets/page.DD_czjjP.js +0 -1
|
@@ -4,9 +4,13 @@ import { OAUTH_ENDPOINTS, GITHUB_COPILOT } from "../config/appConstants.js";
|
|
|
4
4
|
import { HTTP_STATUS } from "../config/runtimeConfig.js";
|
|
5
5
|
import { openaiToOpenAIResponsesRequest } from "../translator/request/openai-responses.js";
|
|
6
6
|
import { openaiResponsesToOpenAIResponse } from "../translator/response/openai-responses.js";
|
|
7
|
-
import { initState } from "../translator/index.js";
|
|
7
|
+
import { initState, translateRequest, translateResponse } from "../translator/index.js";
|
|
8
|
+
import { FORMATS } from "../translator/formats.js";
|
|
8
9
|
import { parseSSELine, formatSSE } from "../utils/streamHelpers.js";
|
|
9
10
|
import { proxyAwareFetch } from "../utils/proxyFetch.js";
|
|
11
|
+
import { stripUnsupportedParams } from "../translator/concerns/paramSupport.js";
|
|
12
|
+
import { SSE_DONE } from "../utils/sseConstants.js";
|
|
13
|
+
import { ANTHROPIC_API_VERSION } from "../providers/shared.js";
|
|
10
14
|
import crypto from "crypto";
|
|
11
15
|
|
|
12
16
|
export class GithubExecutor extends BaseExecutor {
|
|
@@ -15,6 +19,16 @@ export class GithubExecutor extends BaseExecutor {
|
|
|
15
19
|
this.knownCodexModels = new Set();
|
|
16
20
|
}
|
|
17
21
|
|
|
22
|
+
// Claude models get routed to Copilot's Anthropic-native /v1/messages shim (see
|
|
23
|
+
// executeWithMessagesEndpoint below) — the only Copilot endpoint that surfaces
|
|
24
|
+
// prompt-cache token counts. gpt/gemini/grok models stay on /chat/completions
|
|
25
|
+
// (or /responses). Name-pattern check, not a registry field: Copilot's live model
|
|
26
|
+
// catalog (services/copilotModels.js) regularly exposes claude-* variants ahead
|
|
27
|
+
// of the static registry (registry/github.js).
|
|
28
|
+
isClaudeModel(model) {
|
|
29
|
+
return /claude/i.test(model || "");
|
|
30
|
+
}
|
|
31
|
+
|
|
18
32
|
buildUrl(model, stream, urlIndex = 0) {
|
|
19
33
|
return this.config.baseUrl;
|
|
20
34
|
}
|
|
@@ -33,47 +47,20 @@ export class GithubExecutor extends BaseExecutor {
|
|
|
33
47
|
"x-request-id": crypto.randomUUID?.() || `${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
34
48
|
"x-vscode-user-agent-library-version": "electron-fetch",
|
|
35
49
|
"X-Initiator": "user",
|
|
50
|
+
// Harmless no-op on /chat/completions and /responses; required by /v1/messages.
|
|
51
|
+
"anthropic-version": ANTHROPIC_API_VERSION,
|
|
36
52
|
"Accept": stream ? "text/event-stream" : "application/json"
|
|
37
53
|
};
|
|
38
54
|
}
|
|
39
55
|
|
|
40
|
-
// Sanitize messages for GitHub Copilot /chat/completions endpoint
|
|
56
|
+
// Sanitize messages for GitHub Copilot /chat/completions endpoint (gpt/gemini/grok models —
|
|
57
|
+
// claude models never reach this, see execute() below).
|
|
41
58
|
// The endpoint only accepts 'text' and 'image_url' content part types.
|
|
42
59
|
// Tool-related content (tool_use, tool_result, thinking) must be serialized as text.
|
|
43
60
|
sanitizeMessagesForChatCompletions(body) {
|
|
44
61
|
if (!body?.messages) return body;
|
|
45
62
|
|
|
46
63
|
const sanitized = { ...body };
|
|
47
|
-
|
|
48
|
-
// Handle response_format for Claude models via GitHub
|
|
49
|
-
// GitHub's internal translation doesn't respect response_format, so we inject it as a system prompt
|
|
50
|
-
// AND prepend a reminder to the last user message for maximum effectiveness
|
|
51
|
-
if (body.response_format && body.model?.includes('claude')) {
|
|
52
|
-
const responseFormat = body.response_format;
|
|
53
|
-
let systemInstruction = '';
|
|
54
|
-
if (responseFormat.type === 'json_schema' && responseFormat.json_schema?.schema) {
|
|
55
|
-
systemInstruction = 'CRITICAL: You must ONLY output raw JSON. Never use markdown code blocks. Never use backticks. Never wrap JSON in triple backticks. Output ONLY the raw JSON object.';
|
|
56
|
-
} else if (responseFormat.type === 'json_object') {
|
|
57
|
-
systemInstruction = 'CRITICAL: You must ONLY output raw JSON. Never use markdown code blocks. Never use backticks.';
|
|
58
|
-
}
|
|
59
|
-
if (systemInstruction) {
|
|
60
|
-
// Add to system message
|
|
61
|
-
const systemIdx = body.messages.findIndex(m => m.role === 'system');
|
|
62
|
-
if (systemIdx >= 0) {
|
|
63
|
-
body.messages[systemIdx].content = systemInstruction + '\n\n' + body.messages[systemIdx].content;
|
|
64
|
-
} else {
|
|
65
|
-
body.messages.unshift({ role: 'system', content: systemInstruction });
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Also prepend to the last user message as a reminder
|
|
69
|
-
const lastUserIdx = body.messages.map((m, i) => m.role === 'user' ? i : -1).filter(i => i >= 0).pop();
|
|
70
|
-
if (lastUserIdx >= 0) {
|
|
71
|
-
const userMsg = body.messages[lastUserIdx];
|
|
72
|
-
const userContent = typeof userMsg.content === 'string' ? userMsg.content : JSON.stringify(userMsg.content);
|
|
73
|
-
userMsg.content = 'Respond with ONLY raw JSON (no markdown, no backticks, no code blocks): ' + userContent;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
64
|
sanitized.messages = body.messages.map(msg => {
|
|
78
65
|
// assistant messages with only tool_calls have content: null — leave as-is
|
|
79
66
|
if (!msg.content) return msg;
|
|
@@ -108,54 +95,18 @@ export class GithubExecutor extends BaseExecutor {
|
|
|
108
95
|
return /gpt-5|o[134]-/i.test(model);
|
|
109
96
|
}
|
|
110
97
|
|
|
111
|
-
// Some models (like gpt-5.4) don't support the temperature parameter
|
|
112
|
-
supportsTemperature(model) {
|
|
113
|
-
// gpt-5.4 and similar newer models don't support temperature
|
|
114
|
-
return !/gpt-5\.4/i.test(model);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// GitHub Copilot /chat/completions rejects Claude-style thinking payloads
|
|
118
|
-
// (OpenClaw sends thinking: { type: "enabled" } → upstream 400).
|
|
119
|
-
// GPT-5 family on Copilot DOES honor reasoning_effort, so only strip for Claude. (#713)
|
|
120
|
-
supportsThinking(model) {
|
|
121
|
-
return !/claude/i.test(model);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// reasoning_effort works for GPT-5 family AND Claude Opus 4.6 / Sonnet 4.6
|
|
125
|
-
// on GitHub Copilot. Only strip for models that don't support it:
|
|
126
|
-
// Claude Haiku 4.5, Claude Opus 4.7 (rejected upstream).
|
|
127
|
-
supportsReasoningEffort(model) {
|
|
128
|
-
const m = model.toLowerCase();
|
|
129
|
-
// Claude models that DO support reasoning_effort
|
|
130
|
-
if (/claude.*opus.*4\.6/i.test(m) || /claude.*sonnet.*4\.6/i.test(m)) return true;
|
|
131
|
-
// All other Claude models: strip
|
|
132
|
-
if (/claude/i.test(model)) return false;
|
|
133
|
-
// GPT-5 family, Gemini, etc.: keep
|
|
134
|
-
return true;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
98
|
transformRequest(model, body, stream, credentials) {
|
|
138
99
|
const transformed = { ...body };
|
|
139
100
|
if (this.requiresMaxCompletionTokens(model) && transformed.max_tokens !== undefined) {
|
|
140
101
|
transformed.max_completion_tokens = transformed.max_tokens;
|
|
141
102
|
delete transformed.max_tokens;
|
|
142
103
|
}
|
|
143
|
-
// Strip temperature for models that don't support it
|
|
144
|
-
if (!this.supportsTemperature(model) && transformed.temperature !== undefined) {
|
|
145
|
-
delete transformed.temperature;
|
|
146
|
-
}
|
|
147
|
-
// Always strip Claude-style thinking payload (Copilot doesn't understand it)
|
|
148
|
-
if (!this.supportsThinking(model)) {
|
|
149
|
-
delete transformed.thinking;
|
|
150
|
-
}
|
|
151
104
|
// "none" means no thinking — strip it so models that don't support "none" don't 400
|
|
152
105
|
if (transformed.reasoning_effort === "none") {
|
|
153
106
|
delete transformed.reasoning_effort;
|
|
154
107
|
}
|
|
155
|
-
//
|
|
156
|
-
|
|
157
|
-
delete transformed.reasoning_effort;
|
|
158
|
-
}
|
|
108
|
+
// Config-driven strip of params unsupported by this provider/model
|
|
109
|
+
stripUnsupportedParams("github", model, transformed);
|
|
159
110
|
return transformed;
|
|
160
111
|
}
|
|
161
112
|
|
|
@@ -172,6 +123,15 @@ export class GithubExecutor extends BaseExecutor {
|
|
|
172
123
|
async execute(options) {
|
|
173
124
|
const { model, log } = options;
|
|
174
125
|
|
|
126
|
+
// Claude models: route to Copilot's Anthropic-native /v1/messages shim — the only
|
|
127
|
+
// Copilot endpoint that surfaces prompt-cache token counts for Claude. Detected by
|
|
128
|
+
// model NAME (not a registry field): Copilot's live model catalog regularly exposes
|
|
129
|
+
// claude-* variants the static registry hasn't caught up with yet (see registry/github.js).
|
|
130
|
+
if (this.isClaudeModel(model)) {
|
|
131
|
+
log?.debug("GITHUB", `Using /v1/messages route for ${model}`);
|
|
132
|
+
return this.executeWithMessagesEndpoint(options);
|
|
133
|
+
}
|
|
134
|
+
|
|
175
135
|
// Only use /responses for models that are explicitly known to need it (e.g. gpt codex models)
|
|
176
136
|
// and that the /responses endpoint actually serves (excludes Gemini/Claude, see #1062).
|
|
177
137
|
if (this.knownCodexModels.has(model) && this.supportsResponsesEndpoint(model)) {
|
|
@@ -179,8 +139,8 @@ export class GithubExecutor extends BaseExecutor {
|
|
|
179
139
|
return this.executeWithResponsesEndpoint(options);
|
|
180
140
|
}
|
|
181
141
|
|
|
182
|
-
// Sanitize messages before sending to /chat/completions
|
|
183
|
-
//
|
|
142
|
+
// Sanitize messages before sending to /chat/completions (gpt/gemini/grok — the
|
|
143
|
+
// endpoint rejects non-text/image_url content parts).
|
|
184
144
|
const sanitizedOptions = {
|
|
185
145
|
...options,
|
|
186
146
|
body: this.sanitizeMessagesForChatCompletions(options.body)
|
|
@@ -244,7 +204,7 @@ export class GithubExecutor extends BaseExecutor {
|
|
|
244
204
|
if (!parsed) continue;
|
|
245
205
|
|
|
246
206
|
if (parsed.done && stream === true) {
|
|
247
|
-
controller.enqueue(new TextEncoder().encode(
|
|
207
|
+
controller.enqueue(new TextEncoder().encode(SSE_DONE));
|
|
248
208
|
continue;
|
|
249
209
|
}
|
|
250
210
|
|
|
@@ -285,6 +245,101 @@ export class GithubExecutor extends BaseExecutor {
|
|
|
285
245
|
};
|
|
286
246
|
}
|
|
287
247
|
|
|
248
|
+
// Claude models arrive here OpenAI-shape (chatCore.js targets "openai" for github —
|
|
249
|
+
// see the note in execute() above), so we translate to Anthropic-native ourselves.
|
|
250
|
+
// This is what makes prepareClaudeRequest() (translator/formats/claude.js) inject
|
|
251
|
+
// cache_control — /chat/completions never gets there, so it never sees cache tokens.
|
|
252
|
+
async executeWithMessagesEndpoint({ model, body, stream, credentials, signal, log, proxyOptions = null }) {
|
|
253
|
+
const url = this.config.messagesUrl;
|
|
254
|
+
const headers = this.buildHeaders(credentials, stream);
|
|
255
|
+
|
|
256
|
+
// Force stream:true upstream regardless of client preference, same as
|
|
257
|
+
// executeWithResponsesEndpoint below — chatCore.js's non-streaming handler already
|
|
258
|
+
// knows how to buffer an SSE response into a single JSON reply when the client
|
|
259
|
+
// asked for stream:false.
|
|
260
|
+
const transformedBody = translateRequest(FORMATS.OPENAI, FORMATS.CLAUDE, model, body, true, credentials, "github");
|
|
261
|
+
// _toolNameMap is internal bookkeeping (see openai-to-claude.js) — chatCore.js
|
|
262
|
+
// normally strips it before dispatch and threads it into the response state to
|
|
263
|
+
// restore original tool names; we must do the same here, or Anthropic's strict
|
|
264
|
+
// schema rejects the extra field with a 400.
|
|
265
|
+
const toolNameMap = transformedBody._toolNameMap;
|
|
266
|
+
delete transformedBody._toolNameMap;
|
|
267
|
+
|
|
268
|
+
log?.debug("GITHUB", "Sending translated request to /v1/messages");
|
|
269
|
+
|
|
270
|
+
const response = await proxyAwareFetch(url, {
|
|
271
|
+
method: "POST",
|
|
272
|
+
headers,
|
|
273
|
+
body: JSON.stringify(transformedBody),
|
|
274
|
+
signal
|
|
275
|
+
}, proxyOptions);
|
|
276
|
+
|
|
277
|
+
if (!response.ok) {
|
|
278
|
+
return { response, url, headers, transformedBody };
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const state = initState(FORMATS.CLAUDE);
|
|
282
|
+
state.model = model;
|
|
283
|
+
if (toolNameMap) state.toolNameMap = toolNameMap;
|
|
284
|
+
|
|
285
|
+
const decoder = new TextDecoder();
|
|
286
|
+
let buffer = "";
|
|
287
|
+
|
|
288
|
+
const emitAll = (controller, chunks) => {
|
|
289
|
+
for (const c of chunks) {
|
|
290
|
+
controller.enqueue(new TextEncoder().encode(formatSSE(c, "openai")));
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
const transformStream = new TransformStream({
|
|
295
|
+
async transform(chunk, controller) {
|
|
296
|
+
buffer += decoder.decode(chunk, { stream: true });
|
|
297
|
+
const lines = buffer.split("\n");
|
|
298
|
+
|
|
299
|
+
buffer = lines.pop() || "";
|
|
300
|
+
|
|
301
|
+
for (const line of lines) {
|
|
302
|
+
const trimmed = line.trim();
|
|
303
|
+
if (!trimmed) continue;
|
|
304
|
+
|
|
305
|
+
const parsed = parseSSELine(trimmed);
|
|
306
|
+
if (!parsed) continue;
|
|
307
|
+
|
|
308
|
+
if (parsed.done && stream === true) {
|
|
309
|
+
controller.enqueue(new TextEncoder().encode(SSE_DONE));
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
emitAll(controller, translateResponse(FORMATS.CLAUDE, FORMATS.OPENAI, parsed, state));
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
flush(controller) {
|
|
317
|
+
if (buffer.trim()) {
|
|
318
|
+
const parsed = parseSSELine(buffer.trim());
|
|
319
|
+
if (parsed && !parsed.done) {
|
|
320
|
+
emitAll(controller, translateResponse(FORMATS.CLAUDE, FORMATS.OPENAI, parsed, state));
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
if (!response.body) {
|
|
327
|
+
return { response: new Response("", { status: response.status, headers: response.headers }), url, headers, transformedBody };
|
|
328
|
+
}
|
|
329
|
+
const convertedStream = response.body.pipeThrough(transformStream);
|
|
330
|
+
|
|
331
|
+
return {
|
|
332
|
+
response: new Response(convertedStream, {
|
|
333
|
+
status: response.status,
|
|
334
|
+
statusText: response.statusText,
|
|
335
|
+
headers: response.headers
|
|
336
|
+
}),
|
|
337
|
+
url,
|
|
338
|
+
headers,
|
|
339
|
+
transformedBody
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
|
|
288
343
|
async refreshCopilotToken(githubAccessToken, log, proxyOptions = null) {
|
|
289
344
|
try {
|
|
290
345
|
const response = await proxyAwareFetch("https://api.github.com/copilot_internal/v2/token", {
|