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,79 @@
1
+ import type { LanguageModelV3StreamPart } from '@ai-sdk/provider';
2
+ import { LanguageModelMiddleware } from '../types';
3
+
4
+ /**
5
+ * Simulates streaming chunks with the response from a generate call.
6
+ */
7
+ export function simulateStreamingMiddleware(): LanguageModelMiddleware {
8
+ return {
9
+ specificationVersion: 'v3',
10
+ wrapStream: async ({ doGenerate }) => {
11
+ const result = await doGenerate();
12
+
13
+ let id = 0;
14
+
15
+ const simulatedStream = new ReadableStream<LanguageModelV3StreamPart>({
16
+ start(controller) {
17
+ controller.enqueue({
18
+ type: 'stream-start',
19
+ warnings: result.warnings,
20
+ });
21
+
22
+ controller.enqueue({ type: 'response-metadata', ...result.response });
23
+
24
+ for (const part of result.content) {
25
+ switch (part.type) {
26
+ case 'text': {
27
+ if (part.text.length > 0) {
28
+ controller.enqueue({ type: 'text-start', id: String(id) });
29
+ controller.enqueue({
30
+ type: 'text-delta',
31
+ id: String(id),
32
+ delta: part.text,
33
+ });
34
+ controller.enqueue({ type: 'text-end', id: String(id) });
35
+ id++;
36
+ }
37
+ break;
38
+ }
39
+ case 'reasoning': {
40
+ controller.enqueue({
41
+ type: 'reasoning-start',
42
+ id: String(id),
43
+ providerMetadata: part.providerMetadata,
44
+ });
45
+ controller.enqueue({
46
+ type: 'reasoning-delta',
47
+ id: String(id),
48
+ delta: part.text,
49
+ });
50
+ controller.enqueue({ type: 'reasoning-end', id: String(id) });
51
+ id++;
52
+ break;
53
+ }
54
+ default: {
55
+ controller.enqueue(part);
56
+ break;
57
+ }
58
+ }
59
+ }
60
+
61
+ controller.enqueue({
62
+ type: 'finish',
63
+ finishReason: result.finishReason,
64
+ usage: result.usage,
65
+ providerMetadata: result.providerMetadata,
66
+ });
67
+
68
+ controller.close();
69
+ },
70
+ });
71
+
72
+ return {
73
+ stream: simulatedStream,
74
+ request: result.request,
75
+ response: result.response,
76
+ };
77
+ },
78
+ };
79
+ }
@@ -0,0 +1,358 @@
1
+ import {
2
+ EmbeddingModelV3CallOptions,
3
+ EmbeddingModelV3Middleware,
4
+ } from '@ai-sdk/provider';
5
+ import { wrapEmbeddingModel } from '../middleware/wrap-embedding-model';
6
+ import { describe, it, expect, vi } from 'vitest';
7
+ import { MockEmbeddingModelV3 } from '../test/mock-embedding-model-v3';
8
+
9
+ describe('wrapEmbeddingModel', () => {
10
+ describe('model property', () => {
11
+ it('should pass through by default', () => {
12
+ const wrappedModel = wrapEmbeddingModel({
13
+ model: new MockEmbeddingModelV3({
14
+ modelId: 'test-model',
15
+ }),
16
+ middleware: {
17
+ specificationVersion: 'v3',
18
+ },
19
+ });
20
+
21
+ expect(wrappedModel.modelId).toBe('test-model');
22
+ });
23
+
24
+ it('should use middleware overrideModelId if provided', () => {
25
+ const wrappedModel = wrapEmbeddingModel({
26
+ model: new MockEmbeddingModelV3({
27
+ modelId: 'test-model',
28
+ }),
29
+ middleware: {
30
+ specificationVersion: 'v3',
31
+ overrideModelId: ({ model }) => 'override-model',
32
+ },
33
+ });
34
+
35
+ expect(wrappedModel.modelId).toBe('override-model');
36
+ });
37
+
38
+ it('should use modelId parameter if provided', () => {
39
+ const wrappedModel = wrapEmbeddingModel({
40
+ model: new MockEmbeddingModelV3({
41
+ modelId: 'test-model',
42
+ }),
43
+ middleware: {
44
+ specificationVersion: 'v3',
45
+ },
46
+ modelId: 'override-model',
47
+ });
48
+
49
+ expect(wrappedModel.modelId).toBe('override-model');
50
+ });
51
+ });
52
+
53
+ describe('provider property', () => {
54
+ it('should pass through by default', () => {
55
+ const wrappedModel = wrapEmbeddingModel({
56
+ model: new MockEmbeddingModelV3({
57
+ provider: 'test-provider',
58
+ }),
59
+ middleware: {
60
+ specificationVersion: 'v3',
61
+ },
62
+ });
63
+
64
+ expect(wrappedModel.provider).toBe('test-provider');
65
+ });
66
+
67
+ it('should use middleware overrideProvider if provided', () => {
68
+ const wrappedModel = wrapEmbeddingModel({
69
+ model: new MockEmbeddingModelV3({
70
+ provider: 'test-provider',
71
+ }),
72
+ middleware: {
73
+ specificationVersion: 'v3',
74
+ overrideProvider: ({ model }) => 'override-provider',
75
+ },
76
+ });
77
+
78
+ expect(wrappedModel.provider).toBe('override-provider');
79
+ });
80
+
81
+ it('should use providerId parameter if provided', () => {
82
+ const wrappedModel = wrapEmbeddingModel({
83
+ model: new MockEmbeddingModelV3({
84
+ provider: 'test-provider',
85
+ }),
86
+ middleware: {
87
+ specificationVersion: 'v3',
88
+ },
89
+ providerId: 'override-provider',
90
+ });
91
+
92
+ expect(wrappedModel.provider).toBe('override-provider');
93
+ });
94
+ });
95
+
96
+ describe('maxEmbeddingsPerCall property', () => {
97
+ it('should pass through by default', async () => {
98
+ const maxEmbeddingsPerCall = 2;
99
+
100
+ const wrappedModel = wrapEmbeddingModel({
101
+ model: new MockEmbeddingModelV3({ maxEmbeddingsPerCall }),
102
+ middleware: {
103
+ specificationVersion: 'v3',
104
+ },
105
+ });
106
+
107
+ expect(await wrappedModel.maxEmbeddingsPerCall).toStrictEqual(2);
108
+ });
109
+
110
+ it('should use middleware overrideSupportedUrls if provided', () => {
111
+ const wrappedModel = wrapEmbeddingModel({
112
+ model: new MockEmbeddingModelV3({
113
+ maxEmbeddingsPerCall: 2,
114
+ }),
115
+ middleware: {
116
+ specificationVersion: 'v3',
117
+ overrideMaxEmbeddingsPerCall: ({ model }) => 3,
118
+ },
119
+ });
120
+
121
+ expect(wrappedModel.maxEmbeddingsPerCall).toStrictEqual(3);
122
+ });
123
+ });
124
+
125
+ describe('supportsParallelCalls property', () => {
126
+ it('should pass through by default', async () => {
127
+ const supportsParallelCalls = true;
128
+
129
+ const wrappedModel = wrapEmbeddingModel({
130
+ model: new MockEmbeddingModelV3({ supportsParallelCalls }),
131
+ middleware: {
132
+ specificationVersion: 'v3',
133
+ },
134
+ });
135
+
136
+ expect(await wrappedModel.supportsParallelCalls).toStrictEqual(true);
137
+ });
138
+
139
+ it('should use middleware overrideSupportsParallelCalls if provided', () => {
140
+ const wrappedModel = wrapEmbeddingModel({
141
+ model: new MockEmbeddingModelV3({
142
+ supportsParallelCalls: false,
143
+ }),
144
+ middleware: {
145
+ specificationVersion: 'v3',
146
+ overrideSupportsParallelCalls: ({ model }) => true,
147
+ },
148
+ });
149
+
150
+ expect(wrappedModel.supportsParallelCalls).toStrictEqual(true);
151
+ });
152
+ });
153
+
154
+ it('should call transformParams middleware for doEmbed', async () => {
155
+ const mockModel = new MockEmbeddingModelV3({
156
+ doEmbed: [],
157
+ });
158
+
159
+ const transformParams = vi.fn().mockImplementation(({ params }) => ({
160
+ ...params,
161
+ transformed: true,
162
+ }));
163
+
164
+ const wrappedModel = wrapEmbeddingModel({
165
+ model: mockModel,
166
+ middleware: {
167
+ specificationVersion: 'v3',
168
+ transformParams,
169
+ },
170
+ });
171
+
172
+ const params: EmbeddingModelV3CallOptions = {
173
+ values: [
174
+ 'sunny day at the beach',
175
+ 'rainy afternoon in the city',
176
+ 'snowy night in the mountains',
177
+ ],
178
+ };
179
+
180
+ await wrappedModel.doEmbed(params);
181
+
182
+ expect(transformParams).toHaveBeenCalledWith({
183
+ params,
184
+ model: expect.any(Object),
185
+ });
186
+
187
+ expect(mockModel.doEmbedCalls[0]).toStrictEqual({
188
+ ...params,
189
+ transformed: true,
190
+ });
191
+ });
192
+
193
+ it('should call wrapEmbed middleware', async () => {
194
+ const mockModel = new MockEmbeddingModelV3({
195
+ doEmbed: vi.fn().mockResolvedValue('mock result'),
196
+ });
197
+
198
+ const wrapEmbed = vi.fn().mockImplementation(({ doEmbed }) => doEmbed());
199
+
200
+ const wrappedModel = wrapEmbeddingModel({
201
+ model: mockModel,
202
+ middleware: {
203
+ specificationVersion: 'v3',
204
+ wrapEmbed,
205
+ },
206
+ });
207
+
208
+ const params: EmbeddingModelV3CallOptions = {
209
+ values: [
210
+ 'sunny day at the beach',
211
+ 'rainy afternoon in the city',
212
+ 'snowy night in the mountains',
213
+ ],
214
+ };
215
+
216
+ await wrappedModel.doEmbed(params);
217
+
218
+ expect(wrapEmbed).toHaveBeenCalledWith({
219
+ doEmbed: expect.any(Function),
220
+ params,
221
+ model: mockModel,
222
+ });
223
+ });
224
+
225
+ describe('multiple middlewares', () => {
226
+ it('should call multiple transformParams middlewares in sequence for doEmbed', async () => {
227
+ const mockModel = new MockEmbeddingModelV3({
228
+ doEmbed: [],
229
+ });
230
+
231
+ const transformParams1 = vi.fn().mockImplementation(({ params }) => ({
232
+ ...params,
233
+ transformationStep1: true,
234
+ }));
235
+
236
+ const transformParams2 = vi.fn().mockImplementation(({ params }) => ({
237
+ ...params,
238
+ transformationStep2: true,
239
+ }));
240
+
241
+ const wrappedModel = wrapEmbeddingModel({
242
+ model: mockModel,
243
+ middleware: [
244
+ {
245
+ specificationVersion: 'v3',
246
+ transformParams: transformParams1,
247
+ },
248
+ {
249
+ specificationVersion: 'v3',
250
+ transformParams: transformParams2,
251
+ },
252
+ ],
253
+ });
254
+
255
+ const params: EmbeddingModelV3CallOptions = {
256
+ values: [
257
+ 'sunny day at the beach',
258
+ 'rainy afternoon in the city',
259
+ 'snowy night in the mountains',
260
+ ],
261
+ };
262
+
263
+ await wrappedModel.doEmbed(params);
264
+
265
+ expect(transformParams1).toHaveBeenCalledWith({
266
+ params,
267
+ model: expect.any(Object),
268
+ });
269
+
270
+ expect(transformParams2).toHaveBeenCalledWith({
271
+ params: { ...params, transformationStep1: true },
272
+ model: expect.any(Object),
273
+ });
274
+
275
+ expect(mockModel.doEmbedCalls[0]).toStrictEqual(
276
+ expect.objectContaining({
277
+ transformationStep1: true,
278
+ transformationStep2: true,
279
+ }),
280
+ );
281
+ });
282
+
283
+ it('should chain multiple wrapEmbed middlewares in the correct order', async () => {
284
+ const mockModel = new MockEmbeddingModelV3({
285
+ doEmbed: vi.fn().mockResolvedValue('final generate result'),
286
+ });
287
+
288
+ const wrapEmbed1 = vi
289
+ .fn()
290
+ .mockImplementation(async ({ doEmbed, params, model }) => {
291
+ const result = await doEmbed();
292
+ return `wrapEmbed1(${result})`;
293
+ });
294
+
295
+ const wrapEmbed2 = vi
296
+ .fn()
297
+ .mockImplementation(async ({ doEmbed, params, model }) => {
298
+ const result = await doEmbed();
299
+ return `wrapEmbed2(${result})`;
300
+ });
301
+
302
+ const wrappedModel = wrapEmbeddingModel({
303
+ model: mockModel,
304
+ middleware: [
305
+ {
306
+ specificationVersion: 'v3',
307
+ wrapEmbed: wrapEmbed1,
308
+ },
309
+ {
310
+ specificationVersion: 'v3',
311
+ wrapEmbed: wrapEmbed2,
312
+ },
313
+ ],
314
+ });
315
+
316
+ const params: EmbeddingModelV3CallOptions = {
317
+ values: [
318
+ 'sunny day at the beach',
319
+ 'rainy afternoon in the city',
320
+ 'snowy night in the mountains',
321
+ ],
322
+ };
323
+
324
+ const result = await wrappedModel.doEmbed(params);
325
+
326
+ // The middlewares should wrap in order, applying wrapEmbed2 last
327
+ expect(result).toBe('wrapEmbed1(wrapEmbed2(final generate result))');
328
+ expect(wrapEmbed1).toHaveBeenCalled();
329
+ expect(wrapEmbed2).toHaveBeenCalled();
330
+ });
331
+
332
+ it('should not mutate the middleware array argument', async () => {
333
+ const middleware1 = {
334
+ specificationVersion: 'v3',
335
+ wrapStream: vi.fn(),
336
+ };
337
+
338
+ const middleware2 = {
339
+ specificationVersion: 'v3',
340
+ wrapStream: vi.fn(),
341
+ };
342
+
343
+ const middlewares = [
344
+ middleware1,
345
+ middleware2,
346
+ ] as EmbeddingModelV3Middleware[];
347
+
348
+ wrapEmbeddingModel({
349
+ model: new MockEmbeddingModelV3(),
350
+ middleware: middlewares,
351
+ });
352
+
353
+ expect(middlewares.length).toBe(2);
354
+ expect(middlewares[0]).toBe(middleware1);
355
+ expect(middlewares[1]).toBe(middleware2);
356
+ });
357
+ });
358
+ });
@@ -0,0 +1,86 @@
1
+ import {
2
+ EmbeddingModelV3,
3
+ EmbeddingModelV3CallOptions,
4
+ } from '@ai-sdk/provider';
5
+ import { EmbeddingModelMiddleware } from '../types';
6
+ import { asArray } from '../util/as-array';
7
+
8
+ /**
9
+ * Wraps a EmbeddingModelV3 instance with middleware functionality.
10
+ * This function allows you to apply middleware to transform parameters,
11
+ * wrap embed operations of a language model.
12
+ *
13
+ * @param options - Configuration options for wrapping the embedding model.
14
+ * @param options.model - The original EmbeddingModelV3 instance to be wrapped.
15
+ * @param options.middleware - The middleware to be applied to the embedding model. When multiple middlewares are provided, the first middleware will transform the input first, and the last middleware will be wrapped directly around the model.
16
+ * @param options.modelId - Optional custom model ID to override the original model's ID.
17
+ * @param options.providerId - Optional custom provider ID to override the original model's provider ID.
18
+ * @returns A new EmbeddingModelV3 instance with middleware applied.
19
+ */
20
+ export const wrapEmbeddingModel = ({
21
+ model,
22
+ middleware: middlewareArg,
23
+ modelId,
24
+ providerId,
25
+ }: {
26
+ model: EmbeddingModelV3;
27
+ middleware: EmbeddingModelMiddleware | EmbeddingModelMiddleware[];
28
+ modelId?: string;
29
+ providerId?: string;
30
+ }): EmbeddingModelV3 => {
31
+ return [...asArray(middlewareArg)]
32
+ .reverse()
33
+ .reduce((wrappedModel, middleware) => {
34
+ return doWrap({ model: wrappedModel, middleware, modelId, providerId });
35
+ }, model);
36
+ };
37
+
38
+ const doWrap = ({
39
+ model,
40
+ middleware: {
41
+ transformParams,
42
+ wrapEmbed,
43
+ overrideProvider,
44
+ overrideModelId,
45
+ overrideMaxEmbeddingsPerCall,
46
+ overrideSupportsParallelCalls,
47
+ },
48
+ modelId,
49
+ providerId,
50
+ }: {
51
+ model: EmbeddingModelV3;
52
+ middleware: EmbeddingModelMiddleware;
53
+ modelId?: string;
54
+ providerId?: string;
55
+ }): EmbeddingModelV3 => {
56
+ async function doTransform({
57
+ params,
58
+ }: {
59
+ params: EmbeddingModelV3CallOptions;
60
+ }) {
61
+ return transformParams ? await transformParams({ params, model }) : params;
62
+ }
63
+
64
+ return {
65
+ specificationVersion: 'v3',
66
+ provider: providerId ?? overrideProvider?.({ model }) ?? model.provider,
67
+ modelId: modelId ?? overrideModelId?.({ model }) ?? model.modelId,
68
+ maxEmbeddingsPerCall:
69
+ overrideMaxEmbeddingsPerCall?.({ model }) ?? model.maxEmbeddingsPerCall,
70
+ supportsParallelCalls:
71
+ overrideSupportsParallelCalls?.({ model }) ?? model.supportsParallelCalls,
72
+ async doEmbed(
73
+ params: EmbeddingModelV3CallOptions,
74
+ ): Promise<Awaited<ReturnType<EmbeddingModelV3['doEmbed']>>> {
75
+ const transformedParams = await doTransform({ params });
76
+ const doEmbed = async () => model.doEmbed(transformedParams);
77
+ return wrapEmbed
78
+ ? wrapEmbed({
79
+ doEmbed,
80
+ params: transformedParams,
81
+ model,
82
+ })
83
+ : doEmbed();
84
+ },
85
+ };
86
+ };