@jsonstudio/rcc 0.89.1205 → 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.
Files changed (332) hide show
  1. package/README.md +17 -0
  2. package/configsamples/config.json +426 -0
  3. package/configsamples/config.reference.json +58 -0
  4. package/configsamples/provider/crs/config.v1.json +46 -0
  5. package/configsamples/provider/glm/config.v1.json +81 -0
  6. package/configsamples/provider/glm-anthropic/config.v1.json +45 -0
  7. package/configsamples/provider/iflow/config.v1.json +74 -0
  8. package/configsamples/provider/kimi/config.v1.json +41 -0
  9. package/configsamples/provider/lmstudio/config.v1.json +101 -0
  10. package/configsamples/provider/mimo/config.v1.json +35 -0
  11. package/configsamples/provider/modelscope/config.v1.json +96 -0
  12. package/configsamples/provider/qwen/config.v1.json +38 -0
  13. package/configsamples/provider/tab/config.v1.json +50 -0
  14. package/configsamples/provider/tabglm/config.v1.json +49 -0
  15. package/dist/build-info.js +2 -2
  16. package/dist/cli/commands/code.js +12 -6
  17. package/dist/cli/commands/code.js.map +1 -1
  18. package/dist/cli/commands/config.d.ts +2 -1
  19. package/dist/cli/commands/config.js +74 -103
  20. package/dist/cli/commands/config.js.map +1 -1
  21. package/dist/cli/commands/examples.js +6 -6
  22. package/dist/cli/commands/examples.js.map +1 -1
  23. package/dist/cli/commands/init.d.ts +28 -0
  24. package/dist/cli/commands/init.js +91 -0
  25. package/dist/cli/commands/init.js.map +1 -0
  26. package/dist/cli/commands/port.js +10 -2
  27. package/dist/cli/commands/port.js.map +1 -1
  28. package/dist/cli/commands/restart.js +5 -2
  29. package/dist/cli/commands/restart.js.map +1 -1
  30. package/dist/cli/commands/start.js +25 -22
  31. package/dist/cli/commands/start.js.map +1 -1
  32. package/dist/cli/commands/status.js +1 -0
  33. package/dist/cli/commands/status.js.map +1 -1
  34. package/dist/cli/commands/stop.js +1 -0
  35. package/dist/cli/commands/stop.js.map +1 -1
  36. package/dist/cli/config/bundled-docs.d.ts +20 -0
  37. package/dist/cli/config/bundled-docs.js +91 -0
  38. package/dist/cli/config/bundled-docs.js.map +1 -0
  39. package/dist/cli/config/init-config.d.ts +36 -0
  40. package/dist/cli/config/init-config.js +180 -0
  41. package/dist/cli/config/init-config.js.map +1 -0
  42. package/dist/cli/config/init-provider-catalog.d.ts +8 -0
  43. package/dist/cli/config/init-provider-catalog.js +187 -0
  44. package/dist/cli/config/init-provider-catalog.js.map +1 -0
  45. package/dist/cli/register/init-command.d.ts +3 -0
  46. package/dist/cli/register/init-command.js +5 -0
  47. package/dist/cli/register/init-command.js.map +1 -0
  48. package/dist/cli.js +28 -3
  49. package/dist/cli.js.map +1 -1
  50. package/dist/client/gemini-cli/gemini-cli-protocol-client.js +1 -1
  51. package/dist/client/gemini-cli/gemini-cli-protocol-client.js.map +1 -1
  52. package/dist/config/risk-control-config.d.ts +94 -0
  53. package/dist/config/risk-control-config.js +196 -0
  54. package/dist/config/risk-control-config.js.map +1 -0
  55. package/dist/constants/index.d.ts +6 -0
  56. package/dist/constants/index.js +13 -0
  57. package/dist/constants/index.js.map +1 -1
  58. package/dist/docs/daemon-admin-ui.html +2113 -190
  59. package/dist/index.js +0 -1
  60. package/dist/index.js.map +1 -1
  61. package/dist/manager/modules/health/index.d.ts +1 -1
  62. package/dist/manager/modules/quota/antigravity-quota-manager.d.ts +70 -0
  63. package/dist/manager/modules/quota/antigravity-quota-manager.js +442 -0
  64. package/dist/manager/modules/quota/antigravity-quota-manager.js.map +1 -0
  65. package/dist/manager/modules/quota/index.d.ts +3 -127
  66. package/dist/manager/modules/quota/index.js +2 -1093
  67. package/dist/manager/modules/quota/index.js.map +1 -1
  68. package/dist/manager/modules/quota/provider-key-normalization.d.ts +3 -0
  69. package/dist/manager/modules/quota/provider-key-normalization.js +155 -0
  70. package/dist/manager/modules/quota/provider-key-normalization.js.map +1 -0
  71. package/dist/manager/modules/quota/provider-quota-daemon.cooldown.d.ts +9 -0
  72. package/dist/manager/modules/quota/provider-quota-daemon.cooldown.js +115 -0
  73. package/dist/manager/modules/quota/provider-quota-daemon.cooldown.js.map +1 -0
  74. package/dist/manager/modules/quota/provider-quota-daemon.d.ts +77 -0
  75. package/dist/manager/modules/quota/provider-quota-daemon.events.d.ts +12 -0
  76. package/dist/manager/modules/quota/provider-quota-daemon.events.js +237 -0
  77. package/dist/manager/modules/quota/provider-quota-daemon.events.js.map +1 -0
  78. package/dist/manager/modules/quota/provider-quota-daemon.js +404 -0
  79. package/dist/manager/modules/quota/provider-quota-daemon.js.map +1 -0
  80. package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.d.ts +11 -0
  81. package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.js +189 -0
  82. package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.js.map +1 -0
  83. package/dist/manager/modules/quota/provider-quota-daemon.snapshot.d.ts +8 -0
  84. package/dist/manager/modules/quota/provider-quota-daemon.snapshot.js +96 -0
  85. package/dist/manager/modules/quota/provider-quota-daemon.snapshot.js.map +1 -0
  86. package/dist/manager/modules/quota/provider-quota-daemon.view.d.ts +19 -0
  87. package/dist/manager/modules/quota/provider-quota-daemon.view.js +37 -0
  88. package/dist/manager/modules/quota/provider-quota-daemon.view.js.map +1 -0
  89. package/dist/manager/modules/routing/index.d.ts +1 -0
  90. package/dist/manager/modules/routing/index.js +11 -25
  91. package/dist/manager/modules/routing/index.js.map +1 -1
  92. package/dist/manager/quota/provider-quota-center.d.ts +2 -0
  93. package/dist/manager/quota/provider-quota-center.js +80 -82
  94. package/dist/manager/quota/provider-quota-center.js.map +1 -1
  95. package/dist/modules/llmswitch/bridge.d.ts +16 -18
  96. package/dist/modules/llmswitch/bridge.js +293 -94
  97. package/dist/modules/llmswitch/bridge.js.map +1 -1
  98. package/dist/modules/llmswitch/core-loader.d.ts +4 -2
  99. package/dist/modules/llmswitch/core-loader.js +32 -20
  100. package/dist/modules/llmswitch/core-loader.js.map +1 -1
  101. package/dist/modules/pipeline/utils/colored-logger.js +3 -2
  102. package/dist/modules/pipeline/utils/colored-logger.js.map +1 -1
  103. package/dist/modules/pipeline/utils/debug-logger.js +1 -1
  104. package/dist/modules/pipeline/utils/debug-logger.js.map +1 -1
  105. package/dist/providers/auth/iflow-cookie-auth.js +0 -2
  106. package/dist/providers/auth/iflow-cookie-auth.js.map +1 -1
  107. package/dist/providers/auth/oauth-lifecycle.js +2 -23
  108. package/dist/providers/auth/oauth-lifecycle.js.map +1 -1
  109. package/dist/providers/core/config/camoufox-launcher.js +35 -4
  110. package/dist/providers/core/config/camoufox-launcher.js.map +1 -1
  111. package/dist/providers/core/runtime/antigravity-quota-client.js +6 -3
  112. package/dist/providers/core/runtime/antigravity-quota-client.js.map +1 -1
  113. package/dist/providers/core/runtime/base-provider.d.ts +2 -2
  114. package/dist/providers/core/runtime/base-provider.js +74 -69
  115. package/dist/providers/core/runtime/base-provider.js.map +1 -1
  116. package/dist/providers/core/runtime/gemini-cli-http-provider.js +6 -4
  117. package/dist/providers/core/runtime/gemini-cli-http-provider.js.map +1 -1
  118. package/dist/providers/core/runtime/http-request-executor.js +2 -2
  119. package/dist/providers/core/runtime/http-request-executor.js.map +1 -1
  120. package/dist/providers/core/runtime/http-transport-provider.d.ts +14 -0
  121. package/dist/providers/core/runtime/http-transport-provider.js +111 -5
  122. package/dist/providers/core/runtime/http-transport-provider.js.map +1 -1
  123. package/dist/providers/core/runtime/provider-error-classifier.js +10 -0
  124. package/dist/providers/core/runtime/provider-error-classifier.js.map +1 -1
  125. package/dist/providers/core/runtime/provider-factory.js +7 -5
  126. package/dist/providers/core/runtime/provider-factory.js.map +1 -1
  127. package/dist/providers/core/runtime/provider-runtime-metadata.d.ts +6 -0
  128. package/dist/providers/core/runtime/provider-runtime-metadata.js.map +1 -1
  129. package/dist/providers/core/runtime/responses-provider.d.ts +1 -7
  130. package/dist/providers/core/runtime/responses-provider.js +12 -93
  131. package/dist/providers/core/runtime/responses-provider.js.map +1 -1
  132. package/dist/providers/core/strategies/oauth-auth-code-flow.js +12 -8
  133. package/dist/providers/core/strategies/oauth-auth-code-flow.js.map +1 -1
  134. package/dist/providers/core/utils/http-client.js +16 -3
  135. package/dist/providers/core/utils/http-client.js.map +1 -1
  136. package/dist/providers/core/utils/provider-error-logger.d.ts +1 -1
  137. package/dist/providers/core/utils/provider-error-reporter.d.ts +3 -1
  138. package/dist/providers/core/utils/provider-error-reporter.js +3 -0
  139. package/dist/providers/core/utils/provider-error-reporter.js.map +1 -1
  140. package/dist/providers/core/utils/snapshot-writer.js +1 -4
  141. package/dist/providers/core/utils/snapshot-writer.js.map +1 -1
  142. package/dist/providers/mock/mock-provider-runtime.js +57 -27
  143. package/dist/providers/mock/mock-provider-runtime.js.map +1 -1
  144. package/dist/scripts/camoufox/launch-auth.mjs +193 -58
  145. package/dist/server/handlers/handler-utils.js +3 -2
  146. package/dist/server/handlers/handler-utils.js.map +1 -1
  147. package/dist/server/runtime/http-server/daemon-admin/auth-handler.d.ts +2 -0
  148. package/dist/server/runtime/http-server/daemon-admin/auth-handler.js +103 -0
  149. package/dist/server/runtime/http-server/daemon-admin/auth-handler.js.map +1 -0
  150. package/dist/server/runtime/http-server/daemon-admin/auth-session.d.ts +5 -0
  151. package/dist/server/runtime/http-server/daemon-admin/auth-session.js +77 -0
  152. package/dist/server/runtime/http-server/daemon-admin/auth-session.js.map +1 -0
  153. package/dist/server/runtime/http-server/daemon-admin/auth-store.d.ts +18 -0
  154. package/dist/server/runtime/http-server/daemon-admin/auth-store.js +89 -0
  155. package/dist/server/runtime/http-server/daemon-admin/auth-store.js.map +1 -0
  156. package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js +1 -2
  157. package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js.map +1 -1
  158. package/dist/server/runtime/http-server/daemon-admin/providers-handler.js +226 -24
  159. package/dist/server/runtime/http-server/daemon-admin/providers-handler.js.map +1 -1
  160. package/dist/server/runtime/http-server/daemon-admin/quota-handler.js +47 -8
  161. package/dist/server/runtime/http-server/daemon-admin/quota-handler.js.map +1 -1
  162. package/dist/server/runtime/http-server/daemon-admin/restart-handler.js +1 -1
  163. package/dist/server/runtime/http-server/daemon-admin/restart-handler.js.map +1 -1
  164. package/dist/server/runtime/http-server/daemon-admin/stats-handler.js +1 -1
  165. package/dist/server/runtime/http-server/daemon-admin/stats-handler.js.map +1 -1
  166. package/dist/server/runtime/http-server/daemon-admin/status-handler.js +68 -4
  167. package/dist/server/runtime/http-server/daemon-admin/status-handler.js.map +1 -1
  168. package/dist/server/runtime/http-server/daemon-admin-routes.d.ts +3 -4
  169. package/dist/server/runtime/http-server/daemon-admin-routes.js +9 -14
  170. package/dist/server/runtime/http-server/daemon-admin-routes.js.map +1 -1
  171. package/dist/server/runtime/http-server/executor-metadata.js +1 -1
  172. package/dist/server/runtime/http-server/executor-metadata.js.map +1 -1
  173. package/dist/server/runtime/http-server/executor-response.js +0 -16
  174. package/dist/server/runtime/http-server/executor-response.js.map +1 -1
  175. package/dist/server/runtime/http-server/hub-shadow-compare.js +110 -34
  176. package/dist/server/runtime/http-server/hub-shadow-compare.js.map +1 -1
  177. package/dist/server/runtime/http-server/index.d.ts +5 -3
  178. package/dist/server/runtime/http-server/index.js +215 -109
  179. package/dist/server/runtime/http-server/index.js.map +1 -1
  180. package/dist/server/runtime/http-server/middleware.js +19 -1
  181. package/dist/server/runtime/http-server/middleware.js.map +1 -1
  182. package/dist/server/runtime/http-server/request-executor.js +10 -19
  183. package/dist/server/runtime/http-server/request-executor.js.map +1 -1
  184. package/dist/server/runtime/http-server/routes.js +8 -2
  185. package/dist/server/runtime/http-server/routes.js.map +1 -1
  186. package/dist/server/runtime/http-server/session-dir.d.ts +2 -0
  187. package/dist/server/runtime/http-server/session-dir.js +59 -0
  188. package/dist/server/runtime/http-server/session-dir.js.map +1 -0
  189. package/dist/server/runtime/http-server/types.d.ts +0 -4
  190. package/dist/server/utils/utf8-chunk-buffer.js +6 -3
  191. package/dist/server/utils/utf8-chunk-buffer.js.map +1 -1
  192. package/dist/server/utils/warmup-storm-tracker.js +1 -1
  193. package/dist/server/utils/warmup-storm-tracker.js.map +1 -1
  194. package/dist/server-factory.d.ts +6 -28
  195. package/dist/server-factory.js +8 -93
  196. package/dist/server-factory.js.map +1 -1
  197. package/dist/token-daemon/index.js +2 -2
  198. package/dist/token-daemon/index.js.map +1 -1
  199. package/dist/token-daemon/provider-registry.js +0 -1
  200. package/dist/token-daemon/provider-registry.js.map +1 -1
  201. package/dist/token-daemon/server-utils.js +8 -9
  202. package/dist/token-daemon/server-utils.js.map +1 -1
  203. package/dist/token-daemon/token-utils.js +1 -1
  204. package/dist/token-daemon/token-utils.js.map +1 -1
  205. package/dist/tools/semantic-replay.js +2 -2
  206. package/dist/tools/semantic-replay.js.map +1 -1
  207. package/dist/tools/stats-request-events.d.ts +1 -1
  208. package/dist/tools/stats-usage.js +6 -3
  209. package/dist/tools/stats-usage.js.map +1 -1
  210. package/dist/utils/llms-engine-shadow.d.ts +19 -0
  211. package/dist/utils/llms-engine-shadow.js +209 -0
  212. package/dist/utils/llms-engine-shadow.js.map +1 -0
  213. package/dist/utils/runtime-versions.js +2 -1
  214. package/dist/utils/runtime-versions.js.map +1 -1
  215. package/docs/ARCHITECTURE.md +402 -0
  216. package/docs/CODEX_AND_CLAUDE_CODE.md +69 -0
  217. package/docs/CONFIG_ARCHITECTURE.md +517 -0
  218. package/docs/ERROR_HANDLING_AUDIT.md +0 -0
  219. package/docs/GCLI2API_PARITY_GAPS.md +98 -0
  220. package/docs/INSTALLATION_AND_QUICKSTART.md +74 -0
  221. package/docs/INSTRUCTION_MARKUP.md +89 -0
  222. package/docs/MODULE_ENHANCEMENT_SYSTEM.md +666 -0
  223. package/docs/PORTS.md +36 -0
  224. package/docs/PROVIDERS_BUILTIN.md +111 -0
  225. package/docs/PROVIDER_TYPES.md +55 -0
  226. package/docs/SERVERTOOL_CLOCK_DESIGN.md +233 -0
  227. package/docs/USAGE_HANDLING_ANALYSIS.md +335 -0
  228. package/docs/USER_CONFIG_PARSER_CHANGES.md +175 -0
  229. package/docs/V3_INBOUND_OUTBOUND_DESIGN.md +86 -0
  230. package/docs/VIRTUAL_ROUTER_PRIORITY_AND_HEALTH.md +125 -0
  231. package/docs/anthropic-request-golden-samples.md +50 -0
  232. package/docs/ccr-alignment-enhancetool.md +105 -0
  233. package/docs/chat-glm-500-analysis.md +79 -0
  234. package/docs/chat-request-golden-samples.md +42 -0
  235. package/docs/chat-semantic-expansion-plan.md +82 -0
  236. package/docs/cli-command-inventory.md +76 -0
  237. package/docs/codex-samples-replay.md +50 -0
  238. package/docs/daemon-admin-api-design.md +350 -0
  239. package/docs/daemon-admin-module-structure.md +169 -0
  240. package/docs/daemon-admin-ui.html +3394 -0
  241. package/docs/debug-system-design.md +734 -0
  242. package/docs/debugging/gemini-sse-root-cause.md +52 -0
  243. package/docs/debugging/sse_encoding_failure_analysis.md +53 -0
  244. package/docs/dry-run/README.md +721 -0
  245. package/docs/error-handling-v2.md +92 -0
  246. package/docs/exec-command-guard-policy.example.v1.json +42 -0
  247. package/docs/fixes/gemini-protocol-mapping.md +57 -0
  248. package/docs/fixes/oauth-portal-timing-fix.md +202 -0
  249. package/docs/fixes/web-search-hop3-fix.md +265 -0
  250. package/docs/glm-api-reference.md +390 -0
  251. package/docs/glm-chat-completions.md +1779 -0
  252. package/docs/glm-history-inline-images.md +44 -0
  253. package/docs/golden-ci-library.md +66 -0
  254. package/docs/lmstudio-dry-run-summary.md +203 -0
  255. package/docs/lmstudio-tool-calling.md +214 -0
  256. package/docs/mapping-tables/anthropic-to-openai.json +290 -0
  257. package/docs/mapping-tables/iflow-to-openai.json +215 -0
  258. package/docs/mapping-tables/openai-passthrough.json +190 -0
  259. package/docs/mapping-tables/openai-to-iflow.json +227 -0
  260. package/docs/monitoring/Design.md +61 -0
  261. package/docs/multi-token-auth-guide.md +66 -0
  262. package/docs/oauth-authentication-guide.md +168 -0
  263. package/docs/oauth-iflow-implementation.md +153 -0
  264. package/docs/pipeline-routing-report.md +209 -0
  265. package/docs/plans/manager-daemon/PLAN.md +86 -0
  266. package/docs/plans/provider-config-v2-plan.md +176 -0
  267. package/docs/plans/provider-runtime-manager-plan.md +209 -0
  268. package/docs/plans/transparent-429-failover.md +89 -0
  269. package/docs/plans/unified-hub-framework-v1.md +245 -0
  270. package/docs/provider-config-v2-ui-design.md +181 -0
  271. package/docs/provider-quota-design.md +129 -0
  272. package/docs/providers/gemini-provider.md +62 -0
  273. package/docs/providers/lmstudio-v2-migration-report.md +102 -0
  274. package/docs/providers/provider-composite-design.md +142 -0
  275. package/docs/providers/provider-composite-testing.md +98 -0
  276. package/docs/providers/provider-type-only-migration.md +111 -0
  277. package/docs/rccx-wasm-migration.md +74 -0
  278. package/docs/refactoring/architecture-comparison-diagram.md +140 -0
  279. package/docs/refactoring/compatibility-v2-architecture-design.md +738 -0
  280. package/docs/refactoring/workflow-compatibility-refactoring-design.md +361 -0
  281. package/docs/reports/routing-classification-report.json +24 -0
  282. package/docs/reports/routing-classification-report.md +18 -0
  283. package/docs/reports/thinking-keywords-report.json +19 -0
  284. package/docs/responses/README.md +156 -0
  285. package/docs/responses-generic-provider.md +86 -0
  286. package/docs/responses-passthrough-provider-design.md +202 -0
  287. package/docs/routing-awrr-health-weighted-round-robin.md +179 -0
  288. package/docs/routing-instructions.md +393 -0
  289. package/docs/stop-message-auto.md +225 -0
  290. package/docs/streaming-flow.html +30 -0
  291. package/docs/streaming-flow.md +182 -0
  292. package/docs/token-daemon-preview.html +490 -0
  293. package/docs/token-refresh-daemon-plan.md +269 -0
  294. package/docs/transformation-tables/Gemini-FinishReason/345/256/214/346/225/264/350/275/254/346/215/242/350/241/250.json +233 -0
  295. package/docs/transformation-tables/README.md +225 -0
  296. package/docs/transformation-tables/claude-code-router-anthropic-to-gemini.json +283 -0
  297. package/docs/transformation-tables/claude-code-router-anthropic-to-openai.json +208 -0
  298. package/docs/transformation-tables/claude-code-router-openai-to-anthropic.json +261 -0
  299. package/docs/transformation-tables/claude-code-router-openai-to-gemini.json +208 -0
  300. package/docs/transformation-tables/claude-code-router-openai-to-lmstudio.json +182 -0
  301. package/docs/transformation-tables/claude-code-router-openai-to-ollama.json +250 -0
  302. package/docs/transformation-tables/claude-code-router-openai-to-textgenwebui.json +295 -0
  303. package/docs/transformation-tables/claude-code-router-provider-conversions.json +193 -0
  304. 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
  305. 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
  306. 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
  307. 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
  308. 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
  309. 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
  310. 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
  311. package/docs/v2-architecture/IMPLEMENTATION-ROADMAP.md +367 -0
  312. package/docs/v2-architecture/OPTIMIZED-DESIGN.md +827 -0
  313. package/docs/v2-architecture/PRERUN-CONNECTION-DESIGN.md +716 -0
  314. package/docs/v2-architecture/README.md +551 -0
  315. package/docs/verification/modelscope-verify.md +59 -0
  316. package/docs/web-search-service-design.md +322 -0
  317. package/package.json +12 -7
  318. package/scripts/camoufox/launch-auth.mjs +193 -58
  319. package/scripts/monitor-diff.mjs +126 -0
  320. package/scripts/pack-mode.mjs +19 -1
  321. package/scripts/pack-rcc.mjs +63 -0
  322. package/scripts/unified-hub-shadow-compare.mjs +33 -13
  323. package/scripts/verify-e2e-toolcall.mjs +115 -26
  324. package/dist/modules/llmswitch/pipeline-registry.d.ts +0 -57
  325. package/dist/modules/llmswitch/pipeline-registry.js +0 -229
  326. package/dist/modules/llmswitch/pipeline-registry.js.map +0 -1
  327. package/dist/server/RouteCodexServer.d.ts +0 -13
  328. package/dist/server/RouteCodexServer.js +0 -25
  329. package/dist/server/RouteCodexServer.js.map +0 -1
  330. package/dist/v2/conversion/hub/snapshot-recorder.d.ts +0 -12
  331. package/dist/v2/conversion/hub/snapshot-recorder.js +0 -22
  332. package/dist/v2/conversion/hub/snapshot-recorder.js.map +0 -1
