@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
@@ -0,0 +1,125 @@
1
+ # Virtual Router: Priority + Health-Weighted Selection
2
+
3
+ This document describes how RouteCodex/llmswitch-core selects a `providerKey` from a route pool, with emphasis on:
4
+
5
+ - `mode: "priority"` pools (strict priority, failover only when needed)
6
+ - `mode: "round-robin"` pools (health-weighted AWRR)
7
+ - How quota/health signals affect selection order and weights
8
+
9
+ ## Terms
10
+
11
+ - **providerKey**: `providerId.<keyAlias>.<modelId>` (example: `antigravity.gbplasu1.claude-sonnet-4-5-thinking`)
12
+ - **pool**: A `RoutePoolTier` (`routing.<routeName>[]`), containing `targets` and a `mode`
13
+ - **quotaView**: Host-injected view (`ProviderQuotaView`) that provides:
14
+ - `inPool`, `cooldownUntil`, `blacklistUntil`
15
+ - `priorityTier` (static)
16
+ - `selectionPenalty`, `lastErrorAtMs`, `consecutiveErrorCount` (soft health signals)
17
+
18
+ ## Priority Pools (`mode: "priority"`)
19
+
20
+ Goal: always use the highest-priority candidate first, and only fall back when the current best becomes unavailable.
21
+
22
+ ### Base priority (config order)
23
+
24
+ When targets do not carry explicit per-target priority metadata at runtime, the router derives a deterministic base score from the target list ordering:
25
+
26
+ - Treat each contiguous `(providerId, modelId)` block in `tier.targets` as a **target group**
27
+ - This matches how `bootstrapVirtualRouterConfig()` expands a single routing entry into multiple auth aliases
28
+ - Group base scores: `100, 90, 80, ...` (step `10`) by appearance order
29
+ - Inside a group (different aliases for the same provider+model), alias scores: `100, 99, 98, ...` (step `1`)
30
+
31
+ This makes it difficult for a single transient failure to instantly flip priority to the next target, while still allowing repeated errors to degrade a key.
32
+
33
+ ### Error priority penalty (soft)
34
+
35
+ If `quotaView` provides `selectionPenalty` for a key, priority selection subtracts it from the derived base score:
36
+
37
+ ```
38
+ effectivePriority = basePriority - selectionPenalty
39
+ ```
40
+
41
+ `selectionPenalty` is produced by the host quota daemon:
42
+
43
+ - `selectionPenalty = consecutiveErrorCount` when the last error is within `ROUTECODEX_QUOTA_ERROR_PRIORITY_WINDOW_MS` (default `10min`)
44
+ - Resets to `0` on a successful response
45
+
46
+ This is a *soft* preference signal (it does not exclude the key); exclusion is controlled by `inPool/cooldownUntil/blacklistUntil`.
47
+
48
+ ### What “exhausted” means
49
+
50
+ In priority mode, a higher-priority key is considered exhausted only when it is **not selectable** due to:
51
+
52
+ - health manager unavailable (tripped/cooldown)
53
+ - quotaView exclusion (`inPool=false` / active `cooldownUntil` / active `blacklistUntil`)
54
+ - routing instructions / user exclusions
55
+
56
+ Only then will routing advance to the next candidate in priority order.
57
+
58
+ ## Round-Robin Pools (`mode: "round-robin"`) — Health-Weighted AWRR
59
+
60
+ Goal: evenly distribute traffic across healthy keys, while reducing the hit rate of recently failing keys (without starving them).
61
+
62
+ Implementation: deterministic smooth weighted round-robin (no randomness).
63
+
64
+ ### Health-weighted weights (AWRR)
65
+
66
+ If enabled (`loadBalancing.healthWeighted.enabled=true`) and `quotaView` provides error metadata, the router computes:
67
+
68
+ - `weight = baseWeight * multiplier`
69
+ - `multiplier` decreases with `consecutiveErrorCount`
70
+ - `multiplier` recovers over time using exponential decay (half-life)
71
+ - `multiplier` is floored by `minMultiplier` (prevents starvation)
72
+
73
+ Defaults live in:
74
+
75
+ - `sharedmodule/llmswitch-core/src/router/virtual-router/health-weighted.ts`
76
+
77
+ Key knobs (configurable under `loadBalancing.healthWeighted`):
78
+
79
+ - `baseWeight` (default `100`)
80
+ - `minMultiplier` (default `0.5`)
81
+ - `beta` (default `0.1`) — one error reduces weight by ~10%
82
+ - `halfLifeMs` (default `10min`)
83
+ - `recoverToBestOnRetry` — on router retries, prefer the healthiest key first
84
+
85
+ ## Model-capacity 429 handling (host quota)
86
+
87
+ Some upstreams report `HTTP 429` with capacity semantics (e.g. “No capacity available for model …”).
88
+ This is not “quota depleted” locally; switching keys often does not help.
89
+
90
+ RouteCodex treats this as a *model-series* cooldown:
91
+
92
+ - On capacity-exhausted 429, host applies an immediate cooldown to the entire `${providerId}.${modelId}` series
93
+ - Default cooldown: `60s`
94
+
95
+ Implementation:
96
+
97
+ - `src/manager/modules/quota/provider-quota-daemon.model-backoff.ts`
98
+
99
+ ## Context-weighted selection (preserve large windows)
100
+
101
+ Some clients have a fixed maximum usable context (e.g. `200k`). When multiple candidates are all "safe" for the current
102
+ request, we want to bias traffic toward smaller effective safe windows early, so that larger windows remain available
103
+ later when context grows.
104
+
105
+ This is implemented as an additional multiplier on top of existing weights (health-weighted / legacy), and is only
106
+ applied inside the same pool bucket and only for candidates in `ContextAdvisor.safe`.
107
+
108
+ Config (under `virtualrouter.loadBalancing.contextWeighted`):
109
+
110
+ - `enabled` (default `false`)
111
+ - `clientCapTokens` (default `200000`)
112
+ - `gamma` (default `1`, proportional compensation)
113
+ - `maxMultiplier` (default `2`)
114
+
115
+ Effective safe window (`T_safeEff`) used for compensation:
116
+
117
+ - `T_eff = min(modelMaxTokens, clientCapTokens)`
118
+ - `reserve = ceil(T_eff * (1 - warnRatio))` (warnRatio comes from `virtualrouter.contextRouting.warnRatio`, default `0.9`)
119
+ - `slack = max(0, modelMaxTokens - clientCapTokens)`
120
+ - `reserveEff = max(0, reserve - slack)` (models with slack can "absorb" the reserve)
121
+ - `T_safeEff = T_eff - reserveEff`
122
+
123
+ Then, within the bucket:
124
+
125
+ - `multiplier = min(maxMultiplier, (max(T_safeEff) / T_safeEff) ^ gamma)`
@@ -0,0 +1,50 @@
1
+ ### Anthropic Golden Request Samples
2
+
3
+ 我们把真实 `/v1/messages` 请求快照统一保存在 `~/.routecodex/golden_samples/anthropic_requests/`,每个目录
4
+ 包含:
5
+
6
+ ```
7
+ <slug>/
8
+ request_payload.json # 直接发送给 Anthropics API 的 json
9
+ meta.json # 来源阶段、采样说明、endpoint 等元数据
10
+ ```
11
+
12
+ > **提示**:仓库内 `samples/chat-blackbox/anthropic/request-basic.json` 为上述样本的版本化拷贝,可在代码评审时直接 diff。
13
+ > 建议先用真实 provider 生成阶段快照,并把 `body` + `stageFile` 写入
14
+ > `~/.routecodex/golden_samples/new/anthropic-messages/<providerId>/`。随后执行
15
+ > `node scripts/tools/capture-provider-goldens.mjs --update-golden`,脚本会读取这些快照并同步
16
+ > `provider_golden_samples/`,检测到字段差异时会提示是否覆盖。
17
+
18
+ 当前样本:
19
+
20
+ | slug | 描述 | Source Stage |
21
+ |------|------|--------------|
22
+ | `glm46-toolcall-20251209T223550158-010` | 用户让助手列出仓库目录,prompt 中包含 Codex/CLAUDE 大段 system 规则,`stream=true`,用于验证工具治理路径 | `anthropic-messages/req_1765290950164_req_inbound_stage1_format_parse.json` |
23
+ | `glm46-toolcall-20251209T223550463-011` | 用户只说“列出本地文件”,模型应拒绝直接读取本地盘,适合验证拒绝/告警逻辑 | `anthropic-messages/req_1765290950463_req_inbound_stage1_format_parse.json` |
24
+
25
+ #### 如何回放
26
+
27
+ 1. 启动 RouteCodex,确保目标 provider(例如 `glm.key1.glm-4.6`)可用。
28
+ 2. 直接将样本作为请求体发送:
29
+
30
+ ```bash
31
+ curl -s http://127.0.0.1:5555/v1/messages \
32
+ -H 'Content-Type: application/json' \
33
+ -H 'Authorization: Bearer test' \
34
+ --data @~/.routecodex/golden_samples/anthropic_requests/glm46-toolcall-20251209T223550158-010/request_payload.json
35
+ ```
36
+
37
+ 3. 如果需要切换 provider,只需修改 JSON 中的 `model` 字段或配合用户配置热更(无需 CLI 抓样本)。
38
+
39
+ #### 验证快照
40
+
41
+ - 设置 `ROUTECODEX_HUB_SNAPSHOTS=1` 后回放,`~/.routecodex/codex-samples/anthropic-messages/` 将刷新对应的
42
+ `req_*` 与 `resp_*` 阶段文件,可直接 diff。
43
+ - `anthropic/glm46-toolcall-…` 目录内已有响应黄金样本,可与请求目录交叉比对,确认入站/出站一致性。
44
+
45
+ #### 扩展样本
46
+
47
+ 1. 捕获目标请求期间的 `req_*_req_inbound_stage1_format_parse.json`
48
+ 2. 在 `anthropic_requests/` 下创建新子目录,复制 `body.payload` 为 `request_payload.json`
49
+ 3. 写入 `meta.json` 说明模型、来源阶段、场景描述
50
+ 4. 更新本文档表格即可
@@ -0,0 +1,105 @@
1
+ # CCR enhancetool 行为与对齐方案(形状/语法修复,非语义重写)
2
+
3
+ 本文档总结了 claude-code-router(下称 CCR)中内置 transformer “enhancetool”的关键行为,并给出在 llmswitch-core 中实现等价对齐的方案。对齐范围严格限定为“整体形状/语法/JSON(JSON5) 层”,不解析或重写具体命令语义(如 grep 正则、管道策略等)。
4
+
5
+ ## 1. CCR enhancetool 行为摘要
6
+
7
+ - 非流 JSON(application/json)
8
+ - 对 `choices[0].message.tool_calls[].function.arguments` 执行三段式容错修复:
9
+ 1) 尝试 `JSON.parse` 成功 → 使用原字符串。
10
+ 2) 失败则 `JSON5.parse` 成功 → `JSON.stringify` 输出合法 JSON 字符串。
11
+ 3) 再失败则进行“安全修复”(典型策略:去除围栏标记、去掉尾随逗号、单引号转双引号、补齐引号/括号等),成功后 `JSON.stringify`。
12
+ 4) 全部失败 → 回退为字符串 "{}"(空对象)。
13
+ - 若存在 `tool_calls`:标准化 `content=null`;无 `finish_reason` 时补齐为 `tool_calls`。
14
+
15
+ - 流式(text/event-stream)
16
+ - 吞掉“工具参数增量”片段,不向下游透出 arguments 的碎片增量。
17
+ - 聚合策略:
18
+ - 记录工具调用开始(OpenAI Chat: `delta.tool_calls`;Anthropic Messages: `content_block_start` 等),保存 `index/name/id`。
19
+ - 聚合 `partial_json` / `function.arguments` 的增量数据到缓冲;不在增量阶段向下游发送 arguments 内容。
20
+ - 在工具完成时(OpenAI: `finish_reason=tool_calls`;Anthropic: `content_block_stop`)一次性下发:
21
+ - 将聚合后的 arguments 走上述“三段式容错修复”,最终保证为“单个 JSON 字符串”。
22
+ - 构造新的 delta(含完整 `name` 与 `arguments`),并删除任何同时出现的 `delta.content`。
23
+ - 思考文本(reasoning)在 CCR 中被专门转为 `thinking` 域;本轮对齐聚焦工具通路,不改变我们已存在的 reasoning 处理策略。
24
+
25
+ - 不做的事
26
+ - 不解析或重写具体命令语义(不拆分正则、多 -e 重写、命令管道改写等)。
27
+ - 不注入系统提示词;仅允许在 tools schema 描述中加入“形状/用法提示”(非 system)。
28
+
29
+ ## 2. 我们的对齐原则(三端一致)
30
+
31
+ 1) 形状优先:仅保障 `function.arguments` 在所有输出路径上都是“单个 JSON 字符串”,并保持 `content=null`、`finish_reason=tool_calls` 等不变式。
32
+ 2) 三端统一:Chat(OpenAI)、Responses(OpenAI)、Messages(Anthropic)在非流与流式两条通路都执行一致策略。
33
+ 3) 不解析命令语义:不对 grep/正则/管道等进行语义重写,避免引入不可预测副作用。
34
+
35
+ ## 3. 对齐实施方案
36
+
37
+ ### 3.1 非流(一次性 JSON)
38
+
39
+ - 入口:`llmswitch-core v2` 的响应治理(response 相位)。
40
+ - 动作:
41
+ - 若 `function.arguments` 是对象 → 仅 `JSON.stringify`(保持语义原样)。
42
+ - 若是字符串 → 走 `repairArguments`(JSON→JSON5→安全修复→失败回退 "{}")。
43
+ - 补齐 `finish_reason=tool_calls`(若缺),以及 `content=null`(当存在 `tool_calls`)。
44
+
45
+ ### 3.2 流式(SSE 聚合)
46
+
47
+ - Chat(OpenAI /v1/chat/completions):新增“Chat SSE 工具参数聚合器”。
48
+ - 吞掉增量 arguments,不向下游透出;工具完成时合并缓冲并 `repairArguments`,一次性发送完整字符串。
49
+
50
+ - Messages(Anthropic /v1/messages):新增“Messages SSE 工具参数聚合器”。
51
+ - 聚合 `input_json_delta.partial_json`;`content_block_stop` 时进行 `repairArguments` 并一次性下发。
52
+
53
+ - Responses(OpenAI /v1/responses):改造现有 `ResponsesSSETransformer` 为同策略。
54
+ - 工具参数不再逐片外发,仅在工具结束时一次性输出完整字符串。
55
+
56
+ ### 3.3 repairArguments(对齐 CCR,形状/语法修复)
57
+
58
+ - 实现在 `shared/v2/conversion/shared/jsonish.ts`:
59
+ - `repairArguments(arg: unknown): string`:输入任意字符串/对象,输出“单个 JSON 字符串”。
60
+ - 顺序:`JSON.parse` → `JSON5.parse` → 安全修复(去围栏/尾逗号/单引号等)→ 失败返回 "{}"。
61
+ - 不触碰命令语义(值中的命令原封不动)。
62
+
63
+ ### 3.4 tools schema 描述增强(非 system 提示)
64
+
65
+ - 在 `augmentOpenAITools` 的 `shell` 描述中追加“稳健用法提示”(仅描述层):
66
+ - 长 OR 模式建议使用多个 `-e` 或 `-f`(从 stdin 读模式列表)。
67
+ - 可优先使用 `rg`(ripgrep)以减少引号/括号陷阱。
68
+ - 避免将解释性文字混入 `arguments`;说明性文字放在普通对话文本中。
69
+
70
+ ## 4. 开关与默认
71
+
72
+ - `RCC_TOOL_ENHANCE=1`(默认开):启用 `repairArguments` 三段式修复(失败回退 "{}")。
73
+ - `RCC_SSE_TOOL_AGGREGATE=1`(默认开):吞掉参数增量,完结一次性下发完整 arguments。
74
+
75
+ ## 5. 快照与验收
76
+
77
+ - 预期在 `*_provider-request.json`:
78
+ - `assistant.tool_calls[].function.arguments` 均为合法 JSON 字符串;
79
+ - 当有 `tool_calls` 时,`content=null`,`finish_reason='tool_calls'`;
80
+ - 无 arguments 增量碎片。
81
+
82
+ - SSE:不再透出 arguments 增量;仅在工具完成时出现一次完整 arguments。
83
+
84
+ - 失败回退:当 JSON/JSON5/修复全部失败时,arguments 应为 "{}"。
85
+
86
+ ## 6. 边界与不做项
87
+
88
+ - 不解析或重写具体命令语义(例如:不拆分大正则为多 `-e`,不重排管道)。
89
+ - 不在服务器端点或兼容层重复实现工具转换/聚合;统一入口仅在 `llmswitch-core`。
90
+
91
+ ## 7. 实施清单(按顺序)
92
+
93
+ 1) 文档到位(本文件 + AGENTS.md 对齐段落)。
94
+ 2) 新增 `repairArguments`(JSON→JSON5→安全修复→"{}")。
95
+ 3) 改造响应相位(非流)调用 `repairArguments` 并保证 finish_reason/content 不变式。
96
+ 4) 新增 Chat/Anthropic 两个 SSE 聚合器;改造 Responses SSE 统一策略。
97
+ 5) 更新 tools schema 描述(仅描述增强)。
98
+ 6) 严格按“先编译共享模块、再构建根包并全局安装”的顺序验证。
99
+
100
+ ---
101
+
102
+ 附:CCR 代码阅读锚点(仅供对照,不在代码注释中引用)
103
+ - (更新)移除 `@musistudio/llms` 依赖描述;增强工具路径由 llmswitch-core 统一实现(透明代理 + 二轮请求)。
104
+ - 流式路径中 `content_block_start/stop` 与 `partial_json` 聚合逻辑;
105
+ - 非流路径中 arguments 三段式修复与回退策略。
@@ -0,0 +1,79 @@
1
+ # Chat GLM 500 调查与处置记录(精准定位)
2
+
3
+ ## 背景
4
+ - 现象:Chat 通路上游 GLM 返回 500(Operation failed)。
5
+ - 最新失败样本目录:`~/.routecodex/codex-samples/openai-chat`
6
+ - 例:`req_1761955101841_2d71u9w6x_provider-request.json`
7
+
8
+ ## 症状与证据
9
+ - 请求载荷体积异常:多轮 `role:"tool"` 消息携带巨大 JSON/文本结果;两条超长 system 提示叠加。
10
+ - codec/compat 阶段的快照显示:`assistant.tool_calls` 的 `content` 已规范为 `null`;但 `provider-request.json` 依然包含大量工具结果文本(历史轮未最小化)。
11
+ - SSE 侧报错:`Error: GLM API error: 500 Internal Server Error - Operation failed`。
12
+
13
+ ## 根因(Root Cause)
14
+ - 历史工具结果在多轮会话中持续累积为长文本,叠加双 system 文本,导致上游 GLM 对载荷体量/结构敏感触发 500。
15
+ - 并非“工具引导未生效”。工具引导与工具增强均在 llmswitch-core 正常注入(`[Codex Tool Guidance v1]` + 严格 schema)。
16
+
17
+ ## CCR(Claude Code Router)的相关做法(预算来源)
18
+ - CCR 以“总上下文预算(token count)”为核心,计算消息 + system + tools 的 token 数,并基于阈值选用长上下文模型:
19
+ - 位置:`../../claude-code-router/src/utils/router.ts`
20
+ - 关键点:
21
+ - 使用 `tiktoken` 计算 token(消息文本、tool_use/input、tool_result/content、system 文本、工具 schema 都计入)。
22
+ - 与配置阈值比较(`virtualrouter.classifier.longContextThresholdTokens`,默认 180,000 tokens)。
23
+ - 超阈值或结合上一轮 usage 过大则切换到 `config.Router.longContext` 模型。
24
+ - CCR 并不把大段工具结果回灌到 assistant 文本;工作流结束时通过 ExitTool 返回最终文本,移除 `tool_calls`。
25
+
26
+ ## 我们的对齐策略(直击根因)
27
+ - 唯一入口:仅在 `sharedmodule/llmswitch-core` 做统一处理;Provider/兼容层不做逻辑修改。
28
+ - 两类措施:
29
+ 1) 工具结果“主动最小化 + 分层预算”
30
+ - 所有 `role:'tool'` 消息统一“文本化+裁剪”。
31
+ - rcc.tool.v1 成功 → 提取 stdout/简明输出;失败 → `执行失败:前三行`;无输出 → `执行成功(无输出)`。
32
+ - 为避免累计膨胀,引入分层预算:
33
+ - 总载荷预算(token/字节,按 CCR 思路来自配置/环境)。
34
+ - 每条工具消息预算(HEAD/TAIL、类型化提要),最近 N 条额度更大,其余更严格。
35
+ - 保留结构与 `tool_call_id`,不改角色、不清历史(记忆靠历史)。
36
+ 2) 去噪
37
+ - 删除“无 `tool_calls` 且内容为空/仅空白”的 `assistant` 回合,减少空 turn.
38
+
39
+ ## 已落地(当前版本)
40
+ - 实施位置:`sharedmodule/llmswitch-core/src/conversion/shared/openai-message-normalize.ts`
41
+ - 统一对所有 `role:'tool'` 消息做“文本化+截断”,并在文本前加截断提示(例如:`[输出已截断至 2048 字符]`)。
42
+ - 默认阈值:`RCC_TOOL_TEXT_LIMIT`(默认 2048,可调)。
43
+ - `assistant` 含 `tool_calls` 时,将空字符串 `content` 规范为 `null`(保留混合内容)。
44
+ - 删除空文本 `assistant`(无工具调用)。
45
+
46
+ ## curl 复现与验证
47
+ 1. 启动本地服务(示例端口 5520)
48
+ ```bash
49
+ rcc start # 或 routecodex start
50
+ ```
51
+ 2. 使用失败样本 `*_raw-request.json` 复现
52
+ ```bash
53
+ jq -r '.body' ~/.routecodex/codex-samples/openai-chat/<失败样本>_raw-request.json > /tmp/rc_req_body.json
54
+ curl -s -o /tmp/rc_resp.json -w "%{http_code}" \
55
+ -H 'Content-Type: application/json' \
56
+ --data @/tmp/rc_req_body.json \
57
+ http://127.0.0.1:5520/v1/chat/completions
58
+ ```
59
+ 3. 成功标准
60
+ - `provider-request.json` 中:
61
+ - `role:'tool'` 文本出现截断提示;历史轮不再巨量。
62
+ - 不再出现空的 `assistant` turn。
63
+ - SSE/JSON 不再出现上游 500。
64
+
65
+ ## 后续工作(对齐 CCR 的“预算来源”)
66
+ - 预算来源与策略:
67
+ - 总上下文预算:
68
+ - 从配置载入(建议:`virtualrouter.classifier.longContextThresholdTokens`,或在用户配置中覆盖)。
69
+ - 用 `tiktoken` 计算请求 token 数,参照 CCR 的 `router.ts` 逻辑。
70
+ - 分层预算落到工具结果:
71
+ - 最近 N 条工具消息额度更大,其余更严格(HEAD/TAIL/摘要)。
72
+ - 类型化提要(stderr/失败仅前几行,stdout/JSON 取关键信息)。
73
+ - 超预算策略:
74
+ - 优先压缩工具结果文本,不修改历史结构与角色;必要时切换长上下文模型(CCR 同源策略)。
75
+
76
+ ## 结论
77
+ - 500 原因是“累积工具结果文本 + 超长 system 导致载荷过大”,而非“工具引导缺失”。
78
+ - 处置方案定位在唯一入口(llmswitch-core),以“主动最小化 + 预算控制”预防问题发生。
79
+ - 下一步将把“分层预算 + 类型化提要 + 全局上下文预算(CCR 同源)”落地为可配置策略,并继续用 curl 真样本回放验证。
@@ -0,0 +1,42 @@
1
+ ### OpenAI Chat Golden Request Samples
2
+
3
+ 存放位置:`~/.routecodex/golden_samples/openai_requests/<slug>/`
4
+
5
+ > **提示**:
6
+ > - 自 0.87.21 起,chat 入口的 provider 专属样本统一存放在
7
+ > `~/.routecodex/golden_samples/new/<entryType>/<providerId>/`(例如 `new/openai-chat/glm`)。
8
+ > 目录内包含 `request.sample.json`(直接从阶段快照复制的 `body`)以及 `meta.json`
9
+ > (指向原始 `*_stage2_format_build.json` 路径)。`scripts/tools/capture-provider-goldens.mjs`
10
+ > 会优先读取这些“真实快照”,无需再回放 `samples/chat-blackbox/**/request-basic.json`。
11
+ > - 仍需保留仓库内 `samples/chat-blackbox/*/request-basic.json`,用于快速审查/比较;当新增场景时,
12
+ > 先运行真实请求生成阶段快照,再在 `new/<entryType>/<providerId>/` 放置 `request.sample` 与 `meta`,
13
+ > 最后执行 `node scripts/tools/capture-provider-goldens.mjs --update-golden`,脚本会把同一份请求复制到
14
+ > `provider_golden_samples/`,供 mock/provider 单元测试使用。
15
+
16
+ ```
17
+ <slug>/
18
+ request_payload.json # 直接发送到 /v1/chat/completions 的 JSON
19
+ meta.json # 包含来源阶段、endpoint、描述等元数据
20
+ ```
21
+
22
+ | slug | 描述 | Source Stage |
23
+ |------|------|--------------|
24
+ | `chat-toolcall-20251209T225016004-002` | Codex CLI 会话(用户 repeatedly “列出本地文件”,`stream=true`,含完整 system/环境上下文与工具 schema),用于验证 chat 入口 → glm.provider 的骨架路径 | `openai-chat/req_1765291814052_req_inbound_stage1_format_parse.json` |
25
+
26
+ #### 回放方式
27
+
28
+ ```bash
29
+ curl -s http://127.0.0.1:5555/v1/chat/completions \
30
+ -H 'Content-Type: application/json' \
31
+ -H 'Authorization: Bearer test' \
32
+ --data @~/.routecodex/golden_samples/openai_requests/chat-toolcall-20251209T225016004-002/request_payload.json
33
+ ```
34
+
35
+ 该样本会沿 V2 骨架走 chat 入口 → hub → glm provider,可直接用来对比 legacy/chat-provider 行为。
36
+
37
+ #### 如何扩展
38
+
39
+ 1. 在 `~/.routecodex/golden_samples/openai-chat/req_*_req_inbound_stage1_format_parse.json` 中找到需要的请求负载。
40
+ 2. 将 `body.payload` 拷贝为新的 `request_payload.json`;注明 slug、描述后写入 `meta.json`。
41
+ 3. 更新本文件表格,描述该样本的用途、对应阶段文件。若需要刷新所有 provider 的黄金请求,可运行
42
+ `node scripts/tools/capture-provider-goldens.mjs --update-golden`,脚本将自动覆盖 `provider_golden_samples/` 下对应入口的请求副本。
@@ -0,0 +1,82 @@
1
+ ## Chat 语义扩展与接线计划
2
+
3
+ > 目标:让 llmswitch-core 中的 Chat Process / Standardized 桥承接四种协议的语义,不再依赖 metadata 透传 “raw payload”,并按顺序分阶段完成。
4
+
5
+ ### 阶段 0:现状确认
6
+
7
+ 1. **协议扫描**
8
+ - `chat-mapper.ts`:系统提示、工具空数组、未知字段依赖 `metadata.systemInstructions/extraFields/toolsFieldPresent`。
9
+ - `responses-mapper.ts`:resume/include/store 等通过 `metadata.responsesContext/responseFormat` 储存。
10
+ - `anthropic-mapper.ts`:system blocks、tool alias、内容 shape 等塞进 `metadata.extraFields`。
11
+ - `gemini-mapper.ts`:systemInstruction、safetySettings、generationConfig、toolConfig 均在 metadata/parameters。
12
+ 2. **chat-process / standardized 桥**
13
+ - 只理解 `messages/tools/toolOutputs/parameters`,其余通通进 `metadata.capturedContext`。
14
+
15
+ ### 阶段 1:扩展 Chat Process + Standardized 桥
16
+
17
+ 1. **类型扩展**
18
+ - 在 `ChatEnvelope`、`StandardizedRequest` 新增 `semantics`,并明确区分:
19
+ - **通用横向字段**:如 `semantics.session.previousResponseId`、`semantics.system.textBlocks`,用于跨协议共享。
20
+ - **协议专属命名空间**:`semantics.responses` / `semantics.anthropic` / `semantics.gemini`。每个命名空间内定义稳定 contract,禁止随意往里塞 provider extras。
21
+ - **providerExtras** 仅用于临时透传,默认禁止业务逻辑读取,后续接线完成后应趋近于空。
22
+ - `chatEnvelopeToStandardized` / `standardizedToChatEnvelope` 深拷贝 `semantics`。
23
+ 2. **chat-process 适配**
24
+ - `runHubChatProcess`、工具治理、路由决策只读 `request.semantics`;除 mapper/bridge 外,任何模块不得写入 `semantics`。
25
+ - Metadata 退回诊断角色:仅保留 `missingFields/providerMetadata` 等调试字段,`capturedContext` 禁止再夹带业务语义。
26
+ 3. **模块测试**
27
+ - 新增 spec:构造 `ChatEnvelope` (含 system/responses/anthropic/gemini),执行标准化→还原→chat-process,断言 `semantics` 原样保留。
28
+
29
+ > 完成该阶段后,chat-process 成为“语义承接层”,为后续接线提供可靠落点。
30
+
31
+ ### 阶段 2:协议语义接线(分批)
32
+
33
+ 1. **OpenAI Chat**
34
+ - 将 `metadata.systemInstructions`/`extraFields`/`toolsFieldPresent` 迁移到 `semantics.system` / `semantics.tools`,只允许在 `semantics.providerExtras` 做临时镜像。
35
+ - 迁移期间保持“语义双写”:写入 semantics 后,兼容代码仍可读旧 metadata,但新逻辑必须只读 semantics。
36
+ - 更新现有 chat mapper 测试,确认 round-trip 不丢数据。
37
+ 2. **Responses**
38
+ - `captureResponsesContext` 输出的 include/store/responseFormat/resume 等写入 `semantics.responses`,必要时临时镜像到旧 metadata。
39
+ - SubmitToolOutputs、resume、responses-roundtrip 仅依赖 `semantics.responses`;现有逻辑若仍读 metadata,需先迁移。
40
+ - 针对 responses 的 mock sample 回放,验证 `semantics.responses` 中包含 `previousResponseId`、`resumeToolOutputs` 等。
41
+ 3. **Anthropic**
42
+ - system blocks、alias map、passthrough metadata、anthropicMirror -> `semantics.anthropic`。
43
+ - outbound mapper 从 `semantics` 还原 payload,metadata.extraFields 仅做兼容写;新读路径统一指向 semantics。
44
+ - 更新 `tests/sharedmodule/gemini/anthropic` 相关断言。
45
+ 4. **Gemini**
46
+ - systemInstruction、safetySettings、toolConfig、generationConfig、`__rcc_stream` → `semantics.gemini`,仅在兼容期间写 metadata 镜像。
47
+ - generationConfig / toolConfig 通过 `semantics` 显式传递,metadata 不得再承载业务语义。
48
+ - 确认 `buildGeminiRequestFromChat` 仅依赖 `chat.semantics.gemini`。
49
+
50
+ 每完成一个协议接线:
51
+ - 编写/更新对应 spec。
52
+ - 运行协议相关现有测试(tool-loop、responses-submit、anthropic roundtrip、gemini mapper)。
53
+ - 确认黑盒模块测试(阶段 1)依然通过。
54
+
55
+ ### 阶段 3:清理与回归
56
+
57
+ 1. **移除遗留 metadata 键**
58
+ - 删除 `metadata.systemInstructions/extraFields.responsesContext` 等已迁移字段,保留 `missingFields/providerMetadata`。
59
+ - 更新文档与类型约束。
60
+ 2. **回归测试矩阵**
61
+ - `npm run test:sharedmodule`
62
+ - `npm run verify:e2e-toolcall`(覆盖 responses tool loop)
63
+ - `scripts/tests/apply-patch-loop.mjs` / `responses-submit` 样本回放
64
+ - Anthropic / Gemini 专属 dry-run(若有)。
65
+ 3. **文档更新**
66
+ - `docs/responses-...`, `docs/pipeline/...` 添加新语义字段说明。
67
+ - 记录“metadata 仅用于诊断,业务语义全部进入 `semantics`”的新约束。
68
+
69
+ ### 注意事项
70
+
71
+ - **严格顺序**:阶段 1 完成并通过黑盒测试后,才能启动阶段 2 的任何接线工作。
72
+ - **只读语义**:除 Semantic Mapper / Bridge 外,任何模块不得写 `semantics`; chat-process 之后的所有节点禁止从 metadata/raw 读取业务语义。
73
+ - **最小增量**:每个协议接线尽量独立 PR/commit,便于回滚。
74
+ - **兼容期双写**:阶段 2 中需维护 semantics & metadata 双写(写 semantics → 同步旧字段);读路径优先 semantics,metadata 仅保底兼容,直到阶段 3 清理完成。
75
+ - **验证方式**:所有语义字段必须能在 `StandardizedRequest.semantics` 中观测到,且 chat-process/路由/工具治理仅依赖该结构。
76
+
77
+ ### 审查建议
78
+
79
+ - **横纵拆分**:在 `semantics` 结构中明确跨协议共享字段(例如 `semantics.session.previousResponseId`、`semantics.system.textBlocks`),避免每个协议重复定义同义字段;协议专属字段需在命名空间内列出 contract,并写测试覆盖。
80
+ - **提交策略**:阶段 2~3 的每个协议迁移都需更新 spec + 运行现有样本(responses submit、anthropic/gemini roundtrip 等),并用黑盒模块测试确认 semantics 不丢失。
81
+ - **metadata 清理**:阶段 3 清理前做 StandardizedRequest/ChatEnvelope 快照测试,确保 metadata 只剩诊断信息;用 codex samples 回放检查 semantics 是否完整覆盖我们关心的语义。
82
+ - **与“禁止 raw 打洞”对齐**:任何绕开 semantics、试图回读 raw/metatada 的逻辑都应视为架构违规;新文档明确强调这一点,保持与工具链路治理的统一思路。
@@ -0,0 +1,76 @@
1
+ # CLI Command Inventory & Contracts
2
+
3
+ Source of truth: `src/cli.ts` (wiring) + command implementations in `src/cli/commands/*` and `src/commands/*`.
4
+
5
+ ## Inventory (from `src/cli.ts`)
6
+
7
+ | Command | Where registered | Implementation | Side effects (non-exhaustive) | Exit behavior |
8
+ |---|---|---|---|---|
9
+ | `env` | `src/cli/register/basic-commands.ts` | `src/cli/commands/env.ts` | Reads config file (optional) | `ctx.exit(1)` on parse/config errors; otherwise returns |
10
+ | `clean` | `src/cli/register/basic-commands.ts` | `src/cli/commands/clean.ts` | Deletes captures/logs via `fs.rmSync(recursive)` | Returns on success; on failure uses spinner/logger (no direct `ctx.exit` in this file) |
11
+ | `examples` | `src/cli/register/basic-commands.ts` | `src/cli/commands/examples.ts` | Prints examples | Returns |
12
+ | `port` | `src/cli/register/basic-commands.ts` | `src/cli/commands/port.ts` | Reads port listeners; may kill PIDs (`--kill`) | `ctx.exit(2)` on invalid port; `ctx.exit(1)` on failures |
13
+ | `config` | `src/cli/register/status-config-commands.ts` | `src/cli/commands/config.ts` | Writes config file; reads existing config | Returns (no direct `ctx.exit` in this file) |
14
+ | `status` | `src/cli/register/status-config-commands.ts` | `src/cli/commands/status.ts` | Network `fetch` to server status endpoint | Returns (no direct `ctx.exit` in this file) |
15
+ | `start` | `src/cli/register/start-command.ts` | `src/cli/commands/start.ts` | Reads config; may write temp config + pid file; may `fetch` shutdown; may kill PIDs; spawns server (`node dist/index.js`) | Uses `ctx.exit(...)` for success/error paths |
16
+ | `stop` | `src/cli/register/stop-command.ts` | `src/cli/commands/stop.ts` | Reads config (release); kill PIDs; optional token-daemon stop | `ctx.exit(1)` on config/stop failures; otherwise returns |
17
+ | `restart` | `src/cli/register/restart-command.ts` | `src/cli/commands/restart.ts` | Reads config; kill PIDs; may `fetch` shutdown; spawns server; writes pid file | Uses `ctx.exit(...)` for success/error paths |
18
+ | `code` | `src/cli/register/code-command.ts` | `src/cli/commands/code.ts` | Reads config for `apikey`; may `fetch /ready`; may spawn server; spawns `claude` | Uses `ctx.exit(...)` for success/error paths |
19
+ | `provider-update` *(optional)* | `src/cli.ts` dynamic import | `src/commands/provider-update.ts` | Reads/writes provider config and lists; may call RouteCodex HTTP endpoint for probing | Uses `process.exit(1)` in multiple branches |
20
+ | `camoufox-fp` *(optional)* | `src/cli.ts` dynamic import | `src/commands/camoufox-fp.ts` | Reads fingerprint JSON on disk | Sets `process.exitCode` on errors |
21
+ | `camoufox-backfill` *(optional)* | `src/cli.ts` dynamic import | `src/commands/camoufox-backfill.ts` | Backfills fingerprints (disk IO) | Uses `process.exitCode` on errors (by pattern) |
22
+ | `token-daemon` *(optional)* | `src/cli.ts` dynamic import | `src/commands/token-daemon.ts` | Spawns background daemon; reads/writes snapshots | Uses `process.exit(...)` / `process.exitCode` in command handlers |
23
+ | `quota-status` *(optional)* | `src/cli.ts` dynamic import | `src/commands/quota-status.ts` | Reads quota snapshot file | Returns; throws on missing file |
24
+ | `quota-daemon` *(optional)* | `src/cli.ts` dynamic import | `src/commands/quota-daemon.ts` | Reads replay NDJSON; writes `provider-quota.json` unless `--dry-run` | Returns; on failure throws/sets exit |
25
+ | `oauth` *(optional)* | `src/cli.ts` dynamic import | `src/commands/oauth.ts` | Triggers OAuth flows (Camoufox/browser automation) | Returns; may set exit codes on failures (subcommands) |
26
+ | `validate` *(optional)* | `src/cli.ts` dynamic import | `src/commands/validate.ts` | `fetch` health + API; may spawn `rcc start`; reads payload file | Calls `process.exit(1)` on failures |
27
+
28
+ ## Contracts (inputs/outputs) — extracted from `.option(...)`
29
+
30
+ ### `env` (`src/cli/commands/env.ts`)
31
+ - Inputs: `--port`, `--host`, `--config`, `--json`; reads config file if present.
32
+ - Output: prints shell exports (default) or JSON (`--json`).
33
+ - Exit: `1` on invalid/missing config-derived port.
34
+
35
+ ### `clean` (`src/cli/commands/clean.ts`)
36
+ - Inputs: `--yes`, `--what <targets>` (default `all`).
37
+ - Output: spinner/log messages about deleted targets.
38
+ - Exit: no explicit `ctx.exit` in this file (errors are handled inside action).
39
+
40
+ ### `port` (`src/cli/commands/port.ts`)
41
+ - Inputs: `--port <port>` (default `5555`), `--kill`.
42
+ - Output: diagnostics; when `--kill`, attempts to kill listeners.
43
+ - Exit: `2` on invalid port; `1` on kill failure or unexpected errors.
44
+
45
+ ### `config` (`src/cli/commands/config.ts`)
46
+ - Inputs: `--config <config>`, `--template <template>`, `--force`.
47
+ - Output: writes/prints config info via logger/spinner.
48
+ - Exit: no explicit `ctx.exit` in this file.
49
+
50
+ ### `status` (`src/cli/commands/status.ts`)
51
+ - Inputs: `--json`.
52
+ - Output: human-readable status or JSON.
53
+ - Exit: no explicit `ctx.exit` in this file.
54
+
55
+ ### `start` (`src/cli/commands/start.ts`)
56
+ - Inputs: `--config`, `--port`, `--quota-routing on|off`, `--log-level`, `--codex/--claude`, `--ua`, `--snap/--snap-off`, `--verbose-errors/--quiet-errors`, `--restart`, `--exclusive`.
57
+ - Output: spinner/log lines; server process inherits stdio.
58
+ - Exit: `0` on normal termination; `1` on validation/start/shutdown errors.
59
+
60
+ ### `stop` (`src/cli/commands/stop.ts`)
61
+ - Inputs: none; release mode reads config file for port; dev mode uses default/env port.
62
+ - Output: spinner/log lines about stop result.
63
+ - Exit: `1` on configuration/stop errors.
64
+
65
+ ### `restart` (`src/cli/commands/restart.ts`)
66
+ - Inputs: `--config`, `--log-level`, `--codex/--claude`.
67
+ - Output: spinner/log lines; server process inherits stdio.
68
+ - Exit: `0` on normal termination; `1` on validation/restart errors.
69
+
70
+ ### `code` (`src/cli/commands/code.ts`)
71
+ - Inputs: `--port`, `--host` (default `0.0.0.0`), `--url`, `--config`, `--apikey`, `--claude-path`, `--cwd`, `--model`, `--profile`, `--ensure-server`.
72
+ - Output: launches Claude Code (subprocess inherits stdio).
73
+ - Exit: `0` when Claude exits cleanly; `1` on connection/start failures.
74
+
75
+ ### Optional command groups (`src/commands/*`)
76
+ These are wired via `program.addCommand(...)` and still use `process.exit(...)`/`process.exitCode` in places. They are not yet migrated into the `ctx.exit`/testable registration pattern.
@@ -0,0 +1,50 @@
1
+ # Codex Samples 回放
2
+
3
+ `scripts/replay-codex-sample.mjs` 允许我们将 `~/.routecodex/codex-samples/**/*_client-request.json` 等样本重新发送到本地 RouteCodex,确保工具调用、SSE chunk 和最终 JSON 都被完整记录。
4
+
5
+ ## 使用步骤
6
+
7
+ 1. 启动 RouteCodex 主包(默认 `http://127.0.0.1:5555`)。
8
+ 2. 准备好想要回放的样本文件,例如:
9
+ `~/.routecodex/codex-samples/openai-responses/req_req-v2-1764415000213-z1sxtbhuo_client-request.json`
10
+ 3. 执行:
11
+
12
+ ```bash
13
+ npm run replay:codex-sample -- \
14
+ --sample ~/.routecodex/codex-samples/openai-responses/req_req-v2-1764415000213-z1sxtbhuo_client-request.json \
15
+ --label first-run
16
+ ```
17
+
18
+ 可选参数:
19
+
20
+ | 参数 | 说明 |
21
+ | --- | --- |
22
+ | `--label` | 为本次运行命名(默认使用时间戳)。 |
23
+ | `--base` | RouteCodex 基地址,默认 `http://127.0.0.1:5555`。 |
24
+ | `--key` | API Key / Bearer Token,默认 `routecodex-test`。 |
25
+
26
+ ## 产出内容
27
+
28
+ 脚本会在样本所在目录下生成 `runs/<requestId>/<label>/`,包括:
29
+
30
+ - `request.json`:发送给 RouteCodex 的 endpoint 与 body;
31
+ - `response.meta.json`:状态码、响应头以及是否流式;
32
+ - 若为流式:
33
+ - `response.sse.log`:完整的 SSE 文本(`event:`/`data:`);
34
+ - `response.sse.ndjson`:逐帧 NDJSON,方便与黄金样本 diff;
35
+ - 若为 JSON:
36
+ - `response.json`:RouteCodex 返回的 JSON payload;
37
+ - 若发生错误,额外写入 `response.error.txt`。
38
+
39
+ ## 配合 proxy replay
40
+
41
+ 对于 responses SSE,可使用 `scripts/responses-sse-proxy.mjs --replay <capture>/response.sse.log` 将黄金样本作为上游输出,再结合本脚本回放客户端 payload,实现“同一份请求 + 同一份 SSE 流”在 RouteCodex 中的完整闭环。
42
+
43
+ ## 常见场景
44
+
45
+ - **工具调用链路**:先回放 `/v1/responses` 样本捕获 `required_action`,再回放对应的 `/v1/responses.submit_tool_outputs` 样本;
46
+ - **对比黄金样本**:和 `npm run verify:sse-loop -- --skip-chat --skip-anthropic --use-proxy-capture` 搭配,先复现请求,再检查 SSE 是否与黄金帧一致;
47
+ - **调试快照**:`runs/` 输出可以直接归档到版本库/CI 工件,作为后续 Regression 的输入。
48
+
49
+ 通过上述流程,可以确保 codex samples 中的工具请求、工具返回以及最终响应数据均可被精准复现,并在磁盘上形成完备的 JSON/SSE 证据链。
50
+