Ensure unique fallback tool ids

This commit is contained in:
Mohamed Boudra
2025-11-15 17:41:15 +01:00
parent 19d172cc8d
commit e208f1c5bd
3 changed files with 43 additions and 3 deletions
+38
View File
@@ -1199,6 +1199,43 @@ function testMetadataReplayDeduplicationHydrated() {
});
}
function testFallbackToolCallIdsStayUnique() {
const timestamp = new Date('2025-01-01T14:05:00Z');
const updates = [
{
event: toolTimeline(
'fallback-shell-1',
'completed',
{ type: 'tool_result', tool_use_id: 'fallback-shell-1' },
{ callId: null, server: 'command', tool: 'shell', displayName: 'Run shell' }
),
timestamp,
},
{
event: toolTimeline(
'fallback-shell-2',
'completed',
{ type: 'tool_result', tool_use_id: 'fallback-shell-2' },
{ callId: null, server: 'command', tool: 'shell', displayName: 'Run shell' }
),
timestamp,
},
];
const hydrated = hydrateStreamState(updates);
const toolCalls = hydrated.filter(
(item): item is ToolCallItem => item.kind === 'tool_call' && item.payload.source === 'agent'
);
assert.strictEqual(toolCalls.length, 2, 'Hydration should retain multiple fallback tool entries');
const ids = toolCalls.map((item) => item.id);
assert.strictEqual(
new Set(ids).size,
ids.length,
'Fallback-generated tool ids must be unique even when metadata matches and callIds are missing'
);
}
describe('stream timeline reducers', () => {
it('produces deterministic hydration results', testIdempotentReduction);
it('deduplicates pending/completed tool entries in place', testUserMessageDeduplication);
@@ -1222,4 +1259,5 @@ describe('stream timeline reducers', () => {
it('merges out-of-order tool call updates without duplicating entries (hydrated)', testOutOfOrderToolCallMergingHydrated);
it('replays metadata-only tool calls without duplicating entries (live)', testMetadataReplayDeduplicationLive);
it('replays metadata-only tool calls without duplicating entries (hydrated)', testMetadataReplayDeduplicationHydrated);
it('assigns unique ids for fallback tool calls without call ids', testFallbackToolCallIdsStayUnique);
});
+3 -2
View File
@@ -35,7 +35,7 @@ function createTimelineId(prefix: string, text: string, timestamp: Date): string
function createUniqueTimelineId(
state: StreamItem[],
prefix: "assistant" | "thought" | "user",
prefix: "assistant" | "thought" | "user" | "tool",
text: string,
timestamp: Date
): string {
@@ -459,7 +459,8 @@ function appendAgentToolCall(
const id = callId
? `agent_tool_${callId}`
: createTimelineId(
: createUniqueTimelineId(
state,
"tool",
`${data.provider}:${data.server}:${data.tool}`,
timestamp