ai 6.0.32 → 6.0.34

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 (353) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/index.js +12 -2
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +12 -2
  5. package/dist/index.mjs.map +1 -1
  6. package/dist/internal/index.js +1 -1
  7. package/dist/internal/index.mjs +1 -1
  8. package/docs/02-foundations/03-prompts.mdx +2 -2
  9. package/docs/03-ai-sdk-core/15-tools-and-tool-calling.mdx +1 -1
  10. package/docs/07-reference/01-ai-sdk-core/28-output.mdx +1 -1
  11. package/package.json +6 -4
  12. package/src/agent/agent.ts +116 -0
  13. package/src/agent/create-agent-ui-stream-response.test.ts +258 -0
  14. package/src/agent/create-agent-ui-stream-response.ts +50 -0
  15. package/src/agent/create-agent-ui-stream.ts +73 -0
  16. package/src/agent/index.ts +33 -0
  17. package/src/agent/infer-agent-tools.ts +7 -0
  18. package/src/agent/infer-agent-ui-message.test-d.ts +54 -0
  19. package/src/agent/infer-agent-ui-message.ts +11 -0
  20. package/src/agent/pipe-agent-ui-stream-to-response.ts +52 -0
  21. package/src/agent/tool-loop-agent-on-finish-callback.ts +31 -0
  22. package/src/agent/tool-loop-agent-on-step-finish-callback.ts +11 -0
  23. package/src/agent/tool-loop-agent-settings.ts +182 -0
  24. package/src/agent/tool-loop-agent.test-d.ts +114 -0
  25. package/src/agent/tool-loop-agent.test.ts +442 -0
  26. package/src/agent/tool-loop-agent.ts +114 -0
  27. package/src/embed/__snapshots__/embed-many.test.ts.snap +191 -0
  28. package/src/embed/__snapshots__/embed.test.ts.snap +81 -0
  29. package/src/embed/embed-many-result.ts +53 -0
  30. package/src/embed/embed-many.test.ts +653 -0
  31. package/src/embed/embed-many.ts +378 -0
  32. package/src/embed/embed-result.ts +50 -0
  33. package/src/embed/embed.test.ts +298 -0
  34. package/src/embed/embed.ts +211 -0
  35. package/src/embed/index.ts +4 -0
  36. package/src/error/index.ts +34 -0
  37. package/src/error/invalid-argument-error.ts +34 -0
  38. package/src/error/invalid-stream-part-error.ts +28 -0
  39. package/src/error/invalid-tool-approval-error.ts +26 -0
  40. package/src/error/invalid-tool-input-error.ts +33 -0
  41. package/src/error/no-image-generated-error.ts +39 -0
  42. package/src/error/no-object-generated-error.ts +70 -0
  43. package/src/error/no-output-generated-error.ts +26 -0
  44. package/src/error/no-speech-generated-error.ts +18 -0
  45. package/src/error/no-such-tool-error.ts +35 -0
  46. package/src/error/no-transcript-generated-error.ts +20 -0
  47. package/src/error/tool-call-not-found-for-approval-error.ts +32 -0
  48. package/src/error/tool-call-repair-error.ts +30 -0
  49. package/src/error/unsupported-model-version-error.ts +23 -0
  50. package/src/error/verify-no-object-generated-error.ts +27 -0
  51. package/src/generate-image/generate-image-result.ts +42 -0
  52. package/src/generate-image/generate-image.test.ts +1420 -0
  53. package/src/generate-image/generate-image.ts +360 -0
  54. package/src/generate-image/index.ts +18 -0
  55. package/src/generate-object/__snapshots__/generate-object.test.ts.snap +133 -0
  56. package/src/generate-object/__snapshots__/stream-object.test.ts.snap +297 -0
  57. package/src/generate-object/generate-object-result.ts +67 -0
  58. package/src/generate-object/generate-object.test-d.ts +49 -0
  59. package/src/generate-object/generate-object.test.ts +1191 -0
  60. package/src/generate-object/generate-object.ts +518 -0
  61. package/src/generate-object/index.ts +9 -0
  62. package/src/generate-object/inject-json-instruction.test.ts +181 -0
  63. package/src/generate-object/inject-json-instruction.ts +30 -0
  64. package/src/generate-object/output-strategy.ts +415 -0
  65. package/src/generate-object/parse-and-validate-object-result.ts +111 -0
  66. package/src/generate-object/repair-text.ts +12 -0
  67. package/src/generate-object/stream-object-result.ts +120 -0
  68. package/src/generate-object/stream-object.test-d.ts +74 -0
  69. package/src/generate-object/stream-object.test.ts +1950 -0
  70. package/src/generate-object/stream-object.ts +986 -0
  71. package/src/generate-object/validate-object-generation-input.ts +144 -0
  72. package/src/generate-speech/generate-speech-result.ts +30 -0
  73. package/src/generate-speech/generate-speech.test.ts +300 -0
  74. package/src/generate-speech/generate-speech.ts +190 -0
  75. package/src/generate-speech/generated-audio-file.ts +65 -0
  76. package/src/generate-speech/index.ts +3 -0
  77. package/src/generate-text/__snapshots__/generate-text.test.ts.snap +1872 -0
  78. package/src/generate-text/__snapshots__/stream-text.test.ts.snap +1255 -0
  79. package/src/generate-text/collect-tool-approvals.test.ts +553 -0
  80. package/src/generate-text/collect-tool-approvals.ts +116 -0
  81. package/src/generate-text/content-part.ts +25 -0
  82. package/src/generate-text/execute-tool-call.ts +129 -0
  83. package/src/generate-text/extract-reasoning-content.ts +17 -0
  84. package/src/generate-text/extract-text-content.ts +15 -0
  85. package/src/generate-text/generate-text-result.ts +168 -0
  86. package/src/generate-text/generate-text.test-d.ts +68 -0
  87. package/src/generate-text/generate-text.test.ts +7011 -0
  88. package/src/generate-text/generate-text.ts +1223 -0
  89. package/src/generate-text/generated-file.ts +70 -0
  90. package/src/generate-text/index.ts +57 -0
  91. package/src/generate-text/is-approval-needed.ts +29 -0
  92. package/src/generate-text/output-utils.ts +23 -0
  93. package/src/generate-text/output.test.ts +698 -0
  94. package/src/generate-text/output.ts +590 -0
  95. package/src/generate-text/parse-tool-call.test.ts +570 -0
  96. package/src/generate-text/parse-tool-call.ts +188 -0
  97. package/src/generate-text/prepare-step.ts +103 -0
  98. package/src/generate-text/prune-messages.test.ts +720 -0
  99. package/src/generate-text/prune-messages.ts +167 -0
  100. package/src/generate-text/reasoning-output.ts +20 -0
  101. package/src/generate-text/reasoning.ts +8 -0
  102. package/src/generate-text/response-message.ts +10 -0
  103. package/src/generate-text/run-tools-transformation.test.ts +1143 -0
  104. package/src/generate-text/run-tools-transformation.ts +420 -0
  105. package/src/generate-text/smooth-stream.test.ts +2101 -0
  106. package/src/generate-text/smooth-stream.ts +162 -0
  107. package/src/generate-text/step-result.ts +238 -0
  108. package/src/generate-text/stop-condition.ts +29 -0
  109. package/src/generate-text/stream-text-result.ts +463 -0
  110. package/src/generate-text/stream-text.test-d.ts +200 -0
  111. package/src/generate-text/stream-text.test.ts +19979 -0
  112. package/src/generate-text/stream-text.ts +2505 -0
  113. package/src/generate-text/to-response-messages.test.ts +922 -0
  114. package/src/generate-text/to-response-messages.ts +163 -0
  115. package/src/generate-text/tool-approval-request-output.ts +21 -0
  116. package/src/generate-text/tool-call-repair-function.ts +27 -0
  117. package/src/generate-text/tool-call.ts +47 -0
  118. package/src/generate-text/tool-error.ts +34 -0
  119. package/src/generate-text/tool-output-denied.ts +21 -0
  120. package/src/generate-text/tool-output.ts +7 -0
  121. package/src/generate-text/tool-result.ts +36 -0
  122. package/src/generate-text/tool-set.ts +14 -0
  123. package/src/global.ts +24 -0
  124. package/src/index.ts +50 -0
  125. package/src/logger/index.ts +6 -0
  126. package/src/logger/log-warnings.test.ts +351 -0
  127. package/src/logger/log-warnings.ts +119 -0
  128. package/src/middleware/__snapshots__/simulate-streaming-middleware.test.ts.snap +64 -0
  129. package/src/middleware/add-tool-input-examples-middleware.test.ts +476 -0
  130. package/src/middleware/add-tool-input-examples-middleware.ts +90 -0
  131. package/src/middleware/default-embedding-settings-middleware.test.ts +126 -0
  132. package/src/middleware/default-embedding-settings-middleware.ts +22 -0
  133. package/src/middleware/default-settings-middleware.test.ts +388 -0
  134. package/src/middleware/default-settings-middleware.ts +33 -0
  135. package/src/middleware/extract-json-middleware.test.ts +827 -0
  136. package/src/middleware/extract-json-middleware.ts +197 -0
  137. package/src/middleware/extract-reasoning-middleware.test.ts +1028 -0
  138. package/src/middleware/extract-reasoning-middleware.ts +238 -0
  139. package/src/middleware/index.ts +10 -0
  140. package/src/middleware/simulate-streaming-middleware.test.ts +911 -0
  141. package/src/middleware/simulate-streaming-middleware.ts +79 -0
  142. package/src/middleware/wrap-embedding-model.test.ts +358 -0
  143. package/src/middleware/wrap-embedding-model.ts +86 -0
  144. package/src/middleware/wrap-image-model.test.ts +423 -0
  145. package/src/middleware/wrap-image-model.ts +85 -0
  146. package/src/middleware/wrap-language-model.test.ts +518 -0
  147. package/src/middleware/wrap-language-model.ts +104 -0
  148. package/src/middleware/wrap-provider.test.ts +120 -0
  149. package/src/middleware/wrap-provider.ts +51 -0
  150. package/src/model/as-embedding-model-v3.test.ts +319 -0
  151. package/src/model/as-embedding-model-v3.ts +24 -0
  152. package/src/model/as-image-model-v3.test.ts +409 -0
  153. package/src/model/as-image-model-v3.ts +24 -0
  154. package/src/model/as-language-model-v3.test.ts +508 -0
  155. package/src/model/as-language-model-v3.ts +103 -0
  156. package/src/model/as-provider-v3.ts +36 -0
  157. package/src/model/as-speech-model-v3.test.ts +356 -0
  158. package/src/model/as-speech-model-v3.ts +24 -0
  159. package/src/model/as-transcription-model-v3.test.ts +529 -0
  160. package/src/model/as-transcription-model-v3.ts +24 -0
  161. package/src/model/resolve-model.test.ts +244 -0
  162. package/src/model/resolve-model.ts +126 -0
  163. package/src/prompt/call-settings.ts +148 -0
  164. package/src/prompt/content-part.ts +209 -0
  165. package/src/prompt/convert-to-language-model-prompt.test.ts +2018 -0
  166. package/src/prompt/convert-to-language-model-prompt.ts +442 -0
  167. package/src/prompt/create-tool-model-output.test.ts +508 -0
  168. package/src/prompt/create-tool-model-output.ts +34 -0
  169. package/src/prompt/data-content.test.ts +15 -0
  170. package/src/prompt/data-content.ts +134 -0
  171. package/src/prompt/index.ts +27 -0
  172. package/src/prompt/invalid-data-content-error.ts +29 -0
  173. package/src/prompt/invalid-message-role-error.ts +27 -0
  174. package/src/prompt/message-conversion-error.ts +28 -0
  175. package/src/prompt/message.ts +68 -0
  176. package/src/prompt/prepare-call-settings.test.ts +159 -0
  177. package/src/prompt/prepare-call-settings.ts +108 -0
  178. package/src/prompt/prepare-tools-and-tool-choice.test.ts +461 -0
  179. package/src/prompt/prepare-tools-and-tool-choice.ts +86 -0
  180. package/src/prompt/prompt.ts +43 -0
  181. package/src/prompt/split-data-url.ts +17 -0
  182. package/src/prompt/standardize-prompt.test.ts +82 -0
  183. package/src/prompt/standardize-prompt.ts +99 -0
  184. package/src/prompt/wrap-gateway-error.ts +29 -0
  185. package/src/registry/custom-provider.test.ts +211 -0
  186. package/src/registry/custom-provider.ts +155 -0
  187. package/src/registry/index.ts +7 -0
  188. package/src/registry/no-such-provider-error.ts +41 -0
  189. package/src/registry/provider-registry.test.ts +691 -0
  190. package/src/registry/provider-registry.ts +328 -0
  191. package/src/rerank/index.ts +2 -0
  192. package/src/rerank/rerank-result.ts +70 -0
  193. package/src/rerank/rerank.test.ts +516 -0
  194. package/src/rerank/rerank.ts +237 -0
  195. package/src/telemetry/assemble-operation-name.ts +21 -0
  196. package/src/telemetry/get-base-telemetry-attributes.ts +53 -0
  197. package/src/telemetry/get-tracer.ts +20 -0
  198. package/src/telemetry/noop-tracer.ts +69 -0
  199. package/src/telemetry/record-span.ts +63 -0
  200. package/src/telemetry/select-telemetry-attributes.ts +78 -0
  201. package/src/telemetry/select-temetry-attributes.test.ts +114 -0
  202. package/src/telemetry/stringify-for-telemetry.test.ts +114 -0
  203. package/src/telemetry/stringify-for-telemetry.ts +33 -0
  204. package/src/telemetry/telemetry-settings.ts +44 -0
  205. package/src/test/mock-embedding-model-v2.ts +35 -0
  206. package/src/test/mock-embedding-model-v3.ts +48 -0
  207. package/src/test/mock-image-model-v2.ts +28 -0
  208. package/src/test/mock-image-model-v3.ts +28 -0
  209. package/src/test/mock-language-model-v2.ts +72 -0
  210. package/src/test/mock-language-model-v3.ts +77 -0
  211. package/src/test/mock-provider-v2.ts +68 -0
  212. package/src/test/mock-provider-v3.ts +80 -0
  213. package/src/test/mock-reranking-model-v3.ts +25 -0
  214. package/src/test/mock-server-response.ts +69 -0
  215. package/src/test/mock-speech-model-v2.ts +24 -0
  216. package/src/test/mock-speech-model-v3.ts +24 -0
  217. package/src/test/mock-tracer.ts +156 -0
  218. package/src/test/mock-transcription-model-v2.ts +24 -0
  219. package/src/test/mock-transcription-model-v3.ts +24 -0
  220. package/src/test/mock-values.ts +4 -0
  221. package/src/test/not-implemented.ts +3 -0
  222. package/src/text-stream/create-text-stream-response.test.ts +38 -0
  223. package/src/text-stream/create-text-stream-response.ts +18 -0
  224. package/src/text-stream/index.ts +2 -0
  225. package/src/text-stream/pipe-text-stream-to-response.test.ts +38 -0
  226. package/src/text-stream/pipe-text-stream-to-response.ts +26 -0
  227. package/src/transcribe/index.ts +2 -0
  228. package/src/transcribe/transcribe-result.ts +60 -0
  229. package/src/transcribe/transcribe.test.ts +313 -0
  230. package/src/transcribe/transcribe.ts +173 -0
  231. package/src/types/embedding-model-middleware.ts +3 -0
  232. package/src/types/embedding-model.ts +18 -0
  233. package/src/types/image-model-middleware.ts +3 -0
  234. package/src/types/image-model-response-metadata.ts +16 -0
  235. package/src/types/image-model.ts +19 -0
  236. package/src/types/index.ts +29 -0
  237. package/src/types/json-value.ts +15 -0
  238. package/src/types/language-model-middleware.ts +3 -0
  239. package/src/types/language-model-request-metadata.ts +6 -0
  240. package/src/types/language-model-response-metadata.ts +21 -0
  241. package/src/types/language-model.ts +104 -0
  242. package/src/types/provider-metadata.ts +16 -0
  243. package/src/types/provider.ts +55 -0
  244. package/src/types/reranking-model.ts +6 -0
  245. package/src/types/speech-model-response-metadata.ts +21 -0
  246. package/src/types/speech-model.ts +6 -0
  247. package/src/types/transcription-model-response-metadata.ts +16 -0
  248. package/src/types/transcription-model.ts +9 -0
  249. package/src/types/usage.ts +200 -0
  250. package/src/types/warning.ts +7 -0
  251. package/src/ui/__snapshots__/append-response-messages.test.ts.snap +416 -0
  252. package/src/ui/__snapshots__/convert-to-model-messages.test.ts.snap +419 -0
  253. package/src/ui/__snapshots__/process-chat-text-response.test.ts.snap +142 -0
  254. package/src/ui/call-completion-api.ts +157 -0
  255. package/src/ui/chat-transport.ts +83 -0
  256. package/src/ui/chat.test-d.ts +233 -0
  257. package/src/ui/chat.test.ts +2695 -0
  258. package/src/ui/chat.ts +716 -0
  259. package/src/ui/convert-file-list-to-file-ui-parts.ts +36 -0
  260. package/src/ui/convert-to-model-messages.test.ts +2775 -0
  261. package/src/ui/convert-to-model-messages.ts +373 -0
  262. package/src/ui/default-chat-transport.ts +36 -0
  263. package/src/ui/direct-chat-transport.test.ts +446 -0
  264. package/src/ui/direct-chat-transport.ts +118 -0
  265. package/src/ui/http-chat-transport.test.ts +185 -0
  266. package/src/ui/http-chat-transport.ts +292 -0
  267. package/src/ui/index.ts +71 -0
  268. package/src/ui/last-assistant-message-is-complete-with-approval-responses.ts +44 -0
  269. package/src/ui/last-assistant-message-is-complete-with-tool-calls.test.ts +371 -0
  270. package/src/ui/last-assistant-message-is-complete-with-tool-calls.ts +39 -0
  271. package/src/ui/process-text-stream.test.ts +38 -0
  272. package/src/ui/process-text-stream.ts +16 -0
  273. package/src/ui/process-ui-message-stream.test.ts +8052 -0
  274. package/src/ui/process-ui-message-stream.ts +713 -0
  275. package/src/ui/text-stream-chat-transport.ts +23 -0
  276. package/src/ui/transform-text-to-ui-message-stream.test.ts +124 -0
  277. package/src/ui/transform-text-to-ui-message-stream.ts +27 -0
  278. package/src/ui/ui-messages.test.ts +48 -0
  279. package/src/ui/ui-messages.ts +534 -0
  280. package/src/ui/use-completion.ts +84 -0
  281. package/src/ui/validate-ui-messages.test.ts +1428 -0
  282. package/src/ui/validate-ui-messages.ts +476 -0
  283. package/src/ui-message-stream/create-ui-message-stream-response.test.ts +266 -0
  284. package/src/ui-message-stream/create-ui-message-stream-response.ts +32 -0
  285. package/src/ui-message-stream/create-ui-message-stream.test.ts +639 -0
  286. package/src/ui-message-stream/create-ui-message-stream.ts +124 -0
  287. package/src/ui-message-stream/get-response-ui-message-id.test.ts +55 -0
  288. package/src/ui-message-stream/get-response-ui-message-id.ts +24 -0
  289. package/src/ui-message-stream/handle-ui-message-stream-finish.test.ts +429 -0
  290. package/src/ui-message-stream/handle-ui-message-stream-finish.ts +135 -0
  291. package/src/ui-message-stream/index.ts +13 -0
  292. package/src/ui-message-stream/json-to-sse-transform-stream.ts +12 -0
  293. package/src/ui-message-stream/pipe-ui-message-stream-to-response.test.ts +90 -0
  294. package/src/ui-message-stream/pipe-ui-message-stream-to-response.ts +40 -0
  295. package/src/ui-message-stream/read-ui-message-stream.test.ts +122 -0
  296. package/src/ui-message-stream/read-ui-message-stream.ts +87 -0
  297. package/src/ui-message-stream/ui-message-chunks.test-d.ts +18 -0
  298. package/src/ui-message-stream/ui-message-chunks.ts +344 -0
  299. package/src/ui-message-stream/ui-message-stream-headers.ts +7 -0
  300. package/src/ui-message-stream/ui-message-stream-on-finish-callback.ts +32 -0
  301. package/src/ui-message-stream/ui-message-stream-response-init.ts +5 -0
  302. package/src/ui-message-stream/ui-message-stream-writer.ts +24 -0
  303. package/src/util/as-array.ts +3 -0
  304. package/src/util/async-iterable-stream.test.ts +241 -0
  305. package/src/util/async-iterable-stream.ts +94 -0
  306. package/src/util/consume-stream.ts +29 -0
  307. package/src/util/cosine-similarity.test.ts +57 -0
  308. package/src/util/cosine-similarity.ts +47 -0
  309. package/src/util/create-resolvable-promise.ts +30 -0
  310. package/src/util/create-stitchable-stream.test.ts +239 -0
  311. package/src/util/create-stitchable-stream.ts +112 -0
  312. package/src/util/data-url.ts +17 -0
  313. package/src/util/deep-partial.ts +84 -0
  314. package/src/util/detect-media-type.test.ts +670 -0
  315. package/src/util/detect-media-type.ts +184 -0
  316. package/src/util/download/download-function.ts +45 -0
  317. package/src/util/download/download.test.ts +69 -0
  318. package/src/util/download/download.ts +46 -0
  319. package/src/util/error-handler.ts +1 -0
  320. package/src/util/fix-json.test.ts +279 -0
  321. package/src/util/fix-json.ts +401 -0
  322. package/src/util/get-potential-start-index.test.ts +34 -0
  323. package/src/util/get-potential-start-index.ts +30 -0
  324. package/src/util/index.ts +11 -0
  325. package/src/util/is-deep-equal-data.test.ts +119 -0
  326. package/src/util/is-deep-equal-data.ts +48 -0
  327. package/src/util/is-non-empty-object.ts +5 -0
  328. package/src/util/job.ts +1 -0
  329. package/src/util/log-v2-compatibility-warning.ts +21 -0
  330. package/src/util/merge-abort-signals.test.ts +155 -0
  331. package/src/util/merge-abort-signals.ts +43 -0
  332. package/src/util/merge-objects.test.ts +118 -0
  333. package/src/util/merge-objects.ts +79 -0
  334. package/src/util/now.ts +4 -0
  335. package/src/util/parse-partial-json.test.ts +80 -0
  336. package/src/util/parse-partial-json.ts +30 -0
  337. package/src/util/prepare-headers.test.ts +51 -0
  338. package/src/util/prepare-headers.ts +14 -0
  339. package/src/util/prepare-retries.test.ts +10 -0
  340. package/src/util/prepare-retries.ts +47 -0
  341. package/src/util/retry-error.ts +41 -0
  342. package/src/util/retry-with-exponential-backoff.test.ts +446 -0
  343. package/src/util/retry-with-exponential-backoff.ts +154 -0
  344. package/src/util/serial-job-executor.test.ts +162 -0
  345. package/src/util/serial-job-executor.ts +36 -0
  346. package/src/util/simulate-readable-stream.test.ts +98 -0
  347. package/src/util/simulate-readable-stream.ts +39 -0
  348. package/src/util/split-array.test.ts +60 -0
  349. package/src/util/split-array.ts +20 -0
  350. package/src/util/value-of.ts +65 -0
  351. package/src/util/write-to-server-response.test.ts +266 -0
  352. package/src/util/write-to-server-response.ts +49 -0
  353. package/src/version.ts +5 -0
