Repository navigation
fix: emit bridge typing events from chat item changes - #378
Conversation
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: needs maintainer review before merge. What this changesThe PR emits bridge typing events when remote typing indicators appear or disappear in IMCore chat-item lists. Example: A participant types and clears a draft while
Review scores
ProductKind: Bug fix · Worth it: Yes · Fix scope: Complete Merge readiness✅ Ready for maintainer review Keep this PR: it restores documented typing events that remain broken on main, with focused regression coverage and convincing live CLI proof; no actionable defects found. Priority: P2 Before mergeNone. FindingsNone. Agent review detailsHow this fits togetherThe injected Messages helper translates IMCore notifications into JSONL events, which the CLI watch command and RPC bridge subscriptions consume through the shared event tailer. flowchart LR
A[Remote participant typing] --> B[IMCore chat item notification]
B --> C[Injected helper observer]
C --> D[Bridge JSONL event log]
D --> E[Shared event tailer]
E --> F[CLI watch]
E --> G[RPC bridge subscription]
Technical reviewBest possible solution: Land the focused observer repair while preserving the existing event writer, payload, and consumers. Do we have a high-confidence way to reproduce the issue? Main's observer mismatch is source-verifiable and supported by the contributor's before/after CLI output and base-failing regression test; this read-only review did not execute target code. Is this the best way to solve the issue? Comparing old/new typing-item presence fixes both the notification mismatch and incorrect payload interpretation at the existing shared producer, without timers, duplicate state, or consumer-specific workarounds. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against 5af52a029b3d. Provenance checked
TestingProof path: shipped entry point. SecurityNone. EvidenceWhat I checked:
Likely related people:
LabelsLabel changes:
Label justifications:
Rating scale6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior. WorkflowClawSweeper edits this one comment on every review. Comment Reviewed November 2, 2026, 3:22 AM ET / 08:22 UTC. |
Emit incoming typing events when the chat transcript's typing indicator appears or disappears (openclaw#378, thanks @logananderson). Co-authored-by: Logan Anderson <poggus@gmail.com>
2c1e18b to
43b00f2
Compare
What
imsg watch --bb-eventsandbridge.events.subscribe(both read.imsg-events.jsonl) never receive thestarted-typing/stopped-typingevents that docs/watch.md, docs/bridge.md, docs/rpc.md and section 5 ofTests/imsgTests/README-live.md("typing events streaming") describe. The observer that writes them, added with the bridge port in #100, has never fired:@"IMChatItemsDidChangeNotification". IMCore posts@"__kIMChatItemsDidChangeNotification"(the value of itsIMChatItemsDidChangeNotificationconstant), so the block never runs.__kIMChatValueKeyorinserted, and the notification has neither. Observed keys, every time:__kIMChatItemsOldItemsand__kIMChatItemsNewItems(the chat's items before and after),__kIMChatItemsInsertedand__kIMChatItemsRemoved(index sets into those lists),__kIMChatItemsReloadand__kIMChatItemsRegenerate.While someone else is typing, the chat's items include an
IMTypingChatItem. The observer now checks the old and new lists for one and emitsstarted-typingwhen it appears,stopped-typingwhen it goes. It looks through the list rather than at the last item: a chat whose transcript hasn't been opened in Messages, and the group chat below, end in anIMReportSpamChatItem, with the typing item earlier in the list. IMCore also hasIMGroupTypingChatItem, a subclass ofIMTypingChatItem(checked at runtime on macOS 26), which the class check covers. The GUID is read with the existingsafelyReadObjectSelector, and only when there is an event.stopped-typingfollows the transcript indicator: it comes when the message arrives, when the sender clears the draft, or when the indicator expires (90 seconds after an abandoned draft in the run below). The local account's own typing isn't reported. If a macOS version lacks either list or theIMTypingChatItemclass, nothing is emitted, which is the behavior today.Tests
Tests/IMsgHelperTests/TypingEventTests.mposts the real notification through the registered observers and reads an isolated event log, so it compiles unchanged against main. Failing first on main (5af52a0):Live proof
macOS 26.6.2 (25G83) arm64 VM, iPhone on the other side. One release CLI (
0.20.0; this change doesn't touch the CLI), with the injected helper swapped between main (5af52a0) and this commit and Messages relaunched after each swap. Both runs in the same 1:1 chat: type without sending, clear the draft, then type and send. Phone numbers replaced with+1555…, message text omitted.imsg watch --bb-events --json, main helper (its.imsg-bridge.logshows2026-11-02T07:20:25Z bootstrap complete, logged afterregisterEventObservers()):This commit:
07:56:11 is the cleared draft; 07:56:30 is the send.
Then, with the same watch running, the helper's typing action was sent to that chat for 8 seconds over the bridge. The iPhone showed the indicator and the watch printed nothing:
Four more runs on this commit's code plus a temporary log of each notification's lists:
Two of those notifications, trimmed (
typingis whether the list contains anIMTypingChatItem):Checks
Not run: macOS 27, and a live run on macOS 14 or 15. On macOS 15.6.1 the dyld shared cache contains
__kIMChatItemsDidChangeNotification,__kIMChatItemsNewItemsandIMTypingChatItem, but I have no working iMessage number on that machine.