diff options
Diffstat (limited to 'packages/tools/src/openai/tools.ts')
| -rw-r--r-- | packages/tools/src/openai/tools.ts | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/packages/tools/src/openai/tools.ts b/packages/tools/src/openai/tools.ts new file mode 100644 index 00000000..4078df09 --- /dev/null +++ b/packages/tools/src/openai/tools.ts @@ -0,0 +1,276 @@ +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<ReturnType<Supermemory["search"]["execute"]>>["results"] + count?: number + error?: string +} + +export interface MemoryAddResult { + success: boolean + memory?: Awaited<ReturnType<Supermemory["memories"]["add"]>> + 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<MemorySearchResult> { + 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<MemoryAddResult> { + try { + const metadata: Record<string, string | number | boolean> = {} + + 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<string> { + 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<OpenAI.Chat.Completions.ChatCompletionToolMessageParam[]> { + 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, + } +} |