@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
@@ -7,13 +7,188 @@
7
7
  * - 认证:OAuth2 Bearer token
8
8
  * - 特性:多 project 支持、token 共享、模型回退
9
9
  */
10
- import { randomUUID } from 'node:crypto';
10
+ import { createHash, randomUUID, randomBytes } from 'node:crypto';
11
+ import { platform as osPlatform, arch as osArch, release as osRelease } from 'node:os';
11
12
  import { Transform } from 'node:stream';
12
13
  import { StringDecoder } from 'node:string_decoder';
13
14
  import { HttpTransportProvider } from './http-transport-provider.js';
14
15
  import { GeminiCLIProtocolClient } from '../../../client/gemini-cli/gemini-cli-protocol-client.js';
15
16
  import { getDefaultProjectId } from '../../auth/gemini-cli-userinfo-helper.js';
16
- import { ANTIGRAVITY_HELPER_DEFAULTS } from '../../auth/antigravity-userinfo-helper.js';
17
+ import { resolveAntigravityApiBaseCandidates } from '../../auth/antigravity-userinfo-helper.js';
18
+ import { getCamoufoxFingerprintProfile } from '../config/camoufox-launcher.js';
19
+ const ANTIGRAVITY_OS_VERSIONS = {
20
+ darwin: ['10.15.7', '11.6.8', '12.6.3', '13.5.2', '14.2.1', '14.5'],
21
+ win32: ['10.0.19041', '10.0.19042', '10.0.19043', '10.0.22000', '10.0.22621', '10.0.22631'],
22
+ linux: ['5.15.0', '5.19.0', '6.1.0', '6.2.0', '6.5.0', '6.6.0']
23
+ };
24
+ const ANTIGRAVITY_ARCHS = ['x64', 'arm64'];
25
+ const ANTIGRAVITY_VERSIONS = ['1.10.0', '1.10.5', '1.11.0', '1.11.2', '1.11.5', '1.12.0', '1.12.1'];
26
+ const ANTIGRAVITY_IDE_TYPES = ['IDE_UNSPECIFIED', 'VSCODE', 'INTELLIJ', 'ANDROID_STUDIO', 'CLOUD_SHELL_EDITOR'];
27
+ const ANTIGRAVITY_PLATFORMS = ['PLATFORM_UNSPECIFIED', 'WINDOWS', 'MACOS', 'LINUX'];
28
+ const ANTIGRAVITY_SDK_CLIENTS = [
29
+ 'google-cloud-sdk vscode_cloudshelleditor/0.1',
30
+ 'google-cloud-sdk vscode/1.86.0',
31
+ 'google-cloud-sdk vscode/1.87.0',
32
+ 'google-cloud-sdk intellij/2024.1',
33
+ 'google-cloud-sdk android-studio/2024.1',
34
+ 'gcloud-python/1.2.0 grpc-google-iam-v1/0.12.6'
35
+ ];
36
+ let antigravitySessionFingerprint = null;
37
+ const randomFrom = (items) => items[Math.floor(Math.random() * items.length)];
38
+ const generateAntigravityFingerprint = () => {
39
+ const platform = randomFrom(['darwin', 'win32', 'linux']);
40
+ const arch = randomFrom(ANTIGRAVITY_ARCHS);
41
+ const osVersion = randomFrom(ANTIGRAVITY_OS_VERSIONS[platform] ?? ANTIGRAVITY_OS_VERSIONS.linux);
42
+ const antigravityVersion = randomFrom(ANTIGRAVITY_VERSIONS);
43
+ const matchingPlatform = platform === 'darwin'
44
+ ? 'MACOS'
45
+ : platform === 'win32'
46
+ ? 'WINDOWS'
47
+ : platform === 'linux'
48
+ ? 'LINUX'
49
+ : randomFrom(ANTIGRAVITY_PLATFORMS);
50
+ return {
51
+ deviceId: randomUUID(),
52
+ sessionToken: randomBytes(16).toString('hex'),
53
+ userAgent: `antigravity/${antigravityVersion} ${platform}/${arch}`,
54
+ apiClient: randomFrom(ANTIGRAVITY_SDK_CLIENTS),
55
+ clientMetadata: {
56
+ ideType: randomFrom(ANTIGRAVITY_IDE_TYPES),
57
+ platform: matchingPlatform,
58
+ pluginType: 'GEMINI',
59
+ osVersion,
60
+ arch,
61
+ sqmId: `{${randomUUID().toUpperCase()}}`
62
+ },
63
+ quotaUser: `device-${randomBytes(8).toString('hex')}`,
64
+ createdAt: Date.now()
65
+ };
66
+ };
67
+ const getAntigravitySessionFingerprint = () => {
68
+ if (!antigravitySessionFingerprint) {
69
+ antigravitySessionFingerprint = generateAntigravityFingerprint();
70
+ }
71
+ return antigravitySessionFingerprint;
72
+ };
73
+ const collectCurrentAntigravityFingerprint = () => {
74
+ const platform = osPlatform();
75
+ const arch = osArch();
76
+ const osVersion = osRelease();
77
+ const matchingPlatform = platform === 'darwin'
78
+ ? 'MACOS'
79
+ : platform === 'win32'
80
+ ? 'WINDOWS'
81
+ : platform === 'linux'
82
+ ? 'LINUX'
83
+ : 'PLATFORM_UNSPECIFIED';
84
+ return {
85
+ deviceId: randomUUID(),
86
+ sessionToken: randomBytes(16).toString('hex'),
87
+ userAgent: `antigravity/1.11.5 ${platform}/${arch}`,
88
+ apiClient: 'google-cloud-sdk vscode_cloudshelleditor/0.1',
89
+ clientMetadata: {
90
+ ideType: 'VSCODE',
91
+ platform: matchingPlatform,
92
+ pluginType: 'GEMINI',
93
+ osVersion,
94
+ arch,
95
+ sqmId: `{${randomUUID().toUpperCase()}}`
96
+ },
97
+ quotaUser: `device-${randomBytes(16).toString('hex').slice(0, 16)}`,
98
+ createdAt: Date.now()
99
+ };
100
+ };
101
+ const buildAntigravityFingerprintHeaders = (fingerprint) => ({
102
+ 'User-Agent': fingerprint.userAgent,
103
+ 'X-Goog-Api-Client': fingerprint.apiClient,
104
+ 'Client-Metadata': JSON.stringify(fingerprint.clientMetadata),
105
+ 'X-Goog-QuotaUser': fingerprint.quotaUser,
106
+ 'X-Client-Device-Id': fingerprint.deviceId,
107
+ ...(fingerprint.acceptEncoding ? { 'Accept-Encoding': fingerprint.acceptEncoding } : {})
108
+ });
109
+ const extractAntigravityAlias = (providerKey) => {
110
+ if (!providerKey) {
111
+ return undefined;
112
+ }
113
+ const parts = providerKey.split('.').filter(Boolean);
114
+ if (!parts.length) {
115
+ return undefined;
116
+ }
117
+ if (parts[0] !== 'antigravity') {
118
+ return undefined;
119
+ }
120
+ return parts.length >= 2 ? parts[1] : undefined;
121
+ };
122
+ const stableIdFromProfile = (profileId) => {
123
+ const hash = createHash('sha256').update(profileId).digest('hex');
124
+ const deviceId = `${hash.slice(0, 8)}-${hash.slice(8, 12)}-${hash.slice(12, 16)}-${hash.slice(16, 20)}-${hash.slice(20, 32)}`;
125
+ return {
126
+ deviceId,
127
+ quotaUser: `device-${hash.slice(0, 16)}`,
128
+ sqmId: `{${hash.slice(0, 8).toUpperCase()}-${hash.slice(8, 12).toUpperCase()}-${hash.slice(12, 16).toUpperCase()}-${hash.slice(16, 20).toUpperCase()}-${hash.slice(20, 32).toUpperCase()}}`
129
+ };
130
+ };
131
+ const buildFingerprintFromCamoufox = (profileId, env) => {
132
+ const camouKeys = Object.keys(env).filter((key) => key.startsWith('CAMOU_CONFIG_')).sort();
133
+ if (camouKeys.length === 0) {
134
+ return null;
135
+ }
136
+ const blob = camouKeys.map((key) => env[key]).join('');
137
+ let parsed = null;
138
+ try {
139
+ parsed = JSON.parse(blob);
140
+ }
141
+ catch {
142
+ return null;
143
+ }
144
+ const ua = typeof parsed['navigator.userAgent'] === 'string' ? parsed['navigator.userAgent'] : '';
145
+ const oscpu = typeof parsed['navigator.oscpu'] === 'string' ? parsed['navigator.oscpu'] : '';
146
+ const platformRaw = typeof parsed['navigator.platform'] === 'string' ? parsed['navigator.platform'] : oscpu;
147
+ const acceptEncoding = typeof parsed['headers.Accept-Encoding'] === 'string' ? parsed['headers.Accept-Encoding'] : undefined;
148
+ const platformLower = platformRaw.toLowerCase();
149
+ const platform = platformLower.includes('win') ? 'WINDOWS' : platformLower.includes('mac') ? 'MACOS' : 'LINUX';
150
+ const arch = platformLower.includes('arm64') || platformLower.includes('aarch64') ? 'arm64' : 'x64';
151
+ const stableIds = stableIdFromProfile(profileId);
152
+ return {
153
+ deviceId: stableIds.deviceId,
154
+ sessionToken: randomBytes(16).toString('hex'),
155
+ userAgent: ua || `antigravity/1.11.5 ${osPlatform()}/${osArch()}`,
156
+ apiClient: 'google-cloud-sdk vscode_cloudshelleditor/0.1',
157
+ acceptEncoding,
158
+ clientMetadata: {
159
+ ideType: 'IDE_UNSPECIFIED',
160
+ platform,
161
+ pluginType: 'GEMINI',
162
+ osVersion: oscpu || osRelease(),
163
+ arch,
164
+ sqmId: stableIds.sqmId
165
+ },
166
+ quotaUser: stableIds.quotaUser,
167
+ createdAt: Date.now()
168
+ };
169
+ };
170
+ const resolveAntigravityFingerprint = (runtime) => {
171
+ const alias = (runtime?.metadata && typeof runtime.metadata === 'object' && typeof runtime.metadata.alias === 'string'
172
+ ? String(runtime.metadata.alias)
173
+ : undefined) || extractAntigravityAlias(runtime?.providerKey);
174
+ const camoufox = getCamoufoxFingerprintProfile('antigravity', alias);
175
+ if (camoufox) {
176
+ const parsed = buildFingerprintFromCamoufox(camoufox.profileId, camoufox.env);
177
+ if (parsed) {
178
+ return parsed;
179
+ }
180
+ }
181
+ const env = (process.env.ROUTECODEX_ANTIGRAVITY_FINGERPRINT_MODE || process.env.RCC_ANTIGRAVITY_FINGERPRINT_MODE || '')
182
+ .trim()
183
+ .toLowerCase();
184
+ if (env === 'current' || env === 'host') {
185
+ return collectCurrentAntigravityFingerprint();
186
+ }
187
+ return getAntigravitySessionFingerprint();
188
+ };
189
+ // Legacy helper seed for Antigravity signature session key generation.
190
+ // Kept for backwards compatibility (even when we avoid auto-injecting sessionId).
191
+ const ANTIGRAVITY_PLUGIN_SESSION_ID = `-${randomUUID()}`;
17
192
  export class GeminiCLIHttpProvider extends HttpTransportProvider {
18
193
  constructor(config, dependencies) {
19
194
  const providerId = typeof config.config?.providerId === 'string' && config.config.providerId.trim().length
@@ -35,11 +210,28 @@ export class GeminiCLIHttpProvider extends HttpTransportProvider {
35
210
  };
36
211
  super(cfg, dependencies, 'gemini-cli-http-provider', new GeminiCLIProtocolClient());
37
212
  }
213
+ applyStreamModeHeaders(headers, wantsSse) {
214
+ if (!this.isAntigravityRuntime()) {
215
+ return super.applyStreamModeHeaders(headers, wantsSse);
216
+ }
217
+ // Antigravity: keep SSE Accept header behavior stable.
218
+ // We intentionally do not force "*/*" here because the upstream is sensitive to header triplets
219
+ // and we have observed successful runs with the default "text/event-stream" Accept.
220
+ return super.applyStreamModeHeaders(headers, wantsSse);
221
+ }
222
+ getBaseUrlCandidates(_context) {
223
+ if (!this.isAntigravityRuntime()) {
224
+ return undefined;
225
+ }
226
+ return resolveAntigravityApiBaseCandidates(this.getEffectiveBaseUrl());
227
+ }
38
228
  async preprocessRequest(request) {
39
229
  const processedRequest = await super.preprocessRequest(request);
40
230
  const adapter = this.resolvePayload(processedRequest);
41
231
  const payload = adapter.payload;
42
- const isAntigravity = this.isAntigravityRuntime();
232
+ const metadata = processedRequest && typeof processedRequest === 'object' && typeof processedRequest.metadata === 'object'
233
+ ? processedRequest.metadata
234
+ : undefined;
43
235
  // 从 auth provider 获取 project_id(仅做最小的 OAuth token 解析,不在此处触发 OAuth 流程)
44
236
  if (!this.authProvider) {
45
237
  throw new Error('Gemini CLI: auth provider not found');
@@ -58,6 +250,16 @@ export class GeminiCLIHttpProvider extends HttpTransportProvider {
58
250
  };
59
251
  const tokenData = readTokenPayload();
60
252
  const projectId = getDefaultProjectId(tokenData || {});
253
+ const projectOverride = (() => {
254
+ const ext = this.config?.config?.extensions;
255
+ const candidates = [ext?.projectId, ext?.project_id, ext?.project];
256
+ for (const candidate of candidates) {
257
+ if (typeof candidate === 'string' && candidate.trim().length) {
258
+ return candidate.trim();
259
+ }
260
+ }
261
+ return undefined;
262
+ })();
61
263
  // 构建 Gemini CLI 格式的请求(仅做传输层整理,不做 OpenAI→Gemini 语义转换)
62
264
  const model = typeof payload.model === 'string' && payload.model.trim().length > 0
63
265
  ? payload.model
@@ -66,10 +268,22 @@ export class GeminiCLIHttpProvider extends HttpTransportProvider {
66
268
  throw new Error('Gemini CLI: model is required');
67
269
  }
68
270
  payload.model = model;
69
- // 若当前 token 中已有 project 元数据,则补充到请求中;否则让上游决定后续行为。
70
- // 注意:Antigravity 运行时保持与早期成功快照一致,始终显式发送 project。
71
- if (projectId) {
72
- payload.project = projectId;
271
+ const isClaudeModel = this.isClaudeModelName(model);
272
+ // Project selection:
273
+ // - honor explicit payload.project (client/config),
274
+ // - otherwise honor provider config extensions project override,
275
+ // - otherwise fall back to token-derived default project_id if present.
276
+ const existingProject = typeof payload.project === 'string' && String(payload.project).trim().length
277
+ ? String(payload.project).trim()
278
+ : '';
279
+ if (!existingProject) {
280
+ const nextProject = projectOverride || projectId;
281
+ if (nextProject && nextProject.trim().length) {
282
+ payload.project = nextProject.trim();
283
+ }
284
+ else if (this.isAntigravityRuntime()) {
285
+ payload.project = this.generateSyntheticProjectId();
286
+ }
73
287
  }
74
288
  this.ensureRequestMetadata(payload);
75
289
  // 删除与 Gemini 协议无关的字段,避免影响 Cloud Code Assist schema 校验。
@@ -86,6 +300,43 @@ export class GeminiCLIHttpProvider extends HttpTransportProvider {
86
300
  // 如果上游/compat 层错误地产生了 payload.request(例如旧版本样本/回放),这里做一次扁平化,
87
301
  // 避免出现 body.request.request.contents 这种非法形状,导致上游生成空响应或被静默忽略。
88
302
  this.flattenRequestContainer(payload);
303
+ // Standard contract: Antigravity identity fields are carried in the JSON wrapper (not headers).
304
+ // gcli2api antigravity alignment:
305
+ // - requestId/requestType are sent as HTTP headers (provider finalizeRequestHeaders)
306
+ // - JSON wrapper should not force-inject extra identity/session fields
307
+ // Provider must not infer request semantics from user payload; modality hints must come from llmswitch-core metadata.
308
+ if (this.isAntigravityRuntime()) {
309
+ const record = payload;
310
+ if (!this.hasNonEmptyString(record.userAgent)) {
311
+ record.userAgent = 'antigravity';
312
+ }
313
+ if (!this.hasNonEmptyString(record.requestType)) {
314
+ const hasImageAttachment = metadata && (metadata.hasImageAttachment === true || metadata.hasImageAttachment === 'true');
315
+ const fallbackImageByModel = typeof model === 'string' && model.toLowerCase().includes('image');
316
+ record.requestType = hasImageAttachment || fallbackImageByModel ? 'image_gen' : 'agent';
317
+ }
318
+ const existingReqId = record.requestId;
319
+ if (typeof existingReqId !== 'string' || !existingReqId.trim().startsWith('req-')) {
320
+ record.requestId = `req-${randomUUID()}`;
321
+ }
322
+ }
323
+ // gcli2api antigravity alignment: keep JSON wrapper minimal.
324
+ // Preserve requestId/requestType in metadata for headers, then remove them from payload.
325
+ if (this.isAntigravityRuntime() && !isClaudeModel) {
326
+ const meta = processedRequest.metadata ?? {};
327
+ processedRequest.metadata = meta;
328
+ if (typeof payload.requestId === 'string' && payload.requestId.trim().length) {
329
+ meta.__antigravityRequestId = String(payload.requestId).trim();
330
+ delete payload.requestId;
331
+ }
332
+ if (typeof payload.requestType === 'string' && payload.requestType.trim().length) {
333
+ meta.__antigravityRequestType = String(payload.requestType).trim();
334
+ delete payload.requestType;
335
+ }
336
+ if (typeof payload.userAgent === 'string' && payload.userAgent.trim().length) {
337
+ delete payload.userAgent;
338
+ }
339
+ }
89
340
  return processedRequest;
90
341
  }
91
342
  wantsUpstreamSse(request, context) {
@@ -108,16 +359,81 @@ export class GeminiCLIHttpProvider extends HttpTransportProvider {
108
359
  async finalizeRequestHeaders(headers, request) {
109
360
  const finalized = await super.finalizeRequestHeaders(headers, request);
110
361
  if (this.isAntigravityRuntime()) {
111
- finalized['User-Agent'] = ANTIGRAVITY_HELPER_DEFAULTS.userAgent;
112
- if (!this.hasNonEmptyString(finalized['Accept-Encoding'])) {
113
- // 对齐旧版成功快照:使用 gzip, deflate, br
114
- finalized['Accept-Encoding'] = 'gzip, deflate, br';
362
+ const deleteHeaderInsensitive = (key) => {
363
+ const target = key.toLowerCase();
364
+ for (const k of Object.keys(finalized)) {
365
+ if (k.toLowerCase() === target) {
366
+ delete finalized[k];
367
+ }
368
+ }
369
+ };
370
+ const payload = this.resolvePayload(request).payload;
371
+ const meta = request.metadata ?? {};
372
+ const runtime = this.getCurrentRuntimeMetadata();
373
+ const isClaudeModel = this.isClaudeModelName(payload?.model);
374
+ const isClaudeThinking = typeof payload?.model === 'string' && payload.model.toLowerCase().includes('thinking');
375
+ const fingerprint = resolveAntigravityFingerprint(runtime);
376
+ const fingerprintHeaders = buildAntigravityFingerprintHeaders(fingerprint);
377
+ finalized['User-Agent'] = fingerprintHeaders['User-Agent'];
378
+ finalized['X-Goog-Api-Client'] = fingerprintHeaders['X-Goog-Api-Client'];
379
+ finalized['Client-Metadata'] = fingerprintHeaders['Client-Metadata'];
380
+ finalized['X-Goog-QuotaUser'] = fingerprintHeaders['X-Goog-QuotaUser'];
381
+ finalized['X-Client-Device-Id'] = fingerprintHeaders['X-Client-Device-Id'];
382
+ if (fingerprintHeaders['Accept-Encoding']) {
383
+ finalized['Accept-Encoding'] = fingerprintHeaders['Accept-Encoding'];
384
+ }
385
+ if (isClaudeModel) {
386
+ if (!finalized['Accept-Encoding']) {
387
+ finalized['Accept-Encoding'] = 'gzip';
388
+ }
389
+ if (isClaudeThinking) {
390
+ const existing = finalized['anthropic-beta'];
391
+ const interleaved = 'interleaved-thinking-2025-05-14';
392
+ finalized['anthropic-beta'] = existing && existing.length
393
+ ? (existing.includes(interleaved) ? existing : `${existing},${interleaved}`)
394
+ : interleaved;
395
+ }
115
396
  }
116
- // 保留 X-Goog-Api-Client / Client-Metadata,由上游决定是否使用;
117
- // 不再强行删除 Accept 头,维持默认的 text/event-stream。
397
+ else {
398
+ // gcli2api/opencode antigravity alignment: use fingerprint headers for non-Claude too.
399
+ if (!finalized['Accept-Encoding']) {
400
+ finalized['Accept-Encoding'] = 'gzip';
401
+ }
402
+ }
403
+ const requestId = (typeof payload.requestId === 'string' && payload.requestId.trim().length ? payload.requestId.trim() : '') ||
404
+ (typeof meta.__antigravityRequestId === 'string' && meta.__antigravityRequestId.trim().length
405
+ ? String(meta.__antigravityRequestId).trim()
406
+ : '');
407
+ const requestType = (typeof payload.requestType === 'string' && payload.requestType.trim().length ? payload.requestType.trim() : '') ||
408
+ (typeof meta.__antigravityRequestType === 'string' && meta.__antigravityRequestType.trim().length
409
+ ? String(meta.__antigravityRequestType).trim()
410
+ : '');
411
+ if (requestId)
412
+ finalized['requestId'] = requestId;
413
+ if (requestType)
414
+ finalized['requestType'] = requestType;
118
415
  }
119
416
  return finalized;
120
417
  }
418
+ buildHttpRequestBody(request) {
419
+ const built = super.buildHttpRequestBody(request);
420
+ if (!this.isAntigravityRuntime() || !built || typeof built !== 'object') {
421
+ return built;
422
+ }
423
+ // gcli2api antigravity alignment: requestId/requestType are headers; JSON wrapper stays minimal.
424
+ return built;
425
+ }
426
+ isClaudeModelName(model) {
427
+ return typeof model === 'string' && model.toLowerCase().includes('claude');
428
+ }
429
+ generateSyntheticProjectId() {
430
+ const adjectives = ['useful', 'bright', 'swift', 'calm', 'bold'];
431
+ const nouns = ['fuze', 'wave', 'spark', 'flow', 'core'];
432
+ const adj = adjectives[Math.floor(Math.random() * adjectives.length)];
433
+ const noun = nouns[Math.floor(Math.random() * nouns.length)];
434
+ const randomPart = randomUUID().slice(0, 5).toLowerCase();
435
+ return `${adj}-${noun}-${randomPart}`;
436
+ }
121
437
  async postprocessResponse(response, context) {
122
438
  const processingTime = Date.now() - context.startTime;
123
439
  if (response && typeof response === 'object') {
@@ -178,7 +494,11 @@ export class GeminiCLIHttpProvider extends HttpTransportProvider {
178
494
  return super.wrapUpstreamSseResponse(normalizer, context);
179
495
  }
180
496
  isAntigravityRuntime() {
181
- return (this.oauthProviderId || '').toLowerCase() === 'antigravity';
497
+ const fromConfig = typeof this.config?.config?.providerId === 'string' && this.config.config.providerId.trim()
498
+ ? this.config.config.providerId.trim().toLowerCase()
499
+ : '';
500
+ const fromOAuth = typeof this.oauthProviderId === 'string' ? this.oauthProviderId.trim().toLowerCase() : '';
501
+ return fromConfig === 'antigravity' || fromOAuth === 'antigravity';
182
502
  }
183
503
  resolvePayload(source) {
184
504
  if (this.hasDataEnvelope(source)) {
@@ -231,62 +551,38 @@ export class GeminiCLIHttpProvider extends HttpTransportProvider {
231
551
  ensureRequestMetadata(payload) {
232
552
  const isAntigravity = this.isAntigravityRuntime();
233
553
  if (!this.hasNonEmptyString(payload.requestId)) {
554
+ // gcli2api antigravity alignment: requestId uses req- prefix (carried as HTTP header).
234
555
  payload.requestId = `req-${randomUUID()}`;
235
556
  }
236
- // 对齐 gcli2api:Antigravity 运行时不发送 session_id,其它运行时保持原有行为。
237
- if (!isAntigravity && !this.hasNonEmptyString(payload.session_id)) {
238
- payload.session_id = `session-${randomUUID()}`;
239
- }
240
- if (!this.hasNonEmptyString(payload.userAgent)) {
241
- payload.userAgent = this.oauthProviderId === 'antigravity' ? 'antigravity' : 'routecodex';
242
- }
243
- // 对齐 gcli2api:Antigravity 路径统一标记 requestType=agent,
244
- // 不区分模型(claude / gemini 均走 agent 配额路径)。
245
- if (isAntigravity && !this.hasNonEmptyString(payload.requestType)) {
246
- payload.requestType = 'agent';
247
- }
248
- // 对齐 gcli2api:Antigravity 统一注入固定 systemInstruction,
249
- // 将已有 systemInstruction.parts 追加在 Antigravity 提示词之后。
557
+ // Never inject legacy snake_case session_id.
250
558
  if (isAntigravity) {
251
- const requestContainer = payload.request && typeof payload.request === 'object'
252
- ? payload.request
253
- : undefined;
254
- const currentSystemInstruction = payload.systemInstruction ??
255
- (requestContainer && requestContainer.systemInstruction);
256
- const currentParts = currentSystemInstruction && typeof currentSystemInstruction === 'object' && !Array.isArray(currentSystemInstruction)
257
- ? currentSystemInstruction.parts
258
- : Array.isArray(currentSystemInstruction)
259
- ? currentSystemInstruction
260
- : undefined;
261
- const antigravityPrompt = 'Please ignore the following [ignore]You are Antigravity, a powerful agentic AI coding assistant designed by the Google Deepmind team working on Advanced Agentic Coding.' +
262
- 'You are pair programming with a USER to solve their coding task. The task may require creating a new codebase, modifying or debugging an existing codebase, or simply answering a question.' +
263
- '**Absolute paths only****Proactiveness**[/ignore]';
264
- const nextParts = [{ text: antigravityPrompt }];
265
- if (Array.isArray(currentParts) && currentParts.length > 0) {
266
- for (const part of currentParts) {
267
- if (part && typeof part === 'object') {
268
- const text = String(part.text ?? '').trim();
269
- if (text.length) {
270
- nextParts.push({ text });
271
- }
272
- }
273
- }
274
- }
275
- const nextSystemInstruction = {
276
- parts: nextParts,
277
- ...(currentSystemInstruction &&
278
- typeof currentSystemInstruction === 'object' &&
279
- !Array.isArray(currentSystemInstruction) &&
280
- typeof currentSystemInstruction.role === 'string'
281
- ? { role: currentSystemInstruction.role }
282
- : {})
283
- };
284
- payload.systemInstruction = nextSystemInstruction;
285
- if (requestContainer && typeof requestContainer === 'object') {
286
- requestContainer.systemInstruction = nextSystemInstruction;
287
- }
559
+ delete payload.session_id;
288
560
  }
289
561
  }
562
+ isAntigravityMinimalCompatibilityEnabled() {
563
+ const raw = (process.env.ROUTECODEX_ANTIGRAVITY_HEADER_MODE || process.env.RCC_ANTIGRAVITY_HEADER_MODE || '')
564
+ .trim()
565
+ .toLowerCase();
566
+ // Legacy switch kept for older deployments; RouteCodex now follows gcli2api antigravity header style by default.
567
+ // This method is currently unused (we avoid forcing sessionId injection and keep requestId/requestType in headers).
568
+ if (!raw) {
569
+ return false;
570
+ }
571
+ if (raw === 'standard' || raw === 'full' || raw === 'headers') {
572
+ return false;
573
+ }
574
+ return raw === 'minimal' || raw === 'gcli2api';
575
+ }
576
+ buildAntigravitySignatureSessionKey(options) {
577
+ const modelKeyRaw = typeof options.model === 'string' ? options.model.trim().toLowerCase() : 'unknown';
578
+ // Antigravity contract: strip tier suffix to reduce cache misses when tier changes.
579
+ const modelKey = modelKeyRaw.replace(/-(minimal|low|medium|high)$/i, '');
580
+ const projectPart = typeof options.project === 'string' && options.project.trim().length ? options.project.trim() : 'default';
581
+ const conversationPart = typeof options.conversationKey === 'string' && options.conversationKey.trim().length
582
+ ? options.conversationKey.trim()
583
+ : 'default';
584
+ return `${ANTIGRAVITY_PLUGIN_SESSION_ID}:${modelKey}:${projectPart}:${conversationPart}`;
585
+ }
290
586
  flattenRequestContainer(payload) {
291
587
  const requestContainer = payload.request && typeof payload.request === 'object'
292
588
  ? payload.request
@@ -354,7 +650,9 @@ class GeminiSseNormalizer extends Transform {
354
650
  // or assume separate handling. Safe approach: treat as bytes.
355
651
  text = this.decoder.write(Buffer.from(String(chunk), 'utf8'));
356
652
  }
357
- this.buffer += text.replace(/\r\n/g, '\n');
653
+ // Upstream can use CRLF (\r\n), and chunk boundaries may split \r and \n.
654
+ // Normalize by removing all \r so the event separator is always \n\n.
655
+ this.buffer += text.replace(/\r/g, '');
358
656
  this.processBuffered();
359
657
  }
360
658
  callback();
@@ -362,14 +660,9 @@ class GeminiSseNormalizer extends Transform {
362
660
  _flush(callback) {
363
661
  const remaining = this.decoder.end();
364
662
  if (remaining) {
365
- this.buffer += remaining.replace(/\r\n/g, '\n');
663
+ this.buffer += remaining.replace(/\r/g, '');
366
664
  }
367
665
  this.processBuffered(true);
368
- console.log('[GeminiSseNormalizer] Stream complete:', {
369
- totalChunks: this.chunkCounter,
370
- processedEvents: this.processedEventCounter,
371
- emittedEvents: this.eventCounter
372
- });
373
666
  if (this.lastDonePayload) {
374
667
  this.pushEvent('gemini.done', this.lastDonePayload);
375
668
  this.lastDonePayload = null;
@@ -389,24 +682,11 @@ class GeminiSseNormalizer extends Transform {
389
682
  this.processEvent(rawEvent);
390
683
  }
391
684
  if (flush && this.buffer.trim().length) {
392
- console.log('[GeminiSseNormalizer] Final buffer flush:', {
393
- bufferLength: this.buffer.length,
394
- bufferPreview: this.buffer.slice(0, 300),
395
- eventsFoundInLoop: eventsFound
396
- });
397
685
  this.processEvent(this.buffer);
398
686
  this.buffer = '';
399
687
  }
400
- else if (flush) {
401
- console.log('[GeminiSseNormalizer] Flush called but buffer empty:', {
402
- eventsFoundInLoop: eventsFound
403
- });
404
- }
405
688
  }
406
689
  processEvent(rawEvent) {
407
- if (process.env.ROUTECODEX_DEBUG_GEMINI_RAW === '1') {
408
- console.log('[DEBUG-GEMINI-INPUT]', JSON.stringify(rawEvent));
409
- }
410
690
  this.processedEventCounter++;
411
691
  const trimmed = rawEvent.trim();
412
692
  if (!trimmed.length) {
@@ -429,22 +709,12 @@ class GeminiSseNormalizer extends Transform {
429
709
  this.capturedEvents.push(parsed);
430
710
  const response = parsed?.response;
431
711
  if (!response || typeof response !== 'object') {
432
- // Log dropped events for debugging
433
- console.warn('[GeminiSseNormalizer] Dropped event without valid response field:', {
434
- hasResponse: !!parsed?.response,
435
- parsedKeys: Object.keys(parsed || {}),
436
- payloadPreview: payloadText.slice(0, 150)
437
- });
438
712
  return;
439
713
  }
440
714
  this.emitCandidateParts(response);
441
715
  }
442
716
  catch (err) {
443
- // Log parse failures for debugging
444
- console.error('[GeminiSseNormalizer] Failed to parse SSE payload:', {
445
- error: err instanceof Error ? err.message : String(err),
446
- payloadPreview: payloadText.slice(0, 200)
447
- });
717
+ // ignore parse errors; upstream stream snapshots (if enabled) are used for debugging
448
718
  }
449
719
  }
450
720
  emitCandidateParts(response) {
@@ -458,8 +728,9 @@ class GeminiSseNormalizer extends Transform {
458
728
  const partsRaw = content?.parts;
459
729
  const parts = Array.isArray(partsRaw) ? partsRaw : [];
460
730
  for (const part of parts) {
461
- if (!part || typeof part !== 'object')
731
+ if (!part || typeof part !== 'object') {
462
732
  continue;
733
+ }
463
734
  // Send raw Gemini part - let llmswitch-core handle the conversion to target protocol
464
735
  this.pushEvent('gemini.data', {
465
736
  candidateIndex: index,