fix(chat/ios): downscale image attachments before send#81608
Conversation
|
Codex review: needs maintainer review before merge. Summary Reproducibility: yes. Source inspection shows current main loads PhotosPicker image bytes, rejects payloads over 5,000,000 bytes before resizing, and base64-encodes the staged bytes directly on send. Real behavior proof Next step before merge Security Review detailsBest possible solution: Land the focused preprocessing path after normal maintainer validation, then close the linked iOS composer bug and mark the older external implementation PR as superseded if this merges. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection shows current main loads PhotosPicker image bytes, rejects payloads over 5,000,000 bytes before resizing, and base64-encodes the staged bytes directly on send. Is this the best way to solve the issue? Yes. Reusing JPEGTranscoder behind a small ChatImageProcessor before staging is the narrow maintainable fix, and this PR avoids the unrelated Settings drift that blocked the older external branch. Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 983064f5f819. |
65d3efe to
66ca4d5
Compare
|
Maintainer verification before merge: Local proof on rebased head swift test --package-path apps/shared/OpenClawKit --filter 'ChatImageProcessorTests|JPEGTranscoderTests|ChatViewModelAttachmentTests'
swiftformat --lint --config config/swiftformat apps/shared/OpenClawKit/Sources/OpenClawKit/ChatImageProcessor.swift apps/shared/OpenClawKit/Sources/OpenClawKit/JPEGTranscoder.swift apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatImageProcessorTests.swift apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatViewModelAttachmentTests.swift
swiftlint lint --config apps/ios/.swiftlint.yml apps/shared/OpenClawKit/Sources/OpenClawKit/ChatImageProcessor.swift apps/shared/OpenClawKit/Sources/OpenClawKit/JPEGTranscoder.swift apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatImageProcessorTests.swift apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatViewModelAttachmentTests.swift
git diff --check origin/main..HEADResult: all passed. Swift test covered 12 tests across Exact-head CI proof on
Known proof gap: no fresh physical iPhone camera roll -> composer -> live gateway send was run on this maintainer branch. The shared iOS chat attachment path is covered by focused Swift tests and macOS Swift CI. Mergeability: GitHub reports |
Summary
chat.send.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
Real behavior proof (required for external PRs)
apps/shared/OpenClawKiton the OpenClaw iOS shared package.swift test --package-path apps/shared/OpenClawKit --filter 'ChatImageProcessorTests|JPEGTranscoderTests|ChatViewModelAttachmentTests'swiftformat --lint --config config/swiftformat apps/shared/OpenClawKit/Sources/OpenClawKit/ChatImageProcessor.swift apps/shared/OpenClawKit/Sources/OpenClawKit/JPEGTranscoder.swift apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatImageProcessorTests.swift apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatViewModelAttachmentTests.swiftswiftlint lint --config apps/ios/.swiftlint.yml apps/shared/OpenClawKit/Sources/OpenClawKit/ChatImageProcessor.swift apps/shared/OpenClawKit/Sources/OpenClawKit/JPEGTranscoder.swift apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatImageProcessorTests.swift apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatViewModelAttachmentTests.swiftgit diff --check origin/main..HEADimage/jpeg, renamed to.jpg, capped to the 1600 px long edge, kept within the 3.5 MB chat payload budget, and tested to avoid source metadata leakage.pnpm ios:buildis currently blocked in this checkout by unrelated existing SwiftFormat failures inapps/ios/Sources/Settings/SettingsTab.swift.Dataand applied only a pre-resize 5 MB hard gate.Root Cause (if applicable)
OpenClawChatViewModel.addImageAttachmentaccepted raw PhotosPicker image bytes, applied a 5 MB size check before any transformation, and staged the original bytes for later base64 send.JPEGTranscoderalready existed, but the chat composer path did not use it.Regression Test Plan (if applicable)
apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatImageProcessorTests.swiftapps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatViewModelAttachmentTests.swiftOpenClawChatViewModelstages resized JPEG bytes rather than the original file.JPEGTranscoderTestscovered the shared transcoder; this PR adds chat-specific policy and view-model coverage.User-visible / Behavior Changes
.jpgfor processed image attachments.Diagram (if applicable)
Security Impact (required)
Yes, explain risk + mitigation: the data scope is reduced because source image metadata is stripped before staging/sending. Tests assert planted source metadata strings and GPS dictionaries do not survive processing.Repro + Verification
Environment
apps/shared/OpenClawKitSteps
ChatImageProcessor.OpenClawChatViewModel.addImageAttachment.Expected
Actual
65d3efe72f.Evidence
Human Verification (required)
What you personally verified (not just CI), and how:
Review Conversations
No review conversations exist on this PR at creation time.
Compatibility / Migration
Risks and Mitigations