ai 6.0.33 → 6.0.35

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 (357) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/index.d.mts +50 -21
  3. package/dist/index.d.ts +50 -21
  4. package/dist/index.js +348 -286
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +280 -219
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/internal/index.js +1 -1
  9. package/dist/internal/index.mjs +1 -1
  10. package/docs/02-foundations/03-prompts.mdx +2 -2
  11. package/docs/03-ai-sdk-core/15-tools-and-tool-calling.mdx +1 -1
  12. package/docs/07-reference/01-ai-sdk-core/28-output.mdx +1 -1
  13. package/docs/07-reference/05-ai-sdk-errors/ai-ui-message-stream-error.mdx +67 -0
  14. package/package.json +6 -4
  15. package/src/agent/agent.ts +116 -0
  16. package/src/agent/create-agent-ui-stream-response.test.ts +258 -0
  17. package/src/agent/create-agent-ui-stream-response.ts +50 -0
  18. package/src/agent/create-agent-ui-stream.ts +73 -0
  19. package/src/agent/index.ts +33 -0
  20. package/src/agent/infer-agent-tools.ts +7 -0
  21. package/src/agent/infer-agent-ui-message.test-d.ts +54 -0
  22. package/src/agent/infer-agent-ui-message.ts +11 -0
  23. package/src/agent/pipe-agent-ui-stream-to-response.ts +52 -0
  24. package/src/agent/tool-loop-agent-on-finish-callback.ts +31 -0
  25. package/src/agent/tool-loop-agent-on-step-finish-callback.ts +11 -0
  26. package/src/agent/tool-loop-agent-settings.ts +182 -0
  27. package/src/agent/tool-loop-agent.test-d.ts +114 -0
  28. package/src/agent/tool-loop-agent.test.ts +442 -0
  29. package/src/agent/tool-loop-agent.ts +114 -0
  30. package/src/embed/__snapshots__/embed-many.test.ts.snap +191 -0
  31. package/src/embed/__snapshots__/embed.test.ts.snap +81 -0
  32. package/src/embed/embed-many-result.ts +53 -0
  33. package/src/embed/embed-many.test.ts +653 -0
  34. package/src/embed/embed-many.ts +378 -0
  35. package/src/embed/embed-result.ts +50 -0
  36. package/src/embed/embed.test.ts +298 -0
  37. package/src/embed/embed.ts +211 -0
  38. package/src/embed/index.ts +4 -0
  39. package/src/error/index.ts +35 -0
  40. package/src/error/invalid-argument-error.ts +34 -0
  41. package/src/error/invalid-stream-part-error.ts +28 -0
  42. package/src/error/invalid-tool-approval-error.ts +26 -0
  43. package/src/error/invalid-tool-input-error.ts +33 -0
  44. package/src/error/no-image-generated-error.ts +39 -0
  45. package/src/error/no-object-generated-error.ts +70 -0
  46. package/src/error/no-output-generated-error.ts +26 -0
  47. package/src/error/no-speech-generated-error.ts +18 -0
  48. package/src/error/no-such-tool-error.ts +35 -0
  49. package/src/error/no-transcript-generated-error.ts +20 -0
  50. package/src/error/tool-call-not-found-for-approval-error.ts +32 -0
  51. package/src/error/tool-call-repair-error.ts +30 -0
  52. package/src/error/ui-message-stream-error.ts +48 -0
  53. package/src/error/unsupported-model-version-error.ts +23 -0
  54. package/src/error/verify-no-object-generated-error.ts +27 -0
  55. package/src/generate-image/generate-image-result.ts +42 -0
  56. package/src/generate-image/generate-image.test.ts +1420 -0
  57. package/src/generate-image/generate-image.ts +360 -0
  58. package/src/generate-image/index.ts +18 -0
  59. package/src/generate-object/__snapshots__/generate-object.test.ts.snap +133 -0
  60. package/src/generate-object/__snapshots__/stream-object.test.ts.snap +297 -0
  61. package/src/generate-object/generate-object-result.ts +67 -0
  62. package/src/generate-object/generate-object.test-d.ts +49 -0
  63. package/src/generate-object/generate-object.test.ts +1191 -0
  64. package/src/generate-object/generate-object.ts +518 -0
  65. package/src/generate-object/index.ts +9 -0
  66. package/src/generate-object/inject-json-instruction.test.ts +181 -0
  67. package/src/generate-object/inject-json-instruction.ts +30 -0
  68. package/src/generate-object/output-strategy.ts +415 -0
  69. package/src/generate-object/parse-and-validate-object-result.ts +111 -0
  70. package/src/generate-object/repair-text.ts +12 -0
  71. package/src/generate-object/stream-object-result.ts +120 -0
  72. package/src/generate-object/stream-object.test-d.ts +74 -0
  73. package/src/generate-object/stream-object.test.ts +1950 -0
  74. package/src/generate-object/stream-object.ts +986 -0
  75. package/src/generate-object/validate-object-generation-input.ts +144 -0
  76. package/src/generate-speech/generate-speech-result.ts +30 -0
  77. package/src/generate-speech/generate-speech.test.ts +300 -0
  78. package/src/generate-speech/generate-speech.ts +190 -0
  79. package/src/generate-speech/generated-audio-file.ts +65 -0
  80. package/src/generate-speech/index.ts +3 -0
  81. package/src/generate-text/__snapshots__/generate-text.test.ts.snap +1872 -0
  82. package/src/generate-text/__snapshots__/stream-text.test.ts.snap +1255 -0
  83. package/src/generate-text/collect-tool-approvals.test.ts +553 -0
  84. package/src/generate-text/collect-tool-approvals.ts +116 -0
  85. package/src/generate-text/content-part.ts +25 -0
  86. package/src/generate-text/execute-tool-call.ts +129 -0
  87. package/src/generate-text/extract-reasoning-content.ts +17 -0
  88. package/src/generate-text/extract-text-content.ts +15 -0
  89. package/src/generate-text/generate-text-result.ts +168 -0
  90. package/src/generate-text/generate-text.test-d.ts +68 -0
  91. package/src/generate-text/generate-text.test.ts +7011 -0
  92. package/src/generate-text/generate-text.ts +1223 -0
  93. package/src/generate-text/generated-file.ts +70 -0
  94. package/src/generate-text/index.ts +57 -0
  95. package/src/generate-text/is-approval-needed.ts +29 -0
  96. package/src/generate-text/output-utils.ts +23 -0
  97. package/src/generate-text/output.test.ts +698 -0
  98. package/src/generate-text/output.ts +590 -0
  99. package/src/generate-text/parse-tool-call.test.ts +570 -0
  100. package/src/generate-text/parse-tool-call.ts +188 -0
  101. package/src/generate-text/prepare-step.ts +103 -0
  102. package/src/generate-text/prune-messages.test.ts +720 -0
  103. package/src/generate-text/prune-messages.ts +167 -0
  104. package/src/generate-text/reasoning-output.ts +20 -0
  105. package/src/generate-text/reasoning.ts +8 -0
  106. package/src/generate-text/response-message.ts +10 -0
  107. package/src/generate-text/run-tools-transformation.test.ts +1143 -0
  108. package/src/generate-text/run-tools-transformation.ts +420 -0
  109. package/src/generate-text/smooth-stream.test.ts +2101 -0
  110. package/src/generate-text/smooth-stream.ts +162 -0
  111. package/src/generate-text/step-result.ts +238 -0
  112. package/src/generate-text/stop-condition.ts +29 -0
  113. package/src/generate-text/stream-text-result.ts +463 -0
  114. package/src/generate-text/stream-text.test-d.ts +200 -0
  115. package/src/generate-text/stream-text.test.ts +19979 -0
  116. package/src/generate-text/stream-text.ts +2505 -0
  117. package/src/generate-text/to-response-messages.test.ts +922 -0
  118. package/src/generate-text/to-response-messages.ts +163 -0
  119. package/src/generate-text/tool-approval-request-output.ts +21 -0
  120. package/src/generate-text/tool-call-repair-function.ts +27 -0
  121. package/src/generate-text/tool-call.ts +47 -0
  122. package/src/generate-text/tool-error.ts +34 -0
  123. package/src/generate-text/tool-output-denied.ts +21 -0
  124. package/src/generate-text/tool-output.ts +7 -0
  125. package/src/generate-text/tool-result.ts +36 -0
  126. package/src/generate-text/tool-set.ts +14 -0
  127. package/src/global.ts +24 -0
  128. package/src/index.ts +50 -0
  129. package/src/logger/index.ts +6 -0
  130. package/src/logger/log-warnings.test.ts +351 -0
  131. package/src/logger/log-warnings.ts +119 -0
  132. package/src/middleware/__snapshots__/simulate-streaming-middleware.test.ts.snap +64 -0
  133. package/src/middleware/add-tool-input-examples-middleware.test.ts +476 -0
  134. package/src/middleware/add-tool-input-examples-middleware.ts +90 -0
  135. package/src/middleware/default-embedding-settings-middleware.test.ts +126 -0
  136. package/src/middleware/default-embedding-settings-middleware.ts +22 -0
  137. package/src/middleware/default-settings-middleware.test.ts +388 -0
  138. package/src/middleware/default-settings-middleware.ts +33 -0
  139. package/src/middleware/extract-json-middleware.test.ts +827 -0
  140. package/src/middleware/extract-json-middleware.ts +197 -0
  141. package/src/middleware/extract-reasoning-middleware.test.ts +1028 -0
  142. package/src/middleware/extract-reasoning-middleware.ts +238 -0
  143. package/src/middleware/index.ts +10 -0
  144. package/src/middleware/simulate-streaming-middleware.test.ts +911 -0
  145. package/src/middleware/simulate-streaming-middleware.ts +79 -0
  146. package/src/middleware/wrap-embedding-model.test.ts +358 -0
  147. package/src/middleware/wrap-embedding-model.ts +86 -0
  148. package/src/middleware/wrap-image-model.test.ts +423 -0
  149. package/src/middleware/wrap-image-model.ts +85 -0
  150. package/src/middleware/wrap-language-model.test.ts +518 -0
  151. package/src/middleware/wrap-language-model.ts +104 -0
  152. package/src/middleware/wrap-provider.test.ts +120 -0
  153. package/src/middleware/wrap-provider.ts +51 -0
  154. package/src/model/as-embedding-model-v3.test.ts +319 -0
  155. package/src/model/as-embedding-model-v3.ts +24 -0
  156. package/src/model/as-image-model-v3.test.ts +409 -0
  157. package/src/model/as-image-model-v3.ts +24 -0
  158. package/src/model/as-language-model-v3.test.ts +508 -0
  159. package/src/model/as-language-model-v3.ts +103 -0
  160. package/src/model/as-provider-v3.ts +36 -0
  161. package/src/model/as-speech-model-v3.test.ts +356 -0
  162. package/src/model/as-speech-model-v3.ts +24 -0
  163. package/src/model/as-transcription-model-v3.test.ts +529 -0
  164. package/src/model/as-transcription-model-v3.ts +24 -0
  165. package/src/model/resolve-model.test.ts +244 -0
  166. package/src/model/resolve-model.ts +126 -0
  167. package/src/prompt/call-settings.ts +148 -0
  168. package/src/prompt/content-part.ts +209 -0
  169. package/src/prompt/convert-to-language-model-prompt.test.ts +2018 -0
  170. package/src/prompt/convert-to-language-model-prompt.ts +442 -0
  171. package/src/prompt/create-tool-model-output.test.ts +508 -0
  172. package/src/prompt/create-tool-model-output.ts +34 -0
  173. package/src/prompt/data-content.test.ts +15 -0
  174. package/src/prompt/data-content.ts +134 -0
  175. package/src/prompt/index.ts +27 -0
  176. package/src/prompt/invalid-data-content-error.ts +29 -0
  177. package/src/prompt/invalid-message-role-error.ts +27 -0
  178. package/src/prompt/message-conversion-error.ts +28 -0
  179. package/src/prompt/message.ts +68 -0
  180. package/src/prompt/prepare-call-settings.test.ts +159 -0
  181. package/src/prompt/prepare-call-settings.ts +108 -0
  182. package/src/prompt/prepare-tools-and-tool-choice.test.ts +461 -0
  183. package/src/prompt/prepare-tools-and-tool-choice.ts +86 -0
  184. package/src/prompt/prompt.ts +43 -0
  185. package/src/prompt/split-data-url.ts +17 -0
  186. package/src/prompt/standardize-prompt.test.ts +82 -0
  187. package/src/prompt/standardize-prompt.ts +99 -0
  188. package/src/prompt/wrap-gateway-error.ts +29 -0
  189. package/src/registry/custom-provider.test.ts +211 -0
  190. package/src/registry/custom-provider.ts +155 -0
  191. package/src/registry/index.ts +7 -0
  192. package/src/registry/no-such-provider-error.ts +41 -0
  193. package/src/registry/provider-registry.test.ts +691 -0
  194. package/src/registry/provider-registry.ts +328 -0
  195. package/src/rerank/index.ts +2 -0
  196. package/src/rerank/rerank-result.ts +70 -0
  197. package/src/rerank/rerank.test.ts +516 -0
  198. package/src/rerank/rerank.ts +237 -0
  199. package/src/telemetry/assemble-operation-name.ts +21 -0
  200. package/src/telemetry/get-base-telemetry-attributes.ts +53 -0
  201. package/src/telemetry/get-tracer.ts +20 -0
  202. package/src/telemetry/noop-tracer.ts +69 -0
  203. package/src/telemetry/record-span.ts +63 -0
  204. package/src/telemetry/select-telemetry-attributes.ts +78 -0
  205. package/src/telemetry/select-temetry-attributes.test.ts +114 -0
  206. package/src/telemetry/stringify-for-telemetry.test.ts +114 -0
  207. package/src/telemetry/stringify-for-telemetry.ts +33 -0
  208. package/src/telemetry/telemetry-settings.ts +44 -0
  209. package/src/test/mock-embedding-model-v2.ts +35 -0
  210. package/src/test/mock-embedding-model-v3.ts +48 -0
  211. package/src/test/mock-image-model-v2.ts +28 -0
  212. package/src/test/mock-image-model-v3.ts +28 -0
  213. package/src/test/mock-language-model-v2.ts +72 -0
  214. package/src/test/mock-language-model-v3.ts +77 -0
  215. package/src/test/mock-provider-v2.ts +68 -0
  216. package/src/test/mock-provider-v3.ts +80 -0
  217. package/src/test/mock-reranking-model-v3.ts +25 -0
  218. package/src/test/mock-server-response.ts +69 -0
  219. package/src/test/mock-speech-model-v2.ts +24 -0
  220. package/src/test/mock-speech-model-v3.ts +24 -0
  221. package/src/test/mock-tracer.ts +156 -0
  222. package/src/test/mock-transcription-model-v2.ts +24 -0
  223. package/src/test/mock-transcription-model-v3.ts +24 -0
  224. package/src/test/mock-values.ts +4 -0
  225. package/src/test/not-implemented.ts +3 -0
  226. package/src/text-stream/create-text-stream-response.test.ts +38 -0
  227. package/src/text-stream/create-text-stream-response.ts +18 -0
  228. package/src/text-stream/index.ts +2 -0
  229. package/src/text-stream/pipe-text-stream-to-response.test.ts +38 -0
  230. package/src/text-stream/pipe-text-stream-to-response.ts +26 -0
  231. package/src/transcribe/index.ts +2 -0
  232. package/src/transcribe/transcribe-result.ts +60 -0
  233. package/src/transcribe/transcribe.test.ts +313 -0
  234. package/src/transcribe/transcribe.ts +173 -0
  235. package/src/types/embedding-model-middleware.ts +3 -0
  236. package/src/types/embedding-model.ts +18 -0
  237. package/src/types/image-model-middleware.ts +3 -0
  238. package/src/types/image-model-response-metadata.ts +16 -0
  239. package/src/types/image-model.ts +19 -0
  240. package/src/types/index.ts +29 -0
  241. package/src/types/json-value.ts +15 -0
  242. package/src/types/language-model-middleware.ts +3 -0
  243. package/src/types/language-model-request-metadata.ts +6 -0
  244. package/src/types/language-model-response-metadata.ts +21 -0
  245. package/src/types/language-model.ts +104 -0
  246. package/src/types/provider-metadata.ts +16 -0
  247. package/src/types/provider.ts +55 -0
  248. package/src/types/reranking-model.ts +6 -0
  249. package/src/types/speech-model-response-metadata.ts +21 -0
  250. package/src/types/speech-model.ts +6 -0
  251. package/src/types/transcription-model-response-metadata.ts +16 -0
  252. package/src/types/transcription-model.ts +9 -0
  253. package/src/types/usage.ts +200 -0
  254. package/src/types/warning.ts +7 -0
  255. package/src/ui/__snapshots__/append-response-messages.test.ts.snap +416 -0
  256. package/src/ui/__snapshots__/convert-to-model-messages.test.ts.snap +419 -0
  257. package/src/ui/__snapshots__/process-chat-text-response.test.ts.snap +142 -0
  258. package/src/ui/call-completion-api.ts +157 -0
  259. package/src/ui/chat-transport.ts +83 -0
  260. package/src/ui/chat.test-d.ts +233 -0
  261. package/src/ui/chat.test.ts +2695 -0
  262. package/src/ui/chat.ts +716 -0
  263. package/src/ui/convert-file-list-to-file-ui-parts.ts +36 -0
  264. package/src/ui/convert-to-model-messages.test.ts +2775 -0
  265. package/src/ui/convert-to-model-messages.ts +373 -0
  266. package/src/ui/default-chat-transport.ts +36 -0
  267. package/src/ui/direct-chat-transport.test.ts +446 -0
  268. package/src/ui/direct-chat-transport.ts +118 -0
  269. package/src/ui/http-chat-transport.test.ts +185 -0
  270. package/src/ui/http-chat-transport.ts +292 -0
  271. package/src/ui/index.ts +71 -0
  272. package/src/ui/last-assistant-message-is-complete-with-approval-responses.ts +44 -0
  273. package/src/ui/last-assistant-message-is-complete-with-tool-calls.test.ts +371 -0
  274. package/src/ui/last-assistant-message-is-complete-with-tool-calls.ts +39 -0
  275. package/src/ui/process-text-stream.test.ts +38 -0
  276. package/src/ui/process-text-stream.ts +16 -0
  277. package/src/ui/process-ui-message-stream.test.ts +8294 -0
  278. package/src/ui/process-ui-message-stream.ts +761 -0
  279. package/src/ui/text-stream-chat-transport.ts +23 -0
  280. package/src/ui/transform-text-to-ui-message-stream.test.ts +124 -0
  281. package/src/ui/transform-text-to-ui-message-stream.ts +27 -0
  282. package/src/ui/ui-messages.test.ts +48 -0
  283. package/src/ui/ui-messages.ts +534 -0
  284. package/src/ui/use-completion.ts +84 -0
  285. package/src/ui/validate-ui-messages.test.ts +1428 -0
  286. package/src/ui/validate-ui-messages.ts +476 -0
  287. package/src/ui-message-stream/create-ui-message-stream-response.test.ts +266 -0
  288. package/src/ui-message-stream/create-ui-message-stream-response.ts +32 -0
  289. package/src/ui-message-stream/create-ui-message-stream.test.ts +639 -0
  290. package/src/ui-message-stream/create-ui-message-stream.ts +124 -0
  291. package/src/ui-message-stream/get-response-ui-message-id.test.ts +55 -0
  292. package/src/ui-message-stream/get-response-ui-message-id.ts +24 -0
  293. package/src/ui-message-stream/handle-ui-message-stream-finish.test.ts +429 -0
  294. package/src/ui-message-stream/handle-ui-message-stream-finish.ts +135 -0
  295. package/src/ui-message-stream/index.ts +13 -0
  296. package/src/ui-message-stream/json-to-sse-transform-stream.ts +12 -0
  297. package/src/ui-message-stream/pipe-ui-message-stream-to-response.test.ts +90 -0
  298. package/src/ui-message-stream/pipe-ui-message-stream-to-response.ts +40 -0
  299. package/src/ui-message-stream/read-ui-message-stream.test.ts +122 -0
  300. package/src/ui-message-stream/read-ui-message-stream.ts +87 -0
  301. package/src/ui-message-stream/ui-message-chunks.test-d.ts +18 -0
  302. package/src/ui-message-stream/ui-message-chunks.ts +344 -0
  303. package/src/ui-message-stream/ui-message-stream-headers.ts +7 -0
  304. package/src/ui-message-stream/ui-message-stream-on-finish-callback.ts +32 -0
  305. package/src/ui-message-stream/ui-message-stream-response-init.ts +5 -0
  306. package/src/ui-message-stream/ui-message-stream-writer.ts +24 -0
  307. package/src/util/as-array.ts +3 -0
  308. package/src/util/async-iterable-stream.test.ts +241 -0
  309. package/src/util/async-iterable-stream.ts +94 -0
  310. package/src/util/consume-stream.ts +29 -0
  311. package/src/util/cosine-similarity.test.ts +57 -0
  312. package/src/util/cosine-similarity.ts +47 -0
  313. package/src/util/create-resolvable-promise.ts +30 -0
  314. package/src/util/create-stitchable-stream.test.ts +239 -0
  315. package/src/util/create-stitchable-stream.ts +112 -0
  316. package/src/util/data-url.ts +17 -0
  317. package/src/util/deep-partial.ts +84 -0
  318. package/src/util/detect-media-type.test.ts +670 -0
  319. package/src/util/detect-media-type.ts +184 -0
  320. package/src/util/download/download-function.ts +45 -0
  321. package/src/util/download/download.test.ts +69 -0
  322. package/src/util/download/download.ts +46 -0
  323. package/src/util/error-handler.ts +1 -0
  324. package/src/util/fix-json.test.ts +279 -0
  325. package/src/util/fix-json.ts +401 -0
  326. package/src/util/get-potential-start-index.test.ts +34 -0
  327. package/src/util/get-potential-start-index.ts +30 -0
  328. package/src/util/index.ts +11 -0
  329. package/src/util/is-deep-equal-data.test.ts +119 -0
  330. package/src/util/is-deep-equal-data.ts +48 -0
  331. package/src/util/is-non-empty-object.ts +5 -0
  332. package/src/util/job.ts +1 -0
  333. package/src/util/log-v2-compatibility-warning.ts +21 -0
  334. package/src/util/merge-abort-signals.test.ts +155 -0
  335. package/src/util/merge-abort-signals.ts +43 -0
  336. package/src/util/merge-objects.test.ts +118 -0
  337. package/src/util/merge-objects.ts +79 -0
  338. package/src/util/now.ts +4 -0
  339. package/src/util/parse-partial-json.test.ts +80 -0
  340. package/src/util/parse-partial-json.ts +30 -0
  341. package/src/util/prepare-headers.test.ts +51 -0
  342. package/src/util/prepare-headers.ts +14 -0
  343. package/src/util/prepare-retries.test.ts +10 -0
  344. package/src/util/prepare-retries.ts +47 -0
  345. package/src/util/retry-error.ts +41 -0
  346. package/src/util/retry-with-exponential-backoff.test.ts +446 -0
  347. package/src/util/retry-with-exponential-backoff.ts +154 -0
  348. package/src/util/serial-job-executor.test.ts +162 -0
  349. package/src/util/serial-job-executor.ts +36 -0
  350. package/src/util/simulate-readable-stream.test.ts +98 -0
  351. package/src/util/simulate-readable-stream.ts +39 -0
  352. package/src/util/split-array.test.ts +60 -0
  353. package/src/util/split-array.ts +20 -0
  354. package/src/util/value-of.ts +65 -0
  355. package/src/util/write-to-server-response.test.ts +266 -0
  356. package/src/util/write-to-server-response.ts +49 -0
  357. package/src/version.ts +5 -0
