@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,827 @@
|
|
|
1
|
+
# V2 Virtual Pipeline Optimization Design
|
|
2
|
+
## (Support for Multi-Configuration Module Static Loading)
|
|
3
|
+
|
|
4
|
+
## 🎯 Core Optimization Concept
|
|
5
|
+
|
|
6
|
+
Based on requirements, V2 architecture is adjusted to **Hybrid Mode**:
|
|
7
|
+
- **Static Instances**: Modules requiring multiple configurations (like compatibility) preload all variants
|
|
8
|
+
- **Virtual Connections**: Runtime dynamic selection of already instantiated modules for connection
|
|
9
|
+
- **Performance Priority**: Avoid module initialization overhead during request processing
|
|
10
|
+
|
|
11
|
+
## 🏗️ Optimized Architecture Design
|
|
12
|
+
|
|
13
|
+
### Architecture Comparison Diagram
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
V1 Static Assembly (Current):
|
|
17
|
+
┌─────────────────────────────────────────────────┐
|
|
18
|
+
│ Pipeline1: [ProviderA][CompatA][LLMSwitchA] │ ← Complete static instances
|
|
19
|
+
│ Pipeline2: [ProviderB][CompatB][LLMSwitchB] │ ← Complete static instances
|
|
20
|
+
│ Pipeline3: [ProviderC][CompatA][LLMSwitchC] │ ← Complete static instances
|
|
21
|
+
└─────────────────────────────────────────────────┘
|
|
22
|
+
|
|
23
|
+
V2 Optimized Hybrid Architecture (New Design):
|
|
24
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
25
|
+
│ Static Module Instance Pool │
|
|
26
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐│
|
|
27
|
+
│ │ ProviderA │ │ ProviderB │ │ CompatGLM │ │ CompatQwen ││
|
|
28
|
+
│ │ (single) │ │ (single) │ │ (single) │ │ (single) ││
|
|
29
|
+
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘│
|
|
30
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐│
|
|
31
|
+
│ │ LLMSwitchA │ │ LLMSwitchB │ │ CompatOpenAI│ │ WorkflowA ││
|
|
32
|
+
│ │ (single) │ │ (single) │ │ (single) │ │ (single) ││
|
|
33
|
+
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘│
|
|
34
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
35
|
+
↓ Dynamic routing selection
|
|
36
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
37
|
+
│ Virtual Pipeline Connection Layer │
|
|
38
|
+
│ RequestA → ProviderA ─→ CompatGLM ─→ LLMSwitchA ─→ ResponseA │
|
|
39
|
+
│ RequestB → ProviderB ─→ CompatQwen ─→ LLMSwitchB ─→ ResponseB │
|
|
40
|
+
│ RequestC → ProviderA ─→ CompatOpenAI ─→ LLMSwitchA ─→ ResponseC│
|
|
41
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 📋 Optimized Design Detailed Plan
|
|
45
|
+
|
|
46
|
+
### 1. Static Module Instance Pool Design
|
|
47
|
+
|
|
48
|
+
#### 1.1 Multi-Configuration Module Preload Mechanism
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
// src/modules/pipeline/v2/core/static-instance-pool.ts
|
|
52
|
+
export class StaticInstancePool {
|
|
53
|
+
// Store instances by module type and config hash
|
|
54
|
+
private instances = new Map<string, Map<string, ModuleInstance>>();
|
|
55
|
+
|
|
56
|
+
// Preload all configuration variants
|
|
57
|
+
async preloadInstances(config: V2SystemConfig): Promise<void> {
|
|
58
|
+
const moduleConfigs = this.extractModuleConfigs(config);
|
|
59
|
+
|
|
60
|
+
for (const [moduleType, configs] of moduleConfigs) {
|
|
61
|
+
await this.preloadModuleType(moduleType, configs);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Preload specific module type's all configurations
|
|
66
|
+
private async preloadModuleType(
|
|
67
|
+
moduleType: string,
|
|
68
|
+
configs: ModuleConfig[]
|
|
69
|
+
): Promise<void> {
|
|
70
|
+
const typeInstances = new Map<string, ModuleInstance>();
|
|
71
|
+
|
|
72
|
+
for (const config of configs) {
|
|
73
|
+
const configHash = this.hashConfig(config);
|
|
74
|
+
const instance = await this.createInstance(moduleType, config);
|
|
75
|
+
typeInstances.set(configHash, instance);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
this.instances.set(moduleType, typeInstances);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Get instance of specific configuration
|
|
82
|
+
getInstance(moduleType: string, config: ModuleConfig): ModuleInstance {
|
|
83
|
+
const configHash = this.hashConfig(config);
|
|
84
|
+
const typeInstances = this.instances.get(moduleType);
|
|
85
|
+
|
|
86
|
+
if (!typeInstances?.has(configHash)) {
|
|
87
|
+
throw new Error(`Instance not found for ${moduleType}:${configHash}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return typeInstances.get(configHash)!;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Configuration hash algorithm (ensure same config maps to same instance)
|
|
94
|
+
private hashConfig(config: ModuleConfig): string {
|
|
95
|
+
const normalized = this.normalizeConfig(config);
|
|
96
|
+
return crypto.createHash('md5').update(JSON.stringify(normalized)).digest('hex');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
#### 1.2 Module Configuration Extractor
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// src/modules/pipeline/v2/config/module-config-extractor.ts
|
|
105
|
+
export class ModuleConfigExtractor {
|
|
106
|
+
// Extract all required module configurations from route table
|
|
107
|
+
extractModuleConfigs(routeTable: RouteTableConfig): Map<string, ModuleConfig[]> {
|
|
108
|
+
const configs = new Map<string, ModuleConfig[]>();
|
|
109
|
+
|
|
110
|
+
// Collect module configurations used in all routes
|
|
111
|
+
for (const route of routeTable.routes) {
|
|
112
|
+
for (const moduleSpec of route.modules) {
|
|
113
|
+
const moduleType = moduleSpec.type;
|
|
114
|
+
const moduleConfig = moduleSpec.config;
|
|
115
|
+
|
|
116
|
+
if (!configs.has(moduleType)) {
|
|
117
|
+
configs.set(moduleType, []);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Check if same configuration already exists
|
|
121
|
+
const existing = configs.get(moduleType)!;
|
|
122
|
+
if (!this.hasSameConfig(existing, moduleConfig)) {
|
|
123
|
+
existing.push(moduleConfig);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return configs;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Check if configuration already exists (avoid duplicate instances)
|
|
132
|
+
private hasSameConfig(existing: ModuleConfig[], newConfig: ModuleConfig): boolean {
|
|
133
|
+
return existing.some(config =>
|
|
134
|
+
JSON.stringify(this.normalizeConfig(config)) ===
|
|
135
|
+
JSON.stringify(this.normalizeConfig(newConfig))
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### 2. Optimized V2 Configuration Schema
|
|
142
|
+
|
|
143
|
+
#### 2.1 Route Definition Supporting Multiple Configurations
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
// src/config/v2-config-schema.ts (Optimized version)
|
|
147
|
+
export interface V2SystemConfig {
|
|
148
|
+
version: '2.0';
|
|
149
|
+
|
|
150
|
+
// Static instance pool configuration
|
|
151
|
+
staticInstances: {
|
|
152
|
+
// Module types list that need preloading
|
|
153
|
+
preloadModules: string[];
|
|
154
|
+
// Instance pool configuration
|
|
155
|
+
poolConfig: {
|
|
156
|
+
maxInstancesPerType: number;
|
|
157
|
+
warmupInstances: number;
|
|
158
|
+
idleTimeout: number;
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
// Virtual routing table
|
|
163
|
+
virtualPipelines: {
|
|
164
|
+
routeTable: RouteTableConfig;
|
|
165
|
+
moduleRegistry: ModuleRegistryConfig;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// Other configurations remain unchanged...
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export interface RouteDefinition {
|
|
172
|
+
id: string;
|
|
173
|
+
pattern: RequestPattern;
|
|
174
|
+
|
|
175
|
+
// Module chain definition (support configuration reference)
|
|
176
|
+
modules: ModuleSpecification[];
|
|
177
|
+
|
|
178
|
+
// Route priority
|
|
179
|
+
priority: number;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export interface ModuleSpecification {
|
|
183
|
+
// Module type
|
|
184
|
+
type: string;
|
|
185
|
+
|
|
186
|
+
// Configuration reference or inline configuration
|
|
187
|
+
config?: ModuleConfig | string; // Support configuration ID reference
|
|
188
|
+
|
|
189
|
+
// Conditional selection (based on request features) - Must match explicitly
|
|
190
|
+
condition?: RequestCondition;
|
|
191
|
+
|
|
192
|
+
// Note: No fallback - fail fast when condition not met
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Usage example
|
|
196
|
+
export const exampleRoute: RouteDefinition = {
|
|
197
|
+
id: 'glm-standard-route',
|
|
198
|
+
pattern: { model: /^glm-/ },
|
|
199
|
+
modules: [
|
|
200
|
+
{
|
|
201
|
+
type: 'provider',
|
|
202
|
+
config: { type: 'glm-http-provider', providerType: 'glm' }
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
type: 'compatibility',
|
|
206
|
+
config: 'glm-compatibility-config' // Reference predefined configuration
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
type: 'llmSwitch',
|
|
210
|
+
config: { type: 'llmswitch-conversion-router' }
|
|
211
|
+
}
|
|
212
|
+
]
|
|
213
|
+
};
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
#### 2.2 Configuration Library Design
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
// src/config/v2-config-library.ts
|
|
220
|
+
export class V2ConfigLibrary {
|
|
221
|
+
private static readonly COMPATIBILITY_CONFIGS = {
|
|
222
|
+
'glm-compatibility-config': {
|
|
223
|
+
type: 'glm-compatibility',
|
|
224
|
+
config: {
|
|
225
|
+
providerType: 'glm',
|
|
226
|
+
// 字段映射配置 - 将GLM特定字段映射到OpenAI标准格式
|
|
227
|
+
fieldMappings: {
|
|
228
|
+
request: {
|
|
229
|
+
// GLM -> OpenAI 映射规则
|
|
230
|
+
'model': 'model',
|
|
231
|
+
'messages': 'messages',
|
|
232
|
+
'temperature': 'temperature',
|
|
233
|
+
'max_tokens': 'max_tokens',
|
|
234
|
+
// GLM特有字段映射
|
|
235
|
+
'top_p': 'top_p',
|
|
236
|
+
'stream': 'stream'
|
|
237
|
+
},
|
|
238
|
+
response: {
|
|
239
|
+
// OpenAI <- GLM 映射规则
|
|
240
|
+
'choices': 'choices',
|
|
241
|
+
'usage': 'usage',
|
|
242
|
+
'created': 'created',
|
|
243
|
+
// GLM特有字段清理
|
|
244
|
+
'request_id': null, // 移除GLM特有字段
|
|
245
|
+
'task_id': null, // 移除GLM特有字段
|
|
246
|
+
'thought': null // 移除GLM特有字段字段
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
// 格式转换配置
|
|
250
|
+
formatConversions: {
|
|
251
|
+
// GLM的reasoning_content字段转换
|
|
252
|
+
reasoningContent: {
|
|
253
|
+
source: 'thought',
|
|
254
|
+
target: 'reasoning_content',
|
|
255
|
+
transform: 'extract_and_format'
|
|
256
|
+
},
|
|
257
|
+
// GLM的使用统计格式标准化
|
|
258
|
+
usage: {
|
|
259
|
+
source: 'usage',
|
|
260
|
+
target: 'usage',
|
|
261
|
+
transform: 'standardize_format'
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
// 供应商特定处理
|
|
265
|
+
providerSpecificProcessing: {
|
|
266
|
+
// GLM特有的清理逻辑
|
|
267
|
+
cleanup: [
|
|
268
|
+
{ field: 'model_id', action: 'remove' },
|
|
269
|
+
{ field: 'session_id', action: 'remove' },
|
|
270
|
+
{ field: 'task_status', action: 'remove' }
|
|
271
|
+
],
|
|
272
|
+
// GLM特有的格式转换
|
|
273
|
+
conversions: [
|
|
274
|
+
{
|
|
275
|
+
from: 'thought',
|
|
276
|
+
to: 'reasoning_content',
|
|
277
|
+
when: { field: 'thought', exists: true }
|
|
278
|
+
}
|
|
279
|
+
]
|
|
280
|
+
},
|
|
281
|
+
// Hooks配置 - 字段映射前后挂载特殊处理
|
|
282
|
+
hooks: {
|
|
283
|
+
beforeFieldMapping: [
|
|
284
|
+
{
|
|
285
|
+
name: 'glm-request-preprocessor',
|
|
286
|
+
enabled: true,
|
|
287
|
+
config: {
|
|
288
|
+
// GLM特有的请求预处理
|
|
289
|
+
normalizeModelName: true,
|
|
290
|
+
addGLMHeaders: true
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
],
|
|
294
|
+
afterFieldMapping: [
|
|
295
|
+
{
|
|
296
|
+
name: 'glm-response-postprocessor',
|
|
297
|
+
enabled: true,
|
|
298
|
+
config: {
|
|
299
|
+
// GLM特有的响应后处理
|
|
300
|
+
extractThoughtContent: true,
|
|
301
|
+
standardizeUsage: true
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
]
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
'qwen-compatibility-config': {
|
|
309
|
+
type: 'qwen-compatibility', // ⚠️ legacy;v2 以后由 sharedmodule/llmswitch-core 的 chat:qwen profile 负责
|
|
310
|
+
config: {
|
|
311
|
+
providerType: 'qwen',
|
|
312
|
+
// 字段映射配置 - 将Qwen特定字段映射到OpenAI标准格式
|
|
313
|
+
fieldMappings: {
|
|
314
|
+
request: {
|
|
315
|
+
'model': 'model',
|
|
316
|
+
'messages': 'messages',
|
|
317
|
+
'temperature': 'temperature',
|
|
318
|
+
'max_tokens': 'max_tokens',
|
|
319
|
+
// Qwen特有字段映射
|
|
320
|
+
'top_p': 'top_p',
|
|
321
|
+
'repetition_penalty': 'frequency_penalty'
|
|
322
|
+
},
|
|
323
|
+
response: {
|
|
324
|
+
'choices': 'choices',
|
|
325
|
+
'usage': 'usage',
|
|
326
|
+
'created': 'created',
|
|
327
|
+
// Qwen特有字段清理
|
|
328
|
+
'task_id': null, // 移除Qwen特有字段
|
|
329
|
+
'request_id': null, // 移除Qwen特有字段
|
|
330
|
+
'object': null // 移除Qwen特有字段
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
// 格式转换配置
|
|
334
|
+
formatConversions: {
|
|
335
|
+
// Qwen的输出格式标准化
|
|
336
|
+
outputFormat: {
|
|
337
|
+
source: 'output',
|
|
338
|
+
target: 'content',
|
|
339
|
+
transform: 'extract_text_content'
|
|
340
|
+
},
|
|
341
|
+
// Qwen的使用统计标准化
|
|
342
|
+
usage: {
|
|
343
|
+
source: 'usage',
|
|
344
|
+
target: 'usage',
|
|
345
|
+
transform: 'standardize_qwen_usage'
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
// 供应商特定处理
|
|
349
|
+
providerSpecificProcessing: {
|
|
350
|
+
cleanup: [
|
|
351
|
+
{ field: 'model_id', action: 'remove' },
|
|
352
|
+
{ field: 'seed', action: 'remove' }
|
|
353
|
+
],
|
|
354
|
+
conversions: [
|
|
355
|
+
{
|
|
356
|
+
from: 'output.text',
|
|
357
|
+
to: 'content',
|
|
358
|
+
when: { field: 'output', exists: true }
|
|
359
|
+
}
|
|
360
|
+
]
|
|
361
|
+
},
|
|
362
|
+
// Hooks配置
|
|
363
|
+
hooks: {
|
|
364
|
+
beforeFieldMapping: [
|
|
365
|
+
{
|
|
366
|
+
name: 'qwen-request-preprocessor',
|
|
367
|
+
enabled: true,
|
|
368
|
+
config: {
|
|
369
|
+
// Qwen特有的请求预处理
|
|
370
|
+
normalizeQwenModelNames: true,
|
|
371
|
+
handleQwenSpecificFields: true
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
],
|
|
375
|
+
afterFieldMapping: [
|
|
376
|
+
{
|
|
377
|
+
name: 'qwen-response-postprocessor',
|
|
378
|
+
enabled: true,
|
|
379
|
+
config: {
|
|
380
|
+
// Qwen特有的响应后处理
|
|
381
|
+
extractTextFromOutput: true,
|
|
382
|
+
standardizeQwenUsage: true
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
]
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
'openai-compatibility-config': {
|
|
390
|
+
type: 'passthrough-compatibility',
|
|
391
|
+
config: {
|
|
392
|
+
providerType: 'openai',
|
|
393
|
+
// OpenAI已经是标准格式,最小化处理
|
|
394
|
+
fieldMappings: {
|
|
395
|
+
request: {
|
|
396
|
+
// OpenAI -> OpenAI 直接映射
|
|
397
|
+
'model': 'model',
|
|
398
|
+
'messages': 'messages',
|
|
399
|
+
'temperature': 'temperature'
|
|
400
|
+
},
|
|
401
|
+
response: {
|
|
402
|
+
// OpenAI <- OpenAI 直接映射
|
|
403
|
+
'choices': 'choices',
|
|
404
|
+
'usage': 'usage'
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
// 格式转换配置 - OpenAI无需转换
|
|
408
|
+
formatConversions: {},
|
|
409
|
+
// 供应商特定处理 - OpenAI无需特殊处理
|
|
410
|
+
providerSpecificProcessing: {
|
|
411
|
+
cleanup: [],
|
|
412
|
+
conversions: []
|
|
413
|
+
},
|
|
414
|
+
// Hooks配置 - OpenAI的hooks可选
|
|
415
|
+
hooks: {
|
|
416
|
+
beforeFieldMapping: [
|
|
417
|
+
{
|
|
418
|
+
name: 'openai-request-validator',
|
|
419
|
+
enabled: false, // 默认关闭
|
|
420
|
+
config: {
|
|
421
|
+
validateOpenAIFormat: true
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
],
|
|
425
|
+
afterFieldMapping: [
|
|
426
|
+
{
|
|
427
|
+
name: 'openai-response-enhancer',
|
|
428
|
+
enabled: false, // 默认关闭
|
|
429
|
+
config: {
|
|
430
|
+
addOpenAIMetadata: true
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
]
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
private static readonly PROVIDER_CONFIGS = {
|
|
440
|
+
'glm-provider-config': {
|
|
441
|
+
type: 'openai-standard',
|
|
442
|
+
config: {
|
|
443
|
+
providerType: 'glm',
|
|
444
|
+
baseUrl: '${GLM_BASE_URL:https://open.bigmodel.cn/api/paas/v4}', // Config-driven, no hardcoded URLs
|
|
445
|
+
auth: { type: 'apikey', apiKey: '${GLM_API_KEY}' },
|
|
446
|
+
validation: {
|
|
447
|
+
requiredEnvVars: ['GLM_API_KEY'],
|
|
448
|
+
optionalEnvVars: ['GLM_BASE_URL']
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
// ... Other predefined configurations
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
static getAllConfigs(): Record<string, ModuleConfig> {
|
|
456
|
+
return {
|
|
457
|
+
...this.COMPATIBILITY_CONFIGS,
|
|
458
|
+
...this.PROVIDER_CONFIGS,
|
|
459
|
+
...this.LLMSWITCH_CONFIGS
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### 3. Optimized Dynamic Router
|
|
466
|
+
|
|
467
|
+
#### 3.1 Hybrid Router Implementation
|
|
468
|
+
|
|
469
|
+
```typescript
|
|
470
|
+
// src/modules/pipeline/v2/core/hybrid-router.ts
|
|
471
|
+
export class HybridDynamicRouter {
|
|
472
|
+
constructor(
|
|
473
|
+
private staticInstancePool: StaticInstancePool,
|
|
474
|
+
private routeTable: RouteTableConfig
|
|
475
|
+
) {}
|
|
476
|
+
|
|
477
|
+
// Route request (main entry point)
|
|
478
|
+
async route(request: PipelineRequest): Promise<PipelineResponse> {
|
|
479
|
+
// 1. Match best route
|
|
480
|
+
const route = this.matchRoute(request);
|
|
481
|
+
|
|
482
|
+
// 2. Build virtual module chain
|
|
483
|
+
const moduleChain = await this.buildModuleChain(route, request);
|
|
484
|
+
|
|
485
|
+
// 3. Execute chain processing
|
|
486
|
+
const response = await this.executeChain(moduleChain, request);
|
|
487
|
+
|
|
488
|
+
// 4. Cleanup temporary connections (keep instances)
|
|
489
|
+
await moduleChain.cleanupConnections();
|
|
490
|
+
|
|
491
|
+
return response;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// Build module chain (use static instances)
|
|
495
|
+
private async buildModuleChain(
|
|
496
|
+
route: RouteDefinition,
|
|
497
|
+
request: PipelineRequest
|
|
498
|
+
): Promise<VirtualModuleChain> {
|
|
499
|
+
const modules: ModuleInstance[] = [];
|
|
500
|
+
|
|
501
|
+
for (const moduleSpec of route.modules) {
|
|
502
|
+
// Select configuration based on request conditions
|
|
503
|
+
const config = this.resolveConfig(moduleSpec, request);
|
|
504
|
+
|
|
505
|
+
// Get instance from static pool (don't create new instance)
|
|
506
|
+
const instance = this.staticInstancePool.getInstance(
|
|
507
|
+
moduleSpec.type,
|
|
508
|
+
config
|
|
509
|
+
);
|
|
510
|
+
|
|
511
|
+
modules.push(instance);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
return new VirtualModuleChain(modules);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Resolve module configuration (fail fast on condition mismatch)
|
|
518
|
+
private resolveConfig(
|
|
519
|
+
moduleSpec: ModuleSpecification,
|
|
520
|
+
request: PipelineRequest
|
|
521
|
+
): ModuleConfig {
|
|
522
|
+
// Check conditional selection - must match explicitly
|
|
523
|
+
if (moduleSpec.condition && !this.evaluateCondition(moduleSpec.condition, request)) {
|
|
524
|
+
throw new Error(`Condition failed for module ${moduleSpec.type}. No fallback allowed - fail fast.`);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Resolve configuration reference
|
|
528
|
+
if (typeof moduleSpec.config === 'string') {
|
|
529
|
+
return V2ConfigLibrary.getConfig(moduleSpec.config);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
return moduleSpec.config!;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
#### 3.2 Virtual Module Chain Implementation
|
|
538
|
+
|
|
539
|
+
```typescript
|
|
540
|
+
// src/modules/pipeline/v2/core/virtual-module-chain.ts
|
|
541
|
+
export class VirtualModuleChain {
|
|
542
|
+
private connections: ModuleConnection[] = [];
|
|
543
|
+
|
|
544
|
+
constructor(public modules: ModuleInstance[]) {
|
|
545
|
+
this.buildConnections();
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// Build temporary connections (don't create new instances)
|
|
549
|
+
private buildConnections(): void {
|
|
550
|
+
for (let i = 0; i < this.modules.length - 1; i++) {
|
|
551
|
+
const from = this.modules[i];
|
|
552
|
+
const to = this.modules[i + 1];
|
|
553
|
+
|
|
554
|
+
// Create virtual connection (reference existing instances)
|
|
555
|
+
const connection = new VirtualModuleConnection(from, to);
|
|
556
|
+
this.connections.push(connection);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// Execute chain processing
|
|
561
|
+
async process(request: PipelineRequest): Promise<PipelineResponse> {
|
|
562
|
+
let currentData = request;
|
|
563
|
+
|
|
564
|
+
for (let i = 0; i < this.modules.length; i++) {
|
|
565
|
+
const module = this.modules[i];
|
|
566
|
+
const connection = this.connections[i];
|
|
567
|
+
|
|
568
|
+
// Process data
|
|
569
|
+
const result = await module.processIncoming(currentData, {
|
|
570
|
+
moduleId: module.id,
|
|
571
|
+
chainPosition: i,
|
|
572
|
+
totalModules: this.modules.length
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
// Pass data through connection
|
|
576
|
+
if (connection) {
|
|
577
|
+
currentData = await connection.transform(result);
|
|
578
|
+
} else {
|
|
579
|
+
currentData = result;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
return currentData as PipelineResponse;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// Only cleanup connections, keep instances
|
|
587
|
+
async cleanupConnections(): Promise<void> {
|
|
588
|
+
for (const connection of this.connections) {
|
|
589
|
+
await connection.cleanup();
|
|
590
|
+
}
|
|
591
|
+
this.connections = [];
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// Virtual connection (don't hold instance ownership)
|
|
596
|
+
export class VirtualModuleConnection {
|
|
597
|
+
constructor(
|
|
598
|
+
private from: ModuleInstance,
|
|
599
|
+
private to: ModuleInstance
|
|
600
|
+
) {}
|
|
601
|
+
|
|
602
|
+
async transform(data: any): Promise<any> {
|
|
603
|
+
// Lightweight data transformation, no instance initialization involved
|
|
604
|
+
return this.to.processIncoming(data, {
|
|
605
|
+
fromModule: this.from.id,
|
|
606
|
+
toModule: this.to.id
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
async cleanup(): Promise<void> {
|
|
611
|
+
// Cleanup connection state, but keep instances
|
|
612
|
+
// Instances managed uniformly by StaticInstancePool
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
### 4. System Startup and Warmup Mechanism
|
|
618
|
+
|
|
619
|
+
#### 4.1 Intelligent Warmup Strategy
|
|
620
|
+
|
|
621
|
+
```typescript
|
|
622
|
+
// src/modules/pipeline/v2/core/warmup-manager.ts
|
|
623
|
+
export class WarmupManager {
|
|
624
|
+
constructor(
|
|
625
|
+
private staticInstancePool: StaticInstancePool,
|
|
626
|
+
private metrics: V2Metrics
|
|
627
|
+
) {}
|
|
628
|
+
|
|
629
|
+
// Warmup system at startup
|
|
630
|
+
async warmupSystem(config: V2SystemConfig): Promise<WarmupReport> {
|
|
631
|
+
const report: WarmupReport = {
|
|
632
|
+
startTime: Date.now(),
|
|
633
|
+
preloadedInstances: 0,
|
|
634
|
+
failedInstances: [],
|
|
635
|
+
warnings: []
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
try {
|
|
639
|
+
// 1. Analyze configuration, determine instances need preloading
|
|
640
|
+
const preloadPlan = this.analyzePreloadRequirements(config);
|
|
641
|
+
|
|
642
|
+
// 2. Load instances by priority order
|
|
643
|
+
await this.preloadByPriority(preloadPlan, report);
|
|
644
|
+
|
|
645
|
+
// 3. Verify instance availability
|
|
646
|
+
await this.validateInstances(report);
|
|
647
|
+
|
|
648
|
+
// 4. Record warmup metrics
|
|
649
|
+
this.recordWarmupMetrics(report);
|
|
650
|
+
|
|
651
|
+
} catch (error) {
|
|
652
|
+
report.failedInstances.push({
|
|
653
|
+
module: 'system',
|
|
654
|
+
error: error.message,
|
|
655
|
+
recoverable: false
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
report.endTime = Date.now();
|
|
660
|
+
report.duration = report.endTime - report.startTime;
|
|
661
|
+
|
|
662
|
+
return report;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// Analyze preload requirements
|
|
666
|
+
private analyzePreloadRequirements(config: V2SystemConfig): PreloadPlan {
|
|
667
|
+
const extractor = new ModuleConfigExtractor();
|
|
668
|
+
const moduleConfigs = extractor.extractModuleConfigs(config.virtualPipelines.routeTable);
|
|
669
|
+
|
|
670
|
+
const plan: PreloadPlan = {
|
|
671
|
+
critical: [], // Core modules (provider, compatibility)
|
|
672
|
+
important: [], // Important modules (llmSwitch)
|
|
673
|
+
optional: [] // Optional modules (workflow, monitoring)
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
// Classify by module type
|
|
677
|
+
for (const [type, configs] of moduleConfigs) {
|
|
678
|
+
const priority = this.getModulePriority(type);
|
|
679
|
+
plan[priority].push({ type, configs });
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
return plan;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// Preload by priority
|
|
686
|
+
private async preloadByPriority(plan: PreloadPlan, report: WarmupReport): Promise<void> {
|
|
687
|
+
const phases = ['critical', 'important', 'optional'] as const;
|
|
688
|
+
|
|
689
|
+
for (const phase of phases) {
|
|
690
|
+
for (const { type, configs } of plan[phase]) {
|
|
691
|
+
try {
|
|
692
|
+
await this.staticInstancePool.preloadModuleType(type, configs);
|
|
693
|
+
report.preloadedInstances += configs.length;
|
|
694
|
+
} catch (error) {
|
|
695
|
+
report.failedInstances.push({
|
|
696
|
+
module: type,
|
|
697
|
+
error: error.message,
|
|
698
|
+
recoverable: phase !== 'critical'
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
### 5. Performance Monitoring and Optimization
|
|
708
|
+
|
|
709
|
+
#### 5.1 Instance Pool Monitoring
|
|
710
|
+
|
|
711
|
+
```typescript
|
|
712
|
+
// src/monitoring/instance-pool-metrics.ts
|
|
713
|
+
export class InstancePoolMetrics {
|
|
714
|
+
// Instance utilization monitoring
|
|
715
|
+
trackInstanceUtilization(): void {
|
|
716
|
+
// Record usage frequency of each instance
|
|
717
|
+
// Identify idle instances and hotspot instances
|
|
718
|
+
// Provide pool size adjustment recommendations
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
// Memory usage monitoring
|
|
722
|
+
trackMemoryUsage(): void {
|
|
723
|
+
// Monitor instance pool memory usage
|
|
724
|
+
// Detect memory leaks
|
|
725
|
+
// Trigger garbage collection recommendations
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// Warmup effectiveness evaluation
|
|
729
|
+
evaluateWarmupEffectiveness(): WarmupReport {
|
|
730
|
+
// Evaluate warmup strategy effectiveness
|
|
731
|
+
// Calculate latency reduction from warmup
|
|
732
|
+
// Optimize warmup configuration
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
## 🔧 Configuration Validation and Hygiene
|
|
738
|
+
|
|
739
|
+
### Config-Driven Values Only
|
|
740
|
+
All configuration must be externalized - no hardcoded values in code:
|
|
741
|
+
|
|
742
|
+
```typescript
|
|
743
|
+
// Correct: Config-driven with validation
|
|
744
|
+
'provider-config': {
|
|
745
|
+
config: {
|
|
746
|
+
baseUrl: '${PROVIDER_BASE_URL:https://api.provider.com/v1}', // Env var with default
|
|
747
|
+
timeout: parseInt('${PROVIDER_TIMEOUT:30000}'), // Parsed env var
|
|
748
|
+
validation: {
|
|
749
|
+
requiredEnvVars: ['PROVIDER_API_KEY'],
|
|
750
|
+
optionalEnvVars: ['PROVIDER_BASE_URL', 'PROVIDER_TIMEOUT']
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// Incorrect: Hardcoded values
|
|
756
|
+
'provider-config': {
|
|
757
|
+
config: {
|
|
758
|
+
baseUrl: 'https://hardcoded-url.com/v1', // ❌ Hardcoded
|
|
759
|
+
timeout: 30000 // ❌ Hardcoded
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
### Stable Configuration Hashing
|
|
765
|
+
To prevent config hash collisions and ensure deterministic instance mapping:
|
|
766
|
+
|
|
767
|
+
```typescript
|
|
768
|
+
private hashConfig(config: ModuleConfig): string {
|
|
769
|
+
// Use stable stringify with consistent key ordering
|
|
770
|
+
const normalized = this.normalizeConfig(config);
|
|
771
|
+
const stableString = this.stableStringify(normalized);
|
|
772
|
+
return crypto.createHash('sha256').update(stableString).digest('hex');
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
private stableStringify(obj: any): string {
|
|
776
|
+
// Recursive stable stringify to handle nested objects consistently
|
|
777
|
+
const seen = new WeakSet();
|
|
778
|
+
|
|
779
|
+
const stringify = (value: any): string => {
|
|
780
|
+
if (value === null || value === undefined) return 'null';
|
|
781
|
+
if (typeof value === 'string') return JSON.stringify(value);
|
|
782
|
+
if (typeof value === 'number' || typeof value === 'boolean') return String(value);
|
|
783
|
+
if (typeof value === 'object') {
|
|
784
|
+
if (seen.has(value)) return '"[Circular]"';
|
|
785
|
+
seen.add(value);
|
|
786
|
+
|
|
787
|
+
if (Array.isArray(value)) {
|
|
788
|
+
const arrayStr = '[' + value.map(stringify).join(',') + ']';
|
|
789
|
+
seen.delete(value);
|
|
790
|
+
return arrayStr;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
const keys = Object.keys(value).sort();
|
|
794
|
+
const objStr = '{' + keys.map(key =>
|
|
795
|
+
JSON.stringify(key) + ':' + stringify(value[key])
|
|
796
|
+
).join(',') + '}';
|
|
797
|
+
seen.delete(value);
|
|
798
|
+
return objStr;
|
|
799
|
+
}
|
|
800
|
+
return 'null';
|
|
801
|
+
};
|
|
802
|
+
|
|
803
|
+
return stringify(obj);
|
|
804
|
+
}
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
## 🎯 Key Advantages
|
|
808
|
+
|
|
809
|
+
### Performance Advantages
|
|
810
|
+
1. **Zero Cold Start**: All module instances preloaded, directly used during requests
|
|
811
|
+
2. **Memory Efficient**: Same configuration shares instances, avoiding duplication
|
|
812
|
+
3. **Lightweight Connections**: Only create temporary connections, no instance initialization involved
|
|
813
|
+
4. **Intelligent Warmup**: Preload key modules by priority
|
|
814
|
+
|
|
815
|
+
### Architecture Advantages
|
|
816
|
+
1. **Flexible Routing**: Support dynamic module selection based on request characteristics
|
|
817
|
+
2. **Configuration Reuse**: Same configuration instances shared between different routes
|
|
818
|
+
3. **Gradual Migration**: V1/V2 dual mode seamless switching
|
|
819
|
+
4. **Observability**: Complete instance pool and routing monitoring
|
|
820
|
+
|
|
821
|
+
### Operations Advantages
|
|
822
|
+
1. **Warmup Report**: Detailed system startup status report
|
|
823
|
+
2. **Performance Insight**: Instance utilization and memory usage monitoring
|
|
824
|
+
3. **Fault Isolation**: Single instance failure doesn't affect overall system
|
|
825
|
+
4. **Dynamic Adjustment**: Support runtime instance pool configuration adjustment
|
|
826
|
+
|
|
827
|
+
This optimized design maintains the flexibility of V2 virtual pipelines while ensuring high performance through static instance pools, meeting the requirement for multi-configuration module preloading.
|