@mastra/core 0.24.5 → 0.24.6

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 (277) hide show
  1. package/CHANGELOG.md +612 -0
  2. package/dist/agent/agent.d.ts +8 -6
  3. package/dist/agent/agent.d.ts.map +1 -1
  4. package/dist/agent/agent.types.d.ts +2 -0
  5. package/dist/agent/agent.types.d.ts.map +1 -1
  6. package/dist/agent/index.cjs +13 -13
  7. package/dist/agent/index.js +2 -2
  8. package/dist/agent/input-processor/index.cjs +6 -6
  9. package/dist/agent/input-processor/index.js +1 -1
  10. package/dist/agent/message-list/index.d.ts.map +1 -1
  11. package/dist/agent/message-list/prompt/attachments-to-parts.d.ts.map +1 -1
  12. package/dist/agent/test-utils.d.ts +4 -3
  13. package/dist/agent/test-utils.d.ts.map +1 -1
  14. package/dist/agent/utils.d.ts.map +1 -1
  15. package/dist/agent/workflows/prepare-stream/index.d.ts +4 -4
  16. package/dist/agent/workflows/prepare-stream/index.d.ts.map +1 -1
  17. package/dist/agent/workflows/prepare-stream/map-results-step.d.ts.map +1 -1
  18. package/dist/agent/workflows/prepare-stream/prepare-memory-step.d.ts +4 -4
  19. package/dist/agent/workflows/prepare-stream/schema.d.ts +4 -4
  20. package/dist/agent/workflows/prepare-stream/stream-step.d.ts +8 -1
  21. package/dist/agent/workflows/prepare-stream/stream-step.d.ts.map +1 -1
  22. package/dist/ai-tracing/index.cjs +36 -36
  23. package/dist/ai-tracing/index.js +1 -1
  24. package/dist/chunk-3PSWNGBF.js +3 -0
  25. package/dist/{chunk-ZV5CC35D.js.map → chunk-3PSWNGBF.js.map} +1 -1
  26. package/dist/{chunk-XHKMGOON.cjs → chunk-42RUESSD.cjs} +204 -150
  27. package/dist/chunk-42RUESSD.cjs.map +1 -0
  28. package/dist/{chunk-UD7DS7OY.cjs → chunk-46XGIEXM.cjs} +4 -4
  29. package/dist/{chunk-UD7DS7OY.cjs.map → chunk-46XGIEXM.cjs.map} +1 -1
  30. package/dist/{chunk-HGNRQ3OG.js → chunk-5O52O25J.js} +15 -8
  31. package/dist/chunk-5O52O25J.js.map +1 -0
  32. package/dist/{chunk-OLERJ2OU.js → chunk-6D2K2CAA.js} +7 -5
  33. package/dist/chunk-6D2K2CAA.js.map +1 -0
  34. package/dist/chunk-6XCINXZ7.cjs +194 -0
  35. package/dist/chunk-6XCINXZ7.cjs.map +1 -0
  36. package/dist/chunk-BJ6XIEC6.js +13 -0
  37. package/dist/chunk-BJ6XIEC6.js.map +1 -0
  38. package/dist/chunk-BWYU7D33.js +192 -0
  39. package/dist/chunk-BWYU7D33.js.map +1 -0
  40. package/dist/{chunk-R7UDZZA5.cjs → chunk-CT2DMHGC.cjs} +8 -8
  41. package/dist/{chunk-R7UDZZA5.cjs.map → chunk-CT2DMHGC.cjs.map} +1 -1
  42. package/dist/{chunk-YSQE5IHK.cjs → chunk-CYEQK4PM.cjs} +10 -8
  43. package/dist/chunk-CYEQK4PM.cjs.map +1 -0
  44. package/dist/{chunk-FCJ5INK7.js → chunk-DHLW4AP7.js} +3 -3
  45. package/dist/{chunk-FCJ5INK7.js.map → chunk-DHLW4AP7.js.map} +1 -1
  46. package/dist/{chunk-4UOIJRD6.cjs → chunk-GZDIHQDK.cjs} +4 -4
  47. package/dist/{chunk-4UOIJRD6.cjs.map → chunk-GZDIHQDK.cjs.map} +1 -1
  48. package/dist/{chunk-WCHE6FJ7.js → chunk-HCCXJ5YJ.js} +111 -6
  49. package/dist/chunk-HCCXJ5YJ.js.map +1 -0
  50. package/dist/{chunk-34ZCWSUA.js → chunk-HSX2K7HB.js} +15 -14
  51. package/dist/chunk-HSX2K7HB.js.map +1 -0
  52. package/dist/{chunk-LZFCR2SE.cjs → chunk-IAJHRFO4.cjs} +4 -4
  53. package/dist/{chunk-LZFCR2SE.cjs.map → chunk-IAJHRFO4.cjs.map} +1 -1
  54. package/dist/{chunk-4HQPVSGA.cjs → chunk-ICF3MCIN.cjs} +64 -12
  55. package/dist/chunk-ICF3MCIN.cjs.map +1 -0
  56. package/dist/{chunk-N2DOZAFH.js → chunk-INOOZ2A2.js} +760 -508
  57. package/dist/chunk-INOOZ2A2.js.map +1 -0
  58. package/dist/{chunk-3JX2Y3WH.cjs → chunk-IWU4YSYT.cjs} +16 -15
  59. package/dist/chunk-IWU4YSYT.cjs.map +1 -0
  60. package/dist/{chunk-3KVI2HLS.cjs → chunk-KWF3J2Q4.cjs} +11 -11
  61. package/dist/{chunk-3KVI2HLS.cjs.map → chunk-KWF3J2Q4.cjs.map} +1 -1
  62. package/dist/{chunk-TEW3ODXX.js → chunk-LAQQETGP.js} +36 -34
  63. package/dist/chunk-LAQQETGP.js.map +1 -0
  64. package/dist/{chunk-EUNOQ7HN.js → chunk-MRSBLBQ5.js} +4 -4
  65. package/dist/{chunk-EUNOQ7HN.js.map → chunk-MRSBLBQ5.js.map} +1 -1
  66. package/dist/{chunk-LLSLFDO6.js → chunk-NRQC7DQW.js} +57 -5
  67. package/dist/chunk-NRQC7DQW.js.map +1 -0
  68. package/dist/{chunk-WBAXXG34.cjs → chunk-PAOBGBU7.cjs} +112 -5
  69. package/dist/chunk-PAOBGBU7.cjs.map +1 -0
  70. package/dist/chunk-PE3V7GUL.cjs +4 -0
  71. package/dist/{chunk-LJFJTTZQ.cjs.map → chunk-PE3V7GUL.cjs.map} +1 -1
  72. package/dist/{chunk-DOLSYVNJ.cjs → chunk-PIH5FBNQ.cjs} +12 -12
  73. package/dist/{chunk-DOLSYVNJ.cjs.map → chunk-PIH5FBNQ.cjs.map} +1 -1
  74. package/dist/{chunk-4SXWN3RR.js → chunk-Q6LWNLAJ.js} +203 -149
  75. package/dist/chunk-Q6LWNLAJ.js.map +1 -0
  76. package/dist/{chunk-SL7VKAQ3.js → chunk-R6XC4DV5.js} +7 -7
  77. package/dist/chunk-R6XC4DV5.js.map +1 -0
  78. package/dist/{chunk-WNFLWMEP.cjs → chunk-RJOVFHWN.cjs} +765 -511
  79. package/dist/chunk-RJOVFHWN.cjs.map +1 -0
  80. package/dist/chunk-UCPGYU55.cjs +15 -0
  81. package/dist/chunk-UCPGYU55.cjs.map +1 -0
  82. package/dist/{chunk-K7MEUZ3O.js → chunk-UWTYVVVZ.js} +3 -3
  83. package/dist/{chunk-K7MEUZ3O.js.map → chunk-UWTYVVVZ.js.map} +1 -1
  84. package/dist/{chunk-ZISECZZO.js → chunk-VHEA3YXS.js} +2 -2
  85. package/dist/chunk-VHEA3YXS.js.map +1 -0
  86. package/dist/chunk-VXHOOZSK.js +446 -0
  87. package/dist/chunk-VXHOOZSK.js.map +1 -0
  88. package/dist/{chunk-NUAURT4I.cjs → chunk-W4UVO3HL.cjs} +2 -2
  89. package/dist/chunk-W4UVO3HL.cjs.map +1 -0
  90. package/dist/{chunk-ZIHEKHUB.js → chunk-WIMFJ2BA.js} +3 -3
  91. package/dist/{chunk-ZIHEKHUB.js.map → chunk-WIMFJ2BA.js.map} +1 -1
  92. package/dist/{chunk-LRSB62Z6.cjs → chunk-X7F4CSGR.cjs} +15 -8
  93. package/dist/chunk-X7F4CSGR.cjs.map +1 -0
  94. package/dist/{chunk-WUFFST2N.cjs → chunk-XDMQQZNX.cjs} +70 -68
  95. package/dist/chunk-XDMQQZNX.cjs.map +1 -0
  96. package/dist/chunk-XWGHD4C7.cjs +450 -0
  97. package/dist/chunk-XWGHD4C7.cjs.map +1 -0
  98. package/dist/{chunk-FZXAPBVV.js → chunk-Z6QCWTTO.js} +3 -3
  99. package/dist/{chunk-FZXAPBVV.js.map → chunk-Z6QCWTTO.js.map} +1 -1
  100. package/dist/{chunk-GWACPQ56.js → chunk-ZIWN73GQ.js} +5 -5
  101. package/dist/{chunk-GWACPQ56.js.map → chunk-ZIWN73GQ.js.map} +1 -1
  102. package/dist/{chunk-IJRERAWQ.cjs → chunk-ZOYE65RA.cjs} +8 -8
  103. package/dist/chunk-ZOYE65RA.cjs.map +1 -0
  104. package/dist/index.cjs +75 -54
  105. package/dist/index.cjs.map +1 -1
  106. package/dist/index.js +15 -10
  107. package/dist/index.js.map +1 -1
  108. package/dist/llm/index.cjs +24 -8
  109. package/dist/llm/index.d.ts +1 -0
  110. package/dist/llm/index.d.ts.map +1 -1
  111. package/dist/llm/index.js +5 -1
  112. package/dist/llm/model/gateways/base.d.ts +9 -4
  113. package/dist/llm/model/gateways/base.d.ts.map +1 -1
  114. package/dist/llm/model/gateways/index.d.ts +3 -1
  115. package/dist/llm/model/gateways/index.d.ts.map +1 -1
  116. package/dist/llm/model/gateways/models-dev.d.ts +3 -2
  117. package/dist/llm/model/gateways/models-dev.d.ts.map +1 -1
  118. package/dist/llm/model/gateways/netlify.d.ts +4 -3
  119. package/dist/llm/model/gateways/netlify.d.ts.map +1 -1
  120. package/dist/llm/model/model.d.ts.map +1 -1
  121. package/dist/llm/model/model.loop.d.ts +1 -1
  122. package/dist/llm/model/model.loop.d.ts.map +1 -1
  123. package/dist/llm/model/provider-registry.d.ts +11 -1
  124. package/dist/llm/model/provider-registry.d.ts.map +1 -1
  125. package/dist/llm/model/provider-types.generated.d.ts +324 -29
  126. package/dist/llm/model/registry-generator.d.ts +12 -0
  127. package/dist/llm/model/registry-generator.d.ts.map +1 -1
  128. package/dist/llm/model/resolve-model.d.ts.map +1 -1
  129. package/dist/llm/model/router.d.ts +6 -1
  130. package/dist/llm/model/router.d.ts.map +1 -1
  131. package/dist/loop/index.cjs +2 -2
  132. package/dist/loop/index.js +1 -1
  133. package/dist/loop/loop.d.ts.map +1 -1
  134. package/dist/loop/network/index.d.ts +6 -6
  135. package/dist/loop/network/index.d.ts.map +1 -1
  136. package/dist/loop/test-utils/generateText.d.ts.map +1 -1
  137. package/dist/loop/test-utils/resultObject.d.ts.map +1 -1
  138. package/dist/loop/test-utils/streamObject.d.ts.map +1 -1
  139. package/dist/loop/types.d.ts +8 -0
  140. package/dist/loop/types.d.ts.map +1 -1
  141. package/dist/loop/workflows/agentic-execution/index.d.ts +36 -36
  142. package/dist/loop/workflows/agentic-execution/index.d.ts.map +1 -1
  143. package/dist/loop/workflows/agentic-execution/llm-execution-step.d.ts +24 -24
  144. package/dist/loop/workflows/agentic-execution/llm-execution-step.d.ts.map +1 -1
  145. package/dist/loop/workflows/agentic-execution/llm-mapping-step.d.ts +12 -12
  146. package/dist/loop/workflows/agentic-execution/tool-call-step.d.ts +1 -1
  147. package/dist/loop/workflows/agentic-execution/tool-call-step.d.ts.map +1 -1
  148. package/dist/loop/workflows/agentic-loop/index.d.ts +36 -36
  149. package/dist/loop/workflows/schema.d.ts +16 -16
  150. package/dist/mastra/index.cjs +2 -2
  151. package/dist/mastra/index.d.ts +23 -0
  152. package/dist/mastra/index.d.ts.map +1 -1
  153. package/dist/mastra/index.js +1 -1
  154. package/dist/memory/index.cjs +4 -4
  155. package/dist/memory/index.js +1 -1
  156. package/dist/memory/types.d.ts +3 -2
  157. package/dist/memory/types.d.ts.map +1 -1
  158. package/dist/models-dev-LJ4O6FNF.js +3 -0
  159. package/dist/{models-dev-BL5TAKE6.js.map → models-dev-LJ4O6FNF.js.map} +1 -1
  160. package/dist/models-dev-T2CXOEDH.cjs +12 -0
  161. package/dist/{models-dev-HZ3LZHPX.cjs.map → models-dev-T2CXOEDH.cjs.map} +1 -1
  162. package/dist/netlify-BAEMIQNH.cjs +12 -0
  163. package/dist/{netlify-TX6V7SJJ.cjs.map → netlify-BAEMIQNH.cjs.map} +1 -1
  164. package/dist/netlify-L7AZ74PV.js +3 -0
  165. package/dist/{netlify-VJXBII33.js.map → netlify-L7AZ74PV.js.map} +1 -1
  166. package/dist/processors/index.cjs +11 -11
  167. package/dist/processors/index.js +1 -1
  168. package/dist/provider-registry-RUDYHG7J.cjs +40 -0
  169. package/dist/provider-registry-RUDYHG7J.cjs.map +1 -0
  170. package/dist/provider-registry-THITZUJ7.js +3 -0
  171. package/dist/provider-registry-THITZUJ7.js.map +1 -0
  172. package/dist/provider-registry.json +705 -68
  173. package/dist/{registry-generator-6WVOHM2L.cjs → registry-generator-DL42NMBM.cjs} +23 -6
  174. package/dist/registry-generator-DL42NMBM.cjs.map +1 -0
  175. package/dist/{registry-generator-DXRSYYYT.js → registry-generator-I6S4ARS6.js} +23 -7
  176. package/dist/registry-generator-I6S4ARS6.js.map +1 -0
  177. package/dist/relevance/index.cjs +4 -4
  178. package/dist/relevance/index.js +1 -1
  179. package/dist/scores/index.cjs +9 -9
  180. package/dist/scores/index.js +2 -2
  181. package/dist/scores/scoreTraces/index.cjs +8 -8
  182. package/dist/scores/scoreTraces/index.js +3 -3
  183. package/dist/server/composite-auth.d.ts +9 -0
  184. package/dist/server/composite-auth.d.ts.map +1 -0
  185. package/dist/server/index.cjs +83 -1
  186. package/dist/server/index.cjs.map +1 -1
  187. package/dist/server/index.d.ts +3 -0
  188. package/dist/server/index.d.ts.map +1 -1
  189. package/dist/server/index.js +82 -2
  190. package/dist/server/index.js.map +1 -1
  191. package/dist/server/simple-auth.d.ts +32 -0
  192. package/dist/server/simple-auth.d.ts.map +1 -0
  193. package/dist/storage/index.cjs +3 -3
  194. package/dist/storage/index.js +1 -1
  195. package/dist/stream/aisdk/v5/output.d.ts.map +1 -1
  196. package/dist/stream/base/output.d.ts.map +1 -1
  197. package/dist/stream/index.cjs +11 -11
  198. package/dist/stream/index.js +2 -2
  199. package/dist/stream/types.d.ts +7 -2
  200. package/dist/stream/types.d.ts.map +1 -1
  201. package/dist/test-utils/llm-mock.cjs +2 -2
  202. package/dist/test-utils/llm-mock.js +1 -1
  203. package/dist/tools/index.cjs +2 -2
  204. package/dist/tools/index.js +1 -1
  205. package/dist/tools/stream.d.ts +1 -0
  206. package/dist/tools/stream.d.ts.map +1 -1
  207. package/dist/utils.cjs +17 -17
  208. package/dist/utils.js +1 -1
  209. package/dist/vector/filter/index.cjs +7 -189
  210. package/dist/vector/filter/index.cjs.map +1 -1
  211. package/dist/vector/filter/index.js +1 -190
  212. package/dist/vector/filter/index.js.map +1 -1
  213. package/dist/vector/index.cjs +9 -4
  214. package/dist/vector/index.d.ts +1 -0
  215. package/dist/vector/index.d.ts.map +1 -1
  216. package/dist/vector/index.js +2 -1
  217. package/dist/vector/types.d.ts +86 -3
  218. package/dist/vector/types.d.ts.map +1 -1
  219. package/dist/vector/vector.d.ts +39 -2
  220. package/dist/vector/vector.d.ts.map +1 -1
  221. package/dist/voice/aisdk/index.d.ts +3 -0
  222. package/dist/voice/aisdk/index.d.ts.map +1 -0
  223. package/dist/voice/aisdk/speech.d.ts +23 -0
  224. package/dist/voice/aisdk/speech.d.ts.map +1 -0
  225. package/dist/voice/aisdk/transcription.d.ts +22 -0
  226. package/dist/voice/aisdk/transcription.d.ts.map +1 -0
  227. package/dist/voice/composite-voice.d.ts +3 -2
  228. package/dist/voice/composite-voice.d.ts.map +1 -1
  229. package/dist/voice/index.cjs +12 -4
  230. package/dist/voice/index.d.ts +1 -0
  231. package/dist/voice/index.d.ts.map +1 -1
  232. package/dist/voice/index.js +1 -1
  233. package/dist/workflows/evented/index.cjs +10 -10
  234. package/dist/workflows/evented/index.js +1 -1
  235. package/dist/workflows/index.cjs +14 -14
  236. package/dist/workflows/index.js +1 -1
  237. package/dist/workflows/legacy/index.cjs +22 -22
  238. package/dist/workflows/legacy/index.js +1 -1
  239. package/dist/workflows/legacy/machine.d.ts +1 -1
  240. package/dist/workflows/legacy/workflow-instance.d.ts +2 -2
  241. package/dist/workflows/utils.d.ts.map +1 -1
  242. package/dist/workflows/workflow.d.ts +2 -0
  243. package/dist/workflows/workflow.d.ts.map +1 -1
  244. package/package.json +7 -7
  245. package/src/llm/model/provider-types.generated.d.ts +324 -29
  246. package/dist/chunk-34ZCWSUA.js.map +0 -1
  247. package/dist/chunk-3JX2Y3WH.cjs.map +0 -1
  248. package/dist/chunk-4HQPVSGA.cjs.map +0 -1
  249. package/dist/chunk-4SXWN3RR.js.map +0 -1
  250. package/dist/chunk-HF3GZRFP.cjs +0 -9
  251. package/dist/chunk-HF3GZRFP.cjs.map +0 -1
  252. package/dist/chunk-HGNRQ3OG.js.map +0 -1
  253. package/dist/chunk-IJRERAWQ.cjs.map +0 -1
  254. package/dist/chunk-LJFJTTZQ.cjs +0 -4
  255. package/dist/chunk-LLSLFDO6.js.map +0 -1
  256. package/dist/chunk-LRSB62Z6.cjs.map +0 -1
  257. package/dist/chunk-N2DOZAFH.js.map +0 -1
  258. package/dist/chunk-NUAURT4I.cjs.map +0 -1
  259. package/dist/chunk-OLERJ2OU.js.map +0 -1
  260. package/dist/chunk-RKXWLG33.js +0 -7
  261. package/dist/chunk-RKXWLG33.js.map +0 -1
  262. package/dist/chunk-SL7VKAQ3.js.map +0 -1
  263. package/dist/chunk-TEW3ODXX.js.map +0 -1
  264. package/dist/chunk-WBAXXG34.cjs.map +0 -1
  265. package/dist/chunk-WCHE6FJ7.js.map +0 -1
  266. package/dist/chunk-WNFLWMEP.cjs.map +0 -1
  267. package/dist/chunk-WUFFST2N.cjs.map +0 -1
  268. package/dist/chunk-XHKMGOON.cjs.map +0 -1
  269. package/dist/chunk-YSQE5IHK.cjs.map +0 -1
  270. package/dist/chunk-ZISECZZO.js.map +0 -1
  271. package/dist/chunk-ZV5CC35D.js +0 -3
  272. package/dist/models-dev-BL5TAKE6.js +0 -3
  273. package/dist/models-dev-HZ3LZHPX.cjs +0 -12
  274. package/dist/netlify-TX6V7SJJ.cjs +0 -12
  275. package/dist/netlify-VJXBII33.js +0 -3
  276. package/dist/registry-generator-6WVOHM2L.cjs.map +0 -1
  277. package/dist/registry-generator-DXRSYYYT.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,617 @@
