@jsonstudio/rcc 0.89.1205 → 0.89.1457

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. package/README.md +53 -1412
  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 +77 -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 +94 -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 +37 -0
  40. package/dist/cli/config/init-config.js +212 -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/gemini-protocol-client.js +2 -1
  51. package/dist/client/gemini/gemini-protocol-client.js.map +1 -1
  52. package/dist/client/gemini-cli/gemini-cli-protocol-client.js +40 -16
  53. package/dist/client/gemini-cli/gemini-cli-protocol-client.js.map +1 -1
  54. package/dist/client/openai/chat-protocol-client.js +2 -1
  55. package/dist/client/openai/chat-protocol-client.js.map +1 -1
  56. package/dist/client/responses/responses-protocol-client.js +2 -1
  57. package/dist/client/responses/responses-protocol-client.js.map +1 -1
  58. package/dist/config/risk-control-config.d.ts +94 -0
  59. package/dist/config/risk-control-config.js +196 -0
  60. package/dist/config/risk-control-config.js.map +1 -0
  61. package/dist/constants/index.d.ts +6 -0
  62. package/dist/constants/index.js +13 -0
  63. package/dist/constants/index.js.map +1 -1
  64. package/dist/docs/daemon-admin-ui.html +2113 -190
  65. package/dist/error-handling/quiet-error-handling-center.js +46 -8
  66. package/dist/error-handling/quiet-error-handling-center.js.map +1 -1
  67. package/dist/index.js +0 -1
  68. package/dist/index.js.map +1 -1
  69. package/dist/manager/modules/health/index.d.ts +1 -1
  70. package/dist/manager/modules/quota/antigravity-quota-manager.d.ts +70 -0
  71. package/dist/manager/modules/quota/antigravity-quota-manager.js +442 -0
  72. package/dist/manager/modules/quota/antigravity-quota-manager.js.map +1 -0
  73. package/dist/manager/modules/quota/index.d.ts +3 -127
  74. package/dist/manager/modules/quota/index.js +2 -1093
  75. package/dist/manager/modules/quota/index.js.map +1 -1
  76. package/dist/manager/modules/quota/provider-key-normalization.d.ts +3 -0
  77. package/dist/manager/modules/quota/provider-key-normalization.js +155 -0
  78. package/dist/manager/modules/quota/provider-key-normalization.js.map +1 -0
  79. package/dist/manager/modules/quota/provider-quota-daemon.cooldown.d.ts +9 -0
  80. package/dist/manager/modules/quota/provider-quota-daemon.cooldown.js +115 -0
  81. package/dist/manager/modules/quota/provider-quota-daemon.cooldown.js.map +1 -0
  82. package/dist/manager/modules/quota/provider-quota-daemon.d.ts +77 -0
  83. package/dist/manager/modules/quota/provider-quota-daemon.events.d.ts +12 -0
  84. package/dist/manager/modules/quota/provider-quota-daemon.events.js +239 -0
  85. package/dist/manager/modules/quota/provider-quota-daemon.events.js.map +1 -0
  86. package/dist/manager/modules/quota/provider-quota-daemon.js +404 -0
  87. package/dist/manager/modules/quota/provider-quota-daemon.js.map +1 -0
  88. package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.d.ts +11 -0
  89. package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.js +192 -0
  90. package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.js.map +1 -0
  91. package/dist/manager/modules/quota/provider-quota-daemon.snapshot.d.ts +8 -0
  92. package/dist/manager/modules/quota/provider-quota-daemon.snapshot.js +96 -0
  93. package/dist/manager/modules/quota/provider-quota-daemon.snapshot.js.map +1 -0
  94. package/dist/manager/modules/quota/provider-quota-daemon.view.d.ts +19 -0
  95. package/dist/manager/modules/quota/provider-quota-daemon.view.js +37 -0
  96. package/dist/manager/modules/quota/provider-quota-daemon.view.js.map +1 -0
  97. package/dist/manager/modules/routing/index.d.ts +1 -0
  98. package/dist/manager/modules/routing/index.js +11 -25
  99. package/dist/manager/modules/routing/index.js.map +1 -1
  100. package/dist/manager/quota/provider-quota-center.d.ts +2 -0
  101. package/dist/manager/quota/provider-quota-center.js +80 -82
  102. package/dist/manager/quota/provider-quota-center.js.map +1 -1
  103. package/dist/modules/llmswitch/bridge.d.ts +16 -18
  104. package/dist/modules/llmswitch/bridge.js +293 -94
  105. package/dist/modules/llmswitch/bridge.js.map +1 -1
  106. package/dist/modules/llmswitch/core-loader.d.ts +4 -2
  107. package/dist/modules/llmswitch/core-loader.js +32 -20
  108. package/dist/modules/llmswitch/core-loader.js.map +1 -1
  109. package/dist/modules/pipeline/utils/colored-logger.js +3 -2
  110. package/dist/modules/pipeline/utils/colored-logger.js.map +1 -1
  111. package/dist/modules/pipeline/utils/debug-logger.js +1 -1
  112. package/dist/modules/pipeline/utils/debug-logger.js.map +1 -1
  113. package/dist/providers/auth/antigravity-userinfo-helper.d.ts +2 -1
  114. package/dist/providers/auth/antigravity-userinfo-helper.js +25 -4
  115. package/dist/providers/auth/antigravity-userinfo-helper.js.map +1 -1
  116. package/dist/providers/auth/iflow-cookie-auth.js +0 -2
  117. package/dist/providers/auth/iflow-cookie-auth.js.map +1 -1
  118. package/dist/providers/auth/oauth-lifecycle.js +2 -23
  119. package/dist/providers/auth/oauth-lifecycle.js.map +1 -1
  120. package/dist/providers/auth/tokenfile-auth.d.ts +2 -0
  121. package/dist/providers/auth/tokenfile-auth.js +33 -1
  122. package/dist/providers/auth/tokenfile-auth.js.map +1 -1
  123. package/dist/providers/core/config/camoufox-launcher.d.ts +5 -0
  124. package/dist/providers/core/config/camoufox-launcher.js +40 -4
  125. package/dist/providers/core/config/camoufox-launcher.js.map +1 -1
  126. package/dist/providers/core/config/service-profiles.js +7 -18
  127. package/dist/providers/core/config/service-profiles.js.map +1 -1
  128. package/dist/providers/core/runtime/antigravity-quota-client.js +6 -3
  129. package/dist/providers/core/runtime/antigravity-quota-client.js.map +1 -1
  130. package/dist/providers/core/runtime/base-provider.d.ts +2 -7
  131. package/dist/providers/core/runtime/base-provider.js +84 -165
  132. package/dist/providers/core/runtime/base-provider.js.map +1 -1
  133. package/dist/providers/core/runtime/gemini-cli-http-provider.d.ts +7 -0
  134. package/dist/providers/core/runtime/gemini-cli-http-provider.js +368 -97
  135. package/dist/providers/core/runtime/gemini-cli-http-provider.js.map +1 -1
  136. package/dist/providers/core/runtime/http-request-executor.d.ts +3 -0
  137. package/dist/providers/core/runtime/http-request-executor.js +110 -38
  138. package/dist/providers/core/runtime/http-request-executor.js.map +1 -1
  139. package/dist/providers/core/runtime/http-transport-provider.d.ts +17 -0
  140. package/dist/providers/core/runtime/http-transport-provider.js +165 -16
  141. package/dist/providers/core/runtime/http-transport-provider.js.map +1 -1
  142. package/dist/providers/core/runtime/provider-error-classifier.js +10 -0
  143. package/dist/providers/core/runtime/provider-error-classifier.js.map +1 -1
  144. package/dist/providers/core/runtime/provider-factory.js +7 -5
  145. package/dist/providers/core/runtime/provider-factory.js.map +1 -1
  146. package/dist/providers/core/runtime/provider-runtime-metadata.d.ts +6 -0
  147. package/dist/providers/core/runtime/provider-runtime-metadata.js.map +1 -1
  148. package/dist/providers/core/runtime/rate-limit-manager.d.ts +1 -12
  149. package/dist/providers/core/runtime/rate-limit-manager.js +4 -77
  150. package/dist/providers/core/runtime/rate-limit-manager.js.map +1 -1
  151. package/dist/providers/core/runtime/responses-provider.d.ts +1 -7
  152. package/dist/providers/core/runtime/responses-provider.js +12 -93
  153. package/dist/providers/core/runtime/responses-provider.js.map +1 -1
  154. package/dist/providers/core/strategies/oauth-auth-code-flow.js +12 -8
  155. package/dist/providers/core/strategies/oauth-auth-code-flow.js.map +1 -1
  156. package/dist/providers/core/utils/http-client.js +36 -46
  157. package/dist/providers/core/utils/http-client.js.map +1 -1
  158. package/dist/providers/core/utils/provider-error-logger.d.ts +1 -1
  159. package/dist/providers/core/utils/provider-error-reporter.d.ts +3 -1
  160. package/dist/providers/core/utils/provider-error-reporter.js +3 -0
  161. package/dist/providers/core/utils/provider-error-reporter.js.map +1 -1
  162. package/dist/providers/core/utils/snapshot-writer.js +1 -4
  163. package/dist/providers/core/utils/snapshot-writer.js.map +1 -1
  164. package/dist/providers/mock/mock-provider-runtime.js +57 -27
  165. package/dist/providers/mock/mock-provider-runtime.js.map +1 -1
  166. package/dist/scripts/camoufox/launch-auth.mjs +193 -58
  167. package/dist/server/handlers/handler-utils.js +8 -3
  168. package/dist/server/handlers/handler-utils.js.map +1 -1
  169. package/dist/server/handlers/responses-handler.js +1 -1
  170. package/dist/server/handlers/responses-handler.js.map +1 -1
  171. package/dist/server/runtime/http-server/daemon-admin/auth-handler.d.ts +2 -0
  172. package/dist/server/runtime/http-server/daemon-admin/auth-handler.js +103 -0
  173. package/dist/server/runtime/http-server/daemon-admin/auth-handler.js.map +1 -0
  174. package/dist/server/runtime/http-server/daemon-admin/auth-session.d.ts +5 -0
  175. package/dist/server/runtime/http-server/daemon-admin/auth-session.js +77 -0
  176. package/dist/server/runtime/http-server/daemon-admin/auth-session.js.map +1 -0
  177. package/dist/server/runtime/http-server/daemon-admin/auth-store.d.ts +18 -0
  178. package/dist/server/runtime/http-server/daemon-admin/auth-store.js +89 -0
  179. package/dist/server/runtime/http-server/daemon-admin/auth-store.js.map +1 -0
  180. package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js +1 -2
  181. package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js.map +1 -1
  182. package/dist/server/runtime/http-server/daemon-admin/providers-handler.js +226 -24
  183. package/dist/server/runtime/http-server/daemon-admin/providers-handler.js.map +1 -1
  184. package/dist/server/runtime/http-server/daemon-admin/quota-handler.js +47 -8
  185. package/dist/server/runtime/http-server/daemon-admin/quota-handler.js.map +1 -1
  186. package/dist/server/runtime/http-server/daemon-admin/restart-handler.js +1 -1
  187. package/dist/server/runtime/http-server/daemon-admin/restart-handler.js.map +1 -1
  188. package/dist/server/runtime/http-server/daemon-admin/stats-handler.js +1 -1
  189. package/dist/server/runtime/http-server/daemon-admin/stats-handler.js.map +1 -1
  190. package/dist/server/runtime/http-server/daemon-admin/status-handler.js +68 -4
  191. package/dist/server/runtime/http-server/daemon-admin/status-handler.js.map +1 -1
  192. package/dist/server/runtime/http-server/daemon-admin-routes.d.ts +3 -4
  193. package/dist/server/runtime/http-server/daemon-admin-routes.js +9 -14
  194. package/dist/server/runtime/http-server/daemon-admin-routes.js.map +1 -1
  195. package/dist/server/runtime/http-server/executor-metadata.js +1 -1
  196. package/dist/server/runtime/http-server/executor-metadata.js.map +1 -1
  197. package/dist/server/runtime/http-server/executor-response.js +0 -16
  198. package/dist/server/runtime/http-server/executor-response.js.map +1 -1
  199. package/dist/server/runtime/http-server/hub-shadow-compare.js +110 -34
  200. package/dist/server/runtime/http-server/hub-shadow-compare.js.map +1 -1
  201. package/dist/server/runtime/http-server/index.d.ts +5 -3
  202. package/dist/server/runtime/http-server/index.js +281 -136
  203. package/dist/server/runtime/http-server/index.js.map +1 -1
  204. package/dist/server/runtime/http-server/middleware.js +19 -1
  205. package/dist/server/runtime/http-server/middleware.js.map +1 -1
  206. package/dist/server/runtime/http-server/request-executor.js +59 -24
  207. package/dist/server/runtime/http-server/request-executor.js.map +1 -1
  208. package/dist/server/runtime/http-server/routes.js +12 -3
  209. package/dist/server/runtime/http-server/routes.js.map +1 -1
  210. package/dist/server/runtime/http-server/session-dir.d.ts +2 -0
  211. package/dist/server/runtime/http-server/session-dir.js +59 -0
  212. package/dist/server/runtime/http-server/session-dir.js.map +1 -0
  213. package/dist/server/runtime/http-server/types.d.ts +0 -4
  214. package/dist/server/utils/utf8-chunk-buffer.js +6 -3
  215. package/dist/server/utils/utf8-chunk-buffer.js.map +1 -1
  216. package/dist/server/utils/warmup-storm-tracker.js +1 -1
  217. package/dist/server/utils/warmup-storm-tracker.js.map +1 -1
  218. package/dist/server-factory.d.ts +6 -28
  219. package/dist/server-factory.js +8 -93
  220. package/dist/server-factory.js.map +1 -1
  221. package/dist/token-daemon/index.js +2 -2
  222. package/dist/token-daemon/index.js.map +1 -1
  223. package/dist/token-daemon/provider-registry.js +0 -1
  224. package/dist/token-daemon/provider-registry.js.map +1 -1
  225. package/dist/token-daemon/server-utils.js +8 -9
  226. package/dist/token-daemon/server-utils.js.map +1 -1
  227. package/dist/token-daemon/token-utils.js +1 -1
  228. package/dist/token-daemon/token-utils.js.map +1 -1
  229. package/dist/tools/semantic-replay.js +2 -2
  230. package/dist/tools/semantic-replay.js.map +1 -1
  231. package/dist/tools/stats-request-events.d.ts +1 -1
  232. package/dist/tools/stats-usage.js +6 -3
  233. package/dist/tools/stats-usage.js.map +1 -1
  234. package/dist/utils/llms-engine-shadow.d.ts +19 -0
  235. package/dist/utils/llms-engine-shadow.js +209 -0
  236. package/dist/utils/llms-engine-shadow.js.map +1 -0
  237. package/dist/utils/runtime-versions.js +2 -1
  238. package/dist/utils/runtime-versions.js.map +1 -1
  239. package/dist/utils/strip-internal-keys.d.ts +12 -0
  240. package/dist/utils/strip-internal-keys.js +28 -0
  241. package/dist/utils/strip-internal-keys.js.map +1 -0
  242. package/docs/ARCHITECTURE.md +402 -0
  243. package/docs/CHAT_PROCESS_PROTOCOL_AND_PIPELINE.md +221 -0
  244. package/docs/CODEX_AND_CLAUDE_CODE.md +69 -0
  245. package/docs/CONFIG_ARCHITECTURE.md +517 -0
  246. package/docs/ERROR_HANDLING_AUDIT.md +0 -0
  247. package/docs/GCLI2API_PARITY_GAPS.md +98 -0
  248. package/docs/INSTALLATION_AND_QUICKSTART.md +74 -0
  249. package/docs/INSTRUCTION_MARKUP.md +89 -0
  250. package/docs/MODULE_ENHANCEMENT_SYSTEM.md +666 -0
  251. package/docs/PORTS.md +36 -0
  252. package/docs/PROVIDERS_BUILTIN.md +111 -0
  253. package/docs/PROVIDER_TYPES.md +55 -0
  254. package/docs/SERVERTOOL_CLOCK_DESIGN.md +233 -0
  255. package/docs/USAGE_HANDLING_ANALYSIS.md +335 -0
  256. package/docs/USER_CONFIG_PARSER_CHANGES.md +175 -0
  257. package/docs/V3_INBOUND_OUTBOUND_DESIGN.md +86 -0
  258. package/docs/VIRTUAL_ROUTER_PRIORITY_AND_HEALTH.md +125 -0
  259. package/docs/anthropic-request-golden-samples.md +50 -0
  260. package/docs/antigravity-gemini-format-cleanup.md +102 -0
  261. package/docs/antigravity-routing-contract.md +31 -0
  262. package/docs/ccr-alignment-enhancetool.md +105 -0
  263. package/docs/chat-glm-500-analysis.md +79 -0
  264. package/docs/chat-request-golden-samples.md +42 -0
  265. package/docs/chat-semantic-expansion-plan.md +84 -0
  266. package/docs/cli-command-inventory.md +76 -0
  267. package/docs/codex-samples-replay.md +50 -0
  268. package/docs/daemon-admin-api-design.md +350 -0
  269. package/docs/daemon-admin-module-structure.md +169 -0
  270. package/docs/daemon-admin-ui.html +3394 -0
  271. package/docs/debug-system-design.md +734 -0
  272. package/docs/debugging/gemini-sse-root-cause.md +52 -0
  273. package/docs/debugging/sse_encoding_failure_analysis.md +53 -0
  274. package/docs/dry-run/README.md +721 -0
  275. package/docs/error-handling-v2.md +92 -0
  276. package/docs/exec-command-guard-policy.example.v1.json +42 -0
  277. package/docs/fixes/gemini-protocol-mapping.md +57 -0
  278. package/docs/fixes/oauth-portal-timing-fix.md +202 -0
  279. package/docs/fixes/web-search-hop3-fix.md +265 -0
  280. package/docs/glm-api-reference.md +390 -0
  281. package/docs/glm-chat-completions.md +1779 -0
  282. package/docs/glm-history-inline-images.md +44 -0
  283. package/docs/golden-ci-library.md +66 -0
  284. package/docs/lmstudio-dry-run-summary.md +203 -0
  285. package/docs/lmstudio-tool-calling.md +214 -0
  286. package/docs/mapping-tables/anthropic-to-openai.json +290 -0
  287. package/docs/mapping-tables/iflow-to-openai.json +215 -0
  288. package/docs/mapping-tables/openai-passthrough.json +190 -0
  289. package/docs/mapping-tables/openai-to-iflow.json +227 -0
  290. package/docs/monitoring/Design.md +61 -0
  291. package/docs/multi-token-auth-guide.md +66 -0
  292. package/docs/oauth-authentication-guide.md +168 -0
  293. package/docs/oauth-iflow-implementation.md +153 -0
  294. package/docs/pipeline-routing-report.md +209 -0
  295. package/docs/plans/manager-daemon/PLAN.md +86 -0
  296. package/docs/plans/provider-config-v2-plan.md +176 -0
  297. package/docs/plans/provider-runtime-manager-plan.md +209 -0
  298. package/docs/plans/transparent-429-failover.md +89 -0
  299. package/docs/plans/unified-hub-framework-v1.md +245 -0
  300. package/docs/provider-config-v2-ui-design.md +181 -0
  301. package/docs/provider-quota-design.md +129 -0
  302. package/docs/providers/gemini-provider.md +62 -0
  303. package/docs/providers/lmstudio-v2-migration-report.md +102 -0
  304. package/docs/providers/provider-composite-design.md +142 -0
  305. package/docs/providers/provider-composite-testing.md +98 -0
  306. package/docs/providers/provider-type-only-migration.md +111 -0
  307. package/docs/rccx-wasm-migration.md +74 -0
  308. package/docs/refactoring/architecture-comparison-diagram.md +140 -0
  309. package/docs/refactoring/compatibility-v2-architecture-design.md +738 -0
  310. package/docs/refactoring/workflow-compatibility-refactoring-design.md +361 -0
  311. package/docs/reports/routing-classification-report.json +24 -0
  312. package/docs/reports/routing-classification-report.md +18 -0
  313. package/docs/reports/thinking-keywords-report.json +19 -0
  314. package/docs/responses/README.md +156 -0
  315. package/docs/responses-generic-provider.md +86 -0
  316. package/docs/responses-passthrough-provider-design.md +202 -0
  317. package/docs/routing-awrr-health-weighted-round-robin.md +179 -0
  318. package/docs/routing-instructions.md +393 -0
  319. package/docs/servertool-framework.md +65 -0
  320. package/docs/stop-message-auto.md +225 -0
  321. package/docs/streaming-flow.html +30 -0
  322. package/docs/streaming-flow.md +182 -0
  323. package/docs/token-daemon-preview.html +490 -0
  324. package/docs/token-refresh-daemon-plan.md +269 -0
  325. package/docs/transformation-tables/Gemini-FinishReason/345/256/214/346/225/264/350/275/254/346/215/242/350/241/250.json +233 -0
  326. package/docs/transformation-tables/README.md +225 -0
  327. package/docs/transformation-tables/claude-code-router-anthropic-to-gemini.json +283 -0
  328. package/docs/transformation-tables/claude-code-router-anthropic-to-openai.json +208 -0
  329. package/docs/transformation-tables/claude-code-router-openai-to-anthropic.json +261 -0
  330. package/docs/transformation-tables/claude-code-router-openai-to-gemini.json +208 -0
  331. package/docs/transformation-tables/claude-code-router-openai-to-lmstudio.json +182 -0
  332. package/docs/transformation-tables/claude-code-router-openai-to-ollama.json +250 -0
  333. package/docs/transformation-tables/claude-code-router-openai-to-textgenwebui.json +295 -0
  334. package/docs/transformation-tables/claude-code-router-provider-conversions.json +193 -0
  335. 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
  336. 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
  337. 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
  338. 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
  339. 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
  340. 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
  341. 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
  342. package/docs/v2-architecture/IMPLEMENTATION-ROADMAP.md +367 -0
  343. package/docs/v2-architecture/OPTIMIZED-DESIGN.md +827 -0
  344. package/docs/v2-architecture/PRERUN-CONNECTION-DESIGN.md +716 -0
  345. package/docs/v2-architecture/README.md +549 -0
  346. package/docs/verification/modelscope-verify.md +59 -0
  347. package/docs/verified-configs/README.md +60 -0
  348. package/docs/verified-configs/v0.45.0/README.md +244 -0
  349. package/docs/verified-configs/v0.45.0/lmstudio-5521-gpt-oss-20b-mlx.json +135 -0
  350. package/docs/verified-configs/v0.45.0/merged-config.5521.json +1205 -0
  351. package/docs/verified-configs/v0.45.0/merged-config.qwen-5522.json +1559 -0
  352. package/docs/verified-configs/v0.45.0/qwen-5522-qwen3-coder-plus-final.json +221 -0
  353. package/docs/verified-configs/v0.45.0/qwen-5522-qwen3-coder-plus-fixed.json +242 -0
  354. package/docs/verified-configs/v0.45.0/qwen-5522-qwen3-coder-plus.json +242 -0
  355. package/docs/web-search-service-design.md +322 -0
  356. package/package.json +26 -15
  357. package/scripts/build-core.mjs +3 -1
  358. package/scripts/camoufox/launch-auth.mjs +193 -58
  359. package/scripts/ci/repo-sanity.mjs +138 -0
  360. package/scripts/mock-provider/run-regressions.mjs +157 -1
  361. package/scripts/monitor-diff.mjs +126 -0
  362. package/scripts/pack-mode.mjs +19 -1
  363. package/scripts/pack-rcc.mjs +63 -0
  364. package/scripts/run-bg.sh +0 -14
  365. package/scripts/tests/ci-jest.mjs +119 -0
  366. package/scripts/tools-dev/responses-debug-client/README.md +23 -0
  367. package/scripts/tools-dev/responses-debug-client/payloads/poem.json +13 -0
  368. package/scripts/tools-dev/responses-debug-client/payloads/sample-no-tools.json +98 -0
  369. package/scripts/tools-dev/responses-debug-client/payloads/text.json +13 -0
  370. package/scripts/tools-dev/responses-debug-client/payloads/tool.json +27 -0
  371. package/scripts/tools-dev/responses-debug-client/run.mjs +65 -0
  372. package/scripts/tools-dev/responses-debug-client/src/index.ts +281 -0
  373. package/scripts/tools-dev/run-llmswitch-chat.mjs +53 -0
  374. package/scripts/tools-dev/server-tools-dev/run-web-fetch.mjs +65 -0
  375. package/scripts/unified-hub-shadow-compare.mjs +33 -13
  376. package/scripts/vendor-core.mjs +13 -3
  377. package/scripts/verify-e2e-toolcall.mjs +115 -26
  378. package/dist/modules/llmswitch/pipeline-registry.d.ts +0 -57
  379. package/dist/modules/llmswitch/pipeline-registry.js +0 -229
  380. package/dist/modules/llmswitch/pipeline-registry.js.map +0 -1
  381. package/dist/server/RouteCodexServer.d.ts +0 -13
  382. package/dist/server/RouteCodexServer.js +0 -25
  383. package/dist/server/RouteCodexServer.js.map +0 -1
  384. package/dist/v2/conversion/hub/snapshot-recorder.d.ts +0 -12
  385. package/dist/v2/conversion/hub/snapshot-recorder.js +0 -22
  386. package/dist/v2/conversion/hub/snapshot-recorder.js.map +0 -1
  387. package/scripts/test-fc-responses.mjs +0 -66
  388. package/scripts/test-guidance.mjs +0 -100
  389. package/scripts/test-iflow-web-search.mjs +0 -141
  390. package/scripts/test-iflow.mjs +0 -379
  391. package/scripts/test-tool-exec.mjs +0 -26
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import process from 'node:process';
5
+ import OpenAI from 'openai';
6
+
7
+ function parseArgs(argv){ const out={}; for(let i=2;i<argv.length;i++){ const a=argv[i]; if(!a) continue; if(a.startsWith('--')){ const [k,v]=a.split('='); const key=k.replace(/^--/,''); if(typeof v==='string'&&v.length) out[key]=v; else if(i+1<argv.length && !argv[i+1].startsWith('--')) out[key]=argv[++i]; else out[key]=true; } } return out; }
8
+ function short(s,n=60){ return s.length<=n?s:(s.slice(0,n)+'…'); }
9
+ function nowIso(){ return new Date().toISOString(); }
10
+ async function readJson(file){ const abs=path.isAbsolute(file)?file:path.resolve(process.cwd(),file); const raw=await fs.readFile(abs,'utf-8'); return JSON.parse(raw); }
11
+
12
+ async function main(){
13
+ const args=parseArgs(process.argv);
14
+ const file=String(args.file||args.f||'');
15
+ if(!file){ console.error('Usage: node scripts/tools-dev/responses-debug-client/run.mjs --file <payload.json> [--baseURL URL] [--apiKey KEY] [--timeout 120] [--raw]'); process.exit(1); }
16
+ const baseURL=String(args.baseURL||'http://127.0.0.1:5520/v1');
17
+ const apiKey=String(args.apiKey||'dummy');
18
+ const timeoutSec=Number(args.timeout||120);
19
+ const raw=!!args.raw;
20
+
21
+ const body=await readJson(file);
22
+ if (body.stream == null) body.stream = true;
23
+ // attach client_request_id and snapshot request body
24
+ const clientRequestId = `cli_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;
25
+ try{
26
+ const meta = (body && typeof body==='object' && body.metadata && typeof body.metadata==='object') ? body.metadata : {};
27
+ body.metadata = { ...meta, client_request_id: clientRequestId };
28
+ }catch{}
29
+ try{
30
+ const home = process.env.HOME || process.env.USERPROFILE || '.';
31
+ const dir = path.join(String(home), '.routecodex', 'codex-samples', 'responses-client');
32
+ await fs.mkdir(dir, { recursive: true });
33
+ const out = path.join(dir, `${clientRequestId}_client-request.json`);
34
+ await fs.writeFile(out, JSON.stringify({ timestamp: new Date().toISOString(), baseURL, request: body }, null, 2), 'utf-8');
35
+ if(!raw) console.log('saved client snapshot:', out);
36
+ }catch{}
37
+
38
+ const client=new OpenAI({ apiKey, baseURL });
39
+ console.log(`[${nowIso()}] connect baseURL=${baseURL}`);
40
+ const start=Date.now();
41
+ const stream=await client.responses.stream(body);
42
+ let responseId='';
43
+ let model='';
44
+ let text='';
45
+
46
+ const timer=setTimeout(()=>{ try{ stream.controller?.abort?.(); }catch{}; console.error('timeout'); process.exitCode=3; }, timeoutSec*1000);
47
+
48
+ for await (const ev of stream){
49
+ const t=ev?.type||'event';
50
+ const d=ev?.data ?? ev;
51
+ if(raw){ console.log('evt', t, JSON.stringify(d)); }
52
+ switch(t){
53
+ case 'response.created': responseId=String(d?.response?.id||responseId); model=String(d?.response?.model||model); console.log('created', responseId, model); break;
54
+ case 'response.output_text.delta': { const s=String(d?.delta||''); text+=s; console.log('textΔ', s.length, short(s)); break; }
55
+ case 'response.output_text.done': console.log('text✓ total', text.length); break;
56
+ case 'response.completed': console.log('completed', JSON.stringify(d?.response?.usage||{})); break;
57
+ case 'response.required_action': console.log('required_action', JSON.stringify(d?.required_action||d)); break;
58
+ case 'response.error': console.error('error', JSON.stringify(d?.error||d)); process.exitCode=2; break;
59
+ case 'response.done': { const ms=Date.now()-start; console.log('done', ms,'ms'); clearTimeout(timer); return; }
60
+ default: break;
61
+ }
62
+ }
63
+ }
64
+
65
+ main().catch(e=>{ console.error('fatal', e?.message||String(e)); process.exit(2); });
@@ -0,0 +1,281 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Responses Debug Client
4
+ * - Connects to RCC server (baseURL) using OpenAI SDK Responses stream
5
+ * - Consumes SSE named events, prints concise logs
6
+ * - Completes a minimal tool-calls loop by executing local tools and submitting outputs
7
+ */
8
+
9
+ import fs from 'node:fs/promises';
10
+ import path from 'node:path';
11
+ import process from 'node:process';
12
+ import OpenAI from 'openai';
13
+
14
+ type Unknown = Record<string, any>;
15
+
16
+ function parseArgs(argv: string[]): Record<string, string | boolean> {
17
+ const out: Record<string, string | boolean> = {};
18
+ for (let i = 2; i < argv.length; i++) {
19
+ const a = argv[i];
20
+ if (!a) continue;
21
+ if (a.startsWith('--')) {
22
+ const [k, v] = a.split('=');
23
+ const key = k.replace(/^--/, '');
24
+ if (typeof v === 'string' && v.length) out[key] = v;
25
+ else if (i + 1 < argv.length && !argv[i + 1].startsWith('--')) { out[key] = argv[++i]; }
26
+ else out[key] = true;
27
+ }
28
+ }
29
+ return out;
30
+ }
31
+
32
+ function short(s: string, n = 60): string {
33
+ if (s.length <= n) return s;
34
+ return s.slice(0, n) + '…';
35
+ }
36
+
37
+ function nowIso(): string { return new Date().toISOString(); }
38
+
39
+ async function readJson(file: string): Promise<Unknown> {
40
+ const abs = path.isAbsolute(file) ? file : path.resolve(process.cwd(), file);
41
+ const raw = await fs.readFile(abs, 'utf-8');
42
+ return JSON.parse(raw) as Unknown;
43
+ }
44
+
45
+ type ToolOutput = { tool_call_id: string; output: string };
46
+
47
+ function safeJsonParse(s: string): any {
48
+ try { return JSON.parse(s); } catch { return s; }
49
+ }
50
+
51
+ // Minimal local tool handlers
52
+ const localTools: Record<string, (args: any) => Promise<string> | string> = {
53
+ echo: (args: any) => {
54
+ if (typeof args?.text === 'string') return String(args.text);
55
+ return typeof args === 'string' ? args : JSON.stringify(args ?? {});
56
+ },
57
+ sum: (args: any) => {
58
+ const arr = Array.isArray(args?.numbers) ? args.numbers : [];
59
+ const total = arr.reduce((a: number, b: any) => a + (typeof b === 'number' ? b : 0), 0);
60
+ return String(total);
61
+ },
62
+ time: () => new Date().toISOString(),
63
+ };
64
+
65
+ async function executeTool(name: string, argStr: string): Promise<string> {
66
+ const n = String(name || '').trim();
67
+ const handler = localTools[n] || (async () => `Unsupported tool: ${n}`);
68
+ const args = typeof argStr === 'string' ? safeJsonParse(argStr) : argStr;
69
+ try { return await handler(args); } catch (e: any) { return `Tool error: ${e?.message || String(e)}`; }
70
+ }
71
+
72
+ async function main() {
73
+ const args = parseArgs(process.argv);
74
+ const file = String(args.file || args.f || '');
75
+ if (!file) {
76
+ console.error('Usage: tsx scripts/tools-dev/responses-debug-client/src/index.ts --file <payload.json> [--baseURL URL] [--apiKey KEY] [--timeout 120] [--raw] [--save] [--maxRounds 3]');
77
+ process.exit(1);
78
+ }
79
+ const baseURL = String(args.baseURL || 'http://127.0.0.1:5520/v1');
80
+ const apiKey = String(args.apiKey || 'dummy');
81
+ const timeoutSec = Number(args.timeout || 120);
82
+ const raw = !!args.raw;
83
+ const save = !!args.save;
84
+ const maxRounds = Math.max(1, Number(args.maxRounds || 3));
85
+
86
+ const reqBody = await readJson(file);
87
+ if (reqBody.stream == null) reqBody.stream = true;
88
+
89
+ // Attach a client-side request id into payload.metadata for correlation
90
+ const clientRequestId = `cli_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
91
+ try {
92
+ const meta = (reqBody && typeof reqBody === 'object' && (reqBody as any).metadata && typeof (reqBody as any).metadata === 'object')
93
+ ? (reqBody as any).metadata : {};
94
+ (reqBody as any).metadata = { ...meta, client_request_id: clientRequestId };
95
+ } catch { /* ignore */ }
96
+
97
+ // Snapshot exact client request body to ~/.routecodex/codex-samples/responses-client/
98
+ try {
99
+ const home = process.env.HOME || process.env.USERPROFILE || '.';
100
+ const dir = path.join(String(home), '.routecodex', 'codex-samples', 'responses-client');
101
+ await fs.mkdir(dir, { recursive: true });
102
+ const out = path.join(dir, `${clientRequestId}_client-request.json`);
103
+ await fs.writeFile(out, JSON.stringify({
104
+ timestamp: new Date().toISOString(),
105
+ baseURL,
106
+ request: reqBody
107
+ }, null, 2), 'utf-8');
108
+ if (!raw) console.log(`[${nowIso()}] saved client snapshot: ${out}`);
109
+ } catch { /* non-blocking */ }
110
+
111
+ const client = new OpenAI({ apiKey, baseURL });
112
+ const start = Date.now();
113
+ console.log(`[${nowIso()}] connect baseURL=${baseURL}`);
114
+
115
+ const stream: any = await client.responses.stream(reqBody as any);
116
+ let responseId = '';
117
+ let model = '';
118
+ let round = 1;
119
+ const textBuf: string[] = [];
120
+
121
+ // tool state
122
+ const toolArgs: Record<string, string> = {};
123
+ const toolMeta: Record<string, { name?: string; output_index?: number; type?: string }> = {};
124
+ let sawRequiredAction = false;
125
+ let submittedThisRound = false;
126
+ const seqCheck = { last: -1 };
127
+
128
+ const writeLine = async (o: any) => {
129
+ if (!save) return;
130
+ try {
131
+ const dir = path.resolve(process.cwd(), 'logs', 'responses-debug', responseId || 'unknown');
132
+ await fs.mkdir(dir, { recursive: true });
133
+ await fs.appendFile(path.join(dir, 'events.jsonl'), JSON.stringify({ ts: Date.now(), ...o }) + '\n', 'utf-8');
134
+ } catch { /* ignore */ }
135
+ };
136
+
137
+ const submitToolOutputs = async (requiredAction: any) => {
138
+ const tc = Array.isArray(requiredAction?.submit_tool_outputs?.tool_calls)
139
+ ? requiredAction.submit_tool_outputs.tool_calls : [];
140
+ const outputs: ToolOutput[] = [];
141
+ for (const call of tc) {
142
+ const id = String(call?.id || '');
143
+ const name = String(call?.function?.name || '');
144
+ const argStr = String(call?.function?.arguments || '');
145
+ const out = await executeTool(name, argStr);
146
+ outputs.push({ tool_call_id: id, output: out });
147
+ console.log(` ↳ tool[${name}] id=${id} -> output(${out.length})`);
148
+ }
149
+ if (typeof stream.submitToolOutputs === 'function') {
150
+ console.log(` -> submitToolOutputs(${outputs.length}) via stream`);
151
+ await stream.submitToolOutputs({ tool_outputs: outputs, stream: true });
152
+ return;
153
+ }
154
+ throw new Error('SDK stream.submitToolOutputs unavailable; please upgrade openai package');
155
+ };
156
+
157
+ const dumpEvent = (ev: any) => {
158
+ const t = ev?.type || 'event';
159
+ const d = ev?.data ?? ev;
160
+ const seq = typeof d?.sequence_number === 'number' ? d.sequence_number : undefined;
161
+ if (typeof seq === 'number') {
162
+ if (seq <= seqCheck.last) console.warn(` ! sequence rollback: ${seqCheck.last} -> ${seq}`);
163
+ seqCheck.last = seq;
164
+ }
165
+ if (raw) console.log('evt', t, JSON.stringify(d));
166
+ };
167
+
168
+ for await (const ev of stream) {
169
+ await writeLine({ type: ev?.type || 'event', data: ev });
170
+ dumpEvent(ev);
171
+
172
+ switch (ev?.type) {
173
+ case 'response.created': {
174
+ responseId = String(ev?.data?.response?.id || responseId);
175
+ model = String(ev?.data?.response?.model || model);
176
+ console.log(`created id=${responseId} model=${model}`);
177
+ break;
178
+ }
179
+ case 'response.in_progress': {
180
+ break;
181
+ }
182
+ case 'response.output_text.delta': {
183
+ const s = String(ev?.data?.delta || '');
184
+ textBuf.push(s);
185
+ console.log(` textΔ(${s.length}): ${short(s)}`);
186
+ break;
187
+ }
188
+ case 'response.output_text.done': {
189
+ console.log(` text✓ (total=${textBuf.join('').length})`);
190
+ break;
191
+ }
192
+ case 'response.output_item.added': {
193
+ const item = ev?.data?.item || {};
194
+ const id = String(item?.id || '');
195
+ toolMeta[id] = { name: item?.name, output_index: ev?.data?.output_index, type: item?.type };
196
+ toolArgs[id] = toolArgs[id] || '';
197
+ console.log(` tool+ id=${id} name=${item?.name || ''}`);
198
+ break;
199
+ }
200
+ case 'response.function_call_arguments.delta': {
201
+ const id = String(ev?.data?.id || ev?.data?.item_id || '');
202
+ const d = String(ev?.data?.delta || '');
203
+ toolArgs[id] = (toolArgs[id] || '') + d;
204
+ console.log(` argsΔ id=${id} (+${d.length})`);
205
+ break;
206
+ }
207
+ case 'response.function_call_arguments.done': {
208
+ const id = String(ev?.data?.id || ev?.data?.item_id || '');
209
+ const total = (toolArgs[id] || '').length;
210
+ console.log(` args✓ id=${id} (${total})`);
211
+ break;
212
+ }
213
+ case 'response.output_item.done': {
214
+ const item = ev?.data?.item || {};
215
+ const id = String(item?.id || '');
216
+ console.log(` tool✓ id=${id}`);
217
+ // Fallback path for providers不发 required_action:在 function_call 完成后立即提交工具输出
218
+ if (!sawRequiredAction && !submittedThisRound && (toolMeta[id]?.type === 'function_call')) {
219
+ const name = toolMeta[id]?.name || item?.name || '';
220
+ const argStr = item?.arguments || toolArgs[id] || '';
221
+ const outputs: ToolOutput[] = [{ tool_call_id: id, output: await executeTool(name, String(argStr)) }];
222
+ if (typeof stream.submitToolOutputs === 'function') {
223
+ console.log(` -> submitToolOutputs(fallback, ${outputs.length}) via stream [round ${round}]`);
224
+ await stream.submitToolOutputs({ tool_outputs: outputs, stream: true });
225
+ submittedThisRound = true;
226
+ round++;
227
+ if (round > maxRounds) throw new Error(`Exceeded maxRounds=${maxRounds}`);
228
+ }
229
+ }
230
+ break;
231
+ }
232
+ case 'response.required_action': {
233
+ const ra = ev?.data?.required_action || ev?.data; // SDK shape varies
234
+ const count = Array.isArray(ra?.submit_tool_outputs?.tool_calls) ? ra.submit_tool_outputs.tool_calls.length : 0;
235
+ console.log(` required_action submit_tool_outputs(${count}) [round ${round}]`);
236
+ sawRequiredAction = true;
237
+ await submitToolOutputs(ra);
238
+ round++;
239
+ if (round > maxRounds) throw new Error(`Exceeded maxRounds=${maxRounds}`);
240
+ break;
241
+ }
242
+ case 'response.completed': {
243
+ const u = ev?.data?.response?.usage || {};
244
+ const iu = Number(u?.input_tokens || 0);
245
+ const ou = Number(u?.output_tokens || 0);
246
+ const tt = Number(u?.total_tokens || 0);
247
+ console.log(` completed usage: in=${iu} out=${ou} total=${tt}`);
248
+ // Reset per-round flags to allow下一轮
249
+ submittedThisRound = false;
250
+ sawRequiredAction = false;
251
+ break;
252
+ }
253
+ case 'response.error': {
254
+ console.error(' error:', ev?.data?.error);
255
+ process.exitCode = 2;
256
+ break;
257
+ }
258
+ case 'response.done': {
259
+ const ms = Date.now() - start;
260
+ console.log(` done in ${ms} ms`);
261
+ return;
262
+ }
263
+ default: {
264
+ // Heartbeat or unknown event
265
+ const d = ev?.data;
266
+ if (d && typeof d === 'object' && d.type === 'heartbeat') {
267
+ // ignore
268
+ } else if (!raw) {
269
+ // print brief unknowns
270
+ const t = String(ev?.type || 'evt');
271
+ console.log(` ${t}`);
272
+ }
273
+ }
274
+ }
275
+ }
276
+ }
277
+
278
+ main().catch((e) => {
279
+ console.error('fatal:', e?.message || String(e));
280
+ process.exit(2);
281
+ });
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+ // Quick llmswitch-core Chat filter runner: runStandardChatRequestFilters without starting server.
3
+ // Usage:
4
+ // node scripts/tools-dev/run-llmswitch-chat.mjs path/to/chat-request.json [/v1/chat|/v1/messages|/v1/responses]
5
+
6
+ import fs from 'fs';
7
+ import path from 'path';
8
+ import url from 'url';
9
+ import { runStandardChatRequestFilters } from '../../sharedmodule/llmswitch-core/dist/conversion/index.js';
10
+
11
+ const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
12
+
13
+ async function main() {
14
+ const file = process.argv[2];
15
+ const endpoint = process.argv[3] || '/v1/chat/completions';
16
+
17
+ if (!file) {
18
+ console.error('Usage: node scripts/tools-dev/run-llmswitch-chat.mjs <payload.json> [endpoint]');
19
+ process.exit(1);
20
+ }
21
+
22
+ const abs = path.isAbsolute(file) ? file : path.join(process.cwd(), file);
23
+ const txt = fs.readFileSync(abs, 'utf8');
24
+ const raw = JSON.parse(txt);
25
+
26
+ // Allow passing either a raw chat body, or a provider-request snapshot with { endpoint, data: { body } }
27
+ let payload = raw;
28
+ if (raw && typeof raw === 'object' && raw.data && typeof raw.data === 'object' && raw.data.body) {
29
+ payload = raw.data.body;
30
+ }
31
+
32
+ const requestId = `req_${Date.now()}`;
33
+ const profile = {
34
+ id: 'test-profile',
35
+ incomingProtocol: 'openai-chat',
36
+ outgoingProtocol: 'openai-chat'
37
+ };
38
+
39
+ const context = {
40
+ requestId,
41
+ entryEndpoint: endpoint,
42
+ endpoint,
43
+ metadata: {}
44
+ };
45
+
46
+ const out = await runStandardChatRequestFilters(payload, profile, context);
47
+ process.stdout.write(JSON.stringify(out, null, 2) + '\n');
48
+ }
49
+
50
+ main().catch(err => {
51
+ console.error('Error running llmswitch filters:', err);
52
+ process.exit(1);
53
+ });
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+ import { fileURLToPath, pathToFileURL } from 'node:url';
3
+ import path from 'node:path';
4
+
5
+ function parseArgs(argv) {
6
+ const out = { url: null, timeout: null, maxBytes: null, follow: true, headers: {} };
7
+ for (let i = 2; i < argv.length; i++) {
8
+ const a = argv[i];
9
+ if ((a === '--url' || a === '-u') && i + 1 < argv.length) { out.url = argv[++i]; continue; }
10
+ if ((a === '--timeout' || a === '-t') && i + 1 < argv.length) { out.timeout = Number(argv[++i]); continue; }
11
+ if (a === '--no-follow') { out.follow = false; continue; }
12
+ if ((a === '--max-bytes' || a === '-m') && i + 1 < argv.length) { out.maxBytes = Number(argv[++i]); continue; }
13
+ if ((a === '--header' || a === '-H') && i + 1 < argv.length) {
14
+ const kv = String(argv[++i]);
15
+ const idx = kv.indexOf(':');
16
+ if (idx > 0) { const k = kv.slice(0, idx).trim(); const v = kv.slice(idx + 1).trim(); if (k) out.headers[k] = v; }
17
+ continue;
18
+ }
19
+ if (a === '--help' || a === '-h') { out.help = true; }
20
+ }
21
+ return out;
22
+ }
23
+
24
+ function usage() {
25
+ console.log('Usage: node scripts/tools-dev/server-tools-dev/run-web-fetch.mjs --url <URL> [--timeout 12000] [--max-bytes 524288] [--no-follow] [--header "Key: Value"]');
26
+ }
27
+
28
+ async function importCoreFetcher() {
29
+ // Prefer local sharedmodule path if exists; fallback to installed package
30
+ const __filename = fileURLToPath(import.meta.url);
31
+ const repoRoot = path.resolve(path.dirname(__filename), '../..');
32
+ const local = path.resolve(repoRoot, 'sharedmodule/llmswitch-core/dist/tools/web-fetch-html.js');
33
+ try {
34
+ const mod = await import(pathToFileURL(local).href);
35
+ if (typeof mod?.fetchRawHtml === 'function') return mod.fetchRawHtml;
36
+ } catch {}
37
+ throw new Error('Cannot locate fetchRawHtml in sharedmodule/llmswitch-core/dist。请先构建 sharedmodule/llmswitch-core。');
38
+ }
39
+
40
+ async function main() {
41
+ const args = parseArgs(process.argv);
42
+ if (args.help || !args.url) { usage(); process.exit(args.help ? 0 : 1); }
43
+ const fetchRawHtml = await importCoreFetcher();
44
+ const res = await fetchRawHtml(args.url, {
45
+ timeoutMs: args.timeout || undefined,
46
+ followRedirects: args.follow,
47
+ maxBytes: args.maxBytes || undefined,
48
+ headers: Object.keys(args.headers).length ? args.headers : undefined,
49
+ });
50
+ if (res.ok) {
51
+ console.log('OK');
52
+ console.log(`status: ${res.status}`);
53
+ console.log(`content-type: ${res.contentType}`);
54
+ const preview = res.html ?? '';
55
+ console.log('--- html (first 2048 chars) ---');
56
+ console.log(preview.slice(0, 2048));
57
+ } else {
58
+ console.log('FAIL');
59
+ console.log(`error: ${res.error}`);
60
+ if (res.status) console.log(`status: ${res.status}`);
61
+ if (res.contentType) console.log(`content-type: ${res.contentType}`);
62
+ }
63
+ }
64
+
65
+ main().catch((e) => { console.error(e); process.exit(99); });
@@ -141,6 +141,14 @@ function stableStringify(value) {
141
141
  );
