@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
|
@@ -5,14 +5,16 @@
|
|
|
5
5
|
import { register } from "../index.js";
|
|
6
6
|
import { FORMATS } from "../formats.js";
|
|
7
7
|
import { v4 as uuidv4 } from "uuid";
|
|
8
|
-
import {
|
|
8
|
+
import { applyKiroSessionReplay } from "../../utils/kiroSessionReplay.js";
|
|
9
|
+
import { resolveContinuationId, resolveSessionIdentity } from "../../utils/sessionManager.js";
|
|
9
10
|
import {
|
|
10
11
|
resolveKiroModel,
|
|
12
|
+
resolveKiroThinkingBudget,
|
|
11
13
|
buildThinkingSystemPrefix,
|
|
12
14
|
KIRO_AGENTIC_SYSTEM_PROMPT,
|
|
13
15
|
resolveDefaultProfileArn,
|
|
16
|
+
buildKiroAdditionalModelRequestFieldsForModel
|
|
14
17
|
} from "../../config/kiroConstants.js";
|
|
15
|
-
import { resolveKiroThinkingBudget } from "../../services/thinkingBudget.js";
|
|
16
18
|
import { parseDataUri } from "../concerns/image.js";
|
|
17
19
|
import { DEFAULT_IMAGE_MIME } from "../schema/index.js";
|
|
18
20
|
import { ROLE, OPENAI_BLOCK, CLAUDE_BLOCK } from "../schema/index.js";
|
|
@@ -546,47 +548,74 @@ export function openaiToKiroRequest(model, body, stream, credentials) {
|
|
|
546
548
|
? (credentials?.providerSpecificData?.profileArn || "")
|
|
547
549
|
: (credentials?.providerSpecificData?.profileArn || resolveDefaultProfileArn(authMethod));
|
|
548
550
|
|
|
549
|
-
let finalContent = currentMessage?.userInputMessage?.content || "";
|
|
550
|
-
|
|
551
551
|
const timestamp = new Date().toISOString();
|
|
552
552
|
|
|
553
|
-
//
|
|
554
|
-
//
|
|
555
|
-
//
|
|
556
|
-
const
|
|
553
|
+
// Kiro CLI/KAS sends these as top-level systemPrompt. Keep a content fallback
|
|
554
|
+
// too because the CodeWhisperer surface does not always enforce top-level
|
|
555
|
+
// systemPrompt for direct calls.
|
|
556
|
+
const systemPromptParts = [];
|
|
557
557
|
if (thinkingBudget !== null) {
|
|
558
|
-
|
|
558
|
+
systemPromptParts.push(buildThinkingSystemPrefix(thinkingBudget));
|
|
559
559
|
}
|
|
560
|
-
prefixParts.push(`[Context: Current time is ${timestamp}]`);
|
|
561
560
|
if (agentic) {
|
|
562
|
-
|
|
561
|
+
systemPromptParts.push(KIRO_AGENTIC_SYSTEM_PROMPT);
|
|
563
562
|
}
|
|
564
|
-
|
|
563
|
+
const systemPrompt = systemPromptParts.filter(Boolean).join("\n\n");
|
|
564
|
+
const currentTimeContext = `[Context: Current time is ${timestamp}]`;
|
|
565
|
+
const contentPrefix = [systemPrompt, currentTimeContext].filter(Boolean).join("\n\n");
|
|
566
|
+
|
|
567
|
+
const sessionIdentity = resolveSessionIdentity({ headers: credentials?.rawHeaders, body, connectionId: credentials?.connectionId, scope: "kiro" });
|
|
568
|
+
const conversationId = sessionIdentity.sessionId;
|
|
569
|
+
const continuationId = resolveContinuationId({
|
|
570
|
+
sessionId: conversationId,
|
|
571
|
+
connectionId: credentials?.connectionId,
|
|
572
|
+
scope: "kiro",
|
|
573
|
+
ephemeral: sessionIdentity.ephemeral,
|
|
574
|
+
});
|
|
575
|
+
const replay = applyKiroSessionReplay({
|
|
576
|
+
conversationId,
|
|
577
|
+
connectionId: credentials?.connectionId,
|
|
578
|
+
modelId: upstreamModel,
|
|
579
|
+
systemPrompt,
|
|
580
|
+
contentPrefix,
|
|
581
|
+
currentContentPrefix: currentTimeContext,
|
|
582
|
+
history,
|
|
583
|
+
currentMessage,
|
|
584
|
+
});
|
|
585
|
+
const replayCurrent = replay.currentMessage?.userInputMessage || {};
|
|
565
586
|
|
|
566
587
|
const payload = {
|
|
567
588
|
conversationState: {
|
|
568
589
|
chatTriggerType: "MANUAL",
|
|
569
|
-
conversationId
|
|
590
|
+
conversationId,
|
|
591
|
+
agentContinuationId: continuationId,
|
|
592
|
+
agentTaskType: "vibe",
|
|
570
593
|
currentMessage: {
|
|
571
594
|
userInputMessage: {
|
|
572
|
-
content:
|
|
595
|
+
content: replayCurrent.content || "",
|
|
573
596
|
modelId: upstreamModel,
|
|
574
597
|
origin: "AI_EDITOR",
|
|
575
|
-
...(
|
|
576
|
-
images:
|
|
598
|
+
...(replayCurrent.images?.length > 0 && {
|
|
599
|
+
images: replayCurrent.images
|
|
577
600
|
}),
|
|
578
|
-
...(
|
|
579
|
-
userInputMessageContext:
|
|
601
|
+
...(replayCurrent.userInputMessageContext && {
|
|
602
|
+
userInputMessageContext: replayCurrent.userInputMessageContext
|
|
580
603
|
})
|
|
581
604
|
}
|
|
582
605
|
},
|
|
583
|
-
history: history
|
|
584
|
-
}
|
|
606
|
+
history: replay.history
|
|
607
|
+
},
|
|
608
|
+
agentMode: "vibe",
|
|
585
609
|
};
|
|
586
610
|
|
|
587
611
|
if (profileArn) {
|
|
588
612
|
payload.profileArn = profileArn;
|
|
589
613
|
}
|
|
614
|
+
if (systemPrompt) payload.systemPrompt = systemPrompt;
|
|
615
|
+
const additionalModelRequestFields = buildKiroAdditionalModelRequestFieldsForModel(body, upstreamModel);
|
|
616
|
+
if (additionalModelRequestFields) {
|
|
617
|
+
payload.additionalModelRequestFields = additionalModelRequestFields;
|
|
618
|
+
}
|
|
590
619
|
|
|
591
620
|
if (maxTokens || temperature !== undefined || topP !== undefined) {
|
|
592
621
|
payload.inferenceConfig = {};
|
|
@@ -182,7 +182,3 @@ export function commandCodeToOpenAIResponse(chunk, state) {
|
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
register(FORMATS.COMMANDCODE, FORMATS.OPENAI, null, commandCodeToOpenAIResponse);
|
|
185
|
-
|
|
186
|
-
// Backwards-compatible alias (executor expects this name)
|
|
187
|
-
export const convertCommandCodeToOpenAI = commandCodeToOpenAIResponse;
|
|
188
|
-
|
|
@@ -247,9 +247,24 @@ function mergeChunksToResponse(chunks, sourceFormat) {
|
|
|
247
247
|
|
|
248
248
|
if (messageStart?.message) {
|
|
249
249
|
finalChunk = messageStart.message;
|
|
250
|
-
//
|
|
251
|
-
|
|
252
|
-
|
|
250
|
+
// message_start.usage has input + cache; message_delta.usage has the
|
|
251
|
+
// final output_tokens. Merge so cache survives (delta omits it).
|
|
252
|
+
const startUsage = messageStart.message.usage;
|
|
253
|
+
const deltaUsage = messageDelta?.usage;
|
|
254
|
+
if (startUsage || deltaUsage) {
|
|
255
|
+
finalChunk.usage = {
|
|
256
|
+
...(startUsage || {}),
|
|
257
|
+
...(deltaUsage || {}),
|
|
258
|
+
...(startUsage?.cache_read_input_tokens !== undefined
|
|
259
|
+
? { cache_read_input_tokens: startUsage.cache_read_input_tokens }
|
|
260
|
+
: {}),
|
|
261
|
+
...(startUsage?.cache_creation_input_tokens !== undefined
|
|
262
|
+
? { cache_creation_input_tokens: startUsage.cache_creation_input_tokens }
|
|
263
|
+
: {}),
|
|
264
|
+
...(startUsage?.input_tokens !== undefined
|
|
265
|
+
? { input_tokens: startUsage.input_tokens }
|
|
266
|
+
: {})
|
|
267
|
+
};
|
|
253
268
|
}
|
|
254
269
|
}
|
|
255
270
|
}
|
|
@@ -13,11 +13,18 @@ function generateBillingHeader(payload) {
|
|
|
13
13
|
return `x-anthropic-billing-header: cc_version=${CLAUDE_VERSION}.${buildHash}; cc_entrypoint=${CC_ENTRYPOINT}; cch=${cch};`;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
// Derive a deterministic UUID-v4-shaped string from a seed (stable per account)
|
|
17
|
+
function deriveUuid(seed) {
|
|
18
|
+
const h = createHash("sha256").update(seed).digest("hex");
|
|
19
|
+
return `${h.slice(0, 8)}-${h.slice(8, 12)}-4${h.slice(13, 16)}-${((parseInt(h[16], 16) & 0x3) | 0x8).toString(16)}${h.slice(17, 20)}-${h.slice(20, 32)}`;
|
|
20
|
+
}
|
|
21
|
+
|
|
16
22
|
// Generate fake user ID in Claude Code 2.1.92+ JSON format:
|
|
17
23
|
// {"device_id":"<64hex>","account_uuid":"<uuid>","session_id":"<uuid>"}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
24
|
+
// device_id/account_uuid derive from apiKey (stable per account), session_id per-conversation
|
|
25
|
+
function generateFakeUserID(sessionId, apiKey) {
|
|
26
|
+
const deviceId = apiKey ? createHash("sha256").update(`device:${apiKey}`).digest("hex") : randomBytes(32).toString("hex");
|
|
27
|
+
const accountUuid = apiKey ? deriveUuid(`account:${apiKey}`) : randomUUID();
|
|
21
28
|
const sessionUuid = sessionId || randomUUID();
|
|
22
29
|
return `{"device_id":"${deviceId}","account_uuid":"${accountUuid}","session_id":"${sessionUuid}"}`;
|
|
23
30
|
}
|
|
@@ -40,8 +47,11 @@ export function cloakClaudeTools(body) {
|
|
|
40
47
|
const clientToolNames = new Set();
|
|
41
48
|
const clientDeclarations = [];
|
|
42
49
|
|
|
43
|
-
// All client tools get renamed with suffix
|
|
50
|
+
// All client tools get renamed with suffix.
|
|
51
|
+
// Built-in server tools (web_search_20250305, etc.) carry a `type` and require
|
|
52
|
+
// an exact reserved `name` — never suffix those or Claude rejects the request.
|
|
44
53
|
for (const tool of tools) {
|
|
54
|
+
if (tool.type) { clientDeclarations.push(tool); continue; }
|
|
45
55
|
const suffixed = suffix(tool.name);
|
|
46
56
|
toolNameMap.set(suffixed, tool.name);
|
|
47
57
|
clientToolNames.add(tool.name);
|
|
@@ -148,7 +158,7 @@ export function applyCloaking(body, apiKey, sessionId) {
|
|
|
148
158
|
// Inject fake user ID into metadata (session_id must match X-Claude-Code-Session-Id)
|
|
149
159
|
const existingUserId = result.metadata?.user_id;
|
|
150
160
|
if (!existingUserId) {
|
|
151
|
-
result.metadata = { ...result.metadata, user_id: generateFakeUserID(sessionId) };
|
|
161
|
+
result.metadata = { ...result.metadata, user_id: generateFakeUserID(sessionId, apiKey) };
|
|
152
162
|
}
|
|
153
163
|
|
|
154
164
|
return result;
|
package/open-sse/utils/error.js
CHANGED
|
@@ -145,20 +145,3 @@ export function formatProviderError(error, provider, model, statusCode) {
|
|
|
145
145
|
const causeStr = causeCode || causeMsg ? ` (cause: ${[causeCode, causeMsg].filter(Boolean).join(": ")})` : "";
|
|
146
146
|
return `[${code}]: ${message}${causeStr}`;
|
|
147
147
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Safely escape HTML characters from error strings to prevent XSS in clients that poorly render error JSON.
|
|
152
|
-
* Note: Only intended for string values. Non-string inputs will be returned as-is or cast to strings based on usage.
|
|
153
|
-
* @param {string} message The raw error message
|
|
154
|
-
* @returns {string} The HTML-escaped error message
|
|
155
|
-
*/
|
|
156
|
-
export function sanitizeErrorMessage(message) {
|
|
157
|
-
if (typeof message !== 'string') return String(message);
|
|
158
|
-
return message
|
|
159
|
-
.replace(/&/g, '&')
|
|
160
|
-
.replace(/</g, '<')
|
|
161
|
-
.replace(/>/g, '>')
|
|
162
|
-
.replace(/"/g, '"')
|
|
163
|
-
.replace(/'/g, ''');
|
|
164
|
-
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { MEMORY_CONFIG } from "../config/runtimeConfig.js";
|
|
2
|
+
|
|
3
|
+
const sessionStartStore = new Map();
|
|
4
|
+
const MAX_SESSION_STARTS = 5000;
|
|
5
|
+
|
|
6
|
+
function clone(value) {
|
|
7
|
+
return value == null ? value : JSON.parse(JSON.stringify(value));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function sessionKey(connectionId, conversationId) {
|
|
11
|
+
return `${connectionId || ""}:${conversationId || ""}`;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function ensureUserMessageModelId(message, modelId) {
|
|
15
|
+
if (message?.userInputMessage && !message.userInputMessage.modelId && modelId) {
|
|
16
|
+
message.userInputMessage.modelId = modelId;
|
|
17
|
+
}
|
|
18
|
+
return message;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function ensureHistoryModelIds(history, modelId) {
|
|
22
|
+
for (const item of history || []) {
|
|
23
|
+
ensureUserMessageModelId(item, modelId);
|
|
24
|
+
}
|
|
25
|
+
return history;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function prefixUserMessage(message, contentPrefix, modelId) {
|
|
29
|
+
const out = clone(message) || { userInputMessage: { content: "" } };
|
|
30
|
+
if (!out.userInputMessage) out.userInputMessage = { content: "" };
|
|
31
|
+
ensureUserMessageModelId(out, modelId);
|
|
32
|
+
if (contentPrefix) {
|
|
33
|
+
const content = out.userInputMessage.content || "";
|
|
34
|
+
out.userInputMessage.content = content
|
|
35
|
+
? `${contentPrefix}\n\n${content}`
|
|
36
|
+
: contentPrefix;
|
|
37
|
+
}
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function findFirstUserIndex(history) {
|
|
42
|
+
return history.findIndex((item) => item?.userInputMessage);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function rememberSessionStart(key, entry) {
|
|
46
|
+
if (sessionStartStore.size >= MAX_SESSION_STARTS) {
|
|
47
|
+
sessionStartStore.delete(sessionStartStore.keys().next().value);
|
|
48
|
+
}
|
|
49
|
+
sessionStartStore.set(key, { ...entry, lastUsed: Date.now() });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Preserve Kiro cacheability by freezing the first user message (`msg0`) for a
|
|
54
|
+
* session, replaying that exact message as the first history user on later
|
|
55
|
+
* turns, and injecting volatile current-time context only into the current turn.
|
|
56
|
+
*/
|
|
57
|
+
export function applyKiroSessionReplay({
|
|
58
|
+
conversationId,
|
|
59
|
+
connectionId,
|
|
60
|
+
modelId,
|
|
61
|
+
systemPrompt = "",
|
|
62
|
+
contentPrefix = "",
|
|
63
|
+
currentContentPrefix = "",
|
|
64
|
+
history = [],
|
|
65
|
+
currentMessage,
|
|
66
|
+
} = {}) {
|
|
67
|
+
const key = sessionKey(connectionId, conversationId);
|
|
68
|
+
const existing = conversationId ? sessionStartStore.get(key) : null;
|
|
69
|
+
const baseHistory = clone(history) || [];
|
|
70
|
+
const baseCurrent = clone(currentMessage) || { userInputMessage: { content: "" } };
|
|
71
|
+
|
|
72
|
+
if (existing && existing.modelId === modelId && existing.systemPrompt === systemPrompt) {
|
|
73
|
+
existing.lastUsed = Date.now();
|
|
74
|
+
const firstUserIndex = findFirstUserIndex(baseHistory);
|
|
75
|
+
const sessionStart = ensureUserMessageModelId(clone(existing.sessionStart), modelId);
|
|
76
|
+
if (firstUserIndex >= 0) {
|
|
77
|
+
baseHistory[firstUserIndex] = sessionStart;
|
|
78
|
+
} else {
|
|
79
|
+
baseHistory.unshift(sessionStart);
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
history: ensureHistoryModelIds(baseHistory, modelId),
|
|
83
|
+
currentMessage: prefixUserMessage(baseCurrent, currentContentPrefix, modelId),
|
|
84
|
+
replayed: true,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const firstUserIndex = findFirstUserIndex(baseHistory);
|
|
89
|
+
let sessionStart;
|
|
90
|
+
let nextCurrent = ensureUserMessageModelId(baseCurrent, modelId);
|
|
91
|
+
if (firstUserIndex >= 0) {
|
|
92
|
+
sessionStart = prefixUserMessage(baseHistory[firstUserIndex], contentPrefix, modelId);
|
|
93
|
+
baseHistory[firstUserIndex] = clone(sessionStart);
|
|
94
|
+
nextCurrent = prefixUserMessage(baseCurrent, currentContentPrefix, modelId);
|
|
95
|
+
} else {
|
|
96
|
+
sessionStart = prefixUserMessage(baseCurrent, contentPrefix, modelId);
|
|
97
|
+
nextCurrent = clone(sessionStart);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (conversationId) {
|
|
101
|
+
rememberSessionStart(key, {
|
|
102
|
+
sessionStart: clone(sessionStart),
|
|
103
|
+
modelId,
|
|
104
|
+
systemPrompt,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
history: ensureHistoryModelIds(baseHistory, modelId),
|
|
110
|
+
currentMessage: nextCurrent,
|
|
111
|
+
replayed: false,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function clearKiroSessionReplayStore() {
|
|
116
|
+
sessionStartStore.clear();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const cleanup = setInterval(() => {
|
|
120
|
+
const now = Date.now();
|
|
121
|
+
for (const [key, entry] of sessionStartStore) {
|
|
122
|
+
if (now - entry.lastUsed > MEMORY_CONFIG.sessionTtlMs) sessionStartStore.delete(key);
|
|
123
|
+
}
|
|
124
|
+
}, MEMORY_CONFIG.sessionCleanupIntervalMs);
|
|
125
|
+
if (cleanup.unref) cleanup.unref();
|
package/open-sse/utils/logger.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getAppLogFormat, getAppLogLevel } from "../../
|
|
1
|
+
import { getAppLogFormat, getAppLogLevel } from "../../src/lib/logEnv";
|
|
2
2
|
const LEVELS = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
3
3
|
function isLogLevel(value) {
|
|
4
4
|
return Object.prototype.hasOwnProperty.call(LEVELS, value);
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
// Some thinking-mode providers (DeepSeek, Kimi, MiniMax, ...) require reasoning_content
|
|
2
2
|
// to be echoed back on assistant messages. Clients in OpenAI format don't send it,
|
|
3
3
|
// so we inject a non-empty placeholder to satisfy upstream validation.
|
|
4
|
+
import { PROVIDERS } from "../config/providers.js";
|
|
4
5
|
|
|
5
6
|
const PLACEHOLDER = " ";
|
|
6
7
|
|
|
7
|
-
// Provider-level rules
|
|
8
|
-
const
|
|
9
|
-
deepseek: { scope: "all" },
|
|
10
|
-
minimax: { scope: "all" },
|
|
11
|
-
"minimax-cn": { scope: "all" }
|
|
12
|
-
};
|
|
8
|
+
// Provider-level rules derive from registry transport.reasoningInject (single source)
|
|
9
|
+
const providerRuleFor = (provider) => PROVIDERS[provider]?.reasoningInject;
|
|
13
10
|
|
|
14
11
|
// Model-level rules: matched by predicate against model id
|
|
15
12
|
const MODEL_RULES = [
|
|
@@ -71,7 +68,7 @@ function applyDeepSeekV4ProAlias({ provider, model, body }) {
|
|
|
71
68
|
}
|
|
72
69
|
|
|
73
70
|
export function injectReasoningContent({ provider, model, body }) {
|
|
74
|
-
const providerRule =
|
|
71
|
+
const providerRule = providerRuleFor(provider);
|
|
75
72
|
const modelRule = MODEL_RULES.find(r => r.match(model));
|
|
76
73
|
const rule = providerRule || modelRule;
|
|
77
74
|
const nextBody = applyDeepSeekV4ProAlias({ provider, model, body });
|
|
@@ -13,6 +13,7 @@ import { MEMORY_CONFIG } from "../config/runtimeConfig.js";
|
|
|
13
13
|
|
|
14
14
|
// Runtime storage: Key = connectionId, Value = { sessionId, lastUsed }
|
|
15
15
|
const runtimeSessionStore = new Map();
|
|
16
|
+
const continuationStore = new Map();
|
|
16
17
|
|
|
17
18
|
// Periodically evict entries that haven't been used within TTL
|
|
18
19
|
const cleanupInterval = setInterval(() => {
|
|
@@ -80,6 +81,7 @@ export function generateBinaryStyleId() {
|
|
|
80
81
|
export function clearSessionStore() {
|
|
81
82
|
runtimeSessionStore.clear();
|
|
82
83
|
assistantSessionStore.clear();
|
|
84
|
+
continuationStore.clear();
|
|
83
85
|
}
|
|
84
86
|
|
|
85
87
|
// Conversation-stable session store: Key = hash(scope+assistant text), Value = { sessionId, lastUsed }
|
|
@@ -87,9 +89,10 @@ const assistantSessionStore = new Map();
|
|
|
87
89
|
const ASSISTANT_MIN_LEN = 50;
|
|
88
90
|
const ASSISTANT_CAP_LEN = 50;
|
|
89
91
|
const MAX_ASSISTANT_SESSIONS = 5000;
|
|
92
|
+
const MAX_CONTINUATION_SESSIONS = 5000;
|
|
90
93
|
|
|
91
94
|
// Client headers/body fields that carry an upstream session id (priority order)
|
|
92
|
-
const SESSION_HEADER_KEYS = ["x-session-id", "session-id", "session_id", "x-amp-thread-id"
|
|
95
|
+
const SESSION_HEADER_KEYS = ["x-session-id", "session-id", "session_id", "x-amp-thread-id"];
|
|
93
96
|
const CLAUDE_CODE_SESSION_RE = /_session_([a-f0-9-]+)$/;
|
|
94
97
|
|
|
95
98
|
function sha16(text) {
|
|
@@ -131,7 +134,7 @@ function extractAntigravitySession(body) {
|
|
|
131
134
|
return m ? normalizeSessionId(m[1]) : null;
|
|
132
135
|
}
|
|
133
136
|
|
|
134
|
-
function extractClientSessionId(headers, body) {
|
|
137
|
+
function extractClientSessionId(headers, body, scope = "") {
|
|
135
138
|
const claude = extractClaudeCodeSession(body?.metadata?.user_id);
|
|
136
139
|
if (claude) return `claude:${claude}`;
|
|
137
140
|
const antigravity = extractAntigravitySession(body);
|
|
@@ -140,18 +143,25 @@ function extractClientSessionId(headers, body) {
|
|
|
140
143
|
const v = headerValue(headers, key);
|
|
141
144
|
if (v) return v;
|
|
142
145
|
}
|
|
146
|
+
const requestId = scope === "kiro" ? null : headerValue(headers, "x-client-request-id");
|
|
147
|
+
if (requestId) return requestId;
|
|
143
148
|
const fromBody =
|
|
144
149
|
normalizeSessionId(body?.prompt_cache_key) ||
|
|
145
150
|
normalizeSessionId(body?.session_id) ||
|
|
146
151
|
normalizeSessionId(body?.conversation_id) ||
|
|
147
|
-
normalizeSessionId(body?.metadata?.user_id);
|
|
152
|
+
(scope === "kiro" ? null : normalizeSessionId(body?.metadata?.user_id));
|
|
148
153
|
return fromBody || null;
|
|
149
154
|
}
|
|
150
155
|
|
|
156
|
+
function requestMessages(body) {
|
|
157
|
+
if (Array.isArray(body?.messages)) return body.messages;
|
|
158
|
+
if (Array.isArray(body?.input)) return body.input;
|
|
159
|
+
return [];
|
|
160
|
+
}
|
|
161
|
+
|
|
151
162
|
// Accumulate assistant text from OpenAI/Responses-style input/messages (cap-limited)
|
|
152
163
|
function accumulateAssistantText(body) {
|
|
153
|
-
const items =
|
|
154
|
-
: Array.isArray(body?.messages) ? body.messages : null;
|
|
164
|
+
const items = requestMessages(body);
|
|
155
165
|
if (!items) return "";
|
|
156
166
|
let text = "";
|
|
157
167
|
for (const item of items) {
|
|
@@ -193,16 +203,39 @@ function assistantTextSessionId(scope, body) {
|
|
|
193
203
|
* @param {string} [opts.connectionId] - Connection identifier (fallback scope)
|
|
194
204
|
* @param {string} [opts.workspaceId] - Provider workspace id (account-wide fallback)
|
|
195
205
|
* @param {string} [opts.scope] - Provider scope to isolate cache keys across providers
|
|
196
|
-
* @returns {string} A
|
|
206
|
+
* @returns {{sessionId: string, ephemeral: boolean}} A session id plus whether it is one-shot
|
|
197
207
|
*/
|
|
198
|
-
export function
|
|
199
|
-
const client = extractClientSessionId(headers, body);
|
|
200
|
-
if (client) return client;
|
|
201
|
-
const fromAssistant = assistantTextSessionId(`${scope}:${connectionId || ""}`, body);
|
|
202
|
-
if (fromAssistant) return fromAssistant;
|
|
208
|
+
export function resolveSessionIdentity({ headers, body, connectionId, workspaceId, scope = "" } = {}) {
|
|
209
|
+
const client = extractClientSessionId(headers, body, scope);
|
|
210
|
+
if (client) return { sessionId: client, ephemeral: false };
|
|
211
|
+
const fromAssistant = scope === "kiro" ? null : assistantTextSessionId(`${scope}:${connectionId || ""}`, body);
|
|
212
|
+
if (fromAssistant) return { sessionId: fromAssistant, ephemeral: false };
|
|
203
213
|
const ws = normalizeSessionId(workspaceId);
|
|
204
|
-
if (ws) return ws;
|
|
205
|
-
return
|
|
214
|
+
if (ws) return { sessionId: ws, ephemeral: false };
|
|
215
|
+
if (scope === "kiro") return { sessionId: generateBinaryStyleId(), ephemeral: true };
|
|
216
|
+
return { sessionId: deriveSessionId(connectionId), ephemeral: false };
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function resolveSessionId(opts = {}) {
|
|
220
|
+
return resolveSessionIdentity(opts).sessionId;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function resolveContinuationId({ sessionId, connectionId, scope = "", ephemeral = false } = {}) {
|
|
224
|
+
if (ephemeral) return crypto.randomUUID();
|
|
225
|
+
const key = `${scope}:${connectionId || ""}:${sessionId || ""}`;
|
|
226
|
+
const existing = continuationStore.get(key);
|
|
227
|
+
if (existing) {
|
|
228
|
+
existing.lastUsed = Date.now();
|
|
229
|
+
continuationStore.delete(key);
|
|
230
|
+
continuationStore.set(key, existing);
|
|
231
|
+
return existing.continuationId;
|
|
232
|
+
}
|
|
233
|
+
const continuationId = crypto.randomUUID();
|
|
234
|
+
if (continuationStore.size >= MAX_CONTINUATION_SESSIONS) {
|
|
235
|
+
continuationStore.delete(continuationStore.keys().next().value);
|
|
236
|
+
}
|
|
237
|
+
continuationStore.set(key, { continuationId, lastUsed: Date.now() });
|
|
238
|
+
return continuationId;
|
|
206
239
|
}
|
|
207
240
|
|
|
208
241
|
// Capture session id from request body + credentials (envelope still intact here)
|
|
@@ -227,14 +260,8 @@ const assistantCleanup = setInterval(() => {
|
|
|
227
260
|
for (const [key, entry] of assistantSessionStore) {
|
|
228
261
|
if (now - entry.lastUsed > MEMORY_CONFIG.sessionTtlMs) assistantSessionStore.delete(key);
|
|
229
262
|
}
|
|
263
|
+
for (const [key, entry] of continuationStore) {
|
|
264
|
+
if (now - entry.lastUsed > MEMORY_CONFIG.sessionTtlMs) continuationStore.delete(key);
|
|
265
|
+
}
|
|
230
266
|
}, MEMORY_CONFIG.sessionCleanupIntervalMs);
|
|
231
267
|
if (assistantCleanup.unref) assistantCleanup.unref();
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Stub: get session info by session ID.
|
|
235
|
-
* Returns session object if found, null otherwise.
|
|
236
|
-
* TODO: Wire to actual session store when available.
|
|
237
|
-
*/
|
|
238
|
-
export function getSessionInfo(sessionId) {
|
|
239
|
-
return null;
|
|
240
|
-
}
|