@jsonstudio/rcc 0.89.168 → 0.89.524

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 (431) hide show
  1. package/README.md +18 -15
  2. package/dist/build-info.js +3 -3
  3. package/dist/build-info.js.map +1 -1
  4. package/dist/cli.js +94 -0
  5. package/dist/cli.js.map +1 -1
  6. package/dist/client/gemini-cli/gemini-cli-protocol-client.js +28 -5
  7. package/dist/client/gemini-cli/gemini-cli-protocol-client.js.map +1 -1
  8. package/dist/commands/token-daemon.d.ts +2 -0
  9. package/dist/commands/token-daemon.js +183 -0
  10. package/dist/commands/token-daemon.js.map +1 -0
  11. package/dist/error-handling/quiet-error-handling-center.d.ts +9 -0
  12. package/dist/error-handling/quiet-error-handling-center.js +141 -0
  13. package/dist/error-handling/quiet-error-handling-center.js.map +1 -0
  14. package/dist/error-handling/route-error-hub.js +8 -2
  15. package/dist/error-handling/route-error-hub.js.map +1 -1
  16. package/dist/index.js +4 -3
  17. package/dist/index.js.map +1 -1
  18. package/dist/modules/llmswitch/bridge.d.ts +1 -1
  19. package/dist/modules/llmswitch/bridge.js +3 -2
  20. package/dist/modules/llmswitch/bridge.js.map +1 -1
  21. package/dist/modules/pipeline/utils/colored-logger.d.ts +2 -0
  22. package/dist/modules/pipeline/utils/colored-logger.js +22 -3
  23. package/dist/modules/pipeline/utils/colored-logger.js.map +1 -1
  24. package/dist/providers/auth/antigravity-userinfo-helper.d.ts +10 -0
  25. package/dist/providers/auth/antigravity-userinfo-helper.js +140 -0
  26. package/dist/providers/auth/antigravity-userinfo-helper.js.map +1 -0
  27. package/dist/providers/auth/gemini-cli-userinfo-helper.js +12 -2
  28. package/dist/providers/auth/gemini-cli-userinfo-helper.js.map +1 -1
  29. package/dist/providers/auth/oauth-lifecycle.js +395 -24
  30. package/dist/providers/auth/oauth-lifecycle.js.map +1 -1
  31. package/dist/providers/auth/token-scanner/index.d.ts +32 -0
  32. package/dist/providers/auth/token-scanner/index.js +86 -0
  33. package/dist/providers/auth/token-scanner/index.js.map +1 -0
  34. package/dist/providers/auth/tokenfile-auth.d.ts +17 -0
  35. package/dist/providers/auth/tokenfile-auth.js +27 -5
  36. package/dist/providers/auth/tokenfile-auth.js.map +1 -1
  37. package/dist/providers/core/api/provider-types.d.ts +10 -0
  38. package/dist/providers/core/config/oauth-flows.d.ts +25 -0
  39. package/dist/providers/core/config/oauth-flows.js +92 -5
  40. package/dist/providers/core/config/oauth-flows.js.map +1 -1
  41. package/dist/providers/core/config/provider-oauth-configs.js +93 -2
  42. package/dist/providers/core/config/provider-oauth-configs.js.map +1 -1
  43. package/dist/providers/core/config/service-profiles.js +18 -10
  44. package/dist/providers/core/config/service-profiles.js.map +1 -1
  45. package/dist/providers/core/runtime/base-provider.d.ts +2 -0
  46. package/dist/providers/core/runtime/base-provider.js +135 -15
  47. package/dist/providers/core/runtime/base-provider.js.map +1 -1
  48. package/dist/providers/core/runtime/gemini-cli-http-provider.d.ts +8 -3
  49. package/dist/providers/core/runtime/gemini-cli-http-provider.js +332 -67
  50. package/dist/providers/core/runtime/gemini-cli-http-provider.js.map +1 -1
  51. package/dist/providers/core/runtime/http-request-executor.d.ts +1 -0
  52. package/dist/providers/core/runtime/http-request-executor.js +41 -1
  53. package/dist/providers/core/runtime/http-request-executor.js.map +1 -1
  54. package/dist/providers/core/runtime/http-transport-provider.d.ts +27 -0
  55. package/dist/providers/core/runtime/http-transport-provider.js +342 -69
  56. package/dist/providers/core/runtime/http-transport-provider.js.map +1 -1
  57. package/dist/providers/core/runtime/provider-error-classifier.d.ts +2 -2
  58. package/dist/providers/core/runtime/provider-error-classifier.js +14 -4
  59. package/dist/providers/core/runtime/provider-error-classifier.js.map +1 -1
  60. package/dist/providers/core/runtime/provider-factory.d.ts +1 -0
  61. package/dist/providers/core/runtime/provider-factory.js +37 -8
  62. package/dist/providers/core/runtime/provider-factory.js.map +1 -1
  63. package/dist/providers/core/runtime/responses-provider.d.ts +3 -3
  64. package/dist/providers/core/runtime/responses-provider.js +56 -117
  65. package/dist/providers/core/runtime/responses-provider.js.map +1 -1
  66. package/dist/providers/core/runtime/vision-debug-utils.d.ts +13 -0
  67. package/dist/providers/core/runtime/vision-debug-utils.js +114 -0
  68. package/dist/providers/core/runtime/vision-debug-utils.js.map +1 -0
  69. package/dist/providers/core/strategies/oauth-auth-code-flow.js +82 -25
  70. package/dist/providers/core/strategies/oauth-auth-code-flow.js.map +1 -1
  71. package/dist/providers/core/utils/http-client.d.ts +5 -0
  72. package/dist/providers/core/utils/http-client.js +31 -4
  73. package/dist/providers/core/utils/http-client.js.map +1 -1
  74. package/dist/providers/core/utils/provider-error-reporter.js +8 -2
  75. package/dist/providers/core/utils/provider-error-reporter.js.map +1 -1
  76. package/dist/providers/core/utils/snapshot-writer.d.ts +1 -1
  77. package/dist/providers/core/utils/snapshot-writer.js +5 -1
  78. package/dist/providers/core/utils/snapshot-writer.js.map +1 -1
  79. package/dist/providers/profile/provider-profile-loader.js +8 -4
  80. package/dist/providers/profile/provider-profile-loader.js.map +1 -1
  81. package/dist/runtime/runtime-flags.d.ts +4 -0
  82. package/dist/runtime/runtime-flags.js +32 -0
  83. package/dist/runtime/runtime-flags.js.map +1 -0
  84. package/dist/server/handlers/handler-utils.js +29 -2
  85. package/dist/server/handlers/handler-utils.js.map +1 -1
  86. package/dist/server/handlers/messages-handler.js +27 -26
  87. package/dist/server/handlers/messages-handler.js.map +1 -1
  88. package/dist/server/handlers/responses-handler.js +35 -1
  89. package/dist/server/handlers/responses-handler.js.map +1 -1
  90. package/dist/server/handlers/sse-dispatcher.js +22 -2
  91. package/dist/server/handlers/sse-dispatcher.js.map +1 -1
  92. package/dist/server/runtime/http-server/index.d.ts +10 -0
  93. package/dist/server/runtime/http-server/index.js +551 -148
  94. package/dist/server/runtime/http-server/index.js.map +1 -1
  95. package/dist/server/runtime/http-server/request-executor.d.ts +14 -0
  96. package/dist/server/runtime/http-server/request-executor.js +638 -149
  97. package/dist/server/runtime/http-server/request-executor.js.map +1 -1
  98. package/dist/server/runtime/http-server/routes.d.ts +5 -0
  99. package/dist/server/runtime/http-server/routes.js +69 -0
  100. package/dist/server/runtime/http-server/routes.js.map +1 -1
  101. package/dist/server/runtime/http-server/runtime-manager.js +18 -0
  102. package/dist/server/runtime/http-server/runtime-manager.js.map +1 -1
  103. package/dist/server/utils/sse-request-parser.d.ts +1 -0
  104. package/dist/server/utils/sse-request-parser.js +17 -6
  105. package/dist/server/utils/sse-request-parser.js.map +1 -1
  106. package/dist/server/utils/utf8-chunk-buffer.d.ts +43 -0
  107. package/dist/server/utils/utf8-chunk-buffer.js +132 -0
  108. package/dist/server/utils/utf8-chunk-buffer.js.map +1 -0
  109. package/dist/server/utils/warmup-detector.d.ts +7 -0
  110. package/dist/server/utils/warmup-detector.js +125 -0
  111. package/dist/server/utils/warmup-detector.js.map +1 -0
  112. package/dist/server/utils/warmup-storm-tracker.d.ts +9 -0
  113. package/dist/server/utils/warmup-storm-tracker.js +61 -0
  114. package/dist/server/utils/warmup-storm-tracker.js.map +1 -0
  115. package/dist/token-daemon/index.d.ts +7 -0
  116. package/dist/token-daemon/index.js +242 -0
  117. package/dist/token-daemon/index.js.map +1 -0
  118. package/dist/token-daemon/server-utils.d.ts +33 -0
  119. package/dist/token-daemon/server-utils.js +155 -0
  120. package/dist/token-daemon/server-utils.js.map +1 -0
  121. package/dist/token-daemon/token-daemon.d.ts +20 -0
  122. package/dist/token-daemon/token-daemon.js +144 -0
  123. package/dist/token-daemon/token-daemon.js.map +1 -0
  124. package/dist/token-daemon/token-types.d.ts +44 -0
  125. package/dist/token-daemon/token-types.js +18 -0
  126. package/dist/token-daemon/token-types.js.map +1 -0
  127. package/dist/token-daemon/token-utils.d.ts +17 -0
  128. package/dist/token-daemon/token-utils.js +153 -0
  129. package/dist/token-daemon/token-utils.js.map +1 -0
  130. package/dist/tools/semantic-replay.js +7 -6
  131. package/dist/tools/semantic-replay.js.map +1 -1
  132. package/dist/utils/debug-utils.js +14 -0
  133. package/dist/utils/debug-utils.js.map +1 -1
  134. package/dist/utils/error-handler-registry.d.ts +36 -0
  135. package/dist/utils/error-handler-registry.js +99 -12
  136. package/dist/utils/error-handler-registry.js.map +1 -1
  137. package/dist/utils/error-handling-utils.js +4 -3
  138. package/dist/utils/error-handling-utils.js.map +1 -1
  139. package/dist/utils/log-helpers.d.ts +6 -0
  140. package/dist/utils/log-helpers.js +90 -0
  141. package/dist/utils/log-helpers.js.map +1 -0
  142. package/dist/utils/logger.d.ts +8 -0
  143. package/dist/utils/logger.js +55 -2
  144. package/dist/utils/logger.js.map +1 -1
  145. package/dist/utils/snapshot-writer.js +2 -6
  146. package/dist/utils/snapshot-writer.js.map +1 -1
  147. package/node_modules/@jsonstudio/llms/README.md +2 -0
  148. package/node_modules/@jsonstudio/llms/dist/conversion/codecs/gemini-openai-codec.js +152 -6
  149. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/auto-thinking.d.ts +6 -0
  150. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/auto-thinking.js +25 -0
  151. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/field-mapping.d.ts +14 -0
  152. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/field-mapping.js +155 -0
  153. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/gemini-web-search.d.ts +17 -0
  154. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/gemini-web-search.js +68 -0
  155. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/glm-image-content.d.ts +2 -0
  156. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/glm-image-content.js +83 -0
  157. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/glm-tool-extraction.d.ts +2 -0
  158. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/glm-tool-extraction.js +264 -0
  159. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/glm-vision-prompt.d.ts +11 -0
  160. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/glm-vision-prompt.js +177 -0
  161. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/glm-web-search.d.ts +2 -0
  162. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/glm-web-search.js +63 -0
  163. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/qwen-transform.d.ts +3 -0
  164. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/qwen-transform.js +209 -0
  165. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/request-rules.d.ts +24 -0
  166. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/request-rules.js +63 -0
  167. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/response-blacklist.d.ts +14 -0
  168. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/response-blacklist.js +85 -0
  169. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/response-normalize.d.ts +5 -0
  170. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/response-normalize.js +121 -0
  171. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/response-validate.d.ts +5 -0
  172. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/response-validate.js +76 -0
  173. package/{dist/providers/compat/utils/snapshot-writer.d.ts → node_modules/@jsonstudio/llms/dist/conversion/compat/actions/snapshot.d.ts} +2 -2
  174. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/snapshot.js +21 -0
  175. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/tool-schema.d.ts +6 -0
  176. package/{dist/providers/compat/glm/utils/tool-schema-helpers.js → node_modules/@jsonstudio/llms/dist/conversion/compat/actions/tool-schema.js} +6 -1
  177. package/{dist/providers/compat/filters → node_modules/@jsonstudio/llms/dist/conversion/compat/actions}/universal-shape-filter.d.ts +17 -22
  178. package/{dist/providers/compat/filters → node_modules/@jsonstudio/llms/dist/conversion/compat/actions}/universal-shape-filter.js +46 -99
  179. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-gemini.json +17 -0
  180. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-glm.json +196 -13
  181. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-iflow.json +194 -26
  182. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-lmstudio.json +43 -35
  183. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-qwen.json +20 -16
  184. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/responses-c4m.json +42 -42
  185. package/node_modules/@jsonstudio/llms/dist/conversion/config/sample-config.json +1 -1
  186. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/compat/compat-engine.d.ts +7 -2
  187. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/compat/compat-engine.js +5 -665
  188. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/compat/compat-pipeline-executor.d.ts +9 -0
  189. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/compat/compat-pipeline-executor.js +869 -0
  190. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/compat/compat-types.d.ts +55 -0
  191. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline.d.ts +2 -0
  192. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline.js +74 -5
  193. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage3_compat/index.js +2 -2
  194. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/target-utils.js +9 -0
  195. package/node_modules/@jsonstudio/llms/dist/conversion/hub/process/chat-process.js +213 -1
  196. package/node_modules/@jsonstudio/llms/dist/conversion/hub/response/provider-response.d.ts +34 -0
  197. package/node_modules/@jsonstudio/llms/dist/conversion/hub/response/provider-response.js +84 -24
  198. package/node_modules/@jsonstudio/llms/dist/conversion/hub/response/response-runtime.js +19 -2
  199. package/node_modules/@jsonstudio/llms/dist/conversion/hub/response/server-side-tools.d.ts +26 -0
  200. package/node_modules/@jsonstudio/llms/dist/conversion/hub/response/server-side-tools.js +383 -0
  201. package/node_modules/@jsonstudio/llms/dist/conversion/hub/semantic-mappers/gemini-mapper.js +241 -14
  202. package/node_modules/@jsonstudio/llms/dist/conversion/hub/semantic-mappers/responses-mapper.js +17 -1
  203. package/node_modules/@jsonstudio/llms/dist/conversion/hub/standardized-bridge.js +14 -0
  204. package/node_modules/@jsonstudio/llms/dist/conversion/hub/types/standardized.d.ts +1 -0
  205. package/node_modules/@jsonstudio/llms/dist/conversion/responses/responses-host-policy.d.ts +6 -0
  206. package/node_modules/@jsonstudio/llms/dist/conversion/responses/responses-host-policy.js +14 -0
  207. package/node_modules/@jsonstudio/llms/dist/conversion/responses/responses-openai-bridge.js +133 -5
  208. package/node_modules/@jsonstudio/llms/dist/conversion/shared/anthropic-message-utils.js +98 -3
  209. package/node_modules/@jsonstudio/llms/dist/conversion/shared/bridge-message-utils.js +137 -10
  210. package/node_modules/@jsonstudio/llms/dist/conversion/shared/responses-output-builder.js +43 -2
  211. package/node_modules/@jsonstudio/llms/dist/conversion/shared/responses-reasoning-registry.d.ts +4 -0
  212. package/node_modules/@jsonstudio/llms/dist/conversion/shared/responses-reasoning-registry.js +62 -1
  213. package/node_modules/@jsonstudio/llms/dist/conversion/shared/responses-response-utils.js +23 -1
  214. package/node_modules/@jsonstudio/llms/dist/conversion/shared/snapshot-utils.js +17 -47
  215. package/node_modules/@jsonstudio/llms/dist/conversion/shared/tool-canonicalizer.d.ts +2 -0
  216. package/node_modules/@jsonstudio/llms/dist/conversion/shared/tool-filter-pipeline.js +12 -0
  217. package/node_modules/@jsonstudio/llms/dist/conversion/shared/tool-mapping.js +25 -2
  218. package/node_modules/@jsonstudio/llms/dist/index.d.ts +1 -0
  219. package/node_modules/@jsonstudio/llms/dist/index.js +1 -0
  220. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/bootstrap.js +540 -36
  221. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/classifier.js +12 -11
  222. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/context-advisor.d.ts +19 -0
  223. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/context-advisor.js +64 -0
  224. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine.d.ts +26 -0
  225. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine.js +450 -54
  226. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/features.js +23 -458
  227. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/health-manager.js +2 -7
  228. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/message-utils.d.ts +7 -0
  229. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/message-utils.js +78 -0
  230. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/provider-registry.js +7 -2
  231. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/token-counter.js +14 -3
  232. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/token-estimator.d.ts +2 -0
  233. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/token-estimator.js +16 -0
  234. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/token-file-scanner.d.ts +15 -0
  235. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/token-file-scanner.js +56 -0
  236. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/tool-signals.d.ts +13 -0
  237. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/tool-signals.js +403 -0
  238. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/types.d.ts +86 -2
  239. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/types.js +3 -1
  240. package/node_modules/@jsonstudio/llms/dist/servertool/engine.d.ts +27 -0
  241. package/node_modules/@jsonstudio/llms/dist/servertool/engine.js +60 -0
  242. package/node_modules/@jsonstudio/llms/dist/servertool/flow-types.d.ts +40 -0
  243. package/node_modules/@jsonstudio/llms/dist/servertool/flow-types.js +1 -0
  244. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/vision.d.ts +1 -0
  245. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/vision.js +194 -0
  246. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/web-search.d.ts +1 -0
  247. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/web-search.js +638 -0
  248. package/node_modules/@jsonstudio/llms/dist/servertool/orchestration-types.d.ts +33 -0
  249. package/node_modules/@jsonstudio/llms/dist/servertool/orchestration-types.js +1 -0
  250. package/node_modules/@jsonstudio/llms/dist/servertool/registry.d.ts +18 -0
  251. package/node_modules/@jsonstudio/llms/dist/servertool/registry.js +27 -0
  252. package/node_modules/@jsonstudio/llms/dist/servertool/server-side-tools.d.ts +8 -0
  253. package/node_modules/@jsonstudio/llms/dist/servertool/server-side-tools.js +208 -0
  254. package/node_modules/@jsonstudio/llms/dist/servertool/types.d.ts +88 -0
  255. package/node_modules/@jsonstudio/llms/dist/servertool/types.js +1 -0
  256. package/node_modules/@jsonstudio/llms/dist/servertool/vision-tool.d.ts +2 -0
  257. package/node_modules/@jsonstudio/llms/dist/servertool/vision-tool.js +185 -0
  258. package/node_modules/@jsonstudio/llms/dist/sse/json-to-sse/event-generators/responses.js +15 -3
  259. package/node_modules/@jsonstudio/llms/dist/sse/sse-to-json/builders/response-builder.js +6 -3
  260. package/node_modules/@jsonstudio/llms/dist/sse/sse-to-json/gemini-sse-to-json-converter.js +27 -1
  261. package/node_modules/@jsonstudio/llms/dist/sse/types/gemini-types.d.ts +20 -1
  262. package/node_modules/@jsonstudio/llms/dist/sse/types/responses-types.js +1 -1
  263. package/node_modules/@jsonstudio/llms/dist/telemetry/stats-center.d.ts +73 -0
  264. package/node_modules/@jsonstudio/llms/dist/telemetry/stats-center.js +280 -0
  265. package/node_modules/@jsonstudio/llms/package.json +2 -2
  266. package/package.json +11 -10
  267. package/scripts/README.md +26 -12
  268. package/scripts/auth-antigravity-token.mjs +64 -0
  269. package/scripts/auth-gemini-cli-token.mjs +96 -0
  270. package/scripts/auth-iflow-manual.mjs +81 -0
  271. package/scripts/auth-iflow-token-direct.mjs +87 -0
  272. package/scripts/auth-iflow-token.mjs +77 -0
  273. package/scripts/copy-compat-assets.mjs +3 -15
  274. package/scripts/install-verify.mjs +1 -0
  275. package/scripts/pack-mode.mjs +2 -1
  276. package/scripts/publish-rcc.mjs +20 -4
  277. package/scripts/replay-codex-sample.mjs +13 -8
  278. package/scripts/tests/chat-pipeline-blackbox.mjs +1 -1
  279. package/scripts/tests/virtual-router-health.mjs +141 -6
  280. package/scripts/tools/capture-provider-goldens.mjs +8 -7
  281. package/scripts/verify-client-headers.mjs +224 -0
  282. package/dist/providers/compat/base-compatibility.d.ts +0 -27
  283. package/dist/providers/compat/base-compatibility.js +0 -143
  284. package/dist/providers/compat/base-compatibility.js.map +0 -1
  285. package/dist/providers/compat/compat-directory-loader.d.ts +0 -4
  286. package/dist/providers/compat/compat-directory-loader.js +0 -85
  287. package/dist/providers/compat/compat-directory-loader.js.map +0 -1
  288. package/dist/providers/compat/compatibility-adapter.d.ts +0 -18
  289. package/dist/providers/compat/compatibility-adapter.js +0 -104
  290. package/dist/providers/compat/compatibility-adapter.js.map +0 -1
  291. package/dist/providers/compat/compatibility-factory.d.ts +0 -57
  292. package/dist/providers/compat/compatibility-factory.js +0 -155
  293. package/dist/providers/compat/compatibility-factory.js.map +0 -1
  294. package/dist/providers/compat/compatibility-interface.d.ts +0 -35
  295. package/dist/providers/compat/compatibility-interface.js +0 -2
  296. package/dist/providers/compat/compatibility-interface.js.map +0 -1
  297. package/dist/providers/compat/compatibility-manager.d.ts +0 -85
  298. package/dist/providers/compat/compatibility-manager.js +0 -368
  299. package/dist/providers/compat/compatibility-manager.js.map +0 -1
  300. package/dist/providers/compat/config/config-compatibility.d.ts +0 -28
  301. package/dist/providers/compat/config/config-compatibility.js +0 -95
  302. package/dist/providers/compat/config/config-compatibility.js.map +0 -1
  303. package/dist/providers/compat/field-mapping.d.ts +0 -102
  304. package/dist/providers/compat/field-mapping.js +0 -447
  305. package/dist/providers/compat/field-mapping.js.map +0 -1
  306. package/dist/providers/compat/filters/blacklist-sanitizer.d.ts +0 -45
  307. package/dist/providers/compat/filters/blacklist-sanitizer.js +0 -133
  308. package/dist/providers/compat/filters/blacklist-sanitizer.js.map +0 -1
  309. package/dist/providers/compat/filters/response-blacklist-sanitizer.d.ts +0 -28
  310. package/dist/providers/compat/filters/response-blacklist-sanitizer.js +0 -138
  311. package/dist/providers/compat/filters/response-blacklist-sanitizer.js.map +0 -1
  312. package/dist/providers/compat/filters/universal-shape-filter.js.map +0 -1
  313. package/dist/providers/compat/glm/config/blacklist-rules.json +0 -22
  314. package/dist/providers/compat/glm/config/field-mappings.json +0 -92
  315. package/dist/providers/compat/glm/config/response-blacklist.json +0 -7
  316. package/dist/providers/compat/glm/config/shape-filters.json +0 -37
  317. package/dist/providers/compat/glm/field-mapping/field-mapping-processor.d.ts +0 -28
  318. package/dist/providers/compat/glm/field-mapping/field-mapping-processor.js +0 -306
  319. package/dist/providers/compat/glm/field-mapping/field-mapping-processor.js.map +0 -1
  320. package/dist/providers/compat/glm/functions/glm-processor.d.ts +0 -50
  321. package/dist/providers/compat/glm/functions/glm-processor.js +0 -134
  322. package/dist/providers/compat/glm/functions/glm-processor.js.map +0 -1
  323. package/dist/providers/compat/glm/glm-compatibility.d.ts +0 -34
  324. package/dist/providers/compat/glm/glm-compatibility.js +0 -117
  325. package/dist/providers/compat/glm/glm-compatibility.js.map +0 -1
  326. package/dist/providers/compat/glm/hooks/base-hook.d.ts +0 -21
  327. package/dist/providers/compat/glm/hooks/base-hook.js +0 -53
  328. package/dist/providers/compat/glm/hooks/base-hook.js.map +0 -1
  329. package/dist/providers/compat/glm/hooks/glm-request-validation-hook.d.ts +0 -24
  330. package/dist/providers/compat/glm/hooks/glm-request-validation-hook.js +0 -268
  331. package/dist/providers/compat/glm/hooks/glm-request-validation-hook.js.map +0 -1
  332. package/dist/providers/compat/glm/hooks/glm-response-normalization-hook.d.ts +0 -21
  333. package/dist/providers/compat/glm/hooks/glm-response-normalization-hook.js +0 -171
  334. package/dist/providers/compat/glm/hooks/glm-response-normalization-hook.js.map +0 -1
  335. package/dist/providers/compat/glm/hooks/glm-response-validation-hook.d.ts +0 -25
  336. package/dist/providers/compat/glm/hooks/glm-response-validation-hook.js +0 -236
  337. package/dist/providers/compat/glm/hooks/glm-response-validation-hook.js.map +0 -1
  338. package/dist/providers/compat/glm/hooks/glm-tool-cleaning-hook.d.ts +0 -26
  339. package/dist/providers/compat/glm/hooks/glm-tool-cleaning-hook.js +0 -186
  340. package/dist/providers/compat/glm/hooks/glm-tool-cleaning-hook.js.map +0 -1
  341. package/dist/providers/compat/glm/index.d.ts +0 -24
  342. package/dist/providers/compat/glm/index.js +0 -29
  343. package/dist/providers/compat/glm/index.js.map +0 -1
  344. package/dist/providers/compat/glm/utils/tool-schema-helpers.d.ts +0 -3
  345. package/dist/providers/compat/glm/utils/tool-schema-helpers.js.map +0 -1
  346. package/dist/providers/compat/iflow/config/field-mappings.json +0 -92
  347. package/dist/providers/compat/iflow/config/shape-filters.json +0 -37
  348. package/dist/providers/compat/iflow/field-mapping/iflow-field-mapping-processor.d.ts +0 -34
  349. package/dist/providers/compat/iflow/field-mapping/iflow-field-mapping-processor.js +0 -386
  350. package/dist/providers/compat/iflow/field-mapping/iflow-field-mapping-processor.js.map +0 -1
  351. package/dist/providers/compat/iflow/functions/iflow-processor.d.ts +0 -53
  352. package/dist/providers/compat/iflow/functions/iflow-processor.js +0 -215
  353. package/dist/providers/compat/iflow/functions/iflow-processor.js.map +0 -1
  354. package/dist/providers/compat/iflow/hooks/base-hook.d.ts +0 -23
  355. package/dist/providers/compat/iflow/hooks/base-hook.js +0 -59
  356. package/dist/providers/compat/iflow/hooks/base-hook.js.map +0 -1
  357. package/dist/providers/compat/iflow/hooks/iflow-request-validation-hook.d.ts +0 -23
  358. package/dist/providers/compat/iflow/hooks/iflow-request-validation-hook.js +0 -279
  359. package/dist/providers/compat/iflow/hooks/iflow-request-validation-hook.js.map +0 -1
  360. package/dist/providers/compat/iflow/hooks/iflow-response-normalization-hook.d.ts +0 -20
  361. package/dist/providers/compat/iflow/hooks/iflow-response-normalization-hook.js +0 -180
  362. package/dist/providers/compat/iflow/hooks/iflow-response-normalization-hook.js.map +0 -1
  363. package/dist/providers/compat/iflow/hooks/iflow-response-validation-hook.d.ts +0 -23
  364. package/dist/providers/compat/iflow/hooks/iflow-response-validation-hook.js +0 -232
  365. package/dist/providers/compat/iflow/hooks/iflow-response-validation-hook.js.map +0 -1
  366. package/dist/providers/compat/iflow/hooks/iflow-tool-cleaning-hook.d.ts +0 -25
  367. package/dist/providers/compat/iflow/hooks/iflow-tool-cleaning-hook.js +0 -216
  368. package/dist/providers/compat/iflow/hooks/iflow-tool-cleaning-hook.js.map +0 -1
  369. package/dist/providers/compat/iflow/iflow-compatibility.d.ts +0 -24
  370. package/dist/providers/compat/iflow/iflow-compatibility.js +0 -94
  371. package/dist/providers/compat/iflow/iflow-compatibility.js.map +0 -1
  372. package/dist/providers/compat/index.d.ts +0 -59
  373. package/dist/providers/compat/index.js +0 -83
  374. package/dist/providers/compat/index.js.map +0 -1
  375. package/dist/providers/compat/lmstudio-compatibility.d.ts +0 -44
  376. package/dist/providers/compat/lmstudio-compatibility.js +0 -193
  377. package/dist/providers/compat/lmstudio-compatibility.js.map +0 -1
  378. package/dist/providers/compat/passthrough-compatibility.d.ts +0 -29
  379. package/dist/providers/compat/passthrough-compatibility.js +0 -83
  380. package/dist/providers/compat/passthrough-compatibility.js.map +0 -1
  381. package/dist/providers/compat/profiles/chat/glm/index.d.ts +0 -6
  382. package/dist/providers/compat/profiles/chat/glm/index.js +0 -6
  383. package/dist/providers/compat/profiles/chat/glm/index.js.map +0 -1
  384. package/dist/providers/compat/profiles/chat/iflow/index.d.ts +0 -6
  385. package/dist/providers/compat/profiles/chat/iflow/index.js +0 -6
  386. package/dist/providers/compat/profiles/chat/iflow/index.js.map +0 -1
  387. package/dist/providers/compat/profiles/chat/lmstudio/index.d.ts +0 -6
  388. package/dist/providers/compat/profiles/chat/lmstudio/index.js +0 -6
  389. package/dist/providers/compat/profiles/chat/lmstudio/index.js.map +0 -1
  390. package/dist/providers/compat/profiles/chat/qwen/index.d.ts +0 -6
  391. package/dist/providers/compat/profiles/chat/qwen/index.js +0 -6
  392. package/dist/providers/compat/profiles/chat/qwen/index.js.map +0 -1
  393. package/dist/providers/compat/profiles/compat/passthrough/index.d.ts +0 -6
  394. package/dist/providers/compat/profiles/compat/passthrough/index.js +0 -6
  395. package/dist/providers/compat/profiles/compat/passthrough/index.js.map +0 -1
  396. package/dist/providers/compat/profiles/responses/c4m/index.d.ts +0 -6
  397. package/dist/providers/compat/profiles/responses/c4m/index.js +0 -6
  398. package/dist/providers/compat/profiles/responses/c4m/index.js.map +0 -1
  399. package/dist/providers/compat/profiles/responses/default/index.d.ts +0 -6
  400. package/dist/providers/compat/profiles/responses/default/index.js +0 -6
  401. package/dist/providers/compat/profiles/responses/default/index.js.map +0 -1
  402. package/dist/providers/compat/profiles/responses/fai/index.d.ts +0 -6
  403. package/dist/providers/compat/profiles/responses/fai/index.js +0 -6
  404. package/dist/providers/compat/profiles/responses/fai/index.js.map +0 -1
  405. package/dist/providers/compat/profiles/responses/fc/index.d.ts +0 -6
  406. package/dist/providers/compat/profiles/responses/fc/index.js +0 -6
  407. package/dist/providers/compat/profiles/responses/fc/index.js.map +0 -1
  408. package/dist/providers/compat/qwen/index.d.ts +0 -4
  409. package/dist/providers/compat/qwen/index.js +0 -6
  410. package/dist/providers/compat/qwen/index.js.map +0 -1
  411. package/dist/providers/compat/qwen-compatibility.d.ts +0 -52
  412. package/dist/providers/compat/qwen-compatibility.js +0 -330
  413. package/dist/providers/compat/qwen-compatibility.js.map +0 -1
  414. package/dist/providers/compat/register-compat-module.d.ts +0 -8
  415. package/dist/providers/compat/register-compat-module.js +0 -53
  416. package/dist/providers/compat/register-compat-module.js.map +0 -1
  417. package/dist/providers/compat/responses/c4m-responses-compatibility.d.ts +0 -27
  418. package/dist/providers/compat/responses/c4m-responses-compatibility.js +0 -197
  419. package/dist/providers/compat/responses/c4m-responses-compatibility.js.map +0 -1
  420. package/dist/providers/compat/standard-compatibility-utils.d.ts +0 -1
  421. package/dist/providers/compat/standard-compatibility-utils.js +0 -77
  422. package/dist/providers/compat/standard-compatibility-utils.js.map +0 -1
  423. package/dist/providers/compat/standard-compatibility.d.ts +0 -31
  424. package/dist/providers/compat/standard-compatibility.js +0 -118
  425. package/dist/providers/compat/standard-compatibility.js.map +0 -1
  426. package/dist/providers/compat/utils/snapshot-writer.js +0 -62
  427. package/dist/providers/compat/utils/snapshot-writer.js.map +0 -1
  428. package/dist/tools/replay-request.d.ts +0 -0
  429. package/dist/tools/replay-request.js +0 -2
  430. package/dist/tools/replay-request.js.map +0 -1
  431. package/scripts/check-glm-compat.mjs +0 -47
