Skip to content

Commit 4b620a8

Browse files
author
超渡法師
committed
docs(adr): add @mention parsing details and group chat limitations
- Add §6.1 explaining how mentions are stored in attributedBody blob - Compare mention detection across platforms (Discord/LINE/Slack/iMessage) - Clarify implications for Phase 1 (1:1) vs Phase 5 (group) - Update open question #3 with recommendation to defer group chat - Add @mention parsing to Phase 5 scope
1 parent c8d5257 commit 4b620a8

1 file changed

Lines changed: 29 additions & 2 deletions

File tree

docs/adr/imessage-integration.md

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,33 @@ impl ChatAdapter for IMessageAdapter {
220220
- No threading (conversations are flat)
221221
- Reactions map to tapbacks (❤️, 👍, 👎, 😂, ‼️, ❓) — only 6 options
222222
- No typing indicators via AppleScript (Spectrum Cloud supports this)
223+
- No structured @mention field (see §6.1 below)
224+
225+
### 6.1 @Mention Detection (Group Chat)
226+
227+
iMessage supports @mentions (iOS 14+, displayed as bold blue text), but `chat.db` does **not** expose them as a structured column. The mention data is embedded inside the `attributedBody` blob — a serialized `NSAttributedString` (NSKeyedArchiver / typedstream format).
228+
229+
**To extract mentions, the bridge must:**
230+
231+
1. Read `message.attributedBody` (binary blob)
232+
2. Decode NSKeyedArchiver binary plist
233+
3. Locate ranges where `__kIMMessagePartAttributeName` = 1 (indicates a mention)
234+
4. Extract the mentioned handle ID from `__kIMMentionConfirmedMention`
235+
236+
**Comparison with other platforms:**
237+
238+
| Platform | Mention detection | Complexity |
239+
|----------|-------------------|-----------|
240+
| Discord | `message.mentions` array | Trivial — structured field |
241+
| LINE | `mentionees` in webhook payload | Trivial — structured field |
242+
| Slack | `<@BOT_ID>` in text + `app_mention` event type | Easy — text pattern |
243+
| iMessage | Parse binary `attributedBody` blob | Hard — undocumented binary format |
244+
245+
**Implications for group chat:**
246+
- **1:1 conversations (Phase 1):** No mention detection needed — all messages are directed at the bot
247+
- **Group chat (Phase 5):** Bridge must parse `attributedBody` to know when the bot is mentioned, or fall back to keyword-prefix trigger (e.g. `/ask ...`)
248+
- The `attributedBody` format is undocumented and may change across macOS versions — Rust `plist` crate can decode the binary plist, but the internal schema requires reverse-engineering
249+
- **Outbound:** AppleScript `send` does not support sending @mentions — bot replies are plain text only
223250

224251
---
225252

@@ -293,7 +320,7 @@ project_secret = "${PHOTON_PROJECT_SECRET}"
293320
| **Phase 2** | `IMessageAdapter` in OAB core implementing `ChatAdapter` trait | Multi-Platform Adapters (done) |
294321
| **Phase 3** | Spectrum sidecar adapter (Node.js/Bun wrapper) as alternative to self-hosted bridge | Photon account |
295322
| **Phase 4** | Helm chart additions: bridge sidecar, Spectrum sidecar, config templates | Phase 1 or 3 |
296-
| **Phase 5** | Rich features: tapback reactions, group chat support, attachment handling | Phase 2 |
323+
| **Phase 5** | Rich features: tapback reactions, group chat support, @mention parsing, attachment handling | Phase 2 |
297324

298325
---
299326

@@ -321,7 +348,7 @@ Apple does not provide an official iMessage API. All known approaches rely on:
321348
|---|----------|---------|-------|
322349
| 1 | Bridge language | Rust (consistent with OAB) vs TypeScript (reuse imessage-kit) | Rust preferred for single-binary deployment |
323350
| 2 | Poll interval default | 100ms vs 200ms vs 500ms | Tradeoff: latency vs CPU. agy-acp uses 100ms |
324-
| 3 | Group chat support in Phase 1? | Yes / defer to Phase 5 | Groups add complexity (participant tracking) |
351+
| 3 | Group chat support in Phase 1? | Yes / defer to Phase 5 | Recommend defer — no structured @mention field means bot can't reliably detect when addressed. 1:1 is the sweet spot. |
325352
| 4 | Should bridge run as launchd service? | Yes (auto-restart) / manual | launchd is macOS best practice for daemons |
326353
| 5 | Photon free tier shared numbers acceptable? | Yes for POC / require dedicated | Shared numbers may confuse recipients |
327354

0 commit comments

Comments
 (0)