feat: expose message balloon bundle metadata#137
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 6, 2026, 2:25 PM ET / 18:25 UTC. Summary Reproducibility: not applicable. this is an additive metadata exposure rather than a broken existing behavior report. The PR nevertheless includes a concrete after-fix local DB proof path for history, RPC history, and watch replay. Review metrics: 2 noteworthy metrics.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Merge the focused additive field if maintainers accept exposing raw balloon bundle identifiers as stable message metadata. Do we have a high-confidence way to reproduce the issue? Not applicable: this is an additive metadata exposure rather than a broken existing behavior report. The PR nevertheless includes a concrete after-fix local DB proof path for history, RPC history, and watch replay. Is this the best way to solve the issue? Yes, subject to maintainer API acceptance: reusing the already selected AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against 041b40686a6d. Label changesLabel changes:
Label justifications:
Evidence reviewedWhat I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
76ab0a2 to
0fc650b
Compare
0fc650b to
e223709
Compare
|
Rebased this PR onto current Proof run after the rebase:
Real local Messages DB proof was redacted to row id and structural metadata only. The local DB had 8
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
…th back-compat (#90858) Gate iMessage same-sender DM split-send coalescing on imsg's structural `balloon_bundle_id` URL-balloon marker (openclaw/imsg#137) instead of timing/ text-shape inference, with a session capability latch and a back-compat path: - URL-balloon marker present -> merge (precise split-send). - Build known to emit balloon metadata (session latch) -> keep non-marker buckets separate (the precision win). - Build that never emits balloon metadata (older imsg) -> preserve the legacy unconditional merge, so split-send users do not regress to two turns. Never merges more than shipped main already did. Verified live end-to-end: the patched gateway, watching a real chat.db via an imsg #137 build, merged a real iPhone-sent `Dump <url>` split-send into one turn. Client-side removal once imsg coalesces upstream is tracked in #91243 (openclaw/imsg#141). Closes #90795
…th back-compat (openclaw#90858) Gate iMessage same-sender DM split-send coalescing on imsg's structural `balloon_bundle_id` URL-balloon marker (openclaw/imsg#137) instead of timing/ text-shape inference, with a session capability latch and a back-compat path: - URL-balloon marker present -> merge (precise split-send). - Build known to emit balloon metadata (session latch) -> keep non-marker buckets separate (the precision win). - Build that never emits balloon metadata (older imsg) -> preserve the legacy unconditional merge, so split-send users do not regress to two turns. Never merges more than shipped main already did. Verified live end-to-end: the patched gateway, watching a real chat.db via an imsg openclaw#137 build, merged a real iPhone-sent `Dump <url>` split-send into one turn. Client-side removal once imsg coalesces upstream is tracked in openclaw#91243 (openclaw/imsg#141). Closes openclaw#90795
e223709 to
54a4196
Compare
|
Maintainer pass on PR #137 complete. Changes added during maintainer pass:
Proof:
API decision: accepting the additive nullable |
Summary
Expose the raw Messages
message.balloon_bundle_idvalue in the stable Message JSON/RPC payload asballoon_bundle_id.This gives downstream consumers a structural signal for URL/link-preview balloon rows, especially
com.apple.messages.URLBalloonProvider, instead of forcing them to infer split-send payloads from user-authored text such as short command lead-ins.Details
balloon_bundle_idfrom SQLite row decoding intoIMsgCore.Message.messages.history,watch.subscribe, and search payloads.docs/json.md.searchMessages()initially dropped the decoded balloon metadata.Verification
Rebased on current
openclaw/main(041b40686a6dde88efabb2e401792c24b5093675); GitHub now reports the PR as mergeable at heade223709a91e81f3d405a9a8593eafdc3b6ec0e24.swift buildswift format lint Sources/IMsgCore/Models.swift Sources/IMsgCore/MessageStore+Messages.swift Sources/IMsgCore/MessageStore+Search.swift Sources/imsg/OutputModels.swift Tests/IMsgCoreTests/MessageStoreTests.swift Tests/imsgTests/WatchCommandTests.swiftDEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer swift test --filter MessageStoreTestspassed: 19 tests.DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer swift test --filter WatchCommandTestspassed: 6 tests.DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer make testpassed: 325 tests.Real local Messages DB proof, redacted to only row id and structural metadata:
SELECT COUNT(*) FROM message WHERE balloon_bundle_id='com.apple.messages.URLBalloonProvider';observed8rows; latest joined proof row observedchat_id=3,ROWID=5855../.build/debug/imsg history --chat-id 3 --limit 100 --json | jq -c 'select(has("balloon_bundle_id")) | {id, has_balloon_bundle_id: has("balloon_bundle_id"), balloon_bundle_id}'observed
{"id":5855,"has_balloon_bundle_id":true,"balloon_bundle_id":"com.apple.messages.URLBalloonProvider"}messages.history:printf ... | ./.build/debug/imsg rpc | jq -c '.result.messages[] | select(has("balloon_bundle_id")) | {id, has_balloon_bundle_id: has("balloon_bundle_id"), balloon_bundle_id}'observed
{"id":5855,"has_balloon_bundle_id":true,"balloon_bundle_id":"com.apple.messages.URLBalloonProvider"}watch.subscribereplay from cursor:printf ... since_rowid=5854 ... | ./.build/debug/imsg rpc | jq -c 'select(.method=="message") | .params.message | select(has("balloon_bundle_id")) | {id, has_balloon_bundle_id: has("balloon_bundle_id"), balloon_bundle_id}' | head -1observed
{"id":5855,"has_balloon_bundle_id":true,"balloon_bundle_id":"com.apple.messages.URLBalloonProvider"}