@@ -0,0 +1,120 @@
1
+ import { MockLanguageModelV2 } from '../test/mock-language-model-v2';
2
+ import { MockLanguageModelV3 } from '../test/mock-language-model-v3';
3
+ import { MockImageModelV3 } from '../test/mock-image-model-v3';
4
+ import { MockProviderV2 } from '../test/mock-provider-v2';
5
+ import { MockProviderV3 } from '../test/mock-provider-v3';
6
+ import { wrapProvider } from './wrap-provider';
7
+ import { describe, it, expect, vi } from 'vitest';
8
+
9
+ describe('wrapProvider', () => {
10
+ it('should wrap all language models in the provider', () => {
11
+ const model1 = new MockLanguageModelV3({ modelId: 'model-1' });
12
+ const model2 = new MockLanguageModelV3({ modelId: 'model-2' });
13
+ const model3 = new MockLanguageModelV3({ modelId: 'model-3' });
14
+
15
+ const provider = new MockProviderV3({
16
+ languageModels: {
17
+ 'model-1': model1,
18
+ 'model-2': model2,
19
+ 'model-3': model3,
20
+ },
21
+ });
22
+
23
+ const overrideModelId = vi
24
+ .fn()
25
+ .mockImplementation(({ model }) => `override-${model.modelId}`);
26
+
27
+ const wrappedProvider = wrapProvider({
28
+ provider,
29
+ languageModelMiddleware: {
30
+ specificationVersion: 'v3',
31
+ overrideModelId,
32
+ },
33
+ });
34
+
35
+ expect(wrappedProvider.languageModel('model-1').modelId).toBe(
36
+ 'override-model-1',
37
+ );
38
+ expect(wrappedProvider.languageModel('model-2').modelId).toBe(
39
+ 'override-model-2',
40
+ );
41
+ expect(wrappedProvider.languageModel('model-3').modelId).toBe(
42
+ 'override-model-3',
43
+ );
44
+
45
+ expect(overrideModelId).toHaveBeenCalledTimes(3);
46
+ expect(overrideModelId).toHaveBeenCalledWith({ model: model1 });
47
+ expect(overrideModelId).toHaveBeenCalledWith({ model: model2 });
48
+ expect(overrideModelId).toHaveBeenCalledWith({ model: model3 });
49
+ });
50
+
51
+ it('should work when the provider is a ProviderV2', () => {
52
+ const v2Model1 = new MockLanguageModelV2({ modelId: 'model-1' });
53
+ const v2Model2 = new MockLanguageModelV2({ modelId: 'model-2' });
54
+
55
+ const providerV2 = new MockProviderV2({
56
+ languageModels: {
57
+ 'model-1': v2Model1,
58
+ 'model-2': v2Model2,
59
+ },
60
+ });
61
+
62
+ const wrapped = wrapProvider({
63
+ provider: providerV2,
64
+ languageModelMiddleware: {
65
+ specificationVersion: 'v3',
66
+ overrideModelId: ({ model }) => `override-${model.modelId}`,
67
+ },
68
+ });
69
+
70
+ expect(wrapped.languageModel('model-1').modelId).toBe('override-model-1');
71
+ expect(wrapped.languageModel('model-2').modelId).toBe('override-model-2');
72
+ });
73
+
74
+ it('should wrap all image models in the provider when image middleware is provided', () => {
75
+ const model1 = new MockImageModelV3({ modelId: 'model-1' });
76
+ const model2 = new MockImageModelV3({ modelId: 'model-2' });
77
+ const model3 = new MockImageModelV3({ modelId: 'model-3' });
78
+
79
+ const provider = new MockProviderV3({
80
+ languageModels: {
81
+ 'language-model': new MockLanguageModelV3({
82
+ modelId: 'language-model',
83
+ }),
84
+ },
85
+ imageModels: {
86
+ 'model-1': model1,
87
+ 'model-2': model2,
88
+ 'model-3': model3,
89
+ },
90
+ });
91
+
92
+ const overrideModelId = vi
93
+ .fn()
94
+ .mockImplementation(({ model }) => `override-${model.modelId}`);
95
+
96
+ const wrappedProvider = wrapProvider({
97
+ provider,
98
+ languageModelMiddleware: { specificationVersion: 'v3' },
99
+ imageModelMiddleware: {
100
+ specificationVersion: 'v3',
101
+ overrideModelId,
102
+ },
103
+ });
104
+
105
+ expect(wrappedProvider.imageModel('model-1').modelId).toBe(
106
+ 'override-model-1',
107
+ );
108
+ expect(wrappedProvider.imageModel('model-2').modelId).toBe(
109
+ 'override-model-2',
110
+ );
111
+ expect(wrappedProvider.imageModel('model-3').modelId).toBe(
112
+ 'override-model-3',
113
+ );
114
+
115
+ expect(overrideModelId).toHaveBeenCalledTimes(3);
116
+ expect(overrideModelId).toHaveBeenCalledWith({ model: model1 });
117
+ expect(overrideModelId).toHaveBeenCalledWith({ model: model2 });
118
+ expect(overrideModelId).toHaveBeenCalledWith({ model: model3 });
119
+ });
120
+ });
@@ -0,0 +1,51 @@
1
+ import type { ProviderV2, ProviderV3 } from '@ai-sdk/provider';
2
+ import { ImageModelMiddleware } from '../types/image-model-middleware';
3
+ import { LanguageModelMiddleware } from '../types/language-model-middleware';
4
+ import { wrapImageModel } from './wrap-image-model';
5
+ import { wrapLanguageModel } from './wrap-language-model';
6
+ import { asProviderV3 } from '../model/as-provider-v3';
7
+
8
+ /**
9
+ * Wraps a ProviderV3 instance with middleware functionality.
10
+ * This function allows you to apply middleware to all language models
11
+ * from the provider, enabling you to transform parameters, wrap generate
12
+ * operations, and wrap stream operations for every language model.
13
+ *
14
+ * @param options - Configuration options for wrapping the provider.
15
+ * @param options.provider - The original ProviderV3 instance to be wrapped.
16
+ * @param options.languageModelMiddleware - The middleware to be applied to all language models from the provider. When multiple middlewares are provided, the first middleware will transform the input first, and the last middleware will be wrapped directly around the model.
17
+ * @param options.imageModelMiddleware - Optional middleware to be applied to all image models from the provider. When multiple middlewares are provided, the first middleware will transform the input first, and the last middleware will be wrapped directly around the model.
18
+ * @returns A new ProviderV3 instance with middleware applied to all language models.
19
+ */
20
+ export function wrapProvider({
21
+ provider,
22
+ languageModelMiddleware,
23
+ imageModelMiddleware,
24
+ }: {
25
+ provider: ProviderV3 | ProviderV2;
26
+ languageModelMiddleware: LanguageModelMiddleware | LanguageModelMiddleware[];
27
+ imageModelMiddleware?: ImageModelMiddleware | ImageModelMiddleware[];
28
+ }): ProviderV3 {
29
+ const providerV3 = asProviderV3(provider);
30
+ return {
31
+ specificationVersion: 'v3',
32
+ languageModel: (modelId: string) =>
33
+ wrapLanguageModel({
34
+ model: providerV3.languageModel(modelId),
35
+ middleware: languageModelMiddleware,
36
+ }),
37
+ embeddingModel: providerV3.embeddingModel,
38
+ imageModel: (modelId: string) => {
39
+ let model = providerV3.imageModel(modelId);
40
+
41
+ if (imageModelMiddleware != null) {
42
+ model = wrapImageModel({ model, middleware: imageModelMiddleware });
43
+ }
44
+
45
+ return model;
46
+ },
47
+ transcriptionModel: providerV3.transcriptionModel,
48
+ speechModel: providerV3.speechModel,
49
+ rerankingModel: providerV3.rerankingModel,
50
+ };
51
+ }
@@ -0,0 +1,319 @@
1
+ import { EmbeddingModelV2 } from '@ai-sdk/provider';
2
+ import { asEmbeddingModelV3 } from './as-embedding-model-v3';
3
+ import { MockEmbeddingModelV2 } from '../test/mock-embedding-model-v2';
4
+ import { MockEmbeddingModelV3 } from '../test/mock-embedding-model-v3';
5
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
6
+ import * as logWarningsModule from '../logger/log-warnings';
7
+
8
+ describe('asEmbeddingModelV3', () => {
9
+ let logWarningSpy: ReturnType<typeof vi.spyOn>;
10
+
11
+ beforeEach(() => {
12
+ logWarningSpy = vi.spyOn(logWarningsModule, 'logWarnings');
13
+ });
14
+
15
+ afterEach(() => {
16
+ logWarningSpy.mockRestore();
17
+ });
18
+
19
+ describe('when an embedding model v3 is provided', () => {
20
+ it('should return the same v3 model unchanged', () => {
21
+ const originalModel = new MockEmbeddingModelV3({
22
+ provider: 'test-provider',
23
+ modelId: 'test-model-id',
24
+ });
25
+
26
+ const result = asEmbeddingModelV3(originalModel);
27
+
28
+ expect(result).toBe(originalModel);
29
+ expect(result.specificationVersion).toBe('v3');
30
+ });
31
+
32
+ it('should not log any warning', () => {
33
+ const originalModel = new MockEmbeddingModelV3({
34
+ provider: 'test-provider',
35
+ modelId: 'test-model-id',
36
+ });
37
+
38
+ asEmbeddingModelV3(originalModel);
39
+
40
+ expect(logWarningSpy).not.toHaveBeenCalled();
41
+ });
42
+
43
+ it('should preserve all v3 model properties', () => {
44
+ const originalModel = new MockEmbeddingModelV3({
45
+ provider: 'test-provider-v3',
46
+ modelId: 'test-model-v3',
47
+ maxEmbeddingsPerCall: 10,
48
+ supportsParallelCalls: true,
49
+ });
50
+
51
+ const result = asEmbeddingModelV3(originalModel);
52
+
53
+ expect(result.provider).toBe('test-provider-v3');
54
+ expect(result.modelId).toBe('test-model-v3');
55
+ expect(result.maxEmbeddingsPerCall).toBe(10);
56
+ expect(result.supportsParallelCalls).toBe(true);
57
+ expect(result.specificationVersion).toBe('v3');
58
+ });
59
+ });
60
+
61
+ describe('when an embedding model v2 is provided', () => {
62
+ it('should convert v2 to v3 and change specificationVersion', () => {
63
+ const v2Model = new MockEmbeddingModelV2({
64
+ provider: 'test-provider',
65
+ modelId: 'test-model-id',
66
+ });
67
+
68
+ const result = asEmbeddingModelV3(v2Model);
69
+
70
+ expect(result.specificationVersion).toBe('v3');
71
+ expect(result).not.toBe(v2Model);
72
+ });
73
+
74
+ it('should log a compatibility warning', () => {
75
+ const v2Model = new MockEmbeddingModelV2({
76
+ provider: 'test-provider',
77
+ modelId: 'test-model-id',
78
+ });
79
+
80
+ asEmbeddingModelV3(v2Model);
81
+
82
+ expect(logWarningSpy).toHaveBeenCalledWith({
83
+ warnings: [
84
+ {
85
+ type: 'compatibility',
86
+ feature: 'specificationVersion',
87
+ details: expect.stringContaining(
88
+ 'Using v2 specification compatibility',
89
+ ),
90
+ },
91
+ ],
92
+ provider: 'test-provider',
93
+ model: 'test-model-id',
94
+ });
95
+ });
96
+
97
+ it('should preserve provider property', () => {
98
+ const v2Model = new MockEmbeddingModelV2({
99
+ provider: 'test-provider-v2',
100
+ modelId: 'test-model-id',
101
+ });
102
+
103
+ const result = asEmbeddingModelV3(v2Model);
104
+
105
+ expect(result.provider).toBe('test-provider-v2');
106
+ });
107
+
108
+ it('should preserve modelId property', () => {
109
+ const v2Model = new MockEmbeddingModelV2({
110
+ provider: 'test-provider',
111
+ modelId: 'test-model-v2',
112
+ });
113
+
114
+ const result = asEmbeddingModelV3(v2Model);
115
+
116
+ expect(result.modelId).toBe('test-model-v2');
117
+ });
118
+
119
+ it('should preserve maxEmbeddingsPerCall property', () => {
120
+ const v2Model = new MockEmbeddingModelV2({
121
+ provider: 'test-provider',
122
+ modelId: 'test-model-id',
123
+ maxEmbeddingsPerCall: 5,
124
+ });
125
+
126
+ const result = asEmbeddingModelV3(v2Model);
127
+
128
+ expect(result.maxEmbeddingsPerCall).toBe(5);
129
+ });
130
+
131
+ it('should preserve maxEmbeddingsPerCall as undefined', () => {
132
+ const v2Model = new MockEmbeddingModelV2({
133
+ provider: 'test-provider',
134
+ modelId: 'test-model-id',
135
+ maxEmbeddingsPerCall: null,
136
+ });
137
+
138
+ const result = asEmbeddingModelV3(v2Model);
139
+
140
+ expect(result.maxEmbeddingsPerCall).toBeUndefined();
141
+ });
142
+
143
+ it('should preserve supportsParallelCalls property', () => {
144
+ const v2Model = new MockEmbeddingModelV2({
145
+ provider: 'test-provider',
146
+ modelId: 'test-model-id',
147
+ supportsParallelCalls: true,
148
+ });
149
+
150
+ const result = asEmbeddingModelV3(v2Model);
151
+
152
+ expect(result.supportsParallelCalls).toBe(true);
153
+ });
154
+
155
+ it('should preserve supportsParallelCalls as promise', async () => {
156
+ const v2Model = new MockEmbeddingModelV2({
157
+ provider: 'test-provider',
158
+ modelId: 'test-model-id',
159
+ supportsParallelCalls: Promise.resolve(true),
160
+ });
161
+
162
+ const result = asEmbeddingModelV3(v2Model);
163
+
164
+ expect(await result.supportsParallelCalls).toBe(true);
165
+ });
166
+
167
+ it('should make doEmbed method callable', async () => {
168
+ const v2Model = new MockEmbeddingModelV2({
169
+ provider: 'test-provider',
170
+ modelId: 'test-model-id',
171
+ doEmbed: async () => ({
172
+ embeddings: [[0.1, 0.2, 0.3]],
173
+ }),
174
+ });
175
+
176
+ const result = asEmbeddingModelV3(v2Model);
177
+
178
+ const response = await result.doEmbed({
179
+ values: ['test text'],
180
+ });
181
+
182
+ expect(response.embeddings).toHaveLength(1);
183
+ expect(response.embeddings[0]).toEqual([0.1, 0.2, 0.3]);
184
+ });
185
+
186
+ it('should handle doEmbed with multiple embeddings', async () => {
187
+ const v2Model = new MockEmbeddingModelV2({
188
+ provider: 'test-provider',
189
+ modelId: 'test-model-id',
190
+ doEmbed: async () => ({
191
+ embeddings: [
192
+ [0.1, 0.2, 0.3],
193
+ [0.4, 0.5, 0.6],
194
+ ],
195
+ }),
196
+ });
197
+
198
+ const result = asEmbeddingModelV3(v2Model);
199
+
200
+ const response = await result.doEmbed({
201
+ values: ['text one', 'text two'],
202
+ });
203
+
204
+ expect(response.embeddings).toHaveLength(2);
205
+ expect(response.embeddings[0]).toEqual([0.1, 0.2, 0.3]);
206
+ expect(response.embeddings[1]).toEqual([0.4, 0.5, 0.6]);
207
+ });
208
+
209
+ it('should handle doEmbed with usage information', async () => {
210
+ const v2Model = new MockEmbeddingModelV2({
211
+ provider: 'test-provider',
212
+ modelId: 'test-model-id',
213
+ doEmbed: async () => ({
214
+ embeddings: [[0.1, 0.2, 0.3]],
215
+ usage: { tokens: 50 },
216
+ }),
217
+ });
218
+
219
+ const result = asEmbeddingModelV3(v2Model);
220
+
221
+ const response = await result.doEmbed({
222
+ values: ['test text'],
223
+ });
224
+
225
+ expect(response.usage?.tokens).toBe(50);
226
+ });
227
+
228
+ it('should handle doEmbed with provider metadata', async () => {
229
+ const v2Model = new MockEmbeddingModelV2<string>({
230
+ provider: 'test-provider',
231
+ modelId: 'test-model-id',
232
+ doEmbed: async () => ({
233
+ embeddings: [[0.1, 0.2, 0.3]],
234
+ providerMetadata: {
235
+ testProvider: { customField: 'value' },
236
+ },
237
+ }),
238
+ });
239
+
240
+ const result = asEmbeddingModelV3(v2Model);
241
+
242
+ const response = await result.doEmbed({
243
+ values: ['test text'],
244
+ });
245
+
246
+ expect(response.providerMetadata?.testProvider).toEqual({
247
+ customField: 'value',
248
+ });
249
+ });
250
+
251
+ it('should handle doEmbed with response headers', async () => {
252
+ const v2Model = new MockEmbeddingModelV2<string>({
253
+ provider: 'test-provider',
254
+ modelId: 'test-model-id',
255
+ doEmbed: async () => ({
256
+ embeddings: [[0.1, 0.2, 0.3]],
257
+ response: {
258
+ headers: { 'x-custom': 'header-value' },
259
+ },
260
+ }),
261
+ });
262
+
263
+ const result = asEmbeddingModelV3(v2Model);
264
+
265
+ const response = await result.doEmbed({
266
+ values: ['test text'],
267
+ });
268
+
269
+ expect(response.response?.headers).toEqual({
270
+ 'x-custom': 'header-value',
271
+ });
272
+ });
273
+
274
+ it('should handle doEmbed with response body', async () => {
275
+ const v2Model = new MockEmbeddingModelV2<string>({
276
+ provider: 'test-provider',
277
+ modelId: 'test-model-id',
278
+ doEmbed: async () => ({
279
+ embeddings: [[0.1, 0.2, 0.3]],
280
+ response: {
281
+ body: { raw: 'response data' },
282
+ },
283
+ }),
284
+ });
285
+
286
+ const result = asEmbeddingModelV3(v2Model);
287
+
288
+ const response = await result.doEmbed({
289
+ values: ['test text'],
290
+ });
291
+
292
+ expect(response.response?.body).toEqual({ raw: 'response data' });
293
+ });
294
+
295
+ it('should preserve prototype methods when using class instances', async () => {
296
+ class TestEmbeddingModelV2 implements EmbeddingModelV2<string> {
297
+ readonly specificationVersion = 'v2' as const;
298
+ readonly provider = 'test-provider';
299
+ readonly modelId = 'test-model-id';
300
+ readonly maxEmbeddingsPerCall = 1;
301
+ readonly supportsParallelCalls = false;
302
+
303
+ customMethod() {
304
+ return 'custom-value';
305
+ }
306
+
307
+ async doEmbed() {
308
+ return { embeddings: [[0.1, 0.2, 0.3]] };
309
+ }
310
+ }
311
+
312
+ const v2Model = new TestEmbeddingModelV2();
313
+ const result = asEmbeddingModelV3(v2Model) as any;
314
+
315
+ expect(result.customMethod()).toBe('custom-value');
316
+ expect(result.specificationVersion).toBe('v3');
317
+ });
318
+ });
319
+ });
@@ -0,0 +1,24 @@
1
+ import { EmbeddingModelV2, EmbeddingModelV3 } from '@ai-sdk/provider';
2
+ import { logV2CompatibilityWarning } from '../util/log-v2-compatibility-warning';
3
+
4
+ export function asEmbeddingModelV3(
5
+ model: EmbeddingModelV2<string> | EmbeddingModelV3,
6
+ ): EmbeddingModelV3 {
7
+ if (model.specificationVersion === 'v3') {
8
+ return model;
9
+ }
10
+
11
+ logV2CompatibilityWarning({
12
+ provider: model.provider,
13
+ modelId: model.modelId,
14
+ });
15
+
16
+ // TODO this could break, we need to properly map v2 to v3
17
+ // and support all relevant v3 properties:
18
+ return new Proxy(model, {
19
+ get(target, prop: keyof EmbeddingModelV2<string>) {
20
+ if (prop === 'specificationVersion') return 'v3';
21
+ return target[prop];
22
+ },
23
+ }) as unknown as EmbeddingModelV3;
24
+ }