142
142
  }
143
143
 
144
+ function cloneJsonSafe(value) {
145
+ try {
146
+ return JSON.parse(JSON.stringify(value));
147
+ } catch {
148
+ return value;
149
+ }
150
+ }
151
+
144
152
  function diffPayloads(expected, actual, p = '<root>') {
145
153
  if (Object.is(expected, actual)) return [];
146
154
  if (typeof expected !== typeof actual) {
@@ -254,12 +262,12 @@ async function bootstrapVirtualRouterConfig(rawConfig) {
254
262
  return mod.bootstrapVirtualRouterConfig(rawConfig);
255
263
  }
256
264
 
257
- async function runOnce({ requestId, 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;
@@ -12,12 +12,18 @@ async function rmrf(p) {
12
12
 
13
13
  async function main() {
14
14
  const root = process.cwd();
15
+ const rawMode = String(process.env.BUILD_MODE || process.env.RCC_BUILD_MODE || 'release').toLowerCase();
16
+ const mode = rawMode === 'dev' ? 'dev' : 'release';
15
17
  const sharedDist = path.join(root, 'sharedmodule', 'llmswitch-core', 'dist');
16
18
  const legacyVendorDir = path.join(root, 'vendor', 'rcc-llmswitch-core');
17
19
  const scopedVendorDir = path.join(root, 'vendor', '@jsonstudio', 'llms');
18
20
 
19
- if (!await exists(sharedDist)) {
20
- console.error('[vendor-core] ERROR: 未找到 sharedmodule/llmswitch-core/dist');
21
+ // In release mode we rely on npm-installed `@jsonstudio/llms`, so the local sharedmodule dist
22
+ // is optional and must not block CI (where sharedmodule often doesn't exist).
23
+ // In dev mode, `node_modules/@jsonstudio/llms` is typically symlinked to sharedmodule/llmswitch-core,
24
+ // so we keep a hard requirement for the dist output.
25
+ if (mode === 'dev' && !await exists(sharedDist)) {
26
+ console.error('[vendor-core] ERROR: 未找到 sharedmodule/llmswitch-core/dist (BUILD_MODE=dev)');
21
27
  console.error('[vendor-core] 请先进入 sharedmodule/llmswitch-core 并运行 `npm run build`。');
22
28
  process.exit(2);
23
29
  }
@@ -31,7 +37,11 @@ async function main() {
31
37
  console.log('[vendor-core] removed legacy vendor/@jsonstudio/llms directory');
32
38
  }
33
39
 
34
- console.log('[vendor-core] sharedmodule/llmswitch-core/dist 将被直接引用,已停止生成 vendor 副本。');
40
+ if (mode === 'dev') {
41
+ console.log('[vendor-core] sharedmodule/llmswitch-core/dist 将被直接引用,已停止生成 vendor 副本。');
42
+ } else {
43
+ console.log('[vendor-core] BUILD_MODE=release: using npm-installed @jsonstudio/llms (no vendor copy).');
44
+ }
35
45
  }
36
46
 
37
47
  main().catch((err) => {