@@ -21,7 +21,7 @@ import { registerHttpRoutes, registerOAuthPortalRoute } from './routes.js';
21
21
  import { mapProviderProtocol, normalizeProviderType, resolveProviderIdentity, asRecord } from './provider-utils.js';
22
22
  import { resolveRepoRoot } from './llmswitch-loader.js';
23
23
  import { enhanceProviderRequestId } from '../../utils/request-id-manager.js';
24
- import { convertProviderResponse as bridgeConvertProviderResponse, createSnapshotRecorder as bridgeCreateSnapshotRecorder, rebindResponsesConversationRequestId, bootstrapVirtualRouterConfig, getHubPipelineCtor } from '../../../modules/llmswitch/bridge.js';
24
+ import { convertProviderResponse as bridgeConvertProviderResponse, createSnapshotRecorder as bridgeCreateSnapshotRecorder, rebindResponsesConversationRequestId, extractSessionIdentifiersFromMetadata, bootstrapVirtualRouterConfig, getHubPipelineCtor } from '../../../modules/llmswitch/bridge.js';
25
25
  import { initializeRouteErrorHub, reportRouteError } from '../../../error-handling/route-error-hub.js';
26
26
  import { writeClientSnapshot } from '../../../providers/core/utils/snapshot-writer.js';
