fix: avoid replaying file attachment content#1865
Conversation
📝 WalkthroughWalkthroughAdds an options parameter to ChangesAttachment token bloat reduction
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Caller as createUserChatMessage/recordToChatMessages
participant Builder as buildUserMessageContent
participant FileCtx as buildNonImageFileContext
participant Prompt as ChatMessage content
Caller->>Builder: call with options includeImageData includeAudioData includeFileContent
Builder->>Builder: derive includeImageData and includeAudioData flags
Builder->>Prompt: add input_audio structured part when audio enabled
Builder->>FileCtx: build non-image file context with includeFileContent option
FileCtx-->>Builder: return metadata with placeholder or full file content
Builder->>Prompt: add image_url structured parts when vision and includeImageData enabled
Builder->>Prompt: append image metadata text fallback when no image parts produced
Builder-->>Caller: assembled ChatMessage content
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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.
🧹 Nitpick comments (2)
test/renderer/components/ChatInputBox.test.ts (1)
134-136: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueStatic mocks diverge from derived real-hook behavior.
composerActiveCount/composerActiveSkillItemsare hardcoded rather than derived fromactiveSkillsRef, unlike the realuseSkillsDatawhere they're computed fromcomposerActiveSkills(seeuseSkillsData.tslines 39-56). Not currently exercised sinceChatInputBox.vueonly readscomposerActiveSkills, but any future assertion on these fields would silently diverge from real behavior.♻️ Optional alignment
- composerActiveCount: ref(0), - composerActiveSkillItems: ref([]), + composerActiveCount: computed(() => activeSkillsRef.value.length), + composerActiveSkillItems: ref([]),🤖 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 `@test/renderer/components/ChatInputBox.test.ts` around lines 134 - 136, The test mock in ChatInputBox.test.ts has composerActiveCount and composerActiveSkillItems hardcoded instead of matching the derived behavior in useSkillsData; update the mock setup so these fields are computed from composerActiveSkills/activeSkillsRef the same way useSkillsData does, using the existing activeSkillsRef and the related reactive symbols. Keep the mock aligned with the real hook’s derived outputs so any future assertions against composerActiveCount or composerActiveSkillItems reflect actual behavior.src/main/presenter/agentRuntimePresenter/contextBuilder.ts (1)
426-463: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider simplifying the early-return guard using
shouldBuildImageParts.Line 462's condition
(!supportsVision || imageFiles.length === 0) && audioParts.length === 0doesn't account forincludeImageDatabeing explicitlyfalsewhile vision is supported and images exist (the historical-image path). Functionally the code still converges to the same result via the later!hasStructuredPartsbranch, but it does redundant work building emptyparts/imagePartsarrays for a case that could returnbaseTextimmediately.♻️ Optional simplification
- if ((!supportsVision || imageFiles.length === 0) && audioParts.length === 0) { + if (!shouldBuildImageParts && audioParts.length === 0) { return baseText }🤖 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/main/presenter/agentRuntimePresenter/contextBuilder.ts` around lines 426 - 463, Simplify the early-return guard in contextBuilder so it uses shouldBuildImageParts and returns baseText when image parts are not being built, including the case where includeImageData is false but vision is supported and imageFiles exist. Update the conditional near the baseText return in buildContext to avoid the redundant parts/imageParts work and keep the logic aligned with shouldBuildImageParts and audioParts handling.
🤖 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.
Nitpick comments:
In `@src/main/presenter/agentRuntimePresenter/contextBuilder.ts`:
- Around line 426-463: Simplify the early-return guard in contextBuilder so it
uses shouldBuildImageParts and returns baseText when image parts are not being
built, including the case where includeImageData is false but vision is
supported and imageFiles exist. Update the conditional near the baseText return
in buildContext to avoid the redundant parts/imageParts work and keep the logic
aligned with shouldBuildImageParts and audioParts handling.
In `@test/renderer/components/ChatInputBox.test.ts`:
- Around line 134-136: The test mock in ChatInputBox.test.ts has
composerActiveCount and composerActiveSkillItems hardcoded instead of matching
the derived behavior in useSkillsData; update the mock setup so these fields are
computed from composerActiveSkills/activeSkillsRef the same way useSkillsData
does, using the existing activeSkillsRef and the related reactive symbols. Keep
the mock aligned with the real hook’s derived outputs so any future assertions
against composerActiveCount or composerActiveSkillItems reflect actual behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 3354a114-e83c-4593-84cc-d8effd5e8471
📒 Files selected for processing (6)
.agents/skills/deepchat-sdd/SKILL.mddocs/issues/file-attachment-token-bloat/spec.mdsrc/main/presenter/agentRuntimePresenter/contextBuilder.tstest/main/presenter/agentRuntimePresenter/compactionService.test.tstest/main/presenter/agentRuntimePresenter/contextBuilder.test.tstest/renderer/components/ChatInputBox.test.ts
Summary
close [BUG] File attachments cause massive token bloat — file data resent with every API call #1864
Tests
Summary by CodeRabbit
New Features
Bug Fixes