@@ -1,3 +1,4 @@
1
+ import { recordStage } from '../pipeline/stages/utils.js';
1
2
  import { ChatFormatAdapter } from '../format-adapters/chat-format-adapter.js';
2
3
  import { ResponsesFormatAdapter } from '../format-adapters/responses-format-adapter.js';
3
4
  import { AnthropicFormatAdapter } from '../format-adapters/anthropic-format-adapter.js';
@@ -12,44 +13,36 @@ import { runRespProcessStage2Finalize } from '../pipeline/stages/resp_process/re
12
13
  import { runRespOutboundStage1ClientRemap } from '../pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/index.js';
13
14
  import { runRespOutboundStage2SseStream } from '../pipeline/stages/resp_outbound/resp_outbound_stage2_sse_stream/index.js';
14
15
  import { recordResponsesResponse } from '../../shared/responses-conversation-store.js';
15
- function resolveChatReasoningMode(entryEndpoint) {
16
- const envRaw = (process.env.ROUTECODEX_CHAT_REASONING_MODE || process.env.RCC_CHAT_REASONING_MODE || '').trim().toLowerCase();
17
- const map = {
18
- keep: 'keep',
19
- drop: 'drop',
20
- discard: 'drop',
21
- text: 'append_to_content',
22
- append: 'append_to_content',
23
- append_text: 'append_to_content',
24
- append_to_content: 'append_to_content'
25
- };
26
- if (envRaw && map[envRaw]) {
27
- return map[envRaw];
28
- }
29
- return 'keep';
30
- }
16
+ import { runServerToolOrchestration } from '../../../servertool/engine.js';
31
17
  const PROVIDER_RESPONSE_REGISTRY = {
32
18
  'openai-chat': {
33
- protocol: 'openai-chat',
34
19
  createFormatAdapter: () => new ChatFormatAdapter(),
35
20
  createMapper: () => new OpenAIChatResponseMapper()
36
21
  },
37
22
  'openai-responses': {
38
- protocol: 'openai-responses',
39
23
  createFormatAdapter: () => new ResponsesFormatAdapter(),
40
24
  createMapper: () => new ResponsesResponseMapper()
41
25
  },
42
26
  'anthropic-messages': {
43
- protocol: 'anthropic-messages',
44
27
  createFormatAdapter: () => new AnthropicFormatAdapter(),
45
28
  createMapper: () => new AnthropicResponseMapper()
46
29
  },
47
30
  'gemini-chat': {
48
- protocol: 'gemini-chat',
49
31
  createFormatAdapter: () => new GeminiFormatAdapter(),
50
32
  createMapper: () => new GeminiResponseMapper()
51
33
  }
52
34
  };
