@jsonstudio/rcc 0.89.1189 → 0.89.1348
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 +17 -0
- package/configsamples/config.json +426 -0
- package/configsamples/config.reference.json +58 -0
- package/configsamples/provider/crs/config.v1.json +46 -0
- package/configsamples/provider/glm/config.v1.json +81 -0
- package/configsamples/provider/glm-anthropic/config.v1.json +45 -0
- package/configsamples/provider/iflow/config.v1.json +74 -0
- package/configsamples/provider/kimi/config.v1.json +41 -0
- package/configsamples/provider/lmstudio/config.v1.json +101 -0
- package/configsamples/provider/mimo/config.v1.json +35 -0
- package/configsamples/provider/modelscope/config.v1.json +96 -0
- package/configsamples/provider/qwen/config.v1.json +38 -0
- package/configsamples/provider/tab/config.v1.json +50 -0
- package/configsamples/provider/tabglm/config.v1.json +49 -0
- package/dist/build-info.js +2 -2
- package/dist/cli/commands/code.js +12 -6
- package/dist/cli/commands/code.js.map +1 -1
- package/dist/cli/commands/config.d.ts +2 -1
- package/dist/cli/commands/config.js +74 -103
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/examples.js +6 -6
- package/dist/cli/commands/examples.js.map +1 -1
- package/dist/cli/commands/init.d.ts +28 -0
- package/dist/cli/commands/init.js +91 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/port.js +10 -2
- package/dist/cli/commands/port.js.map +1 -1
- package/dist/cli/commands/restart.js +5 -2
- package/dist/cli/commands/restart.js.map +1 -1
- package/dist/cli/commands/start.js +25 -22
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/status.js +1 -0
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/stop.js +1 -0
- package/dist/cli/commands/stop.js.map +1 -1
- package/dist/cli/config/bundled-docs.d.ts +20 -0
- package/dist/cli/config/bundled-docs.js +91 -0
- package/dist/cli/config/bundled-docs.js.map +1 -0
- package/dist/cli/config/init-config.d.ts +36 -0
- package/dist/cli/config/init-config.js +180 -0
- package/dist/cli/config/init-config.js.map +1 -0
- package/dist/cli/config/init-provider-catalog.d.ts +8 -0
- package/dist/cli/config/init-provider-catalog.js +187 -0
- package/dist/cli/config/init-provider-catalog.js.map +1 -0
- package/dist/cli/register/init-command.d.ts +3 -0
- package/dist/cli/register/init-command.js +5 -0
- package/dist/cli/register/init-command.js.map +1 -0
- package/dist/cli.js +28 -3
- package/dist/cli.js.map +1 -1
- package/dist/client/gemini-cli/gemini-cli-protocol-client.js +1 -1
- package/dist/client/gemini-cli/gemini-cli-protocol-client.js.map +1 -1
- package/dist/config/risk-control-config.d.ts +94 -0
- package/dist/config/risk-control-config.js +196 -0
- package/dist/config/risk-control-config.js.map +1 -0
- package/dist/constants/index.d.ts +6 -0
- package/dist/constants/index.js +13 -0
- package/dist/constants/index.js.map +1 -1
- package/dist/docs/daemon-admin-ui.html +2113 -190
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/manager/modules/health/index.d.ts +1 -1
- package/dist/manager/modules/quota/antigravity-quota-manager.d.ts +70 -0
- package/dist/manager/modules/quota/antigravity-quota-manager.js +442 -0
- package/dist/manager/modules/quota/antigravity-quota-manager.js.map +1 -0
- package/dist/manager/modules/quota/index.d.ts +3 -127
- package/dist/manager/modules/quota/index.js +2 -1093
- package/dist/manager/modules/quota/index.js.map +1 -1
- package/dist/manager/modules/quota/provider-key-normalization.d.ts +3 -0
- package/dist/manager/modules/quota/provider-key-normalization.js +155 -0
- package/dist/manager/modules/quota/provider-key-normalization.js.map +1 -0
- package/dist/manager/modules/quota/provider-quota-daemon.cooldown.d.ts +9 -0
- package/dist/manager/modules/quota/provider-quota-daemon.cooldown.js +115 -0
- package/dist/manager/modules/quota/provider-quota-daemon.cooldown.js.map +1 -0
- package/dist/manager/modules/quota/provider-quota-daemon.d.ts +77 -0
- package/dist/manager/modules/quota/provider-quota-daemon.events.d.ts +12 -0
- package/dist/manager/modules/quota/provider-quota-daemon.events.js +237 -0
- package/dist/manager/modules/quota/provider-quota-daemon.events.js.map +1 -0
- package/dist/manager/modules/quota/provider-quota-daemon.js +404 -0
- package/dist/manager/modules/quota/provider-quota-daemon.js.map +1 -0
- package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.d.ts +11 -0
- package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.js +189 -0
- package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.js.map +1 -0
- package/dist/manager/modules/quota/provider-quota-daemon.snapshot.d.ts +8 -0
- package/dist/manager/modules/quota/provider-quota-daemon.snapshot.js +96 -0
- package/dist/manager/modules/quota/provider-quota-daemon.snapshot.js.map +1 -0
- package/dist/manager/modules/quota/provider-quota-daemon.view.d.ts +19 -0
- package/dist/manager/modules/quota/provider-quota-daemon.view.js +37 -0
- package/dist/manager/modules/quota/provider-quota-daemon.view.js.map +1 -0
- package/dist/manager/modules/routing/index.d.ts +1 -0
- package/dist/manager/modules/routing/index.js +11 -25
- package/dist/manager/modules/routing/index.js.map +1 -1
- package/dist/manager/quota/provider-quota-center.d.ts +2 -0
- package/dist/manager/quota/provider-quota-center.js +80 -82
- package/dist/manager/quota/provider-quota-center.js.map +1 -1
- package/dist/modules/llmswitch/bridge.d.ts +16 -18
- package/dist/modules/llmswitch/bridge.js +314 -71
- package/dist/modules/llmswitch/bridge.js.map +1 -1
- package/dist/modules/llmswitch/core-loader.d.ts +4 -2
- package/dist/modules/llmswitch/core-loader.js +32 -20
- package/dist/modules/llmswitch/core-loader.js.map +1 -1
- package/dist/modules/pipeline/utils/colored-logger.js +3 -2
- package/dist/modules/pipeline/utils/colored-logger.js.map +1 -1
- package/dist/modules/pipeline/utils/debug-logger.js +1 -1
- package/dist/modules/pipeline/utils/debug-logger.js.map +1 -1
- package/dist/providers/auth/iflow-cookie-auth.js +0 -2
- package/dist/providers/auth/iflow-cookie-auth.js.map +1 -1
- package/dist/providers/auth/oauth-lifecycle.js +2 -23
- package/dist/providers/auth/oauth-lifecycle.js.map +1 -1
- package/dist/providers/core/config/camoufox-launcher.js +35 -4
- package/dist/providers/core/config/camoufox-launcher.js.map +1 -1
- package/dist/providers/core/runtime/antigravity-quota-client.js +6 -3
- package/dist/providers/core/runtime/antigravity-quota-client.js.map +1 -1
- package/dist/providers/core/runtime/base-provider.d.ts +2 -2
- package/dist/providers/core/runtime/base-provider.js +74 -69
- package/dist/providers/core/runtime/base-provider.js.map +1 -1
- package/dist/providers/core/runtime/gemini-cli-http-provider.js +6 -4
- package/dist/providers/core/runtime/gemini-cli-http-provider.js.map +1 -1
- package/dist/providers/core/runtime/http-request-executor.js +2 -2
- package/dist/providers/core/runtime/http-request-executor.js.map +1 -1
- package/dist/providers/core/runtime/http-transport-provider.d.ts +14 -0
- package/dist/providers/core/runtime/http-transport-provider.js +111 -5
- package/dist/providers/core/runtime/http-transport-provider.js.map +1 -1
- package/dist/providers/core/runtime/provider-error-classifier.js +10 -0
- package/dist/providers/core/runtime/provider-error-classifier.js.map +1 -1
- package/dist/providers/core/runtime/provider-factory.js +7 -5
- package/dist/providers/core/runtime/provider-factory.js.map +1 -1
- package/dist/providers/core/runtime/provider-runtime-metadata.d.ts +6 -0
- package/dist/providers/core/runtime/provider-runtime-metadata.js.map +1 -1
- package/dist/providers/core/runtime/responses-provider.d.ts +1 -7
- package/dist/providers/core/runtime/responses-provider.js +12 -93
- package/dist/providers/core/runtime/responses-provider.js.map +1 -1
- package/dist/providers/core/strategies/oauth-auth-code-flow.js +12 -8
- package/dist/providers/core/strategies/oauth-auth-code-flow.js.map +1 -1
- package/dist/providers/core/utils/http-client.js +16 -3
- package/dist/providers/core/utils/http-client.js.map +1 -1
- package/dist/providers/core/utils/provider-error-logger.d.ts +1 -1
- package/dist/providers/core/utils/provider-error-reporter.d.ts +3 -1
- package/dist/providers/core/utils/provider-error-reporter.js +3 -0
- package/dist/providers/core/utils/provider-error-reporter.js.map +1 -1
- package/dist/providers/core/utils/snapshot-writer.js +1 -4
- package/dist/providers/core/utils/snapshot-writer.js.map +1 -1
- package/dist/providers/mock/mock-provider-runtime.js +57 -27
- package/dist/providers/mock/mock-provider-runtime.js.map +1 -1
- package/dist/scripts/camoufox/launch-auth.mjs +193 -58
- package/dist/server/handlers/handler-utils.js +3 -2
- package/dist/server/handlers/handler-utils.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin/auth-handler.d.ts +2 -0
- package/dist/server/runtime/http-server/daemon-admin/auth-handler.js +103 -0
- package/dist/server/runtime/http-server/daemon-admin/auth-handler.js.map +1 -0
- package/dist/server/runtime/http-server/daemon-admin/auth-session.d.ts +5 -0
- package/dist/server/runtime/http-server/daemon-admin/auth-session.js +77 -0
- package/dist/server/runtime/http-server/daemon-admin/auth-session.js.map +1 -0
- package/dist/server/runtime/http-server/daemon-admin/auth-store.d.ts +18 -0
- package/dist/server/runtime/http-server/daemon-admin/auth-store.js +89 -0
- package/dist/server/runtime/http-server/daemon-admin/auth-store.js.map +1 -0
- package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js +1 -2
- package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin/providers-handler.js +226 -24
- package/dist/server/runtime/http-server/daemon-admin/providers-handler.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin/quota-handler.js +47 -8
- package/dist/server/runtime/http-server/daemon-admin/quota-handler.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin/restart-handler.js +1 -1
- package/dist/server/runtime/http-server/daemon-admin/restart-handler.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin/stats-handler.js +1 -1
- package/dist/server/runtime/http-server/daemon-admin/stats-handler.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin/status-handler.js +68 -4
- package/dist/server/runtime/http-server/daemon-admin/status-handler.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin-routes.d.ts +3 -4
- package/dist/server/runtime/http-server/daemon-admin-routes.js +9 -14
- package/dist/server/runtime/http-server/daemon-admin-routes.js.map +1 -1
- package/dist/server/runtime/http-server/executor-metadata.js +1 -1
- package/dist/server/runtime/http-server/executor-metadata.js.map +1 -1
- package/dist/server/runtime/http-server/executor-response.js +0 -16
- package/dist/server/runtime/http-server/executor-response.js.map +1 -1
- package/dist/server/runtime/http-server/hub-shadow-compare.d.ts +18 -0
- package/dist/server/runtime/http-server/hub-shadow-compare.js +256 -0
- package/dist/server/runtime/http-server/hub-shadow-compare.js.map +1 -0
- package/dist/server/runtime/http-server/index.d.ts +7 -2
- package/dist/server/runtime/http-server/index.js +287 -49
- package/dist/server/runtime/http-server/index.js.map +1 -1
- package/dist/server/runtime/http-server/middleware.js +19 -1
- package/dist/server/runtime/http-server/middleware.js.map +1 -1
- package/dist/server/runtime/http-server/request-executor.js +10 -19
- package/dist/server/runtime/http-server/request-executor.js.map +1 -1
- package/dist/server/runtime/http-server/routes.js +8 -2
- package/dist/server/runtime/http-server/routes.js.map +1 -1
- package/dist/server/runtime/http-server/session-dir.d.ts +2 -0
- package/dist/server/runtime/http-server/session-dir.js +59 -0
- package/dist/server/runtime/http-server/session-dir.js.map +1 -0
- package/dist/server/runtime/http-server/types.d.ts +0 -4
- package/dist/server/utils/utf8-chunk-buffer.js +6 -3
- package/dist/server/utils/utf8-chunk-buffer.js.map +1 -1
- package/dist/server/utils/warmup-storm-tracker.js +1 -1
- package/dist/server/utils/warmup-storm-tracker.js.map +1 -1
- package/dist/server-factory.d.ts +6 -28
- package/dist/server-factory.js +8 -93
- package/dist/server-factory.js.map +1 -1
- package/dist/token-daemon/index.js +2 -2
- package/dist/token-daemon/index.js.map +1 -1
- package/dist/token-daemon/provider-registry.js +0 -1
- package/dist/token-daemon/provider-registry.js.map +1 -1
- package/dist/token-daemon/server-utils.js +8 -9
- package/dist/token-daemon/server-utils.js.map +1 -1
- package/dist/token-daemon/token-utils.js +1 -1
- package/dist/token-daemon/token-utils.js.map +1 -1
- package/dist/tools/semantic-replay.js +2 -2
- package/dist/tools/semantic-replay.js.map +1 -1
- package/dist/tools/stats-request-events.d.ts +1 -1
- package/dist/tools/stats-usage.js +6 -3
- package/dist/tools/stats-usage.js.map +1 -1
- package/dist/utils/errorsamples.d.ts +5 -0
- package/dist/utils/errorsamples.js +27 -0
- package/dist/utils/errorsamples.js.map +1 -0
- package/dist/utils/llms-engine-shadow.d.ts +19 -0
- package/dist/utils/llms-engine-shadow.js +209 -0
- package/dist/utils/llms-engine-shadow.js.map +1 -0
- package/dist/utils/runtime-versions.d.ts +1 -0
- package/dist/utils/runtime-versions.js +39 -0
- package/dist/utils/runtime-versions.js.map +1 -0
- package/docs/ARCHITECTURE.md +402 -0
- package/docs/CODEX_AND_CLAUDE_CODE.md +69 -0
- package/docs/CONFIG_ARCHITECTURE.md +517 -0
- package/docs/ERROR_HANDLING_AUDIT.md +0 -0
- package/docs/GCLI2API_PARITY_GAPS.md +98 -0
- package/docs/INSTALLATION_AND_QUICKSTART.md +74 -0
- package/docs/INSTRUCTION_MARKUP.md +89 -0
- package/docs/MODULE_ENHANCEMENT_SYSTEM.md +666 -0
- package/docs/PORTS.md +36 -0
- package/docs/PROVIDERS_BUILTIN.md +111 -0
- package/docs/PROVIDER_TYPES.md +55 -0
- package/docs/SERVERTOOL_CLOCK_DESIGN.md +233 -0
- package/docs/USAGE_HANDLING_ANALYSIS.md +335 -0
- package/docs/USER_CONFIG_PARSER_CHANGES.md +175 -0
- package/docs/V3_INBOUND_OUTBOUND_DESIGN.md +86 -0
- package/docs/VIRTUAL_ROUTER_PRIORITY_AND_HEALTH.md +125 -0
- package/docs/anthropic-request-golden-samples.md +50 -0
- package/docs/ccr-alignment-enhancetool.md +105 -0
- package/docs/chat-glm-500-analysis.md +79 -0
- package/docs/chat-request-golden-samples.md +42 -0
- package/docs/chat-semantic-expansion-plan.md +82 -0
- package/docs/cli-command-inventory.md +76 -0
- package/docs/codex-samples-replay.md +50 -0
- package/docs/daemon-admin-api-design.md +350 -0
- package/docs/daemon-admin-module-structure.md +169 -0
- package/docs/daemon-admin-ui.html +3394 -0
- package/docs/debug-system-design.md +734 -0
- package/docs/debugging/gemini-sse-root-cause.md +52 -0
- package/docs/debugging/sse_encoding_failure_analysis.md +53 -0
- package/docs/dry-run/README.md +721 -0
- package/docs/error-handling-v2.md +92 -0
- package/docs/exec-command-guard-policy.example.v1.json +42 -0
- package/docs/fixes/gemini-protocol-mapping.md +57 -0
- package/docs/fixes/oauth-portal-timing-fix.md +202 -0
- package/docs/fixes/web-search-hop3-fix.md +265 -0
- package/docs/glm-api-reference.md +390 -0
- package/docs/glm-chat-completions.md +1779 -0
- package/docs/glm-history-inline-images.md +44 -0
- package/docs/golden-ci-library.md +66 -0
- package/docs/lmstudio-dry-run-summary.md +203 -0
- package/docs/lmstudio-tool-calling.md +214 -0
- package/docs/mapping-tables/anthropic-to-openai.json +290 -0
- package/docs/mapping-tables/iflow-to-openai.json +215 -0
- package/docs/mapping-tables/openai-passthrough.json +190 -0
- package/docs/mapping-tables/openai-to-iflow.json +227 -0
- package/docs/monitoring/Design.md +61 -0
- package/docs/multi-token-auth-guide.md +66 -0
- package/docs/oauth-authentication-guide.md +168 -0
- package/docs/oauth-iflow-implementation.md +153 -0
- package/docs/pipeline-routing-report.md +209 -0
- package/docs/plans/manager-daemon/PLAN.md +86 -0
- package/docs/plans/provider-config-v2-plan.md +176 -0
- package/docs/plans/provider-runtime-manager-plan.md +209 -0
- package/docs/plans/transparent-429-failover.md +89 -0
- package/docs/plans/unified-hub-framework-v1.md +245 -0
- package/docs/provider-config-v2-ui-design.md +181 -0
- package/docs/provider-quota-design.md +129 -0
- package/docs/providers/gemini-provider.md +62 -0
- package/docs/providers/lmstudio-v2-migration-report.md +102 -0
- package/docs/providers/provider-composite-design.md +142 -0
- package/docs/providers/provider-composite-testing.md +98 -0
- package/docs/providers/provider-type-only-migration.md +111 -0
- package/docs/rccx-wasm-migration.md +74 -0
- package/docs/refactoring/architecture-comparison-diagram.md +140 -0
- package/docs/refactoring/compatibility-v2-architecture-design.md +738 -0
- package/docs/refactoring/workflow-compatibility-refactoring-design.md +361 -0
- package/docs/reports/routing-classification-report.json +24 -0
- package/docs/reports/routing-classification-report.md +18 -0
- package/docs/reports/thinking-keywords-report.json +19 -0
- package/docs/responses/README.md +156 -0
- package/docs/responses-generic-provider.md +86 -0
- package/docs/responses-passthrough-provider-design.md +202 -0
- package/docs/routing-awrr-health-weighted-round-robin.md +179 -0
- package/docs/routing-instructions.md +393 -0
- package/docs/stop-message-auto.md +225 -0
- package/docs/streaming-flow.html +30 -0
- package/docs/streaming-flow.md +182 -0
- package/docs/token-daemon-preview.html +490 -0
- package/docs/token-refresh-daemon-plan.md +269 -0
- package/docs/transformation-tables/Gemini-FinishReason/345/256/214/346/225/264/350/275/254/346/215/242/350/241/250.json +233 -0
- package/docs/transformation-tables/README.md +225 -0
- package/docs/transformation-tables/claude-code-router-anthropic-to-gemini.json +283 -0
- package/docs/transformation-tables/claude-code-router-anthropic-to-openai.json +208 -0
- package/docs/transformation-tables/claude-code-router-openai-to-anthropic.json +261 -0
- package/docs/transformation-tables/claude-code-router-openai-to-gemini.json +208 -0
- package/docs/transformation-tables/claude-code-router-openai-to-lmstudio.json +182 -0
- package/docs/transformation-tables/claude-code-router-openai-to-ollama.json +250 -0
- package/docs/transformation-tables/claude-code-router-openai-to-textgenwebui.json +295 -0
- package/docs/transformation-tables/claude-code-router-provider-conversions.json +193 -0
- package/docs/transformation-tables//345/256/214/346/225/264/347/232/204/345/267/245/345/205/267/346/211/247/350/241/214/346/265/201/347/250/213/350/275/254/346/215/242/350/241/250.json +299 -0
- package/docs/transformation-tables//345/257/271/350/257/235/345/216/206/345/217/262/347/273/264/346/212/244/345/210/206/346/236/220.md +134 -0
- package/docs/transformation-tables//345/267/245/345/205/267/350/260/203/347/224/250/346/250/241/345/274/217/345/210/206/346/236/220.md +158 -0
- package/docs/transformation-tables//347/212/266/346/200/201/347/256/241/347/220/206/351/234/200/346/261/202/345/210/206/346/236/220.md +175 -0
- package/docs/transformation-tables//351/235/231/346/200/201/350/241/250vs/345/212/250/346/200/201/345/210/206/346/236/220.md +189 -0
- package/docs/transformation-tables//351/235/231/346/200/201/350/241/250/345/207/206/347/241/256/346/200/247/350/257/204/344/274/260.md +179 -0
- package/docs/transformation-tables//351/235/236/346/265/201/345/274/217/345/234/272/346/231/257/345/210/206/346/236/220.md +189 -0
- package/docs/v2-architecture/IMPLEMENTATION-ROADMAP.md +367 -0
- package/docs/v2-architecture/OPTIMIZED-DESIGN.md +827 -0
- package/docs/v2-architecture/PRERUN-CONNECTION-DESIGN.md +716 -0
- package/docs/v2-architecture/README.md +551 -0
- package/docs/verification/modelscope-verify.md +59 -0
- package/docs/web-search-service-design.md +322 -0
- package/package.json +12 -7
- package/scripts/camoufox/launch-auth.mjs +193 -58
- package/scripts/monitor-diff.mjs +126 -0
- package/scripts/pack-mode.mjs +19 -1
- package/scripts/pack-rcc.mjs +63 -0
- package/scripts/unified-hub-shadow-compare.mjs +33 -13
- package/scripts/verify-e2e-toolcall.mjs +115 -26
- package/dist/modules/llmswitch/pipeline-registry.d.ts +0 -57
- package/dist/modules/llmswitch/pipeline-registry.js +0 -229
- package/dist/modules/llmswitch/pipeline-registry.js.map +0 -1
- package/dist/server/RouteCodexServer.d.ts +0 -13
- package/dist/server/RouteCodexServer.js +0 -25
- package/dist/server/RouteCodexServer.js.map +0 -1
- package/dist/v2/conversion/hub/snapshot-recorder.d.ts +0 -12
- package/dist/v2/conversion/hub/snapshot-recorder.js +0 -22
- package/dist/v2/conversion/hub/snapshot-recorder.js.map +0 -1
|
@@ -0,0 +1,738 @@
|
|
|
1
|
+
# Compatibility V2 架构设计方案
|
|
2
|
+
|
|
3
|
+
## 🎯 设计目标
|
|
4
|
+
|
|
5
|
+
基于Provider V2的成功架构模式,设计全新的Compatibility V2模块,实现:
|
|
6
|
+
- **配置驱动的转换引擎** - 输入输出双向转换表驱动
|
|
7
|
+
- **Hook系统集成** - 完整的hook生命周期支持
|
|
8
|
+
- **模块化架构** - 清晰的职责分离和可扩展性
|
|
9
|
+
- **向后兼容** - 与现有系统完全兼容
|
|
10
|
+
|
|
11
|
+
## 🏗️ 整体架构设计
|
|
12
|
+
|
|
13
|
+
### 架构对比图
|
|
14
|
+
|
|
15
|
+
```mermaid
|
|
16
|
+
graph TB
|
|
17
|
+
subgraph "当前Compatibility V1 (问题状态)"
|
|
18
|
+
A1[glm-compatibility.ts 643行] --> |硬编码逻辑| B1[固定转换]
|
|
19
|
+
A2[field-mapping.ts 180行] --> |10种类型| B2[复杂映射]
|
|
20
|
+
A3[各provider兼容层] --> |重复实现| B3[代码重复]
|
|
21
|
+
|
|
22
|
+
style A1 fill:#ffcccc
|
|
23
|
+
style A2 fill:#ffcccc
|
|
24
|
+
style A3 fill:#ffcccc
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
subgraph "Compatibility V2 (目标架构)"
|
|
28
|
+
C1[BaseCompatibility] --> D1[配置驱动引擎]
|
|
29
|
+
C2[TransformationEngine] --> D2[双向转换表]
|
|
30
|
+
C3[HookIntegration] --> D3[生命周期hooks]
|
|
31
|
+
C4[ProfileRegistry] --> D4[provider配置档案]
|
|
32
|
+
|
|
33
|
+
style C1 fill:#ccffcc
|
|
34
|
+
style C2 fill:#ccffcc
|
|
35
|
+
style C3 fill:#ccffcc
|
|
36
|
+
style C4 fill:#ccffcc
|
|
37
|
+
end
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 📁 目录结构设计
|
|
41
|
+
|
|
42
|
+
### 完整目录结构
|
|
43
|
+
```
|
|
44
|
+
(历史实现,已下线)src/providers/compat/v2/
|
|
45
|
+
├── core/ # 核心抽象层
|
|
46
|
+
│ ├── base-compatibility.ts # 基础兼容性抽象类
|
|
47
|
+
│ ├── compatibility-factory.ts # 兼容性工厂
|
|
48
|
+
│ └── standard-compatibility.ts # 标准兼容性实现
|
|
49
|
+
├── engine/ # 转换引擎
|
|
50
|
+
│ ├── transformation-engine.ts # 配置驱动转换引擎
|
|
51
|
+
│ ├── bidirectional-mapper.ts # 双向映射器
|
|
52
|
+
│ └── field-transformer.ts # 字段转换器
|
|
53
|
+
├── config/ # 配置系统
|
|
54
|
+
│ ├── compatibility-profiles.ts # Provider配置档案
|
|
55
|
+
│ ├── transformation-tables.ts # 转换表定义
|
|
56
|
+
│ └── compatibility-hooks.ts # Hook配置
|
|
57
|
+
├── hooks/ # Hook系统
|
|
58
|
+
│ ├── hooks-integration.ts # Hook系统集成
|
|
59
|
+
│ ├── compatibility-hooks.ts # 兼容性专用hooks
|
|
60
|
+
│ └── hook-executor.ts # Hook执行器
|
|
61
|
+
├── strategies/ # 转换策略
|
|
62
|
+
│ ├── chat-http-provider.ts # OpenAI Chat 协议 Provider
|
|
63
|
+
│ ├── glm-strategy.ts # GLM特定策略
|
|
64
|
+
│ ├── qwen-strategy.ts # Qwen特定策略
|
|
65
|
+
│ └── iflow-strategy.ts # Iflow特定策略
|
|
66
|
+
├── utils/ # 工具类
|
|
67
|
+
│ ├── schema-validator.ts # Schema验证器
|
|
68
|
+
│ ├── type-converter.ts # 类型转换器
|
|
69
|
+
│ └── debug-helper.ts # 调试助手
|
|
70
|
+
├── api/ # API定义
|
|
71
|
+
│ ├── compatibility-types.ts # 类型定义
|
|
72
|
+
│ ├── transformation-config.ts # 转换配置接口
|
|
73
|
+
│ └── hook-config.ts # Hook配置接口
|
|
74
|
+
└── test/ # 测试文件
|
|
75
|
+
├── unit/ # 单元测试
|
|
76
|
+
├── integration/ # 集成测试
|
|
77
|
+
└── fixtures/ # 测试数据
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## 🔧 核心组件设计
|
|
81
|
+
|
|
82
|
+
### 1. BaseCompatibility 基础抽象类
|
|
83
|
+
|
|
84
|
+
**历史文件**: `src/providers/compat/v2/core/base-compatibility.ts`(现由 `sharedmodule/llmswitch-core/src/conversion/compat/*` 取代)
|
|
85
|
+
**职责**: 提供兼容性模块的通用抽象实现
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
export abstract class BaseCompatibility implements ICompatibilityV2 {
|
|
89
|
+
readonly id: string;
|
|
90
|
+
readonly abstract type: string;
|
|
91
|
+
readonly config: CompatibilityConfig;
|
|
92
|
+
|
|
93
|
+
protected dependencies: ModuleDependencies;
|
|
94
|
+
protected transformationEngine: TransformationEngine;
|
|
95
|
+
protected hookIntegration: HookIntegration;
|
|
96
|
+
protected profile: CompatibilityProfile;
|
|
97
|
+
|
|
98
|
+
constructor(config: CompatibilityConfig, dependencies: ModuleDependencies) {
|
|
99
|
+
this.id = `compatibility-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
100
|
+
this.config = config;
|
|
101
|
+
this.dependencies = dependencies;
|
|
102
|
+
|
|
103
|
+
// 初始化核心组件
|
|
104
|
+
this.profile = this.loadCompatibilityProfile();
|
|
105
|
+
this.transformationEngine = new TransformationEngine(this.profile);
|
|
106
|
+
this.hookIntegration = new HookIntegration(dependencies, this.id);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 抽象方法 - 子类实现
|
|
110
|
+
protected abstract loadCompatibilityProfile(): CompatibilityProfile;
|
|
111
|
+
protected abstract createStrategy(): TransformationStrategy;
|
|
112
|
+
|
|
113
|
+
// 通用实现
|
|
114
|
+
async initialize(): Promise<void> {
|
|
115
|
+
await this.transformationEngine.initialize();
|
|
116
|
+
await this.hookIntegration.initialize();
|
|
117
|
+
await this.onInitialize();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async processIncoming(request: UnknownObject): Promise<UnknownObject> {
|
|
121
|
+
const context = this.createContext('incoming');
|
|
122
|
+
|
|
123
|
+
// Hook: 请求预处理
|
|
124
|
+
const preprocessedRequest = await this.hookIntegration.executeHook(
|
|
125
|
+
'incoming_preprocessing',
|
|
126
|
+
request,
|
|
127
|
+
context
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
// 配置驱动转换
|
|
131
|
+
const transformedRequest = await this.transformationEngine.transform(
|
|
132
|
+
preprocessedRequest,
|
|
133
|
+
'incoming',
|
|
134
|
+
this.createStrategy()
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
// Hook: 转换后处理
|
|
138
|
+
const finalRequest = await this.hookIntegration.executeHook(
|
|
139
|
+
'incoming_postprocessing',
|
|
140
|
+
transformedRequest,
|
|
141
|
+
context
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
return finalRequest;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async processOutgoing(response: UnknownObject): Promise<UnknownObject> {
|
|
148
|
+
const context = this.createContext('outgoing');
|
|
149
|
+
|
|
150
|
+
// Hook: 响应预处理
|
|
151
|
+
const preprocessedResponse = await this.hookIntegration.executeHook(
|
|
152
|
+
'outgoing_preprocessing',
|
|
153
|
+
response,
|
|
154
|
+
context
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
// 配置驱动转换
|
|
158
|
+
const transformedResponse = await this.transformationEngine.transform(
|
|
159
|
+
preprocessedResponse,
|
|
160
|
+
'outgoing',
|
|
161
|
+
this.createStrategy()
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
// Hook: 响应后处理
|
|
165
|
+
const finalResponse = await this.hookIntegration.executeHook(
|
|
166
|
+
'outgoing_postprocessing',
|
|
167
|
+
transformedResponse,
|
|
168
|
+
context
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
return finalResponse;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
> 注:自 ProviderComposite 引入后,生产蓝图不再显式编排 compatibility 节点,兼容处理在 Provider 内部通过 composite 执行;
|
|
177
|
+
> 现有兼容模块(GLM/LMStudio/iFlow 等)可被 openai-family 聚合器以“适配器”方式复用,职责保持为最小字段修剪/映射/黑名单,避免工具语义和 SSE 路径改动。
|
|
178
|
+
|
|
179
|
+
### 2. 配置驱动转换引擎
|
|
180
|
+
|
|
181
|
+
**历史文件**: `src/providers/compat/v2/engine/transformation-engine.ts`
|
|
182
|
+
**职责**: 基于配置表的双向转换引擎
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
export class TransformationEngine {
|
|
186
|
+
private profile: CompatibilityProfile;
|
|
187
|
+
private bidirectionalMapper: BidirectionalMapper;
|
|
188
|
+
private fieldTransformer: FieldTransformer;
|
|
189
|
+
|
|
190
|
+
constructor(profile: CompatibilityProfile) {
|
|
191
|
+
this.profile = profile;
|
|
192
|
+
this.bidirectionalMapper = new BidirectionalMapper(profile.transformationTables);
|
|
193
|
+
this.fieldTransformer = new FieldTransformer(profile.fieldConfig);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
async transform(
|
|
197
|
+
data: UnknownObject,
|
|
198
|
+
direction: 'incoming' | 'outgoing',
|
|
199
|
+
strategy: TransformationStrategy
|
|
200
|
+
): Promise<UnknownObject> {
|
|
201
|
+
// 1. 获取转换表
|
|
202
|
+
const transformationTable = this.getTransformationTable(direction, strategy.getType());
|
|
203
|
+
|
|
204
|
+
// 2. 执行字段映射
|
|
205
|
+
const mappedData = await this.bidirectionalMapper.map(data, transformationTable);
|
|
206
|
+
|
|
207
|
+
// 3. 执行类型转换
|
|
208
|
+
const transformedData = await this.fieldTransformer.transform(mappedData, direction);
|
|
209
|
+
|
|
210
|
+
// 4. 应用策略特定逻辑
|
|
211
|
+
const strategyProcessedData = await strategy.process(transformedData, direction);
|
|
212
|
+
|
|
213
|
+
return strategyProcessedData;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private getTransformationTable(
|
|
217
|
+
direction: 'incoming' | 'outgoing',
|
|
218
|
+
providerType: string
|
|
219
|
+
): TransformationTable {
|
|
220
|
+
const tables = this.profile.transformationTables;
|
|
221
|
+
|
|
222
|
+
if (direction === 'incoming') {
|
|
223
|
+
return tables.incoming[providerType] || tables.incoming.default;
|
|
224
|
+
} else {
|
|
225
|
+
return tables.outgoing[providerType] || tables.outgoing.default;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### 3. 双向转换表配置
|
|
232
|
+
|
|
233
|
+
**历史文件**: `src/providers/compat/v2/config/transformation-tables.ts`
|
|
234
|
+
**职责**: 定义输入输出双向转换配置
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
export interface TransformationTable {
|
|
238
|
+
name: string;
|
|
239
|
+
description: string;
|
|
240
|
+
version: string;
|
|
241
|
+
fieldMappings: FieldMapping[];
|
|
242
|
+
typeConversions: TypeConversion[];
|
|
243
|
+
conditionalRules: ConditionalRule[];
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export interface FieldMapping {
|
|
247
|
+
sourcePath: string; // 源字段路径 (如: "usage.prompt_tokens")
|
|
248
|
+
targetPath: string; // 目标字段路径 (如: "usage.input_tokens")
|
|
249
|
+
direction: 'bidirectional' | 'incoming-only' | 'outgoing-only';
|
|
250
|
+
transform?: string; // 转换函数名称 (可选)
|
|
251
|
+
required?: boolean; // 是否必需字段
|
|
252
|
+
defaultValue?: any; // 默认值
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export interface TypeConversion {
|
|
256
|
+
sourceType: string; // 源类型 (如: "string")
|
|
257
|
+
targetType: string; // 目标类型 (如: "number")
|
|
258
|
+
conversionFunction: string; // 转换函数名称
|
|
259
|
+
conditions?: { // 转换条件
|
|
260
|
+
field?: string;
|
|
261
|
+
value?: any;
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// GLM Provider 转换表示例
|
|
266
|
+
export const GLM_TRANSFORMATION_TABLES: Record<string, TransformationTable> = {
|
|
267
|
+
incoming: {
|
|
268
|
+
name: 'glm-incoming',
|
|
269
|
+
description: 'GLM请求转换表',
|
|
270
|
+
version: '1.0.0',
|
|
271
|
+
fieldMappings: [
|
|
272
|
+
{
|
|
273
|
+
sourcePath: 'model',
|
|
274
|
+
targetPath: 'model',
|
|
275
|
+
direction: 'bidirectional',
|
|
276
|
+
required: true
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
sourcePath: 'thinking',
|
|
280
|
+
targetPath: 'thinking.enabled',
|
|
281
|
+
direction: 'incoming-only',
|
|
282
|
+
transform: 'convertThinkingConfig'
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
sourcePath: 'max_tokens',
|
|
286
|
+
targetPath: 'max_tokens',
|
|
287
|
+
direction: 'bidirectional',
|
|
288
|
+
typeConversion: 'ensureNumber'
|
|
289
|
+
}
|
|
290
|
+
],
|
|
291
|
+
typeConversions: [
|
|
292
|
+
{
|
|
293
|
+
sourceType: 'string',
|
|
294
|
+
targetType: 'number',
|
|
295
|
+
conversionFunction: 'stringToNumber',
|
|
296
|
+
conditions: {
|
|
297
|
+
field: 'max_tokens'
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
],
|
|
301
|
+
conditionalRules: [
|
|
302
|
+
{
|
|
303
|
+
condition: 'model.startsWith("glm-thinking")',
|
|
304
|
+
action: 'enableThinkingMode'
|
|
305
|
+
}
|
|
306
|
+
]
|
|
307
|
+
},
|
|
308
|
+
|
|
309
|
+
outgoing: {
|
|
310
|
+
name: 'glm-outgoing',
|
|
311
|
+
description: 'GLM响应转换表',
|
|
312
|
+
version: '1.0.0',
|
|
313
|
+
fieldMappings: [
|
|
314
|
+
{
|
|
315
|
+
sourcePath: 'usage.prompt_tokens',
|
|
316
|
+
targetPath: 'usage.input_tokens',
|
|
317
|
+
direction: 'outgoing-only'
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
sourcePath: 'usage.completion_tokens',
|
|
321
|
+
targetPath: 'usage.output_tokens',
|
|
322
|
+
direction: 'outgoing-only'
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
sourcePath: 'usage.total_tokens',
|
|
326
|
+
targetPath: 'usage.total_tokens',
|
|
327
|
+
direction: 'bidirectional'
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
sourcePath: 'created_at',
|
|
331
|
+
targetPath: 'created',
|
|
332
|
+
direction: 'outgoing-only',
|
|
333
|
+
typeConversion: 'timestampToUnix'
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
sourcePath: 'reasoning_content',
|
|
337
|
+
targetPath: 'reasoning_content',
|
|
338
|
+
direction: 'outgoing-only',
|
|
339
|
+
transform: 'processReasoningContent'
|
|
340
|
+
}
|
|
341
|
+
],
|
|
342
|
+
typeConversions: [],
|
|
343
|
+
conditionalRules: []
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### 4. Hook系统集成
|
|
349
|
+
|
|
350
|
+
**历史文件**: `src/providers/compat/v2/hooks/hooks-integration.ts`
|
|
351
|
+
**职责**: 集成兼容性模块的hook系统
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
export class HookIntegration {
|
|
355
|
+
private dependencies: ModuleDependencies;
|
|
356
|
+
private compatibilityId: string;
|
|
357
|
+
private hookSystem: any;
|
|
358
|
+
private registeredHooks: Map<string, CompatibilityHook> = new Map();
|
|
359
|
+
|
|
360
|
+
constructor(dependencies: ModuleDependencies, compatibilityId: string) {
|
|
361
|
+
this.dependencies = dependencies;
|
|
362
|
+
this.compatibilityId = compatibilityId;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
async initialize(): Promise<void> {
|
|
366
|
+
// 初始化hook系统 (复用provider v2的hook系统)
|
|
367
|
+
const { createHooksSystem } = require('../../../../hooks/index.js');
|
|
368
|
+
|
|
369
|
+
this.hookSystem = createHooksSystem({
|
|
370
|
+
maxConcurrentHooks: 8,
|
|
371
|
+
executionTimeout: 3000,
|
|
372
|
+
enableHealthCheck: true,
|
|
373
|
+
snapshotEnabled: true,
|
|
374
|
+
debugMode: true
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
await this.hookSystem.initialize();
|
|
378
|
+
await this.registerDefaultHooks();
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
async executeHook(
|
|
382
|
+
hookName: string,
|
|
383
|
+
data: UnknownObject,
|
|
384
|
+
context: CompatibilityContext
|
|
385
|
+
): Promise<UnknownObject> {
|
|
386
|
+
const hook = this.registeredHooks.get(hookName);
|
|
387
|
+
if (!hook) {
|
|
388
|
+
return data; // 如果hook不存在,直接返回原数据
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
try {
|
|
392
|
+
const result = await this.hookSystem.hookManager.executeHook({
|
|
393
|
+
name: hookName,
|
|
394
|
+
stage: hook.stage,
|
|
395
|
+
target: hook.target,
|
|
396
|
+
priority: hook.priority,
|
|
397
|
+
async execute(ctx: any, payload: any) {
|
|
398
|
+
return await hook.execute(payload, context);
|
|
399
|
+
}
|
|
400
|
+
}, 'compatibility-v2');
|
|
401
|
+
|
|
402
|
+
return result.data || data;
|
|
403
|
+
} catch (error) {
|
|
404
|
+
this.dependencies.logger?.logModule(this.compatibilityId, 'hook-execution-error', {
|
|
405
|
+
hookName,
|
|
406
|
+
error: error instanceof Error ? error.message : String(error)
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// 快速失败原则 - 不做fallback
|
|
410
|
+
throw error;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
private async registerDefaultHooks(): Promise<void> {
|
|
415
|
+
// 注册默认hooks
|
|
416
|
+
await this.registerHook({
|
|
417
|
+
name: 'request-validation',
|
|
418
|
+
stage: 'incoming_preprocessing',
|
|
419
|
+
target: 'request',
|
|
420
|
+
priority: 100,
|
|
421
|
+
execute: async (data: UnknownObject, context: CompatibilityContext) => {
|
|
422
|
+
return this.validateRequest(data);
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
await this.registerHook({
|
|
427
|
+
name: 'response-normalization',
|
|
428
|
+
stage: 'outgoing_postprocessing',
|
|
429
|
+
target: 'response',
|
|
430
|
+
priority: 200,
|
|
431
|
+
execute: async (data: UnknownObject, context: CompatibilityContext) => {
|
|
432
|
+
return this.normalizeResponse(data);
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
await this.registerHook({
|
|
437
|
+
name: 'debug-logging',
|
|
438
|
+
stage: 'outgoing_postprocessing',
|
|
439
|
+
target: 'response',
|
|
440
|
+
priority: 999,
|
|
441
|
+
execute: async (data: UnknownObject, context: CompatibilityContext) => {
|
|
442
|
+
this.logTransformation(context, data);
|
|
443
|
+
return data;
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
### 5. Provider策略实现
|
|
451
|
+
|
|
452
|
+
**历史文件**: `src/providers/compat/v2/strategies/glm-strategy.ts`
|
|
453
|
+
**职责**: GLM特定转换策略实现
|
|
454
|
+
|
|
455
|
+
```typescript
|
|
456
|
+
export class GLMStrategy implements TransformationStrategy {
|
|
457
|
+
readonly type = 'glm';
|
|
458
|
+
|
|
459
|
+
async process(data: UnknownObject, direction: 'incoming' | 'outgoing'): Promise<UnknownObject> {
|
|
460
|
+
if (direction === 'incoming') {
|
|
461
|
+
return this.processIncoming(data);
|
|
462
|
+
} else {
|
|
463
|
+
return this.processOutgoing(data);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
private async processIncoming(data: UnknownObject): Promise<UnknownObject> {
|
|
468
|
+
// GLM特有的incoming处理
|
|
469
|
+
const processed = { ...data };
|
|
470
|
+
|
|
471
|
+
// 处理thinking模式配置
|
|
472
|
+
if ((processed as any).thinking) {
|
|
473
|
+
(processed as any).thinking = this.normalizeThinkingConfig((processed as any).thinking);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// 处理GLM特有参数
|
|
477
|
+
if ((processed as any).reasoning_content) {
|
|
478
|
+
// 移除GLM特有字段,避免传递到provider
|
|
479
|
+
delete (processed as any).reasoning_content;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
return processed;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
private async processOutgoing(data: UnknownObject): Promise<UnknownObject> {
|
|
486
|
+
// GLM特有的outgoing处理
|
|
487
|
+
const processed = { ...data };
|
|
488
|
+
|
|
489
|
+
// 标准化usage字段
|
|
490
|
+
if ((processed as any).usage) {
|
|
491
|
+
(processed as any).usage = this.normalizeUsageFields((processed as any).usage);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// 标准化时间戳
|
|
495
|
+
if ((processed as any).created_at) {
|
|
496
|
+
(processed as any).created = (processed as any).created_at;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
return processed;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
private normalizeThinkingConfig(thinking: any): any {
|
|
503
|
+
// 标准化thinking配置格式
|
|
504
|
+
if (typeof thinking === 'boolean') {
|
|
505
|
+
return { enabled: thinking };
|
|
506
|
+
}
|
|
507
|
+
if (typeof thinking === 'object') {
|
|
508
|
+
return {
|
|
509
|
+
enabled: thinking.enabled ?? true,
|
|
510
|
+
max_tokens: thinking.max_tokens,
|
|
511
|
+
temperature: thinking.temperature
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
return { enabled: false };
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
private normalizeUsageFields(usage: any): any {
|
|
518
|
+
// GLM usage字段标准化
|
|
519
|
+
return {
|
|
520
|
+
prompt_tokens: usage.prompt_tokens || usage.input_tokens || 0,
|
|
521
|
+
completion_tokens: usage.completion_tokens || usage.output_tokens || 0,
|
|
522
|
+
total_tokens: usage.total_tokens || 0
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
## 🔄 向后兼容性保证
|
|
529
|
+
|
|
530
|
+
### V1到V2迁移适配器
|
|
531
|
+
|
|
532
|
+
**历史文件**: `src/providers/compat/v2/core/v1-adapter.ts`
|
|
533
|
+
**职责**: 确保现有V1兼容性模块无缝迁移到V2
|
|
534
|
+
|
|
535
|
+
```typescript
|
|
536
|
+
export class V1CompatibilityAdapter implements ICompatibilityV2 {
|
|
537
|
+
private v1Implementation: CompatibilityModule;
|
|
538
|
+
private v2Wrapper: StandardCompatibility;
|
|
539
|
+
|
|
540
|
+
constructor(v1Module: CompatibilityModule, dependencies: ModuleDependencies) {
|
|
541
|
+
this.v1Implementation = v1Module;
|
|
542
|
+
|
|
543
|
+
// 创建V2包装器
|
|
544
|
+
const v2Config = this.convertV1ConfigToV2(v1Module.config);
|
|
545
|
+
this.v2Wrapper = new StandardCompatibility(v2Config, dependencies);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
async initialize(): Promise<void> {
|
|
549
|
+
// 初始化V1模块
|
|
550
|
+
await this.v1Implementation.initialize();
|
|
551
|
+
// 初始化V2包装器
|
|
552
|
+
await this.v2Wrapper.initialize();
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
async processIncoming(request: UnknownObject): Promise<UnknownObject> {
|
|
556
|
+
// 优先使用V2处理,V1作为fallback
|
|
557
|
+
try {
|
|
558
|
+
return await this.v2Wrapper.processIncoming(request);
|
|
559
|
+
} catch (error) {
|
|
560
|
+
// 如果V2失败,回退到V1
|
|
561
|
+
this.dependencies.logger?.logModule('v1-adapter', 'v2-fallback-to-v1', {
|
|
562
|
+
error: error instanceof Error ? error.message : String(error)
|
|
563
|
+
});
|
|
564
|
+
return await this.v1Implementation.processIncoming(request as any);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
async processOutgoing(response: UnknownObject): Promise<UnknownObject> {
|
|
569
|
+
// 优先使用V2处理,V1作为fallback
|
|
570
|
+
try {
|
|
571
|
+
return await this.v2Wrapper.processOutgoing(response);
|
|
572
|
+
} catch (error) {
|
|
573
|
+
// 如果V2失败,回退到V1
|
|
574
|
+
this.dependencies.logger?.logModule('v1-adapter', 'v2-fallback-to-v1', {
|
|
575
|
+
error: error instanceof Error ? error.message : String(error)
|
|
576
|
+
});
|
|
577
|
+
return await this.v1Implementation.processOutgoing(response);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
private convertV1ConfigToV2(v1Config: ModuleConfig): CompatibilityConfig {
|
|
582
|
+
// 将V1配置转换为V2格式
|
|
583
|
+
return {
|
|
584
|
+
id: v1Config.id,
|
|
585
|
+
type: 'standard',
|
|
586
|
+
config: {
|
|
587
|
+
providerType: this.extractProviderType(v1Config),
|
|
588
|
+
transformationProfile: this.buildTransformationProfile(v1Config),
|
|
589
|
+
hookConfig: this.buildHookConfig(v1Config)
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
## 📊 配置驱动转换示例
|
|
597
|
+
|
|
598
|
+
### GLM Provider完整转换配置
|
|
599
|
+
|
|
600
|
+
```json
|
|
601
|
+
{
|
|
602
|
+
"providerType": "glm",
|
|
603
|
+
"transformationProfile": {
|
|
604
|
+
"name": "glm-standard",
|
|
605
|
+
"version": "1.0.0",
|
|
606
|
+
"transformationTables": {
|
|
607
|
+
"incoming": {
|
|
608
|
+
"fieldMappings": [
|
|
609
|
+
{
|
|
610
|
+
"sourcePath": "model",
|
|
611
|
+
"targetPath": "model",
|
|
612
|
+
"direction": "bidirectional",
|
|
613
|
+
"required": true
|
|
614
|
+
},
|
|
615
|
+
{
|
|
616
|
+
"sourcePath": "thinking.enabled",
|
|
617
|
+
"targetPath": "thinking",
|
|
618
|
+
"direction": "incoming-only",
|
|
619
|
+
"transform": "convertThinkingToGLMFormat"
|
|
620
|
+
},
|
|
621
|
+
{
|
|
622
|
+
"sourcePath": "messages",
|
|
623
|
+
"targetPath": "messages",
|
|
624
|
+
"direction": "bidirectional",
|
|
625
|
+
"transform": "validateMessageFormat"
|
|
626
|
+
}
|
|
627
|
+
],
|
|
628
|
+
"typeConversions": [
|
|
629
|
+
{
|
|
630
|
+
"sourceType": "boolean",
|
|
631
|
+
"targetType": "object",
|
|
632
|
+
"conversionFunction": "booleanToThinkingConfig",
|
|
633
|
+
"conditions": {
|
|
634
|
+
"field": "thinking"
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
]
|
|
638
|
+
},
|
|
639
|
+
"outgoing": {
|
|
640
|
+
"fieldMappings": [
|
|
641
|
+
{
|
|
642
|
+
"sourcePath": "usage.input_tokens",
|
|
643
|
+
"targetPath": "usage.prompt_tokens",
|
|
644
|
+
"direction": "outgoing-only"
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
"sourcePath": "usage.output_tokens",
|
|
648
|
+
"targetPath": "usage.completion_tokens",
|
|
649
|
+
"direction": "outgoing-only"
|
|
650
|
+
},
|
|
651
|
+
{
|
|
652
|
+
"sourcePath": "reasoning_content",
|
|
653
|
+
"targetPath": "reasoning_content",
|
|
654
|
+
"direction": "outgoing-only",
|
|
655
|
+
"transform": "extractReasoningBlocks"
|
|
656
|
+
}
|
|
657
|
+
]
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
},
|
|
661
|
+
"hookConfig": {
|
|
662
|
+
"enabled": true,
|
|
663
|
+
"hooks": [
|
|
664
|
+
{
|
|
665
|
+
"name": "glm-thinking-injector",
|
|
666
|
+
"stage": "incoming_preprocessing",
|
|
667
|
+
"enabled": true,
|
|
668
|
+
"config": {
|
|
669
|
+
"models": ["glm-thinking-*"],
|
|
670
|
+
"defaultThinking": true
|
|
671
|
+
}
|
|
672
|
+
},
|
|
673
|
+
{
|
|
674
|
+
"name": "glm-response-normalizer",
|
|
675
|
+
"stage": "outgoing_postprocessing",
|
|
676
|
+
"enabled": true,
|
|
677
|
+
"config": {
|
|
678
|
+
"normalizeUsage": true,
|
|
679
|
+
"normalizeTimestamps": true
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
]
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
## 🎯 实施计划
|
|
688
|
+
|
|
689
|
+
### 第一阶段:核心架构 (3天)
|
|
690
|
+
1. 创建V2目录结构
|
|
691
|
+
2. 实现BaseCompatibility抽象类
|
|
692
|
+
3. 实现TransformationEngine转换引擎
|
|
693
|
+
4. 实现Hook系统集成
|
|
694
|
+
|
|
695
|
+
### 第二阶段:配置系统 (2天)
|
|
696
|
+
1. 设计转换表配置格式
|
|
697
|
+
2. 实现双向映射器
|
|
698
|
+
3. 创建Provider配置档案
|
|
699
|
+
4. 实现配置验证器
|
|
700
|
+
|
|
701
|
+
### 第三阶段:策略实现 (3天)
|
|
702
|
+
1. 实现OpenAI标准策略
|
|
703
|
+
2. 实现GLM特定策略
|
|
704
|
+
3. 实现Qwen特定策略
|
|
705
|
+
4. 实现Iflow特定策略
|
|
706
|
+
|
|
707
|
+
### 第四阶段:兼容性保证 (2天)
|
|
708
|
+
1. 实现V1适配器
|
|
709
|
+
2. 测试向后兼容性
|
|
710
|
+
3. 性能基准测试
|
|
711
|
+
4. 文档和示例
|
|
712
|
+
|
|
713
|
+
## ✅ 验收标准
|
|
714
|
+
|
|
715
|
+
### 功能验收
|
|
716
|
+
- [ ] 所有现有兼容性功能正常工作
|
|
717
|
+
- [ ] 配置驱动的转换引擎正常运行
|
|
718
|
+
- [ ] Hook系统完全集成
|
|
719
|
+
- [ ] 向后兼容性100%保证
|
|
720
|
+
|
|
721
|
+
### 架构验收
|
|
722
|
+
- [ ] 模块职责清晰分离
|
|
723
|
+
- [ ] 配置驱动,无硬编码转换
|
|
724
|
+
- [ ] Hook生命周期完整支持
|
|
725
|
+
- [ ] 符合9大架构原则
|
|
726
|
+
|
|
727
|
+
### 质量验收
|
|
728
|
+
- [ ] 测试覆盖率 > 95%
|
|
729
|
+
- [ ] 性能不低于V1实现
|
|
730
|
+
- [ ] 配置验证完整
|
|
731
|
+
- [ ] 文档完整清晰
|
|
732
|
+
|
|
733
|
+
---
|
|
734
|
+
|
|
735
|
+
**设计完成时间**: 2025-11-01
|
|
736
|
+
**架构模式**: 基于Provider V2成功模式
|
|
737
|
+
**预计实施时间**: 10天
|
|
738
|
+
**向后兼容**: 100%保证
|