27
27
  import { createServerColoredLogger } from './colored-logger.js';
@@ -32,11 +32,22 @@ import { ManagerDaemon } from '../../../manager/index.js';
32
32
  import { HealthManagerModule } from '../../../manager/modules/health/index.js';
33
33
  import { RoutingStateManagerModule } from '../../../manager/modules/routing/index.js';
34
34
  import { TokenManagerModule } from '../../../manager/modules/token/index.js';
35
+ import { ensureServerScopedSessionDir } from './session-dir.js';
35
36
  import { StatsManager } from './stats-manager.js';
36
37
  import { loadRouteCodexConfig } from '../../../config/routecodex-config-loader.js';
37
38
  import { buildInfo } from '../../../build-info.js';
38
39
  import { recordHubShadowCompareDiff, resolveHubShadowCompareConfig, shouldRunHubShadowCompare } from './hub-shadow-compare.js';
40
+ import { recordLlmsEngineShadowDiff, isLlmsEngineShadowEnabledForSubpath, resolveLlmsEngineShadowConfig, shouldRunLlmsEngineShadowForSubpath } from '../../../utils/llms-engine-shadow.js';
39
41
  import { resolveLlmswitchCoreVersion } from '../../../utils/runtime-versions.js';
42
+ const DEFAULT_MAX_PROVIDER_ATTEMPTS = 6;
43
+ function resolveMaxProviderAttempts() {
44
+ const raw = String(process.env.ROUTECODEX_MAX_PROVIDER_ATTEMPTS || process.env.RCC_MAX_PROVIDER_ATTEMPTS || '')
45
+ .trim()
46
+ .toLowerCase();
47
+ const parsed = raw ? Number.parseInt(raw, 10) : NaN;
48
+ const candidate = Number.isFinite(parsed) ? parsed : DEFAULT_MAX_PROVIDER_ATTEMPTS;
49
+ return Math.max(1, Math.min(20, candidate));
50
+ }
40
51
  /**
41
52
  * RouteCodex Server V2
42
53
  *
@@ -52,7 +63,6 @@ export class RouteCodexHttpServer {
52
63
  _isRunning = false;
53
64
  // Runtime state
54
65
  hubPipeline = null;
55
- hubShadowComparePipeline = null;
56
66
  providerHandles = new Map();
57
67
  providerKeyToRuntimeKey = new Map();
58
68
  pipelineLogger = createNoopPipelineLogger();
@@ -71,17 +81,18 @@ export class RouteCodexHttpServer {
71
81
  stats = new StatsManager();
72
82
  restartChain = Promise.resolve();
73
83
  hubShadowCompareConfig = resolveHubShadowCompareConfig();
84
+ llmsEngineShadowConfig = resolveLlmsEngineShadowConfig();
74
85
  hubPolicyMode = null;
86
+ hubPipelineEngineShadow = null;
87
+ hubPipelineConfigForShadow = null;
75
88
  constructor(config) {
76
89
  this.config = config;
77
90
  this.app = express();
78
91
  this.errorHandling = new QuietErrorHandlingCenter();
79
92
  this.stageLoggingEnabled = isStageLoggingEnabled();
80
93
  this.repoRoot = resolveRepoRoot(import.meta.url);
81
- const envFlag = (process.env.ROUTECODEX_USE_HUB_PIPELINE || '').trim().toLowerCase();
82
- if (config.pipeline?.useHubPipeline === false || envFlag === '0' || envFlag === 'false') {
83
- console.warn('[RouteCodexHttpServer] Super pipeline has been removed; falling back to Hub pipeline.');
84
- }
94
+ // Ensure session-scoped routing state does not leak across server instances.
95
+ ensureServerScopedSessionDir(`${this.config.server.host}:${this.config.server.port}`);
85
96
  try {
86
97
  this.pipelineLogger = new PipelineDebugLoggerImpl({ colored: this.coloredLogger }, { enableConsoleLogging: true });
87
98
  }
@@ -117,20 +128,11 @@ export class RouteCodexHttpServer {
117
128
  /**
118
129
  * Register Daemon Admin UI route.
119
130
  * Serves docs/daemon-admin-ui.html as a static page.
120
- * - If `httpserver.apikey` is not configured: localhost-only.
121
- * - If `httpserver.apikey` is configured: allow remote UI access (API calls still require apikey).
131
+ * Note: daemon-admin UI/API now uses password login (stored at ~/.routecodex/login) instead of httpserver.apikey.
122
132
  */