@@ -0,0 +1,691 @@
1
+ import { NoSuchModelError } from '@ai-sdk/provider';
2
+ import { MockEmbeddingModelV3 } from '../test/mock-embedding-model-v3';
3
+ import { MockLanguageModelV3 } from '../test/mock-language-model-v3';
4
+ import { NoSuchProviderError } from './no-such-provider-error';
5
+ import { createProviderRegistry } from './provider-registry';
6
+ import { MockImageModelV3 } from '../test/mock-image-model-v3';
7
+ import { MockTranscriptionModelV3 } from '../test/mock-transcription-model-v3';
8
+ import { MockSpeechModelV3 } from '../test/mock-speech-model-v3';
9
+ import { MockRerankingModelV3 } from '../test/mock-reranking-model-v3';
10
+ import { MockProviderV3 } from '../test/mock-provider-v3';
11
+ import { describe, it, expect, vi } from 'vitest';
12
+
13
+ describe('languageModel', () => {
14
+ it('should return language model from provider', () => {
15
+ const model = new MockLanguageModelV3();
16
+
17
+ const modelRegistry = createProviderRegistry({
18
+ provider: {
19
+ specificationVersion: 'v3',
20
+ languageModel: (id: string) => {
21
+ expect(id).toEqual('model');
22
+ return model;
23
+ },
24
+ embeddingModel: (id: string) => {
25
+ return null as any;
26
+ },
27
+ imageModel: (id: string) => {
28
+ return null as any;
29
+ },
30
+ rerankingModel: (id: string) => {
31
+ return null as any;
32
+ },
33
+ },
34
+ });
35
+
36
+ expect(modelRegistry.languageModel('provider:model')).toEqual(model);
37
+ });
38
+
39
+ it('should return language model with additional colon from provider', () => {
40
+ const model = new MockLanguageModelV3();
41
+
42
+ const modelRegistry = createProviderRegistry({
43
+ provider: {
44
+ specificationVersion: 'v3',
45
+ languageModel: id => {
46
+ expect(id).toEqual('model:part2');
47
+ return model;
48
+ },
49
+ embeddingModel: () => {
50
+ return null as any;
51
+ },
52
+ imageModel: () => {
53
+ return null as any;
54
+ },
55
+ rerankingModel: (id: string) => {
56
+ return null as any;
57
+ },
58
+ },
59
+ });
60
+
61
+ expect(modelRegistry.languageModel('provider:model:part2')).toEqual(model);
62
+ });
63
+
64
+ it('should throw NoSuchProviderError if provider does not exist', () => {
65
+ const registry = createProviderRegistry({});
66
+
67
+ // @ts-expect-error - should not accept arbitrary strings
68
+ expect(() => registry.languageModel('provider:model:part2')).toThrowError(
69
+ NoSuchProviderError,
70
+ );
71
+ });
72
+
73
+ it('should throw NoSuchModelError if provider does not return a model', () => {
74
+ const registry = createProviderRegistry({
75
+ provider: {
76
+ specificationVersion: 'v3',
77
+ languageModel: () => {
78
+ return null as any;
79
+ },
80
+ embeddingModel: () => {
81
+ return null as any;
82
+ },
83
+ imageModel: () => {
84
+ return null as any;
85
+ },
86
+ transcriptionModel: () => {
87
+ return null as any;
88
+ },
89
+ speechModel: () => {
90
+ return null as any;
91
+ },
92
+ rerankingModel: () => {
93
+ return null as any;
94
+ },
95
+ },
96
+ });
97
+
98
+ expect(() => registry.languageModel('provider:model')).toThrowError(
99
+ NoSuchModelError,
100
+ );
101
+ });
102
+
103
+ it("should throw NoSuchModelError if model id doesn't contain a colon", () => {
104
+ const registry = createProviderRegistry({});
105
+
106
+ // @ts-expect-error - should not accept arbitrary strings
107
+ expect(() => registry.languageModel('model')).toThrowError(
108
+ NoSuchModelError,
109
+ );
110
+ });
111
+
112
+ it('should support custom separator', () => {
113
+ const model = new MockLanguageModelV3();
114
+
115
+ const modelRegistry = createProviderRegistry(
116
+ {
117
+ provider: {
118
+ specificationVersion: 'v3',
119
+ languageModel: id => {
120
+ expect(id).toEqual('model');
121
+ return model;
122
+ },
123
+ embeddingModel: () => {
124
+ return null as any;
125
+ },
126
+ imageModel: () => {
127
+ return null as any;
128
+ },
129
+ transcriptionModel: () => {
130
+ return null as any;
131
+ },
132
+ speechModel: () => {
133
+ return null as any;
134
+ },
135
+ rerankingModel: () => {
136
+ return null as any;
137
+ },
138
+ },
139
+ },
140
+ { separator: '|' },
141
+ );
142
+
143
+ expect(modelRegistry.languageModel('provider|model')).toEqual(model);
144
+ });
145
+
146
+ it('should support custom separator with multiple characters', () => {
147
+ const model = new MockLanguageModelV3();
148
+
149
+ const modelRegistry = createProviderRegistry(
150
+ {
151
+ provider: {
152
+ specificationVersion: 'v3',
153
+ languageModel: id => {
154
+ expect(id).toEqual('model');
155
+ return model;
156
+ },
157
+ embeddingModel: () => {
158
+ return null as any;
159
+ },
160
+ imageModel: () => {
161
+ return null as any;
162
+ },
163
+ transcriptionModel: () => {
164
+ return null as any;
165
+ },
166
+ speechModel: () => {
167
+ return null as any;
168
+ },
169
+ rerankingModel: () => {
170
+ return null as any;
171
+ },
172
+ },
173
+ },
174
+ { separator: ' > ' },
175
+ );
176
+
177
+ expect(modelRegistry.languageModel('provider > model')).toEqual(model);
178
+ });
179
+ });
180
+
181
+ describe('embeddingModel', () => {
182
+ it('should return embedding model from provider using embeddingModel', () => {
183
+ const model = new MockEmbeddingModelV3();
184
+
185
+ const modelRegistry = createProviderRegistry({
186
+ provider: {
187
+ specificationVersion: 'v3',
188
+ embeddingModel: id => {
189
+ expect(id).toEqual('model');
190
+ return model;
191
+ },
192
+ languageModel: () => {
193
+ return null as any;
194
+ },
195
+ imageModel: () => {
196
+ return null as any;
197
+ },
198
+ transcriptionModel: () => {
199
+ return null as any;
200
+ },
201
+ speechModel: () => {
202
+ return null as any;
203
+ },
204
+ rerankingModel: () => {
205
+ return null as any;
206
+ },
207
+ },
208
+ });
209
+
210
+ expect(modelRegistry.embeddingModel('provider:model')).toEqual(model);
211
+ });
212
+
213
+ it('should throw NoSuchProviderError if provider does not exist', () => {
214
+ const registry = createProviderRegistry({});
215
+
216
+ // @ts-expect-error - should not accept arbitrary strings
217
+ expect(() => registry.embeddingModel('provider:model')).toThrowError(
218
+ NoSuchProviderError,
219
+ );
220
+ });
221
+
222
+ it('should throw NoSuchModelError if provider does not return a model', () => {
223
+ const registry = createProviderRegistry({
224
+ provider: {
225
+ specificationVersion: 'v3',
226
+ embeddingModel: () => {
227
+ return null as any;
228
+ },
229
+ languageModel: () => {
230
+ return null as any;
231
+ },
232
+ imageModel: () => {
233
+ return null as any;
234
+ },
235
+ rerankingModel: (id: string) => {
236
+ return null as any;
237
+ },
238
+ },
239
+ });
240
+
241
+ expect(() => registry.languageModel('provider:model')).toThrowError(
242
+ NoSuchModelError,
243
+ );
244
+ });
245
+
246
+ it("should throw NoSuchModelError if model id doesn't contain a colon", () => {
247
+ const registry = createProviderRegistry({});
248
+
249
+ // @ts-expect-error - should not accept arbitrary strings
250
+ expect(() => registry.embeddingModel('model')).toThrowError(
251
+ NoSuchModelError,
252
+ );
253
+ });
254
+
255
+ it('should support custom separator', () => {
256
+ const model = new MockEmbeddingModelV3();
257
+
258
+ const modelRegistry = createProviderRegistry(
259
+ {
260
+ provider: {
261
+ specificationVersion: 'v3',
262
+ embeddingModel: id => {
263
+ expect(id).toEqual('model');
264
+ return model;
265
+ },
266
+ languageModel: () => {
267
+ return null as any;
268
+ },
269
+ imageModel: () => {
270
+ return null as any;
271
+ },
272
+ transcriptionModel: () => {
273
+ return null as any;
274
+ },
275
+ speechModel: () => {
276
+ return null as any;
277
+ },
278
+ rerankingModel: (id: string) => {
279
+ return null as any;
280
+ },
281
+ },
282
+ },
283
+ { separator: '|' },
284
+ );
285
+
286
+ expect(modelRegistry.embeddingModel('provider|model')).toEqual(model);
287
+ });
288
+ });
289
+
290
+ describe('imageModel', () => {
291
+ it('should return image model from provider', () => {
292
+ const model = new MockImageModelV3();
293
+
294
+ const modelRegistry = createProviderRegistry({
295
+ provider: {
296
+ specificationVersion: 'v3',
297
+ imageModel: id => {
298
+ expect(id).toEqual('model');
299
+ return model;
300
+ },
301
+ languageModel: () => null as any,
302
+ embeddingModel: () => null as any,
303
+ transcriptionModel: () => null as any,
304
+ speechModel: () => null as any,
305
+ rerankingModel: () => null as any,
306
+ },
307
+ });
308
+
309
+ expect(modelRegistry.imageModel('provider:model')).toEqual(model);
310
+ });
311
+
312
+ it('should throw NoSuchProviderError if provider does not exist', () => {
313
+ const registry = createProviderRegistry({});
314
+
315
+ // @ts-expect-error - should not accept arbitrary strings
316
+ expect(() => registry.imageModel('provider:model')).toThrowError(
317
+ NoSuchProviderError,
318
+ );
319
+ });
320
+
321
+ it('should throw NoSuchModelError if provider does not return a model', () => {
322
+ const registry = createProviderRegistry({
323
+ provider: {
324
+ specificationVersion: 'v3',
325
+ imageModel: () => null as any,
326
+ languageModel: () => null as any,
327
+ embeddingModel: () => null as any,
328
+ transcriptionModel: () => null as any,
329
+ rerankingModel: () => null as any,
330
+ },
331
+ });
332
+
333
+ expect(() => registry.imageModel('provider:model')).toThrowError(
334
+ NoSuchModelError,
335
+ );
336
+ });
337
+
338
+ it("should throw NoSuchModelError if model id doesn't contain a colon", () => {
339
+ const registry = createProviderRegistry({});
340
+
341
+ // @ts-expect-error - should not accept arbitrary strings
342
+ expect(() => registry.imageModel('model')).toThrowError(NoSuchModelError);
343
+ });
344
+
345
+ it('should support custom separator', () => {
346
+ const model = new MockImageModelV3();
347
+
348
+ const modelRegistry = createProviderRegistry(
349
+ {
350
+ provider: {
351
+ specificationVersion: 'v3',
352
+ imageModel: id => {
353
+ expect(id).toEqual('model');
354
+ return model;
355
+ },
356
+ languageModel: () => null as any,
357
+ embeddingModel: () => null as any,
358
+ rerankingModel: () => null as any,
359
+ },
360
+ },
361
+ { separator: '|' },
362
+ );
363
+
364
+ expect(modelRegistry.imageModel('provider|model')).toEqual(model);
365
+ });
366
+ });
367
+
368
+ describe('transcriptionModel', () => {
369
+ it('should return transcription model from provider', () => {
370
+ const model = new MockTranscriptionModelV3();
371
+
372
+ const modelRegistry = createProviderRegistry({
373
+ provider: {
374
+ specificationVersion: 'v3',
375
+ transcriptionModel: id => {
376
+ expect(id).toEqual('model');
377
+ return model;
378
+ },
379
+ languageModel: () => null as any,
380
+ embeddingModel: () => null as any,
381
+ imageModel: () => null as any,
382
+ rerankingModel: () => null as any,
383
+ },
384
+ });
385
+
386
+ expect(modelRegistry.transcriptionModel('provider:model')).toEqual(model);
387
+ });
388
+
389
+ it('should throw NoSuchProviderError if provider does not exist', () => {
390
+ const registry = createProviderRegistry({});
391
+
392
+ // @ts-expect-error - should not accept arbitrary strings
393
+ expect(() => registry.transcriptionModel('provider:model')).toThrowError(
394
+ NoSuchProviderError,
395
+ );
396
+ });
397
+
398
+ it('should throw NoSuchModelError if provider does not return a model', () => {
399
+ const registry = createProviderRegistry({
400
+ provider: {
401
+ specificationVersion: 'v3',
402
+ transcriptionModel: () => null as any,
403
+ languageModel: () => null as any,
404
+ embeddingModel: () => null as any,
405
+ imageModel: () => null as any,
406
+ rerankingModel: () => null as any,
407
+ },
408
+ });
409
+
410
+ expect(() => registry.transcriptionModel('provider:model')).toThrowError(
411
+ NoSuchModelError,
412
+ );
413
+ });
414
+
415
+ it("should throw NoSuchModelError if model id doesn't contain a colon", () => {
416
+ const registry = createProviderRegistry({});
417
+
418
+ // @ts-expect-error - should not accept arbitrary strings
419
+ expect(() => registry.transcriptionModel('model')).toThrowError(
420
+ NoSuchModelError,
421
+ );
422
+ });
423
+ });
424
+
425
+ describe('speechModel', () => {
426
+ it('should return speech model from provider', () => {
427
+ const model = new MockSpeechModelV3();
428
+
429
+ const modelRegistry = createProviderRegistry({
430
+ provider: {
431
+ specificationVersion: 'v3',
432
+ speechModel: id => {
433
+ expect(id).toEqual('model');
434
+ return model;
435
+ },
436
+ languageModel: () => null as any,
437
+ embeddingModel: () => null as any,
438
+ imageModel: () => null as any,
439
+ rerankingModel: () => null as any,
440
+ },
441
+ });
442
+
443
+ expect(modelRegistry.speechModel('provider:model')).toEqual(model);
444
+ });
445
+
446
+ it('should throw NoSuchProviderError if provider does not exist', () => {
447
+ const registry = createProviderRegistry({});
448
+
449
+ // @ts-expect-error - should not accept arbitrary strings
450
+ expect(() => registry.speechModel('provider:model')).toThrowError(
451
+ NoSuchProviderError,
452
+ );
453
+ });
454
+
455
+ it('should throw NoSuchModelError if provider does not return a model', () => {
456
+ const registry = createProviderRegistry({
457
+ provider: {
458
+ specificationVersion: 'v3',
459
+ speechModel: () => null as any,
460
+ languageModel: () => null as any,
461
+ embeddingModel: () => null as any,
462
+ imageModel: () => null as any,
463
+ rerankingModel: () => null as any,
464
+ },
465
+ });
466
+
467
+ expect(() => registry.speechModel('provider:model')).toThrowError(
468
+ NoSuchModelError,
469
+ );
470
+ });
471
+
472
+ it("should throw NoSuchModelError if model id doesn't contain a colon", () => {
473
+ const registry = createProviderRegistry({});
474
+
475
+ // @ts-expect-error - should not accept arbitrary strings
476
+ expect(() => registry.speechModel('model')).toThrowError(NoSuchModelError);
477
+ });
478
+ });
479
+
480
+ describe('rerankingModel', () => {
481
+ it('should return reranking model from provider using rerankingModel', () => {
482
+ const model = new MockRerankingModelV3();
483
+
484
+ const modelRegistry = createProviderRegistry({
485
+ provider: {
486
+ specificationVersion: 'v3',
487
+ rerankingModel: id => {
488
+ expect(id).toEqual('model');
489
+ return model;
490
+ },
491
+ embeddingModel: () => {
492
+ return null as any;
493
+ },
494
+ languageModel: () => {
495
+ return null as any;
496
+ },
497
+ imageModel: () => {
498
+ return null as any;
499
+ },
500
+ transcriptionModel: () => {
501
+ return null as any;
502
+ },
503
+ speechModel: () => {
504
+ return null as any;
505
+ },
506
+ },
507
+ });
508
+
509
+ expect(modelRegistry.rerankingModel('provider:model')).toEqual(model);
510
+ });
511
+
512
+ it('should throw NoSuchProviderError if provider does not exist', () => {
513
+ const registry = createProviderRegistry({});
514
+
515
+ // @ts-expect-error - should not accept arbitrary strings
516
+ expect(() => registry.rerankingModel('provider:model')).toThrowError(
517
+ NoSuchProviderError,
518
+ );
519
+ });
520
+
521
+ it('should throw NoSuchModelError if provider does not return a model', () => {
522
+ const registry = createProviderRegistry({
523
+ provider: {
524
+ specificationVersion: 'v3',
525
+ embeddingModel: () => {
526
+ return null as any;
527
+ },
528
+ languageModel: () => {
529
+ return null as any;
530
+ },
531
+ imageModel: () => {
532
+ return null as any;
533
+ },
534
+ rerankingModel: (id: string) => {
535
+ return null as any;
536
+ },
537
+ },
538
+ });
539
+
540
+ expect(() => registry.rerankingModel('provider:model')).toThrowError(
541
+ NoSuchModelError,
542
+ );
543
+ });
544
+
545
+ it("should throw NoSuchModelError if model id doesn't contain a colon", () => {
546
+ const registry = createProviderRegistry({});
547
+
548
+ // @ts-expect-error - should not accept arbitrary strings
549
+ expect(() => registry.rerankingModel('model')).toThrowError(
550
+ NoSuchModelError,
551
+ );
552
+ });
553
+
554
+ it('should support custom separator', () => {
555
+ const model = new MockRerankingModelV3();
556
+
557
+ const modelRegistry = createProviderRegistry(
558
+ {
559
+ provider: {
560
+ specificationVersion: 'v3',
561
+ rerankingModel: id => {
562
+ expect(id).toEqual('model');
563
+ return model;
564
+ },
565
+ embeddingModel: () => {
566
+ return null as any;
567
+ },
568
+ languageModel: () => {
569
+ return null as any;
570
+ },
571
+ imageModel: () => {
572
+ return null as any;
573
+ },
574
+ transcriptionModel: () => {
575
+ return null as any;
576
+ },
577
+ speechModel: () => {
578
+ return null as any;
579
+ },
580
+ },
581
+ },
582
+ { separator: '|' },
583
+ );
584
+
585
+ expect(modelRegistry.rerankingModel('provider|model')).toEqual(model);
586
+ });
587
+ });
588
+
589
+ describe('middleware functionality', () => {
590
+ it('should wrap all language models accessed through the provider registry', () => {
591
+ const model1 = new MockLanguageModelV3({ modelId: 'model-1' });
592
+ const model2 = new MockLanguageModelV3({ modelId: 'model-2' });
593
+ const model3 = new MockLanguageModelV3({ modelId: 'model-3' });
594
+
595
+ const provider1 = new MockProviderV3({
596
+ languageModels: {
597
+ 'model-1': model1,
598
+ 'model-2': model2,
599
+ },
600
+ });
601
+
602
+ const provider2 = new MockProviderV3({
603
+ languageModels: {
604
+ 'model-3': model3,
605
+ },
606
+ });
607
+
608
+ const overrideModelId = vi
609
+ .fn()
610
+ .mockImplementation(({ model }) => `override-${model.modelId}`);
611
+
612
+ const registry = createProviderRegistry(
613
+ {
614
+ provider1,
615
+ provider2,
616
+ },
617
+ {
618
+ languageModelMiddleware: {
619
+ specificationVersion: 'v3',
620
+ overrideModelId,
621
+ },
622
+ },
623
+ );
624
+
625
+ expect(registry.languageModel('provider1:model-1').modelId).toBe(
626
+ 'override-model-1',
627
+ );
628
+ expect(registry.languageModel('provider1:model-2').modelId).toBe(
629
+ 'override-model-2',
630
+ );
631
+ expect(registry.languageModel('provider2:model-3').modelId).toBe(
632
+ 'override-model-3',
633
+ );
634
+
635
+ expect(overrideModelId).toHaveBeenCalledTimes(3);
636
+ expect(overrideModelId).toHaveBeenCalledWith({ model: model1 });
637
+ expect(overrideModelId).toHaveBeenCalledWith({ model: model2 });
638
+ expect(overrideModelId).toHaveBeenCalledWith({ model: model3 });
639
+ });
640
+
641
+ it('should wrap all image models accessed through the provider registry', () => {
642
+ const model1 = new MockImageModelV3({ modelId: 'model-1' });
643
+ const model2 = new MockImageModelV3({ modelId: 'model-2' });
644
+ const model3 = new MockImageModelV3({ modelId: 'model-3' });
645
+
646
+ const provider1 = new MockProviderV3({
647
+ imageModels: {
648
+ 'model-1': model1,
649
+ 'model-2': model2,
650
+ },
651
+ });
652
+
653
+ const provider2 = new MockProviderV3({
654
+ imageModels: {
655
+ 'model-3': model3,
656
+ },
657
+ });
658
+
659
+ const overrideModelId = vi
660
+ .fn()
661
+ .mockImplementation(({ model }) => `override-${model.modelId}`);
662
+
663
+ const registry = createProviderRegistry(
664
+ {
665
+ provider1,
666
+ provider2,
667
+ },
668
+ {
669
+ imageModelMiddleware: {
670
+ specificationVersion: 'v3',
671
+ overrideModelId,
672
+ },
673
+ },
674
+ );
675
+
676
+ expect(registry.imageModel('provider1:model-1').modelId).toBe(
677
+ 'override-model-1',
678
+ );
679
+ expect(registry.imageModel('provider1:model-2').modelId).toBe(
680
+ 'override-model-2',
681
+ );
682
+ expect(registry.imageModel('provider2:model-3').modelId).toBe(
683
+ 'override-model-3',
684
+ );
685
+
686
+ expect(overrideModelId).toHaveBeenCalledTimes(3);
687
+ expect(overrideModelId).toHaveBeenCalledWith({ model: model1 });
688
+ expect(overrideModelId).toHaveBeenCalledWith({ model: model2 });
689
+ expect(overrideModelId).toHaveBeenCalledWith({ model: model3 });
690
+ });
691
+ });