@jsonstudio/rcc 0.89.1205 → 0.89.1457
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 +53 -1412
- 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 +77 -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 +94 -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 +37 -0
- package/dist/cli/config/init-config.js +212 -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/gemini-protocol-client.js +2 -1
- package/dist/client/gemini/gemini-protocol-client.js.map +1 -1
- package/dist/client/gemini-cli/gemini-cli-protocol-client.js +40 -16
- package/dist/client/gemini-cli/gemini-cli-protocol-client.js.map +1 -1
- package/dist/client/openai/chat-protocol-client.js +2 -1
- package/dist/client/openai/chat-protocol-client.js.map +1 -1
- package/dist/client/responses/responses-protocol-client.js +2 -1
- package/dist/client/responses/responses-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/error-handling/quiet-error-handling-center.js +46 -8
- package/dist/error-handling/quiet-error-handling-center.js.map +1 -1
- 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 +239 -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 +192 -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 +293 -94
- 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/antigravity-userinfo-helper.d.ts +2 -1
- package/dist/providers/auth/antigravity-userinfo-helper.js +25 -4
- package/dist/providers/auth/antigravity-userinfo-helper.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/auth/tokenfile-auth.d.ts +2 -0
- package/dist/providers/auth/tokenfile-auth.js +33 -1
- package/dist/providers/auth/tokenfile-auth.js.map +1 -1
- package/dist/providers/core/config/camoufox-launcher.d.ts +5 -0
- package/dist/providers/core/config/camoufox-launcher.js +40 -4
- package/dist/providers/core/config/camoufox-launcher.js.map +1 -1
- package/dist/providers/core/config/service-profiles.js +7 -18
- package/dist/providers/core/config/service-profiles.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 -7
- package/dist/providers/core/runtime/base-provider.js +84 -165
- package/dist/providers/core/runtime/base-provider.js.map +1 -1
- package/dist/providers/core/runtime/gemini-cli-http-provider.d.ts +7 -0
- package/dist/providers/core/runtime/gemini-cli-http-provider.js +368 -97
- package/dist/providers/core/runtime/gemini-cli-http-provider.js.map +1 -1
- package/dist/providers/core/runtime/http-request-executor.d.ts +3 -0
- package/dist/providers/core/runtime/http-request-executor.js +110 -38
- package/dist/providers/core/runtime/http-request-executor.js.map +1 -1
- package/dist/providers/core/runtime/http-transport-provider.d.ts +17 -0
- package/dist/providers/core/runtime/http-transport-provider.js +165 -16
- 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/rate-limit-manager.d.ts +1 -12
- package/dist/providers/core/runtime/rate-limit-manager.js +4 -77
- package/dist/providers/core/runtime/rate-limit-manager.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 +36 -46
- 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 +8 -3
- package/dist/server/handlers/handler-utils.js.map +1 -1
- package/dist/server/handlers/responses-handler.js +1 -1
- package/dist/server/handlers/responses-handler.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.js +110 -34
- package/dist/server/runtime/http-server/hub-shadow-compare.js.map +1 -1
- package/dist/server/runtime/http-server/index.d.ts +5 -3
- package/dist/server/runtime/http-server/index.js +281 -136
- 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 +59 -24
- package/dist/server/runtime/http-server/request-executor.js.map +1 -1
- package/dist/server/runtime/http-server/routes.js +12 -3
- 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/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.js +2 -1
- package/dist/utils/runtime-versions.js.map +1 -1
- package/dist/utils/strip-internal-keys.d.ts +12 -0
- package/dist/utils/strip-internal-keys.js +28 -0
- package/dist/utils/strip-internal-keys.js.map +1 -0
- package/docs/ARCHITECTURE.md +402 -0
- package/docs/CHAT_PROCESS_PROTOCOL_AND_PIPELINE.md +221 -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/antigravity-gemini-format-cleanup.md +102 -0
- package/docs/antigravity-routing-contract.md +31 -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 +84 -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/servertool-framework.md +65 -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 +549 -0
- package/docs/verification/modelscope-verify.md +59 -0
- package/docs/verified-configs/README.md +60 -0
- package/docs/verified-configs/v0.45.0/README.md +244 -0
- package/docs/verified-configs/v0.45.0/lmstudio-5521-gpt-oss-20b-mlx.json +135 -0
- package/docs/verified-configs/v0.45.0/merged-config.5521.json +1205 -0
- package/docs/verified-configs/v0.45.0/merged-config.qwen-5522.json +1559 -0
- package/docs/verified-configs/v0.45.0/qwen-5522-qwen3-coder-plus-final.json +221 -0
- package/docs/verified-configs/v0.45.0/qwen-5522-qwen3-coder-plus-fixed.json +242 -0
- package/docs/verified-configs/v0.45.0/qwen-5522-qwen3-coder-plus.json +242 -0
- package/docs/web-search-service-design.md +322 -0
- package/package.json +26 -15
- package/scripts/build-core.mjs +3 -1
- package/scripts/camoufox/launch-auth.mjs +193 -58
- package/scripts/ci/repo-sanity.mjs +138 -0
- package/scripts/mock-provider/run-regressions.mjs +157 -1
- package/scripts/monitor-diff.mjs +126 -0
- package/scripts/pack-mode.mjs +19 -1
- package/scripts/pack-rcc.mjs +63 -0
- package/scripts/run-bg.sh +0 -14
- package/scripts/tests/ci-jest.mjs +119 -0
- package/scripts/tools-dev/responses-debug-client/README.md +23 -0
- package/scripts/tools-dev/responses-debug-client/payloads/poem.json +13 -0
- package/scripts/tools-dev/responses-debug-client/payloads/sample-no-tools.json +98 -0
- package/scripts/tools-dev/responses-debug-client/payloads/text.json +13 -0
- package/scripts/tools-dev/responses-debug-client/payloads/tool.json +27 -0
- package/scripts/tools-dev/responses-debug-client/run.mjs +65 -0
- package/scripts/tools-dev/responses-debug-client/src/index.ts +281 -0
- package/scripts/tools-dev/run-llmswitch-chat.mjs +53 -0
- package/scripts/tools-dev/server-tools-dev/run-web-fetch.mjs +65 -0
- package/scripts/unified-hub-shadow-compare.mjs +33 -13
- package/scripts/vendor-core.mjs +13 -3
- 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
- package/scripts/test-fc-responses.mjs +0 -66
- package/scripts/test-guidance.mjs +0 -100
- package/scripts/test-iflow-web-search.mjs +0 -141
- package/scripts/test-iflow.mjs +0 -379
- package/scripts/test-tool-exec.mjs +0 -26
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import process from 'node:process';
|
|
5
|
+
import OpenAI from 'openai';
|
|
6
|
+
|
|
7
|
+
function parseArgs(argv){ const out={}; for(let i=2;i<argv.length;i++){ const a=argv[i]; if(!a) continue; if(a.startsWith('--')){ const [k,v]=a.split('='); const key=k.replace(/^--/,''); if(typeof v==='string'&&v.length) out[key]=v; else if(i+1<argv.length && !argv[i+1].startsWith('--')) out[key]=argv[++i]; else out[key]=true; } } return out; }
|
|
8
|
+
function short(s,n=60){ return s.length<=n?s:(s.slice(0,n)+'…'); }
|
|
9
|
+
function nowIso(){ return new Date().toISOString(); }
|
|
10
|
+
async function readJson(file){ const abs=path.isAbsolute(file)?file:path.resolve(process.cwd(),file); const raw=await fs.readFile(abs,'utf-8'); return JSON.parse(raw); }
|
|
11
|
+
|
|
12
|
+
async function main(){
|
|
13
|
+
const args=parseArgs(process.argv);
|
|
14
|
+
const file=String(args.file||args.f||'');
|
|
15
|
+
if(!file){ console.error('Usage: node scripts/tools-dev/responses-debug-client/run.mjs --file <payload.json> [--baseURL URL] [--apiKey KEY] [--timeout 120] [--raw]'); process.exit(1); }
|
|
16
|
+
const baseURL=String(args.baseURL||'http://127.0.0.1:5520/v1');
|
|
17
|
+
const apiKey=String(args.apiKey||'dummy');
|
|
18
|
+
const timeoutSec=Number(args.timeout||120);
|
|
19
|
+
const raw=!!args.raw;
|
|
20
|
+
|
|
21
|
+
const body=await readJson(file);
|
|
22
|
+
if (body.stream == null) body.stream = true;
|
|
23
|
+
// attach client_request_id and snapshot request body
|
|
24
|
+
const clientRequestId = `cli_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;
|
|
25
|
+
try{
|
|
26
|
+
const meta = (body && typeof body==='object' && body.metadata && typeof body.metadata==='object') ? body.metadata : {};
|
|
27
|
+
body.metadata = { ...meta, client_request_id: clientRequestId };
|
|
28
|
+
}catch{}
|
|
29
|
+
try{
|
|
30
|
+
const home = process.env.HOME || process.env.USERPROFILE || '.';
|
|
31
|
+
const dir = path.join(String(home), '.routecodex', 'codex-samples', 'responses-client');
|
|
32
|
+
await fs.mkdir(dir, { recursive: true });
|
|
33
|
+
const out = path.join(dir, `${clientRequestId}_client-request.json`);
|
|
34
|
+
await fs.writeFile(out, JSON.stringify({ timestamp: new Date().toISOString(), baseURL, request: body }, null, 2), 'utf-8');
|
|
35
|
+
if(!raw) console.log('saved client snapshot:', out);
|
|
36
|
+
}catch{}
|
|
37
|
+
|
|
38
|
+
const client=new OpenAI({ apiKey, baseURL });
|
|
39
|
+
console.log(`[${nowIso()}] connect baseURL=${baseURL}`);
|
|
40
|
+
const start=Date.now();
|
|
41
|
+
const stream=await client.responses.stream(body);
|
|
42
|
+
let responseId='';
|
|
43
|
+
let model='';
|
|
44
|
+
let text='';
|
|
45
|
+
|
|
46
|
+
const timer=setTimeout(()=>{ try{ stream.controller?.abort?.(); }catch{}; console.error('timeout'); process.exitCode=3; }, timeoutSec*1000);
|
|
47
|
+
|
|
48
|
+
for await (const ev of stream){
|
|
49
|
+
const t=ev?.type||'event';
|
|
50
|
+
const d=ev?.data ?? ev;
|
|
51
|
+
if(raw){ console.log('evt', t, JSON.stringify(d)); }
|
|
52
|
+
switch(t){
|
|
53
|
+
case 'response.created': responseId=String(d?.response?.id||responseId); model=String(d?.response?.model||model); console.log('created', responseId, model); break;
|
|
54
|
+
case 'response.output_text.delta': { const s=String(d?.delta||''); text+=s; console.log('textΔ', s.length, short(s)); break; }
|
|
55
|
+
case 'response.output_text.done': console.log('text✓ total', text.length); break;
|
|
56
|
+
case 'response.completed': console.log('completed', JSON.stringify(d?.response?.usage||{})); break;
|
|
57
|
+
case 'response.required_action': console.log('required_action', JSON.stringify(d?.required_action||d)); break;
|
|
58
|
+
case 'response.error': console.error('error', JSON.stringify(d?.error||d)); process.exitCode=2; break;
|
|
59
|
+
case 'response.done': { const ms=Date.now()-start; console.log('done', ms,'ms'); clearTimeout(timer); return; }
|
|
60
|
+
default: break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
main().catch(e=>{ console.error('fatal', e?.message||String(e)); process.exit(2); });
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Responses Debug Client
|
|
4
|
+
* - Connects to RCC server (baseURL) using OpenAI SDK Responses stream
|
|
5
|
+
* - Consumes SSE named events, prints concise logs
|
|
6
|
+
* - Completes a minimal tool-calls loop by executing local tools and submitting outputs
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import fs from 'node:fs/promises';
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
import process from 'node:process';
|
|
12
|
+
import OpenAI from 'openai';
|
|
13
|
+
|
|
14
|
+
type Unknown = Record<string, any>;
|
|
15
|
+
|
|
16
|
+
function parseArgs(argv: string[]): Record<string, string | boolean> {
|
|
17
|
+
const out: Record<string, string | boolean> = {};
|
|
18
|
+
for (let i = 2; i < argv.length; i++) {
|
|
19
|
+
const a = argv[i];
|
|
20
|
+
if (!a) continue;
|
|
21
|
+
if (a.startsWith('--')) {
|
|
22
|
+
const [k, v] = a.split('=');
|
|
23
|
+
const key = k.replace(/^--/, '');
|
|
24
|
+
if (typeof v === 'string' && v.length) out[key] = v;
|
|
25
|
+
else if (i + 1 < argv.length && !argv[i + 1].startsWith('--')) { out[key] = argv[++i]; }
|
|
26
|
+
else out[key] = true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function short(s: string, n = 60): string {
|
|
33
|
+
if (s.length <= n) return s;
|
|
34
|
+
return s.slice(0, n) + '…';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function nowIso(): string { return new Date().toISOString(); }
|
|
38
|
+
|
|
39
|
+
async function readJson(file: string): Promise<Unknown> {
|
|
40
|
+
const abs = path.isAbsolute(file) ? file : path.resolve(process.cwd(), file);
|
|
41
|
+
const raw = await fs.readFile(abs, 'utf-8');
|
|
42
|
+
return JSON.parse(raw) as Unknown;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
type ToolOutput = { tool_call_id: string; output: string };
|
|
46
|
+
|
|
47
|
+
function safeJsonParse(s: string): any {
|
|
48
|
+
try { return JSON.parse(s); } catch { return s; }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Minimal local tool handlers
|
|
52
|
+
const localTools: Record<string, (args: any) => Promise<string> | string> = {
|
|
53
|
+
echo: (args: any) => {
|
|
54
|
+
if (typeof args?.text === 'string') return String(args.text);
|
|
55
|
+
return typeof args === 'string' ? args : JSON.stringify(args ?? {});
|
|
56
|
+
},
|
|
57
|
+
sum: (args: any) => {
|
|
58
|
+
const arr = Array.isArray(args?.numbers) ? args.numbers : [];
|
|
59
|
+
const total = arr.reduce((a: number, b: any) => a + (typeof b === 'number' ? b : 0), 0);
|
|
60
|
+
return String(total);
|
|
61
|
+
},
|
|
62
|
+
time: () => new Date().toISOString(),
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
async function executeTool(name: string, argStr: string): Promise<string> {
|
|
66
|
+
const n = String(name || '').trim();
|
|
67
|
+
const handler = localTools[n] || (async () => `Unsupported tool: ${n}`);
|
|
68
|
+
const args = typeof argStr === 'string' ? safeJsonParse(argStr) : argStr;
|
|
69
|
+
try { return await handler(args); } catch (e: any) { return `Tool error: ${e?.message || String(e)}`; }
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function main() {
|
|
73
|
+
const args = parseArgs(process.argv);
|
|
74
|
+
const file = String(args.file || args.f || '');
|
|
75
|
+
if (!file) {
|
|
76
|
+
console.error('Usage: tsx scripts/tools-dev/responses-debug-client/src/index.ts --file <payload.json> [--baseURL URL] [--apiKey KEY] [--timeout 120] [--raw] [--save] [--maxRounds 3]');
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
const baseURL = String(args.baseURL || 'http://127.0.0.1:5520/v1');
|
|
80
|
+
const apiKey = String(args.apiKey || 'dummy');
|
|
81
|
+
const timeoutSec = Number(args.timeout || 120);
|
|
82
|
+
const raw = !!args.raw;
|
|
83
|
+
const save = !!args.save;
|
|
84
|
+
const maxRounds = Math.max(1, Number(args.maxRounds || 3));
|
|
85
|
+
|
|
86
|
+
const reqBody = await readJson(file);
|
|
87
|
+
if (reqBody.stream == null) reqBody.stream = true;
|
|
88
|
+
|
|
89
|
+
// Attach a client-side request id into payload.metadata for correlation
|
|
90
|
+
const clientRequestId = `cli_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
91
|
+
try {
|
|
92
|
+
const meta = (reqBody && typeof reqBody === 'object' && (reqBody as any).metadata && typeof (reqBody as any).metadata === 'object')
|
|
93
|
+
? (reqBody as any).metadata : {};
|
|
94
|
+
(reqBody as any).metadata = { ...meta, client_request_id: clientRequestId };
|
|
95
|
+
} catch { /* ignore */ }
|
|
96
|
+
|
|
97
|
+
// Snapshot exact client request body to ~/.routecodex/codex-samples/responses-client/
|
|
98
|
+
try {
|
|
99
|
+
const home = process.env.HOME || process.env.USERPROFILE || '.';
|
|
100
|
+
const dir = path.join(String(home), '.routecodex', 'codex-samples', 'responses-client');
|
|
101
|
+
await fs.mkdir(dir, { recursive: true });
|
|
102
|
+
const out = path.join(dir, `${clientRequestId}_client-request.json`);
|
|
103
|
+
await fs.writeFile(out, JSON.stringify({
|
|
104
|
+
timestamp: new Date().toISOString(),
|
|
105
|
+
baseURL,
|
|
106
|
+
request: reqBody
|
|
107
|
+
}, null, 2), 'utf-8');
|
|
108
|
+
if (!raw) console.log(`[${nowIso()}] saved client snapshot: ${out}`);
|
|
109
|
+
} catch { /* non-blocking */ }
|
|
110
|
+
|
|
111
|
+
const client = new OpenAI({ apiKey, baseURL });
|
|
112
|
+
const start = Date.now();
|
|
113
|
+
console.log(`[${nowIso()}] connect baseURL=${baseURL}`);
|
|
114
|
+
|
|
115
|
+
const stream: any = await client.responses.stream(reqBody as any);
|
|
116
|
+
let responseId = '';
|
|
117
|
+
let model = '';
|
|
118
|
+
let round = 1;
|
|
119
|
+
const textBuf: string[] = [];
|
|
120
|
+
|
|
121
|
+
// tool state
|
|
122
|
+
const toolArgs: Record<string, string> = {};
|
|
123
|
+
const toolMeta: Record<string, { name?: string; output_index?: number; type?: string }> = {};
|
|
124
|
+
let sawRequiredAction = false;
|
|
125
|
+
let submittedThisRound = false;
|
|
126
|
+
const seqCheck = { last: -1 };
|
|
127
|
+
|
|
128
|
+
const writeLine = async (o: any) => {
|
|
129
|
+
if (!save) return;
|
|
130
|
+
try {
|
|
131
|
+
const dir = path.resolve(process.cwd(), 'logs', 'responses-debug', responseId || 'unknown');
|
|
132
|
+
await fs.mkdir(dir, { recursive: true });
|
|
133
|
+
await fs.appendFile(path.join(dir, 'events.jsonl'), JSON.stringify({ ts: Date.now(), ...o }) + '\n', 'utf-8');
|
|
134
|
+
} catch { /* ignore */ }
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const submitToolOutputs = async (requiredAction: any) => {
|
|
138
|
+
const tc = Array.isArray(requiredAction?.submit_tool_outputs?.tool_calls)
|
|
139
|
+
? requiredAction.submit_tool_outputs.tool_calls : [];
|
|
140
|
+
const outputs: ToolOutput[] = [];
|
|
141
|
+
for (const call of tc) {
|
|
142
|
+
const id = String(call?.id || '');
|
|
143
|
+
const name = String(call?.function?.name || '');
|
|
144
|
+
const argStr = String(call?.function?.arguments || '');
|
|
145
|
+
const out = await executeTool(name, argStr);
|
|
146
|
+
outputs.push({ tool_call_id: id, output: out });
|
|
147
|
+
console.log(` ↳ tool[${name}] id=${id} -> output(${out.length})`);
|
|
148
|
+
}
|
|
149
|
+
if (typeof stream.submitToolOutputs === 'function') {
|
|
150
|
+
console.log(` -> submitToolOutputs(${outputs.length}) via stream`);
|
|
151
|
+
await stream.submitToolOutputs({ tool_outputs: outputs, stream: true });
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
throw new Error('SDK stream.submitToolOutputs unavailable; please upgrade openai package');
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const dumpEvent = (ev: any) => {
|
|
158
|
+
const t = ev?.type || 'event';
|
|
159
|
+
const d = ev?.data ?? ev;
|
|
160
|
+
const seq = typeof d?.sequence_number === 'number' ? d.sequence_number : undefined;
|
|
161
|
+
if (typeof seq === 'number') {
|
|
162
|
+
if (seq <= seqCheck.last) console.warn(` ! sequence rollback: ${seqCheck.last} -> ${seq}`);
|
|
163
|
+
seqCheck.last = seq;
|
|
164
|
+
}
|
|
165
|
+
if (raw) console.log('evt', t, JSON.stringify(d));
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
for await (const ev of stream) {
|
|
169
|
+
await writeLine({ type: ev?.type || 'event', data: ev });
|
|
170
|
+
dumpEvent(ev);
|
|
171
|
+
|
|
172
|
+
switch (ev?.type) {
|
|
173
|
+
case 'response.created': {
|
|
174
|
+
responseId = String(ev?.data?.response?.id || responseId);
|
|
175
|
+
model = String(ev?.data?.response?.model || model);
|
|
176
|
+
console.log(`created id=${responseId} model=${model}`);
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
case 'response.in_progress': {
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
case 'response.output_text.delta': {
|
|
183
|
+
const s = String(ev?.data?.delta || '');
|
|
184
|
+
textBuf.push(s);
|
|
185
|
+
console.log(` textΔ(${s.length}): ${short(s)}`);
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
case 'response.output_text.done': {
|
|
189
|
+
console.log(` text✓ (total=${textBuf.join('').length})`);
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
case 'response.output_item.added': {
|
|
193
|
+
const item = ev?.data?.item || {};
|
|
194
|
+
const id = String(item?.id || '');
|
|
195
|
+
toolMeta[id] = { name: item?.name, output_index: ev?.data?.output_index, type: item?.type };
|
|
196
|
+
toolArgs[id] = toolArgs[id] || '';
|
|
197
|
+
console.log(` tool+ id=${id} name=${item?.name || ''}`);
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
case 'response.function_call_arguments.delta': {
|
|
201
|
+
const id = String(ev?.data?.id || ev?.data?.item_id || '');
|
|
202
|
+
const d = String(ev?.data?.delta || '');
|
|
203
|
+
toolArgs[id] = (toolArgs[id] || '') + d;
|
|
204
|
+
console.log(` argsΔ id=${id} (+${d.length})`);
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
case 'response.function_call_arguments.done': {
|
|
208
|
+
const id = String(ev?.data?.id || ev?.data?.item_id || '');
|
|
209
|
+
const total = (toolArgs[id] || '').length;
|
|
210
|
+
console.log(` args✓ id=${id} (${total})`);
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
case 'response.output_item.done': {
|
|
214
|
+
const item = ev?.data?.item || {};
|
|
215
|
+
const id = String(item?.id || '');
|
|
216
|
+
console.log(` tool✓ id=${id}`);
|
|
217
|
+
// Fallback path for providers不发 required_action:在 function_call 完成后立即提交工具输出
|
|
218
|
+
if (!sawRequiredAction && !submittedThisRound && (toolMeta[id]?.type === 'function_call')) {
|
|
219
|
+
const name = toolMeta[id]?.name || item?.name || '';
|
|
220
|
+
const argStr = item?.arguments || toolArgs[id] || '';
|
|
221
|
+
const outputs: ToolOutput[] = [{ tool_call_id: id, output: await executeTool(name, String(argStr)) }];
|
|
222
|
+
if (typeof stream.submitToolOutputs === 'function') {
|
|
223
|
+
console.log(` -> submitToolOutputs(fallback, ${outputs.length}) via stream [round ${round}]`);
|
|
224
|
+
await stream.submitToolOutputs({ tool_outputs: outputs, stream: true });
|
|
225
|
+
submittedThisRound = true;
|
|
226
|
+
round++;
|
|
227
|
+
if (round > maxRounds) throw new Error(`Exceeded maxRounds=${maxRounds}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
case 'response.required_action': {
|
|
233
|
+
const ra = ev?.data?.required_action || ev?.data; // SDK shape varies
|
|
234
|
+
const count = Array.isArray(ra?.submit_tool_outputs?.tool_calls) ? ra.submit_tool_outputs.tool_calls.length : 0;
|
|
235
|
+
console.log(` required_action submit_tool_outputs(${count}) [round ${round}]`);
|
|
236
|
+
sawRequiredAction = true;
|
|
237
|
+
await submitToolOutputs(ra);
|
|
238
|
+
round++;
|
|
239
|
+
if (round > maxRounds) throw new Error(`Exceeded maxRounds=${maxRounds}`);
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
case 'response.completed': {
|
|
243
|
+
const u = ev?.data?.response?.usage || {};
|
|
244
|
+
const iu = Number(u?.input_tokens || 0);
|
|
245
|
+
const ou = Number(u?.output_tokens || 0);
|
|
246
|
+
const tt = Number(u?.total_tokens || 0);
|
|
247
|
+
console.log(` completed usage: in=${iu} out=${ou} total=${tt}`);
|
|
248
|
+
// Reset per-round flags to allow下一轮
|
|
249
|
+
submittedThisRound = false;
|
|
250
|
+
sawRequiredAction = false;
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
case 'response.error': {
|
|
254
|
+
console.error(' error:', ev?.data?.error);
|
|
255
|
+
process.exitCode = 2;
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
case 'response.done': {
|
|
259
|
+
const ms = Date.now() - start;
|
|
260
|
+
console.log(` done in ${ms} ms`);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
default: {
|
|
264
|
+
// Heartbeat or unknown event
|
|
265
|
+
const d = ev?.data;
|
|
266
|
+
if (d && typeof d === 'object' && d.type === 'heartbeat') {
|
|
267
|
+
// ignore
|
|
268
|
+
} else if (!raw) {
|
|
269
|
+
// print brief unknowns
|
|
270
|
+
const t = String(ev?.type || 'evt');
|
|
271
|
+
console.log(` ${t}`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
main().catch((e) => {
|
|
279
|
+
console.error('fatal:', e?.message || String(e));
|
|
280
|
+
process.exit(2);
|
|
281
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Quick llmswitch-core Chat filter runner: runStandardChatRequestFilters without starting server.
|
|
3
|
+
// Usage:
|
|
4
|
+
// node scripts/tools-dev/run-llmswitch-chat.mjs path/to/chat-request.json [/v1/chat|/v1/messages|/v1/responses]
|
|
5
|
+
|
|
6
|
+
import fs from 'fs';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import url from 'url';
|
|
9
|
+
import { runStandardChatRequestFilters } from '../../sharedmodule/llmswitch-core/dist/conversion/index.js';
|
|
10
|
+
|
|
11
|
+
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
|
|
12
|
+
|
|
13
|
+
async function main() {
|
|
14
|
+
const file = process.argv[2];
|
|
15
|
+
const endpoint = process.argv[3] || '/v1/chat/completions';
|
|
16
|
+
|
|
17
|
+
if (!file) {
|
|
18
|
+
console.error('Usage: node scripts/tools-dev/run-llmswitch-chat.mjs <payload.json> [endpoint]');
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const abs = path.isAbsolute(file) ? file : path.join(process.cwd(), file);
|
|
23
|
+
const txt = fs.readFileSync(abs, 'utf8');
|
|
24
|
+
const raw = JSON.parse(txt);
|
|
25
|
+
|
|
26
|
+
// Allow passing either a raw chat body, or a provider-request snapshot with { endpoint, data: { body } }
|
|
27
|
+
let payload = raw;
|
|
28
|
+
if (raw && typeof raw === 'object' && raw.data && typeof raw.data === 'object' && raw.data.body) {
|
|
29
|
+
payload = raw.data.body;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const requestId = `req_${Date.now()}`;
|
|
33
|
+
const profile = {
|
|
34
|
+
id: 'test-profile',
|
|
35
|
+
incomingProtocol: 'openai-chat',
|
|
36
|
+
outgoingProtocol: 'openai-chat'
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const context = {
|
|
40
|
+
requestId,
|
|
41
|
+
entryEndpoint: endpoint,
|
|
42
|
+
endpoint,
|
|
43
|
+
metadata: {}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const out = await runStandardChatRequestFilters(payload, profile, context);
|
|
47
|
+
process.stdout.write(JSON.stringify(out, null, 2) + '\n');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
main().catch(err => {
|
|
51
|
+
console.error('Error running llmswitch filters:', err);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
});
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
5
|
+
function parseArgs(argv) {
|
|
6
|
+
const out = { url: null, timeout: null, maxBytes: null, follow: true, headers: {} };
|
|
7
|
+
for (let i = 2; i < argv.length; i++) {
|
|
8
|
+
const a = argv[i];
|
|
9
|
+
if ((a === '--url' || a === '-u') && i + 1 < argv.length) { out.url = argv[++i]; continue; }
|
|
10
|
+
if ((a === '--timeout' || a === '-t') && i + 1 < argv.length) { out.timeout = Number(argv[++i]); continue; }
|
|
11
|
+
if (a === '--no-follow') { out.follow = false; continue; }
|
|
12
|
+
if ((a === '--max-bytes' || a === '-m') && i + 1 < argv.length) { out.maxBytes = Number(argv[++i]); continue; }
|
|
13
|
+
if ((a === '--header' || a === '-H') && i + 1 < argv.length) {
|
|
14
|
+
const kv = String(argv[++i]);
|
|
15
|
+
const idx = kv.indexOf(':');
|
|
16
|
+
if (idx > 0) { const k = kv.slice(0, idx).trim(); const v = kv.slice(idx + 1).trim(); if (k) out.headers[k] = v; }
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (a === '--help' || a === '-h') { out.help = true; }
|
|
20
|
+
}
|
|
21
|
+
return out;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function usage() {
|
|
25
|
+
console.log('Usage: node scripts/tools-dev/server-tools-dev/run-web-fetch.mjs --url <URL> [--timeout 12000] [--max-bytes 524288] [--no-follow] [--header "Key: Value"]');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function importCoreFetcher() {
|
|
29
|
+
// Prefer local sharedmodule path if exists; fallback to installed package
|
|
30
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
31
|
+
const repoRoot = path.resolve(path.dirname(__filename), '../..');
|
|
32
|
+
const local = path.resolve(repoRoot, 'sharedmodule/llmswitch-core/dist/tools/web-fetch-html.js');
|
|
33
|
+
try {
|
|
34
|
+
const mod = await import(pathToFileURL(local).href);
|
|
35
|
+
if (typeof mod?.fetchRawHtml === 'function') return mod.fetchRawHtml;
|
|
36
|
+
} catch {}
|
|
37
|
+
throw new Error('Cannot locate fetchRawHtml in sharedmodule/llmswitch-core/dist。请先构建 sharedmodule/llmswitch-core。');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function main() {
|
|
41
|
+
const args = parseArgs(process.argv);
|
|
42
|
+
if (args.help || !args.url) { usage(); process.exit(args.help ? 0 : 1); }
|
|
43
|
+
const fetchRawHtml = await importCoreFetcher();
|
|
44
|
+
const res = await fetchRawHtml(args.url, {
|
|
45
|
+
timeoutMs: args.timeout || undefined,
|
|
46
|
+
followRedirects: args.follow,
|
|
47
|
+
maxBytes: args.maxBytes || undefined,
|
|
48
|
+
headers: Object.keys(args.headers).length ? args.headers : undefined,
|
|
49
|
+
});
|
|
50
|
+
if (res.ok) {
|
|
51
|
+
console.log('OK');
|
|
52
|
+
console.log(`status: ${res.status}`);
|
|
53
|
+
console.log(`content-type: ${res.contentType}`);
|
|
54
|
+
const preview = res.html ?? '';
|
|
55
|
+
console.log('--- html (first 2048 chars) ---');
|
|
56
|
+
console.log(preview.slice(0, 2048));
|
|
57
|
+
} else {
|
|
58
|
+
console.log('FAIL');
|
|
59
|
+
console.log(`error: ${res.error}`);
|
|
60
|
+
if (res.status) console.log(`status: ${res.status}`);
|
|
61
|
+
if (res.contentType) console.log(`content-type: ${res.contentType}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
main().catch((e) => { console.error(e); process.exit(99); });
|
|
@@ -141,6 +141,14 @@ function stableStringify(value) {
|
|
|
141
141
|
);
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
function cloneJsonSafe(value) {
|
|
145
|
+
try {
|
|
146
|
+
return JSON.parse(JSON.stringify(value));
|
|
147
|
+
} catch {
|
|
148
|
+
return value;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
144
152
|
function diffPayloads(expected, actual, p = '<root>') {
|
|
145
153
|
if (Object.is(expected, actual)) return [];
|
|
146
154
|
if (typeof expected !== typeof actual) {
|
|
@@ -254,12 +262,12 @@ async function bootstrapVirtualRouterConfig(rawConfig) {
|
|
|
254
262
|
return mod.bootstrapVirtualRouterConfig(rawConfig);
|
|
255
263
|
}
|
|
256
264
|
|
|
257
|
-
async function runOnce({ requestId,
|
|
265
|
+
async function runOnce({ requestId, candidateMode, baselineMode, entryEndpoint, routeHint, payload }) {
|
|
258
266
|
const HubPipeline = await importHubPipelineCtor();
|
|
259
267
|
const artifacts = await bootstrapVirtualRouterConfig(buildVirtualRouterConfig());
|
|
260
268
|
const pipeline = new HubPipeline({
|
|
261
269
|
virtualRouter: artifacts.config,
|
|
262
|
-
policy: { mode }
|
|
270
|
+
policy: { mode: candidateMode }
|
|
263
271
|
});
|
|
264
272
|
const providerProtocol = normalizeEntryProviderProtocol(entryEndpoint);
|
|
265
273
|
const result = await pipeline.execute({
|
|
@@ -269,7 +277,10 @@ async function runOnce({ requestId, mode, entryEndpoint, routeHint, payload }) {
|
|
|
269
277
|
metadata: {
|
|
270
278
|
entryEndpoint,
|
|
271
279
|
providerProtocol,
|
|
272
|
-
routeHint
|
|
280
|
+
routeHint,
|
|
281
|
+
__hubShadowCompare: {
|
|
282
|
+
baselineMode
|
|
283
|
+
}
|
|
273
284
|
}
|
|
274
285
|
});
|
|
275
286
|
return result;
|
|
@@ -300,18 +311,24 @@ async function main() {
|
|
|
300
311
|
const candidateMode = String(opts.candidateMode);
|
|
301
312
|
const requestId = `shadow_unified_hub_${Date.now()}`;
|
|
302
313
|
|
|
303
|
-
const
|
|
304
|
-
const
|
|
314
|
+
const candidate = await runOnce({ requestId, candidateMode, baselineMode, entryEndpoint, routeHint, payload });
|
|
315
|
+
const shadow = candidate && candidate.metadata && typeof candidate.metadata === 'object'
|
|
316
|
+
? candidate.metadata.hubShadowCompare
|
|
317
|
+
: undefined;
|
|
318
|
+
const baselineProviderPayload =
|
|
319
|
+
shadow && typeof shadow === 'object' && shadow && !Array.isArray(shadow)
|
|
320
|
+
? shadow.baselineProviderPayload
|
|
321
|
+
: undefined;
|
|
305
322
|
|
|
306
323
|
const baselineOut = {
|
|
307
|
-
providerPayload:
|
|
308
|
-
target:
|
|
324
|
+
providerPayload: baselineProviderPayload,
|
|
325
|
+
target: candidate.target,
|
|
309
326
|
metadata: {
|
|
310
|
-
entryEndpoint:
|
|
311
|
-
providerProtocol:
|
|
312
|
-
processMode:
|
|
313
|
-
stream:
|
|
314
|
-
routeHint:
|
|
327
|
+
entryEndpoint: candidate.metadata?.entryEndpoint,
|
|
328
|
+
providerProtocol: candidate.metadata?.providerProtocol,
|
|
329
|
+
processMode: candidate.metadata?.processMode,
|
|
330
|
+
stream: candidate.metadata?.stream,
|
|
331
|
+
routeHint: candidate.metadata?.routeHint
|
|
315
332
|
}
|
|
316
333
|
};
|
|
317
334
|
const candidateOut = {
|
|
@@ -326,7 +343,10 @@ async function main() {
|
|
|
326
343
|
}
|
|
327
344
|
};
|
|
328
345
|
|
|
329
|
-
|
|
346
|
+
if (!baselineProviderPayload || typeof baselineProviderPayload !== 'object') {
|
|
347
|
+
throw new Error('[unified-hub-shadow-compare] hubShadowCompare.baselineProviderPayload missing; ensure llmswitch-core is rebuilt.');
|
|
348
|
+
}
|
|
349
|
+
const diffs = diffPayloads(cloneJsonSafe(baselineOut), cloneJsonSafe(candidateOut));
|
|
330
350
|
if (!diffs.length) {
|
|
331
351
|
console.log('[unified-hub-shadow-compare] OK diff=0');
|
|
332
352
|
return;
|
package/scripts/vendor-core.mjs
CHANGED
|
@@ -12,12 +12,18 @@ async function rmrf(p) {
|
|
|
12
12
|
|
|
13
13
|
async function main() {
|
|
14
14
|
const root = process.cwd();
|
|
15
|
+
const rawMode = String(process.env.BUILD_MODE || process.env.RCC_BUILD_MODE || 'release').toLowerCase();
|
|
16
|
+
const mode = rawMode === 'dev' ? 'dev' : 'release';
|
|
15
17
|
const sharedDist = path.join(root, 'sharedmodule', 'llmswitch-core', 'dist');
|
|
16
18
|
const legacyVendorDir = path.join(root, 'vendor', 'rcc-llmswitch-core');
|
|
17
19
|
const scopedVendorDir = path.join(root, 'vendor', '@jsonstudio', 'llms');
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
// In release mode we rely on npm-installed `@jsonstudio/llms`, so the local sharedmodule dist
|
|
22
|
+
// is optional and must not block CI (where sharedmodule often doesn't exist).
|
|
23
|
+
// In dev mode, `node_modules/@jsonstudio/llms` is typically symlinked to sharedmodule/llmswitch-core,
|
|
24
|
+
// so we keep a hard requirement for the dist output.
|
|
25
|
+
if (mode === 'dev' && !await exists(sharedDist)) {
|
|
26
|
+
console.error('[vendor-core] ERROR: 未找到 sharedmodule/llmswitch-core/dist (BUILD_MODE=dev)');
|
|
21
27
|
console.error('[vendor-core] 请先进入 sharedmodule/llmswitch-core 并运行 `npm run build`。');
|
|
22
28
|
process.exit(2);
|
|
23
29
|
}
|
|
@@ -31,7 +37,11 @@ async function main() {
|
|
|
31
37
|
console.log('[vendor-core] removed legacy vendor/@jsonstudio/llms directory');
|
|
32
38
|
}
|
|
33
39
|
|
|
34
|
-
|
|
40
|
+
if (mode === 'dev') {
|
|
41
|
+
console.log('[vendor-core] sharedmodule/llmswitch-core/dist 将被直接引用,已停止生成 vendor 副本。');
|
|
42
|
+
} else {
|
|
43
|
+
console.log('[vendor-core] BUILD_MODE=release: using npm-installed @jsonstudio/llms (no vendor copy).');
|
|
44
|
+
}
|
|
35
45
|
}
|
|
36
46
|
|
|
37
47
|
main().catch((err) => {
|