diff --git a/packages/tools/test-supermemory.ts b/packages/tools/test-supermemory.ts index b3863c7ea..628968fee 100644 --- a/packages/tools/test-supermemory.ts +++ b/packages/tools/test-supermemory.ts @@ -10,7 +10,9 @@ const openai = new OpenAI({ }) // Wrap OpenAI client with supermemory -const openaiWithSupermemory = withSupermemory(openai, "test_user_123", { +const openaiWithSupermemory = withSupermemory(openai, { + containerTag: "test_user_123", + customId: "test_user_123_chat", verbose: true, // Enable logging to see what's happening mode: "full", // Search both profile and query memories addMemory: "always", // Auto-save conversations as memories diff --git a/packages/tools/test/anthropic-example.ts b/packages/tools/test/anthropic-example.ts index 0da95b77b..a4d1d9fef 100644 --- a/packages/tools/test/anthropic-example.ts +++ b/packages/tools/test/anthropic-example.ts @@ -5,9 +5,33 @@ */ import Anthropic from "@anthropic-ai/sdk" -import { createClaudeMemoryTool } from "./claude-memory" +import { + createClaudeMemoryTool, + type MemoryCommand, +} from "../src/claude-memory" import "dotenv/config" +const MEMORY_COMMANDS: readonly string[] = [ + "view", + "create", + "str_replace", + "insert", + "delete", + "rename", +] + +function isMemoryCommand(input: unknown): input is MemoryCommand { + return ( + typeof input === "object" && + input !== null && + "command" in input && + "path" in input && + typeof input.command === "string" && + MEMORY_COMMANDS.includes(input.command) && + typeof input.path === "string" + ) +} + /** * Handle Claude's memory tool calls using the Anthropic SDK */ @@ -37,7 +61,7 @@ async function chatWithMemoryTool() { }) // Conversation messages - const messages: Anthropic.Messages.MessageParam[] = [ + const messages: Anthropic.Beta.Messages.BetaMessageParam[] = [ { role: "user", content: @@ -45,7 +69,7 @@ async function chatWithMemoryTool() { }, ] - console.log("šŸ’¬ User:", messages[0].content) + console.log("šŸ’¬ User:", messages[0]?.content) console.log("\nšŸ”„ Sending to Claude with memory tool...") try { @@ -66,20 +90,25 @@ async function chatWithMemoryTool() { console.log("šŸ“„ Claude responded:") // Process the response - const toolResults: Anthropic.Messages.ToolResultBlockParam[] = [] + const toolResults: Anthropic.Beta.Messages.BetaToolResultBlockParam[] = [] for (const block of response.content) { if (block.type === "text") { console.log("šŸ’­", block.text) } else if (block.type === "tool_use" && block.name === "memory") { + const command = block.input + if (!isMemoryCommand(command)) { + console.log("Skipping unrecognized memory tool input:", command) + continue + } console.log("šŸ”§ Claude is using memory tool:") - console.log(" Command:", block.input.command) - console.log(" Path:", block.input.path) + console.log(" Command:", command.command) + console.log(" Path:", command.path) // Handle the memory tool call - const memoryResult = await memoryTool.handleCommand(block.input as any) + const memoryResult = await memoryTool.handleCommand(command) - const toolResult: Anthropic.Messages.ToolResultBlockParam = { + const toolResult: Anthropic.Beta.Messages.BetaToolResultBlockParam = { type: "tool_result", tool_use_id: block.id, content: memoryResult.success @@ -138,14 +167,17 @@ async function chatWithMemoryTool() { if (block.type === "text") { console.log("šŸ’­", block.text) } else if (block.type === "tool_use" && block.name === "memory") { + const command = block.input + if (!isMemoryCommand(command)) { + console.log("Skipping unrecognized memory tool input:", command) + continue + } console.log("šŸ”§ Claude is using memory tool again:") - console.log(" Command:", block.input.command) - console.log(" Path:", block.input.path) + console.log(" Command:", command.command) + console.log(" Path:", command.path) // Handle additional memory tool calls - const memoryResult = await memoryTool.handleCommand( - block.input as any, - ) + const memoryResult = await memoryTool.handleCommand(command) console.log( "šŸ“Š Memory operation result:", memoryResult.success ? "āœ… Success" : "āŒ Failed", @@ -239,7 +271,7 @@ async function testMemoryOperations() { command: { command: "view" as const, path: "/memories/project-notes.txt", - view_range: [4, 8], + view_range: [4, 8] as [number, number], }, }, ] diff --git a/packages/tools/test/claude-memory-examples.ts b/packages/tools/test/claude-memory-examples.ts index f37a47fad..4336f1e91 100644 --- a/packages/tools/test/claude-memory-examples.ts +++ b/packages/tools/test/claude-memory-examples.ts @@ -6,7 +6,10 @@ * 2. Anthropic SDK integration */ -import { createClaudeMemoryTool, type MemoryCommand } from "./claude-memory" +import { + createClaudeMemoryTool, + type MemoryCommand, +} from "../src/claude-memory" // ===================================================== // Example 1: Direct TypeScript/fetch Integration @@ -67,8 +70,7 @@ export async function directFetchExample() { ] // Execute each command - for (let i = 0; i < commands.length; i++) { - const command = commands[i] + for (const [i, command] of commands.entries()) { console.log( `\nšŸ“ Step ${i + 1}: ${command.command.toUpperCase()} ${command.path}`, ) diff --git a/packages/tools/test/claude-memory-real-example.ts b/packages/tools/test/claude-memory-real-example.ts index dbd03b21b..1a925669a 100644 --- a/packages/tools/test/claude-memory-real-example.ts +++ b/packages/tools/test/claude-memory-real-example.ts @@ -4,7 +4,10 @@ * This shows actual tool call handling based on real Claude API responses */ -import { createClaudeMemoryTool, type MemoryCommand } from "./claude-memory" +import { + createClaudeMemoryTool, + type MemoryCommand, +} from "../src/claude-memory" // ===================================================== // Real Claude API Integration diff --git a/packages/tools/test/claude-memory.test.ts b/packages/tools/test/claude-memory.test.ts index 97bccd902..f00c95073 100644 --- a/packages/tools/test/claude-memory.test.ts +++ b/packages/tools/test/claude-memory.test.ts @@ -1,5 +1,8 @@ import { describe, it, expect, beforeEach } from "vitest" -import { createClaudeMemoryTool, type MemoryCommand } from "./claude-memory" +import { + createClaudeMemoryTool, + type MemoryCommand, +} from "../src/claude-memory" import "dotenv/config" // Test configuration @@ -10,6 +13,10 @@ const TEST_CONFIG = { memoryContainerTag: "claude_memory_test", } +// Same gate the other integration suites use: these hit the live API, so they +// only run when a key is present. Without one every request comes back 401. +const shouldRunIntegration = !!process.env.SUPERMEMORY_API_KEY + describe("Claude Memory Tool", () => { let memoryTool: ReturnType @@ -62,7 +69,7 @@ describe("Claude Memory Tool", () => { }) }) - describe("File operations", () => { + describe.skipIf(!shouldRunIntegration)("File operations", () => { const testFilePath = "/memories/test-file.txt" const testContent = "Hello, World!\nThis is a test file.\nLine 3 here." @@ -219,7 +226,7 @@ describe("Claude Memory Tool", () => { }) }) - describe("Directory operations", () => { + describe.skipIf(!shouldRunIntegration)("Directory operations", () => { it("should list empty directory", async () => { const result = await memoryTool.handleCommand({ command: "view", @@ -263,7 +270,7 @@ describe("Claude Memory Tool", () => { }) }) - describe("Error handling", () => { + describe.skipIf(!shouldRunIntegration)("Error handling", () => { it("should handle missing file", async () => { const result = await memoryTool.handleCommand({ command: "view", diff --git a/packages/tools/test/mastra/integration.test.ts b/packages/tools/test/mastra/integration.test.ts index 58b79a61d..4f602f29c 100644 --- a/packages/tools/test/mastra/integration.test.ts +++ b/packages/tools/test/mastra/integration.test.ts @@ -120,6 +120,7 @@ describe.skipIf(!shouldRunIntegration)( messageList, abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processInput(args) @@ -152,6 +153,7 @@ describe.skipIf(!shouldRunIntegration)( messageList, abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processInput(args) @@ -191,6 +193,7 @@ describe.skipIf(!shouldRunIntegration)( messageList, abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processInput(args) @@ -233,6 +236,7 @@ describe.skipIf(!shouldRunIntegration)( messageList: createIntegrationMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processInput(args1) @@ -247,6 +251,7 @@ describe.skipIf(!shouldRunIntegration)( messageList: createIntegrationMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processInput(args2) @@ -282,6 +287,7 @@ describe.skipIf(!shouldRunIntegration)( messageList, abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processInput(args) @@ -313,6 +319,7 @@ describe.skipIf(!shouldRunIntegration)( messageList: createIntegrationMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processOutputResult(args) @@ -346,6 +353,7 @@ describe.skipIf(!shouldRunIntegration)( messageList: createIntegrationMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processOutputResult(args) @@ -383,6 +391,7 @@ describe.skipIf(!shouldRunIntegration)( messageList: createIntegrationMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, requestContext, } @@ -417,6 +426,7 @@ describe.skipIf(!shouldRunIntegration)( messageList, abort: vi.fn() as never, retryCount: 0, + state: {}, } await input.processInput(inputArgs) @@ -430,6 +440,7 @@ describe.skipIf(!shouldRunIntegration)( messageList: createIntegrationMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await output.processOutputResult(outputArgs) @@ -470,6 +481,7 @@ describe.skipIf(!shouldRunIntegration)( messageList, abort: vi.fn() as never, retryCount: 0, + state: {}, } await inputProcessor.processInput(args) @@ -534,6 +546,7 @@ describe.skipIf(!shouldRunIntegration)( messageList, abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processInput(args) @@ -558,6 +571,7 @@ describe.skipIf(!shouldRunIntegration)( messageList: createIntegrationMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processInput(args) @@ -592,6 +606,7 @@ describe.skipIf(!shouldRunIntegration)( messageList, abort: vi.fn() as never, retryCount: 0, + state: {}, } const result = await processor.processInput(args) @@ -616,6 +631,7 @@ describe.skipIf(!shouldRunIntegration)( messageList: createIntegrationMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await expect(processor.processOutputResult(args)).resolves.toBeDefined() diff --git a/packages/tools/test/mastra/unit.test.ts b/packages/tools/test/mastra/unit.test.ts index 82b0cac6c..b46d2c37c 100644 --- a/packages/tools/test/mastra/unit.test.ts +++ b/packages/tools/test/mastra/unit.test.ts @@ -190,6 +190,7 @@ describe("SupermemoryInputProcessor", () => { messageList, abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processInput(args) @@ -223,6 +224,7 @@ describe("SupermemoryInputProcessor", () => { messageList: createMockMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processInput(args1) @@ -234,6 +236,7 @@ describe("SupermemoryInputProcessor", () => { messageList: createMockMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processInput(args2) @@ -266,6 +269,7 @@ describe("SupermemoryInputProcessor", () => { messageList: createMockMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processInput(args1) @@ -277,6 +281,7 @@ describe("SupermemoryInputProcessor", () => { messageList: createMockMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processInput(args2) @@ -298,6 +303,7 @@ describe("SupermemoryInputProcessor", () => { messageList, abort: vi.fn() as never, retryCount: 0, + state: {}, } const result = await processor.processInput(args) @@ -329,6 +335,7 @@ describe("SupermemoryInputProcessor", () => { messageList, abort: vi.fn() as never, retryCount: 0, + state: {}, } const result = await processor.processInput(args) @@ -356,6 +363,7 @@ describe("SupermemoryInputProcessor", () => { messageList: createMockMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processInput(args) @@ -385,6 +393,7 @@ describe("SupermemoryInputProcessor", () => { messageList: createMockMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, requestContext, } @@ -428,6 +437,7 @@ describe("SupermemoryInputProcessor", () => { messageList, abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processInput(args) @@ -495,6 +505,7 @@ describe("SupermemoryOutputProcessor", () => { messageList: createMockMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processOutputResult(args) @@ -535,6 +546,7 @@ describe("SupermemoryOutputProcessor", () => { messageList: createMockMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processOutputResult(args) @@ -563,6 +575,7 @@ describe("SupermemoryOutputProcessor", () => { messageList: createMockMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processOutputResult(args) @@ -598,6 +611,7 @@ describe("SupermemoryOutputProcessor", () => { messageList: createMockMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, requestContext, } @@ -632,6 +646,7 @@ describe("SupermemoryOutputProcessor", () => { messageList: createMockMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processOutputResult(args) @@ -668,6 +683,7 @@ describe("SupermemoryOutputProcessor", () => { messageList: createMockMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processOutputResult(args) @@ -723,6 +739,7 @@ describe("SupermemoryOutputProcessor", () => { messageList: createMockMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processOutputResult(args) @@ -756,6 +773,7 @@ describe("SupermemoryOutputProcessor", () => { messageList: createMockMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } // Should not throw @@ -775,6 +793,7 @@ describe("SupermemoryOutputProcessor", () => { messageList: createMockMessageList(), abort: vi.fn() as never, retryCount: 0, + state: {}, } await processor.processOutputResult(args) diff --git a/packages/tools/test/test-memory-tool.ts b/packages/tools/test/test-memory-tool.ts index c0395a791..65bfaa1c8 100644 --- a/packages/tools/test/test-memory-tool.ts +++ b/packages/tools/test/test-memory-tool.ts @@ -4,7 +4,10 @@ * Run with: bun run src/test-memory-tool.ts */ -import { createClaudeMemoryTool, type MemoryCommand } from "./claude-memory" +import { + createClaudeMemoryTool, + type MemoryCommand, +} from "../src/claude-memory" import "dotenv/config" async function testMemoryTool() { @@ -140,8 +143,7 @@ async function testMemoryTool() { let passed = 0 let failed = 0 - for (let i = 0; i < testCases.length; i++) { - const testCase = testCases[i] + for (const [i, testCase] of testCases.entries()) { console.log(`\\nšŸ”„ Test ${i + 1}/${testCases.length}: ${testCase.name}`) try { diff --git a/packages/tools/test/with-supermemory/unit.test.ts b/packages/tools/test/with-supermemory/unit.test.ts index 2653b3454..df52c51b8 100644 --- a/packages/tools/test/with-supermemory/unit.test.ts +++ b/packages/tools/test/with-supermemory/unit.test.ts @@ -446,8 +446,8 @@ describe("Unit: withSupermemory", () => { usage: { inputTokens: 1, outputTokens: 1, + totalTokens: 2, }, - rawCall: { rawPrompt: [], rawSettings: {} }, warnings: [], }) @@ -511,8 +511,8 @@ describe("Unit: withSupermemory", () => { usage: { inputTokens: 1, outputTokens: 1, + totalTokens: 2, }, - rawCall: { rawPrompt: [], rawSettings: {} }, warnings: [], }) diff --git a/packages/tools/tsconfig.json b/packages/tools/tsconfig.json index d40ba072f..61e121d98 100644 --- a/packages/tools/tsconfig.json +++ b/packages/tools/tsconfig.json @@ -1,5 +1,8 @@ { "extends": "@total-typescript/tsconfig/bundler/dom/library-monorepo", + // test/chatapp is a standalone Next.js demo with its own package.json, + // lockfile and tsconfig; it is not part of this package's program. + "exclude": ["node_modules", "test/chatapp"], "compilerOptions": { "baseUrl": ".", "paths": {