@jsonstudio/rcc 0.90.876 → 0.90.1270

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 (833) hide show
  1. package/README.md +5 -6
  2. package/configsamples/provider-default/ali-coding-plan/config.v2.json +6 -1
  3. package/configsamples/provider-default/antigravity/config.v2.json +6 -1
  4. package/configsamples/provider-default/ark-coding-plan/config.v2.json +7 -2
  5. package/configsamples/provider-default/crs/config.v2.json +6 -1
  6. package/configsamples/provider-default/deepseek-web/config.v2.json +6 -1
  7. package/configsamples/provider-default/gemini/config.v2.json +6 -1
  8. package/configsamples/provider-default/gemini-cli/config.v2.json +6 -1
  9. package/configsamples/provider-default/gemini-native/config.v2.json +6 -1
  10. package/configsamples/provider-default/glm/config.v2.json +7 -2
  11. package/configsamples/provider-default/glm-anthropic/config.v2.json +6 -1
  12. package/configsamples/provider-default/kimi/config.v2.json +7 -2
  13. package/configsamples/provider-default/lmstudio/config.v2.json +6 -1
  14. package/configsamples/provider-default/lmstudio-proxy/config.v2.json +6 -1
  15. package/configsamples/provider-default/manifest.json +0 -1
  16. package/configsamples/provider-default/meituan/config.v2.json +6 -1
  17. package/configsamples/provider-default/mimo/config.v2.json +7 -2
  18. package/configsamples/provider-default/modelscope/config.v2.json +7 -2
  19. package/configsamples/provider-default/my-openai/config.v2.json +6 -1
  20. package/configsamples/provider-default/nvidia/config.v2.json +7 -2
  21. package/configsamples/provider-default/opencode-zen-free/config.v2.json +6 -1
  22. package/configsamples/provider-default/openrouter/config.v2.json +6 -1
  23. package/configsamples/provider-default/qwen/config.v2.json +11 -1
  24. package/configsamples/provider-default/tab/config.v2.json +6 -1
  25. package/configsamples/provider-default/tabglm/config.v2.json +7 -2
  26. package/dist/build-info.js +2 -2
  27. package/dist/build-info.js.map +1 -1
  28. package/dist/cli/commands/camoufox.js +44 -3
  29. package/dist/cli/commands/camoufox.js.map +1 -1
  30. package/dist/cli/commands/config.js +2 -2
  31. package/dist/cli/commands/config.js.map +1 -1
  32. package/dist/cli/commands/heartbeat.js +82 -27
  33. package/dist/cli/commands/heartbeat.js.map +1 -1
  34. package/dist/cli/commands/init.js +1 -2
  35. package/dist/cli/commands/init.js.map +1 -1
  36. package/dist/cli/commands/launcher/utils.js +37 -24
  37. package/dist/cli/commands/launcher/utils.js.map +1 -1
  38. package/dist/cli/commands/launcher-kernel.js +6 -3
  39. package/dist/cli/commands/launcher-kernel.js.map +1 -1
  40. package/dist/cli/commands/restart.js +102 -31
  41. package/dist/cli/commands/restart.js.map +1 -1
  42. package/dist/cli/commands/start-types.d.ts +1 -0
  43. package/dist/cli/commands/start-utils.d.ts +1 -0
  44. package/dist/cli/commands/start-utils.js +3 -0
  45. package/dist/cli/commands/start-utils.js.map +1 -1
  46. package/dist/cli/commands/start.js +217 -51
  47. package/dist/cli/commands/start.js.map +1 -1
  48. package/dist/cli/commands/status.js +48 -9
  49. package/dist/cli/commands/status.js.map +1 -1
  50. package/dist/cli/config/bootstrap-provider-templates.js +1 -1
  51. package/dist/cli/config/bootstrap-provider-templates.js.map +1 -1
  52. package/dist/cli/config/init-provider-catalog.js +3 -50
  53. package/dist/cli/config/init-provider-catalog.js.map +1 -1
  54. package/dist/cli/config/init-v2-builder.js +0 -1
  55. package/dist/cli/config/init-v2-builder.js.map +1 -1
  56. package/dist/cli/guardian/client.js +40 -18
  57. package/dist/cli/guardian/client.js.map +1 -1
  58. package/dist/cli/server/port-utils.d.ts +5 -0
  59. package/dist/cli/server/port-utils.js +45 -31
  60. package/dist/cli/server/port-utils.js.map +1 -1
  61. package/dist/commands/camoufox-fp.js +1 -1
  62. package/dist/commands/camoufox-fp.js.map +1 -1
  63. package/dist/commands/oauth.js +48 -64
  64. package/dist/commands/oauth.js.map +1 -1
  65. package/dist/commands/provider-update-maintenance.js +4 -4
  66. package/dist/commands/provider-update-maintenance.js.map +1 -1
  67. package/dist/commands/token-daemon.js +38 -10
  68. package/dist/commands/token-daemon.js.map +1 -1
  69. package/dist/commands/validate.js +31 -3
  70. package/dist/commands/validate.js.map +1 -1
  71. package/dist/config/provider-v2-loader.d.ts +5 -2
  72. package/dist/config/provider-v2-loader.js +80 -26
  73. package/dist/config/provider-v2-loader.js.map +1 -1
  74. package/dist/config/routecodex-config-loader.d.ts +1 -0
  75. package/dist/config/routecodex-config-loader.js +18 -207
  76. package/dist/config/routecodex-config-loader.js.map +1 -1
  77. package/dist/config/virtual-router-builder.d.ts +3 -2
  78. package/dist/config/virtual-router-builder.js +4 -214
  79. package/dist/config/virtual-router-builder.js.map +1 -1
  80. package/dist/constants/index.d.ts +2 -3
  81. package/dist/constants/index.js +2 -4
  82. package/dist/constants/index.js.map +1 -1
  83. package/dist/error-handling/route-error-hub.js +1 -0
  84. package/dist/error-handling/route-error-hub.js.map +1 -1
  85. package/dist/index.js +98 -21
  86. package/dist/index.js.map +1 -1
  87. package/dist/manager/modules/quota/antigravity-quota-manager.d.ts +1 -1
  88. package/dist/manager/modules/quota/antigravity-quota-manager.js +21 -12
  89. package/dist/manager/modules/quota/antigravity-quota-manager.js.map +1 -1
  90. package/dist/manager/modules/quota/antigravity-quota-runtime.d.ts +1 -1
  91. package/dist/manager/modules/quota/antigravity-quota-runtime.js +32 -45
  92. package/dist/manager/modules/quota/antigravity-quota-runtime.js.map +1 -1
  93. package/dist/manager/modules/quota/provider-key-normalization.js +10 -1
  94. package/dist/manager/modules/quota/provider-key-normalization.js.map +1 -1
  95. package/dist/manager/modules/quota/provider-quota-daemon.d.ts +2 -1
  96. package/dist/manager/modules/quota/provider-quota-daemon.error-helpers.d.ts +1 -1
  97. package/dist/manager/modules/quota/provider-quota-daemon.error-helpers.js +22 -12
  98. package/dist/manager/modules/quota/provider-quota-daemon.error-helpers.js.map +1 -1
  99. package/dist/manager/modules/quota/provider-quota-daemon.events.js +69 -33
  100. package/dist/manager/modules/quota/provider-quota-daemon.events.js.map +1 -1
  101. package/dist/manager/modules/quota/provider-quota-daemon.js +47 -35
  102. package/dist/manager/modules/quota/provider-quota-daemon.js.map +1 -1
  103. package/dist/manager/storage/file-store.js +3 -0
  104. package/dist/manager/storage/file-store.js.map +1 -1
  105. package/dist/modules/llmswitch/bridge/antigravity-signature.js +58 -20
  106. package/dist/modules/llmswitch/bridge/antigravity-signature.js.map +1 -1
  107. package/dist/modules/llmswitch/bridge/index.d.ts +1 -1
  108. package/dist/modules/llmswitch/bridge/index.js +1 -1
  109. package/dist/modules/llmswitch/bridge/index.js.map +1 -1
  110. package/dist/modules/llmswitch/bridge/runtime-integrations.d.ts +22 -16
  111. package/dist/modules/llmswitch/bridge/runtime-integrations.js +89 -30
  112. package/dist/modules/llmswitch/bridge/runtime-integrations.js.map +1 -1
  113. package/dist/modules/llmswitch/bridge/snapshot-recorder-runtime.js +10 -9
  114. package/dist/modules/llmswitch/bridge/snapshot-recorder-runtime.js.map +1 -1
  115. package/dist/modules/llmswitch/bridge/snapshot-recorder.js +3 -0
  116. package/dist/modules/llmswitch/bridge/snapshot-recorder.js.map +1 -1
  117. package/dist/modules/llmswitch/bridge/state-integrations.d.ts +1 -0
  118. package/dist/modules/llmswitch/bridge/state-integrations.js +263 -51
  119. package/dist/modules/llmswitch/bridge/state-integrations.js.map +1 -1
  120. package/dist/modules/llmswitch/bridge.d.ts +2 -2
  121. package/dist/modules/llmswitch/bridge.js +2 -2
  122. package/dist/modules/llmswitch/bridge.js.map +1 -1
  123. package/dist/provider-sdk/provider-add-template.d.ts +1 -1
  124. package/dist/provider-sdk/provider-add-template.js.map +1 -1
  125. package/dist/provider-sdk/provider-runtime-inference.js +48 -13
  126. package/dist/provider-sdk/provider-runtime-inference.js.map +1 -1
  127. package/dist/providers/auth/deepseek-account-token-acquirer.d.ts +24 -0
  128. package/dist/providers/auth/deepseek-account-token-acquirer.js +42 -13
  129. package/dist/providers/auth/deepseek-account-token-acquirer.js.map +1 -1
  130. package/dist/providers/auth/oauth-auth.js +12 -5
  131. package/dist/providers/auth/oauth-auth.js.map +1 -1
  132. package/dist/providers/auth/oauth-lifecycle/path-resolver.d.ts +0 -1
  133. package/dist/providers/auth/oauth-lifecycle/path-resolver.js +10 -9
  134. package/dist/providers/auth/oauth-lifecycle/path-resolver.js.map +1 -1
  135. package/dist/providers/auth/oauth-lifecycle/token-helpers.js +0 -1
  136. package/dist/providers/auth/oauth-lifecycle/token-helpers.js.map +1 -1
  137. package/dist/providers/auth/oauth-lifecycle/token-io.js +18 -8
  138. package/dist/providers/auth/oauth-lifecycle/token-io.js.map +1 -1
  139. package/dist/providers/auth/oauth-lifecycle.d.ts +5 -0
  140. package/dist/providers/auth/oauth-lifecycle.js +370 -353
  141. package/dist/providers/auth/oauth-lifecycle.js.map +1 -1
  142. package/dist/providers/auth/oauth-repair-env.js +0 -26
  143. package/dist/providers/auth/oauth-repair-env.js.map +1 -1
  144. package/dist/providers/auth/qwen-userinfo-helper.d.ts +11 -0
  145. package/dist/providers/auth/qwen-userinfo-helper.js +85 -13
  146. package/dist/providers/auth/qwen-userinfo-helper.js.map +1 -1
  147. package/dist/providers/auth/token-refresh/token-state.js +1 -4
  148. package/dist/providers/auth/token-refresh/token-state.js.map +1 -1
  149. package/dist/providers/auth/token-scanner/index.d.ts +1 -1
  150. package/dist/providers/auth/token-scanner/index.js +2 -2
  151. package/dist/providers/auth/token-storage/token-file-resolver.js +0 -3
  152. package/dist/providers/auth/token-storage/token-file-resolver.js.map +1 -1
  153. package/dist/providers/auth/token-storage/token-persistence.js +10 -3
  154. package/dist/providers/auth/token-storage/token-persistence.js.map +1 -1
  155. package/dist/providers/auth/tokenfile-auth.d.ts +0 -1
  156. package/dist/providers/auth/tokenfile-auth.js +23 -30
  157. package/dist/providers/auth/tokenfile-auth.js.map +1 -1
  158. package/dist/providers/core/api/provider-config.d.ts +1 -1
  159. package/dist/providers/core/api/provider-types.d.ts +2 -1
  160. package/dist/providers/core/config/camoufox-actions.js +23 -15
  161. package/dist/providers/core/config/camoufox-actions.js.map +1 -1
  162. package/dist/providers/core/config/camoufox-launcher.js +235 -121
  163. package/dist/providers/core/config/camoufox-launcher.js.map +1 -1
  164. package/dist/providers/core/config/oauth-flows.js +23 -1
  165. package/dist/providers/core/config/oauth-flows.js.map +1 -1
  166. package/dist/providers/core/config/provider-oauth-configs.js +2 -93
  167. package/dist/providers/core/config/provider-oauth-configs.js.map +1 -1
  168. package/dist/providers/core/config/service-profiles.d.ts +0 -1
  169. package/dist/providers/core/config/service-profiles.js +23 -66
  170. package/dist/providers/core/config/service-profiles.js.map +1 -1
  171. package/dist/providers/core/runtime/base-provider-runtime-helpers.js +4 -1
  172. package/dist/providers/core/runtime/base-provider-runtime-helpers.js.map +1 -1
  173. package/dist/providers/core/runtime/base-provider.js +21 -11
  174. package/dist/providers/core/runtime/base-provider.js.map +1 -1
  175. package/dist/providers/core/runtime/deepseek-http-provider-helpers.d.ts +1 -0
  176. package/dist/providers/core/runtime/deepseek-http-provider-helpers.js +28 -0
  177. package/dist/providers/core/runtime/deepseek-http-provider-helpers.js.map +1 -1
  178. package/dist/providers/core/runtime/deepseek-http-provider.d.ts +0 -2
  179. package/dist/providers/core/runtime/deepseek-http-provider.js +3 -33
  180. package/dist/providers/core/runtime/deepseek-http-provider.js.map +1 -1
  181. package/dist/providers/core/runtime/http-request-executor.d.ts +1 -0
  182. package/dist/providers/core/runtime/http-request-executor.js +131 -47
  183. package/dist/providers/core/runtime/http-request-executor.js.map +1 -1
  184. package/dist/providers/core/runtime/http-transport-provider.d.ts +5 -5
  185. package/dist/providers/core/runtime/http-transport-provider.js +97 -38
  186. package/dist/providers/core/runtime/http-transport-provider.js.map +1 -1
  187. package/dist/providers/core/runtime/openai-responses-sdk-transport.js +2 -1
  188. package/dist/providers/core/runtime/openai-responses-sdk-transport.js.map +1 -1
  189. package/dist/providers/core/runtime/provider-error-classifier.js +19 -126
  190. package/dist/providers/core/runtime/provider-error-classifier.js.map +1 -1
  191. package/dist/providers/core/runtime/provider-factory-helpers.d.ts +1 -0
  192. package/dist/providers/core/runtime/provider-factory-helpers.js +8 -12
  193. package/dist/providers/core/runtime/provider-factory-helpers.js.map +1 -1
  194. package/dist/providers/core/runtime/provider-factory.js +2 -9
  195. package/dist/providers/core/runtime/provider-factory.js.map +1 -1
  196. package/dist/providers/core/runtime/provider-failure-policy.d.ts +135 -0
  197. package/dist/providers/core/runtime/provider-failure-policy.js +685 -0
  198. package/dist/providers/core/runtime/provider-failure-policy.js.map +1 -0
  199. package/dist/providers/core/runtime/provider-family-profile-utils.d.ts +0 -10
  200. package/dist/providers/core/runtime/provider-family-profile-utils.js +0 -28
  201. package/dist/providers/core/runtime/provider-family-profile-utils.js.map +1 -1
  202. package/dist/providers/core/runtime/provider-http-executor-utils.js +40 -1
  203. package/dist/providers/core/runtime/provider-http-executor-utils.js.map +1 -1
  204. package/dist/providers/core/runtime/provider-request-header-orchestrator.d.ts +0 -2
  205. package/dist/providers/core/runtime/provider-request-header-orchestrator.js +35 -8
  206. package/dist/providers/core/runtime/provider-request-header-orchestrator.js.map +1 -1
  207. package/dist/providers/core/runtime/provider-response-postprocessor.js +3 -23
  208. package/dist/providers/core/runtime/provider-response-postprocessor.js.map +1 -1
  209. package/dist/providers/core/runtime/provider-runtime-utils.js +4 -1
  210. package/dist/providers/core/runtime/provider-runtime-utils.js.map +1 -1
  211. package/dist/providers/core/runtime/provider-startup-tasks.js +18 -2
  212. package/dist/providers/core/runtime/provider-startup-tasks.js.map +1 -1
  213. package/dist/providers/core/runtime/responses-provider-helpers.d.ts +1 -0
  214. package/dist/providers/core/runtime/responses-provider-helpers.js +11 -12
  215. package/dist/providers/core/runtime/responses-provider-helpers.js.map +1 -1
  216. package/dist/providers/core/runtime/responses-provider.js +15 -10
  217. package/dist/providers/core/runtime/responses-provider.js.map +1 -1
  218. package/dist/providers/core/runtime/transport/auth-provider-factory.d.ts +0 -1
  219. package/dist/providers/core/runtime/transport/auth-provider-factory.js +1 -15
  220. package/dist/providers/core/runtime/transport/auth-provider-factory.js.map +1 -1
  221. package/dist/providers/core/runtime/transport/index.d.ts +0 -1
  222. package/dist/providers/core/runtime/transport/index.js +0 -1
  223. package/dist/providers/core/runtime/transport/index.js.map +1 -1
  224. package/dist/providers/core/runtime/transport/oauth-recovery-handler.d.ts +2 -0
  225. package/dist/providers/core/runtime/transport/oauth-recovery-handler.js +76 -5
  226. package/dist/providers/core/runtime/transport/oauth-recovery-handler.js.map +1 -1
  227. package/dist/providers/core/runtime/transport/request-header-builder.d.ts +0 -1
  228. package/dist/providers/core/runtime/transport/request-header-builder.js +1 -7
  229. package/dist/providers/core/runtime/transport/request-header-builder.js.map +1 -1
  230. package/dist/providers/core/runtime/transport/runtime-detector.d.ts +0 -2
  231. package/dist/providers/core/runtime/transport/runtime-detector.js +0 -20
  232. package/dist/providers/core/runtime/transport/runtime-detector.js.map +1 -1
  233. package/dist/providers/core/runtime/transport/session-header-utils.d.ts +6 -0
  234. package/dist/providers/core/runtime/transport/session-header-utils.js +61 -2
  235. package/dist/providers/core/runtime/transport/session-header-utils.js.map +1 -1
  236. package/dist/providers/core/runtime/vercel-ai-sdk/anthropic-sdk-request-exec.js +2 -1
  237. package/dist/providers/core/runtime/vercel-ai-sdk/anthropic-sdk-request-exec.js.map +1 -1
  238. package/dist/providers/core/runtime/vercel-ai-sdk/openai-sdk-transport.js +2 -1
  239. package/dist/providers/core/runtime/vercel-ai-sdk/openai-sdk-transport.js.map +1 -1
  240. package/dist/providers/core/strategies/oauth-auth-code-flow.d.ts +1 -4
  241. package/dist/providers/core/strategies/oauth-auth-code-flow.js +26 -84
  242. package/dist/providers/core/strategies/oauth-auth-code-flow.js.map +1 -1
  243. package/dist/providers/core/strategies/oauth-device-flow.d.ts +2 -0
  244. package/dist/providers/core/strategies/oauth-device-flow.js +43 -8
  245. package/dist/providers/core/strategies/oauth-device-flow.js.map +1 -1
  246. package/dist/providers/core/utils/http-client.d.ts +7 -5
  247. package/dist/providers/core/utils/http-client.js +108 -33
  248. package/dist/providers/core/utils/http-client.js.map +1 -1
  249. package/dist/providers/core/utils/provider-error-reporter.d.ts +2 -2
  250. package/dist/providers/core/utils/provider-error-reporter.js +9 -85
  251. package/dist/providers/core/utils/provider-error-reporter.js.map +1 -1
  252. package/dist/providers/core/utils/provider-type-utils.js +1 -3
  253. package/dist/providers/core/utils/provider-type-utils.js.map +1 -1
  254. package/dist/providers/core/utils/qwen-client-fingerprint.d.ts +15 -0
  255. package/dist/providers/core/utils/qwen-client-fingerprint.js +47 -0
  256. package/dist/providers/core/utils/qwen-client-fingerprint.js.map +1 -0
  257. package/dist/providers/core/utils/snapshot-writer.d.ts +3 -0
  258. package/dist/providers/core/utils/snapshot-writer.js +385 -26
  259. package/dist/providers/core/utils/snapshot-writer.js.map +1 -1
  260. package/dist/providers/profile/families/qwen-profile.js +285 -22
  261. package/dist/providers/profile/families/qwen-profile.js.map +1 -1
  262. package/dist/providers/profile/profile-registry.js +0 -2
  263. package/dist/providers/profile/profile-registry.js.map +1 -1
  264. package/dist/providers/profile/provider-directory.js +0 -1
  265. package/dist/providers/profile/provider-directory.js.map +1 -1
  266. package/dist/providers/profile/provider-profile-loader.js +1 -1
  267. package/dist/providers/profile/provider-profile-loader.js.map +1 -1
  268. package/dist/server/handlers/chat-handler.js +6 -5
  269. package/dist/server/handlers/chat-handler.js.map +1 -1
  270. package/dist/server/handlers/config-admin-handler.js +44 -69
  271. package/dist/server/handlers/config-admin-handler.js.map +1 -1
  272. package/dist/server/handlers/handler-response-utils.js +190 -27
  273. package/dist/server/handlers/handler-response-utils.js.map +1 -1
  274. package/dist/server/handlers/handler-utils.d.ts +3 -0
  275. package/dist/server/handlers/handler-utils.js +72 -0
  276. package/dist/server/handlers/handler-utils.js.map +1 -1
  277. package/dist/server/handlers/images-handler.js +7 -7
  278. package/dist/server/handlers/images-handler.js.map +1 -1
  279. package/dist/server/handlers/messages-handler.js +6 -5
  280. package/dist/server/handlers/messages-handler.js.map +1 -1
  281. package/dist/server/handlers/responses-handler.js +32 -14
  282. package/dist/server/handlers/responses-handler.js.map +1 -1
  283. package/dist/server/handlers/sse-dispatcher.js +55 -13
  284. package/dist/server/handlers/sse-dispatcher.js.map +1 -1
  285. package/dist/server/handlers/types.d.ts +12 -0
  286. package/dist/server/runtime/http-server/daemon-admin/auth-handler.js +5 -2
  287. package/dist/server/runtime/http-server/daemon-admin/auth-handler.js.map +1 -1
  288. package/dist/server/runtime/http-server/daemon-admin/control-handler.js +62 -18
  289. package/dist/server/runtime/http-server/daemon-admin/control-handler.js.map +1 -1
  290. package/dist/server/runtime/http-server/daemon-admin/credentials-handler-utils.js +1 -1
  291. package/dist/server/runtime/http-server/daemon-admin/credentials-handler-utils.js.map +1 -1
  292. package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js +9 -9
  293. package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js.map +1 -1
  294. package/dist/server/runtime/http-server/daemon-admin/providers-handler-routing-utils.js +36 -10
  295. package/dist/server/runtime/http-server/daemon-admin/providers-handler-routing-utils.js.map +1 -1
  296. package/dist/server/runtime/http-server/daemon-admin/providers-handler.js +11 -11
  297. package/dist/server/runtime/http-server/daemon-admin/providers-handler.js.map +1 -1
  298. package/dist/server/runtime/http-server/daemon-admin/quota-handler.js +49 -8
  299. package/dist/server/runtime/http-server/daemon-admin/quota-handler.js.map +1 -1
  300. package/dist/server/runtime/http-server/daemon-admin-routes.d.ts +1 -0
  301. package/dist/server/runtime/http-server/daemon-admin-routes.js +46 -0
  302. package/dist/server/runtime/http-server/daemon-admin-routes.js.map +1 -1
  303. package/dist/server/runtime/http-server/executor/client-injection-flow.js +2 -0
  304. package/dist/server/runtime/http-server/executor/client-injection-flow.js.map +1 -1
  305. package/dist/server/runtime/http-server/executor/log-rollup.d.ts +38 -0
  306. package/dist/server/runtime/http-server/executor/log-rollup.js +775 -0
  307. package/dist/server/runtime/http-server/executor/log-rollup.js.map +1 -0
  308. package/dist/server/runtime/http-server/executor/provider-response-converter.js +654 -281
  309. package/dist/server/runtime/http-server/executor/provider-response-converter.js.map +1 -1
  310. package/dist/server/runtime/http-server/executor/provider-response-utils.js +34 -3
  311. package/dist/server/runtime/http-server/executor/provider-response-utils.js.map +1 -1
  312. package/dist/server/runtime/http-server/executor/provider-runtime-resolver.js +14 -68
  313. package/dist/server/runtime/http-server/executor/provider-runtime-resolver.js.map +1 -1
  314. package/dist/server/runtime/http-server/executor/request-executor-core-utils.js +26 -2
  315. package/dist/server/runtime/http-server/executor/request-executor-core-utils.js.map +1 -1
  316. package/dist/server/runtime/http-server/executor/request-retry-helpers.js +20 -2
  317. package/dist/server/runtime/http-server/executor/request-retry-helpers.js.map +1 -1
  318. package/dist/server/runtime/http-server/executor/servertool-adapter-context.d.ts +10 -0
  319. package/dist/server/runtime/http-server/executor/servertool-adapter-context.js +120 -0
  320. package/dist/server/runtime/http-server/executor/servertool-adapter-context.js.map +1 -0
  321. package/dist/server/runtime/http-server/executor/servertool-followup-dispatch.d.ts +35 -0
  322. package/dist/server/runtime/http-server/executor/servertool-followup-dispatch.js +101 -0
  323. package/dist/server/runtime/http-server/executor/servertool-followup-dispatch.js.map +1 -0
  324. package/dist/server/runtime/http-server/executor/servertool-followup-error.d.ts +46 -0
  325. package/dist/server/runtime/http-server/executor/servertool-followup-error.js +127 -0
  326. package/dist/server/runtime/http-server/executor/servertool-followup-error.js.map +1 -0
  327. package/dist/server/runtime/http-server/executor/servertool-followup-metadata.d.ts +7 -0
  328. package/dist/server/runtime/http-server/executor/servertool-followup-metadata.js +186 -0
  329. package/dist/server/runtime/http-server/executor/servertool-followup-metadata.js.map +1 -0
  330. package/dist/server/runtime/http-server/executor/servertool-request-normalizer.d.ts +2 -0
  331. package/dist/server/runtime/http-server/executor/servertool-request-normalizer.js +56 -0
  332. package/dist/server/runtime/http-server/executor/servertool-request-normalizer.js.map +1 -0
  333. package/dist/server/runtime/http-server/executor/servertool-response-normalizer.d.ts +8 -0
  334. package/dist/server/runtime/http-server/executor/servertool-response-normalizer.js +31 -0
  335. package/dist/server/runtime/http-server/executor/servertool-response-normalizer.js.map +1 -0
  336. package/dist/server/runtime/http-server/executor/servertool-runtime-log.d.ts +8 -0
  337. package/dist/server/runtime/http-server/executor/servertool-runtime-log.js +33 -0
  338. package/dist/server/runtime/http-server/executor/servertool-runtime-log.js.map +1 -0
  339. package/dist/server/runtime/http-server/executor/sse-error-handler.js +37 -0
  340. package/dist/server/runtime/http-server/executor/sse-error-handler.js.map +1 -1
  341. package/dist/server/runtime/http-server/executor/usage-aggregator.js +32 -2
  342. package/dist/server/runtime/http-server/executor/usage-aggregator.js.map +1 -1
  343. package/dist/server/runtime/http-server/executor/usage-logger.d.ts +12 -0
  344. package/dist/server/runtime/http-server/executor/usage-logger.js +56 -1
  345. package/dist/server/runtime/http-server/executor/usage-logger.js.map +1 -1
  346. package/dist/server/runtime/http-server/executor-metadata.d.ts +15 -0
  347. package/dist/server/runtime/http-server/executor-metadata.js +60 -18
  348. package/dist/server/runtime/http-server/executor-metadata.js.map +1 -1
  349. package/dist/server/runtime/http-server/executor-provider.d.ts +2 -0
  350. package/dist/server/runtime/http-server/executor-provider.js +88 -205
  351. package/dist/server/runtime/http-server/executor-provider.js.map +1 -1
  352. package/dist/server/runtime/http-server/executor-response.js +30 -149
  353. package/dist/server/runtime/http-server/executor-response.js.map +1 -1
  354. package/dist/server/runtime/http-server/http-server-bootstrap.js +53 -17
  355. package/dist/server/runtime/http-server/http-server-bootstrap.js.map +1 -1
  356. package/dist/server/runtime/http-server/http-server-legacy-pipeline.js +28 -1
  357. package/dist/server/runtime/http-server/http-server-legacy-pipeline.js.map +1 -1
  358. package/dist/server/runtime/http-server/http-server-lifecycle.js +17 -4
  359. package/dist/server/runtime/http-server/http-server-lifecycle.js.map +1 -1
  360. package/dist/server/runtime/http-server/http-server-runtime-providers.js +42 -13
  361. package/dist/server/runtime/http-server/http-server-runtime-providers.js.map +1 -1
  362. package/dist/server/runtime/http-server/http-server-runtime-setup.js +40 -2
  363. package/dist/server/runtime/http-server/http-server-runtime-setup.js.map +1 -1
  364. package/dist/server/runtime/http-server/hub-shadow-compare.js +8 -4
  365. package/dist/server/runtime/http-server/hub-shadow-compare.js.map +1 -1
  366. package/dist/server/runtime/http-server/managed-process-probe.js +30 -4
  367. package/dist/server/runtime/http-server/managed-process-probe.js.map +1 -1
  368. package/dist/server/runtime/http-server/middleware.js +32 -4
  369. package/dist/server/runtime/http-server/middleware.js.map +1 -1
  370. package/dist/server/runtime/http-server/provider-traffic-governor.d.ts +45 -1
  371. package/dist/server/runtime/http-server/provider-traffic-governor.js +697 -111
  372. package/dist/server/runtime/http-server/provider-traffic-governor.js.map +1 -1
  373. package/dist/server/runtime/http-server/provider-utils.js +2 -6
  374. package/dist/server/runtime/http-server/provider-utils.js.map +1 -1
  375. package/dist/server/runtime/http-server/request-activity-tracker.d.ts +4 -0
  376. package/dist/server/runtime/http-server/request-activity-tracker.js +54 -11
  377. package/dist/server/runtime/http-server/request-activity-tracker.js.map +1 -1
  378. package/dist/server/runtime/http-server/request-executor.d.ts +247 -0
  379. package/dist/server/runtime/http-server/request-executor.js +2444 -334
  380. package/dist/server/runtime/http-server/request-executor.js.map +1 -1
  381. package/dist/server/runtime/http-server/routes.js +59 -16
  382. package/dist/server/runtime/http-server/routes.js.map +1 -1
  383. package/dist/server/runtime/http-server/runtime-manager.js +0 -15
  384. package/dist/server/runtime/http-server/runtime-manager.js.map +1 -1
  385. package/dist/server/runtime/http-server/session-client-registry-utils.js +46 -10
  386. package/dist/server/runtime/http-server/session-client-registry-utils.js.map +1 -1
  387. package/dist/server/runtime/http-server/session-client-registry.js +22 -4
  388. package/dist/server/runtime/http-server/session-client-registry.js.map +1 -1
  389. package/dist/server/runtime/http-server/session-client-routes.js +40 -18
  390. package/dist/server/runtime/http-server/session-client-routes.js.map +1 -1
  391. package/dist/server/runtime/http-server/session-dir.js +35 -2
  392. package/dist/server/runtime/http-server/session-dir.js.map +1 -1
  393. package/dist/server/runtime/http-server/session-scope-resolution.js +38 -9
  394. package/dist/server/runtime/http-server/session-scope-resolution.js.map +1 -1
  395. package/dist/server/runtime/http-server/session-storage-cleanup.js +64 -27
  396. package/dist/server/runtime/http-server/session-storage-cleanup.js.map +1 -1
  397. package/dist/server/runtime/http-server/stats-manager.d.ts +5 -0
  398. package/dist/server/runtime/http-server/stats-manager.js +138 -6
  399. package/dist/server/runtime/http-server/stats-manager.js.map +1 -1
  400. package/dist/server/runtime/http-server/tmux-injection-history.js +30 -4
  401. package/dist/server/runtime/http-server/tmux-injection-history.js.map +1 -1
  402. package/dist/server/runtime/http-server/tmux-session-probe.d.ts +3 -1
  403. package/dist/server/runtime/http-server/tmux-session-probe.js +198 -9
  404. package/dist/server/runtime/http-server/tmux-session-probe.js.map +1 -1
  405. package/dist/server/utils/client-connection-state.d.ts +1 -0
  406. package/dist/server/utils/client-connection-state.js +45 -5
  407. package/dist/server/utils/client-connection-state.js.map +1 -1
  408. package/dist/server/utils/finish-reason.js +61 -2
  409. package/dist/server/utils/finish-reason.js.map +1 -1
  410. package/dist/server/utils/http-error-mapper.d.ts +4 -0
  411. package/dist/server/utils/http-error-mapper.js +31 -6
  412. package/dist/server/utils/http-error-mapper.js.map +1 -1
  413. package/dist/server/utils/stage-logger.js +42 -13
  414. package/dist/server/utils/stage-logger.js.map +1 -1
  415. package/dist/server-lifecycle/port-utils.js +6 -2
  416. package/dist/server-lifecycle/port-utils.js.map +1 -1
  417. package/dist/token-daemon/index.js +44 -15
  418. package/dist/token-daemon/index.js.map +1 -1
  419. package/dist/token-daemon/leader-lock.js +65 -7
  420. package/dist/token-daemon/leader-lock.js.map +1 -1
  421. package/dist/token-daemon/provider-registry.js +1 -1
  422. package/dist/token-daemon/provider-registry.js.map +1 -1
  423. package/dist/token-daemon/server-utils.d.ts +11 -0
  424. package/dist/token-daemon/server-utils.js +71 -18
  425. package/dist/token-daemon/server-utils.js.map +1 -1
  426. package/dist/token-daemon/token-daemon.d.ts +0 -1
  427. package/dist/token-daemon/token-daemon.js +81 -63
  428. package/dist/token-daemon/token-daemon.js.map +1 -1
  429. package/dist/token-daemon/token-types.d.ts +1 -1
  430. package/dist/token-daemon/token-types.js +0 -1
  431. package/dist/token-daemon/token-types.js.map +1 -1
  432. package/dist/token-daemon/token-utils.js +4 -2
  433. package/dist/token-daemon/token-utils.js.map +1 -1
  434. package/dist/tools/provider-update/fetch-models.js +1 -5
  435. package/dist/tools/provider-update/fetch-models.js.map +1 -1
  436. package/dist/utils/error-handler-registry.js +50 -13
  437. package/dist/utils/error-handler-registry.js.map +1 -1
  438. package/dist/utils/errorsamples.d.ts +3 -1
  439. package/dist/utils/errorsamples.js +198 -14
  440. package/dist/utils/errorsamples.js.map +1 -1
  441. package/dist/utils/http-health-probe.d.ts +42 -0
  442. package/dist/utils/http-health-probe.js +231 -0
  443. package/dist/utils/http-health-probe.js.map +1 -0
  444. package/dist/utils/managed-server-pids.js +2 -2
  445. package/dist/utils/managed-server-pids.js.map +1 -1
  446. package/dist/utils/module-config-reader.js +11 -1
  447. package/dist/utils/module-config-reader.js.map +1 -1
  448. package/dist/utils/runtime-package-root.d.ts +2 -0
  449. package/dist/utils/runtime-package-root.js +47 -0
  450. package/dist/utils/runtime-package-root.js.map +1 -0
  451. package/dist/utils/snapshot-local-disk-gate.d.ts +3 -0
  452. package/dist/utils/snapshot-local-disk-gate.js +50 -0
  453. package/dist/utils/snapshot-local-disk-gate.js.map +1 -0
  454. package/dist/utils/snapshot-payload-guard.d.ts +1 -0
  455. package/dist/utils/snapshot-payload-guard.js +234 -0
  456. package/dist/utils/snapshot-payload-guard.js.map +1 -0
  457. package/dist/utils/snapshot-request-retention.d.ts +3 -0
  458. package/dist/utils/snapshot-request-retention.js +128 -0
  459. package/dist/utils/snapshot-request-retention.js.map +1 -0
  460. package/dist/utils/snapshot-stage-policy.d.ts +3 -0
  461. package/dist/utils/snapshot-stage-policy.js +111 -0
  462. package/dist/utils/snapshot-stage-policy.js.map +1 -0
  463. package/dist/utils/snapshot-writer.js +124 -127
  464. package/dist/utils/snapshot-writer.js.map +1 -1
  465. package/docs/CHAT_PROCESS_PROTOCOL_AND_PIPELINE.md +4 -0
  466. package/docs/CONFIG_ARCHITECTURE.md +2 -2
  467. package/docs/INSTALLATION_AND_QUICKSTART.md +5 -5
  468. package/docs/OAUTH.md +2 -5
  469. package/docs/PORTS.md +1 -1
  470. package/docs/PROVIDERS_BUILTIN.md +1 -5
  471. package/docs/PROVIDER_TYPES.md +1 -1
  472. package/docs/agent-routing/10-runtime-ssot-routing.md +4 -0
  473. package/docs/agent-routing/20-build-test-release-routing.md +2 -2
  474. package/docs/agent-routing/30-servertool-lifecycle-routing.md +2 -0
  475. package/docs/agent-routing/40-task-memory-routing.md +22 -2
  476. package/docs/audit/286.1-provider-failure-policy-audit.md +341 -0
  477. package/docs/audits/2026-04-26-fallback-silent-failure-audit.md +119 -0
  478. package/docs/audits/2026-04-27-provider-failure-policy-ssot-audit.md +153 -0
  479. package/docs/chat-process-continuation-state-contract.md +196 -0
  480. package/docs/chat-semantic-expansion-plan.md +2 -0
  481. package/docs/daemon-admin-api-design.md +9 -9
  482. package/docs/design/provider-failure-policy-ssot.md +215 -0
  483. package/docs/design/reasoning-stop-lifecycle.md +90 -0
  484. package/docs/design/servertool-unified-skeleton.md +202 -0
  485. package/docs/design/websearch-servertool-orchestration.md +190 -0
  486. package/docs/error-handling-v2.md +120 -11
  487. package/docs/protocol-compatibility-matrix.md +147 -0
  488. package/docs/providers/provider-composite-design.md +4 -5
  489. package/docs/providers/provider-composite-testing.md +1 -1
  490. package/docs/providers/provider-type-only-migration.md +2 -15
  491. package/docs/refactoring/compatibility-v2-architecture-design.md +1 -3
  492. package/docs/refactoring/host-164.3-responsibility-migration.md +0 -1
  493. package/docs/routing-instructions.md +42 -1
  494. package/docs/stop-message-auto.md +0 -1
  495. package/docs/token-refresh-daemon-plan.md +14 -14
  496. package/docs/v2-architecture/IMPLEMENTATION-ROADMAP.md +1 -1
  497. package/docs/v2-architecture/PROVIDER-V2-CHANGESET-RELEASE-CHECKLIST.md +1 -9
  498. package/docs/v2-architecture/PROVIDER-V2-LAYERING-ADR-DRAFT.md +3 -4
  499. package/docs/v2-architecture/PROVIDER-V2-MIGRATION-MATRIX-DRAFT.md +4 -15
  500. package/docs/v2-architecture/PROVIDER-V2-PHASED-MIGRATION-ROLLBACK-DRAFT.md +4 -5
  501. package/docs/v2-architecture/PROVIDER-V2-PROFILE-API-REGISTRY-DRAFT.md +4 -4
  502. package/docs/v2-architecture/PROVIDER-V2-REFACTOR-OVERVIEW-DRAFT.md +1 -2
  503. package/docs/v2-architecture/PROVIDER-V2-VERIFICATION-MATRIX-DRAFT.md +2 -2
  504. package/node_modules/@jsonstudio/llms/dist/config-unified/unified-config.js +36 -10
  505. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/deepseek-web-request.js +7 -0
  506. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/deepseek-web-response.js +2 -2
  507. package/node_modules/@jsonstudio/llms/dist/conversion/compat/antigravity-session-signature.js +33 -17
  508. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profile-registry/header-policies.d.ts +20 -0
  509. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profile-registry/header-policies.js +79 -0
  510. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profile-registry/policy-overrides.d.ts +16 -0
  511. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profile-registry/policy-overrides.js +27 -0
  512. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profile-registry/provider-resolver.d.ts +26 -0
  513. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profile-registry/provider-resolver.js +59 -0
  514. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profile-registry/registry.d.ts +35 -0
  515. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profile-registry/registry.js +154 -0
  516. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profile-registry/types.d.ts +75 -0
  517. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profile-registry/types.js +8 -0
  518. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/anthropic-claude-code.json +13 -7
  519. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-claude-code.json +13 -8
  520. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-deepseek-web.json +37 -8
  521. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-qwen.json +48 -11
  522. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/compat-passthrough.json +6 -0
  523. package/node_modules/@jsonstudio/llms/dist/conversion/compat/provider-resolution-config.json +24 -0
  524. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper-config.js +0 -1
  525. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper-from-chat.js +54 -7
  526. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper-to-chat.js +15 -2
  527. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/anthropic-semantics-audit.d.ts +11 -0
  528. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/anthropic-semantics-audit.js +16 -30
  529. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/gemini-mapper-config.js +0 -1
  530. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/gemini-mapper-from-chat.js +15 -1
  531. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/gemini-mapping-audit.d.ts +10 -0
  532. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/gemini-mapping-audit.js +9 -30
  533. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/protocol-mapping-audit.d.ts +43 -0
  534. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/protocol-mapping-audit.js +148 -0
  535. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper-from-chat.js +16 -6
  536. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper-helpers.d.ts +2 -1
  537. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper-helpers.js +65 -3
  538. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper-to-chat.js +1 -1
  539. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.d.ts +1 -1
  540. package/node_modules/@jsonstudio/llms/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.js +1 -1
  541. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/compat/compat-types.d.ts +14 -154
  542. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-chat-process-request-utils.d.ts +6 -1
  543. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-chat-process-request-utils.js +83 -3
  544. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-execute-chat-process-entry.js +6 -5
  545. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-execute-request-stage-inbound.d.ts +0 -1
  546. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-execute-request-stage-inbound.js +9 -5
  547. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-execute-request-stage-provider-payload.js +132 -1
  548. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-execute-request-stage.js +0 -1
  549. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-heavy-input-fastpath.d.ts +4 -22
  550. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-heavy-input-fastpath.js +109 -139
  551. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-max-tokens-policy.js +40 -1
  552. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-route-and-outbound.d.ts +0 -1
  553. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline-route-and-outbound.js +19 -2
  554. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline.d.ts +0 -2
  555. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/hub-pipeline.js +45 -43
  556. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/route-aware-responses-continuation.d.ts +10 -0
  557. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/route-aware-responses-continuation.js +143 -0
  558. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.js +37 -0
  559. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/semantic-lift.js +14 -2
  560. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/responses-context-snapshot.d.ts +3 -0
  561. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/responses-context-snapshot.js +22 -11
  562. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/chat-process-semantics-bridge.js +59 -2
  563. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/client-remap-protocol-switch.d.ts +1 -0
  564. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/client-remap-protocol-switch.js +3 -1
  565. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/index.d.ts +1 -0
  566. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/index.js +2 -1
  567. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage1_tool_governance/index.d.ts +2 -0
  568. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage1_tool_governance/index.js +53 -1
  569. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage2_finalize/index.js +4 -1
  570. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage3_servertool_orchestration/index.d.ts +1 -0
  571. package/node_modules/@jsonstudio/llms/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage3_servertool_orchestration/index.js +16 -0
  572. package/node_modules/@jsonstudio/llms/dist/conversion/hub/policy/policy-engine.js +14 -4
  573. package/node_modules/@jsonstudio/llms/dist/conversion/hub/process/chat-process-anthropic-alias.d.ts +1 -0
  574. package/node_modules/@jsonstudio/llms/dist/conversion/hub/process/chat-process-anthropic-alias.js +29 -1
  575. package/node_modules/@jsonstudio/llms/dist/conversion/hub/process/chat-process-pending-tool-sync.js +38 -2
  576. package/node_modules/@jsonstudio/llms/dist/conversion/hub/process/chat-process-request-sanitizer.js +164 -1
  577. package/node_modules/@jsonstudio/llms/dist/conversion/hub/response/provider-response.js +27 -2
  578. package/node_modules/@jsonstudio/llms/dist/conversion/hub/response/response-mappers.d.ts +9 -3
  579. package/node_modules/@jsonstudio/llms/dist/conversion/hub/response/response-mappers.js +8 -7
  580. package/node_modules/@jsonstudio/llms/dist/conversion/hub/response/response-runtime-anthropic.js +20 -5
  581. package/node_modules/@jsonstudio/llms/dist/conversion/hub/snapshot-recorder.js +1 -247
  582. package/node_modules/@jsonstudio/llms/dist/conversion/hub/types/chat-envelope.d.ts +84 -4
  583. package/node_modules/@jsonstudio/llms/dist/conversion/pipeline/codecs/v2/responses-openai-pipeline.js +26 -1
  584. package/node_modules/@jsonstudio/llms/dist/conversion/responses/responses-openai-bridge/response-payload.js +10 -9
  585. package/node_modules/@jsonstudio/llms/dist/conversion/responses/responses-openai-bridge/utils.js +20 -5
  586. package/node_modules/@jsonstudio/llms/dist/conversion/responses/responses-openai-bridge.js +88 -4
  587. package/node_modules/@jsonstudio/llms/dist/conversion/shared/anthropic-message-utils-core.js +5 -1
  588. package/node_modules/@jsonstudio/llms/dist/conversion/shared/anthropic-message-utils-openai-request.js +55 -14
  589. package/node_modules/@jsonstudio/llms/dist/conversion/shared/anthropic-message-utils-tool-schema.js +1 -2
  590. package/node_modules/@jsonstudio/llms/dist/conversion/shared/anthropic-message-utils.js +38 -15
  591. package/node_modules/@jsonstudio/llms/dist/conversion/shared/openai-message-normalize.js +45 -6
  592. package/node_modules/@jsonstudio/llms/dist/conversion/shared/responses-conversation-store.d.ts +15 -0
  593. package/node_modules/@jsonstudio/llms/dist/conversion/shared/responses-conversation-store.js +157 -13
  594. package/node_modules/@jsonstudio/llms/dist/conversion/shared/responses-reasoning-registry.d.ts +8 -2
  595. package/node_modules/@jsonstudio/llms/dist/conversion/shared/responses-reasoning-registry.js +103 -9
  596. package/node_modules/@jsonstudio/llms/dist/conversion/shared/responses-response-utils.js +10 -10
  597. package/node_modules/@jsonstudio/llms/dist/conversion/shared/tool-filter-pipeline.js +59 -9
  598. package/node_modules/@jsonstudio/llms/dist/conversion/shared/tool-governor-guards.d.ts +1 -1
  599. package/node_modules/@jsonstudio/llms/dist/conversion/shared/tool-governor-guards.js +54 -43
  600. package/node_modules/@jsonstudio/llms/dist/conversion/shared/tool-governor.js +62 -8
  601. package/node_modules/@jsonstudio/llms/dist/conversion/snapshot-utils.js +121 -8
  602. package/node_modules/@jsonstudio/llms/dist/filters/engine.js +64 -6
  603. package/node_modules/@jsonstudio/llms/dist/filters/special/request-tool-list-filter.js +32 -11
  604. package/node_modules/@jsonstudio/llms/dist/filters/special/request-toolcalls-stringify.js +26 -1
  605. package/node_modules/@jsonstudio/llms/dist/filters/special/request-tools-normalize.js +46 -7
  606. package/node_modules/@jsonstudio/llms/dist/filters/special/response-tool-arguments-blacklist.js +10 -1
  607. package/node_modules/@jsonstudio/llms/dist/filters/special/response-tool-arguments-schema-converge.js +10 -1
  608. package/node_modules/@jsonstudio/llms/dist/filters/special/response-tool-arguments-stringify.js +30 -5
  609. package/node_modules/@jsonstudio/llms/dist/filters/special/response-tool-arguments-whitelist.js +10 -1
  610. package/node_modules/@jsonstudio/llms/dist/filters/special/tool-filter-hooks.js +16 -14
  611. package/node_modules/@jsonstudio/llms/dist/filters/utils/snapshot-writer.js +47 -5
  612. package/node_modules/@jsonstudio/llms/dist/guidance/index.js +16 -2
  613. package/node_modules/@jsonstudio/llms/dist/http/sse-response.js +42 -6
  614. package/node_modules/@jsonstudio/llms/dist/native/router_hotpath_napi.node +0 -0
  615. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/bootstrap/auth-utils.js +33 -31
  616. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/bootstrap/provider-normalization.d.ts +6 -0
  617. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/bootstrap/provider-normalization.js +78 -98
  618. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/bootstrap/responses-helpers.js +22 -2
  619. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/bootstrap/routing-config.js +56 -3
  620. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/bootstrap/streaming-helpers.js +19 -1
  621. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/bootstrap.js +62 -293
  622. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/classifier.js +11 -82
  623. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine/antigravity/alias-lease.js +42 -15
  624. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine/cooldown-manager.js +55 -3
  625. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine/health/index.js +66 -15
  626. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine/routing-pools/index.js +44 -8
  627. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine/routing-state/keys.d.ts +7 -0
  628. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine/routing-state/keys.js +65 -21
  629. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine/routing-state/store.js +19 -2
  630. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine/sticky-session-manager.d.ts +9 -0
  631. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine/sticky-session-manager.js +139 -4
  632. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-logging.js +2 -1
  633. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-chat-process-clock-reminder-semantics.js +68 -59
  634. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-chat-process-governance-semantics.js +156 -157
  635. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-chat-process-node-result-semantics.d.ts +1 -0
  636. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-chat-process-node-result-semantics.js +31 -0
  637. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-chat-process-servertool-orchestration-semantics.js +94 -95
  638. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-compat-action-semantics.d.ts +0 -1
  639. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-compat-action-semantics.js +0 -7
  640. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics-parsers.d.ts +1 -1
  641. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics-parsers.js +203 -305
  642. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics-tools-post.js +35 -0
  643. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics-tools-request.js +2 -1
  644. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics-types.d.ts +2 -0
  645. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-bridge-policy-semantics.js +173 -154
  646. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-pipeline-edge-stage-semantics.d.ts +1 -0
  647. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-pipeline-edge-stage-semantics.js +106 -57
  648. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-pipeline-inbound-outbound-semantics.js +122 -114
  649. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-pipeline-orchestration-semantics-builders.d.ts +1 -0
  650. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-pipeline-orchestration-semantics-metadata-policy.js +100 -86
  651. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-pipeline-orchestration-semantics-passthrough.js +52 -33
  652. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-pipeline-orchestration-semantics-protocol.js +79 -62
  653. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-pipeline-orchestration-semantics.d.ts +1 -0
  654. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics-parsers.js +50 -33
  655. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics-types.d.ts +2 -0
  656. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-outbound-semantics-parsers.d.ts +1 -1
  657. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-outbound-semantics-parsers.js +161 -177
  658. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-pipeline-resp-semantics-outbound-tools.d.ts +1 -0
  659. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-pipeline-resp-semantics-outbound-tools.js +1 -0
  660. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-pipeline-resp-semantics-parsers.d.ts +1 -1
  661. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-hub-pipeline-resp-semantics-parsers.js +231 -286
  662. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-router-hotpath-analysis.js +143 -164
  663. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-router-hotpath-required-exports.d.ts +1 -1
  664. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-router-hotpath-required-exports.js +8 -1
  665. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics-reasoning.js +57 -28
  666. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics-responses.d.ts +8 -0
  667. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics-responses.js +76 -0
  668. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.d.ts +1 -1
  669. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.js +1 -1
  670. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-virtual-router-bootstrap-providers.d.ts +24 -0
  671. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-virtual-router-bootstrap-providers.js +78 -0
  672. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-virtual-router-bootstrap-routing.d.ts +17 -0
  673. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/native-virtual-router-bootstrap-routing.js +72 -0
  674. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/route-utils.js +9 -0
  675. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-selection/tier-selection-select.js +11 -5
  676. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine.js +4 -39
  677. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/features.js +199 -31
  678. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/health-manager.js +7 -2
  679. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/load-balancer.d.ts +3 -0
  680. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/load-balancer.js +47 -3
  681. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/native-error.d.ts +11 -0
  682. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/native-error.js +71 -0
  683. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/provider-registry.js +81 -2
  684. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/provider-runtime-ingress.d.ts +24 -0
  685. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/provider-runtime-ingress.js +139 -0
  686. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/routing-instructions/parse.js +21 -1
  687. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/routing-instructions/state.js +46 -0
  688. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/routing-instructions/types.d.ts +7 -0
  689. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/routing-stop-message-state-codec.js +30 -1
  690. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/sticky-session-store.js +44 -15
  691. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/stop-message-state-sync.d.ts +1 -1
  692. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/stop-message-state-sync.js +10 -2
  693. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/success-center.js +39 -2
  694. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/tool-signals.d.ts +1 -0
  695. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/tool-signals.js +25 -24
  696. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/types.d.ts +3 -0
  697. package/node_modules/@jsonstudio/llms/dist/servertool/engine.js +255 -71
  698. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/clock.js +20 -2
  699. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/followup-request-builder.js +120 -85
  700. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/memory-appender.d.ts +6 -0
  701. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/memory-appender.js +42 -0
  702. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/reasoning-only-continue.js +1 -1
  703. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/reasoning-stop-guard.js +630 -0
  704. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/reasoning-stop-state.d.ts +24 -0
  705. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/reasoning-stop-state.js +606 -0
  706. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/reasoning-stop.js +292 -0
  707. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/stop-message-auto/{iflow-followup.d.ts → ai-followup.d.ts} +3 -3
  708. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/stop-message-auto/{iflow-followup.js → ai-followup.js} +76 -81
  709. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/stop-message-auto/config.d.ts +1 -2
  710. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/stop-message-auto/config.js +2 -6
  711. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/stop-message-auto/runtime-utils.d.ts +1 -0
  712. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/stop-message-auto/runtime-utils.js +51 -11
  713. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/stop-message-auto.js +5 -4
  714. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/web-search-auto-trigger.d.ts +9 -0
  715. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/web-search-auto-trigger.js +91 -0
  716. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/web-search.js +1 -131
  717. package/node_modules/@jsonstudio/llms/dist/servertool/heartbeat/session-store.js +49 -18
  718. package/node_modules/@jsonstudio/llms/dist/servertool/registry.js +3 -0
  719. package/node_modules/@jsonstudio/llms/dist/servertool/server-side-tools.d.ts +2 -2
  720. package/node_modules/@jsonstudio/llms/dist/servertool/server-side-tools.js +14 -10
  721. package/node_modules/@jsonstudio/llms/dist/servertool/strip-servertool-calls.js +2 -3
  722. package/node_modules/@jsonstudio/llms/dist/servertool/types.d.ts +11 -1
  723. package/node_modules/@jsonstudio/llms/dist/sse/json-to-sse/chat-json-to-sse-converter.js +26 -1
  724. package/node_modules/@jsonstudio/llms/dist/sse/json-to-sse/event-generators/chat.d.ts +2 -2
  725. package/node_modules/@jsonstudio/llms/dist/sse/json-to-sse/event-generators/chat.js +38 -3
  726. package/node_modules/@jsonstudio/llms/dist/sse/json-to-sse/sequencers/chat-sequencer.js +6 -3
  727. package/node_modules/@jsonstudio/llms/dist/sse/shared/chat-serializer.js +27 -3
  728. package/node_modules/@jsonstudio/llms/dist/sse/shared/constants.d.ts +6 -6
  729. package/node_modules/@jsonstudio/llms/dist/sse/shared/constants.js +3 -3
  730. package/node_modules/@jsonstudio/llms/dist/sse/sse-to-json/anthropic-sse-to-json-converter.d.ts +1 -0
  731. package/node_modules/@jsonstudio/llms/dist/sse/sse-to-json/anthropic-sse-to-json-converter.js +36 -1
  732. package/node_modules/@jsonstudio/llms/dist/sse/sse-to-json/builders/anthropic-response-builder.js +6 -20
  733. package/node_modules/@jsonstudio/llms/dist/sse/sse-to-json/builders/response-builder.d.ts +3 -0
  734. package/node_modules/@jsonstudio/llms/dist/sse/sse-to-json/builders/response-builder.js +125 -42
  735. package/node_modules/@jsonstudio/llms/dist/sse/sse-to-json/chat-sse-to-json-converter.js +59 -10
  736. package/node_modules/@jsonstudio/llms/dist/sse/sse-to-json/parsers/sse-parser.js +2 -0
  737. package/node_modules/@jsonstudio/llms/dist/sse/sse-to-json/responses-sse-to-json-converter.d.ts +1 -0
  738. package/node_modules/@jsonstudio/llms/dist/sse/sse-to-json/responses-sse-to-json-converter.js +71 -2
  739. package/node_modules/@jsonstudio/llms/dist/sse/types/chat-types.d.ts +1 -0
  740. package/node_modules/@jsonstudio/llms/dist/sse/types/chat-types.js +1 -1
  741. package/node_modules/@jsonstudio/llms/dist/sse/types/conversion-context.js +2 -2
  742. package/node_modules/@jsonstudio/llms/dist/sse/types/index.d.ts +1 -1
  743. package/node_modules/@jsonstudio/llms/dist/sse/types/responses-types.d.ts +1 -1
  744. package/node_modules/@jsonstudio/llms/dist/sse/types/responses-types.js +1 -1
  745. package/node_modules/@jsonstudio/llms/dist/telemetry/stats-center.js +34 -12
  746. package/node_modules/@jsonstudio/llms/dist/tools/apply-patch/patch-text/fuzzy-match.d.ts +14 -0
  747. package/node_modules/@jsonstudio/llms/dist/tools/apply-patch/patch-text/fuzzy-match.js +174 -0
  748. package/node_modules/@jsonstudio/llms/dist/tools/apply-patch/patch-text/normalize.js +148 -0
  749. package/node_modules/@jsonstudio/llms/dist/tools/apply-patch/structured.js +31 -2
  750. package/node_modules/@jsonstudio/llms/dist/tools/apply-patch/validator.js +121 -4
  751. package/node_modules/@jsonstudio/llms/dist/tools/exec-command/normalize.d.ts +4 -1
  752. package/node_modules/@jsonstudio/llms/dist/tools/exec-command/normalize.js +31 -16
  753. package/node_modules/@jsonstudio/llms/dist/tools/exec-command/validator.d.ts +1 -0
  754. package/node_modules/@jsonstudio/llms/dist/tools/exec-command/validator.js +3 -1
  755. package/node_modules/@jsonstudio/llms/dist/tools/tool-registry.d.ts +1 -0
  756. package/node_modules/@jsonstudio/llms/dist/tools/tool-registry.js +5 -27
  757. package/node_modules/@jsonstudio/llms/package.json +1 -1
  758. package/package.json +6 -7
  759. package/scripts/ci/repo-sanity.mjs +1 -0
  760. package/scripts/ci/silent-failure-audit.mjs +112 -70
  761. package/scripts/cleanup-stale-server-pids.mjs +0 -6
  762. package/scripts/ensure-cli-command-shim.mjs +49 -15
  763. package/scripts/ensure-cli-executable.mjs +1 -1
  764. package/scripts/install-global.sh +7 -6
  765. package/scripts/install-release-snapshot.mjs +232 -0
  766. package/scripts/install-release.sh +30 -24
  767. package/scripts/link-global-llms-local.mjs +1 -2
  768. package/scripts/pack-mode.mjs +0 -4
  769. package/scripts/pack-rcc.mjs +17 -58
  770. package/scripts/run-bg.sh +0 -6
  771. package/scripts/run-fg-gtimeout.sh +0 -6
  772. package/scripts/tests/antigravity-codex-sample-pipeline-compare.mjs +1 -1
  773. package/scripts/tests/blackbox-rcc-vs-routecodex-antigravity.mjs +60 -39
  774. package/scripts/verify-install-e2e.mjs +64 -26
  775. package/configsamples/provider-default/qwenchat/config.v2.json +0 -53
  776. package/dist/providers/auth/iflow-cookie-auth.d.ts +0 -27
  777. package/dist/providers/auth/iflow-cookie-auth.js +0 -207
  778. package/dist/providers/auth/iflow-cookie-auth.js.map +0 -1
  779. package/dist/providers/auth/iflow-userinfo-helper.d.ts +0 -32
  780. package/dist/providers/auth/iflow-userinfo-helper.js +0 -81
  781. package/dist/providers/auth/iflow-userinfo-helper.js.map +0 -1
  782. package/dist/providers/core/runtime/iflow-http-provider.d.ts +0 -13
  783. package/dist/providers/core/runtime/iflow-http-provider.js +0 -22
  784. package/dist/providers/core/runtime/iflow-http-provider.js.map +0 -1
  785. package/dist/providers/core/runtime/provider-iflow-business-error-utils.d.ts +0 -15
  786. package/dist/providers/core/runtime/provider-iflow-business-error-utils.js +0 -49
  787. package/dist/providers/core/runtime/provider-iflow-business-error-utils.js.map +0 -1
  788. package/dist/providers/core/runtime/qwenchat-http-provider-helpers.d.ts +0 -89
  789. package/dist/providers/core/runtime/qwenchat-http-provider-helpers.js +0 -1698
  790. package/dist/providers/core/runtime/qwenchat-http-provider-helpers.js.map +0 -1
  791. package/dist/providers/core/runtime/qwenchat-http-provider.d.ts +0 -9
  792. package/dist/providers/core/runtime/qwenchat-http-provider.js +0 -78
  793. package/dist/providers/core/runtime/qwenchat-http-provider.js.map +0 -1
  794. package/dist/providers/core/runtime/standard-tool-text-request-transform.d.ts +0 -13
  795. package/dist/providers/core/runtime/standard-tool-text-request-transform.js +0 -138
  796. package/dist/providers/core/runtime/standard-tool-text-request-transform.js.map +0 -1
  797. package/dist/providers/core/runtime/transport/iflow-signer.d.ts +0 -12
  798. package/dist/providers/core/runtime/transport/iflow-signer.js +0 -63
  799. package/dist/providers/core/runtime/transport/iflow-signer.js.map +0 -1
  800. package/dist/providers/profile/families/iflow-profile.d.ts +0 -2
  801. package/dist/providers/profile/families/iflow-profile.js +0 -384
  802. package/dist/providers/profile/families/iflow-profile.js.map +0 -1
  803. package/docs/mapping-tables/iflow-to-openai.json +0 -215
  804. package/docs/mapping-tables/openai-to-iflow.json +0 -227
  805. package/docs/multi-token-auth-guide.md +0 -66
  806. package/docs/oauth-authentication-guide.md +0 -172
  807. package/docs/oauth-iflow-implementation.md +0 -157
  808. package/docs/release-iflow-400-gate.md +0 -58
  809. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/iflow-kimi-cli-defaults.d.ts +0 -10
  810. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/iflow-kimi-cli-defaults.js +0 -31
  811. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/iflow-kimi-history-media-placeholder.d.ts +0 -7
  812. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/iflow-kimi-history-media-placeholder.js +0 -25
  813. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/iflow-kimi-thinking-reasoning-fill.d.ts +0 -12
  814. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/iflow-kimi-thinking-reasoning-fill.js +0 -46
  815. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/iflow-native-compat.d.ts +0 -6
  816. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/iflow-native-compat.js +0 -36
  817. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/iflow-response-body-unwrap.d.ts +0 -9
  818. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/iflow-response-body-unwrap.js +0 -25
  819. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/iflow-tool-text-fallback.d.ts +0 -5
  820. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/iflow-tool-text-fallback.js +0 -29
  821. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/iflow-web-search.d.ts +0 -18
  822. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/iflow-web-search.js +0 -49
  823. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/qwenchat-web-request.d.ts +0 -3
  824. package/node_modules/@jsonstudio/llms/dist/conversion/compat/actions/qwenchat-web-request.js +0 -62
  825. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-iflow.json +0 -353
  826. package/node_modules/@jsonstudio/llms/dist/conversion/compat/profiles/chat-qwenchat-web.json +0 -47
  827. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-health.d.ts +0 -1
  828. package/node_modules/@jsonstudio/llms/dist/router/virtual-router/engine-health.js +0 -1
  829. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/iflow-model-error-retry.js +0 -92
  830. package/node_modules/@jsonstudio/llms/dist/servertool/handlers/review.js +0 -202
  831. package/scripts/publish-rcc.mjs +0 -81
  832. /package/node_modules/@jsonstudio/llms/dist/servertool/handlers/{iflow-model-error-retry.d.ts → reasoning-stop-guard.d.ts} +0 -0
  833. /package/node_modules/@jsonstudio/llms/dist/servertool/handlers/{review.d.ts → reasoning-stop.d.ts} +0 -0
