@prometheus-ai/ai 0.5.4 → 0.5.8

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 (377) hide show
  1. package/dist/types/auth-broker/remote-store.d.ts +2 -1
  2. package/dist/types/auth-broker/wire-schemas.d.ts +4 -1
  3. package/dist/types/auth-gateway/server.d.ts +19 -0
  4. package/dist/types/auth-gateway/types.d.ts +9 -3
  5. package/dist/types/auth-retry.d.ts +119 -0
  6. package/dist/types/auth-storage.d.ts +217 -8
  7. package/dist/types/errors.d.ts +24 -0
  8. package/dist/types/index.d.ts +5 -9
  9. package/dist/types/provider-details.d.ts +1 -1
  10. package/dist/types/providers/amazon-bedrock.d.ts +12 -6
  11. package/dist/types/providers/anthropic-client.d.ts +10 -3
  12. package/dist/types/providers/anthropic-messages-server-schema.d.ts +2 -2
  13. package/dist/types/providers/anthropic-messages-server.d.ts +3 -3
  14. package/dist/types/providers/anthropic-wire.d.ts +3 -3
  15. package/dist/types/providers/anthropic.d.ts +41 -34
  16. package/dist/types/providers/aws-credentials.d.ts +8 -0
  17. package/dist/types/providers/azure-openai-responses.d.ts +1 -0
  18. package/dist/types/providers/google-gemini-cli.d.ts +22 -1
  19. package/dist/types/providers/google-shared.d.ts +22 -0
  20. package/dist/types/providers/google-types.d.ts +13 -1
  21. package/dist/types/providers/mock.d.ts +8 -3
  22. package/dist/types/providers/ollama.d.ts +6 -0
  23. package/dist/types/providers/openai-chat-server-schema.d.ts +6 -3
  24. package/dist/types/providers/openai-chat-server.d.ts +3 -3
  25. package/dist/types/providers/openai-chat-wire.d.ts +644 -0
  26. package/dist/types/providers/openai-codex/request-transformer.d.ts +8 -0
  27. package/dist/types/providers/openai-codex/response-handler.d.ts +9 -0
  28. package/dist/types/providers/openai-codex-responses.d.ts +31 -2
  29. package/dist/types/providers/openai-completions-compat.d.ts +2 -25
  30. package/dist/types/providers/openai-completions.d.ts +2 -10
  31. package/dist/types/providers/openai-responses-server-schema.d.ts +4 -4
  32. package/dist/types/providers/openai-responses-server.d.ts +2 -2
  33. package/dist/types/providers/openai-responses-shared.d.ts +49 -9
  34. package/dist/types/providers/openai-responses-wire.d.ts +6065 -0
  35. package/dist/types/providers/openai-responses.d.ts +13 -4
  36. package/dist/types/providers/prometheus-native-client.d.ts +9 -0
  37. package/dist/types/providers/prometheus-native-server.d.ts +4 -3
  38. package/dist/types/providers/transform-messages.d.ts +1 -2
  39. package/dist/types/rate-limit-utils.d.ts +3 -2
  40. package/dist/types/registry/aimlapi.d.ts +4 -0
  41. package/dist/types/registry/alibaba-coding-plan.d.ts +7 -0
  42. package/dist/types/registry/amazon-bedrock.d.ts +5 -0
  43. package/dist/types/registry/anthropic.d.ts +10 -0
  44. package/dist/types/{utils/oauth → registry}/api-key-login.d.ts +8 -2
  45. package/dist/types/{utils/oauth → registry}/api-key-validation.d.ts +15 -0
  46. package/dist/types/registry/cerebras.d.ts +7 -0
  47. package/dist/types/registry/cloudflare-ai-gateway.d.ts +13 -0
  48. package/dist/types/registry/cursor.d.ts +7 -0
  49. package/dist/types/registry/deepseek.d.ts +8 -0
  50. package/dist/types/registry/derived.d.ts +5 -0
  51. package/dist/types/registry/firepass.d.ts +16 -0
  52. package/dist/types/registry/fireworks.d.ts +7 -0
  53. package/dist/types/registry/github-copilot.d.ts +7 -0
  54. package/dist/types/registry/gitlab-duo.d.ts +9 -0
  55. package/dist/types/registry/google-antigravity.d.ts +9 -0
  56. package/dist/types/registry/google-gemini-cli.d.ts +9 -0
  57. package/dist/types/registry/google-vertex.d.ts +5 -0
  58. package/dist/types/registry/google.d.ts +4 -0
  59. package/dist/types/registry/groq.d.ts +4 -0
  60. package/dist/types/registry/huggingface.d.ts +7 -0
  61. package/dist/types/registry/index.d.ts +4 -0
  62. package/dist/types/registry/kagi.d.ts +14 -0
  63. package/dist/types/registry/kilo.d.ts +7 -0
  64. package/dist/types/registry/kimi-code.d.ts +7 -0
  65. package/dist/types/registry/litellm.d.ts +13 -0
  66. package/dist/types/registry/lm-studio.d.ts +8 -0
  67. package/dist/types/registry/minimax-code-cn.d.ts +6 -0
  68. package/dist/types/registry/minimax-code.d.ts +6 -0
  69. package/dist/types/registry/minimax.d.ts +4 -0
  70. package/dist/types/registry/mistral.d.ts +4 -0
  71. package/dist/types/registry/moonshot.d.ts +7 -0
  72. package/dist/types/registry/nanogpt.d.ts +7 -0
  73. package/dist/types/registry/nvidia.d.ts +7 -0
  74. package/dist/types/registry/oauth/__tests__/xai-oauth.test.d.ts +1 -0
  75. package/dist/types/{utils → registry}/oauth/anthropic.d.ts +2 -1
  76. package/dist/types/{utils → registry}/oauth/github-copilot.d.ts +15 -23
  77. package/dist/types/{utils → registry}/oauth/index.d.ts +1 -0
  78. package/dist/types/{utils → registry}/oauth/minimax-code.d.ts +5 -5
  79. package/dist/types/{utils → registry}/oauth/types.d.ts +6 -1
  80. package/dist/types/{utils → registry}/oauth/xai-oauth.d.ts +2 -1
  81. package/dist/types/registry/ollama-cloud.d.ts +7 -0
  82. package/dist/types/registry/ollama.d.ts +12 -0
  83. package/dist/types/registry/openai-codex-device.d.ts +8 -0
  84. package/dist/types/registry/openai-codex.d.ts +9 -0
  85. package/dist/types/registry/openai.d.ts +4 -0
  86. package/dist/types/registry/opencode-go.d.ts +6 -0
  87. package/dist/types/registry/opencode-zen.d.ts +6 -0
  88. package/dist/types/registry/openrouter.d.ts +13 -0
  89. package/dist/types/registry/parallel.d.ts +14 -0
  90. package/dist/types/registry/perplexity.d.ts +7 -0
  91. package/dist/types/registry/qianfan.d.ts +7 -0
  92. package/dist/types/registry/qwen-portal.d.ts +7 -0
  93. package/dist/types/registry/registry.d.ts +272 -0
  94. package/dist/types/registry/synthetic.d.ts +6 -0
  95. package/dist/types/registry/tavily.d.ts +14 -0
  96. package/dist/types/registry/together.d.ts +6 -0
  97. package/dist/types/registry/types.d.ts +51 -0
  98. package/dist/types/registry/venice.d.ts +13 -0
  99. package/dist/types/registry/vercel-ai-gateway.d.ts +7 -0
  100. package/dist/types/registry/vllm.d.ts +7 -0
  101. package/dist/types/registry/wafer-pass.d.ts +6 -0
  102. package/dist/types/registry/wafer-serverless.d.ts +6 -0
  103. package/dist/types/registry/xai-oauth.d.ts +7 -0
  104. package/dist/types/registry/xai.d.ts +4 -0
  105. package/dist/types/registry/xiaomi-token-plan-ams.d.ts +6 -0
  106. package/dist/types/registry/xiaomi-token-plan-cn.d.ts +6 -0
  107. package/dist/types/registry/xiaomi-token-plan-sgp.d.ts +6 -0
  108. package/dist/types/registry/xiaomi.d.ts +6 -0
  109. package/dist/types/registry/zai.d.ts +7 -0
  110. package/dist/types/registry/zenmux.d.ts +7 -0
  111. package/dist/types/registry/zhipu-coding-plan.d.ts +7 -0
  112. package/dist/types/stream.d.ts +9 -1
  113. package/dist/types/types.d.ts +56 -295
  114. package/dist/types/usage/google-antigravity.d.ts +15 -1
  115. package/dist/types/usage/openai-codex-reset.d.ts +79 -0
  116. package/dist/types/usage/openai-codex.d.ts +1 -0
  117. package/dist/types/usage.d.ts +77 -4
  118. package/dist/types/utils/abort.d.ts +6 -0
  119. package/dist/types/utils/event-stream.d.ts +2 -0
  120. package/dist/types/utils/http-inspector.d.ts +0 -1
  121. package/dist/types/utils/idle-iterator.d.ts +35 -0
  122. package/dist/types/utils/openai-http.d.ts +58 -0
  123. package/dist/types/utils/request-debug.d.ts +3 -0
  124. package/dist/types/utils/retry-after.d.ts +1 -0
  125. package/dist/types/utils/schema/fields.d.ts +5 -0
  126. package/dist/types/utils/schema/json-schema-validator.d.ts +8 -0
  127. package/dist/types/utils/schema/stamps.d.ts +7 -15
  128. package/dist/types/utils/sse-debug.d.ts +0 -5
  129. package/dist/types/utils/stream-markup-healing.d.ts +2 -0
  130. package/dist/types/utils.d.ts +1 -5
  131. package/package.json +17 -29
  132. package/src/auth-broker/remote-store.ts +10 -1
  133. package/src/auth-broker/snapshot-cache.ts +1 -1
  134. package/src/auth-broker/wire-schemas.ts +1 -1
  135. package/src/auth-gateway/http.ts +1 -1
  136. package/src/auth-gateway/server.ts +95 -30
  137. package/src/auth-gateway/types.ts +10 -2
  138. package/src/auth-retry.ts +238 -0
  139. package/src/auth-storage.ts +935 -430
  140. package/src/errors.ts +32 -0
  141. package/src/index.ts +9 -14
  142. package/src/provider-details.ts +1 -1
  143. package/src/providers/__tests__/google-auth.test.ts +144 -0
  144. package/src/providers/amazon-bedrock.ts +70 -40
  145. package/src/providers/anthropic-client.ts +15 -13
  146. package/src/providers/anthropic-messages-server-schema.ts +17 -7
  147. package/src/providers/anthropic-messages-server.ts +88 -20
  148. package/src/providers/anthropic-wire.ts +4 -3
  149. package/src/providers/anthropic.ts +1234 -621
  150. package/src/providers/aws-credentials.ts +47 -5
  151. package/src/providers/aws-eventstream.ts +5 -0
  152. package/src/providers/azure-openai-responses.ts +117 -67
  153. package/src/providers/cursor.ts +30 -30
  154. package/src/providers/github-copilot-headers.ts +1 -1
  155. package/src/providers/gitlab-duo.ts +36 -29
  156. package/src/providers/google-auth.ts +71 -8
  157. package/src/providers/google-gemini-cli.ts +118 -22
  158. package/src/providers/google-shared.ts +163 -43
  159. package/src/providers/google-types.ts +10 -1
  160. package/src/providers/kimi.ts +1 -1
  161. package/src/providers/mock.ts +11 -3
  162. package/src/providers/ollama.ts +64 -7
  163. package/src/providers/openai-anthropic-shim.ts +17 -8
  164. package/src/providers/openai-chat-server-schema.ts +9 -3
  165. package/src/providers/openai-chat-server.ts +82 -16
  166. package/src/providers/openai-chat-wire.ts +847 -0
  167. package/src/providers/openai-codex/request-transformer.ts +129 -34
  168. package/src/providers/openai-codex/response-handler.ts +22 -1
  169. package/src/providers/openai-codex-responses.ts +699 -247
  170. package/src/providers/openai-completions-compat.ts +8 -308
  171. package/src/providers/openai-completions.ts +416 -267
  172. package/src/providers/openai-responses-server-schema.ts +15 -9
  173. package/src/providers/openai-responses-server.ts +162 -114
  174. package/src/providers/openai-responses-shared.ts +320 -82
  175. package/src/providers/openai-responses-wire.ts +6391 -0
  176. package/src/providers/openai-responses.ts +382 -176
  177. package/src/providers/prometheus-native-client.ts +27 -11
  178. package/src/providers/prometheus-native-server.ts +44 -17
  179. package/src/providers/transform-messages.ts +311 -120
  180. package/src/providers/vision-guard.ts +5 -3
  181. package/src/rate-limit-utils.ts +13 -3
  182. package/src/registry/aimlapi.ts +6 -0
  183. package/src/{utils/oauth → registry}/alibaba-coding-plan.ts +8 -18
  184. package/src/registry/amazon-bedrock.ts +22 -0
  185. package/src/registry/anthropic.ts +26 -0
  186. package/src/{utils/oauth → registry}/api-key-login.ts +25 -3
  187. package/src/{utils/oauth → registry}/api-key-validation.ts +62 -2
  188. package/src/{utils/oauth → registry}/cerebras.ts +8 -1
  189. package/src/{utils/oauth → registry}/cloudflare-ai-gateway.ts +8 -12
  190. package/src/registry/cursor.ts +20 -0
  191. package/src/{utils/oauth → registry}/deepseek.ts +9 -17
  192. package/src/registry/derived.ts +9 -0
  193. package/src/{utils/oauth → registry}/firepass.ts +10 -2
  194. package/src/{utils/oauth → registry}/fireworks.ts +8 -1
  195. package/src/registry/github-copilot.ts +22 -0
  196. package/src/registry/gitlab-duo.ts +19 -0
  197. package/src/registry/google-antigravity.ts +21 -0
  198. package/src/registry/google-gemini-cli.ts +21 -0
  199. package/src/registry/google-vertex.ts +38 -0
  200. package/src/registry/google.ts +6 -0
  201. package/src/registry/groq.ts +6 -0
  202. package/src/{utils/oauth → registry}/huggingface.ts +8 -19
  203. package/src/registry/index.ts +4 -0
  204. package/src/{utils/oauth → registry}/kagi.ts +9 -11
  205. package/src/{utils/oauth → registry}/kilo.ts +11 -6
  206. package/src/registry/kimi-code.ts +17 -0
  207. package/src/{utils/oauth → registry}/litellm.ts +8 -12
  208. package/src/{utils/oauth → registry}/lm-studio.ts +9 -17
  209. package/src/registry/minimax-code-cn.ts +12 -0
  210. package/src/registry/minimax-code.ts +12 -0
  211. package/src/registry/minimax.ts +6 -0
  212. package/src/registry/mistral.ts +6 -0
  213. package/src/{utils/oauth → registry}/moonshot.ts +8 -9
  214. package/src/{utils/oauth → registry}/nanogpt.ts +8 -1
  215. package/src/{utils/oauth → registry}/nvidia.ts +8 -18
  216. package/src/{utils → registry}/oauth/__tests__/xai-oauth.test.ts +4 -7
  217. package/src/{utils → registry}/oauth/anthropic.ts +38 -17
  218. package/src/{utils → registry}/oauth/github-copilot.ts +79 -115
  219. package/src/registry/oauth/gitlab-duo.ts +198 -0
  220. package/src/{utils → registry}/oauth/google-antigravity.ts +1 -4
  221. package/src/{utils → registry}/oauth/google-gemini-cli.ts +1 -4
  222. package/src/registry/oauth/index.ts +164 -0
  223. package/src/{utils → registry}/oauth/minimax-code.ts +16 -14
  224. package/src/{utils → registry}/oauth/types.ts +7 -51
  225. package/src/{utils → registry}/oauth/wafer.ts +1 -1
  226. package/src/{utils → registry}/oauth/xai-oauth.ts +16 -8
  227. package/src/{utils → registry}/oauth/xiaomi.ts +9 -4
  228. package/src/{utils/oauth → registry}/ollama-cloud.ts +8 -1
  229. package/src/{utils/oauth → registry}/ollama.ts +8 -13
  230. package/src/registry/openai-codex-device.ts +18 -0
  231. package/src/registry/openai-codex.ts +19 -0
  232. package/src/registry/openai.ts +6 -0
  233. package/src/registry/opencode-go.ts +12 -0
  234. package/src/registry/opencode-zen.ts +12 -0
  235. package/src/{utils/oauth → registry}/openrouter.ts +10 -2
  236. package/src/{utils/oauth → registry}/parallel.ts +9 -11
  237. package/src/registry/perplexity.ts +13 -0
  238. package/src/{utils/oauth → registry}/qianfan.ts +8 -17
  239. package/src/{utils/oauth → registry}/qwen-portal.ts +8 -19
  240. package/src/registry/registry.ts +149 -0
  241. package/src/{utils/oauth → registry}/synthetic.ts +7 -1
  242. package/src/{utils/oauth → registry}/tavily.ts +10 -12
  243. package/src/{utils/oauth → registry}/together.ts +7 -1
  244. package/src/registry/types.ts +56 -0
  245. package/src/{utils/oauth → registry}/venice.ts +8 -12
  246. package/src/{utils/oauth → registry}/vercel-ai-gateway.ts +8 -18
  247. package/src/{utils/oauth → registry}/vllm.ts +9 -16
  248. package/src/registry/wafer-pass.ts +12 -0
  249. package/src/registry/wafer-serverless.ts +12 -0
  250. package/src/registry/xai-oauth.ts +17 -0
  251. package/src/registry/xai.ts +6 -0
  252. package/src/registry/xiaomi-token-plan-ams.ts +12 -0
  253. package/src/registry/xiaomi-token-plan-cn.ts +12 -0
  254. package/src/registry/xiaomi-token-plan-sgp.ts +12 -0
  255. package/src/registry/xiaomi.ts +12 -0
  256. package/src/{utils/oauth → registry}/zai.ts +10 -22
  257. package/src/{utils/oauth → registry}/zenmux.ts +8 -1
  258. package/src/{utils/oauth/zhipu.ts → registry/zhipu-coding-plan.ts} +9 -21
  259. package/src/stream.ts +229 -199
  260. package/src/types.ts +63 -384
  261. package/src/usage/claude.ts +4 -2
  262. package/src/usage/github-copilot.ts +4 -2
  263. package/src/usage/google-antigravity.ts +196 -28
  264. package/src/usage/kimi.ts +1 -1
  265. package/src/usage/minimax-code.ts +5 -6
  266. package/src/usage/openai-codex-reset.ts +174 -0
  267. package/src/usage/openai-codex.ts +19 -2
  268. package/src/usage/zai.ts +2 -1
  269. package/src/usage.ts +93 -4
  270. package/src/utils/abort.ts +14 -0
  271. package/src/utils/event-stream.ts +17 -0
  272. package/src/utils/http-inspector.ts +4 -12
  273. package/src/utils/idle-iterator.ts +250 -79
  274. package/src/utils/openai-http.ts +157 -0
  275. package/src/utils/request-debug.ts +67 -19
  276. package/src/utils/retry-after.ts +1 -1
  277. package/src/utils/retry.ts +23 -2
  278. package/src/utils/schema/CONSTRAINTS.md +4 -2
  279. package/src/utils/schema/fields.ts +16 -0
  280. package/src/utils/schema/json-schema-validator.ts +19 -1
  281. package/src/utils/schema/normalize.ts +80 -8
  282. package/src/utils/schema/stamps.ts +22 -10
  283. package/src/utils/schema/wire.ts +2 -2
  284. package/src/utils/sse-debug.ts +0 -271
  285. package/src/utils/stream-markup-healing.ts +50 -8
  286. package/src/utils/validation.ts +49 -13
  287. package/src/utils.ts +2 -26
  288. package/dist/types/model-cache.d.ts +0 -17
  289. package/dist/types/model-manager.d.ts +0 -64
  290. package/dist/types/model-thinking.d.ts +0 -100
  291. package/dist/types/models.d.ts +0 -12
  292. package/dist/types/provider-models/bundled-references.d.ts +0 -4
  293. package/dist/types/provider-models/descriptors.d.ts +0 -50
  294. package/dist/types/provider-models/google.d.ts +0 -24
  295. package/dist/types/provider-models/index.d.ts +0 -5
  296. package/dist/types/provider-models/ollama.d.ts +0 -7
  297. package/dist/types/provider-models/openai-compat.d.ts +0 -323
  298. package/dist/types/provider-models/special.d.ts +0 -16
  299. package/dist/types/utils/discovery/antigravity.d.ts +0 -61
  300. package/dist/types/utils/discovery/codex.d.ts +0 -38
  301. package/dist/types/utils/discovery/cursor.d.ts +0 -23
  302. package/dist/types/utils/discovery/gemini.d.ts +0 -25
  303. package/dist/types/utils/discovery/index.d.ts +0 -4
  304. package/dist/types/utils/discovery/openai-compatible.d.ts +0 -72
  305. package/dist/types/utils/oauth/alibaba-coding-plan.d.ts +0 -18
  306. package/dist/types/utils/oauth/cerebras.d.ts +0 -1
  307. package/dist/types/utils/oauth/cloudflare-ai-gateway.d.ts +0 -18
  308. package/dist/types/utils/oauth/deepseek.d.ts +0 -10
  309. package/dist/types/utils/oauth/firepass.d.ts +0 -1
  310. package/dist/types/utils/oauth/fireworks.d.ts +0 -1
  311. package/dist/types/utils/oauth/huggingface.d.ts +0 -19
  312. package/dist/types/utils/oauth/kagi.d.ts +0 -17
  313. package/dist/types/utils/oauth/kilo.d.ts +0 -5
  314. package/dist/types/utils/oauth/litellm.d.ts +0 -18
  315. package/dist/types/utils/oauth/lm-studio.d.ts +0 -17
  316. package/dist/types/utils/oauth/moonshot.d.ts +0 -1
  317. package/dist/types/utils/oauth/nanogpt.d.ts +0 -1
  318. package/dist/types/utils/oauth/nvidia.d.ts +0 -18
  319. package/dist/types/utils/oauth/ollama-cloud.d.ts +0 -2
  320. package/dist/types/utils/oauth/ollama.d.ts +0 -18
  321. package/dist/types/utils/oauth/openrouter.d.ts +0 -1
  322. package/dist/types/utils/oauth/parallel.d.ts +0 -17
  323. package/dist/types/utils/oauth/qianfan.d.ts +0 -17
  324. package/dist/types/utils/oauth/qwen-portal.d.ts +0 -19
  325. package/dist/types/utils/oauth/synthetic.d.ts +0 -1
  326. package/dist/types/utils/oauth/tavily.d.ts +0 -17
  327. package/dist/types/utils/oauth/together.d.ts +0 -1
  328. package/dist/types/utils/oauth/venice.d.ts +0 -18
  329. package/dist/types/utils/oauth/vercel-ai-gateway.d.ts +0 -18
  330. package/dist/types/utils/oauth/vllm.d.ts +0 -16
  331. package/dist/types/utils/oauth/zai.d.ts +0 -18
  332. package/dist/types/utils/oauth/zenmux.d.ts +0 -1
  333. package/dist/types/utils/oauth/zhipu.d.ts +0 -18
  334. package/src/model-cache.ts +0 -129
  335. package/src/model-manager.ts +0 -469
  336. package/src/model-thinking.ts +0 -756
  337. package/src/models.json +0 -60287
  338. package/src/models.json.d.ts +0 -9
  339. package/src/models.ts +0 -56
  340. package/src/provider-models/bundled-references.ts +0 -38
  341. package/src/provider-models/descriptors.ts +0 -364
  342. package/src/provider-models/google.ts +0 -88
  343. package/src/provider-models/index.ts +0 -5
  344. package/src/provider-models/ollama.ts +0 -153
  345. package/src/provider-models/openai-compat.ts +0 -2904
  346. package/src/provider-models/special.ts +0 -67
  347. package/src/utils/discovery/antigravity.ts +0 -261
  348. package/src/utils/discovery/codex.ts +0 -371
  349. package/src/utils/discovery/cursor.ts +0 -306
  350. package/src/utils/discovery/gemini.ts +0 -248
  351. package/src/utils/discovery/index.ts +0 -4
  352. package/src/utils/discovery/openai-compatible.ts +0 -224
  353. package/src/utils/oauth/gitlab-duo.ts +0 -123
  354. package/src/utils/oauth/index.ts +0 -502
  355. /package/dist/types/{utils/oauth/__tests__/xai-oauth.test.d.ts → providers/__tests__/google-auth.test.d.ts} +0 -0
  356. /package/dist/types/{utils → registry}/oauth/callback-server.d.ts +0 -0
  357. /package/dist/types/{utils → registry}/oauth/cursor.d.ts +0 -0
  358. /package/dist/types/{utils → registry}/oauth/gitlab-duo.d.ts +0 -0
  359. /package/dist/types/{utils → registry}/oauth/google-antigravity.d.ts +0 -0
  360. /package/dist/types/{utils → registry}/oauth/google-gemini-cli.d.ts +0 -0
  361. /package/dist/types/{utils → registry}/oauth/google-oauth-shared.d.ts +0 -0
  362. /package/dist/types/{utils → registry}/oauth/kimi.d.ts +0 -0
  363. /package/dist/types/{utils → registry}/oauth/openai-codex.d.ts +0 -0
  364. /package/dist/types/{utils → registry}/oauth/opencode.d.ts +0 -0
  365. /package/dist/types/{utils → registry}/oauth/perplexity.d.ts +0 -0
  366. /package/dist/types/{utils → registry}/oauth/pkce.d.ts +0 -0
  367. /package/dist/types/{utils → registry}/oauth/wafer.d.ts +0 -0
  368. /package/dist/types/{utils → registry}/oauth/xiaomi.d.ts +0 -0
  369. /package/src/{utils → registry}/oauth/callback-server.ts +0 -0
  370. /package/src/{utils → registry}/oauth/cursor.ts +0 -0
  371. /package/src/{utils → registry}/oauth/google-oauth-shared.ts +0 -0
  372. /package/src/{utils → registry}/oauth/kimi.ts +0 -0
  373. /package/src/{utils → registry}/oauth/oauth.html +0 -0
  374. /package/src/{utils → registry}/oauth/openai-codex.ts +0 -0
  375. /package/src/{utils → registry}/oauth/opencode.ts +0 -0
  376. /package/src/{utils → registry}/oauth/perplexity.ts +0 -0
  377. /package/src/{utils → registry}/oauth/pkce.ts +0 -0
