@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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snapshot-writer.js","sourceRoot":"","sources":["../../src/utils/snapshot-writer.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,aAAa,CAAC;AAC9B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"snapshot-writer.js","sourceRoot":"","sources":["../../src/utils/snapshot-writer.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,aAAa,CAAC;AAC9B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAkB3D,MAAM,UAAU,kBAAkB;IAChC,8CAA8C;IAC9C,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,UAA4B,CAAC;QACjD,IAAI,OAAO,WAAW,CAAC,mBAAmB,KAAK,SAAS,EAAE,CAAC;YACzD,OAAO,WAAW,CAAC,mBAAmB,CAAC;QACzC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;IACD,OAAO,YAAY,CAAC,gBAAgB,CAAC;AACvC,CAAC;AAED,SAAS,mBAAmB,CAAC,aAAsB;IACjD,MAAM,EAAE,GAAG,MAAM,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACrD,IAAI,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QACjC,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,IAAI,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7D,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,GAAW;IAClC,IAAI,CAAC;QAAC,MAAM,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,OAKzC;IACC,IAAI,CAAC,kBAAkB,EAAE,EAAE,CAAC;QAC1B,OAAO,CAAC,cAAc;IACxB,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,aAAa,IAAI,sBAAsB,CAAC;IAEjE,4CAA4C;IAC5C,IAAI,CAAC;QACH,MAAM,qBAAqB,CAAC,QAAQ,EAAE;YACpC,QAAQ;YACR,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;YAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,SAAS,EAAE,SAAS;SACrB,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,iEAAiE;IACnE,CAAC;IAED,gEAAgE;IAChE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,eAAe,CAAC,CAAC;QACrE,MAAM,MAAM,GAAG,mBAAmB,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpC,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QACrB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CACpB,GAAG,EACH,GAAG,OAAO,CAAC,SAAS,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,OAAO,CACpF,CAAC;QACF,MAAM,OAAO,GAAG;YACd,IAAI,EAAE;gBACJ,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,KAAK,CAAC;gBACxD,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;aACjF;YACD,IAAI,EAAE,OAAO,CAAC,IAAI;SACnB,CAAC;QACF,MAAM,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,sBAAsB;IACxB,CAAC;AACH,CAAC"}
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
|
|
22
22
|
👉 **Hub Pipeline 是当前唯一入口。** 如果 Host 需要直接编排 Virtual Router,请参见 `docs/HUB_PIPELINE_USAGE.md`,了解如何通过 `bootstrapVirtualRouterConfig` + `HubPipeline` 完成初始化与热更新。
|
|
23
23
|
|
|
24
|
+
👉 **ServerTool 是所有 server-side 工具的唯一统一框架。** web_search / vision followup 等服务端工具均在 llmswitch-core 内部通过 ServerTool 执行,Host 只需提供 providerInvoker/reenterPipeline 即可。设计与接入方式详见 `docs/SERVERTOOL_DESIGN.md`。
|
|
25
|
+
|
|
24
26
|
## 总览
|
|
25
27
|
|
|
26
28
|
```
|
|
@@ -3,7 +3,8 @@ import { resolveBridgePolicy, resolvePolicyActions } from '../shared/bridge-poli
|
|
|
3
3
|
import { normalizeChatMessageContent } from '../shared/chat-output-normalizer.js';
|
|
4
4
|
import { mapBridgeToolsToChat } from '../shared/tool-mapping.js';
|
|
5
5
|
import { prepareGeminiToolsForBridge } from '../shared/gemini-tool-utils.js';
|
|
6
|
-
import { registerResponsesReasoning, consumeResponsesReasoning, registerResponsesOutputTextMeta, consumeResponsesOutputTextMeta } from '../shared/responses-reasoning-registry.js';
|
|
6
|
+
import { registerResponsesReasoning, consumeResponsesReasoning, registerResponsesOutputTextMeta, consumeResponsesOutputTextMeta, consumeResponsesPayloadSnapshot, registerResponsesPayloadSnapshot, consumeResponsesPassthrough, registerResponsesPassthrough } from '../shared/responses-reasoning-registry.js';
|
|
7
|
+
const DUMMY_THOUGHT_SIGNATURE = 'skip_thought_signature_validator';
|
|
7
8
|
function isObject(v) {
|
|
8
9
|
return !!v && typeof v === 'object' && !Array.isArray(v);
|
|
9
10
|
}
|
|
@@ -54,6 +55,32 @@ function mapChatRoleToGemini(role) {
|
|
|
54
55
|
return 'tool';
|
|
55
56
|
return 'user';
|
|
56
57
|
}
|
|
58
|
+
function coerceThoughtSignature(value) {
|
|
59
|
+
if (typeof value === 'string' && value.trim().length) {
|
|
60
|
+
return value.trim();
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
function extractThoughtSignatureFromToolCall(tc) {
|
|
65
|
+
if (!tc || typeof tc !== 'object') {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
const direct = coerceThoughtSignature(tc.thought_signature ?? tc.thoughtSignature);
|
|
69
|
+
if (direct) {
|
|
70
|
+
return direct;
|
|
71
|
+
}
|
|
72
|
+
const extraContent = tc.extra_content ?? tc.extraContent;
|
|
73
|
+
if (extraContent && typeof extraContent === 'object') {
|
|
74
|
+
const googleNode = extraContent.google ?? extraContent.Google;
|
|
75
|
+
if (googleNode && typeof googleNode === 'object') {
|
|
76
|
+
const googleSig = coerceThoughtSignature(googleNode.thought_signature ?? googleNode.thoughtSignature);
|
|
77
|
+
if (googleSig) {
|
|
78
|
+
return googleSig;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
57
84
|
export function buildOpenAIChatFromGeminiRequest(payload) {
|
|
58
85
|
const messages = [];
|
|
59
86
|
// systemInstruction → Chat system 消息
|
|
@@ -156,16 +183,22 @@ export function buildOpenAIChatFromGeminiResponse(payload) {
|
|
|
156
183
|
const textParts = [];
|
|
157
184
|
const reasoningParts = [];
|
|
158
185
|
const toolCalls = [];
|
|
186
|
+
const toolResultTexts = [];
|
|
187
|
+
const toolOutputs = [];
|
|
188
|
+
// 为当前响应内生成稳定的工具调用 ID,避免下游 ServerTool 因缺少 id 而跳过。
|
|
189
|
+
let toolCallCounter = 0;
|
|
159
190
|
for (const part of parts) {
|
|
160
191
|
if (!part || typeof part !== 'object')
|
|
161
192
|
continue;
|
|
162
193
|
const pObj = part;
|
|
194
|
+
// 1. Text part
|
|
163
195
|
if (typeof pObj.text === 'string') {
|
|
164
196
|
const t = pObj.text;
|
|
165
197
|
if (t && t.trim().length)
|
|
166
198
|
textParts.push(t);
|
|
167
199
|
continue;
|
|
168
200
|
}
|
|
201
|
+
// 2. Content array (nested structure)
|
|
169
202
|
if (Array.isArray(pObj.content)) {
|
|
170
203
|
for (const inner of pObj.content) {
|
|
171
204
|
if (typeof inner === 'string') {
|
|
@@ -177,16 +210,26 @@ export function buildOpenAIChatFromGeminiResponse(payload) {
|
|
|
177
210
|
}
|
|
178
211
|
continue;
|
|
179
212
|
}
|
|
213
|
+
// 3. Reasoning part (channel mode)
|
|
180
214
|
if (typeof pObj.reasoning === 'string') {
|
|
181
215
|
reasoningParts.push(pObj.reasoning);
|
|
182
216
|
continue;
|
|
183
217
|
}
|
|
218
|
+
// 4. Thought part (thinking/extended thinking)
|
|
219
|
+
if (typeof pObj.thought === 'string') {
|
|
220
|
+
const thoughtText = pObj.thought.trim();
|
|
221
|
+
if (thoughtText.length) {
|
|
222
|
+
reasoningParts.push(thoughtText);
|
|
223
|
+
}
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
// 5. Function call (tool call)
|
|
184
227
|
if (pObj.functionCall && typeof pObj.functionCall === 'object') {
|
|
185
228
|
const fc = pObj.functionCall;
|
|
186
229
|
const name = typeof fc.name === 'string' ? String(fc.name) : undefined;
|
|
187
230
|
if (!name)
|
|
188
231
|
continue;
|
|
189
|
-
|
|
232
|
+
let id = typeof fc.id === 'string' && fc.id.trim().length ? String(fc.id).trim() : undefined;
|
|
190
233
|
const argsRaw = (fc.args ?? fc.arguments);
|
|
191
234
|
let argsStr;
|
|
192
235
|
if (typeof argsRaw === 'string') {
|
|
@@ -195,15 +238,91 @@ export function buildOpenAIChatFromGeminiResponse(payload) {
|
|
|
195
238
|
else {
|
|
196
239
|
argsStr = safeJson(argsRaw);
|
|
197
240
|
}
|
|
198
|
-
|
|
241
|
+
const thoughtSignature = coerceThoughtSignature(pObj.thoughtSignature);
|
|
242
|
+
// Gemini 某些响应中的 functionCall 不带 id,但下游 servertool 需要稳定的
|
|
243
|
+
// tool_call.id 才会识别为有效工具调用;此处在缺失时生成本响应内唯一的占位 ID。
|
|
244
|
+
if (!id) {
|
|
245
|
+
const suffix = toolCallCounter++;
|
|
246
|
+
id = `gemini_tool_${suffix}`;
|
|
247
|
+
}
|
|
248
|
+
const toolCall = {
|
|
199
249
|
id,
|
|
200
250
|
type: 'function',
|
|
201
251
|
function: { name, arguments: argsStr }
|
|
202
|
-
}
|
|
252
|
+
};
|
|
253
|
+
if (thoughtSignature) {
|
|
254
|
+
toolCall.thought_signature = thoughtSignature;
|
|
255
|
+
toolCall.extra_content = {
|
|
256
|
+
google: {
|
|
257
|
+
thought_signature: thoughtSignature
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
toolCalls.push(toolCall);
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
// 6. Function response (tool result)
|
|
265
|
+
if (pObj.functionResponse && typeof pObj.functionResponse === 'object') {
|
|
266
|
+
const fr = pObj.functionResponse;
|
|
267
|
+
const callId = typeof fr.id === 'string' && fr.id.trim().length ? String(fr.id) : undefined;
|
|
268
|
+
const name = typeof fr.name === 'string' && fr.name.trim().length ? String(fr.name) : undefined;
|
|
269
|
+
const resp = fr.response;
|
|
270
|
+
let contentStr = '';
|
|
271
|
+
if (typeof resp === 'string') {
|
|
272
|
+
contentStr = resp;
|
|
273
|
+
}
|
|
274
|
+
else if (resp != null) {
|
|
275
|
+
try {
|
|
276
|
+
contentStr = JSON.stringify(resp);
|
|
277
|
+
}
|
|
278
|
+
catch {
|
|
279
|
+
contentStr = String(resp);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (contentStr && contentStr.trim().length) {
|
|
283
|
+
toolResultTexts.push(contentStr);
|
|
284
|
+
if (callId || name) {
|
|
285
|
+
const entry = {
|
|
286
|
+
tool_call_id: callId ?? undefined,
|
|
287
|
+
id: callId ?? undefined,
|
|
288
|
+
content: contentStr
|
|
289
|
+
};
|
|
290
|
+
if (name) {
|
|
291
|
+
entry.name = name;
|
|
292
|
+
}
|
|
293
|
+
toolOutputs.push(entry);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
// 7. Executable code (code_interpreter)
|
|
299
|
+
if (pObj.executableCode && typeof pObj.executableCode === 'object') {
|
|
300
|
+
const code = pObj.executableCode;
|
|
301
|
+
const language = typeof code.language === 'string' ? code.language : 'python';
|
|
302
|
+
const codeText = typeof code.code === 'string' ? code.code : '';
|
|
303
|
+
if (codeText.trim().length) {
|
|
304
|
+
// Append as text with code block formatting
|
|
305
|
+
textParts.push(`\`\`\`${language}\n${codeText}\n\`\`\``);
|
|
306
|
+
}
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
// 8. Code execution result
|
|
310
|
+
if (pObj.codeExecutionResult && typeof pObj.codeExecutionResult === 'object') {
|
|
311
|
+
const result = pObj.codeExecutionResult;
|
|
312
|
+
const outcome = typeof result.outcome === 'string' ? result.outcome : '';
|
|
313
|
+
const output = typeof result.output === 'string' ? result.output : '';
|
|
314
|
+
if (output.trim().length) {
|
|
315
|
+
textParts.push(`[Code Output${outcome ? ` (${outcome})` : ''}]:\n${output}`);
|
|
316
|
+
}
|
|
203
317
|
continue;
|
|
204
318
|
}
|
|
205
319
|
}
|
|
320
|
+
const hasToolCalls = toolCalls.length > 0;
|
|
206
321
|
const finish_reason = (() => {
|
|
322
|
+
// If the model is emitting tool calls, treat this turn as a tool_calls
|
|
323
|
+
// completion so downstream tool governance can continue the loop.
|
|
324
|
+
if (hasToolCalls)
|
|
325
|
+
return 'tool_calls';
|
|
207
326
|
const fr = String(primary?.finishReason || '').toUpperCase();
|
|
208
327
|
if (fr === 'MAX_TOKENS')
|
|
209
328
|
return 'length';
|
|
@@ -228,9 +347,14 @@ export function buildOpenAIChatFromGeminiResponse(payload) {
|
|
|
228
347
|
usage.total_tokens = totalTokens;
|
|
229
348
|
const combinedText = textParts.join('\n');
|
|
230
349
|
const normalized = combinedText.length ? normalizeChatMessageContent(combinedText) : { contentText: undefined, reasoningText: undefined };
|
|
350
|
+
const baseContent = normalized.contentText ?? combinedText ?? '';
|
|
351
|
+
const toolResultBlock = toolResultTexts.length ? toolResultTexts.join('\n') : '';
|
|
352
|
+
const finalContent = toolResultBlock && baseContent
|
|
353
|
+
? `${baseContent}\n${toolResultBlock}`
|
|
354
|
+
: baseContent || toolResultBlock;
|
|
231
355
|
const chatMsg = {
|
|
232
356
|
role,
|
|
233
|
-
content:
|
|
357
|
+
content: finalContent
|
|
234
358
|
};
|
|
235
359
|
if (typeof normalized.reasoningText === 'string' && normalized.reasoningText.trim().length) {
|
|
236
360
|
reasoningParts.push(normalized.reasoningText.trim());
|
|
@@ -277,6 +401,9 @@ export function buildOpenAIChatFromGeminiResponse(payload) {
|
|
|
277
401
|
if (Object.keys(usage).length > 0) {
|
|
278
402
|
chatResp.usage = usage;
|
|
279
403
|
}
|
|
404
|
+
if (toolOutputs.length > 0) {
|
|
405
|
+
chatResp.tool_outputs = toolOutputs;
|
|
406
|
+
}
|
|
280
407
|
const preservedReasoning = consumeResponsesReasoning(chatResp.id);
|
|
281
408
|
if (preservedReasoning && preservedReasoning.length) {
|
|
282
409
|
chatResp.__responses_reasoning = preservedReasoning;
|
|
@@ -285,6 +412,20 @@ export function buildOpenAIChatFromGeminiResponse(payload) {
|
|
|
285
412
|
if (preservedOutputMeta) {
|
|
286
413
|
chatResp.__responses_output_text_meta = preservedOutputMeta;
|
|
287
414
|
}
|
|
415
|
+
const payloadSnapshot = consumeResponsesPayloadSnapshot(chatResp.id);
|
|
416
|
+
if (payloadSnapshot) {
|
|
417
|
+
registerResponsesPayloadSnapshot(chatResp.id, payloadSnapshot);
|
|
418
|
+
if (typeof chatResp.request_id !== 'string') {
|
|
419
|
+
chatResp.request_id = chatResp.id;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
const passthroughPayload = consumeResponsesPassthrough(chatResp.id);
|
|
423
|
+
if (passthroughPayload) {
|
|
424
|
+
registerResponsesPassthrough(chatResp.id, passthroughPayload);
|
|
425
|
+
if (typeof chatResp.request_id !== 'string') {
|
|
426
|
+
chatResp.request_id = chatResp.id;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
288
429
|
return chatResp;
|
|
289
430
|
}
|
|
290
431
|
export function buildGeminiFromOpenAIChat(chatResp) {
|
|
@@ -384,7 +525,12 @@ export function buildGeminiFromOpenAIChat(chatResp) {
|
|
|
384
525
|
const id = typeof tc.id === 'string' ? String(tc.id) : undefined;
|
|
385
526
|
if (id)
|
|
386
527
|
functionCall.id = id;
|
|
387
|
-
|
|
528
|
+
const thoughtSignature = extractThoughtSignatureFromToolCall(tc) ?? DUMMY_THOUGHT_SIGNATURE;
|
|
529
|
+
const partEntry = { functionCall };
|
|
530
|
+
if (thoughtSignature) {
|
|
531
|
+
partEntry.thoughtSignature = thoughtSignature;
|
|
532
|
+
}
|
|
533
|
+
parts.push(partEntry);
|
|
388
534
|
}
|
|
389
535
|
const candidate = {
|
|
390
536
|
content: {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export function applyAutoThinking(payload, config) {
|
|
2
|
+
if (!config) {
|
|
3
|
+
return payload;
|
|
4
|
+
}
|
|
5
|
+
const record = payload;
|
|
6
|
+
const modelId = typeof record.model === 'string' ? record.model.toLowerCase().trim() : '';
|
|
7
|
+
if (!modelId) {
|
|
8
|
+
return payload;
|
|
9
|
+
}
|
|
10
|
+
const prefixes = config.modelPrefixes ?? [];
|
|
11
|
+
const exclude = config.excludePrefixes ?? [];
|
|
12
|
+
const matches = prefixes.length === 0
|
|
13
|
+
? true
|
|
14
|
+
: prefixes.some(prefix => modelId.startsWith(prefix.toLowerCase()));
|
|
15
|
+
const excluded = exclude.some(prefix => modelId.startsWith(prefix.toLowerCase()));
|
|
16
|
+
if (!matches || excluded) {
|
|
17
|
+
return payload;
|
|
18
|
+
}
|
|
19
|
+
const thinkingNode = record.thinking;
|
|
20
|
+
if (thinkingNode && typeof thinkingNode === 'object') {
|
|
21
|
+
return payload;
|
|
22
|
+
}
|
|
23
|
+
record.thinking = { type: 'enabled' };
|
|
24
|
+
return payload;
|
|
25
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type MappingType = 'string' | 'number' | 'boolean' | 'object' | 'array';
|
|
2
|
+
export interface FieldMapping {
|
|
3
|
+
sourcePath: string;
|
|
4
|
+
targetPath: string;
|
|
5
|
+
type: MappingType;
|
|
6
|
+
transform?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface FieldMappingConfig {
|
|
9
|
+
incomingMappings: FieldMapping[];
|
|
10
|
+
outgoingMappings: FieldMapping[];
|
|
11
|
+
}
|
|
12
|
+
type UnknownRecord = Record<string, unknown>;
|
|
13
|
+
export declare function applyFieldMappings(payload: UnknownRecord, mappings: FieldMapping[]): UnknownRecord;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
const MODEL_PREFIX_NORMALIZATION = {
|
|
2
|
+
'gpt-': 'glm-'
|
|
3
|
+
};
|
|
4
|
+
const FINISH_REASON_MAP = {
|
|
5
|
+
tool_calls: 'tool_calls',
|
|
6
|
+
stop: 'stop',
|
|
7
|
+
length: 'length',
|
|
8
|
+
sensitive: 'content_filter',
|
|
9
|
+
network_error: 'error'
|
|
10
|
+
};
|
|
11
|
+
function isRecord(value) {
|
|
12
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
13
|
+
}
|
|
14
|
+
export function applyFieldMappings(payload, mappings) {
|
|
15
|
+
const result = { ...payload };
|
|
16
|
+
for (const mapping of mappings) {
|
|
17
|
+
applySingleMapping(result, mapping);
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
function applySingleMapping(root, mapping) {
|
|
22
|
+
const sourceValue = getNestedProperty(root, mapping.sourcePath);
|
|
23
|
+
if (sourceValue === undefined) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const transformed = convertType(applyTransform(sourceValue, mapping.transform), mapping.type);
|
|
27
|
+
setNestedProperty(root, mapping.targetPath, transformed);
|
|
28
|
+
}
|
|
29
|
+
function applyTransform(value, transform) {
|
|
30
|
+
if (!transform) {
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
switch (transform) {
|
|
34
|
+
case 'timestamp':
|
|
35
|
+
return typeof value === 'number' ? value : Date.now();
|
|
36
|
+
case 'lowercase':
|
|
37
|
+
return typeof value === 'string' ? value.toLowerCase() : value;
|
|
38
|
+
case 'uppercase':
|
|
39
|
+
return typeof value === 'string' ? value.toUpperCase() : value;
|
|
40
|
+
case 'normalizeModelName':
|
|
41
|
+
if (typeof value === 'string') {
|
|
42
|
+
for (const [prefix, replacement] of Object.entries(MODEL_PREFIX_NORMALIZATION)) {
|
|
43
|
+
if (value.startsWith(prefix)) {
|
|
44
|
+
return value.replace(prefix, replacement);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return value;
|
|
49
|
+
case 'normalizeFinishReason':
|
|
50
|
+
if (typeof value === 'string') {
|
|
51
|
+
return FINISH_REASON_MAP[value] ?? value;
|
|
52
|
+
}
|
|
53
|
+
return value;
|
|
54
|
+
default:
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function convertType(value, targetType) {
|
|
59
|
+
if (value === null || value === undefined) {
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
switch (targetType) {
|
|
63
|
+
case 'string':
|
|
64
|
+
return String(value);
|
|
65
|
+
case 'number': {
|
|
66
|
+
const num = Number(value);
|
|
67
|
+
return Number.isNaN(num) ? 0 : num;
|
|
68
|
+
}
|
|
69
|
+
case 'boolean':
|
|
70
|
+
return Boolean(value);
|
|
71
|
+
case 'object':
|
|
72
|
+
return isRecord(value) ? value : {};
|
|
73
|
+
case 'array':
|
|
74
|
+
return Array.isArray(value) ? value : [value];
|
|
75
|
+
default:
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function getNestedProperty(obj, pathExpression) {
|
|
80
|
+
const keys = pathExpression.split('.');
|
|
81
|
+
if (pathExpression.includes('[*]')) {
|
|
82
|
+
return getWildcardProperty(obj, keys);
|
|
83
|
+
}
|
|
84
|
+
return keys.reduce((current, key) => {
|
|
85
|
+
if (!isRecord(current)) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
return current[key];
|
|
89
|
+
}, obj);
|
|
90
|
+
}
|
|
91
|
+
function getWildcardProperty(obj, keys) {
|
|
92
|
+
const results = [];
|
|
93
|
+
const processWildcard = (current, keyIndex) => {
|
|
94
|
+
if (keyIndex >= keys.length) {
|
|
95
|
+
results.push(current);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const key = keys[keyIndex];
|
|
99
|
+
if (key === '[*]') {
|
|
100
|
+
if (Array.isArray(current)) {
|
|
101
|
+
current.forEach(item => processWildcard(item, keyIndex + 1));
|
|
102
|
+
}
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (isRecord(current) && current[key] !== undefined) {
|
|
106
|
+
processWildcard(current[key], keyIndex + 1);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
processWildcard(obj, 0);
|
|
110
|
+
return results;
|
|
111
|
+
}
|
|
112
|
+
function setNestedProperty(obj, pathExpression, value) {
|
|
113
|
+
const keys = pathExpression.split('.');
|
|
114
|
+
if (pathExpression.includes('[*]')) {
|
|
115
|
+
setWildcardProperty(obj, keys, value);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const lastKey = keys.pop();
|
|
119
|
+
if (!lastKey) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const target = keys.reduce((current, key) => {
|
|
123
|
+
if (!isRecord(current[key])) {
|
|
124
|
+
current[key] = {};
|
|
125
|
+
}
|
|
126
|
+
return current[key];
|
|
127
|
+
}, obj);
|
|
128
|
+
target[lastKey] = value;
|
|
129
|
+
}
|
|
130
|
+
function setWildcardProperty(obj, keys, value) {
|
|
131
|
+
const processSetWildcard = (current, keyIndex) => {
|
|
132
|
+
if (keyIndex >= keys.length - 1) {
|
|
133
|
+
const lastKey = keys[keys.length - 1].replace('[*]', '');
|
|
134
|
+
if (Array.isArray(current)) {
|
|
135
|
+
current.forEach(item => {
|
|
136
|
+
if (isRecord(item)) {
|
|
137
|
+
item[lastKey] = value;
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const key = keys[keyIndex];
|
|
144
|
+
if (key === '[*]') {
|
|
145
|
+
if (Array.isArray(current)) {
|
|
146
|
+
current.forEach(item => processSetWildcard(item, keyIndex + 1));
|
|
147
|
+
}
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (isRecord(current)) {
|
|
151
|
+
processSetWildcard(current[key], keyIndex + 1);
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
processSetWildcard(obj, 0);
|
|
155
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { JsonObject } from '../../hub/types/json.js';
|
|
2
|
+
import type { AdapterContext } from '../../hub/types/chat-envelope.js';
|
|
3
|
+
/**
|
|
4
|
+
* Gemini web_search 请求适配(作用于 Gemini 请求 payload,而不是 ChatEnvelope):
|
|
5
|
+
*
|
|
6
|
+
* - 仅在 routeId 以 `web_search` 开头时生效(来自 AdapterContext.routeId);
|
|
7
|
+
* - 针对 Gemini 请求中的 `tools` 字段进行清洗:
|
|
8
|
+
* - 保留 name === 'web_search' 的 functionDeclarations(如果存在);
|
|
9
|
+
* - 丢弃其它 Codex 自身工具(exec_command / MCP 等),避免 Cloud Code 报
|
|
10
|
+
* “Multiple tools are supported only when they are all search tools.”;
|
|
11
|
+
* - 如果清洗后没有任何工具,则删除 `tools` 字段。
|
|
12
|
+
*
|
|
13
|
+
* 注意:
|
|
14
|
+
* - 这里处理的是 llmswitch-core 为 gemini-chat 构造的中间 payload(buildGeminiRequestFromChat 输出);
|
|
15
|
+
* - 对于 Gemini CLI 后续在传输层添加的 googleSearch 工具,本适配不负责构造或修改。
|
|
16
|
+
*/
|
|
17
|
+
export declare function applyGeminiWebSearchCompat(payload: JsonObject, adapterContext?: AdapterContext): JsonObject;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
2
|
+
/**
|
|
3
|
+
* Gemini web_search 请求适配(作用于 Gemini 请求 payload,而不是 ChatEnvelope):
|
|
4
|
+
*
|
|
5
|
+
* - 仅在 routeId 以 `web_search` 开头时生效(来自 AdapterContext.routeId);
|
|
6
|
+
* - 针对 Gemini 请求中的 `tools` 字段进行清洗:
|
|
7
|
+
* - 保留 name === 'web_search' 的 functionDeclarations(如果存在);
|
|
8
|
+
* - 丢弃其它 Codex 自身工具(exec_command / MCP 等),避免 Cloud Code 报
|
|
9
|
+
* “Multiple tools are supported only when they are all search tools.”;
|
|
10
|
+
* - 如果清洗后没有任何工具,则删除 `tools` 字段。
|
|
11
|
+
*
|
|
12
|
+
* 注意:
|
|
13
|
+
* - 这里处理的是 llmswitch-core 为 gemini-chat 构造的中间 payload(buildGeminiRequestFromChat 输出);
|
|
14
|
+
* - 对于 Gemini CLI 后续在传输层添加的 googleSearch 工具,本适配不负责构造或修改。
|
|
15
|
+
*/
|
|
16
|
+
export function applyGeminiWebSearchCompat(payload, adapterContext) {
|
|
17
|
+
const routeId = typeof adapterContext?.routeId === 'string' ? adapterContext.routeId : '';
|
|
18
|
+
if (!routeId || !routeId.toLowerCase().startsWith('web_search')) {
|
|
19
|
+
return payload;
|
|
20
|
+
}
|
|
21
|
+
const cloned = { ...payload };
|
|
22
|
+
// 对于 Gemini Chat 后端,请求根节点不支持自定义 `web_search` 字段,
|
|
23
|
+
// 统一在 compat 层移除,避免触发
|
|
24
|
+
// "Unknown name \"web_search\" at 'request': Cannot find field." 错误。
|
|
25
|
+
if (cloned.web_search !== undefined) {
|
|
26
|
+
delete cloned.web_search;
|
|
27
|
+
}
|
|
28
|
+
const toolsRaw = cloned.tools;
|
|
29
|
+
// 当 web_search 路由下完全没有 tools 时,为 Gemini 搜索模型注入最小 googleSearch 工具,
|
|
30
|
+
// 保持与 gcli2api 类似的“搜索模型自动启用 Search 工具”行为。
|
|
31
|
+
if (!Array.isArray(toolsRaw)) {
|
|
32
|
+
cloned.tools = [{ googleSearch: {} }];
|
|
33
|
+
return cloned;
|
|
34
|
+
}
|
|
35
|
+
const nextTools = [];
|
|
36
|
+
for (const entry of toolsRaw) {
|
|
37
|
+
if (!isRecord(entry))
|
|
38
|
+
continue;
|
|
39
|
+
// 1) 保留 name === 'web_search' 的 functionDeclarations(单函数声明)。
|
|
40
|
+
const decls = Array.isArray(entry.functionDeclarations)
|
|
41
|
+
? entry.functionDeclarations
|
|
42
|
+
: [];
|
|
43
|
+
const webSearchDecls = decls.filter((fn) => {
|
|
44
|
+
if (!isRecord(fn))
|
|
45
|
+
return false;
|
|
46
|
+
const name = typeof fn.name === 'string' ? fn.name.trim().toLowerCase() : '';
|
|
47
|
+
return name === 'web_search';
|
|
48
|
+
});
|
|
49
|
+
if (webSearchDecls.length) {
|
|
50
|
+
nextTools.push({
|
|
51
|
+
functionDeclarations: webSearchDecls
|
|
52
|
+
});
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
// 2) 若上游已经构造了 googleSearch 工具,则保留。
|
|
56
|
+
if (isRecord(entry.googleSearch)) {
|
|
57
|
+
nextTools.push({ googleSearch: entry.googleSearch });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (nextTools.length > 0) {
|
|
61
|
+
cloned.tools = nextTools;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
// 3) 清洗后没有任何工具时,再次注入一个最小 googleSearch 工具,确保搜索模型仍然启用 Search。
|
|
65
|
+
cloned.tools = [{ googleSearch: {} }];
|
|
66
|
+
}
|
|
67
|
+
return cloned;
|
|
68
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
2
|
+
function normalizeImagePart(part) {
|
|
3
|
+
const rawType = typeof part.type === 'string' ? part.type.toLowerCase() : '';
|
|
4
|
+
if (rawType !== 'image' && rawType !== 'image_url') {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
// Try multiple locations for the URL, since different inbound
|
|
8
|
+
// protocols may populate different keys.
|
|
9
|
+
const imageUrlBlock = isRecord(part.image_url)
|
|
10
|
+
? part.image_url
|
|
11
|
+
: undefined;
|
|
12
|
+
let url;
|
|
13
|
+
if (imageUrlBlock && typeof imageUrlBlock.url === 'string') {
|
|
14
|
+
url = imageUrlBlock.url;
|
|
15
|
+
}
|
|
16
|
+
else if (typeof part.image_url === 'string') {
|
|
17
|
+
url = part.image_url;
|
|
18
|
+
}
|
|
19
|
+
else if (typeof part.url === 'string') {
|
|
20
|
+
url = part.url;
|
|
21
|
+
}
|
|
22
|
+
else if (typeof part.uri === 'string') {
|
|
23
|
+
url = part.uri;
|
|
24
|
+
}
|
|
25
|
+
else if (typeof part.data === 'string') {
|
|
26
|
+
// If caller passed a raw base64/data URI string, forward as-is.
|
|
27
|
+
url = part.data;
|
|
28
|
+
}
|
|
29
|
+
if (!url || !url.trim().length) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const normalized = {
|
|
33
|
+
type: 'image_url',
|
|
34
|
+
image_url: {
|
|
35
|
+
url: url.trim()
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
// Preserve a best-effort "detail" field when present.
|
|
39
|
+
const detailValue = (imageUrlBlock && imageUrlBlock.detail) ?? part.detail;
|
|
40
|
+
if (typeof detailValue === 'string' && detailValue.trim().length) {
|
|
41
|
+
normalized.image_url.detail = detailValue.trim();
|
|
42
|
+
}
|
|
43
|
+
return normalized;
|
|
44
|
+
}
|
|
45
|
+
export function applyGlmImageContentTransform(payload) {
|
|
46
|
+
const root = structuredClone(payload);
|
|
47
|
+
const messagesValue = root.messages;
|
|
48
|
+
if (!Array.isArray(messagesValue)) {
|
|
49
|
+
return root;
|
|
50
|
+
}
|
|
51
|
+
const messages = [];
|
|
52
|
+
for (const msg of messagesValue) {
|
|
53
|
+
if (!isRecord(msg)) {
|
|
54
|
+
messages.push(msg);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const contentValue = msg.content;
|
|
58
|
+
if (!Array.isArray(contentValue)) {
|
|
59
|
+
messages.push(msg);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const newContent = [];
|
|
63
|
+
for (const part of contentValue) {
|
|
64
|
+
if (!isRecord(part)) {
|
|
65
|
+
newContent.push(part);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const normalizedImage = normalizeImagePart(part);
|
|
69
|
+
if (normalizedImage) {
|
|
70
|
+
newContent.push(normalizedImage);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
newContent.push(part);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
messages.push({
|
|
77
|
+
...msg,
|
|
78
|
+
content: newContent
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
root.messages = messages;
|
|
82
|
+
return root;
|
|
83
|
+
}
|