@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
@@ -7,6 +7,12 @@ import fs from 'node:fs';
7
7
  import os from 'node:os';
8
8
  import path from 'node:path';
9
9
 
10
+ function isTruthy(value) {
11
+ if (!value) return false;
12
+ const v = String(value).trim().toLowerCase();
13
+ return v === '1' || v === 'true' || v === 'yes' || v === 'on';
14
+ }
15
+
10
16
  function parseArgs(argv) {
11
17
  const args = { profile: 'default', url: '', autoMode: '', devMode: false };
12
18
  const list = argv.slice(2);
@@ -65,6 +71,44 @@ async function getCamoufoxCacheRoot() {
65
71
  });
66
72
  }
67
73
 
74
+ function resolveCamoufoxBinary(cacheRoot) {
75
+ const override = (process.env.ROUTECODEX_CAMOUFOX_BINARY || '').trim();
76
+ if (override) {
77
+ return override;
78
+ }
79
+
80
+ const isMac = process.platform === 'darwin';
81
+ if (!cacheRoot && isMac) {
82
+ // Best-effort fallback when python3 is unavailable/broken:
83
+ // Camoufox's packaged app is commonly placed under ~/Library/Caches/camoufox/Camoufox.app.
84
+ const guessed = path.join(os.homedir(), 'Library', 'Caches', 'camoufox');
85
+ if (fs.existsSync(path.join(guessed, 'Camoufox.app'))) {
86
+ cacheRoot = guessed;
87
+ }
88
+ }
89
+ if (cacheRoot && isMac) {
90
+ const appPath = path.join(cacheRoot, 'Camoufox.app');
91
+ const macBinary = path.join(appPath, 'Contents', 'MacOS', 'camoufox');
92
+ if (fs.existsSync(macBinary)) {
93
+ return macBinary;
94
+ }
95
+ }
96
+
97
+ try {
98
+ const located = spawnSync('which', ['camoufox'], { encoding: 'utf-8' });
99
+ if (located.status === 0) {
100
+ const resolved = String(located.stdout || '').trim();
101
+ if (resolved) {
102
+ return resolved;
103
+ }
104
+ }
105
+ } catch {
106
+ // ignore lookup failure
107
+ }
108
+
109
+ return 'camoufox';
110
+ }
111
+
68
112
  async function ensureProfileDir(profileId) {
69
113
  const root = path.join(os.homedir(), '.routecodex', 'camoufox-profiles');
70
114
  const dir = path.join(root, profileId);
@@ -108,17 +152,16 @@ async function main() {
108
152
 
109
153
  const cacheRoot = await getCamoufoxCacheRoot();
110
154
  if (!cacheRoot) {
111
- console.error(
112
- '[camoufox-launch-auth] Failed to resolve Camoufox cache root via "python3 -m camoufox path"'
155
+ console.warn(
156
+ '[camoufox-launch-auth] Failed to resolve Camoufox cache root via "python3 -m camoufox path"; falling back to PATH/override.'
113
157
  );
114
- process.exit(1);
115
158
  }
116
159
 
117
160
  const camoufoxBinary = resolveCamoufoxBinary(cacheRoot);
118
161
 
119
162
  if (autoMode && autoMode.trim().toLowerCase() === 'iflow') {
120
163
  try {
121
- await runIflowAutoFlow({ url, profileDir, profileId, camoufoxBinary, devMode });
164
+ await runAutoFlowWithFallback('iflow', { url, profileDir, profileId, camoufoxBinary, devMode });
122
165
  process.exit(0);
123
166
  } catch (error) {
124
167
  console.error(
@@ -132,7 +175,7 @@ async function main() {
132
175
 
133
176
  if (autoMode && autoMode.trim().toLowerCase() === 'gemini') {
134
177
  try {
135
- await runGeminiAutoFlow({ url, profileDir, camoufoxBinary, devMode });
178
+ await runAutoFlowWithFallback('gemini', { url, profileDir, profileId, camoufoxBinary, devMode });
136
179
  process.exit(0);
137
180
  } catch (error) {
138
181
  console.error(
@@ -146,7 +189,7 @@ async function main() {
146
189
 
147
190
  if (autoMode && autoMode.trim().toLowerCase() === 'antigravity') {
148
191
  try {
149
- await runAntigravityAutoFlow({ url, profileDir, camoufoxBinary, devMode });
192
+ await runAutoFlowWithFallback('antigravity', { url, profileDir, profileId, camoufoxBinary, devMode });
150
193
  process.exit(0);
151
194
  } catch (error) {
152
195
  console.error(
@@ -166,59 +209,29 @@ main().catch((err) => {
166
209
  process.exit(1);
167
210
  });
168
211
 
169
- function resolveCamoufoxBinary(cacheRoot) {
170
- const isMac = process.platform === 'darwin';
171
- if (isMac) {
172
- const appPath = path.join(cacheRoot, 'Camoufox.app');
173
- const macBinary = path.join(appPath, 'Contents', 'MacOS', 'camoufox');
174
- if (fs.existsSync(macBinary)) {
175
- return macBinary;
176
- }
177
- }
178
- try {
179
- const located = spawnSync('which', ['camoufox'], { encoding: 'utf-8' });
180
- if (located.status === 0) {
181
- const resolved = located.stdout.trim();
182
- if (resolved) {
183
- return resolved;
212
+ async function launchManualCamoufox({ camoufoxBinary, profileDir, url }) {
213
+ let browserExitCode = 0;
214
+ let browser = null;
215
+ const shutdownBrowser = (signal = 'SIGTERM') => {
216
+ try {
217
+ if (!browser) {
218
+ return;
184
219
  }
220
+ browser.kill(signal);
221
+ } catch {
222
+ // ignore
185
223
  }
186
- } catch {
187
- // ignore lookup failure
188
- }
189
- return 'camoufox';
190
- }
224
+ };
225
+ ['SIGTERM', 'SIGINT', 'SIGHUP'].forEach((signal) => {
226
+ process.on(signal, () => shutdownBrowser(signal));
227
+ });
191
228
 
192
- async function launchManualCamoufox({ camoufoxBinary, profileDir, url }) {
193
- let browserExitCode = 0;
194
229
  try {
195
- const browser = spawn(camoufoxBinary, ['-profile', profileDir, url], {
196
- detached: true,
230
+ browser = spawn(camoufoxBinary, ['-profile', profileDir, url], {
231
+ detached: false,
197
232
  stdio: 'ignore'
198
233
  });
199
234
 
200
- const shutdownBrowser = (signal = 'SIGTERM') => {
201
- try {
202
- if (browser.pid) {
203
- try {
204
- process.kill(-browser.pid, signal);
205
- return;
206
- } catch {
207
- // process group kill may fail on non-unix systems; fall back to direct kill
208
- }
209
- }
210
- browser.kill(signal);
211
- } catch {
212
- // ignore
213
- }
214
- };
215
-
216
- ['SIGTERM', 'SIGINT'].forEach((signal) => {
217
- process.on(signal, () => {
218
- shutdownBrowser(signal);
219
- });
220
- });
221
-
222
235
  browserExitCode = await new Promise((resolve) => {
223
236
  browser.on('exit', (code) => resolve(code ?? 0));
224
237
  browser.on('error', () => resolve(1));
@@ -234,6 +247,95 @@ async function launchManualCamoufox({ camoufoxBinary, profileDir, url }) {
234
247
  process.exit(browserExitCode);
235
248
  }
236
249
 
250
+ function isSelectorOrTimeoutError(error) {
251
+ const message = error instanceof Error ? error.message : String(error || '');
252
+ return (
253
+ /timeout/i.test(message) ||
254
+ /waiting for selector/i.test(message) ||
255
+ /strict mode violation/i.test(message) ||
256
+ message.includes('未能定位') ||
257
+ message.includes('无法定位')
258
+ );
259
+ }
260
+
261
+ async function runHeadedManualAssistFlow({ url, profileDir, camoufoxBinary, timeoutMs, label }) {
262
+ let firefox;
263
+ try {
264
+ ({ firefox } = await import('playwright-core'));
265
+ } catch (error) {
266
+ throw new Error(
267
+ `playwright-core is required for headed manual assist (${error instanceof Error ? error.message : String(error)})`
268
+ );
269
+ }
270
+
271
+ console.warn(
272
+ `[camoufox-launch-auth] ${label}: falling back to headed mode for manual completion (no selector match).`
273
+ );
274
+ cleanupExistingCamoufox(profileDir);
275
+ const context = await firefox.launchPersistentContext(profileDir, {
276
+ executablePath: camoufoxBinary,
277
+ headless: false,
278
+ acceptDownloads: false
279
+ });
280
+
281
+ let closed = false;
282
+ const shutdown = async () => {
283
+ if (closed) return;
284
+ closed = true;
285
+ await context.close().catch(() => {});
286
+ };
287
+ ['SIGTERM', 'SIGINT', 'SIGHUP'].forEach((signal) => {
288
+ process.on(signal, () => {
289
+ void shutdown().finally(() => process.exit(0));
290
+ });
291
+ });
292
+
293
+ try {
294
+ const page = context.pages()[0] || (await context.newPage());
295
+ await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 }).catch(() => {});
296
+ console.log('[camoufox-launch-auth] Headed browser opened. Please complete OAuth manually...');
297
+ const callbackPage = await waitForCallback(context, page, timeoutMs);
298
+ await callbackPage.waitForLoadState('load', { timeout: 120000 }).catch(() => {});
299
+ console.log('[camoufox-launch-auth] OAuth callback detected, manual completion finished.');
300
+ } finally {
301
+ await shutdown();
302
+ }
303
+ }
304
+
305
+ async function runAutoFlowWithFallback(kind, options) {
306
+ const mode = String(kind || '').trim().toLowerCase();
307
+ const label = mode || 'auto';
308
+ const timeoutMs = Number(process.env.ROUTECODEX_CAMOUFOX_GEMINI_TIMEOUT_MS || 120_000);
309
+
310
+ try {
311
+ if (mode === 'iflow') {
312
+ await runIflowAutoFlow(options);
313
+ return;
314
+ }
315
+ if (mode === 'gemini') {
316
+ await runGeminiAutoFlow(options);
317
+ return;
318
+ }
319
+ if (mode === 'antigravity') {
320
+ await runAntigravityAutoFlow(options);
321
+ return;
322
+ }
323
+ throw new Error(`Unknown auto mode: ${mode}`);
324
+ } catch (error) {
325
+ if (!options.devMode && isSelectorOrTimeoutError(error)) {
326
+ await runHeadedManualAssistFlow({
327
+ url: options.url,
328
+ profileDir: options.profileDir,
329
+ camoufoxBinary: options.camoufoxBinary,
330
+ timeoutMs: Number(process.env.ROUTECODEX_OAUTH_TIMEOUT_MS || 10 * 60_000),
331
+ label
332
+ });
333
+ return;
334
+ }
335
+ throw error;
336
+ }
337
+ }
338
+
237
339
  async function runIflowAutoFlow({ url, profileDir, profileId, camoufoxBinary, devMode }) {
238
340
  let firefox;
239
341
  try {
@@ -252,6 +354,17 @@ async function runIflowAutoFlow({ url, profileDir, profileId, camoufoxBinary, de
252
354
  headless,
253
355
  acceptDownloads: false
254
356
  });
357
+ let closing = false;
358
+ const shutdown = async () => {
359
+ if (closing) return;
360
+ closing = true;
361
+ await context.close().catch(() => {});
362
+ };
363
+ ['SIGTERM', 'SIGINT', 'SIGHUP'].forEach((signal) => {
364
+ process.on(signal, () => {
365
+ void shutdown().finally(() => process.exit(0));
366
+ });
367
+ });
255
368
 
256
369
  let callbackObserved = false;
257
370
  try {
@@ -352,7 +465,7 @@ async function runIflowAutoFlow({ url, profileDir, profileId, camoufoxBinary, de
352
465
  }
353
466
  throw error;
354
467
  } finally {
355
- await context.close().catch(() => {});
468
+ await shutdown();
356
469
  }
357
470
  }
358
471
 
@@ -374,6 +487,17 @@ async function runGeminiAutoFlow({ url, profileDir, camoufoxBinary, devMode }) {
374
487
  headless: !devMode,
375
488
  acceptDownloads: false
376
489
  });
490
+ let closing = false;
491
+ const shutdown = async () => {
492
+ if (closing) return;
493
+ closing = true;
494
+ await context.close().catch(() => {});
495
+ };
496
+ ['SIGTERM', 'SIGINT', 'SIGHUP'].forEach((signal) => {
497
+ process.on(signal, () => {
498
+ void shutdown().finally(() => process.exit(0));
499
+ });
500
+ });
377
501
 
378
502
  let callbackObserved = false;
379
503
  try {
@@ -440,7 +564,7 @@ async function runGeminiAutoFlow({ url, profileDir, camoufoxBinary, devMode }) {
440
564
  await callbackPage.waitForLoadState('load', { timeout: timeoutMs }).catch(() => {});
441
565
  console.log('[camoufox-launch-auth] OAuth callback detected, automation complete.');
442
566
  } finally {
443
- await context.close().catch(() => {});
567
+ await shutdown();
444
568
  }
445
569
  }
446
570
 
@@ -462,6 +586,17 @@ async function runAntigravityAutoFlow({ url, profileDir, camoufoxBinary, devMode
462
586
  headless: !devMode,
463
587
  acceptDownloads: false
464
588
  });
589
+ let closing = false;
590
+ const shutdown = async () => {
591
+ if (closing) return;
592
+ closing = true;
593
+ await context.close().catch(() => {});
594
+ };
595
+ ['SIGTERM', 'SIGINT', 'SIGHUP'].forEach((signal) => {
596
+ process.on(signal, () => {
597
+ void shutdown().finally(() => process.exit(0));
598
+ });
599
+ });
465
600
 
466
601
  let callbackObserved = false;
467
602
  try {
@@ -544,7 +679,7 @@ async function runAntigravityAutoFlow({ url, profileDir, camoufoxBinary, devMode
544
679
  }
545
680
  throw error;
546
681
  } finally {
547
- await context.close().catch(() => {});
682
+ await shutdown();
548
683
  }
549
684
  }
550
685
 
@@ -584,7 +719,7 @@ async function waitForElementInPages(context, selector, timeoutMs) {
584
719
  return null;
585
720
  }
586
721
 
587
- async function waitForCallback(context, fallbackPage) {
722
+ async function waitForCallback(context, fallbackPage, timeoutMs = 120000) {
588
723
  const isCallbackUrl = (current) => {
589
724
  if (typeof current !== 'string') {
590
725
  return false;
@@ -605,13 +740,13 @@ async function waitForCallback(context, fallbackPage) {
605
740
  }
606
741
 
607
742
  try {
608
- await fallbackPage.waitForURL((current) => isCallbackUrl(current), { timeout: 120000 });
743
+ await fallbackPage.waitForURL((current) => isCallbackUrl(current), { timeout: timeoutMs });
609
744
  return fallbackPage;
610
745
  } catch {
611
746
  // ignore and wait for popup
612
747
  }
613
748
 
614
- const callback = await context.waitForEvent('page', { timeout: 120000 });
749
+ const callback = await context.waitForEvent('page', { timeout: timeoutMs });
615
750
  await callback.waitForLoadState('domcontentloaded', { timeout: 60000 }).catch(() => {});
616
751
  return callback;
617
752
  }
@@ -0,0 +1,126 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+
5
+ function parseArgs(argv) {
6
+ const args = {
7
+ intervalMs: 1000,
8
+ errorsRoot: process.env.ROUTECODEX_ERRORSAMPLES_DIR || path.join(os.homedir(), '.routecodex', 'errorsamples'),
9
+ once: false
10
+ };
11
+ for (let i = 0; i < argv.length; i += 1) {
12
+ const a = argv[i];
13
+ if (a === '--once') args.once = true;
14
+ else if (a === '--interval' || a === '--intervalMs') {
15
+ const v = argv[i + 1];
16
+ i += 1;
17
+ const n = Number(v);
18
+ if (Number.isFinite(n) && n > 0) args.intervalMs = n;
19
+ } else if (a === '--errorsRoot') {
20
+ const v = argv[i + 1];
21
+ i += 1;
22
+ if (v && String(v).trim()) args.errorsRoot = path.resolve(String(v).trim());
23
+ }
24
+ }
25
+ return args;
26
+ }
27
+
28
+ function safeJsonRead(filePath) {
29
+ try {
30
+ const text = fs.readFileSync(filePath, 'utf8');
31
+ return JSON.parse(text);
32
+ } catch {
33
+ return null;
34
+ }
35
+ }
36
+
37
+ function listJsonFiles(dirPath) {
38
+ try {
39
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
40
+ return entries
41
+ .filter((e) => e.isFile() && e.name.endsWith('.json'))
42
+ .map((e) => path.join(dirPath, e.name));
43
+ } catch {
44
+ return [];
45
+ }
46
+ }
47
+
48
+ function summarizeRecord(record) {
49
+ if (!record || typeof record !== 'object') return null;
50
+ const kind = record.kind || 'unknown';
51
+ const timestamp = record.timestamp || record.time || null;
52
+
53
+ if (String(kind).includes('shadow') || String(kind).includes('diff')) {
54
+ return {
55
+ kind,
56
+ timestamp,
57
+ requestId: record.requestId,
58
+ entryEndpoint: record.entryEndpoint,
59
+ baselineMode: record.baselineMode,
60
+ candidateMode: record.candidateMode,
61
+ diffCount: record.diffCount,
62
+ diffPaths: Array.isArray(record.diffPaths) ? record.diffPaths.slice(0, 12) : undefined,
63
+ runtime: record.runtime
64
+ };
65
+ }
66
+ if (String(kind).includes('hub_policy') || String(kind).includes('policy')) {
67
+ return {
68
+ kind,
69
+ timestamp,
70
+ stage: record.stage,
71
+ requestId: record.requestId,
72
+ endpoint: record.endpoint,
73
+ providerProtocol: record.providerProtocol,
74
+ violationCount: Array.isArray(record.observation?.violations) ? record.observation.violations.length : undefined,
75
+ runtime: record.runtime
76
+ };
77
+ }
78
+ return { kind, timestamp };
79
+ }
80
+
81
+ function printNewFile(filePath) {
82
+ const record = safeJsonRead(filePath);
83
+ const summary = summarizeRecord(record);
84
+ const rel = filePath;
85
+ if (!summary) {
86
+ // eslint-disable-next-line no-console
87
+ console.log(`[errorsamples] ${rel}`);
88
+ return;
89
+ }
90
+ // eslint-disable-next-line no-console
91
+ console.log(`[errorsamples] ${rel} -> ${JSON.stringify(summary)}`);
92
+ }
93
+
94
+ async function main() {
95
+ const args = parseArgs(process.argv.slice(2));
96
+
97
+ const dirs = [
98
+ path.join(args.errorsRoot, 'unified-hub-shadow-runtime'),
99
+ path.join(args.errorsRoot, 'unified-hub-shadow-runtime-routing'),
100
+ path.join(args.errorsRoot, 'policy')
101
+ ];
102
+
103
+ // eslint-disable-next-line no-console
104
+ console.log('[monitor:diff] watching:', dirs.join(', '));
105
+ // eslint-disable-next-line no-console
106
+ console.log('[monitor:diff] intervalMs=', args.intervalMs, 'errorsRoot=', args.errorsRoot);
107
+
108
+ const seen = new Set();
109
+ const scanOnce = () => {
110
+ for (const dir of dirs) {
111
+ const files = listJsonFiles(dir);
112
+ for (const f of files) {
113
+ if (seen.has(f)) continue;
114
+ seen.add(f);
115
+ printNewFile(f);
116
+ }
117
+ }
118
+ };
119
+
120
+ scanOnce();
121
+ if (args.once) return;
122
+ setInterval(scanOnce, args.intervalMs);
123
+ }
124
+
125
+ await main();
126
+
@@ -70,12 +70,30 @@ try {
70
70
  mutated.bundledDependencies = [];
71
71
  mutated.bundleDependencies = [];
72
72
  const llmsVersion = original.dependencies?.['@jsonstudio/llms'] || '^0.6.230';
73
+ const deps = {
74
+ ...(original.dependencies || {})
75
+ };
76
+ // Avoid recursive self-dependency when packing @jsonstudio/rcc.
77
+ if (isRcc && deps['@jsonstudio/rcc']) {
78
+ delete deps['@jsonstudio/rcc'];
79
+ }
73
80
  mutated.dependencies = {
74
- ...(original.dependencies || {}),
81
+ ...deps,
75
82
  ajv: original.dependencies?.ajv || '^8.17.1',
76
83
  zod: original.dependencies?.zod || '^3.23.8',
77
84
  '@jsonstudio/llms': llmsVersion
78
85
  };
86
+ // Ensure rcc ships bundled docs (copied to ~/.routecodex/docs by `rcc init`).
87
+ if (isRcc) {
88
+ const baseFiles = Array.isArray(original.files) ? [...original.files] : [];
89
+ if (!baseFiles.includes('docs/')) {
90
+ baseFiles.push('docs/');
91
+ }
92
+ if (!baseFiles.includes('configsamples/')) {
93
+ baseFiles.push('configsamples/');
94
+ }
95
+ mutated.files = baseFiles;
96
+ }
79
97
  } else if (isRccx) {
80
98
  // rccx: wasm-backed llms 核心,通过 npm alias 将 @jsonstudio/llms 指向 wasm 引擎包。
81
99
  mutated.bundledDependencies = [];
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { spawnSync } from 'node:child_process';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
+ const PROJECT_ROOT = path.resolve(__dirname, '..');
9
+
10
+ const pkgPath = path.join(PROJECT_ROOT, 'package.json');
11
+ const PACK_SCRIPT = path.join(PROJECT_ROOT, 'scripts', 'pack-mode.mjs');
12
+ const llmsPath = path.join(PROJECT_ROOT, 'node_modules', '@jsonstudio', 'llms');
13
+
14
+ function run(command, args, options = {}) {
15
+ const res = spawnSync(command, args, { stdio: 'inherit', ...options });
16
+ if ((res.status ?? 0) !== 0) {
17
+ throw new Error(`${command} ${args.join(' ')} failed`);
18
+ }
19
+ }
20
+
21
+ function isSymlink(p) {
22
+ try {
23
+ return fs.lstatSync(p).isSymbolicLink();
24
+ } catch {
25
+ return false;
26
+ }
27
+ }
28
+
29
+ try {
30
+ const hadDevLink = isSymlink(llmsPath);
31
+
32
+ // 1) release 模式构建 dist(依赖 npm 上的 @jsonstudio/llms)
33
+ run('npm', ['run', 'build:min'], {
34
+ cwd: PROJECT_ROOT,
35
+ env: { ...process.env, BUILD_MODE: 'release' }
36
+ });
37
+
38
+ // 2) 通过 pack-mode 生成 rcc tarball(内部会临时切换 package.json.name/bin 并确保 llms 为 release 包)
39
+ run(process.execPath, [PACK_SCRIPT, '--name', '@jsonstudio/rcc', '--bin', 'rcc'], { cwd: PROJECT_ROOT });
40
+
41
+ const updatedPkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
42
+ const version = updatedPkg.version;
43
+ const tarballName = `jsonstudio-rcc-${version}.tgz`;
44
+ const tarballPath = path.join(PROJECT_ROOT, tarballName);
45
+
46
+ if (!fs.existsSync(tarballPath)) {
47
+ throw new Error(`tarball not found: ${tarballPath}`);
48
+ }
49
+
50
+ console.log(`[pack-rcc] ✅ tarball ready: ${tarballPath}`);
51
+
52
+ // 3) pack 结束后恢复 dev 模式(routecodex 约定始终为 dev CLI;rcc 打包时才切 release)。
53
+ if (hadDevLink) {
54
+ run('npm', ['run', 'llmswitch:ensure'], {
55
+ cwd: PROJECT_ROOT,
56
+ env: { ...process.env, BUILD_MODE: 'dev' }
57
+ });
58
+ }
59
+ } catch (err) {
60
+ console.error('[pack-rcc] failed:', err instanceof Error ? err.message : String(err));
61
+ process.exit(1);
62
+ }
63
+
@@ -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, mode, entryEndpoint, routeHint, payload }) {
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 baseline = await runOnce({ requestId, mode: baselineMode, entryEndpoint, routeHint, payload });
304
- const candidate = await runOnce({ requestId, mode: candidateMode, entryEndpoint, routeHint, payload });
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: baseline.providerPayload,
308
- target: baseline.target,
324
+ providerPayload: baselineProviderPayload,
325
+ target: candidate.target,
309
326
  metadata: {
310
- entryEndpoint: baseline.metadata?.entryEndpoint,
311
- providerProtocol: baseline.metadata?.providerProtocol,
312
- processMode: baseline.metadata?.processMode,
313
- stream: baseline.metadata?.stream,
314
- routeHint: baseline.metadata?.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
- const diffs = diffPayloads(baselineOut, candidateOut);
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;