@jsonstudio/rcc 0.89.168 → 0.89.524
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/README.md +18 -15
- package/dist/build-info.js +3 -3
- package/dist/build-info.js.map +1 -1
- package/dist/cli.js +94 -0
- package/dist/cli.js.map +1 -1
- package/dist/client/gemini-cli/gemini-cli-protocol-client.js +28 -5
- package/dist/client/gemini-cli/gemini-cli-protocol-client.js.map +1 -1
- package/dist/commands/token-daemon.d.ts +2 -0
- package/dist/commands/token-daemon.js +183 -0
- package/dist/commands/token-daemon.js.map +1 -0
- package/dist/error-handling/quiet-error-handling-center.d.ts +9 -0
- package/dist/error-handling/quiet-error-handling-center.js +141 -0
- package/dist/error-handling/quiet-error-handling-center.js.map +1 -0
- package/dist/error-handling/route-error-hub.js +8 -2
- package/dist/error-handling/route-error-hub.js.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/modules/llmswitch/bridge.d.ts +1 -1
- package/dist/modules/llmswitch/bridge.js +3 -2
- package/dist/modules/llmswitch/bridge.js.map +1 -1
- package/dist/modules/pipeline/utils/colored-logger.d.ts +2 -0
- package/dist/modules/pipeline/utils/colored-logger.js +22 -3
- package/dist/modules/pipeline/utils/colored-logger.js.map +1 -1
- package/dist/providers/auth/antigravity-userinfo-helper.d.ts +10 -0
- package/dist/providers/auth/antigravity-userinfo-helper.js +140 -0
- package/dist/providers/auth/antigravity-userinfo-helper.js.map +1 -0
- package/dist/providers/auth/gemini-cli-userinfo-helper.js +12 -2
- package/dist/providers/auth/gemini-cli-userinfo-helper.js.map +1 -1
- package/dist/providers/auth/oauth-lifecycle.js +395 -24
- package/dist/providers/auth/oauth-lifecycle.js.map +1 -1
- package/dist/providers/auth/token-scanner/index.d.ts +32 -0
- package/dist/providers/auth/token-scanner/index.js +86 -0
- package/dist/providers/auth/token-scanner/index.js.map +1 -0
- package/dist/providers/auth/tokenfile-auth.d.ts +17 -0
- package/dist/providers/auth/tokenfile-auth.js +27 -5
- package/dist/providers/auth/tokenfile-auth.js.map +1 -1
- package/dist/providers/core/api/provider-types.d.ts +10 -0
- package/dist/providers/core/config/oauth-flows.d.ts +25 -0
- package/dist/providers/core/config/oauth-flows.js +92 -5
- package/dist/providers/core/config/oauth-flows.js.map +1 -1
- package/dist/providers/core/config/provider-oauth-configs.js +93 -2
- package/dist/providers/core/config/provider-oauth-configs.js.map +1 -1
- package/dist/providers/core/config/service-profiles.js +18 -10
- package/dist/providers/core/config/service-profiles.js.map +1 -1
- package/dist/providers/core/runtime/base-provider.d.ts +2 -0
- package/dist/providers/core/runtime/base-provider.js +135 -15
- package/dist/providers/core/runtime/base-provider.js.map +1 -1
- package/dist/providers/core/runtime/gemini-cli-http-provider.d.ts +8 -3
- package/dist/providers/core/runtime/gemini-cli-http-provider.js +332 -67
- package/dist/providers/core/runtime/gemini-cli-http-provider.js.map +1 -1
- package/dist/providers/core/runtime/http-request-executor.d.ts +1 -0
- package/dist/providers/core/runtime/http-request-executor.js +41 -1
- package/dist/providers/core/runtime/http-request-executor.js.map +1 -1
- package/dist/providers/core/runtime/http-transport-provider.d.ts +27 -0
- package/dist/providers/core/runtime/http-transport-provider.js +342 -69
- package/dist/providers/core/runtime/http-transport-provider.js.map +1 -1
- package/dist/providers/core/runtime/provider-error-classifier.d.ts +2 -2
- package/dist/providers/core/runtime/provider-error-classifier.js +14 -4
- package/dist/providers/core/runtime/provider-error-classifier.js.map +1 -1
- package/dist/providers/core/runtime/provider-factory.d.ts +1 -0
- package/dist/providers/core/runtime/provider-factory.js +37 -8
- package/dist/providers/core/runtime/provider-factory.js.map +1 -1
- package/dist/providers/core/runtime/responses-provider.d.ts +3 -3
- package/dist/providers/core/runtime/responses-provider.js +56 -117
- package/dist/providers/core/runtime/responses-provider.js.map +1 -1
- package/dist/providers/core/runtime/vision-debug-utils.d.ts +13 -0
- package/dist/providers/core/runtime/vision-debug-utils.js +114 -0
- package/dist/providers/core/runtime/vision-debug-utils.js.map +1 -0
- package/dist/providers/core/strategies/oauth-auth-code-flow.js +82 -25
- package/dist/providers/core/strategies/oauth-auth-code-flow.js.map +1 -1
- package/dist/providers/core/utils/http-client.d.ts +5 -0
- package/dist/providers/core/utils/http-client.js +31 -4
- package/dist/providers/core/utils/http-client.js.map +1 -1
- package/dist/providers/core/utils/provider-error-reporter.js +8 -2
- package/dist/providers/core/utils/provider-error-reporter.js.map +1 -1
- package/dist/providers/core/utils/snapshot-writer.d.ts +1 -1
- package/dist/providers/core/utils/snapshot-writer.js +5 -1
- package/dist/providers/core/utils/snapshot-writer.js.map +1 -1
- package/dist/providers/profile/provider-profile-loader.js +8 -4
- package/dist/providers/profile/provider-profile-loader.js.map +1 -1
- package/dist/runtime/runtime-flags.d.ts +4 -0
- package/dist/runtime/runtime-flags.js +32 -0
- package/dist/runtime/runtime-flags.js.map +1 -0
- package/dist/server/handlers/handler-utils.js +29 -2
- package/dist/server/handlers/handler-utils.js.map +1 -1
- package/dist/server/handlers/messages-handler.js +27 -26
- package/dist/server/handlers/messages-handler.js.map +1 -1
- package/dist/server/handlers/responses-handler.js +35 -1
- package/dist/server/handlers/responses-handler.js.map +1 -1
- package/dist/server/handlers/sse-dispatcher.js +22 -2
- package/dist/server/handlers/sse-dispatcher.js.map +1 -1
- package/dist/server/runtime/http-server/index.d.ts +10 -0
- package/dist/server/runtime/http-server/index.js +551 -148
- package/dist/server/runtime/http-server/index.js.map +1 -1
- package/dist/server/runtime/http-server/request-executor.d.ts +14 -0
- package/dist/server/runtime/http-server/request-executor.js +638 -149
- package/dist/server/runtime/http-server/request-executor.js.map +1 -1
- package/dist/server/runtime/http-server/routes.d.ts +5 -0
- package/dist/server/runtime/http-server/routes.js +69 -0
- package/dist/server/runtime/http-server/routes.js.map +1 -1
- package/dist/server/runtime/http-server/runtime-manager.js +18 -0
- package/dist/server/runtime/http-server/runtime-manager.js.map +1 -1
- package/dist/server/utils/sse-request-parser.d.ts +1 -0
- package/dist/server/utils/sse-request-parser.js +17 -6
- package/dist/server/utils/sse-request-parser.js.map +1 -1
- package/dist/server/utils/utf8-chunk-buffer.d.ts +43 -0
- package/dist/server/utils/utf8-chunk-buffer.js +132 -0
- package/dist/server/utils/utf8-chunk-buffer.js.map +1 -0
- package/dist/server/utils/warmup-detector.d.ts +7 -0
- package/dist/server/utils/warmup-detector.js +125 -0
- package/dist/server/utils/warmup-detector.js.map +1 -0
- package/dist/server/utils/warmup-storm-tracker.d.ts +9 -0
- package/dist/server/utils/warmup-storm-tracker.js +61 -0
- package/dist/server/utils/warmup-storm-tracker.js.map +1 -0
- package/dist/token-daemon/index.d.ts +7 -0
- package/dist/token-daemon/index.js +242 -0
- package/dist/token-daemon/index.js.map +1 -0
- package/dist/token-daemon/server-utils.d.ts +33 -0
- package/dist/token-daemon/server-utils.js +155 -0
- package/dist/token-daemon/server-utils.js.map +1 -0
- package/dist/token-daemon/token-daemon.d.ts +20 -0
- package/dist/token-daemon/token-daemon.js +144 -0
- package/dist/token-daemon/token-daemon.js.map +1 -0
- package/dist/token-daemon/token-types.d.ts +44 -0
- package/dist/token-daemon/token-types.js +18 -0
- package/dist/token-daemon/token-types.js.map +1 -0
- package/dist/token-daemon/token-utils.d.ts +17 -0
- package/dist/token-daemon/token-utils.js +153 -0
- package/dist/token-daemon/token-utils.js.map +1 -0
- package/dist/tools/semantic-replay.js +7 -6
- package/dist/tools/semantic-replay.js.map +1 -1
- package/dist/utils/debug-utils.js +14 -0
- package/dist/utils/debug-utils.js.map +1 -1
- package/dist/utils/error-handler-registry.d.ts +36 -0
- package/dist/utils/error-handler-registry.js +99 -12
- package/dist/utils/error-handler-registry.js.map +1 -1
- package/dist/utils/error-handling-utils.js +4 -3
- package/dist/utils/error-handling-utils.js.map +1 -1
- package/dist/utils/log-helpers.d.ts +6 -0
- package/dist/utils/log-helpers.js +90 -0
- package/dist/utils/log-helpers.js.map +1 -0
- package/dist/utils/logger.d.ts +8 -0
- package/dist/utils/logger.js +55 -2
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/snapshot-writer.js +2 -6
- package/dist/utils/snapshot-writer.js.map +1 -1
- package/node_modules/@jsonstudio/llms/README.md +2 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/codecs/gemini-openai-codec.js +152 -6
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/auto-thinking.d.ts +6 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/auto-thinking.js +25 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/field-mapping.d.ts +14 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/field-mapping.js +155 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/gemini-web-search.d.ts +17 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/gemini-web-search.js +68 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/glm-image-content.d.ts +2 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/glm-image-content.js +83 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/glm-tool-extraction.d.ts +2 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/glm-tool-extraction.js +264 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/glm-vision-prompt.d.ts +11 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/glm-vision-prompt.js +177 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/glm-web-search.d.ts +2 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/glm-web-search.js +63 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/qwen-transform.d.ts +3 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/qwen-transform.js +209 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/request-rules.d.ts +24 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/request-rules.js +63 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/response-blacklist.d.ts +14 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/response-blacklist.js +85 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/response-normalize.d.ts +5 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/response-normalize.js +121 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/response-validate.d.ts +5 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/response-validate.js +76 -0
- package/{dist/providers/compat/utils/snapshot-writer.d.ts → node_modules/@jsonstudio/llms/dist/conversion/compat/actions/snapshot.d.ts} +2 -2
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/snapshot.js +21 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/tool-schema.d.ts +6 -0
- package/{dist/providers/compat/glm/utils/tool-schema-helpers.js → node_modules/@jsonstudio/llms/dist/conversion/compat/actions/tool-schema.js} +6 -1
- package/{dist/providers/compat/filters → node_modules/@jsonstudio/llms/dist/conversion/compat/actions}/universal-shape-filter.d.ts +17 -22
- package/{dist/providers/compat/filters → node_modules/@jsonstudio/llms/dist/conversion/compat/actions}/universal-shape-filter.js +46 -99
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-gemini.json +17 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-glm.json +196 -13
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-iflow.json +194 -26
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-lmstudio.json +43 -35
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-qwen.json +20 -16
- package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/responses-c4m.json +42 -42
- package/node_modules/@jsonstudio/llms/dist/conversion/config/sample-config.json +1 -1
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/compat/compat-engine.d.ts +7 -2
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/compat/compat-engine.js +5 -665
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/compat/compat-pipeline-executor.d.ts +9 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/compat/compat-pipeline-executor.js +869 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/compat/compat-types.d.ts +55 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline.d.ts +2 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline.js +74 -5
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage3_compat/index.js +2 -2
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/target-utils.js +9 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/process/chat-process.js +213 -1
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/response/provider-response.d.ts +34 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/response/provider-response.js +84 -24
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/response/response-runtime.js +19 -2
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/response/server-side-tools.d.ts +26 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/response/server-side-tools.js +383 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/semantic-mappers/gemini-mapper.js +241 -14
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/semantic-mappers/responses-mapper.js +17 -1
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/standardized-bridge.js +14 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/hub/types/standardized.d.ts +1 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/responses/responses-host-policy.d.ts +6 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/responses/responses-host-policy.js +14 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/responses/responses-openai-bridge.js +133 -5
- package/node_modules/@jsonstudio/llms/dist/conversion/shared/anthropic-message-utils.js +98 -3
- package/node_modules/@jsonstudio/llms/dist/conversion/shared/bridge-message-utils.js +137 -10
- package/node_modules/@jsonstudio/llms/dist/conversion/shared/responses-output-builder.js +43 -2
- package/node_modules/@jsonstudio/llms/dist/conversion/shared/responses-reasoning-registry.d.ts +4 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/shared/responses-reasoning-registry.js +62 -1
- package/node_modules/@jsonstudio/llms/dist/conversion/shared/responses-response-utils.js +23 -1
- package/node_modules/@jsonstudio/llms/dist/conversion/shared/snapshot-utils.js +17 -47
- package/node_modules/@jsonstudio/llms/dist/conversion/shared/tool-canonicalizer.d.ts +2 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/shared/tool-filter-pipeline.js +12 -0
- package/node_modules/@jsonstudio/llms/dist/conversion/shared/tool-mapping.js +25 -2
- package/node_modules/@jsonstudio/llms/dist/index.d.ts +1 -0
- package/node_modules/@jsonstudio/llms/dist/index.js +1 -0
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/bootstrap.js +540 -36
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/classifier.js +12 -11
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/context-advisor.d.ts +19 -0
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/context-advisor.js +64 -0
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine.d.ts +26 -0
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine.js +450 -54
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/features.js +23 -458
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/health-manager.js +2 -7
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/message-utils.d.ts +7 -0
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/message-utils.js +78 -0
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/provider-registry.js +7 -2
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/token-counter.js +14 -3
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/token-estimator.d.ts +2 -0
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/token-estimator.js +16 -0
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/token-file-scanner.d.ts +15 -0
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/token-file-scanner.js +56 -0
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/tool-signals.d.ts +13 -0
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/tool-signals.js +403 -0
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/types.d.ts +86 -2
- package/node_modules/@jsonstudio/llms/dist/router/virtual-router/types.js +3 -1
- package/node_modules/@jsonstudio/llms/dist/servertool/engine.d.ts +27 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/engine.js +60 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/flow-types.d.ts +40 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/flow-types.js +1 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/handlers/vision.d.ts +1 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/handlers/vision.js +194 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/handlers/web-search.d.ts +1 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/handlers/web-search.js +638 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/orchestration-types.d.ts +33 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/orchestration-types.js +1 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/registry.d.ts +18 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/registry.js +27 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/server-side-tools.d.ts +8 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/server-side-tools.js +208 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/types.d.ts +88 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/types.js +1 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/vision-tool.d.ts +2 -0
- package/node_modules/@jsonstudio/llms/dist/servertool/vision-tool.js +185 -0
- package/node_modules/@jsonstudio/llms/dist/sse/json-to-sse/event-generators/responses.js +15 -3
- package/node_modules/@jsonstudio/llms/dist/sse/sse-to-json/builders/response-builder.js +6 -3
- package/node_modules/@jsonstudio/llms/dist/sse/sse-to-json/gemini-sse-to-json-converter.js +27 -1
- package/node_modules/@jsonstudio/llms/dist/sse/types/gemini-types.d.ts +20 -1
- package/node_modules/@jsonstudio/llms/dist/sse/types/responses-types.js +1 -1
- package/node_modules/@jsonstudio/llms/dist/telemetry/stats-center.d.ts +73 -0
- package/node_modules/@jsonstudio/llms/dist/telemetry/stats-center.js +280 -0
- package/node_modules/@jsonstudio/llms/package.json +2 -2
- package/package.json +11 -10
- package/scripts/README.md +26 -12
- package/scripts/auth-antigravity-token.mjs +64 -0
- package/scripts/auth-gemini-cli-token.mjs +96 -0
- package/scripts/auth-iflow-manual.mjs +81 -0
- package/scripts/auth-iflow-token-direct.mjs +87 -0
- package/scripts/auth-iflow-token.mjs +77 -0
- package/scripts/copy-compat-assets.mjs +3 -15
- package/scripts/install-verify.mjs +1 -0
- package/scripts/pack-mode.mjs +2 -1
- package/scripts/publish-rcc.mjs +20 -4
- package/scripts/replay-codex-sample.mjs +13 -8
- package/scripts/tests/chat-pipeline-blackbox.mjs +1 -1
- package/scripts/tests/virtual-router-health.mjs +141 -6
- package/scripts/tools/capture-provider-goldens.mjs +8 -7
- package/scripts/verify-client-headers.mjs +224 -0
- package/dist/providers/compat/base-compatibility.d.ts +0 -27
- package/dist/providers/compat/base-compatibility.js +0 -143
- package/dist/providers/compat/base-compatibility.js.map +0 -1
- package/dist/providers/compat/compat-directory-loader.d.ts +0 -4
- package/dist/providers/compat/compat-directory-loader.js +0 -85
- package/dist/providers/compat/compat-directory-loader.js.map +0 -1
- package/dist/providers/compat/compatibility-adapter.d.ts +0 -18
- package/dist/providers/compat/compatibility-adapter.js +0 -104
- package/dist/providers/compat/compatibility-adapter.js.map +0 -1
- package/dist/providers/compat/compatibility-factory.d.ts +0 -57
- package/dist/providers/compat/compatibility-factory.js +0 -155
- package/dist/providers/compat/compatibility-factory.js.map +0 -1
- package/dist/providers/compat/compatibility-interface.d.ts +0 -35
- package/dist/providers/compat/compatibility-interface.js +0 -2
- package/dist/providers/compat/compatibility-interface.js.map +0 -1
- package/dist/providers/compat/compatibility-manager.d.ts +0 -85
- package/dist/providers/compat/compatibility-manager.js +0 -368
- package/dist/providers/compat/compatibility-manager.js.map +0 -1
- package/dist/providers/compat/config/config-compatibility.d.ts +0 -28
- package/dist/providers/compat/config/config-compatibility.js +0 -95
- package/dist/providers/compat/config/config-compatibility.js.map +0 -1
- package/dist/providers/compat/field-mapping.d.ts +0 -102
- package/dist/providers/compat/field-mapping.js +0 -447
- package/dist/providers/compat/field-mapping.js.map +0 -1
- package/dist/providers/compat/filters/blacklist-sanitizer.d.ts +0 -45
- package/dist/providers/compat/filters/blacklist-sanitizer.js +0 -133
- package/dist/providers/compat/filters/blacklist-sanitizer.js.map +0 -1
- package/dist/providers/compat/filters/response-blacklist-sanitizer.d.ts +0 -28
- package/dist/providers/compat/filters/response-blacklist-sanitizer.js +0 -138
- package/dist/providers/compat/filters/response-blacklist-sanitizer.js.map +0 -1
- package/dist/providers/compat/filters/universal-shape-filter.js.map +0 -1
- package/dist/providers/compat/glm/config/blacklist-rules.json +0 -22
- package/dist/providers/compat/glm/config/field-mappings.json +0 -92
- package/dist/providers/compat/glm/config/response-blacklist.json +0 -7
- package/dist/providers/compat/glm/config/shape-filters.json +0 -37
- package/dist/providers/compat/glm/field-mapping/field-mapping-processor.d.ts +0 -28
- package/dist/providers/compat/glm/field-mapping/field-mapping-processor.js +0 -306
- package/dist/providers/compat/glm/field-mapping/field-mapping-processor.js.map +0 -1
- package/dist/providers/compat/glm/functions/glm-processor.d.ts +0 -50
- package/dist/providers/compat/glm/functions/glm-processor.js +0 -134
- package/dist/providers/compat/glm/functions/glm-processor.js.map +0 -1
- package/dist/providers/compat/glm/glm-compatibility.d.ts +0 -34
- package/dist/providers/compat/glm/glm-compatibility.js +0 -117
- package/dist/providers/compat/glm/glm-compatibility.js.map +0 -1
- package/dist/providers/compat/glm/hooks/base-hook.d.ts +0 -21
- package/dist/providers/compat/glm/hooks/base-hook.js +0 -53
- package/dist/providers/compat/glm/hooks/base-hook.js.map +0 -1
- package/dist/providers/compat/glm/hooks/glm-request-validation-hook.d.ts +0 -24
- package/dist/providers/compat/glm/hooks/glm-request-validation-hook.js +0 -268
- package/dist/providers/compat/glm/hooks/glm-request-validation-hook.js.map +0 -1
- package/dist/providers/compat/glm/hooks/glm-response-normalization-hook.d.ts +0 -21
- package/dist/providers/compat/glm/hooks/glm-response-normalization-hook.js +0 -171
- package/dist/providers/compat/glm/hooks/glm-response-normalization-hook.js.map +0 -1
- package/dist/providers/compat/glm/hooks/glm-response-validation-hook.d.ts +0 -25
- package/dist/providers/compat/glm/hooks/glm-response-validation-hook.js +0 -236
- package/dist/providers/compat/glm/hooks/glm-response-validation-hook.js.map +0 -1
- package/dist/providers/compat/glm/hooks/glm-tool-cleaning-hook.d.ts +0 -26
- package/dist/providers/compat/glm/hooks/glm-tool-cleaning-hook.js +0 -186
- package/dist/providers/compat/glm/hooks/glm-tool-cleaning-hook.js.map +0 -1
- package/dist/providers/compat/glm/index.d.ts +0 -24
- package/dist/providers/compat/glm/index.js +0 -29
- package/dist/providers/compat/glm/index.js.map +0 -1
- package/dist/providers/compat/glm/utils/tool-schema-helpers.d.ts +0 -3
- package/dist/providers/compat/glm/utils/tool-schema-helpers.js.map +0 -1
- package/dist/providers/compat/iflow/config/field-mappings.json +0 -92
- package/dist/providers/compat/iflow/config/shape-filters.json +0 -37
- package/dist/providers/compat/iflow/field-mapping/iflow-field-mapping-processor.d.ts +0 -34
- package/dist/providers/compat/iflow/field-mapping/iflow-field-mapping-processor.js +0 -386
- package/dist/providers/compat/iflow/field-mapping/iflow-field-mapping-processor.js.map +0 -1
- package/dist/providers/compat/iflow/functions/iflow-processor.d.ts +0 -53
- package/dist/providers/compat/iflow/functions/iflow-processor.js +0 -215
- package/dist/providers/compat/iflow/functions/iflow-processor.js.map +0 -1
- package/dist/providers/compat/iflow/hooks/base-hook.d.ts +0 -23
- package/dist/providers/compat/iflow/hooks/base-hook.js +0 -59
- package/dist/providers/compat/iflow/hooks/base-hook.js.map +0 -1
- package/dist/providers/compat/iflow/hooks/iflow-request-validation-hook.d.ts +0 -23
- package/dist/providers/compat/iflow/hooks/iflow-request-validation-hook.js +0 -279
- package/dist/providers/compat/iflow/hooks/iflow-request-validation-hook.js.map +0 -1
- package/dist/providers/compat/iflow/hooks/iflow-response-normalization-hook.d.ts +0 -20
- package/dist/providers/compat/iflow/hooks/iflow-response-normalization-hook.js +0 -180
- package/dist/providers/compat/iflow/hooks/iflow-response-normalization-hook.js.map +0 -1
- package/dist/providers/compat/iflow/hooks/iflow-response-validation-hook.d.ts +0 -23
- package/dist/providers/compat/iflow/hooks/iflow-response-validation-hook.js +0 -232
- package/dist/providers/compat/iflow/hooks/iflow-response-validation-hook.js.map +0 -1
- package/dist/providers/compat/iflow/hooks/iflow-tool-cleaning-hook.d.ts +0 -25
- package/dist/providers/compat/iflow/hooks/iflow-tool-cleaning-hook.js +0 -216
- package/dist/providers/compat/iflow/hooks/iflow-tool-cleaning-hook.js.map +0 -1
- package/dist/providers/compat/iflow/iflow-compatibility.d.ts +0 -24
- package/dist/providers/compat/iflow/iflow-compatibility.js +0 -94
- package/dist/providers/compat/iflow/iflow-compatibility.js.map +0 -1
- package/dist/providers/compat/index.d.ts +0 -59
- package/dist/providers/compat/index.js +0 -83
- package/dist/providers/compat/index.js.map +0 -1
- package/dist/providers/compat/lmstudio-compatibility.d.ts +0 -44
- package/dist/providers/compat/lmstudio-compatibility.js +0 -193
- package/dist/providers/compat/lmstudio-compatibility.js.map +0 -1
- package/dist/providers/compat/passthrough-compatibility.d.ts +0 -29
- package/dist/providers/compat/passthrough-compatibility.js +0 -83
- package/dist/providers/compat/passthrough-compatibility.js.map +0 -1
- package/dist/providers/compat/profiles/chat/glm/index.d.ts +0 -6
- package/dist/providers/compat/profiles/chat/glm/index.js +0 -6
- package/dist/providers/compat/profiles/chat/glm/index.js.map +0 -1
- package/dist/providers/compat/profiles/chat/iflow/index.d.ts +0 -6
- package/dist/providers/compat/profiles/chat/iflow/index.js +0 -6
- package/dist/providers/compat/profiles/chat/iflow/index.js.map +0 -1
- package/dist/providers/compat/profiles/chat/lmstudio/index.d.ts +0 -6
- package/dist/providers/compat/profiles/chat/lmstudio/index.js +0 -6
- package/dist/providers/compat/profiles/chat/lmstudio/index.js.map +0 -1
- package/dist/providers/compat/profiles/chat/qwen/index.d.ts +0 -6
- package/dist/providers/compat/profiles/chat/qwen/index.js +0 -6
- package/dist/providers/compat/profiles/chat/qwen/index.js.map +0 -1
- package/dist/providers/compat/profiles/compat/passthrough/index.d.ts +0 -6
- package/dist/providers/compat/profiles/compat/passthrough/index.js +0 -6
- package/dist/providers/compat/profiles/compat/passthrough/index.js.map +0 -1
- package/dist/providers/compat/profiles/responses/c4m/index.d.ts +0 -6
- package/dist/providers/compat/profiles/responses/c4m/index.js +0 -6
- package/dist/providers/compat/profiles/responses/c4m/index.js.map +0 -1
- package/dist/providers/compat/profiles/responses/default/index.d.ts +0 -6
- package/dist/providers/compat/profiles/responses/default/index.js +0 -6
- package/dist/providers/compat/profiles/responses/default/index.js.map +0 -1
- package/dist/providers/compat/profiles/responses/fai/index.d.ts +0 -6
- package/dist/providers/compat/profiles/responses/fai/index.js +0 -6
- package/dist/providers/compat/profiles/responses/fai/index.js.map +0 -1
- package/dist/providers/compat/profiles/responses/fc/index.d.ts +0 -6
- package/dist/providers/compat/profiles/responses/fc/index.js +0 -6
- package/dist/providers/compat/profiles/responses/fc/index.js.map +0 -1
- package/dist/providers/compat/qwen/index.d.ts +0 -4
- package/dist/providers/compat/qwen/index.js +0 -6
- package/dist/providers/compat/qwen/index.js.map +0 -1
- package/dist/providers/compat/qwen-compatibility.d.ts +0 -52
- package/dist/providers/compat/qwen-compatibility.js +0 -330
- package/dist/providers/compat/qwen-compatibility.js.map +0 -1
- package/dist/providers/compat/register-compat-module.d.ts +0 -8
- package/dist/providers/compat/register-compat-module.js +0 -53
- package/dist/providers/compat/register-compat-module.js.map +0 -1
- package/dist/providers/compat/responses/c4m-responses-compatibility.d.ts +0 -27
- package/dist/providers/compat/responses/c4m-responses-compatibility.js +0 -197
- package/dist/providers/compat/responses/c4m-responses-compatibility.js.map +0 -1
- package/dist/providers/compat/standard-compatibility-utils.d.ts +0 -1
- package/dist/providers/compat/standard-compatibility-utils.js +0 -77
- package/dist/providers/compat/standard-compatibility-utils.js.map +0 -1
- package/dist/providers/compat/standard-compatibility.d.ts +0 -31
- package/dist/providers/compat/standard-compatibility.js +0 -118
- package/dist/providers/compat/standard-compatibility.js.map +0 -1
- package/dist/providers/compat/utils/snapshot-writer.js +0 -62
- package/dist/providers/compat/utils/snapshot-writer.js.map +0 -1
- package/dist/tools/replay-request.d.ts +0 -0
- package/dist/tools/replay-request.js +0 -2
- package/dist/tools/replay-request.js.map +0 -1
- package/scripts/check-glm-compat.mjs +0 -47
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { VirtualRouterError, VirtualRouterErrorCode } from './types.js';
|
|
1
|
+
import { DEFAULT_MODEL_CONTEXT_TOKENS, VirtualRouterError, VirtualRouterErrorCode } from './types.js';
|
|
2
|
+
import { scanOAuthTokenFiles } from './token-file-scanner.js';
|
|
2
3
|
const DEFAULT_CLASSIFIER = {
|
|
3
4
|
longContextThresholdTokens: 180000,
|
|
4
5
|
thinkingKeywords: ['think step', 'analysis', 'reasoning', '仔细分析', '深度思考'],
|
|
@@ -8,6 +9,10 @@ const DEFAULT_CLASSIFIER = {
|
|
|
8
9
|
};
|
|
9
10
|
const DEFAULT_LOAD_BALANCING = { strategy: 'round-robin' };
|
|
10
11
|
const DEFAULT_HEALTH = { failureThreshold: 3, cooldownMs: 30_000, fatalCooldownMs: 300_000 };
|
|
12
|
+
const DEFAULT_CONTEXT_ROUTING = {
|
|
13
|
+
warnRatio: 0.9,
|
|
14
|
+
hardLimit: false
|
|
15
|
+
};
|
|
11
16
|
/**
|
|
12
17
|
* 将用户提供的 Virtual Router 配置(或包含 virtualrouter 字段的整体配置)
|
|
13
18
|
* 规范化为 VirtualRouterConfig,供 HubPipeline / VirtualRouterEngine 直接使用。
|
|
@@ -22,6 +27,8 @@ export function bootstrapVirtualRouterConfig(input) {
|
|
|
22
27
|
if (!Object.keys(routingSource).length) {
|
|
23
28
|
throw new VirtualRouterError('Virtual Router routing table cannot be empty', VirtualRouterErrorCode.CONFIG_ERROR);
|
|
24
29
|
}
|
|
30
|
+
const webSearch = normalizeWebSearch(section.webSearch, routingSource);
|
|
31
|
+
validateWebSearchRouting(webSearch, routingSource);
|
|
25
32
|
const { runtimeEntries, aliasIndex } = buildProviderRuntimeEntries(providersSource);
|
|
26
33
|
const { routing, targetKeys } = expandRoutingTable(routingSource, aliasIndex);
|
|
27
34
|
if (!routing.default || routing.default.length === 0) {
|
|
@@ -31,12 +38,15 @@ export function bootstrapVirtualRouterConfig(input) {
|
|
|
31
38
|
const classifier = normalizeClassifier(section.classifier);
|
|
32
39
|
const loadBalancing = section.loadBalancing ?? DEFAULT_LOAD_BALANCING;
|
|
33
40
|
const health = section.health ?? DEFAULT_HEALTH;
|
|
41
|
+
const contextRouting = section.contextRouting ?? DEFAULT_CONTEXT_ROUTING;
|
|
34
42
|
const config = {
|
|
35
43
|
routing,
|
|
36
44
|
providers: providerProfiles,
|
|
37
45
|
classifier,
|
|
38
46
|
loadBalancing,
|
|
39
|
-
health
|
|
47
|
+
health,
|
|
48
|
+
contextRouting,
|
|
49
|
+
...(webSearch ? { webSearch } : {})
|
|
40
50
|
};
|
|
41
51
|
return {
|
|
42
52
|
config,
|
|
@@ -56,7 +66,9 @@ function extractVirtualRouterSection(input) {
|
|
|
56
66
|
const classifier = (section.classifier ?? root.classifier);
|
|
57
67
|
const loadBalancing = normalizeLoadBalancing(section.loadBalancing ?? root.loadBalancing);
|
|
58
68
|
const health = normalizeHealth(section.health ?? root.health);
|
|
59
|
-
|
|
69
|
+
const contextRouting = normalizeContextRouting(section.contextRouting ?? root.contextRouting);
|
|
70
|
+
const webSearch = section.webSearch ?? root.webSearch;
|
|
71
|
+
return { providers, routing, classifier, loadBalancing, health, contextRouting, webSearch };
|
|
60
72
|
}
|
|
61
73
|
function buildProviderRuntimeEntries(providers) {
|
|
62
74
|
const runtimeEntries = {};
|
|
@@ -86,6 +98,11 @@ function buildProviderRuntimeEntries(providers) {
|
|
|
86
98
|
userInfoUrl: entry.auth.userInfoUrl,
|
|
87
99
|
refreshUrl: entry.auth.refreshUrl
|
|
88
100
|
};
|
|
101
|
+
// 为 OAuth 类型的 auth 设置 tokenFile 为 alias(如果没有显式配置 tokenFile)
|
|
102
|
+
// 这允许 oauth-lifecycle.ts 的 resolveTokenFilePath 函数正确解析并匹配现有文件
|
|
103
|
+
if (!runtimeAuth.tokenFile && (runtimeAuth.rawType?.includes('oauth') || runtimeAuth.type === 'oauth')) {
|
|
104
|
+
runtimeAuth.tokenFile = entry.keyAlias;
|
|
105
|
+
}
|
|
89
106
|
if (runtimeAuth.type === 'apiKey' && !runtimeAuth.secretRef) {
|
|
90
107
|
runtimeAuth.secretRef = `${providerId}.${entry.keyAlias}`;
|
|
91
108
|
}
|
|
@@ -100,7 +117,12 @@ function buildProviderRuntimeEntries(providers) {
|
|
|
100
117
|
outboundProfile: normalizedProvider.outboundProfile,
|
|
101
118
|
compatibilityProfile: normalizedProvider.compatibilityProfile,
|
|
102
119
|
processMode: normalizedProvider.processMode,
|
|
103
|
-
responsesConfig: normalizedProvider.responsesConfig
|
|
120
|
+
responsesConfig: normalizedProvider.responsesConfig,
|
|
121
|
+
streaming: normalizedProvider.streaming,
|
|
122
|
+
modelStreaming: normalizedProvider.modelStreaming,
|
|
123
|
+
modelContextTokens: normalizedProvider.modelContextTokens,
|
|
124
|
+
defaultContextTokens: normalizedProvider.defaultContextTokens,
|
|
125
|
+
...(normalizedProvider.serverToolsDisabled ? { serverToolsDisabled: true } : {})
|
|
104
126
|
};
|
|
105
127
|
}
|
|
106
128
|
}
|
|
@@ -109,28 +131,40 @@ function buildProviderRuntimeEntries(providers) {
|
|
|
109
131
|
function expandRoutingTable(routingSource, aliasIndex) {
|
|
110
132
|
const routing = {};
|
|
111
133
|
const targetKeys = new Set();
|
|
112
|
-
for (const [routeName,
|
|
113
|
-
const
|
|
114
|
-
for (const
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
134
|
+
for (const [routeName, pools] of Object.entries(routingSource)) {
|
|
135
|
+
const expandedPools = [];
|
|
136
|
+
for (const pool of pools) {
|
|
137
|
+
const expandedTargets = [];
|
|
138
|
+
for (const entry of pool.targets) {
|
|
139
|
+
const parsed = parseRouteEntry(entry, aliasIndex);
|
|
140
|
+
if (!parsed) {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (!aliasIndex.has(parsed.providerId)) {
|
|
144
|
+
throw new VirtualRouterError(`Route "${routeName}" references unknown provider "${parsed.providerId}"`, VirtualRouterErrorCode.CONFIG_ERROR);
|
|
145
|
+
}
|
|
146
|
+
const aliases = parsed.keyAlias ? [parsed.keyAlias] : aliasIndex.get(parsed.providerId);
|
|
147
|
+
if (!aliases.length) {
|
|
148
|
+
throw new VirtualRouterError(`Provider ${parsed.providerId} has no auth aliases but is referenced in routing`, VirtualRouterErrorCode.CONFIG_ERROR);
|
|
149
|
+
}
|
|
150
|
+
for (const alias of aliases) {
|
|
151
|
+
const runtimeKey = buildRuntimeKey(parsed.providerId, alias);
|
|
152
|
+
const targetKey = `${runtimeKey}.${parsed.modelId}`;
|
|
153
|
+
pushUnique(expandedTargets, targetKey);
|
|
154
|
+
targetKeys.add(targetKey);
|
|
155
|
+
}
|
|
125
156
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
157
|
+
if (expandedTargets.length) {
|
|
158
|
+
expandedPools.push({
|
|
159
|
+
id: pool.id,
|
|
160
|
+
priority: pool.priority,
|
|
161
|
+
backup: pool.backup,
|
|
162
|
+
targets: expandedTargets,
|
|
163
|
+
...(pool.force ? { force: true } : {})
|
|
164
|
+
});
|
|
131
165
|
}
|
|
132
166
|
}
|
|
133
|
-
routing[routeName] =
|
|
167
|
+
routing[routeName] = expandedPools;
|
|
134
168
|
}
|
|
135
169
|
return { routing, targetKeys };
|
|
136
170
|
}
|
|
@@ -146,6 +180,10 @@ function buildProviderProfiles(targetKeys, runtimeEntries) {
|
|
|
146
180
|
if (!runtime) {
|
|
147
181
|
throw new VirtualRouterError(`Routing target ${targetKey} references unknown runtime key ${runtimeKey}`, VirtualRouterErrorCode.CONFIG_ERROR);
|
|
148
182
|
}
|
|
183
|
+
const streamingPref = runtime.modelStreaming?.[parsed.modelId] !== undefined
|
|
184
|
+
? runtime.modelStreaming?.[parsed.modelId]
|
|
185
|
+
: runtime.streaming;
|
|
186
|
+
const contextTokens = resolveContextTokens(runtime, parsed.modelId);
|
|
149
187
|
profiles[targetKey] = {
|
|
150
188
|
providerKey: targetKey,
|
|
151
189
|
providerType: runtime.providerType,
|
|
@@ -156,27 +194,166 @@ function buildProviderProfiles(targetKeys, runtimeEntries) {
|
|
|
156
194
|
runtimeKey,
|
|
157
195
|
modelId: parsed.modelId,
|
|
158
196
|
processMode: runtime.processMode || 'chat',
|
|
159
|
-
responsesConfig: runtime.responsesConfig
|
|
197
|
+
responsesConfig: runtime.responsesConfig,
|
|
198
|
+
streaming: streamingPref,
|
|
199
|
+
maxContextTokens: contextTokens,
|
|
200
|
+
...(runtime.serverToolsDisabled ? { serverToolsDisabled: true } : {})
|
|
160
201
|
};
|
|
161
202
|
targetRuntime[targetKey] = {
|
|
162
203
|
...runtime,
|
|
163
|
-
modelId: parsed.modelId
|
|
204
|
+
modelId: parsed.modelId,
|
|
205
|
+
streaming: streamingPref,
|
|
206
|
+
maxContextTokens: contextTokens
|
|
164
207
|
};
|
|
165
208
|
}
|
|
166
209
|
return { profiles, targetRuntime };
|
|
167
210
|
}
|
|
211
|
+
function resolveContextTokens(runtime, modelId) {
|
|
212
|
+
const specific = runtime.modelContextTokens?.[modelId];
|
|
213
|
+
if (typeof specific === 'number' && Number.isFinite(specific) && specific > 0) {
|
|
214
|
+
return Math.floor(specific);
|
|
215
|
+
}
|
|
216
|
+
const fallback = runtime.defaultContextTokens ?? runtime.maxContextTokens;
|
|
217
|
+
if (typeof fallback === 'number' && Number.isFinite(fallback) && fallback > 0) {
|
|
218
|
+
return Math.floor(fallback);
|
|
219
|
+
}
|
|
220
|
+
return DEFAULT_MODEL_CONTEXT_TOKENS;
|
|
221
|
+
}
|
|
168
222
|
function normalizeRouting(source) {
|
|
169
223
|
const routing = {};
|
|
170
224
|
for (const [routeName, entries] of Object.entries(source)) {
|
|
171
|
-
if (!Array.isArray(entries))
|
|
225
|
+
if (!Array.isArray(entries) || !entries.length) {
|
|
226
|
+
routing[routeName] = [];
|
|
172
227
|
continue;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
228
|
+
}
|
|
229
|
+
const allStrings = entries.every((entry) => typeof entry === 'string' || entry === null || entry === undefined);
|
|
230
|
+
if (allStrings) {
|
|
231
|
+
const targets = normalizeTargetList(entries);
|
|
232
|
+
routing[routeName] = targets.length ? [buildLegacyRoutePool(routeName, targets)] : [];
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
const normalized = [];
|
|
236
|
+
const total = entries.length || 1;
|
|
237
|
+
for (let index = 0; index < entries.length; index += 1) {
|
|
238
|
+
const entry = entries[index];
|
|
239
|
+
const pool = normalizeRoutePoolEntry(routeName, entry, index, total);
|
|
240
|
+
if (pool && pool.targets.length) {
|
|
241
|
+
normalized.push(pool);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
routing[routeName] = normalized;
|
|
177
245
|
}
|
|
178
246
|
return routing;
|
|
179
247
|
}
|
|
248
|
+
function buildLegacyRoutePool(routeName, targets) {
|
|
249
|
+
return {
|
|
250
|
+
id: `${routeName}:pool0`,
|
|
251
|
+
priority: targets.length,
|
|
252
|
+
backup: false,
|
|
253
|
+
targets
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function normalizeRoutePoolEntry(routeName, entry, index, total) {
|
|
257
|
+
if (typeof entry === 'string') {
|
|
258
|
+
const targets = normalizeTargetList(entry);
|
|
259
|
+
return targets.length
|
|
260
|
+
? {
|
|
261
|
+
id: `${routeName}:pool${index + 1}`,
|
|
262
|
+
priority: total - index,
|
|
263
|
+
backup: false,
|
|
264
|
+
targets
|
|
265
|
+
}
|
|
266
|
+
: null;
|
|
267
|
+
}
|
|
268
|
+
if (!entry || typeof entry !== 'object') {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
const record = entry;
|
|
272
|
+
const id = readOptionalString(record.id) ??
|
|
273
|
+
readOptionalString(record?.poolId) ??
|
|
274
|
+
`${routeName}:pool${index + 1}`;
|
|
275
|
+
const backup = record.backup === true ||
|
|
276
|
+
record.isBackup === true ||
|
|
277
|
+
(typeof record.type === 'string' && record.type.toLowerCase() === 'backup');
|
|
278
|
+
const priority = normalizePriorityValue(record.priority, total - index);
|
|
279
|
+
const targets = normalizeRouteTargets(record);
|
|
280
|
+
const force = record.force === true ||
|
|
281
|
+
(typeof record.force === 'string' && record.force.trim().toLowerCase() === 'true');
|
|
282
|
+
return targets.length
|
|
283
|
+
? {
|
|
284
|
+
id,
|
|
285
|
+
priority,
|
|
286
|
+
backup,
|
|
287
|
+
targets,
|
|
288
|
+
...(force ? { force: true } : {})
|
|
289
|
+
}
|
|
290
|
+
: null;
|
|
291
|
+
}
|
|
292
|
+
function normalizeRouteTargets(record) {
|
|
293
|
+
const buckets = [
|
|
294
|
+
record.targets,
|
|
295
|
+
record.providers,
|
|
296
|
+
record.pool,
|
|
297
|
+
record.entries,
|
|
298
|
+
record.items,
|
|
299
|
+
record.routes
|
|
300
|
+
];
|
|
301
|
+
const normalized = [];
|
|
302
|
+
for (const bucket of buckets) {
|
|
303
|
+
for (const target of normalizeTargetList(bucket)) {
|
|
304
|
+
if (!normalized.includes(target)) {
|
|
305
|
+
normalized.push(target);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
const singular = [record.target, record.provider];
|
|
310
|
+
for (const candidate of singular) {
|
|
311
|
+
for (const target of normalizeTargetList(candidate)) {
|
|
312
|
+
if (!normalized.includes(target)) {
|
|
313
|
+
normalized.push(target);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return normalized;
|
|
318
|
+
}
|
|
319
|
+
function normalizeTargetList(value) {
|
|
320
|
+
if (Array.isArray(value)) {
|
|
321
|
+
const normalized = [];
|
|
322
|
+
for (const entry of value) {
|
|
323
|
+
if (typeof entry === 'string') {
|
|
324
|
+
const trimmed = entry.trim();
|
|
325
|
+
if (trimmed && !normalized.includes(trimmed)) {
|
|
326
|
+
normalized.push(trimmed);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return normalized;
|
|
331
|
+
}
|
|
332
|
+
if (typeof value === 'string') {
|
|
333
|
+
const trimmed = value.trim();
|
|
334
|
+
return trimmed ? [trimmed] : [];
|
|
335
|
+
}
|
|
336
|
+
if (typeof value === 'number') {
|
|
337
|
+
const str = String(value).trim();
|
|
338
|
+
return str ? [str] : [];
|
|
339
|
+
}
|
|
340
|
+
return [];
|
|
341
|
+
}
|
|
342
|
+
function normalizePriorityValue(value, fallback) {
|
|
343
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
344
|
+
return value;
|
|
345
|
+
}
|
|
346
|
+
if (typeof value === 'string') {
|
|
347
|
+
const trimmed = value.trim();
|
|
348
|
+
if (trimmed) {
|
|
349
|
+
const parsed = Number(trimmed);
|
|
350
|
+
if (Number.isFinite(parsed)) {
|
|
351
|
+
return parsed;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return fallback;
|
|
356
|
+
}
|
|
180
357
|
function normalizeClassifier(input) {
|
|
181
358
|
const normalized = asRecord(input);
|
|
182
359
|
const result = {
|
|
@@ -209,8 +386,18 @@ function normalizeProvider(providerId, raw) {
|
|
|
209
386
|
: '';
|
|
210
387
|
const headers = normalizeHeaders(provider.headers);
|
|
211
388
|
const compatibilityProfile = resolveCompatibilityProfile(providerId, provider);
|
|
212
|
-
const
|
|
389
|
+
const responsesNode = asRecord(provider.responses);
|
|
390
|
+
const responsesConfig = normalizeResponsesConfig(provider, responsesNode);
|
|
213
391
|
const processMode = normalizeProcessMode(provider.process);
|
|
392
|
+
const streaming = resolveProviderStreamingPreference(provider, responsesNode);
|
|
393
|
+
const modelStreaming = normalizeModelStreaming(provider);
|
|
394
|
+
const { modelContextTokens, defaultContextTokens } = normalizeModelContextTokens(provider);
|
|
395
|
+
const serverToolsDisabled = provider.serverToolsDisabled === true ||
|
|
396
|
+
(typeof provider.serverToolsDisabled === 'string' &&
|
|
397
|
+
provider.serverToolsDisabled.trim().toLowerCase() === 'true') ||
|
|
398
|
+
(provider.serverTools &&
|
|
399
|
+
typeof provider.serverTools === 'object' &&
|
|
400
|
+
provider.serverTools.enabled === false);
|
|
214
401
|
return {
|
|
215
402
|
providerId,
|
|
216
403
|
providerType,
|
|
@@ -219,20 +406,106 @@ function normalizeProvider(providerId, raw) {
|
|
|
219
406
|
outboundProfile: mapOutboundProfile(providerType),
|
|
220
407
|
compatibilityProfile,
|
|
221
408
|
processMode,
|
|
222
|
-
responsesConfig
|
|
409
|
+
responsesConfig,
|
|
410
|
+
streaming,
|
|
411
|
+
modelStreaming,
|
|
412
|
+
modelContextTokens,
|
|
413
|
+
defaultContextTokens,
|
|
414
|
+
...(serverToolsDisabled ? { serverToolsDisabled: true } : {})
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
function normalizeModelStreaming(provider) {
|
|
418
|
+
const modelsNode = asRecord(provider.models);
|
|
419
|
+
if (!modelsNode) {
|
|
420
|
+
return undefined;
|
|
421
|
+
}
|
|
422
|
+
const normalized = {};
|
|
423
|
+
for (const [modelId, modelRaw] of Object.entries(modelsNode)) {
|
|
424
|
+
if (!modelRaw || typeof modelRaw !== 'object') {
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
const preference = resolveStreamingPreference(modelRaw);
|
|
428
|
+
if (preference) {
|
|
429
|
+
normalized[modelId] = preference;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return Object.keys(normalized).length ? normalized : undefined;
|
|
433
|
+
}
|
|
434
|
+
function normalizeModelContextTokens(provider) {
|
|
435
|
+
const modelsNode = asRecord(provider.models);
|
|
436
|
+
const normalized = {};
|
|
437
|
+
for (const [modelId, modelRaw] of Object.entries(modelsNode)) {
|
|
438
|
+
if (!modelRaw || typeof modelRaw !== 'object') {
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
const candidate = readContextTokens(modelRaw);
|
|
442
|
+
if (candidate) {
|
|
443
|
+
normalized[modelId] = candidate;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
const configNode = asRecord(provider.config);
|
|
447
|
+
const defaultsNode = asRecord(configNode?.userConfigDefaults);
|
|
448
|
+
const defaultCandidate = readContextTokens(provider) ??
|
|
449
|
+
readContextTokens(configNode) ??
|
|
450
|
+
readContextTokens(defaultsNode);
|
|
451
|
+
return {
|
|
452
|
+
modelContextTokens: Object.keys(normalized).length ? normalized : undefined,
|
|
453
|
+
defaultContextTokens: defaultCandidate
|
|
223
454
|
};
|
|
224
455
|
}
|
|
225
|
-
function
|
|
226
|
-
|
|
227
|
-
|
|
456
|
+
function resolveStreamingPreference(model) {
|
|
457
|
+
return (coerceStreamingPreference(model.streaming) ??
|
|
458
|
+
coerceStreamingPreference(model.stream) ??
|
|
459
|
+
coerceStreamingPreference(model.supportsStreaming));
|
|
460
|
+
}
|
|
461
|
+
function coerceStreamingPreference(value) {
|
|
462
|
+
if (typeof value === 'string') {
|
|
463
|
+
const normalized = value.trim().toLowerCase();
|
|
464
|
+
if (normalized === 'always' || normalized === 'auto' || normalized === 'never') {
|
|
465
|
+
return normalized;
|
|
466
|
+
}
|
|
467
|
+
if (normalized === 'true') {
|
|
468
|
+
return 'always';
|
|
469
|
+
}
|
|
470
|
+
if (normalized === 'false') {
|
|
471
|
+
return 'never';
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
if (typeof value === 'boolean') {
|
|
475
|
+
return value ? 'always' : 'never';
|
|
476
|
+
}
|
|
477
|
+
if (value && typeof value === 'object') {
|
|
478
|
+
const record = value;
|
|
479
|
+
if (record.mode !== undefined) {
|
|
480
|
+
return coerceStreamingPreference(record.mode);
|
|
481
|
+
}
|
|
482
|
+
if (record.value !== undefined) {
|
|
483
|
+
return coerceStreamingPreference(record.value);
|
|
484
|
+
}
|
|
485
|
+
if (record.enabled !== undefined) {
|
|
486
|
+
return coerceStreamingPreference(record.enabled);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
return undefined;
|
|
490
|
+
}
|
|
491
|
+
function normalizeResponsesConfig(provider, node) {
|
|
492
|
+
const source = node ?? asRecord(provider.responses);
|
|
493
|
+
if (!source) {
|
|
228
494
|
return undefined;
|
|
229
495
|
}
|
|
230
|
-
const rawStyle = typeof
|
|
496
|
+
const rawStyle = typeof source.toolCallIdStyle === 'string' ? source.toolCallIdStyle.trim().toLowerCase() : undefined;
|
|
231
497
|
if (rawStyle === 'fc' || rawStyle === 'preserve') {
|
|
232
498
|
return { toolCallIdStyle: rawStyle };
|
|
233
499
|
}
|
|
234
500
|
return undefined;
|
|
235
501
|
}
|
|
502
|
+
function resolveProviderStreamingPreference(provider, responsesNode) {
|
|
503
|
+
const configNode = asRecord(provider.config);
|
|
504
|
+
const configResponses = configNode ? asRecord(configNode.responses) : undefined;
|
|
505
|
+
return (coerceStreamingPreference(provider.streaming ?? provider.stream ?? provider.supportsStreaming ?? provider.streamingPreference) ??
|
|
506
|
+
coerceStreamingPreference(responsesNode?.streaming ?? responsesNode?.stream ?? responsesNode?.supportsStreaming) ??
|
|
507
|
+
coerceStreamingPreference(configResponses?.streaming ?? configResponses?.stream));
|
|
508
|
+
}
|
|
236
509
|
function resolveCompatibilityProfile(providerId, provider) {
|
|
237
510
|
if (typeof provider.compatibilityProfile === 'string' && provider.compatibilityProfile.trim()) {
|
|
238
511
|
return provider.compatibilityProfile.trim();
|
|
@@ -259,6 +532,121 @@ function normalizeProcessMode(value) {
|
|
|
259
532
|
}
|
|
260
533
|
return 'chat';
|
|
261
534
|
}
|
|
535
|
+
function normalizeContextRouting(input) {
|
|
536
|
+
if (!input || typeof input !== 'object') {
|
|
537
|
+
return { ...DEFAULT_CONTEXT_ROUTING };
|
|
538
|
+
}
|
|
539
|
+
const record = input;
|
|
540
|
+
const warnCandidate = coerceRatio(record.warnRatio) ??
|
|
541
|
+
coerceRatio(record?.warn_ratio);
|
|
542
|
+
const hardLimitCandidate = coerceBoolean(record.hardLimit) ??
|
|
543
|
+
coerceBoolean(record?.hard_limit);
|
|
544
|
+
const warnRatio = clampWarnRatio(warnCandidate ?? DEFAULT_CONTEXT_ROUTING.warnRatio);
|
|
545
|
+
const hardLimit = typeof hardLimitCandidate === 'boolean' ? hardLimitCandidate : DEFAULT_CONTEXT_ROUTING.hardLimit;
|
|
546
|
+
return {
|
|
547
|
+
warnRatio,
|
|
548
|
+
hardLimit
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
function validateWebSearchRouting(webSearch, routingSource) {
|
|
552
|
+
if (!webSearch) {
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
const routePools = routingSource['web_search'] ?? routingSource['search'];
|
|
556
|
+
if (!Array.isArray(routePools) || !routePools.length) {
|
|
557
|
+
throw new VirtualRouterError('Virtual Router webSearch.engines configured but routing.web_search (or search) route is missing or empty', VirtualRouterErrorCode.CONFIG_ERROR);
|
|
558
|
+
}
|
|
559
|
+
const targets = new Set();
|
|
560
|
+
for (const pool of routePools) {
|
|
561
|
+
if (!pool || !Array.isArray(pool.targets)) {
|
|
562
|
+
continue;
|
|
563
|
+
}
|
|
564
|
+
for (const target of pool.targets) {
|
|
565
|
+
if (typeof target === 'string' && target.trim()) {
|
|
566
|
+
targets.add(target.trim());
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
for (const engine of webSearch.engines) {
|
|
571
|
+
if (!targets.has(engine.providerKey)) {
|
|
572
|
+
throw new VirtualRouterError(`Virtual Router webSearch engine "${engine.id}" references providerKey "${engine.providerKey}" which is not present in routing.web_search/search`, VirtualRouterErrorCode.CONFIG_ERROR);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
function normalizeWebSearch(input, routingSource) {
|
|
577
|
+
if (!input || typeof input !== 'object') {
|
|
578
|
+
return undefined;
|
|
579
|
+
}
|
|
580
|
+
const record = input;
|
|
581
|
+
const enginesNode = Array.isArray(record.engines) ? record.engines : [];
|
|
582
|
+
const engines = [];
|
|
583
|
+
for (const raw of enginesNode) {
|
|
584
|
+
if (!raw || typeof raw !== 'object') {
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
587
|
+
const node = raw;
|
|
588
|
+
const idRaw = node.id;
|
|
589
|
+
const providerKeyRaw = node.providerKey ?? node.provider ?? node.target;
|
|
590
|
+
const id = typeof idRaw === 'string' && idRaw.trim()
|
|
591
|
+
? idRaw.trim()
|
|
592
|
+
: undefined;
|
|
593
|
+
const providerKey = typeof providerKeyRaw === 'string' && providerKeyRaw.trim()
|
|
594
|
+
? providerKeyRaw.trim()
|
|
595
|
+
: undefined;
|
|
596
|
+
if (!id || !providerKey) {
|
|
597
|
+
continue;
|
|
598
|
+
}
|
|
599
|
+
const description = typeof node.description === 'string' && node.description.trim()
|
|
600
|
+
? node.description.trim()
|
|
601
|
+
: undefined;
|
|
602
|
+
const isDefault = node.default === true ||
|
|
603
|
+
(typeof node.default === 'string' && node.default.trim().toLowerCase() === 'true');
|
|
604
|
+
const serverToolsDisabled = node.serverToolsDisabled === true ||
|
|
605
|
+
(typeof node.serverToolsDisabled === 'string' &&
|
|
606
|
+
node.serverToolsDisabled.trim().toLowerCase() === 'true') ||
|
|
607
|
+
(node.serverTools &&
|
|
608
|
+
typeof node.serverTools === 'object' &&
|
|
609
|
+
node.serverTools.enabled === false);
|
|
610
|
+
// Deduplicate by id; first wins, subsequent are ignored.
|
|
611
|
+
if (engines.some((engine) => engine.id === id)) {
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
engines.push({
|
|
615
|
+
id,
|
|
616
|
+
providerKey,
|
|
617
|
+
description,
|
|
618
|
+
default: isDefault,
|
|
619
|
+
...(serverToolsDisabled ? { serverToolsDisabled: true } : {})
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
if (!engines.length) {
|
|
623
|
+
return undefined;
|
|
624
|
+
}
|
|
625
|
+
let injectPolicy;
|
|
626
|
+
let force;
|
|
627
|
+
const rawPolicy = record.injectPolicy ?? record?.inject_policy;
|
|
628
|
+
if (typeof rawPolicy === 'string') {
|
|
629
|
+
const normalized = rawPolicy.trim().toLowerCase();
|
|
630
|
+
if (normalized === 'always' || normalized === 'selective') {
|
|
631
|
+
injectPolicy = normalized;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
if (record.force === true ||
|
|
635
|
+
(typeof record.force === 'string' && record.force.trim().toLowerCase() === 'true')) {
|
|
636
|
+
force = true;
|
|
637
|
+
}
|
|
638
|
+
else {
|
|
639
|
+
const webSearchPools = routingSource['web_search'] ?? routingSource['search'] ?? [];
|
|
640
|
+
if (Array.isArray(webSearchPools) && webSearchPools.some((pool) => pool.force)) {
|
|
641
|
+
force = true;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
return {
|
|
645
|
+
engines,
|
|
646
|
+
injectPolicy: injectPolicy ?? 'selective',
|
|
647
|
+
...(force ? { force } : {})
|
|
648
|
+
};
|
|
649
|
+
}
|
|
262
650
|
function extractProviderAuthEntries(providerId, raw) {
|
|
263
651
|
const provider = asRecord(raw);
|
|
264
652
|
const auth = asRecord(provider.auth);
|
|
@@ -389,6 +777,43 @@ function extractProviderAuthEntries(providerId, raw) {
|
|
|
389
777
|
else if (typeof apiKeyField === 'string' && apiKeyField.trim()) {
|
|
390
778
|
pushEntry(undefined, buildAuthCandidate(baseTypeSource, { value: apiKeyField.trim() }));
|
|
391
779
|
}
|
|
780
|
+
// 自动多 token 扫描:仅在未显式声明多 key、且为受支持的 OAuth 提供方时触发
|
|
781
|
+
if (baseType === 'oauth') {
|
|
782
|
+
const scanCandidates = new Set();
|
|
783
|
+
const pushCandidate = (value) => {
|
|
784
|
+
if (typeof value === 'string' && value.trim()) {
|
|
785
|
+
scanCandidates.add(value.trim().toLowerCase());
|
|
786
|
+
}
|
|
787
|
+
};
|
|
788
|
+
pushCandidate(auth?.oauthProviderId);
|
|
789
|
+
pushCandidate(baseTypeInfo.oauthProviderId);
|
|
790
|
+
pushCandidate(providerId);
|
|
791
|
+
for (const candidate of scanCandidates) {
|
|
792
|
+
if (!MULTI_TOKEN_OAUTH_PROVIDERS.has(candidate)) {
|
|
793
|
+
continue;
|
|
794
|
+
}
|
|
795
|
+
const tokenFiles = scanOAuthTokenFiles(candidate);
|
|
796
|
+
if (!tokenFiles.length) {
|
|
797
|
+
continue;
|
|
798
|
+
}
|
|
799
|
+
const baseTypeAlias = baseTypeInfo.oauthProviderId?.toLowerCase();
|
|
800
|
+
for (const match of tokenFiles) {
|
|
801
|
+
const alias = match.alias && match.alias !== 'default'
|
|
802
|
+
? `${match.sequence}-${match.alias}`
|
|
803
|
+
: String(match.sequence);
|
|
804
|
+
const typeHint = baseTypeSource && baseTypeAlias === candidate
|
|
805
|
+
? baseTypeSource
|
|
806
|
+
: `${candidate}-oauth`;
|
|
807
|
+
const authConfig = {
|
|
808
|
+
...defaults,
|
|
809
|
+
type: typeHint,
|
|
810
|
+
tokenFile: match.filePath,
|
|
811
|
+
oauthProviderId: candidate
|
|
812
|
+
};
|
|
813
|
+
pushEntry(alias, authConfig);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
392
817
|
if (!entries.length) {
|
|
393
818
|
const fallbackExtras = {
|
|
394
819
|
value: readOptionalString(auth.value),
|
|
@@ -552,6 +977,7 @@ function mergeScopes(primary, fallback) {
|
|
|
552
977
|
}
|
|
553
978
|
return merged.size ? Array.from(merged) : undefined;
|
|
554
979
|
}
|
|
980
|
+
const MULTI_TOKEN_OAUTH_PROVIDERS = new Set(['iflow', 'qwen', 'gemini-cli', 'antigravity']);
|
|
555
981
|
function interpretAuthType(value) {
|
|
556
982
|
if (typeof value !== 'string') {
|
|
557
983
|
return { type: 'apiKey' };
|
|
@@ -595,6 +1021,47 @@ function normalizeLoadBalancing(input) {
|
|
|
595
1021
|
? { strategy, weights: weightsEntries }
|
|
596
1022
|
: { strategy };
|
|
597
1023
|
}
|
|
1024
|
+
function coerceRatio(value) {
|
|
1025
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
1026
|
+
return value;
|
|
1027
|
+
}
|
|
1028
|
+
if (typeof value === 'string') {
|
|
1029
|
+
const trimmed = value.trim();
|
|
1030
|
+
if (!trimmed) {
|
|
1031
|
+
return undefined;
|
|
1032
|
+
}
|
|
1033
|
+
const parsed = Number(trimmed);
|
|
1034
|
+
if (Number.isFinite(parsed)) {
|
|
1035
|
+
return parsed;
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
return undefined;
|
|
1039
|
+
}
|
|
1040
|
+
function clampWarnRatio(value) {
|
|
1041
|
+
if (!Number.isFinite(value)) {
|
|
1042
|
+
return DEFAULT_CONTEXT_ROUTING.warnRatio;
|
|
1043
|
+
}
|
|
1044
|
+
const clamped = Math.max(0.1, Math.min(value, 0.99));
|
|
1045
|
+
return Number.isFinite(clamped) ? clamped : DEFAULT_CONTEXT_ROUTING.warnRatio;
|
|
1046
|
+
}
|
|
1047
|
+
function coerceBoolean(value) {
|
|
1048
|
+
if (typeof value === 'boolean') {
|
|
1049
|
+
return value;
|
|
1050
|
+
}
|
|
1051
|
+
if (typeof value === 'string') {
|
|
1052
|
+
const normalized = value.trim().toLowerCase();
|
|
1053
|
+
if (!normalized) {
|
|
1054
|
+
return undefined;
|
|
1055
|
+
}
|
|
1056
|
+
if (['true', '1', 'yes', 'y'].includes(normalized)) {
|
|
1057
|
+
return true;
|
|
1058
|
+
}
|
|
1059
|
+
if (['false', '0', 'no', 'n'].includes(normalized)) {
|
|
1060
|
+
return false;
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
return undefined;
|
|
1064
|
+
}
|
|
598
1065
|
function normalizeHealth(input) {
|
|
599
1066
|
if (!input || typeof input !== 'object')
|
|
600
1067
|
return undefined;
|
|
@@ -609,6 +1076,43 @@ function normalizeHealth(input) {
|
|
|
609
1076
|
? { failureThreshold, cooldownMs, fatalCooldownMs }
|
|
610
1077
|
: { failureThreshold, cooldownMs };
|
|
611
1078
|
}
|
|
1079
|
+
function readContextTokens(record) {
|
|
1080
|
+
if (!record) {
|
|
1081
|
+
return undefined;
|
|
1082
|
+
}
|
|
1083
|
+
const keys = [
|
|
1084
|
+
'maxContextTokens',
|
|
1085
|
+
'max_context_tokens',
|
|
1086
|
+
'maxContext',
|
|
1087
|
+
'max_context',
|
|
1088
|
+
'contextTokens',
|
|
1089
|
+
'context_tokens'
|
|
1090
|
+
];
|
|
1091
|
+
for (const key of keys) {
|
|
1092
|
+
const value = record[key];
|
|
1093
|
+
const parsed = normalizePositiveInteger(value);
|
|
1094
|
+
if (parsed) {
|
|
1095
|
+
return parsed;
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
return undefined;
|
|
1099
|
+
}
|
|
1100
|
+
function normalizePositiveInteger(value) {
|
|
1101
|
+
if (typeof value === 'number' && Number.isFinite(value) && value > 0) {
|
|
1102
|
+
return Math.floor(value);
|
|
1103
|
+
}
|
|
1104
|
+
if (typeof value === 'string') {
|
|
1105
|
+
const trimmed = value.trim();
|
|
1106
|
+
if (!trimmed) {
|
|
1107
|
+
return undefined;
|
|
1108
|
+
}
|
|
1109
|
+
const parsed = Number(trimmed);
|
|
1110
|
+
if (Number.isFinite(parsed) && parsed > 0) {
|
|
1111
|
+
return Math.floor(parsed);
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
return undefined;
|
|
1115
|
+
}
|
|
612
1116
|
function normalizeHeaders(input) {
|
|
613
1117
|
if (!input || typeof input !== 'object') {
|
|
614
1118
|
return undefined;
|