fix: address tool_result dedup, SDK task ID collision, and doc accuracy

P1: tool_result dedup changed from "first wins" to "last wins"
- claude-client.ts: remove emittedToolResultIds Set, both PostToolUse and
  user message handler emit freely. PostToolUse provides immediate UI feedback;
  user handler's potentially more complete result arrives second.
- route.ts: collectStreamResponse replaces existing contentBlock entry when
  duplicate tool_use_id arrives (last wins for DB persistence).
- ChatView.tsx: onToolResult replaces existing state entry by tool_use_id
  instead of skipping, ensuring most complete result is displayed.

P2: SDK task ID collision risk eliminated
- db.ts: syncSdkTasks now uses full sessionId in task ID
  (`sdk-{fullSessionId}-{index}`) instead of truncated 8-char prefix,
  eliminating cross-session primary key collisions.

P2: Todo ordering stabilized
- db.ts: add sort_order column migration, syncSdkTasks writes array index
  as sort_order. getTasksBySession sorts by sort_order ASC, created_at ASC
  so tasks with identical timestamps maintain insertion order.

P3: Documentation field mapping corrected
- agent-tooling-todo-bridge.md: fix field mapping table — actual implementation
  maps activeForm (not priority) to description column. Updated dedup strategy
  docs from "three-layer skip" to "two-layer last-wins replace".

Lint: fix prefer-const for finalPrompt in claude-client.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
7418andClaude Opus 4.6 committed 2026-02-27 13:22:10 +08:00
1 parent c13ff54638
commit 0c379e5607
5 files changed
+64 -54

No files matched your search

+8 -2
View File
@@ -326,8 +326,14 @@ export function ChatView({ sessionId, initialMessages = [], initialHasMore = fal
markActive();
setStreamingToolOutput('');
setToolResults((prev) => {
// Dedup: skip if already received for this tool_use_id
if (prev.some(r => r.tool_use_id === res.tool_use_id)) return prev;
// Last-wins: if same tool_use_id exists, replace with newer (potentially more complete) result
const existingIdx = prev.findIndex(r => r.tool_use_id === res.tool_use_id);
if (existingIdx >= 0) {
const next = [...prev];
next[existingIdx] = res;
toolResultsRef.current = next;
return next;
}
const next = [...prev, res];
toolResultsRef.current = next;
return next;