1
1
  # @mastra/core
2
2
 
3
+ ## 0.24.6
4
+
5
+ ### Patch Changes
6
+
7
+ - Fix base64 encoded images with threads - issue #10480 ([#10566](https://github.com/mastra-ai/mastra/pull/10566))
8
+
9
+ Fixed "Invalid URL" error when using base64 encoded images (without `data:` prefix) in agent calls with threads and resources. Raw base64 strings are now automatically converted to proper data URIs before being processed.
10
+
11
+ **Changes:**
12
+ - Updated `attachments-to-parts.ts` to detect and convert raw base64 strings to data URIs
13
+ - Fixed `MessageList` image processing to handle raw base64 in two locations:
14
+ - Image part conversion in `aiV4CoreMessageToV1PromptMessage`
15
+ - File part to experimental_attachments conversion in `mastraDBMessageToAIV4UIMessage`
16
+ - Added comprehensive tests for base64 images, data URIs, and HTTP URLs with threads
17
+
18
+ **Breaking Change:** None - this is a bug fix that maintains backward compatibility while adding support for raw base64 strings.
19
+
20
+ - SimpleAuth and improved CloudAuth ([#10569](https://github.com/mastra-ai/mastra/pull/10569))
21
+
22
+ - Fixed OpenAI schema compatibility when using `agent.generate()` or `agent.stream()` with `structuredOutput`. ([#10454](https://github.com/mastra-ai/mastra/pull/10454))
23
+
24
+ ## Changes
25
+ - **Automatic transformation**: Zod schemas are now automatically transformed for OpenAI strict mode compatibility when using OpenAI models (including reasoning models like o1, o3, o4)
26
+ - **Optional field handling**: `.optional()` fields are converted to `.nullable()` with a transform that converts `null` → `undefined`, preserving optional semantics while satisfying OpenAI's strict mode requirements
27
+ - **Preserves nullable fields**: Intentionally `.nullable()` fields remain unchanged
28
+ - **Deep transformation**: Handles `.optional()` fields at any nesting level (objects, arrays, unions, etc.)
29
+ - **JSON Schema objects**: Not transformed, only Zod schemas
30
+
31
+ ## Example
32
+
33
+ ```typescript
34
+ const agent = new Agent({
35
+ name: 'data-extractor',
36
+ model: { provider: 'openai', modelId: 'gpt-4o' },
37
+ instructions: 'Extract user information',
38
+ });
39
+
40
+ const schema = z.object({
41
+ name: z.string(),
42
+ age: z.number().optional(),
43
+ deletedAt: z.date().nullable(),
44
+ });
45
+
46
+ // Schema is automatically transformed for OpenAI compatibility
47
+ const result = await agent.generate('Extract: John, deleted yesterday', {
48
+ structuredOutput: { schema },
49
+ });
50
+
51
+ // Result: { name: 'John', age: undefined, deletedAt: null }
52
+ ```
53
+
54
+ - deleteVectors, deleteFilter when upserting, updateVector filter (#10244) ([#10526](https://github.com/mastra-ai/mastra/pull/10526))
55
+
56
+ - Fix generateTitle model type to accept AI SDK LanguageModelV2 ([#10567](https://github.com/mastra-ai/mastra/pull/10567))
57
+
58
+ Updated the `generateTitle.model` config option to accept `MastraModelConfig` instead of `MastraLanguageModel`. This allows users to pass raw AI SDK `LanguageModelV2` models (e.g., `anthropic.languageModel('claude-3-5-haiku-20241022')`) directly without type errors.
59
+
60
+ Previously, passing a standard `LanguageModelV2` would fail because `MastraLanguageModelV2` has different `doGenerate`/`doStream` return types. Now `MastraModelConfig` is used consistently across:
61
+ - `memory/types.ts` - `generateTitle.model` config
62
+ - `agent.ts` - `genTitle`, `generateTitleFromUserMessage`, `resolveTitleGenerationConfig`
63
+ - `agent-legacy.ts` - `AgentLegacyCapabilities` interface
64
+
65
+ - Fix message metadata not persisting when using simple message format. Previously, custom metadata passed in messages (e.g., `{role: 'user', content: 'text', metadata: {userId: '123'}}`) was not being saved to the database. This occurred because the CoreMessage conversion path didn't preserve metadata fields. ([#10571](https://github.com/mastra-ai/mastra/pull/10571))
66
+
67
+ Now metadata is properly preserved for all message input formats:
68
+ - Simple CoreMessage format: `{role, content, metadata}`
69
+ - Full UIMessage format: `{role, content, parts, metadata}`
70
+ - AI SDK v5 ModelMessage format with metadata
71
+
72
+ Fixes #8556
73
+
74
+ - feat: Composite auth implementation ([#10486](https://github.com/mastra-ai/mastra/pull/10486))
75
+
76
+ - Fix requireApproval property being ignored for tools passed via toolsets, clientTools, and memoryTools parameters. The requireApproval flag now correctly propagates through all tool conversion paths, ensuring tools requiring approval will properly request user approval before execution. ([#10562](https://github.com/mastra-ai/mastra/pull/10562))
77
+
78
+ - Fix Azure Foundry rate limit handling for -1 values ([#10411](https://github.com/mastra-ai/mastra/pull/10411))
79
+
80
+ - Fix model headers not being passed through gateway system ([#10564](https://github.com/mastra-ai/mastra/pull/10564))
81
+
82
+ Previously, custom headers specified in `MastraModelConfig` were not being passed through the gateway system to model providers. This affected:
83
+ - OpenRouter (preventing activity tracking with `HTTP-Referer` and `X-Title`)
84
+ - Custom providers using custom URLs (headers not passed to `createOpenAICompatible`)
85
+ - Custom gateway implementations (headers not available in `resolveLanguageModel`)
86
+
87
+ Now headers are correctly passed through the entire gateway system:
88
+ - Base `MastraModelGateway` interface updated to accept headers
89
+ - `ModelRouterLanguageModel` passes headers from config to all gateways
90
+ - OpenRouter receives headers for activity tracking
91
+ - Custom URL providers receive headers via `createOpenAICompatible`
92
+ - Custom gateways can access headers in their `resolveLanguageModel` implementation
93
+
94
+ Example usage:
95
+
96
+ ```typescript
97
+ // Works with OpenRouter
98
+ const agent = new Agent({
99
+ name: 'my-agent',
100
+ instructions: 'You are a helpful assistant.',
101
+ model: {
102
+ id: 'openrouter/anthropic/claude-3-5-sonnet',
103
+ headers: {
104
+ 'HTTP-Referer': 'https://myapp.com',
105
+ 'X-Title': 'My Application',
106
+ },
107
+ },
108
+ });
109
+
110
+ // Also works with custom providers
111
+ const customAgent = new Agent({
112
+ name: 'custom-agent',
113
+ instructions: 'You are a helpful assistant.',
114
+ model: {
115
+ id: 'custom-provider/model',
116
+ url: 'https://api.custom.com/v1',
117
+ apiKey: 'key',
118
+ headers: {
119
+ 'X-Custom-Header': 'custom-value',
120
+ },
121
+ },
122
+ });
123
+ ```
124
+
125
+ Fixes https://github.com/mastra-ai/mastra/issues/9760
126
+
127
+ - fix(agent): persist messages before tool suspension ([#10542](https://github.com/mastra-ai/mastra/pull/10542))
128
+
129
+ Fixes issues where thread and messages were not saved before suspension when tools require approval or call suspend() during execution. This caused conversation history to be lost if users refreshed during tool approval or suspension.
130
+
131
+ **Backend changes (@mastra/core):**
132
+ - Add assistant messages to messageList immediately after LLM execution
133
+ - Flush messages synchronously before suspension to persist state
134
+ - Create thread if it doesn't exist before flushing
135
+ - Add metadata helpers to persist and remove tool approval state
136
+ - Pass saveQueueManager and memory context through workflow for immediate persistence
137
+
138
+ **Frontend changes (@mastra/react):**
139
+ - Extract runId from pending approvals to enable resumption after refresh
140
+ - Convert `pendingToolApprovals` (DB format) to `requireApprovalMetadata` (runtime format)
141
+ - Handle both `dynamic-tool` and `tool-{NAME}` part types for approval state
142
+ - Change runId from hardcoded `agentId` to unique `uuid()`
143
+
144
+ **UI changes (@mastra/playground-ui):**
145
+ - Handle tool calls awaiting approval in message initialization
146
+ - Convert approval metadata format when loading initial messages
147
+
148
+ Fixes #9745, #9906
149
+
150
+ - Fix race condition in parallel tool stream writes ([#10481](https://github.com/mastra-ai/mastra/pull/10481))
151
+
152
+ Introduces a write queue to ToolStream to serialize access to the underlying stream, preventing writer locked errors
153
+
154
+ - Remove unneeded console warning when flushing messages and no threadId or saveQueueManager is found. ([#10542](https://github.com/mastra-ai/mastra/pull/10542))
155
+
156
+ - Fixes GPT-5 reasoning which was failing on subsequent tool calls with the error: ([#10489](https://github.com/mastra-ai/mastra/pull/10489))
157
+
158
+ ```
159
+ Item 'fc_xxx' of type 'function_call' was provided without its required 'reasoning' item: 'rs_xxx'
160
+ ```
161
+
162
+ - Add optional includeRawChunks parameter to agent execution options, ([#10459](https://github.com/mastra-ai/mastra/pull/10459))
163
+ allowing users to include raw chunks in stream output where supported
164
+ by the model provider.
165
+
166
+ - When `mastra dev` runs, multiple processes can write to `provider-registry.json` concurrently (auto-refresh, syncGateways, syncGlobalCacheToLocal). This causes file corruption where the end of the JSON appears twice, making it unparseable. ([#10529](https://github.com/mastra-ai/mastra/pull/10529))
167
+
168
+ The fix uses atomic writes via the write-to-temp-then-rename pattern. Instead of:
169
+
170
+ ```ts
171
+ fs.writeFileSync(filePath, content, 'utf-8');
172
+ ```
173
+
174
+ We now do:
175
+
176
+ ```ts
177
+ const tempPath = `${filePath}.${process.pid}.${Date.now()}.${randomSuffix}.tmp`;
178
+ fs.writeFileSync(tempPath, content, 'utf-8');
179
+ fs.renameSync(tempPath, filePath); // atomic on POSIX
180
+ ```
181
+
182
+ `fs.rename()` is atomic on POSIX systems when both paths are on the same filesystem, so concurrent writes will each complete fully rather than interleaving.
183
+
184
+ - Ensures that data chunks written via `writer.custom()` always bubble up directly to the top-level stream, even when nested in sub-agents. This allows tools to emit custom progress updates, metrics, and other data that can be consumed at any level of the agent hierarchy. ([#10523](https://github.com/mastra-ai/mastra/pull/10523))
185
+ - **Added bubbling logic in sub-agent execution**: When sub-agents execute, data chunks (chunks with type starting with `data-`) are detected and written via `writer.custom()` instead of `writer.write()`, ensuring they bubble up directly without being wrapped in `tool-output` chunks.
186
+ - **Added comprehensive tests**:
187
+ - Test for `writer.custom()` with direct tool execution
188
+ - Test for `writer.custom()` with sub-agent tools (nested execution)
189
+ - Test for mixed usage of `writer.write()` and `writer.custom()` in the same tool
190
+
191
+ When a sub-agent's tool uses `writer.custom()` to write data chunks, those chunks appear in the sub-agent's stream. The parent agent's execution logic now detects these chunks and uses `writer.custom()` to bubble them up directly, preserving their structure and making them accessible at the top level.
192
+
193
+ This ensures that:
194
+ - Data chunks from tools always appear directly in the stream (not wrapped)
195
+ - Data chunks bubble up correctly through nested agent hierarchies
196
+ - Regular chunks continue to be wrapped in `tool-output` as expected
197
+
198
+ - Adds ability to create custom `MastraModelGateway`'s that can be added to the `Mastra` class instance under the `gateways` property. Giving you typescript autocompletion in any model picker string. ([#10535](https://github.com/mastra-ai/mastra/pull/10535))
199
+
200
+ ```typescript
201
+ import { MastraModelGateway, type ProviderConfig } from '@mastra/core/llm';
202
+ import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
203
+ import type { LanguageModelV2 } from '@ai-sdk/provider';
204
+
205
+ class MyCustomGateway extends MastraModelGateway {
206
+ readonly id = 'custom';
207
+ readonly name = 'My Custom Gateway';
208
+
209
+ async fetchProviders(): Promise<Record<string, ProviderConfig>> {
210
+ return {
211
+ 'my-provider': {
212
+ name: 'My Provider',
213
+ models: ['model-1', 'model-2'],
214
+ apiKeyEnvVar: 'MY_API_KEY',
215
+ gateway: this.id,
216
+ },
217
+ };
218
+ }
219
+
220
+ buildUrl(modelId: string, envVars?: Record<string, string>): string {
221
+ return 'https://api.my-provider.com/v1';
222
+ }
223
+
224
+ async getApiKey(modelId: string): Promise<string> {
225
+ const apiKey = process.env.MY_API_KEY;
226
+ if (!apiKey) throw new Error('MY_API_KEY not set');
227
+ return apiKey;
228
+ }
229
+
230
+ async resolveLanguageModel({
231
+ modelId,
232
+ providerId,
233
+ apiKey,
234
+ }: {
235
+ modelId: string;
236
+ providerId: string;
237
+ apiKey: string;
238
+ }): Promise<LanguageModelV2> {
239
+ const baseURL = this.buildUrl(`${providerId}/${modelId}`);
240
+ return createOpenAICompatible({
241
+ name: providerId,
242
+ apiKey,
243
+ baseURL,
244
+ }).chatModel(modelId);
245
+ }
246
+ }
247
+
248
+ new Mastra({
249
+ gateways: {
250
+ myGateway: new MyCustomGateway(),
251
+ },
252
+ });
253
+ ```
254
+
255
+ - Support AI SDK voice models ([#10558](https://github.com/mastra-ai/mastra/pull/10558))
256
+
257
+ Mastra now supports AI SDK's transcription and speech models directly in `CompositeVoice`, enabling seamless integration with a wide range of voice providers through the AI SDK ecosystem. This allows you to use models from OpenAI, ElevenLabs, Groq, Deepgram, LMNT, Hume, and many more for both speech-to-text (transcription) and text-to-speech capabilities.
258
+
259
+ AI SDK models are automatically wrapped when passed to `CompositeVoice`, so you can mix and match AI SDK models with existing Mastra voice providers for maximum flexibility.
260
+
261
+ ## Usage Example
262
+
263
+ ```typescript
264
+ import { CompositeVoice } from '@mastra/core/voice';
265
+ import { openai } from '@ai-sdk/openai';
266
+ import { elevenlabs } from '@ai-sdk/elevenlabs';
267
+
268
+ // Use AI SDK models directly with CompositeVoice
269
+ const voice = new CompositeVoice({
270
+ input: openai.transcription('whisper-1'), // AI SDK transcription model
271
+ output: elevenlabs.speech('eleven_turbo_v2'), // AI SDK speech model
272
+ });
273
+
274
+ // Convert text to speech
275
+ const audioStream = await voice.speak('Hello from AI SDK!');
276
+
277
+ // Convert speech to text
278
+ const transcript = await voice.listen(audioStream);
279
+ console.log(transcript);
280
+ ```
281
+
282
+ Fixes #9947
283
+
284
+ - Fix network data step formatting in AI SDK stream transformation ([#10525](https://github.com/mastra-ai/mastra/pull/10525))
285
+
286
+ Previously, network execution steps were not being tracked correctly in the AI SDK stream transformation. Steps were being duplicated rather than updated, and critical metadata like step IDs, iterations, and task information was missing or incorrectly structured.
287
+
288
+ **Changes:**
289
+ - Enhanced step tracking in `AgentNetworkToAISDKTransformer` to properly maintain step state throughout execution lifecycle
290
+ - Steps are now identified by unique IDs and updated in place rather than creating duplicates
291
+ - Added proper iteration and task metadata to each step in the network execution flow
292
+ - Fixed agent, workflow, and tool execution events to correctly populate step data
293
+ - Updated network stream event types to include `networkId`, `workflowId`, and consistent `runId` tracking
294
+ - Added test coverage for network custom data chunks with comprehensive validation
295
+
296
+ This ensures the AI SDK correctly represents the full execution flow of agent networks with accurate step sequencing and metadata.
297
+
298
+ - Fix generating provider-registry.json ([#10535](https://github.com/mastra-ai/mastra/pull/10535))
299
+
300
+ - Fix message-list conversion issues when persisting messages before tool suspension: filter internal metadata fields (`__originalContent`) from UI messages, keep reasoning field empty for consistent cache keys during message deduplication, and only include providerMetadata on parts when defined. ([#10552](https://github.com/mastra-ai/mastra/pull/10552))
301
+
302
+ - Fix agent.generate() to use model's doGenerate method instead of doStream ([#10572](https://github.com/mastra-ai/mastra/pull/10572))
303
+
304
+ When calling `agent.generate()`, the model's `doGenerate` method is now correctly invoked instead of always using `doStream`. This aligns the non-streaming generation path with the intended behavior where providers can implement optimized non-streaming responses.
305
+
306
+ - Updated dependencies [[`33a607a`](https://github.com/mastra-ai/mastra/commit/33a607a1f716c2029d4a1ff1603dd756129a33b3)]:
307
+ - @mastra/schema-compat@0.11.8
308
+
309
+ ## 0.24.6-alpha.0
310
+
311
+ ### Patch Changes
312
+
313
+ - Fix base64 encoded images with threads - issue #10480 ([#10566](https://github.com/mastra-ai/mastra/pull/10566))
314
+
315
+ Fixed "Invalid URL" error when using base64 encoded images (without `data:` prefix) in agent calls with threads and resources. Raw base64 strings are now automatically converted to proper data URIs before being processed.
316
+
317
+ **Changes:**
318
+ - Updated `attachments-to-parts.ts` to detect and convert raw base64 strings to data URIs
319
+ - Fixed `MessageList` image processing to handle raw base64 in two locations:
320
+ - Image part conversion in `aiV4CoreMessageToV1PromptMessage`
321
+ - File part to experimental_attachments conversion in `mastraDBMessageToAIV4UIMessage`
322
+ - Added comprehensive tests for base64 images, data URIs, and HTTP URLs with threads
323
+
324
+ **Breaking Change:** None - this is a bug fix that maintains backward compatibility while adding support for raw base64 strings.
325
+
326
+ - SimpleAuth and improved CloudAuth ([#10569](https://github.com/mastra-ai/mastra/pull/10569))
327
+
328
+ - Fixed OpenAI schema compatibility when using `agent.generate()` or `agent.stream()` with `structuredOutput`. ([#10454](https://github.com/mastra-ai/mastra/pull/10454))
329
+
330
+ ## Changes
331
+ - **Automatic transformation**: Zod schemas are now automatically transformed for OpenAI strict mode compatibility when using OpenAI models (including reasoning models like o1, o3, o4)
332
+ - **Optional field handling**: `.optional()` fields are converted to `.nullable()` with a transform that converts `null` → `undefined`, preserving optional semantics while satisfying OpenAI's strict mode requirements
333
+ - **Preserves nullable fields**: Intentionally `.nullable()` fields remain unchanged
334
+ - **Deep transformation**: Handles `.optional()` fields at any nesting level (objects, arrays, unions, etc.)
335
+ - **JSON Schema objects**: Not transformed, only Zod schemas
336
+
337
+ ## Example
338
+
339
+ ```typescript
340
+ const agent = new Agent({
341
+ name: 'data-extractor',
342
+ model: { provider: 'openai', modelId: 'gpt-4o' },
343
+ instructions: 'Extract user information',
344
+ });
345
+
346
+ const schema = z.object({
347
+ name: z.string(),
348
+ age: z.number().optional(),
349
+ deletedAt: z.date().nullable(),
350
+ });
351
+
352
+ // Schema is automatically transformed for OpenAI compatibility
353
+ const result = await agent.generate('Extract: John, deleted yesterday', {
354
+ structuredOutput: { schema },
355
+ });
356
+
357
+ // Result: { name: 'John', age: undefined, deletedAt: null }
358
+ ```
359
+
360
+ - deleteVectors, deleteFilter when upserting, updateVector filter (#10244) ([#10526](https://github.com/mastra-ai/mastra/pull/10526))
361
+
362
+ - Fix generateTitle model type to accept AI SDK LanguageModelV2 ([#10567](https://github.com/mastra-ai/mastra/pull/10567))
363
+
364
+ Updated the `generateTitle.model` config option to accept `MastraModelConfig` instead of `MastraLanguageModel`. This allows users to pass raw AI SDK `LanguageModelV2` models (e.g., `anthropic.languageModel('claude-3-5-haiku-20241022')`) directly without type errors.
365
+
366
+ Previously, passing a standard `LanguageModelV2` would fail because `MastraLanguageModelV2` has different `doGenerate`/`doStream` return types. Now `MastraModelConfig` is used consistently across:
367
+ - `memory/types.ts` - `generateTitle.model` config
368
+ - `agent.ts` - `genTitle`, `generateTitleFromUserMessage`, `resolveTitleGenerationConfig`
369
+ - `agent-legacy.ts` - `AgentLegacyCapabilities` interface
370
+
371
+ - Fix message metadata not persisting when using simple message format. Previously, custom metadata passed in messages (e.g., `{role: 'user', content: 'text', metadata: {userId: '123'}}`) was not being saved to the database. This occurred because the CoreMessage conversion path didn't preserve metadata fields. ([#10571](https://github.com/mastra-ai/mastra/pull/10571))
372
+
373
+ Now metadata is properly preserved for all message input formats:
374
+ - Simple CoreMessage format: `{role, content, metadata}`
375
+ - Full UIMessage format: `{role, content, parts, metadata}`
376
+ - AI SDK v5 ModelMessage format with metadata
377
+
378
+ Fixes #8556
379
+
380
+ - feat: Composite auth implementation ([#10486](https://github.com/mastra-ai/mastra/pull/10486))
381
+
382
+ - Fix requireApproval property being ignored for tools passed via toolsets, clientTools, and memoryTools parameters. The requireApproval flag now correctly propagates through all tool conversion paths, ensuring tools requiring approval will properly request user approval before execution. ([#10562](https://github.com/mastra-ai/mastra/pull/10562))
383
+
384
+ - Fix Azure Foundry rate limit handling for -1 values ([#10411](https://github.com/mastra-ai/mastra/pull/10411))
385
+
386
+ - Fix model headers not being passed through gateway system ([#10564](https://github.com/mastra-ai/mastra/pull/10564))
387
+
388
+ Previously, custom headers specified in `MastraModelConfig` were not being passed through the gateway system to model providers. This affected:
389
+ - OpenRouter (preventing activity tracking with `HTTP-Referer` and `X-Title`)
390
+ - Custom providers using custom URLs (headers not passed to `createOpenAICompatible`)
391
+ - Custom gateway implementations (headers not available in `resolveLanguageModel`)
392
+
393
+ Now headers are correctly passed through the entire gateway system:
394
+ - Base `MastraModelGateway` interface updated to accept headers
395
+ - `ModelRouterLanguageModel` passes headers from config to all gateways
396
+ - OpenRouter receives headers for activity tracking
397
+ - Custom URL providers receive headers via `createOpenAICompatible`
398
+ - Custom gateways can access headers in their `resolveLanguageModel` implementation
399
+
400
+ Example usage:
401
+
402
+ ```typescript
403
+ // Works with OpenRouter
404
+ const agent = new Agent({
405
+ name: 'my-agent',
406
+ instructions: 'You are a helpful assistant.',
407
+ model: {
408
+ id: 'openrouter/anthropic/claude-3-5-sonnet',
409
+ headers: {
410
+ 'HTTP-Referer': 'https://myapp.com',
411
+ 'X-Title': 'My Application',
412
+ },
413
+ },
414
+ });
415
+
416
+ // Also works with custom providers
417
+ const customAgent = new Agent({
418
+ name: 'custom-agent',
419
+ instructions: 'You are a helpful assistant.',
420
+ model: {
421
+ id: 'custom-provider/model',
422
+ url: 'https://api.custom.com/v1',
423
+ apiKey: 'key',
424
+ headers: {
425
+ 'X-Custom-Header': 'custom-value',
426
+ },
427
+ },
428
+ });
429
+ ```
430
+
431
+ Fixes https://github.com/mastra-ai/mastra/issues/9760
432
+
433
+ - fix(agent): persist messages before tool suspension ([#10542](https://github.com/mastra-ai/mastra/pull/10542))
434
+
435
+ Fixes issues where thread and messages were not saved before suspension when tools require approval or call suspend() during execution. This caused conversation history to be lost if users refreshed during tool approval or suspension.
436
+
437
+ **Backend changes (@mastra/core):**
438
+ - Add assistant messages to messageList immediately after LLM execution
439
+ - Flush messages synchronously before suspension to persist state
440
+ - Create thread if it doesn't exist before flushing
441
+ - Add metadata helpers to persist and remove tool approval state
442
+ - Pass saveQueueManager and memory context through workflow for immediate persistence
443
+
444
+ **Frontend changes (@mastra/react):**
445
+ - Extract runId from pending approvals to enable resumption after refresh
446
+ - Convert `pendingToolApprovals` (DB format) to `requireApprovalMetadata` (runtime format)
447
+ - Handle both `dynamic-tool` and `tool-{NAME}` part types for approval state
448
+ - Change runId from hardcoded `agentId` to unique `uuid()`
449
+
450
+ **UI changes (@mastra/playground-ui):**
451
+ - Handle tool calls awaiting approval in message initialization
452
+ - Convert approval metadata format when loading initial messages
453
+
454
+ Fixes #9745, #9906
455
+
456
+ - Fix race condition in parallel tool stream writes ([#10481](https://github.com/mastra-ai/mastra/pull/10481))
457
+
458
+ Introduces a write queue to ToolStream to serialize access to the underlying stream, preventing writer locked errors
459
+
460
+ - Remove unneeded console warning when flushing messages and no threadId or saveQueueManager is found. ([#10542](https://github.com/mastra-ai/mastra/pull/10542))
461
+
462
+ - Fixes GPT-5 reasoning which was failing on subsequent tool calls with the error: ([#10489](https://github.com/mastra-ai/mastra/pull/10489))
463
+
464
+ ```
465
+ Item 'fc_xxx' of type 'function_call' was provided without its required 'reasoning' item: 'rs_xxx'
466
+ ```
467
+
468
+ - Add optional includeRawChunks parameter to agent execution options, ([#10459](https://github.com/mastra-ai/mastra/pull/10459))
469
+ allowing users to include raw chunks in stream output where supported
470
+ by the model provider.
471
+
472
+ - When `mastra dev` runs, multiple processes can write to `provider-registry.json` concurrently (auto-refresh, syncGateways, syncGlobalCacheToLocal). This causes file corruption where the end of the JSON appears twice, making it unparseable. ([#10529](https://github.com/mastra-ai/mastra/pull/10529))
473
+
474
+ The fix uses atomic writes via the write-to-temp-then-rename pattern. Instead of:
475
+
476
+ ```ts
477
+ fs.writeFileSync(filePath, content, 'utf-8');
478
+ ```
479
+
480
+ We now do:
481
+
482
+ ```ts
483
+ const tempPath = `${filePath}.${process.pid}.${Date.now()}.${randomSuffix}.tmp`;
484
+ fs.writeFileSync(tempPath, content, 'utf-8');
485
+ fs.renameSync(tempPath, filePath); // atomic on POSIX
486
+ ```
487
+
488
+ `fs.rename()` is atomic on POSIX systems when both paths are on the same filesystem, so concurrent writes will each complete fully rather than interleaving.
489
+
490
+ - Ensures that data chunks written via `writer.custom()` always bubble up directly to the top-level stream, even when nested in sub-agents. This allows tools to emit custom progress updates, metrics, and other data that can be consumed at any level of the agent hierarchy. ([#10523](https://github.com/mastra-ai/mastra/pull/10523))
491
+ - **Added bubbling logic in sub-agent execution**: When sub-agents execute, data chunks (chunks with type starting with `data-`) are detected and written via `writer.custom()` instead of `writer.write()`, ensuring they bubble up directly without being wrapped in `tool-output` chunks.
492
+ - **Added comprehensive tests**:
493
+ - Test for `writer.custom()` with direct tool execution
494
+ - Test for `writer.custom()` with sub-agent tools (nested execution)
495
+ - Test for mixed usage of `writer.write()` and `writer.custom()` in the same tool
496
+
497
+ When a sub-agent's tool uses `writer.custom()` to write data chunks, those chunks appear in the sub-agent's stream. The parent agent's execution logic now detects these chunks and uses `writer.custom()` to bubble them up directly, preserving their structure and making them accessible at the top level.
498
+
499
+ This ensures that:
500
+ - Data chunks from tools always appear directly in the stream (not wrapped)
501
+ - Data chunks bubble up correctly through nested agent hierarchies
502
+ - Regular chunks continue to be wrapped in `tool-output` as expected
503
+
504
+ - Adds ability to create custom `MastraModelGateway`'s that can be added to the `Mastra` class instance under the `gateways` property. Giving you typescript autocompletion in any model picker string. ([#10535](https://github.com/mastra-ai/mastra/pull/10535))
505
+
506
+ ```typescript
507
+ import { MastraModelGateway, type ProviderConfig } from '@mastra/core/llm';
508
+ import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
509
+ import type { LanguageModelV2 } from '@ai-sdk/provider';
510
+
511
+ class MyCustomGateway extends MastraModelGateway {
512
+ readonly id = 'custom';
513
+ readonly name = 'My Custom Gateway';
514
+
515
+ async fetchProviders(): Promise<Record<string, ProviderConfig>> {
516
+ return {
517
+ 'my-provider': {
518
+ name: 'My Provider',
519
+ models: ['model-1', 'model-2'],
520
+ apiKeyEnvVar: 'MY_API_KEY',
521
+ gateway: this.id,
522
+ },
523
+ };
524
+ }
525
+
526
+ buildUrl(modelId: string, envVars?: Record<string, string>): string {
527
+ return 'https://api.my-provider.com/v1';
528
+ }
529
+
530
+ async getApiKey(modelId: string): Promise<string> {
531
+ const apiKey = process.env.MY_API_KEY;
532
+ if (!apiKey) throw new Error('MY_API_KEY not set');
533
+ return apiKey;
534
+ }
535
+
536
+ async resolveLanguageModel({
537
+ modelId,
538
+ providerId,
539
+ apiKey,
540
+ }: {
541
+ modelId: string;
542
+ providerId: string;
543
+ apiKey: string;
544
+ }): Promise<LanguageModelV2> {
545
+ const baseURL = this.buildUrl(`${providerId}/${modelId}`);
546
+ return createOpenAICompatible({
547
+ name: providerId,
548
+ apiKey,
549
+ baseURL,
550
+ }).chatModel(modelId);
551
+ }
552
+ }
553
+
554
+ new Mastra({
555
+ gateways: {
556
+ myGateway: new MyCustomGateway(),
557
+ },
558
+ });
559
+ ```
560
+
561
+ - Support AI SDK voice models ([#10558](https://github.com/mastra-ai/mastra/pull/10558))
562
+
563
+ Mastra now supports AI SDK's transcription and speech models directly in `CompositeVoice`, enabling seamless integration with a wide range of voice providers through the AI SDK ecosystem. This allows you to use models from OpenAI, ElevenLabs, Groq, Deepgram, LMNT, Hume, and many more for both speech-to-text (transcription) and text-to-speech capabilities.
564
+
565
+ AI SDK models are automatically wrapped when passed to `CompositeVoice`, so you can mix and match AI SDK models with existing Mastra voice providers for maximum flexibility.
566
+
567
+ ## Usage Example
568
+
569
+ ```typescript
570
+ import { CompositeVoice } from '@mastra/core/voice';
571
+ import { openai } from '@ai-sdk/openai';
572
+ import { elevenlabs } from '@ai-sdk/elevenlabs';
573
+
574
+ // Use AI SDK models directly with CompositeVoice
575
+ const voice = new CompositeVoice({
576
+ input: openai.transcription('whisper-1'), // AI SDK transcription model
577
+ output: elevenlabs.speech('eleven_turbo_v2'), // AI SDK speech model
578
+ });
579
+
580
+ // Convert text to speech
581
+ const audioStream = await voice.speak('Hello from AI SDK!');
582
+
583
+ // Convert speech to text
584
+ const transcript = await voice.listen(audioStream);
585
+ console.log(transcript);
586
+ ```
587
+
588
+ Fixes #9947
589
+
590
+ - Fix network data step formatting in AI SDK stream transformation ([#10525](https://github.com/mastra-ai/mastra/pull/10525))
591
+
592
+ Previously, network execution steps were not being tracked correctly in the AI SDK stream transformation. Steps were being duplicated rather than updated, and critical metadata like step IDs, iterations, and task information was missing or incorrectly structured.
593
+
594
+ **Changes:**
595
+ - Enhanced step tracking in `AgentNetworkToAISDKTransformer` to properly maintain step state throughout execution lifecycle
596
+ - Steps are now identified by unique IDs and updated in place rather than creating duplicates
597
+ - Added proper iteration and task metadata to each step in the network execution flow
598
+ - Fixed agent, workflow, and tool execution events to correctly populate step data
599
+ - Updated network stream event types to include `networkId`, `workflowId`, and consistent `runId` tracking
600
+ - Added test coverage for network custom data chunks with comprehensive validation
601
+
602
+ This ensures the AI SDK correctly represents the full execution flow of agent networks with accurate step sequencing and metadata.
603
+
604
+ - Fix generating provider-registry.json ([#10535](https://github.com/mastra-ai/mastra/pull/10535))
605
+
606
+ - Fix message-list conversion issues when persisting messages before tool suspension: filter internal metadata fields (`__originalContent`) from UI messages, keep reasoning field empty for consistent cache keys during message deduplication, and only include providerMetadata on parts when defined. ([#10552](https://github.com/mastra-ai/mastra/pull/10552))
607
+
608
+ - Fix agent.generate() to use model's doGenerate method instead of doStream ([#10572](https://github.com/mastra-ai/mastra/pull/10572))
609
+
610
+ When calling `agent.generate()`, the model's `doGenerate` method is now correctly invoked instead of always using `doStream`. This aligns the non-streaming generation path with the intended behavior where providers can implement optimized non-streaming responses.
611
+
612
+ - Updated dependencies [[`33a607a`](https://github.com/mastra-ai/mastra/commit/33a607a1f716c2029d4a1ff1603dd756129a33b3)]:
613
+ - @mastra/schema-compat@0.11.8-alpha.0
614
+
3
615
  ## 0.24.5
4
616
 
5
617
  ### Patch Changes
@@ -32,7 +32,7 @@ import type { AgentExecutionOptions, DeprecatedOutputOptions, MultiPrimitiveExec
32
32
  import { MessageList } from './message-list/index.js';
33
33
  import type { MessageInput, MessageListInput, UIMessageWithMetadata } from './message-list/index.js';
34
34
  import { SaveQueueManager } from './save-queue/index.js';
35
- import type { AgentConfig, AgentGenerateOptions, AgentStreamOptions, ToolsetsInput, ToolsInput, AgentModelManagerConfig, AgentInstructions } from './types.js';
35
+ import type { AgentConfig, AgentGenerateOptions, AgentStreamOptions, ToolsetsInput, ToolsInput, AgentModelManagerConfig, AgentInstructions, AgentMethodType } from './types.js';
36
36
  export type MastraLLM = MastraLLMV1 | MastraLLMVNext;
37
37
  type ModelFallbacks = {
38
38
  id: string;
@@ -355,11 +355,11 @@ export declare class Agent<TAgentId extends string = string, TTools extends Tool
355
355
  message: string | MessageInput;
356
356
  runtimeContext?: RuntimeContext;
357
357
  tracingContext: TracingContext;
358
- model?: DynamicArgument<MastraLanguageModel>;
358
+ model?: DynamicArgument<MastraModelConfig>;
359
359
  instructions?: DynamicArgument<string>;
360
360
  }): Promise<string>;
361
361
  getMostRecentUserMessage(messages: Array<UIMessage | UIMessageWithMetadata>): UIMessage | UIMessageWithMetadata | undefined;
362
- genTitle(userMessage: string | MessageInput | undefined, runtimeContext: RuntimeContext, tracingContext: TracingContext, model?: DynamicArgument<MastraLanguageModel>, instructions?: DynamicArgument<string>): Promise<string | undefined>;
362
+ genTitle(userMessage: string | MessageInput | undefined, runtimeContext: RuntimeContext, tracingContext: TracingContext, model?: DynamicArgument<MastraModelConfig>, instructions?: DynamicArgument<string>): Promise<string | undefined>;
363
363
  __setMemory(memory: DynamicArgument<MastraMemory>): void;
364
364
  fetchMemory({ threadId, thread: passedThread, memoryConfig, resourceId, runId, userMessages, systemMessage, messageList, runtimeContext, }: {
365
365
  resourceId: string;
@@ -550,7 +550,9 @@ export declare class Agent<TAgentId extends string = string, TTools extends Tool
550
550
  * @deprecated `streamVNext()` has been renamed to `stream()`. Please use `stream()` instead.
551
551
  */
552
552
  streamVNext<OUTPUT extends OutputSchema = undefined, FORMAT extends 'mastra' | 'aisdk' | undefined = undefined>(_messages: MessageListInput, _streamOptions?: AgentExecutionOptions<OUTPUT, FORMAT>): Promise<FORMAT extends 'aisdk' ? AISDKV5OutputStream<OUTPUT> : MastraModelOutput<OUTPUT>>;
553
- stream<OUTPUT extends OutputSchema = undefined, FORMAT extends 'mastra' | 'aisdk' | undefined = undefined>(messages: MessageListInput, streamOptions?: AgentExecutionOptions<OUTPUT, FORMAT> & DeprecatedOutputOptions<OUTPUT>): Promise<FORMAT extends 'aisdk' ? AISDKV5OutputStream<OUTPUT> : MastraModelOutput<OUTPUT>>;
553
+ stream<OUTPUT extends OutputSchema = undefined, FORMAT extends 'mastra' | 'aisdk' | undefined = undefined>(messages: MessageListInput, streamOptions?: AgentExecutionOptions<OUTPUT, FORMAT> & DeprecatedOutputOptions<OUTPUT> & {
554
+ methodType?: AgentMethodType;
555
+ }): Promise<FORMAT extends 'aisdk' ? AISDKV5OutputStream<OUTPUT> : MastraModelOutput<OUTPUT>>;
554
556
  /**
555
557
  * Resumes a previously suspended VNext stream execution.
556
558
  * Used to continue execution after a suspension point (e.g., tool approval, workflow suspend).
@@ -709,11 +711,11 @@ export declare class Agent<TAgentId extends string = string, TTools extends Tool
709
711
  * @internal
710
712
  */
711
713
  resolveTitleGenerationConfig(generateTitleConfig: boolean | {
712
- model: DynamicArgument<MastraLanguageModel>;
714
+ model: DynamicArgument<MastraModelConfig>;
713
715
  instructions?: DynamicArgument<string>;
714
716
  } | undefined): {
715
717
  shouldGenerate: boolean;
716
- model?: DynamicArgument<MastraLanguageModel>;
718
+ model?: DynamicArgument<MastraModelConfig>;
717
719
  instructions?: DynamicArgument<string>;
718
720
  };
719
721
  /**