1- import { createUIMessageStream } from "ai" ;
1+ import {
2+ createUIMessageStream ,
3+ createUIMessageStreamResponse ,
4+ } from "ai" ;
25import { toAISdkFormat } from "@mastra/ai-sdk" ;
3- import type { ChunkType , MastraModelOutput } from "@mastra/core/stream" ;
4-
5- const response = await agent . stream ( { messages : "Tell me a story" } ) ;
6-
7- const chunkStream : ReadableStream < ChunkType > = new ReadableStream < ChunkType > ( {
8- start ( controller ) {
9- response
10- . processDataStream ( {
11- onChunk : async ( chunk ) => controller . enqueue ( chunk as ChunkType ) ,
12- } )
13- . finally ( ( ) => controller . close ( ) ) ;
14- } ,
15- } ) ;
16-
17- const uiMessageStream = createUIMessageStream ( {
18- execute : async ( { writer } ) => {
19- for await ( const part of toAISdkFormat (
20- chunkStream as unknown as MastraModelOutput ,
21- { from : "agent" } ,
22- ) ) {
23- writer . write ( part ) ;
6+ import type { MastraModelOutput } from "@mastra/core/stream" ;
7+
8+ export interface StreamToAISdkOptions {
9+ agentId : string ;
10+ messages : string | Array < { role : string ; content : string } > ;
11+ threadId ?: string ;
12+ resourceId ?: string ;
13+ }
14+
15+ export interface AgentStreamOptions {
16+ format ?: "aisdk" | "mastra" ;
17+ threadId ?: string ;
18+ resourceId ?: string ;
19+ memory ?: {
20+ thread ?: string | { id : string ; resourceId ?: string } ;
21+ resource ?: string ;
22+ options ?: {
23+ lastMessages ?: number ;
24+ semanticRecall ?: boolean ;
25+ workingMemory ?: { enabled ?: boolean } ;
26+ } ;
27+ } ;
28+ maxSteps ?: number ;
29+ }
30+
31+ type MastraAgent = {
32+ stream : (
33+ messages : unknown ,
34+ options ?: {
35+ format ?: string ;
36+ threadId ?: string ;
37+ resourceId ?: string ;
38+ memory ?: AgentStreamOptions [ "memory" ] ;
39+ maxSteps ?: number ;
2440 }
25- } ,
26- } ) ;
41+ ) => Promise < MastraModelOutput & { toUIMessageStreamResponse ?: ( ) => Response } > ;
42+ } ;
43+
44+ type MastraInstance = {
45+ getAgent : ( id : string ) => MastraAgent ;
46+ } & Record < string , any > ;
47+
48+ /**
49+ * Creates a streaming Response for Next.js API routes using server-side Mastra agent.
50+ *
51+ * IMPORTANT: This should be used in API routes with the SERVER-SIDE mastra instance,
52+ * not the client SDK. The client SDK (MastraClient) is for frontend use only.
53+ *
54+ * @example
55+ * ```ts
56+ * // app/api/chat/route.ts
57+ * import { mastra } from "@/src/mastra";
58+ * import { createAgentStreamResponse } from "@/lib/client-stream-to-ai-sdk";
59+ *
60+ * export async function POST(req: Request) {
61+ * const { messages, agentId, threadId, resourceId, memory } = await req.json();
62+ * return createAgentStreamResponse(mastra, agentId, messages, {
63+ * threadId,
64+ * resourceId,
65+ * memory,
66+ * });
67+ * }
68+ * ```
69+ *
70+ * @see https://mastra.ai/docs/frameworks/agentic-uis/ai-sdk
71+ */
72+ export async function createAgentStreamResponse (
73+ mastra : MastraInstance ,
74+ agentId : string ,
75+ messages : unknown ,
76+ options ?: AgentStreamOptions
77+ ) : Promise < Response > {
78+ const agent = mastra . getAgent ( agentId ) ;
79+
80+ const streamOptions = {
81+ format : options ?. format ?? "aisdk" ,
82+ threadId : options ?. threadId ,
83+ resourceId : options ?. resourceId ,
84+ memory : options ?. memory ,
85+ maxSteps : options ?. maxSteps ,
86+ } ;
87+
88+ // Preferred: Use built-in AI SDK format
89+ if ( streamOptions . format === "aisdk" ) {
90+ const stream = await agent . stream ( messages , streamOptions ) ;
91+ if ( stream . toUIMessageStreamResponse ) {
92+ return stream . toUIMessageStreamResponse ( ) ;
93+ }
94+ }
95+
96+ // Fallback: Manual transformation with toAISdkFormat
97+ const stream = await agent . stream ( messages , {
98+ threadId : options ?. threadId ,
99+ resourceId : options ?. resourceId ,
100+ memory : options ?. memory ,
101+ maxSteps : options ?. maxSteps ,
102+ } ) ;
103+
104+ const uiMessageStream = createUIMessageStream ( {
105+ execute : async ( { writer } ) => {
106+ const aiSdkStream = toAISdkFormat ( stream , { from : "agent" } ) ;
107+ const reader = aiSdkStream . getReader ( ) ;
108+ try {
109+ while ( true ) {
110+ const { done, value } = await reader . read ( ) ;
111+ if ( done ) break ;
112+ writer . write ( value ) ;
113+ }
114+ } finally {
115+ reader . releaseLock ( ) ;
116+ }
117+ } ,
118+ } ) ;
119+
120+ return createUIMessageStreamResponse ( { stream : uiMessageStream } ) ;
121+ }
27122
28- for await ( const part of uiMessageStream ) {
29- console . log ( part ) ;
123+ /**
124+ * @deprecated Use createAgentStreamResponse with server-side mastra instance instead.
125+ * This export exists for backward compatibility only.
126+ */
127+ export async function createMastraStreamResponse (
128+ _client : unknown ,
129+ _options : StreamToAISdkOptions
130+ ) : Promise < Response > {
131+ throw new Error (
132+ "createMastraStreamResponse is deprecated. Use createAgentStreamResponse with " +
133+ "the server-side mastra instance instead. See: https://mastra.ai/docs/frameworks/agentic-uis/ai-sdk"
134+ ) ;
30135}
0 commit comments