perf: 为 tool_result 建立惰性索引,避免 /artifacts 二次方扫描 - #1349
Conversation
📝 WalkthroughWalkthroughThe artifact scanner now builds a cached tool-result index after the first artifact. The index preserves first-result-wins behavior. Tests cover multiple artifacts, result ordering, duplicate IDs, and results that precede tool-use messages. ChangesArtifact scanning
Estimated code review effort: 3 (Moderate) | ~20 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/commands/artifacts/scanner.ts`:
- Around line 128-140: The tool_result scan must ignore malformed entries with
non-string tool_use_id values. In the loop processing blocks in scanner.ts,
validate b.tool_use_id with typeof === 'string' and continue before checking
results or calling results.set; retain the existing first-result-wins behavior
for valid string IDs.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: bef1e453-b237-4ea9-a7b8-b965d3beb793
📒 Files selected for processing (2)
src/commands/artifacts/__tests__/scanner.test.tssrc/commands/artifacts/scanner.ts
| for (const block of content) { | ||
| if (typeof block !== 'object' || block === null) continue | ||
| if (!('type' in block)) continue | ||
| const b = block as unknown as Record<string, unknown> | ||
| if (b.type !== 'tool_result') continue | ||
| const toolUseId = b.tool_use_id as string | ||
| if (results.has(toolUseId)) continue | ||
|
|
||
| // Match findToolResult's first-result-wins behavior for duplicate IDs. | ||
| results.set(toolUseId, { | ||
| content: b.content, | ||
| is_error: b.is_error as boolean | undefined, | ||
| }) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
ast-grep outline src/types/message.ts --items all
rg -n -C 4 '\btool_use_id\b|\bid\b' \
src/types/message.ts \
src/commands/artifacts/scanner.tsRepository: claude-code-best/claude-code
Length of output: 2464
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- scanner.ts ---'
sed -n '1,180p' src/commands/artifacts/scanner.ts
printf '%s\n' '--- message type definitions and relevant references ---'
rg -n -C 5 'ContentBlock|ToolResult|tool_use_id|tool_use' src/types src/commands/artifacts src --glob '*.{ts,tsx}' | head -n 500
printf '%s\n' '--- scanner tests and call sites ---'
rg -n -C 4 'findToolResult|build.*Index|ArtifactToolResult|scanArtifacts|tool_use_id' src --glob '*.{ts,tsx}'Repository: claude-code-best/claude-code
Length of output: 50385
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- scanner.ts ---'
cat -n src/commands/artifacts/scanner.ts | sed -n '1,175p'
printf '%s\n' '--- scanner symbols and local tests ---'
rg -n -C 8 'ArtifactToolResult|findToolResult|results\.|scanArtifacts|scanner' \
src/commands/artifacts --glob '*.{ts,tsx}'
printf '%s\n' '--- message.ts relevant declarations ---'
rg -n -C 8 'ContentBlock|ToolResultBlock|tool_use_id|Message' src/types/message.ts
printf '%s\n' '--- package/dependency declarations for SDK block types ---'
rg -n -C 4 'ToolResultBlock|tool_use_id' package.json bun.lockb bun.lock yarn.lock pnpm-lock.yaml node_modules/@anthropic-ai 2>/dev/null || trueRepository: claude-code-best/claude-code
Length of output: 18996
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- scanner tests ---'
cat -n src/commands/artifacts/__tests__/scanner.test.ts | sed -n '1,260p'
printf '%s\n' '--- model-provider type sources in the repository ---'
git ls-files | rg '(^|/)(model-provider|.*message.*|.*content.*)\.(ts|tsx|d\.ts)$' | head -n 200
printf '%s\n' '--- all scanner casts and transcript construction ---'
rg -n -C 3 'as string|as unknown as|tool_use_id' src/commands/artifacts src/types src/utils/sessionStorage.ts src/utils/conversationRecovery.ts --glob '*.{ts,tsx}' | head -n 400Repository: claude-code-best/claude-code
Length of output: 21571
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- model-provider message types ---'
rg -n -C 12 'ToolResult|tool_result|ToolUse|tool_use|ContentBlock' packages/@ant/model-provider/src/types/message.ts
printf '%s\n' '--- Message input boundary and artifact command callers ---'
rg -n -C 8 'extractArtifacts\(|context\.messages|messages\?:|messages:' \
src/commands/artifacts packages/@ant/model-provider/src --glob '*.{ts,tsx}'
printf '%s\n' '--- malformed-block test feasibility ---'
rg -n -C 5 'as unknown as Message|tool_use_id: [^'\''"]|tool_use_id: null|tool_use_id: [0-9]' \
src/commands/artifacts src --glob '*.{test.ts,test.tsx}' | head -n 300Repository: claude-code-best/claude-code
Length of output: 50034
🏁 Script executed:
#!/bin/bash
set -euo pipefail
node - <<'JS'
const results = new Map()
const malformedToolResult = { type: 'tool_result', tool_use_id: 42, content: 'payload' }
const assertedToolUseId = malformedToolResult.tool_use_id
results.set(assertedToolUseId, { content: malformedToolResult.content })
console.log({
storedKeyType: typeof [...results.keys()][0],
lookupWithStringId: results.get('42') ?? null,
lookupWithNumberId: results.get(42) ?? null,
})
JSRepository: claude-code-best/claude-code
Length of output: 270
Narrow tool_use_id before indexing.
If a malformed tool_result contains a non-string tool_use_id, the assertion stores a non-string key and string lookups fail. Skip the block unless typeof toolUseId === 'string'.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/commands/artifacts/scanner.ts` around lines 128 - 140, The tool_result
scan must ignore malformed entries with non-string tool_use_id values. In the
loop processing blocks in scanner.ts, validate b.tool_use_id with typeof ===
'string' and continue before checking results or calling results.set; retain the
existing first-result-wins behavior for valid string IDs.
Source: Coding guidelines
Summary
tool_result索引。tool_use_id常数时间查找,避免对 transcript 反复全表扫描。Benchmark
每场景 60 对预热,3 trial × 120 次随机平衡 AB/BA,共 360 样本/实现;所有输出严格等价。
低基数边界:1k / 1 artifact 的 median 为 0.02630 → 0.02901 ms(+2.7 μs),p95 为 0.04004 → 0.04104 ms;未宣称所有场景都加速。
Test plan
bun test src/commands/artifacts/__tests__/scanner.test.ts(8 pass)bun run typecheckgit diff --check关联 issue
Closes #1346Summary by CodeRabbit
Bug Fixes
Performance