@@ -12,9 +12,13 @@ import {
1212} from "./middleware"
1313import type { PromptTemplate , MemoryPromptData } from "./memory-prompt"
1414
15- interface WrapVercelLanguageModelOptions {
16- /** Conversation ID to group messages into a single document (maps to customId in Supermemory). Required when addMemory is "always". */
17- conversationId ?: string
15+ interface WrapVercelLanguageModelOptions < T extends LanguageModel > {
16+ /** The language model to wrap with supermemory capabilities */
17+ model : T
18+ /** The container tag/identifier for memory search (e.g., user ID, project ID) */
19+ containerTag : string
20+ /** Custom ID to group messages into a single document. Required. */
21+ customId : string
1822 /** Enable detailed logging of memory search and injection */
1923 verbose ?: boolean
2024 /**
@@ -35,8 +39,8 @@ interface WrapVercelLanguageModelOptions {
3539 searchLimit ?: number
3640 /**
3741 * Memory persistence mode:
38- * - "always": Automatically save conversations as memories (requires conversationId )
39- * - "never": Only retrieve memories, don't store new ones (default)
42+ * - "always": Automatically save conversations as memories (default )
43+ * - "never": Only retrieve memories, don't store new ones
4044 */
4145 addMemory ?: "always" | "never"
4246 /** Supermemory API key (falls back to SUPERMEMORY_API_KEY env var) */
@@ -72,35 +76,40 @@ interface WrapVercelLanguageModelOptions {
7276 * Supports both Vercel AI SDK 5 (LanguageModelV2) and SDK 6 (LanguageModelV3) via runtime
7377 * detection of `model.specificationVersion`.
7478 *
75- * @param model - The language model to wrap with supermemory capabilities (V2 or V3)
76- * @param containerTag - The container tag/identifier for memory search (e.g., user ID, project ID )
77- * @param options - Configuration options for the middleware
78- * @param options.conversationId - Conversation ID to group messages into a single document (maps to customId in Supermemory)
79+ * @param options - Configuration object containing model and Supermemory options
80+ * @param options.model - The language model to wrap with supermemory capabilities (V2 or V3 )
81+ * @param options.containerTag - Required. The container tag/identifier for memory search (e.g., user ID, project ID)
82+ * @param options.customId - Required. Custom ID to group messages into a single document
7983 * @param options.verbose - Optional flag to enable detailed logging of memory search and injection process (default: false)
8084 * @param options.mode - Optional mode for memory search: "profile", "query", or "full" (default: "profile")
8185 * @param options.searchMode - Optional search mode: "memories" (default), "hybrid" (memories + chunks), or "documents" (chunks only)
8286 * @param options.searchLimit - Optional maximum number of search results when using hybrid/documents mode (default: 10)
83- * @param options.addMemory - Optional mode for memory persistence: "always" (requires conversationId ), "never" (default )
87+ * @param options.addMemory - Optional mode for memory persistence: "always" (default - saves conversations ), "never" (read-only mode )
8488 * @param options.apiKey - Optional Supermemory API key to use instead of the environment variable
8589 * @param options.baseUrl - Optional base URL for the Supermemory API (default: "https://api.supermemory.ai")
8690 *
8791 * @returns A wrapped language model that automatically includes relevant memories in prompts
8892 *
8993 * @example
9094 * ```typescript
91- * import { withSupermemory } from "@supermemory/tools/ai-sdk "
95+ * import { withSupermemory } from "@supermemory/tools/vercel "
9296 * import { openai } from "@ai-sdk/openai"
97+ * import { generateText } from "ai"
9398 *
9499 * // Basic usage with profile memories
95- * const modelWithMemory = withSupermemory(openai("gpt-4"), "user-123", {
96- * conversationId: "conv-456",
100+ * const modelWithMemory = withSupermemory({
101+ * model: openai("gpt-4"),
102+ * containerTag: "user-123",
103+ * customId: "conv-456",
97104 * mode: "full",
98105 * addMemory: "always"
99106 * })
100107 *
101108 * // RAG usage with hybrid search (memories + document chunks)
102- * const ragModel = withSupermemory(openai("gpt-4"), "user-123", {
103- * conversationId: "conv-789",
109+ * const ragModel = withSupermemory({
110+ * model: openai("gpt-4"),
111+ * containerTag: "user-123",
112+ * customId: "conv-789",
104113 * mode: "full",
105114 * searchMode: "hybrid", // Search both memories and document chunks
106115 * searchLimit: 15,
@@ -116,38 +125,28 @@ interface WrapVercelLanguageModelOptions {
116125 * @throws {Error } When supermemory API request fails
117126 */
118127const wrapVercelLanguageModel = < T extends LanguageModel > (
119- model : T ,
120- containerTag : string ,
121- options ?: WrapVercelLanguageModelOptions ,
128+ options : WrapVercelLanguageModelOptions < T > ,
122129) : T => {
123- const providedApiKey = options ?. apiKey ?? process . env . SUPERMEMORY_API_KEY
130+ const { model, containerTag, customId, ...restOptions } = options
131+ const providedApiKey = restOptions . apiKey ?? process . env . SUPERMEMORY_API_KEY
124132
125133 if ( ! providedApiKey ) {
126134 throw new Error (
127135 "SUPERMEMORY_API_KEY is not set — provide it via `options.apiKey` or set `process.env.SUPERMEMORY_API_KEY`" ,
128136 )
129137 }
130138
131- if (
132- ( options ?. addMemory ?? "never" ) === "always" &&
133- ! options ?. conversationId
134- ) {
135- throw new Error (
136- 'conversationId is required when addMemory is "always" — provide it via options.conversationId to group messages into a single document' ,
137- )
138- }
139-
140139 const ctx = createSupermemoryContext ( {
141140 containerTag,
142141 apiKey : providedApiKey ,
143- conversationId : options ?. conversationId ,
144- verbose : options ? .verbose ?? false ,
145- mode : options ? .mode ?? "profile" ,
146- searchMode : options ? .searchMode ?? "memories" ,
147- searchLimit : options ? .searchLimit ?? 10 ,
148- addMemory : options ? .addMemory ?? "never " ,
149- baseUrl : options ? .baseUrl ,
150- promptTemplate : options ? .promptTemplate ,
142+ customId ,
143+ verbose : restOptions . verbose ?? false ,
144+ mode : restOptions . mode ?? "profile" ,
145+ searchMode : restOptions . searchMode ?? "memories" ,
146+ searchLimit : restOptions . searchLimit ?? 10 ,
147+ addMemory : restOptions . addMemory ?? "always " ,
148+ baseUrl : restOptions . baseUrl ,
149+ promptTemplate : restOptions . promptTemplate ,
151150 } )
152151
153152 const wrappedModel = {
@@ -163,7 +162,7 @@ const wrapVercelLanguageModel = <T extends LanguageModel>(
163162 const userMessage = getLastUserMessage ( params )
164163 if (
165164 ctx . addMemory === "always" &&
166- ctx . conversationId &&
165+ ctx . customId &&
167166 userMessage &&
168167 userMessage . trim ( )
169168 ) {
@@ -173,7 +172,7 @@ const wrapVercelLanguageModel = <T extends LanguageModel>(
173172 saveMemoryAfterResponse (
174173 ctx . client ,
175174 ctx . containerTag ,
176- ctx . conversationId ,
175+ ctx . customId ,
177176 assistantResponseText ,
178177 params ,
179178 ctx . logger ,
@@ -216,14 +215,14 @@ const wrapVercelLanguageModel = <T extends LanguageModel>(
216215 const userMessage = getLastUserMessage ( params )
217216 if (
218217 ctx . addMemory === "always" &&
219- ctx . conversationId &&
218+ ctx . customId &&
220219 userMessage &&
221220 userMessage . trim ( )
222221 ) {
223222 saveMemoryAfterResponse (
224223 ctx . client ,
225224 ctx . containerTag ,
226- ctx . conversationId ,
225+ ctx . customId ,
227226 generatedText ,
228227 params ,
229228 ctx . logger ,
0 commit comments