35
+ function isServerToolFollowup(context) {
36
+ const raw = context.serverToolFollowup;
37
+ if (raw === true) {
38
+ return true;
39
+ }
40
+ if (typeof raw === 'string') {
41
+ const v = raw.trim().toLowerCase();
42
+ return v === '1' || v === 'true';
43
+ }
44
+ return false;
45
+ }
53
46
  function resolveClientProtocol(entryEndpoint) {
54
47
  const lowered = (entryEndpoint || '').toLowerCase();
55
48
  if (lowered.includes('/v1/responses'))
@@ -85,8 +78,28 @@ function applyModelOverride(payload, model) {
85
78
  /* ignore */
86
79
  }
87
80
  }
81
+ function resolveChatReasoningMode(_entryEndpoint) {
82
+ // 当前保持默认策略:保留 reasoning_content 字段,不做额外拼接或删除。
83
+ return 'keep';
84
+ }
88
85
  export async function convertProviderResponse(options) {
89
86
  const clientProtocol = resolveClientProtocol(options.entryEndpoint);
87
+ const hasServerToolSupport = Boolean(options.providerInvoker) || Boolean(options.reenterPipeline);
88
+ const skipServerTools = isServerToolFollowup(options.context) || !hasServerToolSupport;
89
+ // 对于由 server-side 工具触发的内部跳转(二跳/三跳),统一禁用 SSE 聚合输出,
90
+ // 始终返回完整的 ChatCompletion JSON,便于在 llms 内部直接解析,而不是拿到
91
+ // __sse_responses 可读流。
92
+ const wantsStream = isServerToolFollowup(options.context) ? false : options.wantsStream;
93
+ try {
94
+ // eslint-disable-next-line no-console
95
+ console.log(`\x1b[38;5;33m[servertool][orchestrator][debug] requestId=${options.context.requestId} ` +
96
+ `protocol=${options.providerProtocol} endpoint=${options.entryEndpoint} ` +
97
+ `skipServerTools=${skipServerTools} hasInvoker=${Boolean(options.providerInvoker)} ` +
98
+ `hasReenter=${Boolean(options.reenterPipeline)}\x1b[0m`);
99
+ }
100
+ catch {
101
+ /* logging best-effort */
102
+ }
90
103
  const displayModel = extractDisplayModel(options.context);
91
104
  const plan = PROVIDER_RESPONSE_REGISTRY[options.providerProtocol];
92
105
  if (!plan) {
@@ -96,7 +109,7 @@ export async function convertProviderResponse(options) {
96
109
  providerProtocol: options.providerProtocol,
97
110
  payload: options.providerResponse,
98
111
  adapterContext: options.context,
99
- wantsStream: options.wantsStream,
112
+ wantsStream,
100
113
  stageRecorder: options.stageRecorder
101
114
  });
102
115
  const formatAdapter = plan.createFormatAdapter();
@@ -137,8 +150,55 @@ export async function convertProviderResponse(options) {
137
150
  mapper,
138
151
  stageRecorder: options.stageRecorder
139
152
  });
