fix: deduplicate tool_call stream events by toolCallId (#199)
The Letta server streams tool_call_message events token-by-token as the model generates tool arguments. A single tool call (e.g. memory_rethink with a large new_memory arg) can produce hundreds of wire events, all sharing the same toolCallId. Without dedup, the bot miscounts these as separate tool calls -- logging "Calling tool: X" hundreds of times and potentially triggering the tool-loop abort at maxToolCalls (default 100) for what is actually a single call. Track seen toolCallIds per stream and skip chunks already yielded. Written by Cameron and Letta Code "In the beginner's mind there are many possibilities, but in the expert's mind there are few." -- Shunryu Suzuki
This commit is contained in:
@@ -477,8 +477,18 @@ export class LettaBot {
|
||||
adapter.sendTypingIndicator(msg.chatId).catch(() => {});
|
||||
}, 4000);
|
||||
|
||||
const seenToolCallIds = new Set<string>();
|
||||
try {
|
||||
for await (const streamMsg of session.stream()) {
|
||||
// Deduplicate tool_call chunks: the server streams tool_call_message
|
||||
// events token-by-token as arguments are generated, so a single tool
|
||||
// call produces many wire events with the same toolCallId.
|
||||
// Only count/log the first chunk per unique toolCallId.
|
||||
if (streamMsg.type === 'tool_call') {
|
||||
const toolCallId = (streamMsg as any).toolCallId;
|
||||
if (toolCallId && seenToolCallIds.has(toolCallId)) continue;
|
||||
if (toolCallId) seenToolCallIds.add(toolCallId);
|
||||
}
|
||||
const msgUuid = (streamMsg as any).uuid;
|
||||
watchdog.ping();
|
||||
receivedAnyData = true;
|
||||
|
||||
Reference in New Issue
Block a user