123
133
  registerDaemonAdminUiRoute() {
124
134
  this.app.get('/daemon/admin', async (req, res) => {
125
135
  try {
126
- const ip = req.socket?.remoteAddress || '';
127
- const isLocal = ip === '127.0.0.1' || ip === '::1' || ip === '::ffff:127.0.0.1';
128
- const expectedKey = typeof this.config?.server?.apikey === 'string' ? this.config.server.apikey.trim() : '';
129
- const hasConfiguredKey = Boolean(expectedKey);
130
- if (!isLocal && !hasConfiguredKey) {
131
- res.status(403).json({ error: { message: 'forbidden', code: 'forbidden' } });
132
- return;
133
- }
134
136
  const fs = await import('node:fs/promises');
135
137
  let html = '';
136
138
  try {
@@ -359,6 +361,46 @@ export class RouteCodexHttpServer {
359
361
  this.hubPipelineCtor = ctorFactory;
360
362
  return this.hubPipelineCtor;
361
363
  }
364
+ async ensureHubPipelineEngineShadow() {
365
+ if (this.hubPipelineEngineShadow) {
366
+ return this.hubPipelineEngineShadow;
367
+ }
368
+ if (!this.hubPipelineConfigForShadow) {
369
+ throw new Error('Hub pipeline shadow config is not initialized');
370
+ }
371
+ const baseConfig = this.hubPipelineConfigForShadow;
372
+ const shadowConfig = { ...baseConfig };
373
+ // Avoid double side effects when shadow-running the pipeline: keep reads, drop writes.
374
+ const routingStateStore = baseConfig.routingStateStore;
375
+ if (routingStateStore && typeof routingStateStore.loadSync === 'function') {
376
+ shadowConfig.routingStateStore = {
377
+ loadSync: routingStateStore.loadSync.bind(routingStateStore),
378
+ saveAsync: () => { }
379
+ };
380
+ }
381
+ const healthStore = baseConfig.healthStore;
382
+ if (healthStore && typeof healthStore.loadInitialSnapshot === 'function') {
383
+ shadowConfig.healthStore = {
384
+ loadInitialSnapshot: healthStore.loadInitialSnapshot.bind(healthStore)
385
+ };
386
+ }
387
+ const quotaViewReadOnly = baseConfig.quotaViewReadOnly;
388
+ if (typeof quotaViewReadOnly === 'function') {
389
+ shadowConfig.quotaView = quotaViewReadOnly;
390
+ }
391
+ const bridge = (await import('../../../modules/llmswitch/bridge.js'));
392
+ const getCtor = bridge.getHubPipelineCtorForImpl;
393
+ if (typeof getCtor !== 'function') {
394
+ throw new Error('llmswitch bridge does not expose getHubPipelineCtorForImpl');
395
+ }
396
+ const ctorFactory = await getCtor('engine');
397
+ const hubCtor = ctorFactory;
398
+ if (!('virtualRouter' in shadowConfig)) {
399
+ throw new Error('HubPipeline shadow config missing virtualRouter');
400
+ }
401
+ this.hubPipelineEngineShadow = new hubCtor(shadowConfig);
402
+ return this.hubPipelineEngineShadow;
403
+ }
362
404
  isPipelineReady() {
363
405
  return Boolean(this.hubPipeline);
364
406
  }
@@ -671,6 +713,40 @@ export class RouteCodexHttpServer {
671
713
  ...(Number.isFinite(sampleRate) ? { sampleRate } : {})
672
714
  };
673
715
  }
716
+ // Unified Hub Framework V1: tool surface rollout toggle (enforce by default in dev).
717
+ // - Disable via env: ROUTECODEX_HUB_TOOL_SURFACE_MODE=off
718
+ // - Observe via env: ROUTECODEX_HUB_TOOL_SURFACE_MODE=observe
719
+ // - Shadow (diff-only, no rewrites) via env: ROUTECODEX_HUB_TOOL_SURFACE_MODE=shadow
720
+ // - Enforce (rewrite outbound payload) via env: ROUTECODEX_HUB_TOOL_SURFACE_MODE=enforce
721
+ const toolSurfaceModeRaw = String(process.env.ROUTECODEX_HUB_TOOL_SURFACE_MODE || '').trim().toLowerCase();
722
+ const toolSurfaceMode = toolSurfaceModeRaw === 'off' || toolSurfaceModeRaw === '0' || toolSurfaceModeRaw === 'false'
723
+ ? null
724
+ : toolSurfaceModeRaw === 'observe' || toolSurfaceModeRaw === 'shadow' || toolSurfaceModeRaw === 'enforce'
725
+ ? toolSurfaceModeRaw
726
+ : buildInfo.mode === 'dev'
727
+ ? 'enforce'
728
+ : null;
729
+ if (toolSurfaceMode) {
730
+ const sampleRateRaw = String(process.env.ROUTECODEX_HUB_TOOL_SURFACE_SAMPLE_RATE || '').trim();
731
+ const sampleRate = sampleRateRaw ? Number(sampleRateRaw) : undefined;
732
+ hubConfig.toolSurface = {
733
+ mode: toolSurfaceMode,
734
+ ...(Number.isFinite(sampleRate) ? { sampleRate } : {})
735
+ };
736
+ // Also export the resolved mode to env so llmswitch-core response conversion
737
+ // (convertProviderResponse) can observe tool surface mismatches consistently.
738
+ if (!process.env.ROUTECODEX_HUB_TOOL_SURFACE_MODE) {
739
+ process.env.ROUTECODEX_HUB_TOOL_SURFACE_MODE = toolSurfaceMode;
740
+ }
741
+ }
742
+ // Unified Hub Framework V1: followup (servertool) shadow compare toggle.
743
+ // Implemented in llmswitch-core servertool engine; controlled by env for progressive rollout.
744
+ // Default: shadow in dev builds; off in release builds.
745
+ if (!process.env.ROUTECODEX_HUB_FOLLOWUP_MODE) {
746
+ if (buildInfo.mode === 'dev') {
747
+ process.env.ROUTECODEX_HUB_FOLLOWUP_MODE = 'shadow';
748
+ }
749
+ }
674
750
  const healthModule = this.managerDaemon?.getModule('health');
675
751
  const healthStore = healthModule?.getHealthStore();
676
752
  if (healthStore) {
@@ -684,6 +760,9 @@ export class RouteCodexHttpServer {
684
760
  const quotaModule = this.managerDaemon?.getModule('provider-quota');
685
761
  if (this.isQuotaRoutingEnabled() && quotaModule && typeof quotaModule.getQuotaView === 'function') {
686
762
  hubConfig.quotaView = quotaModule.getQuotaView();
763
+ if (typeof quotaModule.getQuotaViewReadOnly === 'function') {
764
+ hubConfig.quotaViewReadOnly = quotaModule.getQuotaViewReadOnly();
765
+ }
687
766
  }
688
767
  if (!this.hubPipeline) {
689
768
  this.hubPipeline = new hubCtor(hubConfig);
@@ -702,37 +781,9 @@ export class RouteCodexHttpServer {
702
781
  }
703
782
  this.hubPipeline.updateVirtualRouterConfig(bootstrapArtifacts.config);
704
783
  }
705
- // Unified Hub Framework V1: optional shadow compare pipeline (same runtime deps, same config).
706
- // Used to execute baseline runs without contending with the main pipeline instance.
707
- if (this.hubShadowCompareConfig.enabled) {
708
- if (!this.hubShadowComparePipeline) {
709
- this.hubShadowComparePipeline = new hubCtor(hubConfig);
710
- }
711
- else {
712
- const existingShadow = this.hubShadowComparePipeline;
713
- try {
714
- existingShadow.updateRuntimeDeps?.({
715
- ...(healthStore ? { healthStore } : {}),
716
- ...(routingStateStore ? { routingStateStore } : {}),
717
- ...('quotaView' in hubConfig ? { quotaView: hubConfig.quotaView } : {})
718
- });
719
- }
720
- catch {
721
- // best-effort: runtime deps updates must never block reload
722
- }
723
- this.hubShadowComparePipeline.updateVirtualRouterConfig(bootstrapArtifacts.config);
724
- }
725
- }
726
- else if (this.hubShadowComparePipeline) {
727
- try {
728
- const shadow = this.hubShadowComparePipeline;
729
- shadow.dispose?.();
730
- }
731
- catch {
732
- // ignore dispose failures
733
- }
734
- this.hubShadowComparePipeline = null;
735
- }
784
+ // llms-engine shadow: capture the latest hub config and reset shadow pipeline to avoid stale deps.
785
+ this.hubPipelineConfigForShadow = hubConfig;
786
+ this.hubPipelineEngineShadow = null;
736
787
  await this.initializeProviderRuntimes(bootstrapArtifacts);
737
788
  }
738
789
  buildHandlerContext() {
@@ -962,11 +1013,12 @@ export class RouteCodexHttpServer {
962
1013
  }
963
1014
  const pipelineLabel = 'hub';
964
1015
  const iterationMetadata = initialMetadata;
965
- const _followupTriggered = false;
966
- // 单次 HTTP 请求内最多做一次 failover(不在 Provider 层做重试):
1016
+ // _followupTriggered = false;
1017
+ // 单次 HTTP 请求内允许多次 failover(不在 Provider 层做重试):
967
1018
  // - 让 VirtualRouter 根据 excludedProviderKeys 跳过失败目标
968
1019
  // - 避免客户端“一次就断”导致对话破裂(尤其是 429 / prompt too long 等可恢复错误)
969
- const maxAttempts = 2;
1020
+ // - 通过 env 允许按部署/客户端调整:ROUTECODEX_MAX_PROVIDER_ATTEMPTS / RCC_MAX_PROVIDER_ATTEMPTS
1021
+ const maxAttempts = resolveMaxProviderAttempts();
970
1022
  let attempt = 0;
971
1023
  let firstError = null;
972
1024
  const originalBodySnapshot = this.cloneRequestPayload(input.body);
@@ -1140,9 +1192,13 @@ export class RouteCodexHttpServer {
1140
1192
  const sessionId = typeof mergedMetadata.sessionId === "string" && mergedMetadata.sessionId.trim()
1141
1193
  ? mergedMetadata.sessionId.trim()
1142
1194
  : undefined;
1143
- const conversationId = typeof mergedMetadata.conversationId === "string" && mergedMetadata.conversationId.trim()
1195
+ let conversationId = typeof mergedMetadata.conversationId === "string" && mergedMetadata.conversationId.trim()
1144
1196
  ? mergedMetadata.conversationId.trim()
1145
1197
  : undefined;
1198
+ // 对称补齐:如果只有 session_id,则回传 conversation_id=session_id
1199
+ if (!conversationId && sessionId) {
1200
+ conversationId = sessionId;
1201
+ }
1146
1202
  if (sessionId || conversationId) {
1147
1203
  if (!converted.headers) {
1148
1204
  converted.headers = {};
@@ -1205,11 +1261,18 @@ export class RouteCodexHttpServer {
1205
1261
  throw new Error('Hub pipeline runtime is not initialized');
1206
1262
  }
1207
1263
  const payload = asRecord(input.body);
1264
+ const isInternalFollowup = metadata.serverToolFollowup === true;
1265
+ const wantsShadowCompare = !isInternalFollowup && shouldRunHubShadowCompare(this.hubShadowCompareConfig);
1208
1266
  const pipelineInput = {
1209
1267
  ...input,
1268
+ id: input.requestId,
1269
+ endpoint: input.entryEndpoint,
1210
1270
  metadata: {
1211
1271
  ...metadata,
1212
- logger: this.coloredLogger
1272
+ logger: this.coloredLogger,
1273
+ ...(wantsShadowCompare
1274
+ ? { __hubShadowCompare: { baselineMode: this.hubShadowCompareConfig.baselineMode } }
1275
+ : {})
1213
1276
  },
1214
1277
  payload
1215
1278
  };
@@ -1225,13 +1288,23 @@ export class RouteCodexHttpServer {
1225
1288
  const derivedRequestId = typeof resultRecord.requestId === 'string'
1226
1289
  ? resultRecord.requestId
1227
1290
  : input.requestId;
1291
+ const llmsEngineShadowEnabled = !isInternalFollowup &&
1292
+ isLlmsEngineShadowEnabledForSubpath(this.llmsEngineShadowConfig, 'conversion/hub/pipeline');
1293
+ if (llmsEngineShadowEnabled) {
1294
+ // Fail fast: if shadow is enabled for this module, engine core must be available.
1295
+ await this.ensureHubPipelineEngineShadow();
1296
+ }
1297
+ const wantsLlmsEngineShadow = llmsEngineShadowEnabled &&
1298
+ shouldRunLlmsEngineShadowForSubpath(this.llmsEngineShadowConfig, 'conversion/hub/pipeline');
1228
1299
  // Unified Hub Framework V1: runtime black-box shadow compare (baseline policy vs current policy).
1229
- // - baseline run uses the same input but overrides policy mode
1300
+ // - baseline payload is computed in the SAME hub pipeline execution (single-pass)
1230
1301
  // - only writes errorsample when diff exists
1231
- // - baseline run disables hub snapshots to avoid polluting codex-samples
1232
1302
  try {
1233
- const isInternalFollowup = metadata.serverToolFollowup === true;
1234
- if (!isInternalFollowup && shouldRunHubShadowCompare(this.hubShadowCompareConfig)) {
1303
+ const shadow = result.metadata?.hubShadowCompare;
1304
+ const baselineProviderPayload = shadow && typeof shadow === 'object' && !Array.isArray(shadow)
1305
+ ? shadow.baselineProviderPayload
1306
+ : undefined;
1307
+ if (wantsShadowCompare && baselineProviderPayload && typeof baselineProviderPayload === 'object') {
1235
1308
  const entryEndpoint = String(input.entryEndpoint || '/v1/chat/completions');
1236
1309
  const routeHint = typeof metadata.routeHint === 'string'
1237
1310
  ? String(metadata.routeHint)
@@ -1260,31 +1333,17 @@ export class RouteCodexHttpServer {
1260
1333
  };
1261
1334
  void (async () => {
1262
1335
  try {
1263
- const baselineMeta = {
1264
- ...(pipelineInput.metadata ?? {}),
1265
- __hubPolicyOverride: { mode: this.hubShadowCompareConfig.baselineMode },
1266
- __disableHubSnapshots: true
1267
- };
1268
- const baselineInput = {
1269
- ...pipelineInput,
1270
- // Ensure baseline run uses the exact same HubPipeline requestId as the candidate run.
1271
- // Otherwise internal requestId fields (e.g. responsesContext.requestId) will differ and
1272
- // produce noisy diffs even when providerPayload is otherwise identical.
1273
- id: derivedRequestId,
1274
- endpoint: entryEndpoint,
1275
- metadata: baselineMeta
1276
- };
1277
- const baselinePipeline = this.hubShadowComparePipeline || this.hubPipeline;
1278
- const baseline = await baselinePipeline.execute(baselineInput);
1279
1336
  const baselineOut = {
1280
- providerPayload: cloneJsonSafe(baseline.providerPayload),
1281
- target: cloneJsonSafe(baseline.target),
1337
+ providerPayload: cloneJsonSafe(baselineProviderPayload),
1338
+ target: shadow && typeof shadow === 'object' && !Array.isArray(shadow) && shadow.baselineTarget
1339
+ ? cloneJsonSafe(shadow.baselineTarget)
1340
+ : cloneJsonSafe(result.target),
1282
1341
  metadata: {
1283
- entryEndpoint: baseline.metadata?.entryEndpoint,
1284
- providerProtocol: baseline.metadata?.providerProtocol,
1285
- processMode: baseline.metadata?.processMode,
1286
- stream: baseline.metadata?.stream,
1287
- routeHint: baseline.metadata?.routeHint
1342
+ entryEndpoint: result.metadata?.entryEndpoint,
1343
+ providerProtocol: result.metadata?.providerProtocol,
1344
+ processMode: result.metadata?.processMode,
1345
+ stream: result.metadata?.stream,
1346
+ routeHint: result.metadata?.routeHint
1288
1347
  }
1289
1348
  };
1290
1349
  await recordHubShadowCompareDiff({
@@ -1293,7 +1352,7 @@ export class RouteCodexHttpServer {
1293
1352
  routeHint,
1294
1353
  excludedProviderKeys,
1295
1354
  baselineMode: this.hubShadowCompareConfig.baselineMode,
1296
- candidateMode: this.hubPolicyMode ?? undefined,
1355
+ candidateMode: typeof shadow?.candidateMode === 'string' ? shadow.candidateMode : (this.hubPolicyMode ?? undefined),
1297
1356
  baselineOut,
1298
1357
  candidateOut
1299
1358
  });
@@ -1308,6 +1367,77 @@ export class RouteCodexHttpServer {
1308
1367
  catch {
1309
1368
  // best-effort only
1310
1369
  }
1370
+ // llms-engine: runtime black-box shadow compare (TS vs engine) for hub pipeline.
1371
+ if (wantsLlmsEngineShadow) {
1372
+ const cloneJsonSafe = (value) => {
1373
+ try {
1374
+ return JSON.parse(JSON.stringify(value));
1375
+ }
1376
+ catch {
1377
+ return value;
1378
+ }
1379
+ };
1380
+ const entryEndpoint = String(input.entryEndpoint || '/v1/chat/completions');
1381
+ const routeHint = typeof metadata.routeHint === 'string'
1382
+ ? String(metadata.routeHint)
1383
+ : undefined;
1384
+ const baselineOut = {
1385
+ providerPayload: cloneJsonSafe(result.providerPayload),
1386
+ target: cloneJsonSafe(result.target),
1387
+ metadata: {
1388
+ entryEndpoint: result.metadata?.entryEndpoint,
1389
+ providerProtocol: result.metadata?.providerProtocol,
1390
+ processMode: result.metadata?.processMode,
1391
+ stream: result.metadata?.stream,
1392
+ routeHint: result.metadata?.routeHint
1393
+ }
1394
+ };
1395
+ void (async () => {
1396
+ try {
1397
+ const shadowPipeline = await this.ensureHubPipelineEngineShadow();
1398
+ const shadowRequestId = `${input.requestId}__llms_engine_shadow`;
1399
+ const baseMeta = pipelineInput.metadata;
1400
+ const shadowInput = {
1401
+ ...pipelineInput,
1402
+ id: shadowRequestId,
1403
+ endpoint: input.entryEndpoint,
1404
+ metadata: {
1405
+ ...(baseMeta && typeof baseMeta === 'object' ? baseMeta : {}),
1406
+ __llmsEngineShadow: { baselineRequestId: derivedRequestId, entryEndpoint, routeHint }
1407
+ },
1408
+ payload: cloneJsonSafe(payload)
1409
+ };
1410
+ const shadowResult = await shadowPipeline.execute(shadowInput);
1411
+ if (!shadowResult?.providerPayload || !shadowResult?.target) {
1412
+ return;
1413
+ }
1414
+ const candidateOut = {
1415
+ providerPayload: cloneJsonSafe(shadowResult.providerPayload),
1416
+ target: cloneJsonSafe(shadowResult.target),
1417
+ metadata: {
1418
+ entryEndpoint: shadowResult.metadata?.entryEndpoint,
1419
+ providerProtocol: shadowResult.metadata?.providerProtocol,
1420
+ processMode: shadowResult.metadata?.processMode,
1421
+ stream: shadowResult.metadata?.stream,
1422
+ routeHint: shadowResult.metadata?.routeHint
1423
+ }
1424
+ };
1425
+ await recordLlmsEngineShadowDiff({
1426
+ group: 'hub-pipeline',
1427
+ requestId: derivedRequestId,
1428
+ subpath: 'conversion/hub/pipeline',
1429
+ baselineImpl: 'ts',
1430
+ candidateImpl: 'engine',
1431
+ baselineOut,
1432
+ candidateOut
1433
+ });
1434
+ }
1435
+ catch (error) {
1436
+ // eslint-disable-next-line no-console
1437
+ console.error('[llms-engine-shadow] hub pipeline shadow failed:', error);
1438
+ }
1439
+ })();
1440
+ }
1311
1441
  return {
1312
1442
  requestId: derivedRequestId,
1313
1443
  providerPayload: result.providerPayload,
@@ -1376,19 +1506,12 @@ export class RouteCodexHttpServer {
1376
1506
  }
1377
1507
  // 在 Host 入口统一解析会话标识,后续 HubPipeline / servertool 等模块仅依赖
1378
1508
  // sessionId / conversationId 字段,不再重复解析 clientHeaders。
1379
- try {
1380
- // eslint-disable-next-line @typescript-eslint/no-var-requires
1381
- const { extractSessionIdentifiersFromMetadata } = require('../../../../sharedmodule/llmswitch-core/dist/conversion/hub/pipeline/session-identifiers.js');
1382
- const identifiers = extractSessionIdentifiersFromMetadata(metadata);
1383
- if (identifiers.sessionId) {
1384
- metadata.sessionId = identifiers.sessionId;
1385
- }
1386
- if (identifiers.conversationId) {
1387
- metadata.conversationId = identifiers.conversationId;
1388
- }
1509
+ const identifiers = extractSessionIdentifiersFromMetadata(metadata);
1510
+ if (identifiers.sessionId) {
1511
+ metadata.sessionId = identifiers.sessionId;
1389
1512
  }
1390
- catch {
1391
- // best-effort:解析失败时不影响主流程
1513
+ if (identifiers.conversationId) {
1514
+ metadata.conversationId = identifiers.conversationId;
1392
1515
  }
1393
1516
  return metadata;
1394
1517
  }
@@ -1600,7 +1723,6 @@ export class RouteCodexHttpServer {
1600
1723
  const reenterPipeline = async (reenterOpts) => {
1601
1724
  const nestedEntry = reenterOpts.entryEndpoint || options.entryEndpoint || entry;
1602
1725
  const nestedExtra = asRecord(reenterOpts.metadata) ?? {};
1603
- const nestedEntryLower = nestedEntry.toLowerCase();
1604
1726
  // 基于首次 HubPipeline metadata + 调用方注入的 metadata 构建新的请求 metadata。
1605
1727
  // 不在 Host 层编码 servertool/web_search 等语义,由 llmswitch-core 负责。
1606
1728
  const nestedMetadata = {
@@ -1616,22 +1738,6 @@ export class RouteCodexHttpServer {
1616
1738
  delete nestedMetadata.clientHeaders;
1617
1739
  delete nestedMetadata.clientRequestId;
1618
1740
  }
1619
- // 针对 reenterPipeline 的入口端点,纠正 providerProtocol,避免沿用外层协议。
1620
- if (nestedEntryLower.includes('/v1/chat/completions')) {
1621
- nestedMetadata.providerProtocol = 'openai-chat';
1622
- }
1623
- else if (nestedEntryLower.includes('/v1/responses')) {
1624
- nestedMetadata.providerProtocol = 'openai-responses';
1625
- }
1626
- else if (nestedEntryLower.includes('/v1/messages')) {
1627
- nestedMetadata.providerProtocol = 'anthropic-messages';
1628
- }
1629
- const followupProtocol = typeof nestedExtra.serverToolFollowupProtocol === 'string'
1630
- ? nestedExtra.serverToolFollowupProtocol
1631
- : undefined;
1632
- if (followupProtocol) {
1633
- nestedMetadata.providerProtocol = followupProtocol;
1634
- }
1635
1741
  const nestedInput = {
1636
1742
  entryEndpoint: nestedEntry,
1637
1743
  method: 'POST',