From 748620f29b213a48f26faadcdf41bfc691b2e7b0 Mon Sep 17 00:00:00 2001 From: Saket Aryan Date: Sat, 30 Aug 2025 21:58:30 +0530 Subject: [PATCH] fix(Vercel AI SDK): Streaming not working properly (#3386) --- vercel-ai-sdk/package.json | 2 +- .../src/mem0-generic-language-model.ts | 76 ++----------------- vercel-ai-sdk/src/mem0-types.ts | 1 + vercel-ai-sdk/src/mem0-utils.ts | 12 +-- 4 files changed, 15 insertions(+), 76 deletions(-) diff --git a/vercel-ai-sdk/package.json b/vercel-ai-sdk/package.json index c457489ca..34afea7a1 100644 --- a/vercel-ai-sdk/package.json +++ b/vercel-ai-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@mem0/vercel-ai-provider", - "version": "2.0.1", + "version": "2.0.2", "description": "Vercel AI Provider for providing memory to LLMs", "main": "./dist/index.js", "module": "./dist/index.mjs", diff --git a/vercel-ai-sdk/src/mem0-generic-language-model.ts b/vercel-ai-sdk/src/mem0-generic-language-model.ts index a7bf65a0e..7c2c8898b 100644 --- a/vercel-ai-sdk/src/mem0-generic-language-model.ts +++ b/vercel-ai-sdk/src/mem0-generic-language-model.ts @@ -2,17 +2,16 @@ import { LanguageModelV2CallOptions, LanguageModelV2Message, - LanguageModelV2Source, - LanguageModelV2StreamPart + LanguageModelV2Source } from '@ai-sdk/provider'; import { LanguageModelV2 } from '@ai-sdk/provider'; -import { simulateStreamingMiddleware, wrapLanguageModel } from 'ai'; +// streaming uses provider-native doStream; no middleware needed import { Mem0ChatConfig, Mem0ChatModelId, Mem0ChatSettings, Mem0ConfigSettings, Mem0StreamResponse } from "./mem0-types"; import { Mem0ClassSelector } from "./mem0-provider-selector"; import { Mem0ProviderSettings } from "./mem0-provider"; -import { addMemories, getMemories, retrieveMemories } from "./mem0-utils"; +import { addMemories, getMemories } from "./mem0-utils"; const generateRandomId = () => { return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); @@ -203,13 +202,8 @@ export class Mem0GenericLanguageModel implements LanguageModelV2 { const baseModel = selector.createProvider(); - // Wrap the model with streaming middleware using the new Vercel AI SDK 5.0 approach - const model = wrapLanguageModel({ - model: baseModel, - middleware: simulateStreamingMiddleware(), - }); - - const streamResponse = await model.doStream({ + // Use the provider's native streaming directly to avoid buffering + const streamResponse = await baseModel.doStream({ ...options, prompt: updatedPrompts, }); @@ -219,65 +213,9 @@ export class Mem0GenericLanguageModel implements LanguageModelV2 { return streamResponse; } - // Create a new stream that includes memory sources - const originalStream = streamResponse.stream; - - // Create a transform stream that adds memory sources at the beginning - const transformStream = new TransformStream({ - start(controller) { - // Add source chunks for each memory at the beginning - try { - if (Array.isArray(memories) && memories?.length > 0) { - // Create a single source that contains all memories - controller.enqueue({ - type: 'source', - title: "Mem0 Memories", - sourceType: "url", - id: "mem0-" + generateRandomId(), - url: "https://app.mem0.ai", - - providerOptions: { - mem0: { - memories: memories, - memoriesText: memories?.map((memory: any) => memory?.memory).join("\n\n") - } - } - }); - - // Also add individual memory sources for more detailed information - memories?.forEach((memory: any) => { - controller.enqueue({ - type: 'source', - title: memory?.title || "Memory", - sourceType: "url", - id: "mem0-memory-" + generateRandomId(), - url: "https://app.mem0.ai", - - providerOptions: { - mem0: { - memory: memory, - memoryText: memory?.memory - } - } - }); - }); - } - } catch (error) { - console.error("Error adding memory sources:", error); - } - }, - transform(chunk, controller) { - // Pass through all chunks from the original stream - controller.enqueue(chunk); - } - }); - - // Pipe the original stream through our transform stream - const enhancedStream = originalStream.pipeThrough(transformStream); - - // Return a new stream response with our enhanced stream + // Return stream untouched for true streaming behavior return { - stream: enhancedStream, + stream: streamResponse.stream, request: streamResponse.request, response: streamResponse.response, }; diff --git a/vercel-ai-sdk/src/mem0-types.ts b/vercel-ai-sdk/src/mem0-types.ts index 70c4d4d9b..ed68aad0f 100644 --- a/vercel-ai-sdk/src/mem0-types.ts +++ b/vercel-ai-sdk/src/mem0-types.ts @@ -29,6 +29,7 @@ export interface Mem0ConfigSettings { host?: string; output_format?: string; filter_memories?: boolean; + async_mode?: boolean; } export interface Mem0ChatConfig extends Mem0ConfigSettings, Mem0ProviderSettings {} diff --git a/vercel-ai-sdk/src/mem0-utils.ts b/vercel-ai-sdk/src/mem0-utils.ts index 6484882dc..2a3906720 100644 --- a/vercel-ai-sdk/src/mem0-utils.ts +++ b/vercel-ai-sdk/src/mem0-utils.ts @@ -62,26 +62,26 @@ const convertToMem0Format = (messages: LanguageModelV2Prompt) => { const searchInternalMemories = async (query: string, config?: Mem0ConfigSettings, top_k: number = 5) => { try { - const filters: { AND: Array<{ [key: string]: string | undefined }> } = { - AND: [], + const filters: { OR: Array<{ [key: string]: string | undefined }> } = { + OR: [], }; if (config?.user_id) { - filters.AND.push({ + filters.OR.push({ user_id: config.user_id, }); } if (config?.app_id) { - filters.AND.push({ + filters.OR.push({ app_id: config.app_id, }); } if (config?.agent_id) { - filters.AND.push({ + filters.OR.push({ agent_id: config.agent_id, }); } if (config?.run_id) { - filters.AND.push({ + filters.OR.push({ run_id: config.run_id, }); }