153
+ // 记录语义映射后的 ChatCompletion,便于回放 server-side 工具流程。
154
+ recordStage(options.stageRecorder, 'resp_inbound_stage3_semantic_map.chat', chatResponse);
155
+ // 检查是否需要进行 ServerTool 编排
156
+ // 使用新的 ChatEnvelope 级别的 servertool 实现
157
+ let effectiveChatResponse = chatResponse;
158
+ if (!skipServerTools && options.reenterPipeline) {
159
+ try {
160
+ // eslint-disable-next-line no-console
161
+ console.log(`\x1b[38;5;33m[servertool][orchestrator] start requestId=${options.context.requestId} ` +
162
+ `protocol=${options.providerProtocol} endpoint=${options.entryEndpoint}\x1b[0m`);
163
+ }
164
+ catch {
165
+ /* logging best-effort */
166
+ }
167
+ const orchestration = await runServerToolOrchestration({
168
+ chat: chatResponse,
169
+ adapterContext: options.context,
170
+ requestId: options.context.requestId,
171
+ entryEndpoint: options.entryEndpoint,
172
+ providerProtocol: options.providerProtocol,
173
+ providerInvoker: options.providerInvoker,
174
+ reenterPipeline: options.reenterPipeline
175
+ });
176
+ if (orchestration.executed) {
177
+ const flowLabel = orchestration.flowId ?? 'servertool_flow';
178
+ try {
179
+ // eslint-disable-next-line no-console
180
+ console.log(`\x1b[38;5;33m[servertool][orchestrator] completed requestId=${options.context.requestId} ` +
181
+ `mode=${flowLabel}\x1b[0m`);
182
+ }
183
+ catch {
184
+ /* logging best-effort */
185
+ }
186
+ effectiveChatResponse = orchestration.chat;
187
+ }
188
+ else {
189
+ try {
190
+ // eslint-disable-next-line no-console
191
+ console.log(`\x1b[38;5;33m[servertool][orchestrator] skipped requestId=${options.context.requestId} ` +
192
+ 'reason=no_servertool_match\x1b[0m');
193
+ }
194
+ catch {
195
+ /* logging best-effort */
196
+ }
197
+ }
198
+ }
199
+ // 如果没有执行 servertool,继续原来的处理流程
140
200
  const governanceResult = await runRespProcessStage1ToolGovernance({
141
- payload: chatResponse,
201
+ payload: effectiveChatResponse,
142
202
  entryEndpoint: options.entryEndpoint,
143
203
  requestId: options.context.requestId,
144
204
  clientProtocol,
@@ -148,7 +208,7 @@ export async function convertProviderResponse(options) {
148
208
  payload: governanceResult.governedPayload,
149
209
  entryEndpoint: options.entryEndpoint,
150
210
  requestId: options.context.requestId,
151
- wantsStream: options.wantsStream,
211
+ wantsStream,
152
212
  reasoningMode: resolveChatReasoningMode(options.entryEndpoint),
153
213
  stageRecorder: options.stageRecorder
154
214
  });
@@ -165,7 +225,7 @@ export async function convertProviderResponse(options) {
165
225
  clientPayload,
166
226
  clientProtocol,
167
227
  requestId: options.context.requestId,
168
- wantsStream: options.wantsStream,
228
+ wantsStream,
169
229
  stageRecorder: options.stageRecorder
170
230
  });