@@ -50,8 +50,8 @@ export function isZodSchema(value: unknown): value is ZodType {
50
50
  }
51
51
 
52
52
  /** Symbol-stamped caches keyed by schema object identity. */
53
- const kZodWireSchema = Symbol("pi.schema.zod.wire");
54
- const kJsonWireSchema = Symbol("pi.schema.json.wire");
53
+ const kZodWireSchema = Symbol("prometheus.schema.zod.wire");
54
+ const kJsonWireSchema = Symbol("prometheus.schema.json.wire");
55
55
 
56
56
  /**
57
57
  * Post-process Zod-emitted JSON Schema so it matches the wire shape providers
@@ -1,9 +1,6 @@
1
1
  import type { ServerSentEvent } from "@prometheus-ai/utils";
2
2
  import type { RawSseEvent } from "../types";
3
3
 
4
- type FetchFunction = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
5
- type FetchWithPreconnect = FetchFunction & { preconnect?: typeof fetch.preconnect };
6
-
7
4
  type RawSseObserver = (event: RawSseEvent) => void;
8
5
 
9
6
  export function notifyRawSseEvent(observer: RawSseObserver | undefined, event: ServerSentEvent | RawSseEvent): void {
@@ -19,271 +16,3 @@ export function notifyRawSseEvent(observer: RawSseObserver | undefined, event: S
19
16
  // Raw stream observers are diagnostic only and must not affect generation.
20
17
  }
21
18
  }
22
-
23
- function isSseResponse(response: Response): boolean {
24
- // `response.body` is non-null for any fetch Response with a body, but we
25
- // still guard because user-supplied `fetch` mocks may return `{ body: null }`
26
- // for empty responses and we don't want to wrap those.
27
- if (!response.ok || !response.body) return false;
28
- const contentType = response.headers.get("content-type");
29
- // All providers in this repo emit lowercase `text/event-stream` (verified
30
- // against anthropic, openai-completions, openai-responses, azure-openai-responses,
31
- // google-shared, google-gemini-cli, openai-codex-responses, prometheus-native-client,
32
- // and the auth-gateway server). A canonical `includes` check is sufficient;
33
- // if a future provider sends mixed case it will fall back to the unwrapped
34
- // fetch — observably safe, just no debug tee for that response.
35
- return contentType?.includes("text/event-stream") ?? false;
36
- }
37
-
38
- // Reused for every UTF-8 line decode. Safe because lines are split on LF
39
- // (0x0a), which is single-byte ASCII and never appears inside a UTF-8
40
- // multi-byte sequence — each line is a complete UTF-8 run, so the decoder
41
- // carries no state across calls.
42
- const SSE_LINE_DECODER = new TextDecoder("utf-8");
43
-
44
- // Decode bytes [start, end) of an SSE line.
45
- //
46
- // A previous revision added an ASCII fast-path using `String.fromCharCode.apply`
47
- // over chunked subarrays, on the theory that skipping `TextDecoder` would save
48
- // the ~9.7% `decode` self-time the profile reported. In practice the swap
49
- // *regressed* total wall time: `fromCharCode` became a new 7.8% hotspot,
50
- // `Uint8Array` allocations grew 5.3%, and `subarray` rose from 11.5% to 18.3%
51
- // — net loss of ~10pp. Bun's `TextDecoder.decode` has a fast C++ ASCII path
52
- // that beats chunked `fromCharCode.apply` for the typical sub-1KB SSE line,
53
- // so we keep the decoder. The line is bounded by LF (0x0a, single-byte
54
- // ASCII), so each [start, end) slice is a complete UTF-8 run and the shared
55
- // stateless decoder is safe to reuse.
56
- function decodeSseLine(buf: Uint8Array, start: number, end: number): string {
57
- if (start === 0 && end === buf.length) return SSE_LINE_DECODER.decode(buf);
58
- return SSE_LINE_DECODER.decode(buf.subarray(start, end));
59
- }
60
-
61
- /**
62
- * Inline SSE event splitter. Walks the byte stream as it flows through a
63
- * `TransformStream`, dispatching parsed events to the debug observer while
64
- * the bytes are forwarded unchanged to the response consumer. Replaces the
65
- * previous `body.tee()` + `readSseEvents` re-parse pipeline so the byte
66
- * stream is parsed exactly once when a debug observer is attached.
67
- *
68
- * Field parsing intentionally mirrors `readSseEvents` in `@prometheus-ai/utils`
69
- * (only `event` and `data` are observed; `id`/`retry` ignored; CR stripped
70
- * before LF dispatch; leading space after `:` trimmed; `data:` lines join
71
- * with `\n`). Reusing `readSseEvents` directly would require a second stream
72
- * pipeline, which is exactly what this class avoids.
73
- */
74
- class SseTeeParser {
75
- #observer: RawSseObserver;
76
- // Trailing bytes from the previous chunk that did not end with LF.
77
- #partial: Uint8Array | null = null;
78
- #event: string | null = null;
79
- #data: string | null = null;
80
- #raw: string[] = [];
81
-
82
- constructor(observer: RawSseObserver) {
83
- this.#observer = observer;
84
- }
85
-
86
- push(chunk: Uint8Array): void {
87
- // Carry-forward path: concat the partial line with the new chunk so the
88
- // LF scan walks a single contiguous buffer. The common case (partial is
89
- // null) skips the allocation entirely.
90
- let buf: Uint8Array;
91
- if (this.#partial) {
92
- buf = new Uint8Array(this.#partial.length + chunk.length);
93
- buf.set(this.#partial, 0);
94
- buf.set(chunk, this.#partial.length);
95
- this.#partial = null;
96
- } else {
97
- buf = chunk;
98
- }
99
-
100
- const len = buf.length;
101
- let i = 0;
102
- while (i < len) {
103
- const lf = buf.indexOf(0x0a, i);
104
- if (lf === -1) {
105
- // Retain the tail as a partial line for the next chunk. Copy
106
- // because the source `chunk` buffer may be reused upstream.
107
- this.#partial = buf.subarray(i).slice();
108
- return;
109
- }
110
- let end = lf;
111
- if (end > i && buf[end - 1] === 0x0d) end--;
112
- this.#consumeLine(buf, i, end);
113
- i = lf + 1;
114
- }
115
- }
116
-
117
- flush(): void {
118
- // Treat any trailing partial line (no terminating LF) as a complete line.
119
- if (this.#partial) {
120
- const tail = this.#partial;
121
- this.#partial = null;
122
- let end = tail.length;
123
- if (end > 0 && tail[end - 1] === 0x0d) end--;
124
- if (end > 0) this.#consumeLine(tail, 0, end);
125
- }
126
- // Real services don't always close on a blank line — flush any pending event.
127
- this.#dispatch();
128
- }
129
-
130
- #consumeLine(buf: Uint8Array, start: number, end: number): void {
131
- if (end === start) {
132
- this.#dispatch();
133
- return;
134
- }
135
- // Comment line: keep verbatim in `raw` for diagnostic context, skip parsing.
136
- // SSE spec § 9.2.6: lines beginning with ':' are heartbeats/comments and
137
- // MUST NOT contribute to the event dispatch state. Heartbeats are the
138
- // single most common line type on long-poll provider streams, so the
139
- // early-return here directly avoids ~half the field-parse work.
140
- if (buf[start] === 0x3a /* ':' */) {
141
- this.#raw.push(decodeSseLine(buf, start, end));
142
- return;
143
- }
144
- // Byte-level field parse. We avoid `text.indexOf(':')` + two `String.slice`
145
- // calls (~6% of CPU pre-optimization) by scanning bytes for the field
146
- // delimiter and matching the field name byte-for-byte. Field-name bytes
147
- // are ASCII per SSE spec, so byte offsets equal char offsets in the
148
- // decoded string and we can `slice` the value directly off `text` without
149
- // re-decoding.
150
- //
151
- // ASCII signatures (verified against SSE spec):
152
- // "event" = 0x65 0x76 0x65 0x6e 0x74 (5 bytes)
153
- // "data" = 0x64 0x61 0x74 0x61 (4 bytes)
154
- let colon = -1;
155
- for (let k = start; k < end; k++) {
156
- if (buf[k] === 0x3a) {
157
- colon = k;
158
- break;
159
- }
160
- }
161
- const fieldEnd = colon === -1 ? end : colon;
162
- let valueStart = colon === -1 ? end : colon + 1;
163
- // Per SSE spec, a single leading SP after the colon is stripped.
164
- if (valueStart < end && buf[valueStart] === 0x20 /* ' ' */) valueStart++;
165
- const fieldLen = fieldEnd - start;
166
- const isEvent =
167
- fieldLen === 5 &&
168
- buf[start] === 0x65 &&
169
- buf[start + 1] === 0x76 &&
170
- buf[start + 2] === 0x65 &&
171
- buf[start + 3] === 0x6e &&
172
- buf[start + 4] === 0x74;
173
- const isData =
174
- !isEvent &&
175
- fieldLen === 4 &&
176
- buf[start] === 0x64 &&
177
- buf[start + 1] === 0x61 &&
178
- buf[start + 2] === 0x74 &&
179
- buf[start + 3] === 0x61;
180
- // Decode the line exactly once. Raw observers (debug buffer) want it
181
- // regardless of field kind; `id`/`retry`/unknown lines pay only the
182
- // decode cost, not any extra slicing.
183
- const text = decodeSseLine(buf, start, end);
184
- this.#raw.push(text);
185
- if (isEvent) {
186
- // `valueStart - start` is a byte offset into the line; since the
187
- // "event:" prefix (and the optional SP) are pure ASCII, that byte
188
- // offset equals the char offset in the decoded `text`.
189
- this.#event = valueStart === end ? "" : text.slice(valueStart - start);
190
- } else if (isData) {
191
- const value = valueStart === end ? "" : text.slice(valueStart - start);
192
- if (this.#data === null) this.#data = value;
193
- else this.#data = `${this.#data}\n${value}`;
194
- }
195
- // `id` and `retry` are intentionally ignored — providers don't use them
196
- // and reconnects are handled by the underlying transport.
197
- }
198
-
199
- // Hands ownership of the accumulated `raw` array to the observer. The
200
- // observer (currently only `RawSseDebugBuffer.recordEvent`) MAY retain the
201
- // array; we install a fresh `#raw = []` for the next event before invoking
202
- // the observer so there is no aliasing across dispatches. This contract is
203
- // mirrored in `notifyRawSseEvent` (no defensive clone) — see its comment.
204
- //
205
- // TODO(BufferOpt): once the buffer-side audit confirms it never mutates
206
- // `event.raw`, the defensive `[...event.raw]` clone in older call paths
207
- // (search for `notifyRawSseEvent`) can be dropped repository-wide.
208
- #dispatch(): void {
209
- if (this.#event === null && this.#data === null) return;
210
- const event: RawSseEvent = {
211
- event: this.#event,
212
- data: this.#data ?? "",
213
- raw: this.#raw,
214
- };
215
- this.#event = null;
216
- this.#data = null;
217
- this.#raw = [];
218
- try {
219
- this.#observer(event);
220
- } catch {
221
- // Raw stream observers are diagnostic only and must not affect generation.
222
- }
223
- }
224
- }
225
-
226
- export function wrapFetchForSseDebug(
227
- fetchImpl: FetchWithPreconnect,
228
- observer: RawSseObserver | undefined,
229
- ): FetchWithPreconnect {
230
- if (!observer) return fetchImpl;
231
-
232
- const wrapped = Object.assign(
233
- async (input: string | URL | Request, init?: RequestInit): Promise<Response> => {
234
- const response = await fetchImpl(input, init);
235
- if (!isSseResponse(response)) {
236
- return response;
237
- }
238
-
239
- const body = response.body;
240
- if (!body) return response;
241
-
242
- // Single-pass interception. Previously implemented as
243
- // `body.pipeThrough(new TransformStream({...}))`, but the WHATWG
244
- // TransformStream machinery imposes a per-chunk Promise boundary
245
- // (`#handleNumberResult` showed at 8.8% self-time in CPU profile).
246
- // A manual ReadableStream pulling directly from `body.getReader()`
247
- // skips that hop: every `read()` immediately feeds both the parser
248
- // and the controller in the same microtask.
249
- const parser = new SseTeeParser(observer);
250
- const reader = body.getReader();
251
- const teed = new ReadableStream<Uint8Array>({
252
- async pull(controller) {
253
- try {
254
- const { done, value } = await reader.read();
255
- if (done) {
256
- parser.flush();
257
- controller.close();
258
- return;
259
- }
260
- // Enqueue first so the consumer sees bytes ASAP; parser
261
- // dispatch is best-effort diagnostic and runs after.
262
- controller.enqueue(value);
263
- parser.push(value);
264
- } catch (err) {
265
- // Mirror TransformStream semantics: surface upstream
266
- // errors to the consumer; do not flush a partial event.
267
- controller.error(err);
268
- }
269
- },
270
- cancel(reason) {
271
- // Propagate downstream cancellation to the source body so the
272
- // underlying connection is released. Matches `pipeThrough`'s
273
- // cancel-propagation behavior; `flush()` is intentionally NOT
274
- // called (TransformStream skips `flush` on abort too).
275
- return reader.cancel(reason);
276
- },
277
- });
278
-
279
- return new Response(teed, {
280
- status: response.status,
281
- statusText: response.statusText,
282
- headers: response.headers,
283
- });
284
- },
285
- fetchImpl.preconnect ? { preconnect: fetchImpl.preconnect } : {},
286
- );
287
-
288
- return wrapped;
289
- }
@@ -13,6 +13,8 @@
13
13
  * deltas for thinking blocks, and holds partial tags across chunk boundaries.
14
14
  */
15
15
 
16
+ import { isDeepseekModelIdOrName } from "@prometheus-ai/catalog/identity";
17
+
16
18
  import { parseJsonWithRepair } from "./json-parse";
17
19
 
18
20
  const KIMI_SECTION_BEGIN = "<|tool_calls_section_begin|>";
@@ -36,6 +38,8 @@ const DSML_PARAMETER_OPEN_RE = new RegExp(
36
38
  "y",
37
39
  );
38
40
  const DSML_PARAMETER_CLOSE_RE = new RegExp(`</${DSML_PIPE}DSML${DSML_PIPE}parameter>`, "y");
41
+ /** Canonical DSML section-open shape; `|` positions accept either pipe variant. */
42
+ const DSML_SECTION_OPEN_TEMPLATE = "<|DSML|tool_calls>";
39
43
 
40
44
  const THINK_OPEN = "<think>";
41
45
  const THINK_CLOSE = "</think>";
@@ -81,6 +85,7 @@ type XmlToolState =
81
85
  readonly paramName: string;
82
86
  readonly isString: boolean;
83
87
  value: string;
88
+ truncated?: boolean;
84
89
  };
85
90
 
86
91
  type ThinkingTag = { readonly open: string; readonly close: string };
@@ -429,12 +434,25 @@ export class StreamMarkupHealing {
429
434
  continue;
430
435
  }
431
436
  } else if (this.#tryMatch(config.parameterClose)) {
432
- state.args[state.paramName] = coerceXmlParamValue(state.value, state.isString);
437
+ // A capped value executes with silently corrupted input unless the
438
+ // truncation is made explicit — the marker fails JSON params loudly
439
+ // and tells the model/tool what happened to string params.
440
+ const paramValue = state.truncated
441
+ ? `${state.value}\n…[parameter truncated: exceeded ${MAX_XML_PARAM_VALUE_LENGTH} bytes]`
442
+ : state.value;
443
+ state.args[state.paramName] = coerceXmlParamValue(paramValue, state.isString);
433
444
  config.setState({ kind: "invoke", name: state.invokeName, args: state.args });
434
445
  continue;
435
446
  }
436
447
 
437
- if (this.#startsWithPartialXmlTag()) break;
448
+ if (state.kind === "idle") {
449
+ // In idle, a bare `<` is legitimate output (`a < b`, generics, JSX).
450
+ // Only hold back tails that could still grow into the DSML
451
+ // section-open tag; everything else flows through immediately.
452
+ if (this.#startsWithPartialDsmlSectionOpen()) break;
453
+ } else if (this.#startsWithPartialXmlTag()) {
454
+ break;
455
+ }
438
456
 
439
457
  const ch = this.#buffer[this.#offset]!;
440
458
  this.#offset += 1;
@@ -443,11 +461,15 @@ export class StreamMarkupHealing {
443
461
  continue;
444
462
  }
445
463
  if (state.kind === "parameter") {
446
- if (state.value.length >= MAX_XML_PARAM_VALUE_LENGTH) {
447
- config.setState({ kind: "idle" });
448
- continue;
464
+ if (state.value.length < MAX_XML_PARAM_VALUE_LENGTH) {
465
+ state.value += ch;
466
+ } else {
467
+ // Beyond the cap the value stops growing, but we stay in
468
+ // `parameter` state so the rest of the envelope — including its
469
+ // close tags — is still swallowed instead of leaking into
470
+ // visible text. The close handler appends an explicit marker.
471
+ state.truncated = true;
449
472
  }
450
- state.value += ch;
451
473
  }
452
474
  }
453
475
 
@@ -511,6 +533,21 @@ export class StreamMarkupHealing {
511
533
  return true;
512
534
  }
513
535
 
536
+ #startsWithPartialDsmlSectionOpen(): boolean {
537
+ const tailLength = this.#buffer.length - this.#offset;
538
+ if (tailLength === 0 || tailLength >= DSML_SECTION_OPEN_TEMPLATE.length) return false;
539
+ for (let i = 0; i < tailLength; i++) {
540
+ const ch = this.#buffer[this.#offset + i]!;
541
+ const expected = DSML_SECTION_OPEN_TEMPLATE[i]!;
542
+ if (expected === "|") {
543
+ if (ch !== "|" && ch !== "|") return false;
544
+ } else if (ch !== expected) {
545
+ return false;
546
+ }
547
+ }
548
+ return true;
549
+ }
550
+
514
551
  #bufferIsPrefixOf(token: string, remainingLength: number): boolean {
515
552
  for (let i = 0; i < remainingLength; i++) {
516
553
  if (this.#buffer[this.#offset + i] !== token[i]) return false;
@@ -587,7 +624,7 @@ export function modelMayLeakKimiToolCalls(provider: string, modelId: string): bo
587
624
 
588
625
  /** Cheap model/provider gate for DeepSeek DSML envelope leaks. */
589
626
  export function modelMayLeakDsmlToolCalls(provider: string, modelId: string): boolean {
590
- if (!/deepseek/i.test(modelId)) return false;
627
+ if (!isDeepseekModelIdOrName(modelId)) return false;
591
628
  return (
592
629
  provider === "ollama" ||
593
630
  provider === "ollama-cloud" ||
@@ -600,12 +637,17 @@ export function modelMayLeakDsmlToolCalls(provider: string, modelId: string): bo
600
637
  );
601
638
  }
602
639
 
640
+ /** Cheap model/provider gate for MiniMax plain thinking tag leaks. */
641
+ export function modelMayLeakThinkingTags(provider: string, modelId: string): boolean {
642
+ return /minimax/i.test(provider) || /minimax/i.test(modelId);
643
+ }
644
+
603
645
  export function getStreamMarkupHealingPattern(
604
646
  provider: string,
605
647
  modelId: string,
606
648
  options?: { readonly parseThinkingTags?: boolean },
607
649
  ): StreamMarkupHealingPattern | undefined {
608
- if (options?.parseThinkingTags) return "thinking";
650
+ if (options?.parseThinkingTags || modelMayLeakThinkingTags(provider, modelId)) return "thinking";
609
651
  if (modelMayLeakKimiToolCalls(provider, modelId)) return "kimi";
610
652
  if (modelMayLeakDsmlToolCalls(provider, modelId)) return "dsml";
611
653
  return undefined;
@@ -724,6 +724,7 @@ interface FlatIssue {
724
724
  keyword: "type" | "unrecognized" | "other";
725
725
  instancePath: string;
726
726
  expectedTypes: string[];
727
+ unionBranch: boolean;
727
728
  }
728
729
 
729
730
  /**
@@ -759,12 +760,12 @@ function mapZodExpectedToJsonSchemaType(expected: unknown): string | null {
759
760
  */
760
761
  function flattenIssues(issues: ReadonlyArray<ZodIssue>): FlatIssue[] {
761
762
  const out: FlatIssue[] = [];
762
- const walk = (issue: ZodIssue, prefix: ReadonlyArray<PropertyKey>): void => {
763
+ const walk = (issue: ZodIssue, prefix: ReadonlyArray<PropertyKey>, unionBranch: boolean): void => {
763
764
  const fullPath = prefix.length === 0 ? issue.path : [...prefix, ...issue.path];
764
765
  if (issue.code === "invalid_type") {
765
766
  const mapped = mapZodExpectedToJsonSchemaType((issue as { expected?: unknown }).expected);
766
767
  if (mapped) {
767
- out.push({ keyword: "type", instancePath: pathToPointer(fullPath), expectedTypes: [mapped] });
768
+ out.push({ keyword: "type", instancePath: pathToPointer(fullPath), expectedTypes: [mapped], unionBranch });
768
769
  return;
769
770
  }
770
771
  }
@@ -775,6 +776,7 @@ function flattenIssues(issues: ReadonlyArray<ZodIssue>): FlatIssue[] {
775
776
  keyword: "unrecognized",
776
777
  instancePath: pathToPointer([...fullPath, key]),
777
778
  expectedTypes: [],
779
+ unionBranch,
778
780
  });
779
781
  }
780
782
  return;
@@ -782,17 +784,21 @@ function flattenIssues(issues: ReadonlyArray<ZodIssue>): FlatIssue[] {
782
784
  if (issue.code === "invalid_union") {
783
785
  const inner = (issue as unknown as { errors?: ReadonlyArray<ReadonlyArray<ZodIssue>> }).errors;
784
786
  if (inner) {
787
+ // A union-branch issue only competes with a sibling branch when it
788
+ // sits at the union node's own path. Issues whose own path is
789
+ // non-empty live on a deeper field that an already-identified
790
+ // branch owns, so the singleton-array repair should still apply.
785
791
  for (const branch of inner) {
786
792
  for (const child of branch) {
787
- walk(child, fullPath);
793
+ walk(child, fullPath, child.path.length === 0);
788
794
  }
789
795
  }
790
796
  }
791
797
  return;
792
798
  }
793
- out.push({ keyword: "other", instancePath: pathToPointer(fullPath), expectedTypes: [] });
799
+ out.push({ keyword: "other", instancePath: pathToPointer(fullPath), expectedTypes: [], unionBranch });
794
800
  };
795
- for (const issue of issues) walk(issue, []);
801
+ for (const issue of issues) walk(issue, [], false);
796
802
  return out;
797
803
  }
798
804
 
@@ -801,7 +807,9 @@ function flattenIssues(issues: ReadonlyArray<ZodIssue>): FlatIssue[] {
801
807
  *
802
808
  * Two kinds of repair are applied:
803
809
  * - **type**: when a value is a JSON-encoded string and the schema wants
804
- * something else, parse it and substitute the parsed value.
810
+ * something else, parse it and substitute the parsed value. When a
811
+ * non-union schema wants an array but receives a singleton value, wrap that
812
+ * value in a one-element array.
805
813
  * - **unrecognized**: when a strict object received an extra key (Zod's
806
814
  * `unrecognized_keys` or JSON Schema's `additionalProperties: false`),
807
815
  * drop that key so re-validation succeeds. This effectively coerces every
@@ -811,6 +819,7 @@ function flattenIssues(issues: ReadonlyArray<ZodIssue>): FlatIssue[] {
811
819
  * The function is safe and conservative:
812
820
  * - Only processes "type" and "unrecognized" issues
813
821
  * - Only attempts JSON coercion on string values
822
+ * - Only wraps singleton array values for non-union type expectations
814
823
  * - Only accepts parsed results that match the expected type
815
824
  * - Clones the args object before mutation (copy-on-write)
816
825
  */
@@ -836,12 +845,16 @@ function coerceArgsFromIssues(args: unknown, issues: FlatIssue[]): { value: unkn
836
845
  if (issue.expectedTypes.length === 0) continue;
837
846
 
838
847
  const currentValue = getValueAtPointer(nextArgs, issue.instancePath);
839
- if (typeof currentValue !== "string") continue;
840
-
841
- const result = tryParseJsonForTypes(currentValue, issue.expectedTypes);
848
+ const result =
849
+ typeof currentValue === "string"
850
+ ? tryParseJsonForTypes(currentValue, issue.expectedTypes)
851
+ : { value: currentValue, changed: false };
842
852
  const coercedValue = result.changed
843
853
  ? result.value
844
- : issue.expectedTypes.includes("array")
854
+ : issue.expectedTypes.includes("array") &&
855
+ !issue.unionBranch &&
856
+ currentValue !== undefined &&
857
+ !Array.isArray(currentValue)
845
858
  ? [currentValue]
846
859
  : undefined;
847
860
  if (coercedValue === undefined) continue;
@@ -905,17 +918,20 @@ function preserveUnknownRootFields(input: unknown, parsed: unknown): unknown {
905
918
 
906
919
  function flattenJsonSchemaIssues(issues: ReadonlyArray<JsonSchemaValidationIssue>): FlatIssue[] {
907
920
  return issues.map(issue => {
921
+ const unionBranch = issue.fromUnionBranch === true;
908
922
  if (issue.keyword === "additionalProperties") {
909
923
  return {
910
924
  keyword: "unrecognized",
911
925
  instancePath: pathToPointer(issue.path),
912
926
  expectedTypes: [],
927
+ unionBranch,
913
928
  };
914
929
  }
915
930
  return {
916
931
  keyword: issue.keyword === "type" ? "type" : "other",
917
932
  instancePath: pathToPointer(issue.path),
918
933
  expectedTypes: issue.expectedTypes ?? [],
934
+ unionBranch,
919
935
  };
920
936
  });
921
937
  }
@@ -963,6 +979,23 @@ export function validateToolCall(tools: Tool[], toolCall: ToolCall): ToolCall["a
963
979
  return validateToolArguments(tool, toolCall);
964
980
  }
965
981
 
982
+ /** Cap per-field string lengths when embedding received args in an error message. */
983
+ const MAX_ERROR_ARG_STRING_LENGTH = 256;
984
+
985
+ function truncateArgsForError(value: unknown): unknown {
986
+ if (typeof value === "string") {
987
+ if (value.length <= MAX_ERROR_ARG_STRING_LENGTH) return value;
988
+ return `${value.slice(0, MAX_ERROR_ARG_STRING_LENGTH)}… [truncated ${value.length - MAX_ERROR_ARG_STRING_LENGTH} chars]`;
989
+ }
990
+ if (Array.isArray(value)) return value.map(truncateArgsForError);
991
+ if (value !== null && typeof value === "object") {
992
+ const out: Record<string, unknown> = {};
993
+ for (const [key, entry] of Object.entries(value)) out[key] = truncateArgsForError(entry);
994
+ return out;
995
+ }
996
+ return value;
997
+ }
998
+
966
999
  /**
967
1000
  * Validates tool call arguments against the tool's schema (Zod or plain JSON
968
1001
  * Schema). Applies LLM-quirk coercions (numeric strings, JSON-string
@@ -1009,12 +1042,15 @@ export function validateToolArguments(tool: Tool, toolCall: ToolCall): ToolCall[
1009
1042
  // existing tests; the detailed body is informational.
1010
1043
  const errors = result.messages.join("\n") || "Unknown validation error";
1011
1044
 
1045
+ // Truncate long per-field strings: the full payload (potentially hundreds
1046
+ // of KB for write/edit-class calls) would otherwise round-trip back to the
1047
+ // model inside the tool error.
1012
1048
  const receivedArgs = changed
1013
1049
  ? {
1014
- original: originalArgs,
1015
- normalized: normalizedArgs,
1050
+ original: truncateArgsForError(originalArgs),
1051
+ normalized: truncateArgsForError(normalizedArgs),
1016
1052
  }
1017
- : originalArgs;
1053
+ : truncateArgsForError(originalArgs);
1018
1054
 
1019
1055
  const errorMessage = `Validation failed for tool "${
1020
1056
  toolCall.name
package/src/utils.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { $env } from "@prometheus-ai/utils";
2
- import type { ResponseInput } from "openai/resources/responses/responses";
2
+ import type { ResponseInput } from "./providers/openai-responses-wire";
3
3
  import type { CacheRetention, OpenAIResponsesHistoryPayload, ProviderPayload } from "./types";
4
4
 
5
5
  type OpenAIResponsesReplayItem = ResponseInput[number];
@@ -8,27 +8,7 @@ export { isRecord } from "@prometheus-ai/utils";
8
8
  export function normalizeSystemPrompts(systemPrompt: readonly string[] | string | undefined | null): string[] {
9
9
  if (systemPrompt === undefined || systemPrompt === null) return [];
10
10
  const prompts = Array.isArray(systemPrompt) ? systemPrompt : typeof systemPrompt === "string" ? [systemPrompt] : [];
11
- return prompts.map(prompt => prompt.toWellFormed()).filter(prompt => prompt.length > 0);
12
- }
13
-
14
- export function toNumber(value: unknown): number | undefined {
15
- if (typeof value === "number" && Number.isFinite(value)) return value;
16
- if (typeof value === "string" && value.trim()) {
17
- const parsed = Number(value);
18
- return Number.isFinite(parsed) ? parsed : undefined;
19
- }
20
- return undefined;
21
- }
22
-
23
- export function toPositiveNumber(value: unknown, fallback: number): number {
24
- if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
25
- return fallback;
26
- }
27
- return value;
28
- }
29
-
30
- export function toBoolean(value: unknown): boolean | undefined {
31
- return typeof value === "boolean" ? value : undefined;
11
+ return prompts.map(prompt => prompt.toWellFormed()).filter(prompt => prompt.trim().length > 0);
32
12
  }
33
13
 
34
14
  export function normalizeToolCallId(id: string): string {
@@ -160,7 +140,3 @@ export function resolveCacheRetention(cacheRetention?: CacheRetention): CacheRet
160
140
  if ($env.PROMETHEUS_CACHE_RETENTION === "long") return "long";
161
141
  return "short";
162
142
  }
163
-
164
- export function isAnthropicOAuthToken(key: string): boolean {
165
- return key.includes("sk-ant-oat");
166
- }
@@ -1,17 +0,0 @@
1
- import type { Api, Model } from "./types";
2
- interface CacheEntry<TApi extends Api = Api> {
3
- models: Model<TApi>[];
4
- fresh: boolean;
5
- authoritative: boolean;
6
- updatedAt: number;
7
- /**
8
- * Hash of the static catalog slice that was merged into `models` when this
9
- * row was written. `resolveProviderModels` compares against the current
10
- * static fingerprint and bypasses the static+cache re-merge when they
11
- * match — the cache already incorporates the same static state.
12
- */
13
- staticFingerprint: string;
14
- }
15
- export declare function readModelCache<TApi extends Api>(providerId: string, ttlMs: number, now: () => number, dbPath?: string): CacheEntry<TApi> | null;
16
- export declare function writeModelCache<TApi extends Api>(providerId: string, updatedAt: number, models: Model<TApi>[], authoritative: boolean, staticFingerprint: string, dbPath?: string): void;
17
- export {};