import type OpenAI from "openai" import Supermemory from "supermemory" import { DEFAULT_VALUES, PARAMETER_DESCRIPTIONS, TOOL_DESCRIPTIONS, getContainerTags, } from "../shared" import type { SupermemoryToolsConfig } from "../types" /** * Result types for memory operations */ export interface MemorySearchResult { success: boolean results?: Awaited>["results"] count?: number error?: string } export interface MemoryAddResult { success: boolean memory?: Awaited> error?: string } /** * Function schemas for OpenAI function calling */ export const memoryToolSchemas = { searchMemories: { name: "searchMemories", description: TOOL_DESCRIPTIONS.searchMemories, parameters: { type: "object", properties: { informationToGet: { type: "string", description: PARAMETER_DESCRIPTIONS.informationToGet, }, includeFullDocs: { type: "boolean", description: PARAMETER_DESCRIPTIONS.includeFullDocs, default: DEFAULT_VALUES.includeFullDocs, }, limit: { type: "number", description: PARAMETER_DESCRIPTIONS.limit, default: DEFAULT_VALUES.limit, }, }, required: ["informationToGet"], }, } satisfies OpenAI.FunctionDefinition, addMemory: { name: "addMemory", description: TOOL_DESCRIPTIONS.addMemory, parameters: { type: "object", properties: { memory: { type: "string", description: PARAMETER_DESCRIPTIONS.memory, }, }, required: ["memory"], }, } satisfies OpenAI.FunctionDefinition, } as const /** * Create a Supermemory client with configuration */ function createClient(apiKey: string, config?: SupermemoryToolsConfig) { const client = new Supermemory({ apiKey, ...(config?.baseUrl && { baseURL: config.baseUrl }), }) const containerTags = getContainerTags(config) return { client, containerTags } } /** * Search memories function */ export function createSearchMemoriesFunction( apiKey: string, config?: SupermemoryToolsConfig, ) { const { client, containerTags } = createClient(apiKey, config) return async function searchMemories({ informationToGet, includeFullDocs = DEFAULT_VALUES.includeFullDocs, limit = DEFAULT_VALUES.limit, }: { informationToGet: string includeFullDocs?: boolean limit?: number }): Promise { try { const response = await client.search.execute({ q: informationToGet, containerTags, limit, chunkThreshold: DEFAULT_VALUES.chunkThreshold, includeFullDocs, }) return { success: true, results: response.results, count: response.results?.length || 0, } } catch (error) { return { success: false, error: error instanceof Error ? error.message : "Unknown error", } } } } /** * Add memory function */ export function createAddMemoryFunction( apiKey: string, config?: SupermemoryToolsConfig, ) { const { client, containerTags } = createClient(apiKey, config) return async function addMemory({ memory, }: { memory: string }): Promise { try { const metadata: Record = {} const response = await client.memories.add({ content: memory, containerTags, ...(Object.keys(metadata).length > 0 && { metadata }), }) return { success: true, memory: response, } } catch (error) { return { success: false, error: error instanceof Error ? error.message : "Unknown error", } } } } /** * Create all memory tools functions */ export function supermemoryTools( apiKey: string, config?: SupermemoryToolsConfig, ) { const searchMemories = createSearchMemoriesFunction(apiKey, config) const addMemory = createAddMemoryFunction(apiKey, config) return { searchMemories, addMemory, } } /** * Get OpenAI function definitions for all memory tools */ export function getToolDefinitions(): OpenAI.Chat.Completions.ChatCompletionTool[] { return [ { type: "function", function: memoryToolSchemas.searchMemories }, { type: "function", function: memoryToolSchemas.addMemory }, ] } /** * Execute a tool call based on the function name and arguments */ export function createToolCallExecutor( apiKey: string, config?: SupermemoryToolsConfig, ) { const tools = supermemoryTools(apiKey, config) return async function executeToolCall( toolCall: OpenAI.Chat.Completions.ChatCompletionMessageToolCall, ): Promise { const functionName = toolCall.function.name const args = JSON.parse(toolCall.function.arguments) switch (functionName) { case "searchMemories": return JSON.stringify(await tools.searchMemories(args)) case "addMemory": return JSON.stringify(await tools.addMemory(args)) default: return JSON.stringify({ success: false, error: `Unknown function: ${functionName}`, }) } } } /** * Execute tool calls from OpenAI function calling */ export function createToolCallsExecutor( apiKey: string, config?: SupermemoryToolsConfig, ) { const executeToolCall = createToolCallExecutor(apiKey, config) return async function executeToolCalls( toolCalls: OpenAI.Chat.Completions.ChatCompletionMessageToolCall[], ): Promise { const results = await Promise.all( toolCalls.map(async (toolCall) => { const result = await executeToolCall(toolCall) return { tool_call_id: toolCall.id, role: "tool" as const, content: result, } }), ) return results } } /** * Individual tool creators for more granular control */ export function createSearchMemoriesTool( apiKey: string, config?: SupermemoryToolsConfig, ) { const searchMemories = createSearchMemoriesFunction(apiKey, config) return { definition: { type: "function" as const, function: memoryToolSchemas.searchMemories, }, execute: searchMemories, } } export function createAddMemoryTool( apiKey: string, config?: SupermemoryToolsConfig, ) { const addMemory = createAddMemoryFunction(apiKey, config) return { definition: { type: "function" as const, function: memoryToolSchemas.addMemory, }, execute: addMemory, } }