171
231
  if (outbound.stream) {
@@ -3,7 +3,7 @@ import { deriveToolCallKey } from '../../shared/tool-call-utils.js';
3
3
  import { createBridgeActionState, runBridgeActionPipeline } from '../../shared/bridge-actions.js';
4
4
  import { resolveBridgePolicy, resolvePolicyActions } from '../../shared/bridge-policies.js';
5
5
  import { normalizeAnthropicToolName } from '../../shared/anthropic-message-utils.js';
6
- import { registerResponsesReasoning, consumeResponsesReasoning, registerResponsesOutputTextMeta, consumeResponsesOutputTextMeta } from '../../shared/responses-reasoning-registry.js';
6
+ import { registerResponsesReasoning, consumeResponsesReasoning, registerResponsesOutputTextMeta, consumeResponsesOutputTextMeta, consumeResponsesPayloadSnapshot, registerResponsesPayloadSnapshot, consumeResponsesPassthrough, registerResponsesPassthrough } from '../../shared/responses-reasoning-registry.js';
7
7
  function flattenAnthropicContent(content) {
8
8
  if (typeof content === 'string')
9
9
  return content;
@@ -262,6 +262,20 @@ export function buildOpenAIChatFromAnthropicMessage(payload, options) {
262
262
  if (preservedOutputMeta) {
263
263
  chatResponse.__responses_output_text_meta = preservedOutputMeta;
264
264
  }
265
+ const payloadSnapshot = consumeResponsesPayloadSnapshot(chatResponse.id);
266
+ if (payloadSnapshot) {
267
+ registerResponsesPayloadSnapshot(chatResponse.id, payloadSnapshot);
268
+ if (typeof chatResponse.request_id !== 'string') {
269
+ chatResponse.request_id = chatResponse.id;
270
+ }
271
+ }
272
+ const passthroughPayload = consumeResponsesPassthrough(chatResponse.id);
273
+ if (passthroughPayload) {
274
+ registerResponsesPassthrough(chatResponse.id, passthroughPayload);
275
+ if (typeof chatResponse.request_id !== 'string') {
276
+ chatResponse.request_id = chatResponse.id;
277
+ }
278
+ }
265
279
  if (Object.keys(aliasCollector).length && !chatResponse.anthropicToolNameMap) {
266
280
  chatResponse.anthropicToolNameMap = aliasCollector;
267
281
  }
@@ -358,8 +372,11 @@ export function buildAnthropicResponseFromChat(chatResponse, options) {
358
372
  default: return 'end_turn';
359
373
  }
360
374
  })();
375
+ const canonicalId = typeof chatResponse.request_id === 'string'
376
+ ? chatResponse.request_id
377
+ : (typeof chatResponse.id === 'string' ? chatResponse.id : `resp_${Date.now()}`);
361
378
  const raw = {
362
- id: typeof chatResponse.id === 'string' ? chatResponse.id : `resp_${Date.now()}`,
379
+ id: canonicalId,
363
380
  type: 'message',
364
381
  role: 'assistant',
365
382
  content: contentBlocks,
@@ -0,0 +1,26 @@
1
+ import type { AdapterContext } from '../types/chat-envelope.js';
2
+ import type { JsonObject } from '../types/json.js';
3
+ export type ProviderInvoker = (options: {
4
+ providerKey: string;
5
+ providerType?: string;
6
+ modelId?: string;
7
+ providerProtocol: string;
8
+ payload: JsonObject;
9
+ entryEndpoint: string;
10
+ requestId: string;
11
+ }) => Promise<{
12
+ providerResponse: JsonObject;
13
+ }>;
14
+ export interface ServerSideToolEngineOptions {
15
+ chatResponse: JsonObject;
16
+ adapterContext: AdapterContext;
17
+ entryEndpoint: string;
18
+ requestId: string;
19
+ providerProtocol: string;
20
+ providerInvoker?: ProviderInvoker;
21
+ }
22
+ export interface ServerSideToolEngineResult {
23
+ mode: 'passthrough' | 'web_search_flow';
24
+ finalChatResponse: JsonObject;
25
+ }
26
+ export declare function runServerSideToolEngine(options: ServerSideToolEngineOptions): Promise<ServerSideToolEngineResult>;
@@ -0,0 +1,383 @@
1
+ import { buildOpenAIChatFromGeminiResponse } from '../../codecs/gemini-openai-codec.js';
2
+ function asObject(value) {
3
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : null;
4
+ }
5
+ function getArray(value) {
6
+ return Array.isArray(value) ? value : [];
7
+ }
8
+ function extractToolCalls(chatResponse) {
9
+ const choices = getArray(chatResponse.choices);
10
+ const calls = [];
11
+ for (const choice of choices) {
12
+ const choiceObj = asObject(choice);
13
+ if (!choiceObj)
14
+ continue;
15
+ const message = asObject(choiceObj.message);
16
+ if (!message)
17
+ continue;
18
+ const toolCalls = getArray(message.tool_calls);
19
+ for (const raw of toolCalls) {
20
+ const tc = asObject(raw);
21
+ if (!tc)
22
+ continue;
23
+ const id = typeof tc.id === 'string' && tc.id.trim() ? tc.id.trim() : '';
24
+ const fn = asObject(tc.function);
25
+ const name = fn && typeof fn.name === 'string' && fn.name.trim() ? fn.name.trim() : '';
26
+ const args = fn && typeof fn.arguments === 'string' ? fn.arguments : '';
27
+ if (!id || !name)
28
+ continue;
29
+ calls.push({ id, name, arguments: args });
30
+ }
31
+ }
32
+ return calls;
33
+ }
34
+ function extractTextFromChatLike(payload) {
35
+ // 1) 解包常见包装层:data / response 节点
36
+ let current = payload;
37
+ const visited = new Set();
38
+ while (current && typeof current === 'object' && !Array.isArray(current) && !visited.has(current)) {
39
+ visited.add(current);
40
+ if (Array.isArray(current.choices) || Array.isArray(current.output)) {
41
+ break;
42
+ }
43
+ const data = current.data;
44
+ if (data && typeof data === 'object' && !Array.isArray(data)) {
45
+ current = data;
46
+ continue;
47
+ }
48
+ const response = current.response;
49
+ if (response && typeof response === 'object' && !Array.isArray(response)) {
50
+ current = response;
51
+ continue;
52
+ }
53
+ break;
54
+ }
55
+ // 2) 优先从 choices[].message.content 提取(OpenAI/GLM 兼容)
56
+ const choices = getArray(current.choices);
57
+ if (!choices.length)
58
+ return '';
59
+ const first = asObject(choices[0]);
60
+ if (!first)
61
+ return '';
62
+ const message = asObject(first.message);
63
+ if (!message)
64
+ return '';
65
+ const content = message.content;
66
+ if (typeof content === 'string')
67
+ return content.trim();
68
+ const parts = getArray(content);
69
+ const texts = [];
70
+ for (const part of parts) {
71
+ if (typeof part === 'string') {
72
+ texts.push(part);
73
+ }
74
+ else if (part && typeof part === 'object') {
75
+ const record = part;
76
+ if (typeof record.text === 'string') {
77
+ texts.push(record.text);
78
+ }
79
+ else if (typeof record.content === 'string') {
80
+ texts.push(record.content);
81
+ }
82
+ }
83
+ }
84
+ const joinedFromChoices = texts.join('\n').trim();
85
+ if (joinedFromChoices) {
86
+ return joinedFromChoices;
87
+ }
88
+ // 3) 回退:从 output[].content[] 中提取(部分 Responses/自定义后端)
89
+ const output = current.output;
90
+ if (Array.isArray(output)) {
91
+ const altTexts = [];
92
+ for (const entry of output) {
93
+ if (!entry || typeof entry !== 'object')
94
+ continue;
95
+ const blocks = entry.content;
96
+ const blockArray = Array.isArray(blocks) ? blocks : [];
97
+ for (const block of blockArray) {
98
+ if (!block || typeof block !== 'object')
99
+ continue;
100
+ const record = block;
101
+ if (typeof record.text === 'string') {
102
+ altTexts.push(record.text);
103
+ }
104
+ else if (typeof record.output_text === 'string') {
105
+ altTexts.push(record.output_text);
106
+ }
107
+ else if (typeof record.content === 'string') {
108
+ altTexts.push(record.content);
109
+ }
110
+ }
111
+ }
112
+ const joined = altTexts.join('\n').trim();
113
+ if (joined) {
114
+ return joined;
115
+ }
116
+ }
117
+ return '';
118
+ }
119
+ function getWebSearchConfig(ctx) {
120
+ const raw = ctx.webSearch;
121
+ const record = raw && typeof raw === 'object' && !Array.isArray(raw) ? raw : null;
122
+ if (!record)
123
+ return undefined;
124
+ const enginesRaw = Array.isArray(record.engines) ? record.engines : [];
125
+ const engines = [];
126
+ for (const entry of enginesRaw) {
127
+ const obj = entry && typeof entry === 'object' && !Array.isArray(entry) ? entry : null;
128
+ if (!obj)
129
+ continue;
130
+ const id = typeof obj.id === 'string' && obj.id.trim() ? obj.id.trim() : undefined;
131
+ const providerKey = typeof obj.providerKey === 'string' && obj.providerKey.trim()
132
+ ? obj.providerKey.trim()
133
+ : undefined;
134
+ if (!id || !providerKey)
135
+ continue;
136
+ engines.push({
137
+ id,
138
+ providerKey,
139
+ description: typeof obj.description === 'string' && obj.description.trim() ? obj.description.trim() : undefined,
140
+ default: obj.default === true
141
+ });
142
+ }
143
+ if (!engines.length) {
144
+ return undefined;
145
+ }
146
+ const config = { engines };
147
+ if (typeof record.injectPolicy === 'string') {
148
+ const val = String(record.injectPolicy).trim().toLowerCase();
149
+ if (val === 'always' || val === 'selective') {
150
+ config.injectPolicy = val;
151
+ }
152
+ }
153
+ return config;
154
+ }
155
+ function resolveWebSearchEngine(config, engineId) {
156
+ const trimmedId = engineId && typeof engineId === 'string' && engineId.trim() ? engineId.trim() : undefined;
157
+ if (trimmedId) {
158
+ const byId = config.engines.find((e) => e.id === trimmedId);
159
+ if (byId) {
160
+ return byId;
161
+ }
162
+ }
163
+ const byDefault = config.engines.find((e) => e.default);
164
+ if (byDefault) {
165
+ return byDefault;
166
+ }
167
+ if (config.engines.length === 1) {
168
+ return config.engines[0];
169
+ }
170
+ return undefined;
171
+ }
172
+ function isGeminiWebSearchEngine(engine) {
173
+ const key = engine.providerKey.toLowerCase();
174
+ return key.startsWith('gemini-cli.') || key.startsWith('antigravity.');
175
+ }
176
+ function logServerToolWebSearch(engine, requestId, query) {
177
+ const providerAlias = engine.providerKey.split('.')[0] || engine.providerKey;
178
+ const backendLabel = `${providerAlias}:${engine.id}`;
179
+ const prefix = `[server-tool][web_search][${backendLabel}]`;
180
+ const line = `${prefix} requestId=${requestId} query=${JSON.stringify(query)}`;
181
+ // 深蓝色输出
182
+ // eslint-disable-next-line no-console
183
+ console.log(`\x1b[38;5;27m${line}\x1b[0m`);
184
+ }
185
+ function resolveEnvServerSideToolsEnabled() {
186
+ const raw = (process.env.ROUTECODEX_SERVER_SIDE_TOOLS || process.env.RCC_SERVER_SIDE_TOOLS || '').trim().toLowerCase();
187
+ if (!raw)
188
+ return false;
189
+ if (raw === '1' || raw === 'true' || raw === 'yes')
190
+ return true;
191
+ if (raw === 'web_search')
192
+ return true;
193
+ return false;
194
+ }
195
+ export async function runServerSideToolEngine(options) {
196
+ const base = asObject(options.chatResponse);
197
+ if (!base) {
198
+ return { mode: 'passthrough', finalChatResponse: options.chatResponse };
199
+ }
200
+ // 内建 OpenAI Responses `/v1/responses` 已经支持 server-side web_search。
201
+ // 仅当“入口端点为 /v1/responses 且 providerProtocol 也是 openai-responses”时保持透传,
202
+ // 避免对 Responses→Responses 的链路重复执行搜索回环;
203
+ // 其它场景(例如 /v1/responses → gemini/glm 后端)仍允许 server-side web_search 生效。
204
+ const entry = (options.entryEndpoint || '').toLowerCase();
205
+ if (options.providerProtocol === 'openai-responses' && entry.includes('/v1/responses')) {
206
+ return { mode: 'passthrough', finalChatResponse: base };
207
+ }
208
+ // Feature flag: keep behaviour fully backwards-compatible unless explicitly enabled.
209
+ const toolsEnabled = resolveEnvServerSideToolsEnabled();
210
+ const toolCalls = extractToolCalls(base);
211
+ const webSearchCall = toolCalls.find((tc) => tc.name === 'web_search');
212
+ if (!toolsEnabled || !webSearchCall || !options.providerInvoker) {
213
+ return { mode: 'passthrough', finalChatResponse: base };
214
+ }
215
+ const webSearchConfig = getWebSearchConfig(options.adapterContext);
216
+ if (!webSearchConfig) {
217
+ return { mode: 'passthrough', finalChatResponse: base };
218
+ }
219
+ let parsedArgs = {};
220
+ if (webSearchCall.arguments && typeof webSearchCall.arguments === 'string') {
221
+ try {
222
+ parsedArgs = JSON.parse(webSearchCall.arguments);
223
+ }
224
+ catch {
225
+ parsedArgs = {};
226
+ }
227
+ }
228
+ const query = typeof parsedArgs?.query === 'string' && parsedArgs.query.trim()
229
+ ? parsedArgs.query.trim()
230
+ : undefined;
231
+ const engineId = typeof parsedArgs?.engine === 'string' && parsedArgs.engine.trim()
232
+ ? parsedArgs.engine.trim()
233
+ : undefined;
234
+ const recency = typeof parsedArgs?.recency === 'string' && parsedArgs.recency.trim()
235
+ ? parsedArgs.recency.trim()
236
+ : undefined;
237
+ const count = typeof parsedArgs?.count === 'number' && Number.isFinite(parsedArgs.count)
238
+ ? Math.floor(parsedArgs.count)
239
+ : undefined;
240
+ if (!query) {
241
+ return { mode: 'passthrough', finalChatResponse: base };
242
+ }
243
+ const engine = resolveWebSearchEngine(webSearchConfig, engineId);
244
+ if (!engine) {
245
+ return { mode: 'passthrough', finalChatResponse: base };
246
+ }
247
+ const providerInvoker = options.providerInvoker;
248
+ // 1) Call search backend (secondary request)
249
+ let searchSummary = '';
250
+ try {
251
+ logServerToolWebSearch(engine, options.requestId, query);
252
+ if (isGeminiWebSearchEngine(engine)) {
253
+ const geminiPayload = {
254
+ model: engine.id,
255
+ contents: [
256
+ {
257
+ role: 'user',
258
+ parts: [
259
+ {
260
+ text: query
261
+ }
262
+ ]
263
+ }
264
+ ],
265
+ // Cloud Code search models treat googleSearch as the web search tool.
266
+ tools: [
267
+ {
268
+ googleSearch: {}
269
+ }
270
+ ]
271
+ };
272
+ const backend = await providerInvoker({
273
+ providerKey: engine.providerKey,
274
+ providerType: undefined,
275
+ modelId: engine.id,
276
+ providerProtocol: 'gemini-chat',
277
+ payload: geminiPayload,
278
+ entryEndpoint: '/v1/models/gemini:generateContent',
279
+ requestId: `${options.requestId}:web_search:${engine.id}`
280
+ });
281
+ const backendResponse = asObject(backend.providerResponse);
282
+ if (backendResponse) {
283
+ const chatLike = asObject(buildOpenAIChatFromGeminiResponse(backendResponse));
284
+ if (chatLike) {
285
+ searchSummary = extractTextFromChatLike(chatLike);
286
+ }
287
+ }
288
+ }
289
+ else {
290
+ const backendPayload = {
291
+ model: engine.providerKey,
292
+ messages: [
293
+ {
294
+ role: 'system',
295
+ content: 'You are a web search engine. Answer with up-to-date information based on the open internet.'
296
+ },
297
+ {
298
+ role: 'user',
299
+ content: query
300
+ }
301
+ ],
302
+ stream: false,
303
+ web_search: {
304
+ query,
305
+ ...(recency ? { recency } : {}),
306
+ ...(typeof count === 'number' ? { count } : {}),
307
+ engine: engine.id
308
+ }
309
+ };
310
+ const backend = await providerInvoker({
311
+ providerKey: engine.providerKey,
312
+ providerType: undefined,
313
+ modelId: undefined,
314
+ providerProtocol: options.providerProtocol,
315
+ payload: backendPayload,
316
+ entryEndpoint: '/v1/chat/completions',
317
+ requestId: `${options.requestId}:web_search:${engine.id}`
318
+ });
319
+ const backendResponse = asObject(backend.providerResponse);
320
+ if (backendResponse) {
321
+ searchSummary = extractTextFromChatLike(backendResponse);
322
+ }
323
+ }
324
+ }
325
+ catch {
326
+ // fall back to passthrough if backend fails
327
+ return { mode: 'passthrough', finalChatResponse: base };
328
+ }
329
+ if (!searchSummary) {
330
+ return { mode: 'passthrough', finalChatResponse: base };
331
+ }
332
+ // 2) Call main provider again with synthesized prompt (third request)
333
+ const ctxTarget = options.adapterContext.target;
334
+ const target = ctxTarget && typeof ctxTarget === 'object' && !Array.isArray(ctxTarget)
335
+ ? ctxTarget
336
+ : undefined;
337
+ const mainProviderKey = typeof target?.providerKey === 'string' && target.providerKey.trim()
338
+ ? target.providerKey.trim()
339
+ : undefined;
340
+ const mainModelId = (typeof base.model === 'string' && base.model.trim()
341
+ ? base.model.trim()
342
+ : typeof target?.modelId === 'string' && target.modelId.trim()
343
+ ? target.modelId.trim()
344
+ : undefined) ?? 'gpt-4o-mini';
345
+ if (!mainProviderKey) {
346
+ return { mode: 'passthrough', finalChatResponse: base };
347
+ }
348
+ let finalResponse = base;
349
+ try {
350
+ const followupPayload = {
351
+ model: mainModelId,
352
+ messages: [
353
+ {
354
+ role: 'system',
355
+ content: 'You are an assistant that answers using the provided web_search results. Use them as the primary source.'
356
+ },
357
+ {
358
+ role: 'user',
359
+ content: `User question: ${query}\n\nWeb search results:\n${searchSummary}`
360
+ }
361
+ ],
362
+ stream: false
363
+ };
364
+ const followup = await providerInvoker({
365
+ providerKey: mainProviderKey,
366
+ providerType: undefined,
367
+ modelId: mainModelId,
368
+ providerProtocol: options.providerProtocol,
369
+ payload: followupPayload,
370
+ entryEndpoint: '/v1/chat/completions',
371
+ requestId: `${options.requestId}:web_search_followup`
372
+ });
373
+ const followupResponse = asObject(followup.providerResponse);
374
+ if (followupResponse) {
375
+ finalResponse = followupResponse;
376
+ }
377
+ }
378
+ catch {
379
+ // If follow-up fails, keep original base response to avoid breaking clients.
380
+ finalResponse = base;
381
+ }
382
+ return { mode: 'web_search_flow', finalChatResponse: finalResponse };
383
+ }