mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-04-28 03:29:59 +00:00
voltagent-sdk (#791)
This commit is contained in:
parent
e7144407f5
commit
0783594b8d
11 changed files with 1726 additions and 140 deletions
|
|
@ -161,6 +161,7 @@
|
|||
"integrations/openai-agents-sdk",
|
||||
"integrations/agent-framework",
|
||||
"integrations/mastra",
|
||||
"integrations/voltagent",
|
||||
"integrations/langchain",
|
||||
"integrations/crewai",
|
||||
"integrations/agno",
|
||||
|
|
|
|||
170
apps/docs/integrations/voltagent.mdx
Normal file
170
apps/docs/integrations/voltagent.mdx
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
---
|
||||
title: "VoltAgent"
|
||||
sidebarTitle: "VoltAgent"
|
||||
description: "Integrate Supermemory with VoltAgent for long-term memory in AI agents"
|
||||
icon: "bolt"
|
||||
---
|
||||
|
||||
Supermemory integrates with [VoltAgent](https://github.com/VoltAgent/voltagent), providing long-term memory capabilities for AI agents. Your VoltAgent applications will remember past conversations and provide personalized responses based on user history.
|
||||
|
||||
<Card title="@supermemory/tools on npm" icon="npm" href="https://www.npmjs.com/package/@supermemory/tools">
|
||||
Check out the NPM page for more details
|
||||
</Card>
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @supermemory/tools @voltagent/core
|
||||
```
|
||||
|
||||
Set up your API key as an environment variable:
|
||||
|
||||
```bash
|
||||
export SUPERMEMORY_API_KEY=your_supermemory_api_key
|
||||
```
|
||||
|
||||
You can obtain an API key from [console.supermemory.ai](https://console.supermemory.ai).
|
||||
|
||||
## Quick Start
|
||||
|
||||
Supermemory provides a `withSupermemory` wrapper that enhances any VoltAgent agent config with automatic memory retrieval and storage:
|
||||
|
||||
```typescript
|
||||
import { withSupermemory } from "@supermemory/tools/voltagent"
|
||||
import { Agent } from "@voltagent/core"
|
||||
import { openai } from "@ai-sdk/openai"
|
||||
|
||||
// Create an agent with Supermemory memory capabilities
|
||||
const configWithMemory = withSupermemory({
|
||||
agentConfig: {
|
||||
name: "my-agent",
|
||||
instructions: "You are a helpful assistant.",
|
||||
model: openai("gpt-4o"),
|
||||
},
|
||||
containerTag: "user-123",
|
||||
customId: "conversation-123",
|
||||
})
|
||||
|
||||
const agent = new Agent(configWithMemory)
|
||||
|
||||
// Memories are automatically injected and saved
|
||||
const result = await agent.generateText({
|
||||
messages: [{ role: "user", content: "What's my name?" }],
|
||||
})
|
||||
```
|
||||
|
||||
<Note>
|
||||
**Memory saving is enabled by default** in the VoltAgent integration. To disable it:
|
||||
|
||||
```typescript
|
||||
const configWithMemory = withSupermemory({
|
||||
agentConfig: {
|
||||
name: "my-agent",
|
||||
instructions: "You are a helpful assistant.",
|
||||
model: openai("gpt-4o"),
|
||||
},
|
||||
containerTag: "user-123",
|
||||
customId: "conversation-123",
|
||||
addMemory: "never",
|
||||
})
|
||||
```
|
||||
</Note>
|
||||
|
||||
## How It Works
|
||||
|
||||
When integrated with VoltAgent, Supermemory hooks into two lifecycle events:
|
||||
|
||||
### 1. Memory Retrieval (onPrepareMessages)
|
||||
|
||||
Before each LLM call, Supermemory automatically:
|
||||
- Extracts the user's latest message
|
||||
- Searches for relevant memories scoped to the `containerTag`
|
||||
- Injects retrieved memories into the system prompt
|
||||
|
||||
### 2. Conversation Saving (onEnd)
|
||||
|
||||
After each agent response, the conversation is saved to Supermemory for future retrieval. This requires a `customId` to be set.
|
||||
|
||||
## Memory Modes
|
||||
|
||||
| Mode | Description | Use Case |
|
||||
| ----------- | ------------------------------------------- | ------------------------------ |
|
||||
| `"profile"` | Retrieves the user's complete profile | Personalization without search |
|
||||
| `"query"` | Searches memories based on the user's message | Finding relevant past context |
|
||||
| `"full"` | Combines profile AND query-based search | Complete memory (recommended) |
|
||||
|
||||
```typescript
|
||||
const configWithMemory = withSupermemory({
|
||||
agentConfig: {
|
||||
name: "my-agent",
|
||||
instructions: "You are a helpful assistant.",
|
||||
model: openai("gpt-4o"),
|
||||
},
|
||||
containerTag: "user-123",
|
||||
customId: "conversation-123",
|
||||
mode: "full",
|
||||
})
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
```typescript
|
||||
const configWithMemory = withSupermemory({
|
||||
// Agent configuration
|
||||
agentConfig: {
|
||||
name: "my-agent",
|
||||
instructions: "You are a helpful assistant.",
|
||||
model: openai("gpt-4o"),
|
||||
},
|
||||
|
||||
// Required
|
||||
containerTag: "user-123", // User/project ID for scoping memories
|
||||
|
||||
// Memory behavior
|
||||
mode: "full", // "profile" | "query" | "full"
|
||||
addMemory: "always", // "always" | "never"
|
||||
customId: "conv-456", // Groups messages into a conversation
|
||||
|
||||
// Search tuning
|
||||
searchMode: "hybrid", // "memories" | "documents" | "hybrid"
|
||||
threshold: 0.1, // 0.0-1.0 (higher = more accurate)
|
||||
limit: 10, // Max results to return
|
||||
rerank: true, // Rerank for best relevance
|
||||
rewriteQuery: false, // AI-rewrite query (+400ms latency)
|
||||
|
||||
// Context
|
||||
entityContext: "This is John, a software engineer", // Guides memory extraction (max 1500 chars)
|
||||
metadata: { source: "voltagent" }, // Attached to saved conversations
|
||||
|
||||
// API
|
||||
apiKey: "sk-...", // Falls back to SUPERMEMORY_API_KEY env var
|
||||
baseUrl: "https://api.supermemory.ai",
|
||||
})
|
||||
```
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
| ----------------- | -------- | ------------ | -------------------------------------------------------- |
|
||||
| `agentConfig` | object | **required** | VoltAgent agent configuration object |
|
||||
| `containerTag` | string | **required** | User/project ID for scoping memories |
|
||||
| `mode` | string | `"profile"` | Memory retrieval mode |
|
||||
| `addMemory` | string | `"always"` | Whether to save conversations after each response |
|
||||
| `customId` | string | **required** | Custom ID to group messages into a conversation |
|
||||
| `searchMode` | string | — | `"memories"`, `"documents"`, or `"hybrid"` |
|
||||
| `threshold` | number | `0.1` | Similarity threshold (0 = more results, 1 = more accurate) |
|
||||
| `limit` | number | `10` | Maximum number of memory results |
|
||||
| `rerank` | boolean | `false` | Rerank results for relevance |
|
||||
| `rewriteQuery` | boolean | `false` | AI-rewrite query for better results (+400ms) |
|
||||
| `entityContext` | string | — | Context for memory extraction (max 1500 chars) |
|
||||
| `metadata` | object | — | Custom metadata attached to saved conversations |
|
||||
| `promptTemplate` | function | — | Custom function to format memory data into prompt |
|
||||
|
||||
## Search Modes
|
||||
|
||||
The `searchMode` option controls what type of results are searched:
|
||||
|
||||
| Mode | Description |
|
||||
| ------------- | ------------------------------------------------------ |
|
||||
| `"memories"` | Search only memory entries (atomic facts about the user) |
|
||||
| `"documents"` | Search only document chunks |
|
||||
| `"hybrid"` | Search both memories AND document chunks (recommended) |
|
||||
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
"devDependencies": {
|
||||
"@ai-sdk/provider": "^3.0.0",
|
||||
"@anthropic-ai/sdk": "^0.65.0",
|
||||
"@voltagent/core": "^2.6.12",
|
||||
"@mastra/core": "^1.0.0",
|
||||
"@total-typescript/tsconfig": "^1.0.4",
|
||||
"@types/bun": "^1.2.21",
|
||||
|
|
@ -31,7 +32,13 @@
|
|||
"vitest": "^3.2.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ai-sdk/provider": "^2.0.0 || ^3.0.0"
|
||||
"@ai-sdk/provider": "^2.0.0 || ^3.0.0",
|
||||
"@voltagent/core": "^2.6.12"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@voltagent/core": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
|
|
@ -45,6 +52,7 @@
|
|||
"./claude-memory": "./dist/claude-memory.js",
|
||||
"./mastra": "./dist/mastra.js",
|
||||
"./openai": "./dist/openai/index.js",
|
||||
"./voltagent": "./dist/voltagent/index.js",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"repository": {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ export interface AddConversationParams {
|
|||
messages: ConversationMessage[]
|
||||
containerTags?: string[]
|
||||
metadata?: Record<string, string | number | boolean>
|
||||
entityContext?: string
|
||||
apiKey: string
|
||||
baseUrl?: string
|
||||
}
|
||||
|
|
@ -86,6 +87,7 @@ export async function addConversation(
|
|||
messages: params.messages,
|
||||
containerTags: params.containerTags,
|
||||
metadata: params.metadata,
|
||||
entityContext: params.entityContext,
|
||||
}),
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
export type { SupermemoryToolsConfig } from "./types"
|
||||
|
||||
export type { OpenAIMiddlewareOptions } from "./openai"
|
||||
|
||||
export type { SupermemoryVoltAgent } from "./voltagent"
|
||||
|
|
|
|||
207
packages/tools/src/voltagent/hooks.ts
Normal file
207
packages/tools/src/voltagent/hooks.ts
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/**
|
||||
* VoltAgent hooks for Supermemory integration.
|
||||
*
|
||||
* Provides onPrepareMessages and onEnd hooks that inject memories
|
||||
* and save conversations.
|
||||
*/
|
||||
|
||||
import type {
|
||||
VoltAgentHooks,
|
||||
HookPrepareMessagesArgs,
|
||||
HookEndArgs,
|
||||
VoltAgentMessage,
|
||||
SupermemoryVoltAgent,
|
||||
} from "./types"
|
||||
import {
|
||||
createSupermemoryContext,
|
||||
enhanceMessagesWithMemories,
|
||||
saveConversation,
|
||||
} from "./middleware"
|
||||
|
||||
/**
|
||||
* Creates Supermemory hooks for VoltAgent agents.
|
||||
*
|
||||
* These hooks intercept the agent lifecycle to inject memories
|
||||
* before LLM calls and save conversations after completion.
|
||||
*
|
||||
* @param containerTag - The container tag/user ID for scoping memories
|
||||
* @param options - Configuration options for memory behavior
|
||||
* @returns VoltAgent hooks object with onPrepareMessages and onEnd
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { createSupermemoryHooks } from "@supermemory/tools/voltagent"
|
||||
*
|
||||
* const hooks = createSupermemoryHooks("user-123", {
|
||||
* mode: "full",
|
||||
* addMemory: "always",
|
||||
* customId: "conv-456",
|
||||
* })
|
||||
*
|
||||
* const agent = new Agent({
|
||||
* name: "my-agent",
|
||||
* instructions: "You are a helpful assistant",
|
||||
* llm: new VercelAIProvider(),
|
||||
* model: openai("gpt-4o"),
|
||||
* hooks
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export function createSupermemoryHooks(
|
||||
containerTag: string,
|
||||
options: SupermemoryVoltAgent,
|
||||
): VoltAgentHooks {
|
||||
const ctx = createSupermemoryContext(containerTag, options)
|
||||
|
||||
return {
|
||||
onPrepareMessages: async (
|
||||
args: HookPrepareMessagesArgs,
|
||||
): Promise<{ messages: VoltAgentMessage[] }> => {
|
||||
try {
|
||||
// VoltAgent passes user messages in args.context.input.messages
|
||||
// and the prepared messages (system + conversation) in args.messages
|
||||
const contextInput = args.context?.input as
|
||||
| { messages?: VoltAgentMessage[] }
|
||||
| undefined
|
||||
const inputMessages = contextInput?.messages || []
|
||||
|
||||
ctx.logger.debug("onPrepareMessages called", {
|
||||
messageCount: args.messages.length,
|
||||
inputMessageCount: inputMessages.length,
|
||||
agentName: args.agent.name,
|
||||
})
|
||||
|
||||
const enhancedMessages = await enhanceMessagesWithMemories(
|
||||
inputMessages,
|
||||
ctx,
|
||||
args.messages,
|
||||
)
|
||||
|
||||
ctx.logger.debug("Messages enhanced with memories", {
|
||||
originalCount: args.messages.length,
|
||||
enhancedCount: enhancedMessages.length,
|
||||
})
|
||||
|
||||
return { messages: enhancedMessages }
|
||||
} catch (error) {
|
||||
ctx.logger.error("Error in onPrepareMessages", {
|
||||
error: error instanceof Error ? error.message : "Unknown error",
|
||||
})
|
||||
return { messages: args.messages }
|
||||
}
|
||||
},
|
||||
|
||||
onEnd: async (args: HookEndArgs): Promise<void> => {
|
||||
try {
|
||||
ctx.logger.debug("onEnd called", {
|
||||
agentName: args.agent.name,
|
||||
hasContext: !!args.context,
|
||||
hasOutput: !!args.output,
|
||||
})
|
||||
|
||||
let messages: VoltAgentMessage[] = []
|
||||
|
||||
if (args.context?.input && args.output) {
|
||||
const inputData = args.context.input as
|
||||
| { messages?: VoltAgentMessage[] }
|
||||
| undefined
|
||||
const inputMessages = inputData?.messages || []
|
||||
|
||||
const outputData = args.output as
|
||||
| string
|
||||
| { text?: string; content?: string }
|
||||
| undefined
|
||||
const outputText =
|
||||
typeof outputData === "string"
|
||||
? outputData
|
||||
: outputData?.text || outputData?.content
|
||||
|
||||
if (inputMessages.length > 0 && outputText) {
|
||||
messages = [
|
||||
...inputMessages,
|
||||
{ role: "assistant" as const, content: outputText },
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (messages.length === 0) {
|
||||
ctx.logger.debug("No messages to save, skipping")
|
||||
return
|
||||
}
|
||||
|
||||
saveConversation(messages, ctx).catch((error) => {
|
||||
ctx.logger.error("Background conversation save failed", {
|
||||
error: error instanceof Error ? error.message : "Unknown error",
|
||||
})
|
||||
})
|
||||
} catch (error) {
|
||||
ctx.logger.error("Error in onEnd", {
|
||||
error: error instanceof Error ? error.message : "Unknown error",
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges Supermemory hooks with existing hooks from an agent config.
|
||||
* Preserves existing hooks and adds Supermemory hooks.
|
||||
*
|
||||
* @param existingHooks - Existing hooks from agent config (if any)
|
||||
* @param supermemoryHooks - Supermemory hooks to merge
|
||||
* @returns Merged hooks object
|
||||
*/
|
||||
export function mergeHooks(
|
||||
existingHooks: VoltAgentHooks | undefined,
|
||||
supermemoryHooks: VoltAgentHooks,
|
||||
): VoltAgentHooks {
|
||||
if (!existingHooks) {
|
||||
return supermemoryHooks
|
||||
}
|
||||
|
||||
const mergedHooks: VoltAgentHooks = { ...existingHooks }
|
||||
|
||||
if (existingHooks.onPrepareMessages && supermemoryHooks.onPrepareMessages) {
|
||||
const existingOnPrepareMessages = existingHooks.onPrepareMessages
|
||||
const supermemoryOnPrepareMessages = supermemoryHooks.onPrepareMessages
|
||||
|
||||
mergedHooks.onPrepareMessages = async (args) => {
|
||||
const resultAfterExisting = await existingOnPrepareMessages(args)
|
||||
const messagesAfterExisting =
|
||||
resultAfterExisting?.messages || args.messages
|
||||
|
||||
return await supermemoryOnPrepareMessages({
|
||||
...args,
|
||||
messages: messagesAfterExisting,
|
||||
})
|
||||
}
|
||||
} else if (supermemoryHooks.onPrepareMessages) {
|
||||
mergedHooks.onPrepareMessages = supermemoryHooks.onPrepareMessages
|
||||
}
|
||||
|
||||
if (existingHooks.onEnd && supermemoryHooks.onEnd) {
|
||||
const existingOnEnd = existingHooks.onEnd
|
||||
const supermemoryOnEnd = supermemoryHooks.onEnd
|
||||
|
||||
mergedHooks.onEnd = async (args) => {
|
||||
await supermemoryOnEnd(args)
|
||||
await existingOnEnd(args)
|
||||
}
|
||||
} else if (supermemoryHooks.onEnd) {
|
||||
mergedHooks.onEnd = supermemoryHooks.onEnd
|
||||
}
|
||||
|
||||
if (existingHooks.onStart && supermemoryHooks.onStart) {
|
||||
const existingOnStart = existingHooks.onStart
|
||||
const supermemoryOnStart = supermemoryHooks.onStart
|
||||
|
||||
mergedHooks.onStart = async (args) => {
|
||||
await existingOnStart(args)
|
||||
await supermemoryOnStart(args)
|
||||
}
|
||||
} else if (supermemoryHooks.onStart) {
|
||||
mergedHooks.onStart = supermemoryHooks.onStart
|
||||
}
|
||||
|
||||
return mergedHooks
|
||||
}
|
||||
179
packages/tools/src/voltagent/index.ts
Normal file
179
packages/tools/src/voltagent/index.ts
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
/**
|
||||
* VoltAgent integration for Supermemory.
|
||||
*
|
||||
* Provides a wrapper function that enhances VoltAgent agent configurations
|
||||
* with Supermemory hooks for automatic memory injection and storage.
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
||||
import { createSupermemoryHooks, mergeHooks } from "./hooks"
|
||||
import type { VoltAgentConfig, SupermemoryVoltAgent } from "./types"
|
||||
|
||||
/**
|
||||
* Configuration options for withSupermemory.
|
||||
*/
|
||||
interface WithSupermemoryOptions<T extends VoltAgentConfig>
|
||||
extends SupermemoryVoltAgent {
|
||||
/**
|
||||
* The VoltAgent agent configuration to enhance
|
||||
*/
|
||||
agentConfig: T
|
||||
|
||||
/**
|
||||
* Required. The container tag/user ID for scoping memories (e.g., "user-123")
|
||||
*/
|
||||
containerTag: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Enhances a VoltAgent agent configuration with Supermemory memory capabilities.
|
||||
*
|
||||
* The function injects hooks that automatically:
|
||||
* - Retrieve relevant memories before LLM calls (via onPrepareMessages)
|
||||
* - Inject memories into the system prompt
|
||||
* - Optionally save conversations after completion (via onEnd)
|
||||
*
|
||||
* @param options - Configuration object containing agent config and Supermemory options
|
||||
* @param options.agentConfig - The VoltAgent agent configuration to enhance
|
||||
* @param options.containerTag - Required. The container tag/user ID for scoping memories (e.g., "user-123")
|
||||
* @param options.mode - Memory retrieval mode: "profile" (default), "query", or "full"
|
||||
* @param options.addMemory - Memory persistence: "always" (default for VoltAgent) or "never"
|
||||
* @param options.customId - Required. Custom ID to group messages into a single document
|
||||
* @param options.apiKey - Supermemory API key (falls back to SUPERMEMORY_API_KEY env var)
|
||||
* @param options.baseUrl - Custom Supermemory API base URL
|
||||
* @param options.promptTemplate - Custom function to format memory data into prompt
|
||||
* @param options.threshold - Search sensitivity: 0 (more results) to 1 (more accurate). Default: 0.1
|
||||
* @param options.limit - Maximum number of memory results to return. Default: 10
|
||||
* @param options.rerank - If true, rerank results for relevance. Default: false
|
||||
* @param options.rewriteQuery - If true, AI-rewrite query for better results (+400ms latency). Default: false
|
||||
* @param options.filters - Advanced AND/OR filters for search
|
||||
* @param options.include - Control what additional data to include (chunks, documents, etc.)
|
||||
* @param options.metadata - Optional metadata to attach to saved conversations
|
||||
* @param options.searchMode - Search mode: "memories" (atomic facts), "documents" (chunks), or "hybrid" (both)
|
||||
* @param options.entityContext - Context for memory extraction (max 1500 chars), guides how memories are understood
|
||||
* @returns Enhanced agent config with Supermemory hooks injected
|
||||
*
|
||||
* @example
|
||||
* Basic usage with profile memories:
|
||||
* ```typescript
|
||||
* import { withSupermemory } from "@supermemory/tools/voltagent"
|
||||
* import { Agent } from "@voltagent/core"
|
||||
* import { VercelAIProvider } from "@voltagent/vercel-ai"
|
||||
* import { openai } from "@ai-sdk/openai"
|
||||
*
|
||||
* const configWithMemory = withSupermemory({
|
||||
* agentConfig: {
|
||||
* name: "my-agent",
|
||||
* instructions: "You are a helpful assistant",
|
||||
* llm: new VercelAIProvider(),
|
||||
* model: openai("gpt-4o"),
|
||||
* },
|
||||
* containerTag: "user-123",
|
||||
* customId: "conversation-123"
|
||||
* })
|
||||
*
|
||||
* const agent = new Agent(configWithMemory)
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* Advanced usage with full memory mode and conversation saving:
|
||||
* ```typescript
|
||||
* const configWithMemory = withSupermemory({
|
||||
* agentConfig: {
|
||||
* name: "my-agent",
|
||||
* instructions: "You are a helpful assistant",
|
||||
* llm: new VercelAIProvider(),
|
||||
* model: openai("gpt-4o"),
|
||||
* },
|
||||
* containerTag: "user-123", // Required: user/project ID
|
||||
* mode: "full", // "profile" | "query" | "full"
|
||||
* addMemory: "always", // "always" | "never"
|
||||
* customId: "conv-456", // Group messages by conversation
|
||||
* threshold: 0.7, // 0.0-1.0 (higher = more accurate)
|
||||
* limit: 15, // Max results to return
|
||||
* rerank: true, // Rerank for best relevance
|
||||
* searchMode: "hybrid", // "memories" | "documents" | "hybrid"
|
||||
* entityContext: "This is John, a software engineer saving technical discussions",
|
||||
* metadata: { // Custom metadata
|
||||
* source: "voltagent",
|
||||
* version: "1.0"
|
||||
* }
|
||||
* })
|
||||
*
|
||||
* const agent = new Agent(configWithMemory)
|
||||
*
|
||||
* // Use the agent - memories are automatically injected
|
||||
* const result = await agent.generateText({
|
||||
* messages: [{ role: "user", content: "What's my favorite programming language?" }]
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* Custom prompt template:
|
||||
* ```typescript
|
||||
* const configWithMemory = withSupermemory({
|
||||
* agentConfig: {
|
||||
* name: "my-agent",
|
||||
* instructions: "...",
|
||||
* llm: new VercelAIProvider(),
|
||||
* model: openai("gpt-4o"),
|
||||
* },
|
||||
* containerTag: "user-123",
|
||||
* customId: "conversation-123",
|
||||
* mode: "full",
|
||||
* promptTemplate: (data) => `
|
||||
* <user_context>
|
||||
* ${data.userMemories}
|
||||
* ${data.generalSearchMemories}
|
||||
* </user_context>
|
||||
* `.trim()
|
||||
* })
|
||||
*
|
||||
* const agent = new Agent(configWithMemory)
|
||||
* ```
|
||||
*
|
||||
* @throws {Error} When neither `options.apiKey` nor `process.env.SUPERMEMORY_API_KEY` are set
|
||||
* @throws {Error} When Supermemory API request fails
|
||||
*/
|
||||
export function withSupermemory<T extends VoltAgentConfig>(
|
||||
options: WithSupermemoryOptions<T>,
|
||||
): T {
|
||||
const { agentConfig, containerTag, ...supermemoryOptions } = options
|
||||
|
||||
// Create Supermemory hooks (internally creates its own context, validates API key)
|
||||
const supermemoryHooks = createSupermemoryHooks(
|
||||
containerTag,
|
||||
supermemoryOptions,
|
||||
)
|
||||
|
||||
// Merge with existing hooks if present
|
||||
const mergedHooks = mergeHooks(agentConfig.hooks, supermemoryHooks)
|
||||
|
||||
// Return enhanced config with merged hooks
|
||||
return {
|
||||
...agentConfig,
|
||||
hooks: mergedHooks,
|
||||
}
|
||||
}
|
||||
|
||||
// Export types for consumers
|
||||
export type {
|
||||
SupermemoryVoltAgent,
|
||||
VoltAgentConfig,
|
||||
VoltAgentMessage,
|
||||
VoltAgentHooks,
|
||||
SearchFilters,
|
||||
IncludeOptions,
|
||||
PromptTemplate,
|
||||
MemoryMode,
|
||||
AddMemoryMode,
|
||||
MemoryPromptData,
|
||||
} from "./types"
|
||||
|
||||
export type { WithSupermemoryOptions }
|
||||
|
||||
// Note: WithSupermemoryOptions is exported above separately because it's generic
|
||||
|
||||
// Export hook creation utilities for advanced use cases
|
||||
export { createSupermemoryHooks } from "./hooks"
|
||||
481
packages/tools/src/voltagent/middleware.ts
Normal file
481
packages/tools/src/voltagent/middleware.ts
Normal file
|
|
@ -0,0 +1,481 @@
|
|||
/**
|
||||
* Middleware utilities for VoltAgent integration with Supermemory.
|
||||
*
|
||||
* Provides memory retrieval, injection, and storage functionality.
|
||||
*/
|
||||
|
||||
import Supermemory from "supermemory"
|
||||
import {
|
||||
addConversation,
|
||||
type ConversationMessage,
|
||||
} from "../conversations-client"
|
||||
import {
|
||||
createLogger,
|
||||
normalizeBaseUrl,
|
||||
MemoryCache,
|
||||
buildMemoriesText,
|
||||
extractQueryText,
|
||||
type Logger,
|
||||
type MemoryMode,
|
||||
} from "../shared"
|
||||
import type { SupermemoryVoltAgent, VoltAgentMessage } from "./types"
|
||||
|
||||
/**
|
||||
* Context for Supermemory middleware operations.
|
||||
*/
|
||||
export interface SupermemoryMiddlewareContext {
|
||||
client: Supermemory
|
||||
logger: Logger
|
||||
containerTag: string
|
||||
customId: string
|
||||
mode: MemoryMode
|
||||
addMemory: "always" | "never"
|
||||
normalizedBaseUrl: string
|
||||
apiKey: string
|
||||
promptTemplate?: (data: {
|
||||
userMemories: string
|
||||
generalSearchMemories: string
|
||||
searchResults: Array<{ memory: string; metadata?: Record<string, unknown> }>
|
||||
}) => string
|
||||
/**
|
||||
* Per-turn memory cache. Stores the injected memories string for each
|
||||
* user turn (keyed by turnKey) to avoid redundant API calls.
|
||||
*/
|
||||
memoryCache: MemoryCache<string>
|
||||
// New search parameters
|
||||
threshold?: number
|
||||
limit?: number
|
||||
rerank?: boolean
|
||||
rewriteQuery?: boolean
|
||||
filters?: { OR: Array<unknown> } | { AND: Array<unknown> }
|
||||
include?: {
|
||||
chunks?: boolean
|
||||
documents?: boolean
|
||||
forgottenMemories?: boolean
|
||||
relatedMemories?: boolean
|
||||
summaries?: boolean
|
||||
}
|
||||
// Storage parameters
|
||||
metadata?: Record<string, string | number | boolean>
|
||||
searchMode?: "memories" | "documents" | "hybrid"
|
||||
entityContext?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Supermemory middleware context.
|
||||
*/
|
||||
export const createSupermemoryContext = (
|
||||
containerTag: string,
|
||||
options: SupermemoryVoltAgent,
|
||||
): SupermemoryMiddlewareContext => {
|
||||
const apiKey = options.apiKey ?? process.env.SUPERMEMORY_API_KEY
|
||||
if (!apiKey) {
|
||||
throw new Error(
|
||||
"SUPERMEMORY_API_KEY is not set — provide it via `options.apiKey` or set `process.env.SUPERMEMORY_API_KEY`",
|
||||
)
|
||||
}
|
||||
|
||||
const {
|
||||
customId,
|
||||
mode = "profile",
|
||||
addMemory = "always", // VoltAgent default: save conversations by default for chat apps
|
||||
baseUrl,
|
||||
promptTemplate,
|
||||
threshold,
|
||||
limit,
|
||||
rerank,
|
||||
rewriteQuery,
|
||||
filters,
|
||||
include,
|
||||
metadata,
|
||||
searchMode,
|
||||
entityContext,
|
||||
} = options
|
||||
|
||||
// Runtime validation: customId is required
|
||||
if (!customId || typeof customId !== "string" || customId.trim() === "") {
|
||||
throw new Error(
|
||||
"customId is required and must be a non-empty string — provide it via `options.customId`",
|
||||
)
|
||||
}
|
||||
|
||||
const logger = createLogger(false) // VoltAgent SDK doesn't use verbose
|
||||
const normalizedBaseUrl = normalizeBaseUrl(baseUrl)
|
||||
|
||||
const client = new Supermemory({
|
||||
apiKey,
|
||||
...(normalizedBaseUrl !== "https://api.supermemory.ai"
|
||||
? { baseURL: normalizedBaseUrl }
|
||||
: {}),
|
||||
})
|
||||
|
||||
return {
|
||||
client,
|
||||
logger,
|
||||
containerTag,
|
||||
customId,
|
||||
mode,
|
||||
addMemory,
|
||||
normalizedBaseUrl,
|
||||
apiKey,
|
||||
promptTemplate,
|
||||
memoryCache: new MemoryCache<string>(),
|
||||
threshold,
|
||||
limit,
|
||||
rerank,
|
||||
rewriteQuery,
|
||||
filters,
|
||||
include,
|
||||
metadata,
|
||||
searchMode,
|
||||
entityContext,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a cache key for the current turn based on context and user message.
|
||||
*/
|
||||
const makeTurnKey = (
|
||||
ctx: SupermemoryMiddlewareContext,
|
||||
userMessage: string,
|
||||
): string => {
|
||||
return MemoryCache.makeTurnKey(
|
||||
ctx.containerTag,
|
||||
ctx.customId,
|
||||
ctx.mode,
|
||||
userMessage,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this is a new user turn (last message is from user).
|
||||
*/
|
||||
const isNewUserTurn = (messages: VoltAgentMessage[]): boolean => {
|
||||
const lastMessage = messages.at(-1)
|
||||
return lastMessage?.role === "user"
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the last user message text from messages array.
|
||||
*/
|
||||
const getLastUserMessage = (messages: VoltAgentMessage[]): string => {
|
||||
const lastUserMessage = messages
|
||||
.slice()
|
||||
.reverse()
|
||||
.find((msg) => msg.role === "user")
|
||||
|
||||
if (!lastUserMessage) {
|
||||
return ""
|
||||
}
|
||||
|
||||
const content = lastUserMessage.content
|
||||
|
||||
if (typeof content === "string") {
|
||||
return content
|
||||
}
|
||||
|
||||
if (Array.isArray(content)) {
|
||||
return content
|
||||
.filter((part) => part.type === "text")
|
||||
.map((part) => part.text || "")
|
||||
.join(" ")
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and injects memories into messages.
|
||||
* Returns enhanced messages with memories injected into system prompt.
|
||||
*
|
||||
* @param searchMessages - Messages to search for user input (VoltAgent's input messages)
|
||||
* @param ctx - Supermemory middleware context
|
||||
* @param systemMessages - System messages to inject memories into (VoltAgent's prepared messages)
|
||||
*/
|
||||
export const enhanceMessagesWithMemories = async (
|
||||
searchMessages: VoltAgentMessage[],
|
||||
ctx: SupermemoryMiddlewareContext,
|
||||
systemMessages?: VoltAgentMessage[],
|
||||
): Promise<VoltAgentMessage[]> => {
|
||||
const messagesToEnhance = systemMessages || searchMessages
|
||||
const messages = searchMessages
|
||||
|
||||
const userMessage = getLastUserMessage(messages)
|
||||
|
||||
if (ctx.mode !== "profile" && !userMessage) {
|
||||
ctx.logger.debug("No user message found, skipping memory search")
|
||||
return messagesToEnhance
|
||||
}
|
||||
|
||||
const turnKey = makeTurnKey(ctx, userMessage || "")
|
||||
const isNewTurn = isNewUserTurn(messages)
|
||||
|
||||
const cachedMemories = ctx.memoryCache.get(turnKey)
|
||||
if (!isNewTurn && cachedMemories) {
|
||||
ctx.logger.debug("Using cached memories", { turnKey })
|
||||
return injectMemoriesIntoMessages(
|
||||
messagesToEnhance,
|
||||
cachedMemories,
|
||||
ctx.logger,
|
||||
)
|
||||
}
|
||||
|
||||
ctx.logger.info("Starting memory search", {
|
||||
containerTag: ctx.containerTag,
|
||||
customId: ctx.customId,
|
||||
mode: ctx.mode,
|
||||
isNewTurn,
|
||||
})
|
||||
|
||||
const genericMessages = messages.map((msg) => ({
|
||||
role: msg.role,
|
||||
content: msg.content,
|
||||
}))
|
||||
|
||||
const queryText = extractQueryText(genericMessages, ctx.mode)
|
||||
|
||||
const useAdvancedSearch =
|
||||
ctx.threshold !== undefined ||
|
||||
ctx.limit !== undefined ||
|
||||
ctx.rerank !== undefined ||
|
||||
ctx.rewriteQuery !== undefined ||
|
||||
ctx.filters !== undefined ||
|
||||
ctx.include !== undefined ||
|
||||
ctx.searchMode !== undefined
|
||||
|
||||
let memories: string
|
||||
|
||||
if (useAdvancedSearch && ctx.mode !== "profile") {
|
||||
ctx.logger.info("Using advanced search with custom parameters")
|
||||
|
||||
const searchParams: {
|
||||
q: string
|
||||
containerTag: string
|
||||
threshold?: number
|
||||
limit?: number
|
||||
rerank?: boolean
|
||||
rewriteQuery?: boolean
|
||||
filters?: { OR: Array<unknown> } | { AND: Array<unknown> }
|
||||
include?: {
|
||||
chunks?: boolean
|
||||
documents?: boolean
|
||||
forgottenMemories?: boolean
|
||||
relatedMemories?: boolean
|
||||
summaries?: boolean
|
||||
}
|
||||
searchMode?: "memories" | "documents" | "hybrid"
|
||||
} = {
|
||||
q: queryText,
|
||||
containerTag: ctx.containerTag,
|
||||
}
|
||||
|
||||
if (ctx.threshold !== undefined) searchParams.threshold = ctx.threshold
|
||||
if (ctx.limit !== undefined) searchParams.limit = ctx.limit
|
||||
if (ctx.rerank !== undefined) searchParams.rerank = ctx.rerank
|
||||
if (ctx.rewriteQuery !== undefined)
|
||||
searchParams.rewriteQuery = ctx.rewriteQuery
|
||||
if (ctx.filters !== undefined) searchParams.filters = ctx.filters
|
||||
if (ctx.include !== undefined) searchParams.include = ctx.include
|
||||
if (ctx.searchMode !== undefined) searchParams.searchMode = ctx.searchMode
|
||||
|
||||
const response = await ctx.client.search.memories(searchParams)
|
||||
|
||||
// Hybrid search returns both memory entries (`memory` field) and
|
||||
// document chunks (`chunk` field). Handle both.
|
||||
type SearchResult = {
|
||||
memory?: string
|
||||
chunk?: string
|
||||
metadata?: Record<string, unknown>
|
||||
}
|
||||
const formattedMemories = response.results
|
||||
.map((result: SearchResult) => {
|
||||
const text = result.memory || result.chunk
|
||||
return text ? `- ${text}` : null
|
||||
})
|
||||
.filter(Boolean)
|
||||
.join("\n")
|
||||
|
||||
memories = ctx.promptTemplate
|
||||
? ctx.promptTemplate({
|
||||
userMemories: "",
|
||||
generalSearchMemories: formattedMemories,
|
||||
searchResults: response.results as Array<{
|
||||
memory: string
|
||||
metadata?: Record<string, unknown>
|
||||
}>,
|
||||
})
|
||||
: `The following are relevant memories and context about this user retrieved from previous interactions. Use these to personalize your response:\n\n${formattedMemories}`
|
||||
} else {
|
||||
memories = await buildMemoriesText({
|
||||
containerTag: ctx.containerTag,
|
||||
queryText,
|
||||
mode: ctx.mode,
|
||||
baseUrl: ctx.normalizedBaseUrl,
|
||||
apiKey: ctx.apiKey,
|
||||
logger: ctx.logger,
|
||||
promptTemplate: ctx.promptTemplate,
|
||||
})
|
||||
}
|
||||
|
||||
ctx.memoryCache.set(turnKey, memories)
|
||||
ctx.logger.debug("Cached memories for turn", { turnKey })
|
||||
|
||||
return injectMemoriesIntoMessages(messagesToEnhance, memories, ctx.logger)
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects memories into messages by appending to existing system prompt
|
||||
* or creating a new one. Pure function - does not mutate the original messages.
|
||||
*
|
||||
* VoltAgent uses AI SDK v5's UIMessage format which requires `id` and `parts`
|
||||
* (not just `content`). We must conform to this format for messages to
|
||||
* actually reach the LLM.
|
||||
*/
|
||||
const injectMemoriesIntoMessages = (
|
||||
messages: VoltAgentMessage[],
|
||||
memories: string,
|
||||
logger: Logger,
|
||||
): VoltAgentMessage[] => {
|
||||
const systemMessageIndex = messages.findIndex((msg) => msg.role === "system")
|
||||
|
||||
if (systemMessageIndex !== -1) {
|
||||
logger.debug("Added memories to existing system message")
|
||||
const newMessages = [...messages]
|
||||
const systemMessage = newMessages[systemMessageIndex]
|
||||
if (!systemMessage) {
|
||||
return messages
|
||||
}
|
||||
|
||||
// Extract existing text from parts (UIMessage format) or content fallback
|
||||
const parts = (
|
||||
systemMessage as { parts?: Array<{ type: string; text?: string }> }
|
||||
).parts
|
||||
const existingContent = parts
|
||||
? parts
|
||||
.filter((p) => p.type === "text")
|
||||
.map((p) => p.text || "")
|
||||
.join("\n")
|
||||
: typeof systemMessage.content === "string"
|
||||
? systemMessage.content
|
||||
: ""
|
||||
|
||||
const newContent = `${existingContent}\n\n${memories}`
|
||||
|
||||
newMessages[systemMessageIndex] = {
|
||||
...systemMessage,
|
||||
content: newContent,
|
||||
// Update parts array to match - this is what the LLM actually reads
|
||||
parts: [{ type: "text", text: newContent }],
|
||||
} as VoltAgentMessage
|
||||
return newMessages
|
||||
}
|
||||
|
||||
logger.debug("Created system message with memories")
|
||||
return [
|
||||
{
|
||||
id: crypto.randomUUID(),
|
||||
role: "system" as const,
|
||||
content: memories,
|
||||
parts: [{ type: "text", text: memories }],
|
||||
} as VoltAgentMessage,
|
||||
...messages,
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts VoltAgent messages to conversation format for storage.
|
||||
*/
|
||||
const convertToConversationMessages = (
|
||||
messages: VoltAgentMessage[],
|
||||
): ConversationMessage[] => {
|
||||
const conversationMessages: ConversationMessage[] = []
|
||||
|
||||
for (const msg of messages) {
|
||||
if (msg.role === "system") {
|
||||
continue
|
||||
}
|
||||
|
||||
if (typeof msg.content === "string") {
|
||||
if (msg.content) {
|
||||
conversationMessages.push({
|
||||
role: msg.role as "user" | "assistant" | "tool",
|
||||
content: msg.content,
|
||||
})
|
||||
}
|
||||
} else if (Array.isArray(msg.content)) {
|
||||
const contentParts = msg.content
|
||||
.map((c) => {
|
||||
if (c.type === "text" && c.text) {
|
||||
return {
|
||||
type: "text" as const,
|
||||
text: c.text,
|
||||
}
|
||||
}
|
||||
// Handle image URLs if present
|
||||
if (c.type === "image_url" && typeof c.image_url === "object") {
|
||||
const imageUrl = c.image_url as { url?: string }
|
||||
if (imageUrl.url) {
|
||||
return {
|
||||
type: "image_url" as const,
|
||||
image_url: { url: imageUrl.url },
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
})
|
||||
.filter((part) => part !== null)
|
||||
|
||||
if (contentParts.length > 0) {
|
||||
conversationMessages.push({
|
||||
role: msg.role as "user" | "assistant" | "tool",
|
||||
content: contentParts,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return conversationMessages
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves conversation to Supermemory (fire-and-forget).
|
||||
*/
|
||||
export const saveConversation = async (
|
||||
messages: VoltAgentMessage[],
|
||||
ctx: SupermemoryMiddlewareContext,
|
||||
): Promise<void> => {
|
||||
if (ctx.addMemory !== "always") {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const conversationMessages = convertToConversationMessages(messages)
|
||||
|
||||
if (conversationMessages.length === 0) {
|
||||
ctx.logger.debug("No messages to save")
|
||||
return
|
||||
}
|
||||
|
||||
const response = await addConversation({
|
||||
conversationId: ctx.customId,
|
||||
messages: conversationMessages,
|
||||
containerTags: [ctx.containerTag],
|
||||
metadata: ctx.metadata,
|
||||
entityContext: ctx.entityContext,
|
||||
apiKey: ctx.apiKey,
|
||||
baseUrl: ctx.normalizedBaseUrl,
|
||||
})
|
||||
|
||||
ctx.logger.info("Conversation saved successfully via /v4/conversations", {
|
||||
containerTag: ctx.containerTag,
|
||||
customId: ctx.customId,
|
||||
messageCount: conversationMessages.length,
|
||||
responseId: response.id,
|
||||
metadata: ctx.metadata,
|
||||
})
|
||||
} catch (error) {
|
||||
ctx.logger.error("Error saving conversation", {
|
||||
error: error instanceof Error ? error.message : "Unknown error",
|
||||
})
|
||||
}
|
||||
}
|
||||
210
packages/tools/src/voltagent/types.ts
Normal file
210
packages/tools/src/voltagent/types.ts
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
/**
|
||||
* Type definitions for VoltAgent integration.
|
||||
*
|
||||
* VoltAgent uses hooks to intercept and modify agent behavior. We integrate
|
||||
* Supermemory by providing hooks that inject memories before LLM calls.
|
||||
*/
|
||||
|
||||
import type {
|
||||
PromptTemplate,
|
||||
MemoryMode,
|
||||
AddMemoryMode,
|
||||
MemoryPromptData,
|
||||
SupermemoryBaseOptions,
|
||||
} from "../shared"
|
||||
|
||||
/**
|
||||
* Configuration options for the Supermemory VoltAgent integration.
|
||||
* Extends base options with VoltAgent-specific settings.
|
||||
*/
|
||||
export interface SupermemoryVoltAgent
|
||||
extends Omit<SupermemoryBaseOptions, "verbose"> {
|
||||
/**
|
||||
* Custom ID to group messages into a single document.
|
||||
* Ensures related messages are added to the same document for that conversation.
|
||||
*/
|
||||
customId: string
|
||||
|
||||
/**
|
||||
* Threshold / sensitivity for memory selection. 0 is least sensitive (returns
|
||||
* most memories, more results), 1 is most sensitive (returns fewer memories,
|
||||
* more accurate results). Default: 0.1
|
||||
*/
|
||||
threshold?: number
|
||||
|
||||
/**
|
||||
* Maximum number of memory results to return. Default: 10
|
||||
*/
|
||||
limit?: number
|
||||
|
||||
/**
|
||||
* If true, rerank the results based on the query. This helps ensure the most
|
||||
* relevant results are returned. Default: false
|
||||
*/
|
||||
rerank?: boolean
|
||||
|
||||
/**
|
||||
* If true, rewrites the query to make it easier to find memories. This increases
|
||||
* latency by about 400ms. Default: false
|
||||
*/
|
||||
rewriteQuery?: boolean
|
||||
|
||||
/**
|
||||
* Advanced filters to apply to the search using AND/OR logic.
|
||||
* Example: { OR: [{ metadata: { type: "note" } }, { metadata: { type: "conversation" } }] }
|
||||
*/
|
||||
filters?: SearchFilters
|
||||
|
||||
/**
|
||||
* Control what additional data to include in search results
|
||||
*/
|
||||
include?: IncludeOptions
|
||||
|
||||
/**
|
||||
* Optional metadata to attach to saved documents/conversations.
|
||||
* Can include strings, numbers, or booleans.
|
||||
*/
|
||||
metadata?: Record<string, string | number | boolean>
|
||||
|
||||
/**
|
||||
* Search mode controlling what type of results to search.
|
||||
* - "memories": Search only memory entries (atomic facts)
|
||||
* - "documents": Search only document chunks
|
||||
* - "hybrid": Search both memories AND document chunks (recommended)
|
||||
*/
|
||||
searchMode?: "memories" | "documents" | "hybrid"
|
||||
|
||||
/**
|
||||
* Context for memory extraction when saving conversations.
|
||||
* Helps guide how memories are extracted and understood from content.
|
||||
* Max 1500 characters.
|
||||
* Example: "This is John, saving items in a personal knowledge management system"
|
||||
*/
|
||||
entityContext?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Advanced search filters using AND/OR logic
|
||||
*/
|
||||
export type SearchFilters = { OR: Array<unknown> } | { AND: Array<unknown> }
|
||||
|
||||
/**
|
||||
* Options for including additional data in search results
|
||||
*/
|
||||
export interface IncludeOptions {
|
||||
/**
|
||||
* If true, fetch and return chunks from documents associated with found memories.
|
||||
* Performs vector search on chunks within those documents.
|
||||
*/
|
||||
chunks?: boolean
|
||||
|
||||
/**
|
||||
* If true, include full document information in results
|
||||
*/
|
||||
documents?: boolean
|
||||
|
||||
/**
|
||||
* If true, include forgotten memories in search results. Forgotten memories are
|
||||
* memories that have been explicitly forgotten or have passed their expiration date.
|
||||
*/
|
||||
forgottenMemories?: boolean
|
||||
|
||||
/**
|
||||
* If true, include related memories (parents/children in the memory graph)
|
||||
*/
|
||||
relatedMemories?: boolean
|
||||
|
||||
/**
|
||||
* If true, include document summaries in results
|
||||
*/
|
||||
summaries?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* VoltAgent message format (simplified to avoid direct dependency).
|
||||
* Compatible with VoltAgent's Message type.
|
||||
*/
|
||||
export interface VoltAgentMessage {
|
||||
role: "system" | "user" | "assistant" | "tool"
|
||||
content:
|
||||
| string
|
||||
| Array<{ type: string; text?: string; [key: string]: unknown }>
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimal VoltAgent AgentConfig interface representing properties we enhance.
|
||||
* This avoids a direct dependency on @voltagent/core while staying type-safe.
|
||||
*/
|
||||
export interface VoltAgentConfig {
|
||||
name: string
|
||||
instructions?: string
|
||||
model?: unknown
|
||||
llm?: unknown
|
||||
hooks?: VoltAgentHooks
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
/**
|
||||
* VoltAgent hooks interface (simplified).
|
||||
* Hooks allow intercepting agent lifecycle events.
|
||||
*/
|
||||
export interface VoltAgentHooks {
|
||||
onStart?: (args: HookStartArgs) => void | Promise<void>
|
||||
onPrepareMessages?: (
|
||||
args: HookPrepareMessagesArgs,
|
||||
) =>
|
||||
| { messages?: VoltAgentMessage[] }
|
||||
| Promise<{ messages?: VoltAgentMessage[] }>
|
||||
onEnd?: (args: HookEndArgs) => void | Promise<void>
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments passed to onStart hook.
|
||||
*/
|
||||
export interface HookStartArgs {
|
||||
agent: {
|
||||
name: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
context?: {
|
||||
messages?: VoltAgentMessage[]
|
||||
[key: string]: unknown
|
||||
}
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments passed to onPrepareMessages hook.
|
||||
*/
|
||||
export interface HookPrepareMessagesArgs {
|
||||
messages: VoltAgentMessage[]
|
||||
agent: {
|
||||
name: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
context?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments passed to onEnd hook.
|
||||
*/
|
||||
export interface HookEndArgs {
|
||||
agent: {
|
||||
name: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
context?: {
|
||||
input?: unknown
|
||||
[key: string]: unknown
|
||||
}
|
||||
output?: unknown
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
// Re-export shared types for convenience
|
||||
export type { PromptTemplate, MemoryMode, AddMemoryMode, MemoryPromptData }
|
||||
|
|
@ -7,6 +7,7 @@ export default defineConfig({
|
|||
"src/claude-memory.ts",
|
||||
"src/openai/index.ts",
|
||||
"src/mastra.ts",
|
||||
"src/voltagent/index.ts",
|
||||
],
|
||||
format: "esm",
|
||||
sourcemap: false,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue