#!/usr/bin/env bun /** * Anthropic SDK Example with Claude Memory Tool * Shows how to use the memory tool with the official Anthropic SDK */ import Anthropic from "@anthropic-ai/sdk" import { createClaudeMemoryTool } from "./claude-memory" import "dotenv/config" /** * Handle Claude's memory tool calls using the Anthropic SDK */ async function chatWithMemoryTool() { console.log("๐Ÿค– Anthropic SDK Example - Claude with Memory Tool") console.log("=".repeat(50)) const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY const SUPERMEMORY_API_KEY = process.env.SUPERMEMORY_API_KEY if (!ANTHROPIC_API_KEY || !SUPERMEMORY_API_KEY) { console.error("โŒ Missing required API keys:") console.error("- ANTHROPIC_API_KEY") console.error("- SUPERMEMORY_API_KEY") return } // Initialize Anthropic client const anthropic = new Anthropic({ apiKey: ANTHROPIC_API_KEY, }) // Initialize memory tool const memoryTool = createClaudeMemoryTool(SUPERMEMORY_API_KEY, { projectId: "anthropic-sdk-demo", memoryContainerTag: "claude_memory_anthropic", }) // Conversation messages const messages: Anthropic.Messages.MessageParam[] = [ { role: "user", content: "Hi Claude! I'm working on a new React project using TypeScript and I want you to remember my preferences. Can you help me debug some code later?", }, ] console.log("๐Ÿ’ฌ User:", messages[0].content) console.log("\n๐Ÿ”„ Sending to Claude with memory tool...") try { // Make initial request to Claude with memory tool const response = await anthropic.beta.messages.create({ model: "claude-sonnet-4-5", max_tokens: 2048, messages: messages, tools: [ { type: "memory_20250818", name: "memory", }, ], betas: ["context-management-2025-06-27"], }) console.log("๐Ÿ“ฅ Claude responded:") // Process the response const toolResults: Anthropic.Messages.ToolResultBlockParam[] = [] for (const block of response.content) { if (block.type === "text") { console.log("๐Ÿ’ญ", block.text) } else if (block.type === "tool_use" && block.name === "memory") { console.log("๐Ÿ”ง Claude is using memory tool:") console.log(" Command:", block.input.command) console.log(" Path:", block.input.path) // Handle the memory tool call const memoryResult = await memoryTool.handleCommand(block.input as any) const toolResult: Anthropic.Messages.ToolResultBlockParam = { type: "tool_result", tool_use_id: block.id, content: memoryResult.success ? memoryResult.content || "Operation completed successfully" : `Error: ${memoryResult.error}`, is_error: !memoryResult.success, } toolResults.push(toolResult) console.log( "๐Ÿ“Š Memory operation result:", memoryResult.success ? "โœ… Success" : "โŒ Failed", ) if (memoryResult.content) { console.log( "๐Ÿ“„ Content preview:", memoryResult.content.substring(0, 100) + "...", ) } } } // If Claude used memory tools, send the results back if (toolResults.length > 0) { console.log("\n๐Ÿ”„ Sending tool results back to Claude...") // Add Claude's response to conversation messages.push({ role: "assistant", content: response.content, }) // Add tool results messages.push({ role: "user", content: toolResults, }) const finalResponse = await anthropic.beta.messages.create({ model: "claude-sonnet-4-5", max_tokens: 2048, messages: messages, tools: [ { type: "memory_20250818", name: "memory", }, ], betas: ["context-management-2025-06-27"], }) console.log("๐Ÿ“ฅ Claude's final response:") for (const block of finalResponse.content) { if (block.type === "text") { console.log("๐Ÿ’ญ", block.text) } else if (block.type === "tool_use" && block.name === "memory") { console.log("๐Ÿ”ง Claude is using memory tool again:") console.log(" Command:", block.input.command) console.log(" Path:", block.input.path) // Handle additional memory tool calls const memoryResult = await memoryTool.handleCommand( block.input as any, ) console.log( "๐Ÿ“Š Memory operation result:", memoryResult.success ? "โœ… Success" : "โŒ Failed", ) } } } console.log("\nโœจ Conversation completed!") console.log("\n๐Ÿ“‹ Usage statistics:") console.log("- Input tokens:", response.usage.input_tokens) console.log("- Output tokens:", response.usage.output_tokens) console.log("- Memory operations:", toolResults.length) } catch (error) { console.error("โŒ Error:", error) } } /** * Test memory tool operations directly */ async function testMemoryOperations() { console.log("\n๐Ÿงช Testing Memory Operations Directly") console.log("=".repeat(50)) if (!process.env.SUPERMEMORY_API_KEY) { console.error("โŒ SUPERMEMORY_API_KEY is required") return } const memoryTool = createClaudeMemoryTool(process.env.SUPERMEMORY_API_KEY, { projectId: "direct-test", memoryContainerTag: "claude_memory_direct", }) const testCases = [ { name: "View empty memory directory", command: { command: "view" as const, path: "/memories" }, }, { name: "Create user preferences file", command: { command: "create" as const, path: "/memories/user-preferences.md", file_text: "# User Preferences\n\n- Prefers React with TypeScript\n- Likes clean, readable code\n- Uses functional programming style\n- Prefers ESLint and Prettier for code formatting", }, }, { name: "Create project notes", command: { command: "create" as const, path: "/memories/project-notes.txt", file_text: "Current Project: React TypeScript App\n\nFeatures to implement:\n1. User authentication\n2. Dashboard with widgets\n3. Data visualization\n4. Export functionality\n\nTech stack:\n- React 18\n- TypeScript\n- Vite\n- Tailwind CSS", }, }, { name: "List directory contents", command: { command: "view" as const, path: "/memories/" }, }, { name: "Read user preferences", command: { command: "view" as const, path: "/memories/user-preferences.md", }, }, { name: "Update preferences (add VS Code)", command: { command: "str_replace" as const, path: "/memories/user-preferences.md", old_str: "- Prefers ESLint and Prettier for code formatting", new_str: "- Prefers ESLint and Prettier for code formatting\n- Uses VS Code as primary editor\n- Likes GitHub Copilot for code completion", }, }, { name: "Insert new task in project notes", command: { command: "insert" as const, path: "/memories/project-notes.txt", insert_line: 6, insert_text: "5. Unit testing with Jest and React Testing Library", }, }, { name: "Read updated project notes", command: { command: "view" as const, path: "/memories/project-notes.txt", view_range: [4, 8], }, }, ] for (const testCase of testCases) { console.log(`\n๐Ÿ” ${testCase.name}`) try { const result = await memoryTool.handleCommand(testCase.command) if (result.success) { console.log("โœ… Success") if (result.content && result.content.length <= 200) { console.log("๐Ÿ“„ Result:", result.content) } else if (result.content) { console.log( "๐Ÿ“„ Result:", result.content.substring(0, 150) + "... (truncated)", ) } } else { console.log("โŒ Failed") console.log("๐Ÿ“„ Error:", result.error) } } catch (error) { console.log("๐Ÿ’ฅ Exception:", error) } // Small delay to avoid rate limiting await new Promise((resolve) => setTimeout(resolve, 300)) } } // Run the examples async function main() { await testMemoryOperations() console.log("\n" + "=".repeat(70) + "\n") await chatWithMemoryTool() } if (import.meta.main) { main().catch(console.error) }