Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/tools/test-supermemory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
60 changes: 46 additions & 14 deletions packages/tools/test/anthropic-example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -37,15 +61,15 @@ async function chatWithMemoryTool() {
})

// Conversation messages
const messages: Anthropic.Messages.MessageParam[] = [
const messages: Anthropic.Beta.Messages.BetaMessageParam[] = [
{
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("💬 User:", messages[0]?.content)
console.log("\n🔄 Sending to Claude with memory tool...")

try {
Expand All @@ -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
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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],
},
},
]
Expand Down
8 changes: 5 additions & 3 deletions packages/tools/test/claude-memory-examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -20,7 +23,7 @@
console.log("=".repeat(50))

// Initialize the memory tool
const memoryTool = createClaudeMemoryTool(process.env.SUPERMEMORY_API_KEY!, {

Check warning on line 26 in packages/tools/test/claude-memory-examples.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

lint/style/noNonNullAssertion

Forbidden non-null assertion.
projectId: "claude-memory-demo",
memoryContainerTag: "claude_memory_demo",
})
Expand Down Expand Up @@ -67,8 +70,7 @@
]

// 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}`,
)
Expand Down Expand Up @@ -105,7 +107,7 @@
console.log("=".repeat(50))

// Initialize memory tool
const memoryTool = createClaudeMemoryTool(process.env.SUPERMEMORY_API_KEY!, {

Check warning on line 110 in packages/tools/test/claude-memory-examples.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

lint/style/noNonNullAssertion

Forbidden non-null assertion.
projectId: "claude-chat-session",
memoryContainerTag: "claude_memory_chat",
})
Expand Down
5 changes: 4 additions & 1 deletion packages/tools/test/claude-memory-real-example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -121,7 +124,7 @@
if (responseData.content) {
const memoryToolCalls = responseData.content.filter(
(
block: any,

Check warning on line 127 in packages/tools/test/claude-memory-real-example.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

lint/suspicious/noExplicitAny

Unexpected any. Specify a different type.
): block is {
type: "tool_use"
id: string
Expand All @@ -131,7 +134,7 @@
)

const results = await Promise.all(
memoryToolCalls.map((block: any) => {

Check warning on line 137 in packages/tools/test/claude-memory-real-example.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

lint/suspicious/noExplicitAny

Unexpected any. Specify a different type.
console.log("\n🔧 Processing memory tool call:")
console.log(`Command: ${block.input.command}`)
console.log(`Path: ${block.input.path}`)
Expand Down Expand Up @@ -191,20 +194,20 @@
* Simplified function to process Claude tool calls
*/
export async function processClaudeResponse(
claudeResponseData: any,

Check warning on line 197 in packages/tools/test/claude-memory-real-example.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

lint/suspicious/noExplicitAny

Unexpected any. Specify a different type.
supermemoryApiKey: string,
config?: {
projectId?: string
memoryContainerTag?: string
baseUrl?: string
},
): Promise<any[]> {

Check warning on line 204 in packages/tools/test/claude-memory-real-example.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

lint/suspicious/noExplicitAny

Unexpected any. Specify a different type.
const toolResults = []

if (claudeResponseData.content) {
const memoryToolCalls = claudeResponseData.content.filter(
(
block: any,

Check warning on line 210 in packages/tools/test/claude-memory-real-example.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

lint/suspicious/noExplicitAny

Unexpected any. Specify a different type.
): block is {
type: "tool_use"
id: string
Expand All @@ -214,7 +217,7 @@
)

const results = await Promise.all(
memoryToolCalls.map((block: any) =>

Check warning on line 220 in packages/tools/test/claude-memory-real-example.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

lint/suspicious/noExplicitAny

Unexpected any. Specify a different type.
handleClaudeMemoryToolCall(block, supermemoryApiKey, config),
),
)
Expand Down
15 changes: 11 additions & 4 deletions packages/tools/test/claude-memory.test.ts
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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<typeof createClaudeMemoryTool>

Expand Down Expand Up @@ -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."

Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
16 changes: 16 additions & 0 deletions packages/tools/test/mastra/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ describe.skipIf(!shouldRunIntegration)(
messageList,
abort: vi.fn() as never,
retryCount: 0,
state: {},
}

await processor.processInput(args)
Expand Down Expand Up @@ -152,6 +153,7 @@ describe.skipIf(!shouldRunIntegration)(
messageList,
abort: vi.fn() as never,
retryCount: 0,
state: {},
}

await processor.processInput(args)
Expand Down Expand Up @@ -191,6 +193,7 @@ describe.skipIf(!shouldRunIntegration)(
messageList,
abort: vi.fn() as never,
retryCount: 0,
state: {},
}

await processor.processInput(args)
Expand Down Expand Up @@ -233,6 +236,7 @@ describe.skipIf(!shouldRunIntegration)(
messageList: createIntegrationMessageList(),
abort: vi.fn() as never,
retryCount: 0,
state: {},
}

await processor.processInput(args1)
Expand All @@ -247,6 +251,7 @@ describe.skipIf(!shouldRunIntegration)(
messageList: createIntegrationMessageList(),
abort: vi.fn() as never,
retryCount: 0,
state: {},
}

await processor.processInput(args2)
Expand Down Expand Up @@ -282,6 +287,7 @@ describe.skipIf(!shouldRunIntegration)(
messageList,
abort: vi.fn() as never,
retryCount: 0,
state: {},
}

await processor.processInput(args)
Expand Down Expand Up @@ -313,6 +319,7 @@ describe.skipIf(!shouldRunIntegration)(
messageList: createIntegrationMessageList(),
abort: vi.fn() as never,
retryCount: 0,
state: {},
}

await processor.processOutputResult(args)
Expand Down Expand Up @@ -346,6 +353,7 @@ describe.skipIf(!shouldRunIntegration)(
messageList: createIntegrationMessageList(),
abort: vi.fn() as never,
retryCount: 0,
state: {},
}

await processor.processOutputResult(args)
Expand Down Expand Up @@ -383,6 +391,7 @@ describe.skipIf(!shouldRunIntegration)(
messageList: createIntegrationMessageList(),
abort: vi.fn() as never,
retryCount: 0,
state: {},
requestContext,
}

Expand Down Expand Up @@ -417,6 +426,7 @@ describe.skipIf(!shouldRunIntegration)(
messageList,
abort: vi.fn() as never,
retryCount: 0,
state: {},
}

await input.processInput(inputArgs)
Expand All @@ -430,6 +440,7 @@ describe.skipIf(!shouldRunIntegration)(
messageList: createIntegrationMessageList(),
abort: vi.fn() as never,
retryCount: 0,
state: {},
}

await output.processOutputResult(outputArgs)
Expand Down Expand Up @@ -470,6 +481,7 @@ describe.skipIf(!shouldRunIntegration)(
messageList,
abort: vi.fn() as never,
retryCount: 0,
state: {},
}

await inputProcessor.processInput(args)
Expand Down Expand Up @@ -534,6 +546,7 @@ describe.skipIf(!shouldRunIntegration)(
messageList,
abort: vi.fn() as never,
retryCount: 0,
state: {},
}

await processor.processInput(args)
Expand All @@ -558,6 +571,7 @@ describe.skipIf(!shouldRunIntegration)(
messageList: createIntegrationMessageList(),
abort: vi.fn() as never,
retryCount: 0,
state: {},
}

await processor.processInput(args)
Expand Down Expand Up @@ -592,6 +606,7 @@ describe.skipIf(!shouldRunIntegration)(
messageList,
abort: vi.fn() as never,
retryCount: 0,
state: {},
}

const result = await processor.processInput(args)
Expand All @@ -616,6 +631,7 @@ describe.skipIf(!shouldRunIntegration)(
messageList: createIntegrationMessageList(),
abort: vi.fn() as never,
retryCount: 0,
state: {},
}

await expect(processor.processOutputResult(args)).resolves.toBeDefined()
Expand Down
Loading
Loading