Skip to content
Open
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
54 changes: 28 additions & 26 deletions packages/tools/test/claude-memory-real-example.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**

Check failure on line 1 in packages/tools/test/claude-memory-real-example.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

format

File content differs from formatting output
* Real Claude Memory Tool Integration Examples
*
* This shows actual tool call handling based on real Claude API responses
Expand Down Expand Up @@ -119,25 +119,25 @@
const toolResults = []

if (responseData.content) {
for (const block of responseData.content) {
if (block.type === "tool_use" && block.name === "memory") {
console.log("\\n🔧 Processing memory tool call:")
const memoryToolCalls = responseData.content.filter(
(block: any): block is { type: 'tool_use'; id: string; name: 'memory'; input: { command: MemoryCommand; path: string } } =>

Check warning on line 123 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.type === "tool_use" && block.name === "memory",
)

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

Check warning on line 128 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}`)

// Handle the memory tool call
const toolResult = await handleClaudeMemoryToolCall(
block,
SUPERMEMORY_API_KEY,
{
projectId: "python-scraper-help",
memoryContainerTag: "claude_memory_debug",
},
)

toolResults.push(toolResult)
}
}
return handleClaudeMemoryToolCall(block, SUPERMEMORY_API_KEY, {
projectId: "python-scraper-help",
memoryContainerTag: "claude_memory_debug",
})
}),
)
Comment on lines +128 to +138
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Switching to Promise.all() for tool processing introduces a potential race condition. Concurrent handleClaudeMemoryToolCall operations on the same file can lead to silent data loss due to an unsynchronized read-modify-write pattern.
Severity: MEDIUM

Suggested Fix

Verify the concurrency safety of the Supermemory client.add() method for calls with the same customId. If it is not atomic, introduce a synchronization mechanism (like a mutex or processing tool calls for the same file sequentially) to prevent concurrent read-modify-write operations on the same resource. Alternatively, revert to sequential processing if concurrency is not a strict requirement.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: packages/tools/test/claude-memory-real-example.ts#L127-L138

Potential issue: The change from a sequential `for...of` loop to concurrent processing
with `Promise.all()` for Claude tool calls introduces a potential race condition. The
`handleClaudeMemoryToolCall` function performs a read-modify-write sequence on files
managed by the Supermemory API (`getFileDocument()` to read, then `client.add()` to
write). If Claude sends multiple tool calls that target the same file path concurrently,
these operations can interleave. This could result in one modification being silently
overwritten by another, leading to data loss. While the scenario of Claude sending such
conflicting calls is considered unlikely, the new concurrent execution model makes this
theoretically possible.

Did we get this right? 👍 / 👎 to inform future reviews.


toolResults.push(...results)
}

// Step 3: Send tool results back to Claude if there were any
Expand Down Expand Up @@ -185,27 +185,29 @@
* Simplified function to process Claude tool calls
*/
export async function processClaudeResponse(
claudeResponseData: any,

Check warning on line 188 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 195 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) {
for (const block of claudeResponseData.content) {
if (block.type === "tool_use" && block.name === "memory") {
const toolResult = await handleClaudeMemoryToolCall(
block,
supermemoryApiKey,
config,
)
toolResults.push(toolResult)
}
}
const memoryToolCalls = claudeResponseData.content.filter(
(block: any): block is { type: 'tool_use'; id: string; name: 'memory'; input: { command: MemoryCommand; path: string } } =>

Check warning on line 200 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.type === "tool_use" && block.name === "memory",
)

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

Check warning on line 205 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),
),
)

toolResults.push(...results)
}

return toolResults
Expand Down
Loading