Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/docs/ai-sdk/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const result = await generateText({

```typescript
const modelWithMemory = withSupermemory(openai("gpt-5"), "user-123", {
conversationId: "conv-1",
addMemory: "always"
})
```
Expand Down
27 changes: 27 additions & 0 deletions apps/docs/ai-sdk/user-profiles.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ All of this happens transparently - you write code as if using a normal model, b

```typescript
const model = withSupermemory(openai("gpt-5"), "user-123", {
conversationId: "conv-1",
addMemory: "always"
})
```
Expand Down Expand Up @@ -117,6 +118,32 @@ const result = await generateText({
// Uses both profile (user's expertise) AND search (previous debugging sessions)
```

### Hybrid Search Mode

Use `searchMode: "hybrid"` to search both memories AND document chunks.

```typescript
const model = withSupermemory(openai("gpt-4"), "user-123", {
mode: "full",
searchMode: "hybrid", // Search memories + document chunks
searchLimit: 15 // Max results (default: 10)
})

const result = await generateText({
model,
messages: [{
role: "user",
content: "What's in my documents about quarterly goals?"
}]
})
// Searches both extracted memories AND raw document content
```

**Search Mode Options:**
- `"memories"` (default) - Search only memory entries
- `"hybrid"` - Search memories + document chunks
- `"documents"` - Search only document chunks

## Custom Prompt Templates

Customize how memories are formatted and injected into the system prompt using the `promptTemplate` option. This is useful for:
Expand Down
50 changes: 39 additions & 11 deletions apps/docs/integrations/ai-sdk.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,14 @@ Automatically inject user profiles into every LLM call for instant personalizati

```typescript
import { generateText } from "ai"
import { withSupermemory } from "@supermemory/tools/ai-sdk"
import { withSupermemory } from "@supermemory/tools/vercel"
import { openai } from "@ai-sdk/openai"

const modelWithMemory = withSupermemory(openai("gpt-5"), "user-123")
const modelWithMemory = withSupermemory({
model: openai("gpt-4"),
containerTag: "user-123",
customId: "conv-456"
})

const result = await generateText({
model: modelWithMemory,
Expand All @@ -44,11 +48,14 @@ const result = await generateText({
```

<Note>
**Memory saving is disabled by default.** The middleware only retrieves existing memories. To automatically save new memories:
**Memory saving is enabled by default.** The middleware automatically saves conversations to memory. To disable memory saving:

```typescript
const modelWithMemory = withSupermemory(openai("gpt-5"), "user-123", {
addMemory: "always"
const modelWithMemory = withSupermemory({
model: openai("gpt-4"),
containerTag: "user-123",
customId: "conv-456",
addMemory: "never"
})
```
</Note>
Expand All @@ -58,27 +65,42 @@ const result = await generateText({
**Profile Mode (Default)** - Retrieves the user's complete profile:

```typescript
const model = withSupermemory(openai("gpt-4"), "user-123", { mode: "profile" })
const model = withSupermemory({
model: openai("gpt-4"),
containerTag: "user-123",
customId: "conv-456",
mode: "profile"
})
```

**Query Mode** - Searches memories based on the user's message:

```typescript
const model = withSupermemory(openai("gpt-4"), "user-123", { mode: "query" })
const model = withSupermemory({
model: openai("gpt-4"),
containerTag: "user-123",
customId: "conv-456",
mode: "query"
})
```

**Full Mode** - Combines profile AND query-based search:

```typescript
const model = withSupermemory(openai("gpt-4"), "user-123", { mode: "full" })
const model = withSupermemory({
model: openai("gpt-4"),
containerTag: "user-123",
customId: "conv-456",
mode: "full"
})
```

### Custom Prompt Templates

Customize how memories are formatted. The template receives `userMemories`, `generalSearchMemories`, and `searchResults` (raw array for filtering by metadata):

```typescript
import { withSupermemory, type MemoryPromptData } from "@supermemory/tools/ai-sdk"
import { withSupermemory, type MemoryPromptData } from "@supermemory/tools/vercel"

const claudePrompt = (data: MemoryPromptData) => `
<context>
Expand All @@ -91,7 +113,10 @@ const claudePrompt = (data: MemoryPromptData) => `
</context>
`.trim()

const model = withSupermemory(anthropic("claude-3-sonnet"), "user-123", {
const model = withSupermemory({
model: anthropic("claude-3-sonnet"),
containerTag: "user-123",
customId: "conv-456",
mode: "full",
promptTemplate: claudePrompt
})
Expand All @@ -100,7 +125,10 @@ const model = withSupermemory(anthropic("claude-3-sonnet"), "user-123", {
### Verbose Logging

```typescript
const model = withSupermemory(openai("gpt-4"), "user-123", {
const model = withSupermemory({
model: openai("gpt-4"),
containerTag: "user-123",
customId: "conv-456",
verbose: true
})
// Console output shows memory retrieval details
Expand Down
10 changes: 6 additions & 4 deletions apps/web/components/memory-graph/memory-graph-wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,12 @@
maxNodes={maxNodes}
canvasRef={canvasRef}
totalCount={totalCount}
colors={{
bg: "transparent",
edgeDerives: "#9ca3af",
} as any}
colors={
{
bg: "transparent",
edgeDerives: "#9ca3af",
} as any

Check warning on line 78 in apps/web/components/memory-graph/memory-graph-wrapper.tsx

View workflow job for this annotation

GitHub Actions / Quality Checks

lint/suspicious/noExplicitAny

Unexpected any. Specify a different type.
}
{...rest}
>
{children}
Expand Down
3 changes: 1 addition & 2 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 13 additions & 7 deletions packages/memory-graph/src/components/memory-graph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -197,22 +197,29 @@
setViewportVersion((v) => v + 1)
}

const { hasMore: more, isLoadingMore: loading, onLoadMore: load } = loadMoreRef.current
const {
hasMore: more,
isLoadingMore: loading,
onLoadMore: load,
} = loadMoreRef.current
if (!more || loading || !load || !viewportRef.current) return

const vp = viewportRef.current
const currentNodes = nodes
if (currentNodes.length === 0) return

const topLeft = vp.screenToWorld(0, 0)
const bottomRight = vp.screenToWorld(containerSize.width, containerSize.height)
const bottomRight = vp.screenToWorld(
containerSize.width,
containerSize.height,
)
const viewW = bottomRight.x - topLeft.x
const viewH = bottomRight.y - topLeft.y

let minX = Infinity
let minY = Infinity
let maxX = -Infinity
let maxY = -Infinity
let minX = Number.POSITIVE_INFINITY
let minY = Number.POSITIVE_INFINITY
let maxX = Number.NEGATIVE_INFINITY
let maxY = Number.NEGATIVE_INFINITY
for (const n of currentNodes) {
if (n.x < minX) minX = n.x
if (n.y < minY) minY = n.y
Expand Down Expand Up @@ -466,7 +473,7 @@
const onSlideshowNodeChangeRef = useRef(onSlideshowNodeChange)
onSlideshowNodeChangeRef.current = onSlideshowNodeChange

// biome-ignore lint/correctness/useExhaustiveDependencies: reads from refs to avoid resetting interval on resize/node changes

Check warning on line 476 in packages/memory-graph/src/components/memory-graph.tsx

View workflow job for this annotation

GitHub Actions / Quality Checks

suppressions/unused

Suppression comment has no effect. Remove the suppression or make sure you are suppressing the correct rule.
useEffect(() => {
if (!isSlideshowActive || nodes.length === 0) {
if (!isSlideshowActive) {
Expand All @@ -491,7 +498,7 @@
idx = 0
}
lastIdx = idx
const n = currentNodes[idx]!

Check warning on line 501 in packages/memory-graph/src/components/memory-graph.tsx

View workflow job for this annotation

GitHub Actions / Quality Checks

lint/style/noNonNullAssertion

Forbidden non-null assertion.
setSelectedNode(n.id)
const sz = containerSizeRef.current
viewportRef.current?.centerOn(n.x, n.y, sz.width, sz.height)
Expand Down Expand Up @@ -613,7 +620,6 @@
colors={colors}
/>


{!isLoading && !nodes.some((n) => n.type === "document") && children && (
<div style={emptyStateStyle}>{children}</div>
)}
Expand Down
27 changes: 27 additions & 0 deletions packages/tools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,29 @@ const result = await generateText({
})
```

**Hybrid Search Mode (RAG)** - Search both memories AND document chunks:
```typescript
import { generateText } from "ai"
import { withSupermemory } from "@supermemory/tools/ai-sdk"
import { openai } from "@ai-sdk/openai"

const modelWithHybrid = withSupermemory(openai("gpt-4"), "user-123", {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation doesn't match the new API

This PR changed the withSupermemory function signature from positional arguments to an options object, but the README examples still use the old API.

This example uses:

withSupermemory(openai("gpt-4"), "user-123", { ... })

But the new API requires:

withSupermemory({
  model: openai("gpt-4"),
  containerTag: "user-123",
  customId: "conv-123",  // Now required
  ...options
})

All README examples need to be updated to use the new options object pattern. Users following these docs will get runtime errors.

mode: "full",
searchMode: "hybrid", // Search memories + document chunks
searchLimit: 15 // Max results (default: 10)
})

const result = await generateText({
model: modelWithHybrid,
messages: [{ role: "user", content: "What's in my documents about quarterly goals?" }],
})
```

Search mode options:
- `"memories"` (default) - Search only memory entries
- `"hybrid"` - Search memories + document chunks (recommended for RAG)
- `"documents"` - Search only document chunks

#### Automatic Memory Capture

The middleware can automatically save user messages as memories:
Expand Down Expand Up @@ -653,6 +676,8 @@ interface WithSupermemoryOptions {
conversationId?: string
verbose?: boolean
mode?: "profile" | "query" | "full"
searchMode?: "memories" | "hybrid" | "documents"
searchLimit?: number
addMemory?: "always" | "never"
/** Optional Supermemory API key. Use this in browser environments. */
apiKey?: string
Expand All @@ -662,6 +687,8 @@ interface WithSupermemoryOptions {
- **conversationId**: Optional conversation ID to group messages into a single document for contextual memory generation
- **verbose**: Enable detailed logging of memory search and injection process (default: false)
- **mode**: Memory search mode - "profile" (default), "query", or "full"
- **searchMode**: Search mode - "memories" (default), "hybrid", or "documents". Use "hybrid" for RAG applications
- **searchLimit**: Maximum number of search results when using hybrid/documents mode (default: 10)
- **addMemory**: Automatic memory storage mode - "always" or "never" (default: "never")

## Available Tools
Expand Down
3 changes: 1 addition & 2 deletions packages/tools/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@supermemory/tools",
"type": "module",
"version": "1.4.01",
"version": "1.5.0",
"description": "Memory tools for AI SDK and OpenAI function calling with supermemory",
"scripts": {
"build": "tsdown",
Expand All @@ -14,7 +14,6 @@
"@ai-sdk/anthropic": "^2.0.25",
"@ai-sdk/openai": "^2.0.23",
"ai": "^5.0.29",
"lru-cache": "^11.2.6",
"openai": "^4.104.0",
"supermemory": "^3.0.0-alpha.26",
"zod": "^4.1.5"
Expand Down
33 changes: 0 additions & 33 deletions packages/tools/src/ai-sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,38 +220,6 @@ export const documentListTool = (
})
}

export const documentDeleteTool = (
apiKey: string,
config?: SupermemoryToolsConfig,
) => {
const client = new Supermemory({
apiKey,
...(config?.baseUrl ? { baseURL: config.baseUrl } : {}),
})

return tool({
description: TOOL_DESCRIPTIONS.documentDelete,
inputSchema: z.object({
documentId: z.string().describe(PARAMETER_DESCRIPTIONS.documentId),
}),
execute: async ({ documentId }) => {
try {
await client.documents.delete({ docId: documentId })

return {
success: true,
message: `Document ${documentId} deleted successfully`,
}
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : "Unknown error",
}
}
},
})
}

export const documentAddTool = (
apiKey: string,
config?: SupermemoryToolsConfig,
Expand Down Expand Up @@ -368,7 +336,6 @@ export function supermemoryTools(
addMemory: addMemoryTool(apiKey, config),
getProfile: getProfileTool(apiKey, config),
documentList: documentListTool(apiKey, config),
documentDelete: documentDeleteTool(apiKey, config),
documentAdd: documentAddTool(apiKey, config),
memoryForget: memoryForgetTool(apiKey, config),
}
Expand Down
4 changes: 4 additions & 0 deletions packages/tools/src/shared/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export type {
MemoryPromptData,
PromptTemplate,
MemoryMode,
SearchMode,
AddMemoryMode,
Logger,
ProfileStructure,
Expand Down Expand Up @@ -34,9 +35,12 @@ export {
// Memory client
export {
supermemoryProfileSearch,
supermemoryHybridSearch,
buildMemoriesText,
extractQueryText,
getLastUserMessageText,
type BuildMemoriesTextOptions,
type GenericMessage,
type SearchResultItem,
type SearchResponse,
} from "./memory-client"
Loading
Loading