@@ -1,1698 +0,0 @@
1
- import { createHash, createHmac, randomBytes, randomUUID } from 'node:crypto';
2
- import { isIP } from 'node:net';
3
- import { PassThrough } from 'node:stream';
4
- import { applyStandardToolTextRequestTransform } from './standard-tool-text-request-transform.js';
5
- import { applyStandardToolTextHarvestToChatPayload } from './standard-tool-text-harvest.js';
6
- export const DEFAULT_QWENCHAT_BASE_URL = 'https://chat.qwen.ai';
7
- export const DEFAULT_QWENCHAT_USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36';
8
- export const DEFAULT_QWENCHAT_ACCEPT_LANGUAGE = 'zh-CN,zh;q=0.9,en;q=0.8';
9
- export const DEFAULT_QWENCHAT_COMPLETION_ENDPOINT = '/api/v2/chat/completions';
10
- export const DEFAULT_QWENCHAT_CHAT_CREATE_ENDPOINT = '/api/v2/chats/new';
11
- const BAXIA_VERSION = '2.5.36';
12
- const BAXIA_CACHE_TTL_MS = 4 * 60 * 1000;
13
- const DEFAULT_ATTACHMENT_FETCH_TIMEOUT_MS = 15_000;
14
- const DEFAULT_ATTACHMENT_MAX_BYTES = 20 * 1024 * 1024;
15
- function isRecord(value) {
16
- return value !== null && typeof value === 'object' && !Array.isArray(value);
17
- }
18
- function normalizeInputString(value) {
19
- if (typeof value !== 'string') {
20
- return '';
21
- }
22
- const trimmed = value.trim();
23
- if (!trimmed) {
24
- return '';
25
- }
26
- const lowered = trimmed.toLowerCase();
27
- if (lowered === 'undefined' || lowered === '[undefined]' || lowered === 'null' || lowered === '[null]') {
28
- return '';
29
- }
30
- return trimmed;
31
- }
32
- function clampInteger(value, fallback, min, max) {
33
- const parsed = typeof value === 'number' && Number.isFinite(value)
34
- ? Math.trunc(value)
35
- : Number.parseInt(normalizeInputString(value), 10);
36
- if (!Number.isFinite(parsed)) {
37
- return fallback;
38
- }
39
- return Math.min(max, Math.max(min, parsed));
40
- }
41
- function readBooleanEnv(keys, fallback) {
42
- for (const key of keys) {
43
- const raw = normalizeInputString(process.env[key]);
44
- if (!raw) {
45
- continue;
46
- }
47
- const normalized = raw.trim().toLowerCase();
48
- if (['1', 'true', 'yes', 'on'].includes(normalized)) {
49
- return true;
50
- }
51
- if (['0', 'false', 'no', 'off'].includes(normalized)) {
52
- return false;
53
- }
54
- }
55
- return fallback;
56
- }
57
- function parseImageSizeToQwenRatio(size) {
58
- const text = normalizeInputString(size);
59
- if (!text) {
60
- return '1:1';
61
- }
62
- const ratioMatch = text.match(/^(\d{1,2}):(\d{1,2})$/);
63
- if (ratioMatch) {
64
- const w = Number.parseInt(ratioMatch[1], 10);
65
- const h = Number.parseInt(ratioMatch[2], 10);
66
- if (Number.isFinite(w) && Number.isFinite(h) && w > 0 && h > 0) {
67
- const ratio = `${w}:${h}`;
68
- if (['1:1', '16:9', '9:16', '4:3', '3:4'].includes(ratio)) {
69
- return ratio;
70
- }
71
- }
72
- }
73
- const sizeMatch = text.toLowerCase().match(/^(\d{2,5})\s*x\s*(\d{2,5})$/);
74
- if (!sizeMatch) {
75
- return '1:1';
76
- }
77
- const width = Number.parseInt(sizeMatch[1], 10);
78
- const height = Number.parseInt(sizeMatch[2], 10);
79
- if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
80
- return '1:1';
81
- }
82
- const ratio = width / height;
83
- const candidates = [
84
- { key: '1:1', ratio: 1 },
85
- { key: '16:9', ratio: 16 / 9 },
86
- { key: '9:16', ratio: 9 / 16 },
87
- { key: '4:3', ratio: 4 / 3 },
88
- { key: '3:4', ratio: 3 / 4 }
89
- ];
90
- let best = candidates[0];
91
- let bestDiff = Number.POSITIVE_INFINITY;
92
- for (const candidate of candidates) {
93
- const diff = Math.abs(ratio - candidate.ratio);
94
- if (diff < bestDiff) {
95
- best = candidate;
96
- bestDiff = diff;
97
- }
98
- }
99
- return best.key;
100
- }
101
- function parseQwenImageGenerationOptions(metadata) {
102
- const node = metadata && isRecord(metadata.qwenImageGeneration)
103
- ? metadata.qwenImageGeneration
104
- : undefined;
105
- const enabled = metadata?.qwenImageGeneration === true
106
- || metadata?.imageGeneration === true
107
- || normalizeInputString(metadata?.generationMode).toLowerCase() === 'image'
108
- || Boolean(node);
109
- const count = clampInteger(node?.n ?? metadata?.n, 1, 1, 10);
110
- const sizeRatio = parseImageSizeToQwenRatio(node?.size ?? metadata?.size);
111
- const responseFormatRaw = normalizeInputString(node?.responseFormat ?? node?.response_format ?? metadata?.response_format).toLowerCase();
112
- const responseFormat = responseFormatRaw === 'b64_json' ? 'b64_json' : 'url';
113
- return {
114
- enabled,
115
- count,
116
- sizeRatio,
117
- responseFormat
118
- };
119
- }
120
- function readPositiveIntegerEnv(keys, fallback, min = 1, max = Number.MAX_SAFE_INTEGER) {
121
- for (const key of keys) {
122
- const raw = normalizeInputString(process.env[key]);
123
- if (!raw) {
124
- continue;
125
- }
126
- const parsed = Number.parseInt(raw, 10);
127
- if (!Number.isFinite(parsed)) {
128
- continue;
129
- }
130
- const normalized = Math.floor(parsed);
131
- if (normalized < min || normalized > max) {
132
- continue;
133
- }
134
- return normalized;
135
- }
136
- return fallback;
137
- }
138
- function isPrivateIpv4(host) {
139
- const segments = host.split('.');
140
- if (segments.length !== 4) {
141
- return false;
142
- }
143
- const numbers = segments.map((segment) => Number.parseInt(segment, 10));
144
- if (numbers.some((value) => !Number.isFinite(value) || value < 0 || value > 255)) {
145
- return false;
146
- }
147
- const [a, b] = numbers;
148
- if (a === 10 || a === 127 || a === 0) {
149
- return true;
150
- }
151
- if (a === 169 && b === 254) {
152
- return true;
153
- }
154
- if (a === 192 && b === 168) {
155
- return true;
156
- }
157
- if (a === 172 && b >= 16 && b <= 31) {
158
- return true;
159
- }
160
- return false;
161
- }
162
- function isPrivateIpv6(host) {
163
- const normalized = host.toLowerCase();
164
- return normalized === '::1'
165
- || normalized.startsWith('fc')
166
- || normalized.startsWith('fd')
167
- || normalized.startsWith('fe80:');
168
- }
169
- function validateAttachmentSourceUrl(input) {
170
- let parsed;
171
- try {
172
- parsed = new URL(input);
173
- }
174
- catch {
175
- throw new Error('Invalid attachment URL');
176
- }
177
- const protocol = parsed.protocol.toLowerCase();
178
- if (protocol !== 'https:' && protocol !== 'http:') {
179
- throw new Error(`Unsupported attachment URL protocol: ${protocol}`);
180
- }
181
- if (parsed.username || parsed.password) {
182
- throw new Error('Attachment URL must not include username/password');
183
- }
184
- const hostname = parsed.hostname.trim().toLowerCase();
185
- if (!hostname) {
186
- throw new Error('Attachment URL hostname is required');
187
- }
188
- if (hostname === 'localhost' || hostname.endsWith('.localhost') || hostname.endsWith('.local')) {
189
- throw new Error('Attachment URL localhost/local domains are not allowed');
190
- }
191
- const ipType = isIP(hostname);
192
- if (ipType === 4 && isPrivateIpv4(hostname)) {
193
- throw new Error('Attachment URL private IPv4 is not allowed');
194
- }
195
- if (ipType === 6 && isPrivateIpv6(hostname)) {
196
- throw new Error('Attachment URL private IPv6 is not allowed');
197
- }
198
- return parsed;
199
- }
200
- async function readResponseBytesWithLimit(response, maxBytes) {
201
- const contentLengthText = normalizeInputString(response.headers.get('content-length'));
202
- if (contentLengthText) {
203
- const contentLength = Number.parseInt(contentLengthText, 10);
204
- if (Number.isFinite(contentLength) && contentLength > maxBytes) {
205
- throw new Error(`Attachment exceeds max size (${contentLength} > ${maxBytes})`);
206
- }
207
- }
208
- const reader = response.body?.getReader();
209
- if (!reader) {
210
- return new Uint8Array(await response.arrayBuffer());
211
- }
212
- const chunks = [];
213
- let total = 0;
214
- while (true) {
215
- const step = await reader.read();
216
- if (step.done) {
217
- break;
218
- }
219
- const chunk = step.value;
220
- total += chunk.byteLength;
221
- if (total > maxBytes) {
222
- try {
223
- await reader.cancel('attachment_too_large');
224
- }
225
- catch {
226
- // ignore
227
- }
228
- throw new Error(`Attachment exceeds max size (${total} > ${maxBytes})`);
229
- }
230
- chunks.push(chunk);
231
- }
232
- const merged = new Uint8Array(total);
233
- let offset = 0;
234
- for (const chunk of chunks) {
235
- merged.set(chunk, offset);
236
- offset += chunk.byteLength;
237
- }
238
- return merged;
239
- }
240
- function randomString(length) {
241
- const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
242
- const bytes = randomBytes(length);
243
- let out = '';
244
- for (let i = 0; i < length; i += 1) {
245
- out += chars[bytes[i] % chars.length];
246
- }
247
- return out;
248
- }
249
- function cryptoHashBase64Md5(data) {
250
- return createHash('md5').update(data).digest('base64').substring(0, 32);
251
- }
252
- function encodeBaxiaToken(data) {
253
- const json = JSON.stringify(data);
254
- const encoded = Buffer.from(json, 'utf8').toString('base64');
255
- return `${BAXIA_VERSION.replace(/\./g, '')}!${encoded}`;
256
- }
257
- async function collectFingerprintData() {
258
- const platforms = ['Win32', 'Linux x86_64', 'MacIntel'];
259
- const languages = ['en-US', 'zh-CN', 'en-GB'];
260
- const canvas = cryptoHashBase64Md5(randomBytes(32));
261
- return {
262
- p: platforms[Math.floor(Math.random() * platforms.length)],
263
- l: languages[Math.floor(Math.random() * languages.length)],
264
- hc: 4 + Math.floor(Math.random() * 12),
265
- dm: [4, 8, 16, 32][Math.floor(Math.random() * 4)],
266
- to: [-480, -300, 0, 60, 480][Math.floor(Math.random() * 5)],
267
- sw: 1920 + Math.floor(Math.random() * 200),
268
- sh: 1080 + Math.floor(Math.random() * 100),
269
- cd: 24,
270
- pr: [1, 1.25, 1.5, 2][Math.floor(Math.random() * 4)],
271
- wf: 'ANGLE (Intel, Intel(R) UHD Graphics 630, OpenGL 4.6)'.substring(0, 20),
272
- cf: canvas,
273
- af: (124.04347527516074 + Math.random() * 0.001).toFixed(14),
274
- ts: Date.now(),
275
- r: Math.random()
276
- };
277
- }
278
- export async function getQwenBaxiaTokens(cache) {
279
- const now = Date.now();
280
- if (cache.tokenCache && now - cache.tokenCacheTime < BAXIA_CACHE_TTL_MS) {
281
- return cache.tokenCache;
282
- }
283
- const bxUa = encodeBaxiaToken(await collectFingerprintData());
284
- let bxUmidToken = `T2gA${randomString(40)}`;
285
- try {
286
- const resp = await fetch('https://sg-wum.alibaba.com/w/wu.json', {
287
- headers: { 'User-Agent': DEFAULT_QWENCHAT_USER_AGENT }
288
- });
289
- const etag = normalizeInputString(resp.headers.get('etag'));
290
- if (etag) {
291
- bxUmidToken = etag;
292
- }
293
- }
294
- catch {
295
- // keep generated fallback token
296
- }
297
- const next = { bxUa, bxUmidToken, bxV: BAXIA_VERSION };
298
- cache.tokenCache = next;
299
- cache.tokenCacheTime = now;
300
- return next;
301
- }
302
- async function safeReadJsonResponse(response) {
303
- const rawText = await response.text().catch(() => '');
304
- if (!rawText) {
305
- return {
306
- ok: false,
307
- status: response.status,
308
- data: null,
309
- rawText: '',
310
- parseError: new Error('Empty response body')
311
- };
312
- }
313
- try {
314
- const parsed = JSON.parse(rawText);
315
- if (!isRecord(parsed)) {
316
- return {
317
- ok: false,
318
- status: response.status,
319
- data: null,
320
- rawText,
321
- parseError: new Error('Response is not a JSON object')
322
- };
323
- }
324
- return {
325
- ok: true,
326
- status: response.status,
327
- data: parsed,
328
- rawText
329
- };
330
- }
331
- catch (error) {
332
- return {
333
- ok: false,
334
- status: response.status,
335
- data: null,
336
- rawText,
337
- parseError: error instanceof Error ? error : new Error(String(error))
338
- };
339
- }
340
- }
341
- function joinUrl(baseUrl, path) {
342
- const base = baseUrl.replace(/\/$/, '');
343
- const suffix = path.startsWith('/') ? path : `/${path}`;
344
- return `${base}${suffix}`;
345
- }
346
- function normalizeMimeType(raw) {
347
- const value = normalizeInputString(raw).toLowerCase();
348
- return value || 'application/octet-stream';
349
- }
350
- function inferFileCategory(mimeType, explicitType) {
351
- if (explicitType) {
352
- return explicitType;
353
- }
354
- const mime = normalizeMimeType(mimeType);
355
- if (mime.startsWith('image/'))
356
- return 'image';
357
- if (mime.startsWith('audio/'))
358
- return 'audio';
359
- if (mime.startsWith('video/'))
360
- return 'video';
361
- return 'document';
362
- }
363
- function fileExtensionFromMime(mimeType) {
364
- const mime = normalizeMimeType(mimeType);
365
- const mapping = {
366
- 'image/png': 'png',
367
- 'image/jpeg': 'jpg',
368
- 'image/jpg': 'jpg',
369
- 'image/webp': 'webp',
370
- 'image/gif': 'gif',
371
- 'application/pdf': 'pdf',
372
- 'text/plain': 'txt',
373
- 'text/markdown': 'md',
374
- 'application/json': 'json',
375
- 'audio/mpeg': 'mp3',
376
- 'audio/wav': 'wav',
377
- 'audio/x-wav': 'wav',
378
- 'audio/mp4': 'm4a',
379
- 'audio/ogg': 'ogg',
380
- 'video/mp4': 'mp4',
381
- 'video/webm': 'webm',
382
- 'video/quicktime': 'mov',
383
- 'video/x-matroska': 'mkv',
384
- 'video/avi': 'avi'
385
- };
386
- return mapping[mime] || 'bin';
387
- }
388
- function decodeBase64ToBytes(base64) {
389
- return new Uint8Array(Buffer.from(base64, 'base64'));
390
- }
391
- function parseDataUrl(dataUrl) {
392
- const matched = dataUrl.match(/^data:([^;,]+)?;base64,(.+)$/i);
393
- if (!matched) {
394
- return null;
395
- }
396
- return {
397
- mimeType: normalizeMimeType(matched[1] || 'application/octet-stream'),
398
- bytes: decodeBase64ToBytes(matched[2])
399
- };
400
- }
401
- function inferFilename(rawFilename, mimeType) {
402
- const normalized = normalizeInputString(rawFilename);
403
- if (normalized) {
404
- return normalized;
405
- }
406
- return `attachment-${randomUUID()}.${fileExtensionFromMime(mimeType)}`;
407
- }
408
- function normalizeLegacyFiles(message) {
409
- const out = [];
410
- const rawAttachments = Array.isArray(message.attachments) ? message.attachments : [];
411
- const rawFiles = Array.isArray(message.files) ? message.files : [];
412
- for (const item of [...rawAttachments, ...rawFiles]) {
413
- if (!isRecord(item))
414
- continue;
415
- const source = normalizeInputString(item.data || item.file_data || item.url || item.file_url);
416
- if (!source)
417
- continue;
418
- const explicitRaw = normalizeInputString(item.type).toLowerCase();
419
- const explicitType = explicitRaw === 'image' || explicitRaw === 'audio' || explicitRaw === 'video' || explicitRaw === 'document'
420
- ? explicitRaw
421
- : undefined;
422
- out.push({
423
- source,
424
- filename: normalizeInputString(item.filename || item.name) || undefined,
425
- mimeType: normalizeInputString(item.mime_type || item.content_type || item.type) || undefined,
426
- explicitType: explicitType
427
- });
428
- }
429
- return out;
430
- }
431
- const VIDEO_SOURCE_HINT_RE = /(^data:video\/)|(\.(mp4|mov|m4v|webm|avi|mkv|m3u8|flv)(?:$|[?#]))/i;
432
- function sourceLooksLikeVideo(source, mimeType) {
433
- const normalizedSource = normalizeInputString(source);
434
- if (normalizedSource && VIDEO_SOURCE_HINT_RE.test(normalizedSource)) {
435
- return true;
436
- }
437
- const normalizedMime = normalizeMimeType(mimeType).toLowerCase();
438
- return normalizedMime.startsWith('video/');
439
- }
440
- function normalizeContentParts(content) {
441
- if (typeof content === 'string') {
442
- return { text: normalizeInputString(content), attachments: [] };
443
- }
444
- if (!Array.isArray(content)) {
445
- return { text: '', attachments: [] };
446
- }
447
- const textParts = [];
448
- const attachments = [];
449
- for (const partRaw of content) {
450
- if (!isRecord(partRaw)) {
451
- if (typeof partRaw === 'string') {
452
- const text = normalizeInputString(partRaw);
453
- if (text)
454
- textParts.push(text);
455
- }
456
- continue;
457
- }
458
- const type = normalizeInputString(partRaw.type).toLowerCase();
459
- if (type === 'text' || type === 'input_text') {
460
- const text = normalizeInputString(partRaw.text || partRaw.input_text);
461
- if (text)
462
- textParts.push(text);
463
- continue;
464
- }
465
- if (type === 'image_url' || type === 'input_image') {
466
- const rawImage = isRecord(partRaw.image_url) ? partRaw.image_url.url : partRaw.image_url;
467
- const source = normalizeInputString(rawImage || partRaw.url || partRaw.file_url || partRaw.file_data);
468
- if (!source)
469
- continue;
470
- const mimeHint = normalizeInputString(partRaw.mime_type || partRaw.content_type);
471
- attachments.push({
472
- source,
473
- filename: normalizeInputString(partRaw.filename || partRaw.name) || undefined,
474
- mimeType: mimeHint || undefined,
475
- // Some clients put video URLs in image_url blocks; preserve shape, only fix type.
476
- explicitType: sourceLooksLikeVideo(source, mimeHint) ? 'video' : 'image'
477
- });
478
- continue;
479
- }
480
- if (type === 'file' ||
481
- type === 'input_file' ||
482
- type === 'audio' ||
483
- type === 'input_audio' ||
484
- type === 'video' ||
485
- type === 'input_video' ||
486
- type === 'video_url') {
487
- const rawVideo = isRecord(partRaw.video_url) ? partRaw.video_url.url : partRaw.video_url;
488
- const source = normalizeInputString(rawVideo || partRaw.file_data || partRaw.url || partRaw.file_url || partRaw.data);
489
- if (!source)
490
- continue;
491
- const explicitType = type.includes('audio') ? 'audio' : (type.includes('video') || sourceLooksLikeVideo(source, normalizeInputString(partRaw.mime_type || partRaw.content_type))) ? 'video' : undefined;
492
- attachments.push({
493
- source,
494
- filename: normalizeInputString(partRaw.filename || partRaw.name) || undefined,
495
- mimeType: normalizeInputString(partRaw.mime_type || partRaw.content_type) || undefined,
496
- explicitType
497
- });
498
- continue;
499
- }
500
- const fallbackText = normalizeInputString(partRaw.text || partRaw.content);
501
- if (fallbackText) {
502
- textParts.push(fallbackText);
503
- }
504
- }
505
- return {
506
- text: textParts.join('\n'),
507
- attachments
508
- };
509
- }
510
- export function parseIncomingMessages(messages) {
511
- const safeMessages = Array.isArray(messages) ? messages : [];
512
- const normalized = safeMessages.map((messageRaw) => {
513
- const message = isRecord(messageRaw) ? messageRaw : {};
514
- const parsed = normalizeContentParts(message.content);
515
- return {
516
- role: normalizeInputString(message.role) || 'user',
517
- text: parsed.text,
518
- attachments: [...parsed.attachments, ...normalizeLegacyFiles(message)]
519
- };
520
- });
521
- if (normalized.length === 0) {
522
- return { content: '', attachments: [] };
523
- }
524
- const last = normalized[normalized.length - 1];
525
- const history = normalized
526
- .slice(0, -1)
527
- .map((item) => {
528
- if (!item.text)
529
- return '';
530
- const role = item.role === 'assistant' ? 'Assistant' : item.role === 'system' ? 'System' : 'User';
531
- return `[${role}]: ${item.text}`;
532
- })
533
- .filter(Boolean)
534
- .join('\n\n');
535
- const lastText = last.text || (last.attachments.length > 0 ? '请结合附件内容回答。' : '');
536
- const merged = history ? `${history}\n\n[User]: ${lastText}` : lastText;
537
- return {
538
- content: merged,
539
- attachments: last.attachments
540
- };
541
- }
542
- async function loadAttachmentBytes(attachment) {
543
- const parsedDataUrl = parseDataUrl(attachment.source);
544
- if (parsedDataUrl) {
545
- const mimeType = normalizeMimeType(attachment.mimeType || parsedDataUrl.mimeType);
546
- return {
547
- bytes: parsedDataUrl.bytes,
548
- mimeType,
549
- filename: inferFilename(attachment.filename, mimeType),
550
- explicitType: attachment.explicitType
551
- };
552
- }
553
- if (/^https?:\/\//i.test(attachment.source)) {
554
- const parsedUrl = validateAttachmentSourceUrl(attachment.source);
555
- const timeoutMs = readPositiveIntegerEnv(['ROUTECODEX_QWENCHAT_ATTACHMENT_FETCH_TIMEOUT_MS', 'RCC_QWENCHAT_ATTACHMENT_FETCH_TIMEOUT_MS'], DEFAULT_ATTACHMENT_FETCH_TIMEOUT_MS, 1_000, 300_000);
556
- const maxBytes = readPositiveIntegerEnv(['ROUTECODEX_QWENCHAT_ATTACHMENT_MAX_BYTES', 'RCC_QWENCHAT_ATTACHMENT_MAX_BYTES'], DEFAULT_ATTACHMENT_MAX_BYTES, 1024);
557
- const controller = new AbortController();
558
- const timer = setTimeout(() => controller.abort('attachment_fetch_timeout'), timeoutMs);
559
- if (typeof timer.unref === 'function') {
560
- timer.unref();
561
- }
562
- const resp = await fetch(parsedUrl, { signal: controller.signal }).finally(() => clearTimeout(timer));
563
- if (!resp.ok) {
564
- throw new Error(`Failed to fetch attachment URL: HTTP ${resp.status}`);
565
- }
566
- const bytes = await readResponseBytesWithLimit(resp, maxBytes);
567
- const mimeType = normalizeMimeType(attachment.mimeType || resp.headers.get('content-type'));
568
- return {
569
- bytes,
570
- mimeType,
571
- filename: inferFilename(attachment.filename, mimeType),
572
- explicitType: attachment.explicitType
573
- };
574
- }
575
- const normalizedBase64 = attachment.source.replace(/\s+/g, '');
576
- const bytes = decodeBase64ToBytes(normalizedBase64);
577
- const mimeType = normalizeMimeType(attachment.mimeType);
578
- return {
579
- bytes,
580
- mimeType,
581
- filename: inferFilename(attachment.filename, mimeType),
582
- explicitType: attachment.explicitType
583
- };
584
- }
585
- function qwenCommonHeaders(baxiaTokens, authHeaders, options) {
586
- const forwardAuthHeaders = readBooleanEnv(['ROUTECODEX_QWENCHAT_FORWARD_AUTH_HEADERS', 'RCC_QWENCHAT_FORWARD_AUTH_HEADERS'], false);
587
- const normalizedBase = normalizeInputString(options?.baseUrl) || DEFAULT_QWENCHAT_BASE_URL;
588
- const base = normalizedBase.replace(/\/$/, '');
589
- const referer = options?.refererMode === 'guest' ? `${base}/c/guest` : `${base}/`;
590
- const accept = options?.acceptMode === 'json' ? 'application/json' : 'application/json, text/plain, */*';
591
- return {
592
- 'Accept': accept,
593
- 'Content-Type': 'application/json',
594
- 'bx-ua': baxiaTokens.bxUa,
595
- 'bx-umidtoken': baxiaTokens.bxUmidToken,
596
- 'bx-v': baxiaTokens.bxV,
597
- 'source': 'web',
598
- 'timezone': new Date().toUTCString(),
599
- 'Referer': referer,
600
- 'User-Agent': DEFAULT_QWENCHAT_USER_AGENT,
601
- 'Accept-Language': DEFAULT_QWENCHAT_ACCEPT_LANGUAGE,
602
- 'x-request-id': randomUUID(),
603
- ...(forwardAuthHeaders ? authHeaders || {} : {})
604
- };
605
- }
606
- function extractQwenErrorMessage(payload) {
607
- const readNestedMessage = (value) => {
608
- if (typeof value === 'string') {
609
- return normalizeInputString(value);
610
- }
611
- if (!isRecord(value)) {
612
- return '';
613
- }
614
- const nested = [
615
- normalizeInputString(value.message),
616
- normalizeInputString(value.msg),
617
- normalizeInputString(value.details),
618
- normalizeInputString(value.template),
619
- normalizeInputString(value.code),
620
- isRecord(value.error) ? normalizeInputString(value.error.message) : ''
621
- ].filter(Boolean);
622
- return nested[0] || '';
623
- };
624
- const readNode = (node) => {
625
- if (!node)
626
- return '';
627
- const direct = [
628
- normalizeInputString(node.msg),
629
- normalizeInputString(node.message),
630
- normalizeInputString(node.error),
631
- normalizeInputString(node.err_msg),
632
- normalizeInputString(node.details),
633
- normalizeInputString(node.template),
634
- normalizeInputString(node.code)
635
- ].filter(Boolean);
636
- if (direct.length > 0) {
637
- return direct[0];
638
- }
639
- if (isRecord(node.error)) {
640
- const nested = [
641
- normalizeInputString(node.error.message),
642
- normalizeInputString(node.error.msg),
643
- normalizeInputString(node.error.code)
644
- ].filter(Boolean);
645
- if (nested.length > 0) {
646
- return nested[0];
647
- }
648
- }
649
- if (isRecord(node.details)) {
650
- const nestedDetails = readNestedMessage(node.details);
651
- if (nestedDetails) {
652
- return nestedDetails;
653
- }
654
- }
655
- return '';
656
- };
657
- const dataNode = isRecord(payload.data) ? payload.data : undefined;
658
- const detailsNode = isRecord(dataNode?.details) ? dataNode.details : undefined;
659
- return readNode(payload) || readNode(dataNode) || readNode(detailsNode) || '';
660
- }
661
- function extractQwenUploadTokenData(payload) {
662
- const tryReadNode = (node) => {
663
- if (!isRecord(node)) {
664
- return null;
665
- }
666
- const fileUrl = normalizeInputString(node.file_url) ||
667
- normalizeInputString(node.fileUrl) ||
668
- normalizeInputString(node.upload_url) ||
669
- normalizeInputString(node.uploadUrl) ||
670
- normalizeInputString(node.url);
671
- const accessKeyId = normalizeInputString(node.access_key_id) ||
672
- normalizeInputString(node.accessKeyId);
673
- const accessKeySecret = normalizeInputString(node.access_key_secret) ||
674
- normalizeInputString(node.accessKeySecret);
675
- const securityToken = normalizeInputString(node.security_token) ||
676
- normalizeInputString(node.securityToken);
677
- if (!fileUrl || !accessKeyId || !accessKeySecret || !securityToken) {
678
- return null;
679
- }
680
- return {
681
- file_url: fileUrl,
682
- file_id: normalizeInputString(node.file_id) || normalizeInputString(node.fileId) || undefined,
683
- access_key_id: accessKeyId,
684
- access_key_secret: accessKeySecret,
685
- security_token: securityToken
686
- };
687
- };
688
- const dataNode = isRecord(payload.data) ? payload.data : undefined;
689
- const resultNode = isRecord(payload.result) ? payload.result : undefined;
690
- const candidateNodes = [
691
- dataNode,
692
- isRecord(dataNode?.data) ? dataNode.data : undefined,
693
- isRecord(dataNode?.result) ? dataNode.result : undefined,
694
- resultNode,
695
- isRecord(resultNode?.data) ? resultNode.data : undefined,
696
- payload
697
- ];
698
- for (const node of candidateNodes) {
699
- const hit = tryReadNode(node);
700
- if (hit) {
701
- return hit;
702
- }
703
- }
704
- return null;
705
- }
706
- function throwQwenUploadTokenError(message, opts) {
707
- const err = new Error(message);
708
- err.statusCode = opts?.statusCode ?? 502;
709
- err.code = opts?.code || 'QWENCHAT_UPLOAD_TOKEN_FAILED';
710
- throw err;
711
- }
712
- async function requestUploadToken(baseUrl, file, baxiaTokens, authHeaders) {
713
- const filetype = inferFileCategory(file.mimeType, file.explicitType);
714
- const resp = await fetch(joinUrl(baseUrl, '/api/v2/files/getstsToken'), {
715
- method: 'POST',
716
- headers: qwenCommonHeaders(baxiaTokens, authHeaders, { baseUrl, refererMode: 'web', acceptMode: 'default' }),
717
- body: JSON.stringify({
718
- filename: file.filename,
719
- filesize: file.bytes.length,
720
- filetype
721
- })
722
- });
723
- const parsed = await safeReadJsonResponse(resp);
724
- if (!parsed.ok || !resp.ok) {
725
- const preview = parsed.rawText.slice(0, 200).replace(/\s+/g, ' ').trim();
726
- const suffix = preview ? ` body=${preview}` : '';
727
- throwQwenUploadTokenError(`Failed to get qwen upload token: HTTP ${resp.status}${suffix}`, {
728
- statusCode: resp.ok ? 502 : resp.status,
729
- code: 'QWENCHAT_UPLOAD_TOKEN_HTTP_ERROR'
730
- });
731
- }
732
- const payload = parsed.data;
733
- if (payload.success === false) {
734
- const reason = extractQwenErrorMessage(payload);
735
- const dataNode = isRecord(payload.data) ? payload.data : undefined;
736
- const dataKeys = dataNode ? Object.keys(dataNode).slice(0, 8).join(',') : '';
737
- const preview = parsed.rawText.slice(0, 200).replace(/\s+/g, ' ').trim();
738
- const detail = [reason, dataKeys ? `keys=${dataKeys}` : '', preview ? `body=${preview}` : '']
739
- .filter(Boolean)
740
- .join(' ');
741
- throwQwenUploadTokenError(`Failed to get qwen upload token: ${detail || 'upstream rejected request'}`, {
742
- statusCode: 502,
743
- code: 'QWENCHAT_UPLOAD_TOKEN_REJECTED'
744
- });
745
- }
746
- const tokenData = extractQwenUploadTokenData(payload);
747
- if (!tokenData) {
748
- const dataNode = isRecord(payload.data) ? payload.data : undefined;
749
- const dataKeys = dataNode ? Object.keys(dataNode).slice(0, 8).join(',') : '';
750
- const preview = parsed.rawText.slice(0, 200).replace(/\s+/g, ' ').trim();
751
- const detail = [dataKeys ? `keys=${dataKeys}` : '', preview ? `body=${preview}` : '']
752
- .filter(Boolean)
753
- .join(' ');
754
- const suffix = detail ? ` (${detail})` : '';
755
- throwQwenUploadTokenError(`Failed to get qwen upload token: malformed response${suffix}`, {
756
- statusCode: 502,
757
- code: 'QWENCHAT_UPLOAD_TOKEN_MALFORMED'
758
- });
759
- }
760
- return {
761
- tokenData,
762
- filetype
763
- };
764
- }
765
- function toHex(bytes) {
766
- return Array.from(bytes)
767
- .map((b) => b.toString(16).padStart(2, '0'))
768
- .join('');
769
- }
770
- function formatOssDate(date = new Date()) {
771
- const yyyy = date.getUTCFullYear();
772
- const mm = String(date.getUTCMonth() + 1).padStart(2, '0');
773
- const dd = String(date.getUTCDate()).padStart(2, '0');
774
- const hh = String(date.getUTCHours()).padStart(2, '0');
775
- const mi = String(date.getUTCMinutes()).padStart(2, '0');
776
- const ss = String(date.getUTCSeconds()).padStart(2, '0');
777
- return `${yyyy}${mm}${dd}T${hh}${mi}${ss}Z`;
778
- }
779
- function formatOssDateScope(date = new Date()) {
780
- const yyyy = date.getUTCFullYear();
781
- const mm = String(date.getUTCMonth() + 1).padStart(2, '0');
782
- const dd = String(date.getUTCDate()).padStart(2, '0');
783
- return `${yyyy}${mm}${dd}`;
784
- }
785
- function hmacSha256(key, content) {
786
- const hmac = createHmac('sha256', Buffer.from(key));
787
- hmac.update(typeof content === 'string' ? Buffer.from(content, 'utf8') : Buffer.from(content));
788
- return new Uint8Array(hmac.digest());
789
- }
790
- function sha256Hex(content) {
791
- return createHash('sha256').update(content, 'utf8').digest('hex');
792
- }
793
- function buildOssSignedHeaders(uploadUrl, tokenData, file) {
794
- const parsedUrl = new URL(uploadUrl);
795
- const query = parsedUrl.searchParams;
796
- const credentialFromQuery = decodeURIComponent(query.get('x-oss-credential') || '');
797
- const credentialParts = credentialFromQuery.split('/');
798
- const dateScope = credentialParts[1] || formatOssDateScope();
799
- const region = credentialParts[2] || 'ap-southeast-1';
800
- const xOssDate = query.get('x-oss-date') || formatOssDate();
801
- const hostParts = parsedUrl.hostname.split('.');
802
- const bucket = hostParts.length > 0 ? hostParts[0] : '';
803
- const objectPath = parsedUrl.pathname || '/';
804
- const canonicalUri = bucket ? `/${bucket}${objectPath}` : objectPath;
805
- const xOssUserAgent = 'aliyun-sdk-js/6.23.0';
806
- const canonicalHeaders = [
807
- `content-type:${file.mimeType}`,
808
- 'x-oss-content-sha256:UNSIGNED-PAYLOAD',
809
- `x-oss-date:${xOssDate}`,
810
- `x-oss-security-token:${tokenData.security_token}`,
811
- `x-oss-user-agent:${xOssUserAgent}`
812
- ].join('\n') + '\n';
813
- const canonicalRequest = ['PUT', canonicalUri, '', canonicalHeaders, '', 'UNSIGNED-PAYLOAD'].join('\n');
814
- const credentialScope = `${dateScope}/${region}/oss/aliyun_v4_request`;
815
- const stringToSign = ['OSS4-HMAC-SHA256', xOssDate, credentialScope, sha256Hex(canonicalRequest)].join('\n');
816
- const kDate = hmacSha256(Buffer.from(`aliyun_v4${tokenData.access_key_secret}`, 'utf8'), dateScope);
817
- const kRegion = hmacSha256(kDate, region);
818
- const kService = hmacSha256(kRegion, 'oss');
819
- const kSigning = hmacSha256(kService, 'aliyun_v4_request');
820
- const signature = toHex(hmacSha256(kSigning, stringToSign));
821
- return {
822
- 'Accept': '*/*',
823
- 'Content-Type': file.mimeType,
824
- 'authorization': `OSS4-HMAC-SHA256 Credential=${tokenData.access_key_id}/${credentialScope},Signature=${signature}`,
825
- 'x-oss-content-sha256': 'UNSIGNED-PAYLOAD',
826
- 'x-oss-date': xOssDate,
827
- 'x-oss-security-token': tokenData.security_token,
828
- 'x-oss-user-agent': xOssUserAgent,
829
- 'Referer': `${DEFAULT_QWENCHAT_BASE_URL}/`
830
- };
831
- }
832
- async function uploadFileToQwenOss(file, tokenData) {
833
- const uploadUrl = normalizeInputString(tokenData.file_url).split('?')[0];
834
- if (!uploadUrl) {
835
- throw new Error('Upload failed: missing qwen oss upload url');
836
- }
837
- const signedHeaders = buildOssSignedHeaders(tokenData.file_url, tokenData, file);
838
- const resp = await fetch(uploadUrl, {
839
- method: 'PUT',
840
- headers: signedHeaders,
841
- body: Buffer.from(file.bytes)
842
- });
843
- if (!resp.ok) {
844
- const detail = await resp.text().catch(() => '');
845
- throw new Error(`Upload failed with status ${resp.status}${detail ? `: ${detail}` : ''}`);
846
- }
847
- }
848
- function extractUploadedFileId(fileUrl) {
849
- try {
850
- const pathname = decodeURIComponent(new URL(fileUrl).pathname);
851
- const filename = pathname.split('/').pop() || '';
852
- if (filename.includes('_')) {
853
- return filename.split('_')[0];
854
- }
855
- }
856
- catch {
857
- // fallback uuid
858
- }
859
- return randomUUID();
860
- }
861
- function buildQwenFilePayload(file, tokenData, filetype) {
862
- const now = Date.now();
863
- const id = normalizeInputString(tokenData.file_id) || extractUploadedFileId(tokenData.file_url);
864
- const isDocument = filetype === 'document';
865
- const showType = isDocument ? 'file' : filetype;
866
- const fileClass = isDocument ? 'document' : filetype === 'image' ? 'vision' : filetype;
867
- return {
868
- type: showType,
869
- file: {
870
- created_at: now,
871
- data: {},
872
- filename: file.filename,
873
- hash: null,
874
- id,
875
- meta: {
876
- name: file.filename,
877
- size: file.bytes.length,
878
- content_type: file.mimeType
879
- },
880
- update_at: now
881
- },
882
- id,
883
- url: tokenData.file_url,
884
- name: file.filename,
885
- collection_name: '',
886
- progress: 0,
887
- status: 'uploaded',
888
- is_uploading: false,
889
- error: '',
890
- showType,
891
- file_class: fileClass,
892
- itemId: randomUUID(),
893
- greenNet: 'success',
894
- size: file.bytes.length,
895
- file_type: file.mimeType,
896
- uploadTaskId: randomUUID()
897
- };
898
- }
899
- async function ensureUploadStatusForNonVideo(baseUrl, filetype, baxiaTokens, authHeaders) {
900
- if (filetype === 'video') {
901
- return;
902
- }
903
- const maxAttempts = 6;
904
- for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
905
- const resp = await fetch(joinUrl(baseUrl, '/api/v2/users/status'), {
906
- method: 'POST',
907
- headers: qwenCommonHeaders(baxiaTokens, authHeaders, { baseUrl, refererMode: 'web', acceptMode: 'default' }),
908
- body: JSON.stringify({
909
- typarms: {
910
- typarm1: 'web',
911
- typarm2: '',
912
- typarm3: 'prod',
913
- typarm4: 'qwen_chat',
914
- typarm5: 'product',
915
- orgid: 'tongyi'
916
- }
917
- })
918
- });
919
- if (!resp.ok) {
920
- const detail = await resp.text().catch(() => '');
921
- throw new Error(`Upload status check failed with status ${resp.status}${detail ? `: ${detail}` : ''}`);
922
- }
923
- const payload = (await resp.json().catch(() => ({})));
924
- if (payload.data === true) {
925
- return;
926
- }
927
- if (attempt < maxAttempts) {
928
- await new Promise((resolve) => setTimeout(resolve, 400));
929
- }
930
- }
931
- throw new Error('Upload status not ready for non-video file');
932
- }
933
- async function parseDocumentIfNeeded(baseUrl, qwenFilePayload, filetype, baxiaTokens, authHeaders) {
934
- if (filetype !== 'document') {
935
- return;
936
- }
937
- const fileId = normalizeInputString(qwenFilePayload.id);
938
- if (!fileId) {
939
- return;
940
- }
941
- const resp = await fetch(joinUrl(baseUrl, '/api/v2/files/parse'), {
942
- method: 'POST',
943
- headers: qwenCommonHeaders(baxiaTokens, authHeaders, { baseUrl, refererMode: 'web', acceptMode: 'default' }),
944
- body: JSON.stringify({ file_id: fileId })
945
- });
946
- const text = await resp.text().catch(() => '');
947
- if (!resp.ok) {
948
- throw new Error(`Document parse failed with status ${resp.status}${text ? `: ${text}` : ''}`);
949
- }
950
- if (text) {
951
- try {
952
- const payload = JSON.parse(text);
953
- if (payload.success === false) {
954
- const message = normalizeInputString(payload.msg) || 'Document parse rejected';
955
- throw new Error(message);
956
- }
957
- }
958
- catch (error) {
959
- if (error instanceof Error) {
960
- throw error;
961
- }
962
- }
963
- }
964
- }
965
- export async function uploadAttachments(args) {
966
- const files = [];
967
- for (const rawAttachment of args.attachments) {
968
- const loaded = await loadAttachmentBytes(rawAttachment);
969
- const { tokenData, filetype } = await requestUploadToken(args.baseUrl, loaded, args.baxiaTokens, args.authHeaders);
970
- await uploadFileToQwenOss(loaded, tokenData);
971
- const qwenFilePayload = buildQwenFilePayload(loaded, tokenData, filetype);
972
- await ensureUploadStatusForNonVideo(args.baseUrl, filetype, args.baxiaTokens, args.authHeaders);
973
- await parseDocumentIfNeeded(args.baseUrl, qwenFilePayload, filetype, args.baxiaTokens, args.authHeaders);
974
- if (filetype === 'document') {
975
- await ensureUploadStatusForNonVideo(args.baseUrl, filetype, args.baxiaTokens, args.authHeaders);
976
- }
977
- files.push(qwenFilePayload);
978
- }
979
- return { files };
980
- }
981
- export function extractQwenChatPayload(request) {
982
- const container = isRecord(request) ? request : {};
983
- const payload = isRecord(container.data) ? container.data : container;
984
- const model = normalizeInputString(payload.model) || 'qwen3.6-plus';
985
- const directMessages = Array.isArray(payload.messages) ? payload.messages : [];
986
- const compatPrompt = normalizeInputString(payload.prompt);
987
- const messages = directMessages.length > 0
988
- ? directMessages
989
- : compatPrompt
990
- ? [{ role: 'user', content: compatPrompt }]
991
- : [];
992
- const streamFlag = payload.stream;
993
- // Follow OpenAI semantics: stream defaults to false unless explicitly true.
994
- const stream = streamFlag === true;
995
- const metadata = isRecord(payload.metadata)
996
- ? payload.metadata
997
- : isRecord(container.metadata)
998
- ? container.metadata
999
- : undefined;
1000
- return {
1001
- model,
1002
- messages,
1003
- stream,
1004
- tools: payload.tools,
1005
- metadata
1006
- };
1007
- }
1008
- export function shouldUseSearchMode(payload) {
1009
- if (parseQwenImageGenerationOptions(payload.metadata).enabled) {
1010
- return false;
1011
- }
1012
- if (payload.metadata?.qwenWebSearch === true || payload.metadata?.webSearch === true) {
1013
- return true;
1014
- }
1015
- return false;
1016
- }
1017
- function shouldUseImageGenerationMode(payload) {
1018
- return parseQwenImageGenerationOptions(payload.metadata).enabled;
1019
- }
1020
- function extractChatIdFromCreatePayload(payload) {
1021
- const readChatIdFromText = (value) => {
1022
- const text = normalizeInputString(value);
1023
- if (!text) {
1024
- return '';
1025
- }
1026
- const namedMatch = text.match(/(?:chat[_-]?id|session[_-]?id|conversation[_-]?id)\s*[:=]\s*["']?([a-zA-Z0-9._:-]{8,})["']?/i);
1027
- if (namedMatch?.[1]) {
1028
- return namedMatch[1].trim();
1029
- }
1030
- return '';
1031
- };
1032
- const readDirect = (node) => {
1033
- if (!node) {
1034
- return '';
1035
- }
1036
- return (normalizeInputString(node.id) ||
1037
- normalizeInputString(node.chat_id) ||
1038
- normalizeInputString(node.chatId) ||
1039
- normalizeInputString(node.session_id) ||
1040
- normalizeInputString(node.sessionId) ||
1041
- normalizeInputString(node.conversation_id) ||
1042
- normalizeInputString(node.conversationId) ||
1043
- readChatIdFromText(node.details) ||
1044
- readChatIdFromText(node.message) ||
1045
- readChatIdFromText(node.msg));
1046
- };
1047
- const root = payload;
1048
- const dataNode = isRecord(root.data) ? root.data : undefined;
1049
- const resultNode = isRecord(root.result) ? root.result : undefined;
1050
- const chatNode = isRecord(dataNode?.chat) ? dataNode.chat : undefined;
1051
- const dataDetailsNode = isRecord(dataNode?.details) ? dataNode.details : undefined;
1052
- const resultDetailsNode = isRecord(resultNode?.details) ? resultNode.details : undefined;
1053
- const rootDetailsNode = isRecord(root.details) ? root.details : undefined;
1054
- const nestedDataNode = isRecord(dataNode?.data) ? dataNode.data : undefined;
1055
- const nestedResultNode = isRecord(dataNode?.result) ? dataNode.result : undefined;
1056
- const conversationNode = isRecord(dataNode?.conversation) ? dataNode.conversation : undefined;
1057
- const sessionNode = isRecord(dataNode?.session) ? dataNode.session : undefined;
1058
- return (readDirect(dataNode) ||
1059
- readDirect(chatNode) ||
1060
- readDirect(conversationNode) ||
1061
- readDirect(sessionNode) ||
1062
- readDirect(nestedDataNode) ||
1063
- readDirect(nestedResultNode) ||
1064
- readDirect(resultNode) ||
1065
- readDirect(dataDetailsNode) ||
1066
- readDirect(resultDetailsNode) ||
1067
- readDirect(rootDetailsNode) ||
1068
- readDirect(root));
1069
- }
1070
- function extractCreateErrorMessage(payload) {
1071
- const reason = extractQwenErrorMessage(payload);
1072
- if (reason) {
1073
- return reason;
1074
- }
1075
- const dataNode = isRecord(payload.data) ? payload.data : undefined;
1076
- const detailsNode = isRecord(dataNode?.details) ? dataNode.details : undefined;
1077
- const detailsParts = [
1078
- detailsNode ? normalizeInputString(detailsNode.message) : '',
1079
- detailsNode ? normalizeInputString(detailsNode.msg) : '',
1080
- detailsNode ? normalizeInputString(detailsNode.details) : '',
1081
- detailsNode ? normalizeInputString(detailsNode.template) : '',
1082
- detailsNode ? normalizeInputString(detailsNode.code) : ''
1083
- ].filter(Boolean);
1084
- return detailsParts[0] || '';
1085
- }
1086
- function inferCreateSessionStatusCode(payload, reason) {
1087
- const dataNode = isRecord(payload.data) ? payload.data : undefined;
1088
- const normalized = [
1089
- normalizeInputString(payload.code),
1090
- normalizeInputString(dataNode?.code),
1091
- reason
1092
- ]
1093
- .filter(Boolean)
1094
- .join(' ')
1095
- .toLowerCase();
1096
- if (normalized.includes('ratelimit') ||
1097
- normalized.includes('rate_limit') ||
1098
- normalized.includes('daily usage limit') ||
1099
- normalized.includes('too many request') ||
1100
- normalized.includes('达到今日的使用上限') ||
1101
- normalized.includes('请求过于频繁')) {
1102
- return 429;
1103
- }
1104
- if (normalized.includes('forbidden') ||
1105
- normalized.includes('permission denied') ||
1106
- normalized.includes('没有权限') ||
1107
- normalized.includes('无权限') ||
1108
- normalized.includes('permission')) {
1109
- return 403;
1110
- }
1111
- if (normalized.includes('unauthorized') ||
1112
- normalized.includes('invalid token') ||
1113
- normalized.includes('login') ||
1114
- normalized.includes('auth') ||
1115
- normalized.includes('未登录')) {
1116
- return 401;
1117
- }
1118
- return 502;
1119
- }
1120
- function parseQwenUpstreamBusinessErrorFromRaw(rawPayload) {
1121
- const trimmed = rawPayload.trim();
1122
- if (!trimmed || trimmed.startsWith('data:')) {
1123
- return null;
1124
- }
1125
- try {
1126
- const parsed = JSON.parse(trimmed);
1127
- if (!isRecord(parsed)) {
1128
- return null;
1129
- }
1130
- const success = parsed.success;
1131
- const hasErrorNode = isRecord(parsed.error);
1132
- const hasCode = Boolean(normalizeInputString(parsed.code));
1133
- // Only treat as business rejection when payload explicitly signals failure.
1134
- if (success !== false && !hasErrorNode && !hasCode) {
1135
- return null;
1136
- }
1137
- const reason = extractQwenErrorMessage(parsed) || normalizeInputString(parsed.message) || 'upstream rejected request';
1138
- const statusCode = inferCreateSessionStatusCode(parsed, reason);
1139
- const code = statusCode === 429 ? 'QWENCHAT_RATE_LIMITED' : 'QWENCHAT_COMPLETION_REJECTED';
1140
- return {
1141
- message: `QwenChat upstream rejected completion request: ${reason}`,
1142
- statusCode,
1143
- code
1144
- };
1145
- }
1146
- catch {
1147
- return null;
1148
- }
1149
- }
1150
- export async function createQwenChatSession(args) {
1151
- const resp = await fetch(joinUrl(args.baseUrl, DEFAULT_QWENCHAT_CHAT_CREATE_ENDPOINT), {
1152
- method: 'POST',
1153
- headers: qwenCommonHeaders(args.baxiaTokens, args.authHeaders, {
1154
- baseUrl: args.baseUrl,
1155
- refererMode: 'guest',
1156
- acceptMode: 'json'
1157
- }),
1158
- body: JSON.stringify({
1159
- title: '新建对话',
1160
- models: [args.model],
1161
- chat_mode: 'guest',
1162
- chat_type: args.chatType,
1163
- timestamp: Date.now(),
1164
- project_id: ''
1165
- })
1166
- });
1167
- const parsed = await safeReadJsonResponse(resp);
1168
- if (!parsed.ok || !resp.ok) {
1169
- const bodyPreview = parsed.rawText.slice(0, 280).replace(/\s+/g, ' ').trim();
1170
- const suffix = bodyPreview ? ` body=${bodyPreview}` : '';
1171
- const err = new Error(`Failed to create qwenchat session: HTTP ${resp.status}${suffix}`);
1172
- err.statusCode = resp.ok ? 502 : resp.status;
1173
- err.code = 'QWENCHAT_CREATE_SESSION_FAILED';
1174
- throw err;
1175
- }
1176
- const chatId = extractChatIdFromCreatePayload(parsed.data);
1177
- const success = parsed.data.success === true;
1178
- if (chatId) {
1179
- return chatId;
1180
- }
1181
- if (parsed.data.success === false) {
1182
- const reason = extractCreateErrorMessage(parsed.data);
1183
- const dataNode = isRecord(parsed.data.data) ? parsed.data.data : undefined;
1184
- const dataKeys = dataNode ? Object.keys(dataNode).slice(0, 8).join(',') : '';
1185
- const detail = [reason, dataKeys ? `keys=${dataKeys}` : ''].filter(Boolean).join(' ');
1186
- const suffix = detail ? ` (${detail})` : '';
1187
- const err = new Error(`Failed to create qwenchat session: upstream rejected request${suffix}`);
1188
- err.statusCode = inferCreateSessionStatusCode(parsed.data, reason);
1189
- err.code = 'QWENCHAT_CREATE_SESSION_REJECTED';
1190
- throw err;
1191
- }
1192
- if (!chatId) {
1193
- const reason = extractCreateErrorMessage(parsed.data);
1194
- const dataNode = isRecord(parsed.data.data) ? parsed.data.data : undefined;
1195
- const dataKeys = dataNode ? Object.keys(dataNode).slice(0, 8).join(',') : '';
1196
- const detail = reason || (dataKeys ? `keys=${dataKeys}` : '') || (success ? 'success=true' : '');
1197
- const suffix = detail ? ` (${detail})` : '';
1198
- const err = new Error(`Failed to create qwenchat session: missing chat id${suffix}`);
1199
- err.statusCode = 502;
1200
- err.code = 'QWENCHAT_CREATE_SESSION_FAILED';
1201
- throw err;
1202
- }
1203
- return chatId;
1204
- }
1205
- export function buildQwenChatCompletionRequest(args) {
1206
- const request = {
1207
- stream: true,
1208
- version: '2.1',
1209
- incremental_output: true,
1210
- chat_id: args.chatId,
1211
- chat_mode: 'guest',
1212
- model: args.model,
1213
- parent_id: null,
1214
- messages: [
1215
- {
1216
- fid: randomUUID(),
1217
- parentId: null,
1218
- childrenIds: [randomUUID()],
1219
- role: 'user',
1220
- content: args.content,
1221
- user_action: 'chat',
1222
- files: args.uploadedFiles,
1223
- timestamp: Date.now(),
1224
- models: [args.model],
1225
- chat_type: args.chatType,
1226
- feature_config: {
1227
- thinking_enabled: true,
1228
- output_schema: 'phase',
1229
- research_mode: 'normal',
1230
- auto_thinking: true,
1231
- thinking_mode: 'Auto',
1232
- thinking_format: 'summary',
1233
- auto_search: args.chatType === 'search'
1234
- },
1235
- extra: { meta: { subChatType: args.chatType } },
1236
- sub_chat_type: args.chatType,
1237
- parent_id: null
1238
- }
1239
- ],
1240
- timestamp: Date.now()
1241
- };
1242
- if (args.chatType === 't2i' && args.imageSize) {
1243
- request.size = args.imageSize;
1244
- }
1245
- return request;
1246
- }
1247
- function extractReasoningContentFromDelta(delta) {
1248
- const direct = normalizeInputString(delta.reasoning_content || delta.reasoning);
1249
- if (direct) {
1250
- return direct;
1251
- }
1252
- const phase = normalizeInputString(delta.phase);
1253
- if (phase !== 'thinking_summary') {
1254
- return '';
1255
- }
1256
- const extra = isRecord(delta.extra) ? delta.extra : undefined;
1257
- const summaryThought = extra && isRecord(extra.summary_thought) ? extra.summary_thought : undefined;
1258
- const content = summaryThought?.content;
1259
- if (typeof content === 'string') {
1260
- return normalizeInputString(content);
1261
- }
1262
- if (Array.isArray(content)) {
1263
- const parts = content
1264
- .map((item) => {
1265
- if (typeof item === 'string')
1266
- return normalizeInputString(item);
1267
- if (isRecord(item))
1268
- return normalizeInputString(item.text || item.content || item.value);
1269
- return '';
1270
- })
1271
- .filter(Boolean);
1272
- return parts.join('\n');
1273
- }
1274
- return '';
1275
- }
1276
- function mapUpstreamDeltaToOpenAi(deltaRaw) {
1277
- if (!isRecord(deltaRaw)) {
1278
- return null;
1279
- }
1280
- const mapped = {};
1281
- if (normalizeInputString(deltaRaw.role) === 'assistant') {
1282
- mapped.role = 'assistant';
1283
- }
1284
- const content = normalizeInputString(deltaRaw.content);
1285
- if (content) {
1286
- mapped.content = content;
1287
- }
1288
- const reasoning = extractReasoningContentFromDelta(deltaRaw);
1289
- if (reasoning) {
1290
- mapped.reasoning_content = reasoning;
1291
- }
1292
- return Object.keys(mapped).length > 0 ? mapped : null;
1293
- }
1294
- function mapUsageToOpenAi(usageRaw) {
1295
- if (!isRecord(usageRaw)) {
1296
- return undefined;
1297
- }
1298
- const inputTokens = Number(usageRaw.input_tokens || 0);
1299
- const outputTokens = Number(usageRaw.output_tokens || 0);
1300
- const totalTokens = Number(usageRaw.total_tokens || inputTokens + outputTokens);
1301
- const usage = {
1302
- prompt_tokens: Number.isFinite(inputTokens) ? inputTokens : 0,
1303
- completion_tokens: Number.isFinite(outputTokens) ? outputTokens : 0,
1304
- total_tokens: Number.isFinite(totalTokens) ? totalTokens : 0
1305
- };
1306
- if (isRecord(usageRaw.input_tokens_details) && Object.keys(usageRaw.input_tokens_details).length > 0) {
1307
- usage.prompt_tokens_details = usageRaw.input_tokens_details;
1308
- }
1309
- if (isRecord(usageRaw.output_tokens_details) && Object.keys(usageRaw.output_tokens_details).length > 0) {
1310
- usage.completion_tokens_details = usageRaw.output_tokens_details;
1311
- }
1312
- return usage;
1313
- }
1314
- function createOpenAiChunk(args) {
1315
- const chunk = {
1316
- id: args.id,
1317
- object: 'chat.completion.chunk',
1318
- created: args.created,
1319
- model: args.model,
1320
- choices: [
1321
- {
1322
- index: 0,
1323
- delta: args.delta,
1324
- finish_reason: args.finishReason
1325
- }
1326
- ]
1327
- };
1328
- if (args.usage) {
1329
- chunk.usage = args.usage;
1330
- }
1331
- return chunk;
1332
- }
1333
- function processQwenSsePayloadLines(args) {
1334
- for (const line of args.payload.split('\n')) {
1335
- const trimmed = line.trimStart();
1336
- if (!trimmed.startsWith('data:'))
1337
- continue;
1338
- const data = trimmed.slice(5).trim();
1339
- if (!data)
1340
- continue;
1341
- if (data === '[DONE]') {
1342
- args.onDone();
1343
- continue;
1344
- }
1345
- try {
1346
- const parsed = JSON.parse(data);
1347
- const choiceNode = Array.isArray(parsed.choices) && parsed.choices.length > 0 && isRecord(parsed.choices[0])
1348
- ? parsed.choices[0]
1349
- : undefined;
1350
- const deltaNode = choiceNode && isRecord(choiceNode.delta) ? choiceNode.delta : undefined;
1351
- const delta = mapUpstreamDeltaToOpenAi(deltaNode);
1352
- const finishReason = normalizeInputString(choiceNode?.finish_reason) || null;
1353
- if (finishReason && args.onFinishReason) {
1354
- args.onFinishReason(finishReason);
1355
- }
1356
- const usage = mapUsageToOpenAi(parsed.usage);
1357
- if (usage && args.collect) {
1358
- args.collect.usageRef.usage = usage;
1359
- }
1360
- if (delta && args.collect) {
1361
- const content = normalizeInputString(delta.content);
1362
- if (content)
1363
- args.collect.contentParts.push(content);
1364
- const reasoning = normalizeInputString(delta.reasoning_content);
1365
- if (reasoning)
1366
- args.collect.reasoningParts.push(reasoning);
1367
- }
1368
- if (args.collect && deltaNode) {
1369
- const phase = normalizeInputString(deltaNode.phase);
1370
- const rawContent = normalizeInputString(deltaNode.content);
1371
- if (phase === 'image_gen' && /^https?:\/\//i.test(rawContent)) {
1372
- args.collect.imageUrls.push(rawContent);
1373
- }
1374
- }
1375
- if (delta || finishReason || usage) {
1376
- const deltaForEmit = delta ? { ...delta } : {};
1377
- args.onChunk(createOpenAiChunk({
1378
- id: args.responseId,
1379
- created: args.created,
1380
- model: args.model,
1381
- delta: deltaForEmit,
1382
- finishReason: args.includeFinishReason === false ? null : finishReason,
1383
- usage
1384
- }));
1385
- }
1386
- }
1387
- catch {
1388
- // ignore malformed data line
1389
- }
1390
- }
1391
- }
1392
- export function createOpenAiMappedSseStream(input) {
1393
- const output = new PassThrough();
1394
- const responseId = `chatcmpl-${randomUUID()}`;
1395
- const created = Math.floor(Date.now() / 1000);
1396
- let doneWritten = false;
1397
- let buffer = '';
1398
- const contentParts = [];
1399
- const reasoningParts = [];
1400
- const imageUrls = [];
1401
- const usageRef = {};
1402
- let lastUpstreamFinishReason = null;
1403
- const writeDone = () => {
1404
- if (doneWritten)
1405
- return;
1406
- doneWritten = true;
1407
- output.write('data: [DONE]\n\n');
1408
- };
1409
- input.upstreamStream.on('data', (chunk) => {
1410
- buffer += typeof chunk === 'string' ? chunk : chunk.toString('utf8');
1411
- const lines = buffer.split('\n');
1412
- buffer = lines.pop() || '';
1413
- for (const line of lines) {
1414
- processQwenSsePayloadLines({
1415
- payload: `${line}\n`,
1416
- onChunk: (mappedChunk) => {
1417
- output.write(`data: ${JSON.stringify(mappedChunk)}\n\n`);
1418
- },
1419
- onDone: () => {
1420
- // defer done to stream end, so harvest-produced final tool_calls can be emitted first.
1421
- },
1422
- onFinishReason: (reason) => {
1423
- lastUpstreamFinishReason = reason;
1424
- },
1425
- includeFinishReason: false,
1426
- collect: { contentParts, reasoningParts, imageUrls, usageRef },
1427
- responseId,
1428
- created,
1429
- model: input.model
1430
- });
1431
- }
1432
- });
1433
- input.upstreamStream.on('end', () => {
1434
- if (buffer.trim()) {
1435
- const upstreamBusinessError = parseQwenUpstreamBusinessErrorFromRaw(buffer);
1436
- if (upstreamBusinessError) {
1437
- output.write(`data: ${JSON.stringify({
1438
- error: {
1439
- message: upstreamBusinessError.message,
1440
- code: upstreamBusinessError.code,
1441
- status: upstreamBusinessError.statusCode
1442
- }
1443
- })}\n\n`);
1444
- writeDone();
1445
- output.end();
1446
- return;
1447
- }
1448
- processQwenSsePayloadLines({
1449
- payload: buffer,
1450
- onChunk: (mappedChunk) => {
1451
- output.write(`data: ${JSON.stringify(mappedChunk)}\n\n`);
1452
- },
1453
- onDone: () => {
1454
- // defer done to stream end, so harvest-produced final tool_calls can be emitted first.
1455
- },
1456
- onFinishReason: (reason) => {
1457
- lastUpstreamFinishReason = reason;
1458
- },
1459
- includeFinishReason: false,
1460
- collect: { contentParts, reasoningParts, imageUrls, usageRef },
1461
- responseId,
1462
- created,
1463
- model: input.model
1464
- });
1465
- }
1466
- const dedupImageUrls = Array.from(new Set(imageUrls));
1467
- const aggregatedContent = dedupImageUrls.length > 0
1468
- ? dedupImageUrls.join('\n')
1469
- : contentParts.join('');
1470
- const harvested = applyStandardToolTextHarvestToChatPayload({
1471
- id: responseId,
1472
- object: 'chat.completion',
1473
- created,
1474
- model: input.model,
1475
- choices: [
1476
- {
1477
- index: 0,
1478
- finish_reason: 'stop',
1479
- message: {
1480
- role: 'assistant',
1481
- content: aggregatedContent,
1482
- ...(reasoningParts.length ? { reasoning_content: reasoningParts.join('') } : {})
1483
- }
1484
- }
1485
- ],
1486
- ...(usageRef.usage ? { usage: usageRef.usage } : {})
1487
- });
1488
- const harvestedChoice = Array.isArray(harvested.choices) && harvested.choices.length > 0 && isRecord(harvested.choices[0])
1489
- ? harvested.choices[0]
1490
- : undefined;
1491
- const harvestedMessage = harvestedChoice && isRecord(harvestedChoice.message)
1492
- ? harvestedChoice.message
1493
- : undefined;
1494
- const harvestedToolCalls = harvestedMessage && Array.isArray(harvestedMessage.tool_calls)
1495
- ? harvestedMessage.tool_calls
1496
- : [];
1497
- const finalFinishReason = harvestedToolCalls.length > 0
1498
- ? 'tool_calls'
1499
- : lastUpstreamFinishReason || 'stop';
1500
- const finalDelta = harvestedToolCalls.length > 0
1501
- ? { tool_calls: harvestedToolCalls }
1502
- : {};
1503
- output.write(`data: ${JSON.stringify(createOpenAiChunk({
1504
- id: responseId,
1505
- created,
1506
- model: input.model,
1507
- delta: finalDelta,
1508
- finishReason: finalFinishReason,
1509
- usage: usageRef.usage
1510
- }))}\n\n`);
1511
- writeDone();
1512
- output.end();
1513
- });
1514
- input.upstreamStream.on('error', (error) => {
1515
- output.write(`data: ${JSON.stringify({ error: { message: error instanceof Error ? error.message : String(error) } })}\n\n`);
1516
- writeDone();
1517
- output.end();
1518
- });
1519
- return output;
1520
- }
1521
- export async function collectQwenSseAsOpenAiResult(args) {
1522
- const contentParts = [];
1523
- const reasoningParts = [];
1524
- const imageUrls = [];
1525
- const usageRef = {};
1526
- let buffer = '';
1527
- await new Promise((resolve, reject) => {
1528
- args.upstreamStream.on('data', (chunk) => {
1529
- buffer += typeof chunk === 'string' ? chunk : chunk.toString('utf8');
1530
- });
1531
- args.upstreamStream.on('end', resolve);
1532
- args.upstreamStream.on('error', reject);
1533
- });
1534
- const upstreamBusinessError = parseQwenUpstreamBusinessErrorFromRaw(buffer);
1535
- if (upstreamBusinessError) {
1536
- const err = new Error(upstreamBusinessError.message);
1537
- err.statusCode = upstreamBusinessError.statusCode;
1538
- err.code = upstreamBusinessError.code;
1539
- throw err;
1540
- }
1541
- processQwenSsePayloadLines({
1542
- payload: buffer,
1543
- onChunk: () => {
1544
- // no-op in aggregate mode
1545
- },
1546
- onDone: () => {
1547
- // no-op in aggregate mode
1548
- },
1549
- collect: { contentParts, reasoningParts, imageUrls, usageRef },
1550
- responseId: `chatcmpl-${randomUUID()}`,
1551
- created: Math.floor(Date.now() / 1000),
1552
- model: args.model
1553
- });
1554
- const dedupImageUrls = Array.from(new Set(imageUrls));
1555
- const aggregatedContent = dedupImageUrls.length > 0
1556
- ? dedupImageUrls.join('\n')
1557
- : contentParts.join('');
1558
- const result = {
1559
- id: `chatcmpl-${randomUUID()}`,
1560
- object: 'chat.completion',
1561
- created: Math.floor(Date.now() / 1000),
1562
- model: args.model,
1563
- choices: [
1564
- {
1565
- index: 0,
1566
- message: {
1567
- role: 'assistant',
1568
- content: aggregatedContent,
1569
- ...(reasoningParts.length ? { reasoning_content: reasoningParts.join('') } : {})
1570
- },
1571
- finish_reason: 'stop'
1572
- }
1573
- ]
1574
- };
1575
- if (usageRef.usage) {
1576
- result.usage = usageRef.usage;
1577
- }
1578
- const harvested = applyStandardToolTextHarvestToChatPayload(result);
1579
- const firstChoice = Array.isArray(harvested.choices) && harvested.choices.length > 0 && isRecord(harvested.choices[0])
1580
- ? harvested.choices[0]
1581
- : undefined;
1582
- const messageNode = firstChoice && isRecord(firstChoice.message) ? firstChoice.message : undefined;
1583
- const finishReason = normalizeInputString(firstChoice?.finish_reason) || 'stop';
1584
- const content = normalizeInputString(messageNode?.content);
1585
- const reasoning = normalizeInputString(messageNode?.reasoning_content);
1586
- const toolCalls = messageNode && Array.isArray(messageNode.tool_calls) ? messageNode.tool_calls : [];
1587
- if (finishReason === 'stop' && !content && !reasoning && toolCalls.length === 0) {
1588
- const err = new Error('QwenChat upstream returned an empty assistant message');
1589
- err.statusCode = 502;
1590
- err.code = 'QWENCHAT_EMPTY_ASSISTANT';
1591
- throw err;
1592
- }
1593
- return harvested;
1594
- }
1595
- export async function buildQwenChatSendPlan(input) {
1596
- const normalizedPayload = applyStandardToolTextRequest(input.payload);
1597
- if (!Array.isArray(normalizedPayload.messages) || normalizedPayload.messages.length === 0) {
1598
- const err = new Error('Messages are required');
1599
- err.statusCode = 400;
1600
- err.code = 'QWENCHAT_INVALID_REQUEST';
1601
- throw err;
1602
- }
1603
- const imageGenOptions = parseQwenImageGenerationOptions(normalizedPayload.metadata);
1604
- const chatType = shouldUseImageGenerationMode(normalizedPayload)
1605
- ? 't2i'
1606
- : shouldUseSearchMode(normalizedPayload)
1607
- ? 'search'
1608
- : 't2t';
1609
- const chatId = await createQwenChatSession({
1610
- baseUrl: input.baseUrl,
1611
- model: normalizedPayload.model,
1612
- chatType,
1613
- baxiaTokens: input.baxiaTokens,
1614
- authHeaders: input.authHeaders
1615
- });
1616
- const parsedMessages = parseIncomingMessages(normalizedPayload.messages);
1617
- const finalContent = chatType === 't2i' && imageGenOptions.count > 1
1618
- ? `${parsedMessages.content}\n\n(Generate ${imageGenOptions.count} images.)`
1619
- : parsedMessages.content;
1620
- const uploaded = parsedMessages.attachments.length
1621
- ? await uploadAttachments({
1622
- baseUrl: input.baseUrl,
1623
- attachments: parsedMessages.attachments,
1624
- baxiaTokens: input.baxiaTokens,
1625
- authHeaders: input.authHeaders
1626
- })
1627
- : { files: [] };
1628
- const completionBody = buildQwenChatCompletionRequest({
1629
- chatId,
1630
- model: normalizedPayload.model,
1631
- content: finalContent,
1632
- uploadedFiles: uploaded.files,
1633
- chatType,
1634
- ...(chatType === 't2i' ? { imageSize: imageGenOptions.sizeRatio } : {})
1635
- });
1636
- const completionHeaders = {
1637
- ...qwenCommonHeaders(input.baxiaTokens, input.authHeaders, {
1638
- baseUrl: input.baseUrl,
1639
- refererMode: 'guest',
1640
- acceptMode: 'json'
1641
- }),
1642
- version: '0.2.9'
1643
- };
1644
- return {
1645
- completionUrl: `${joinUrl(input.baseUrl, DEFAULT_QWENCHAT_COMPLETION_ENDPOINT)}?chat_id=${encodeURIComponent(chatId)}`,
1646
- completionHeaders,
1647
- completionBody
1648
- };
1649
- }
1650
- function applyStandardToolTextRequest(payload) {
1651
- if (!Array.isArray(payload.tools) || payload.tools.length === 0) {
1652
- return payload;
1653
- }
1654
- const transformed = applyStandardToolTextRequestTransform({
1655
- model: payload.model,
1656
- messages: payload.messages,
1657
- tools: payload.tools,
1658
- metadata: payload.metadata
1659
- }, {
1660
- providerProtocol: 'openai-chat',
1661
- entryEndpoint: '/v1/chat/completions'
1662
- });
1663
- const prompt = normalizeInputString(transformed.prompt);
1664
- if (!prompt) {
1665
- const err = new Error('QwenChat tool-text transform failed: prompt is empty');
1666
- err.statusCode = 422;
1667
- err.code = 'QWENCHAT_TOOL_TEXT_TRANSFORM_FAILED';
1668
- throw err;
1669
- }
1670
- return {
1671
- ...payload,
1672
- messages: [{ role: 'user', content: prompt }],
1673
- tools: undefined
1674
- };
1675
- }
1676
- export function extractForwardAuthHeaders(headers) {
1677
- const out = {};
1678
- for (const [key, value] of Object.entries(headers || {})) {
1679
- const lowered = key.toLowerCase();
1680
- if (lowered === 'authorization' || lowered === 'cookie') {
1681
- out[key] = value;
1682
- }
1683
- }
1684
- return out;
1685
- }
1686
- export function classifyQwenChatProviderIdentity(input) {
1687
- const candidates = [
1688
- normalizeInputString(input.providerFamily).toLowerCase(),
1689
- normalizeInputString(input.providerId).toLowerCase(),
1690
- normalizeInputString(input.providerKey).toLowerCase(),
1691
- normalizeInputString(input.compatibilityProfile).toLowerCase()
1692
- ].filter(Boolean);
1693
- return candidates.some((value) => value === 'qwenchat' ||
1694
- value.startsWith('qwenchat.') ||
1695
- value.includes('qwenchat') ||
1696
- value === 'chat:qwenchat-web');
1697
- }
1698
- //# sourceMappingURL=qwenchat-http-provider-helpers.js.map