fix(imessage): honor block streaming config#91449
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 8, 2026, 12:04 PM ET / 16:04 UTC. Summary PR surface: Source +97, Tests +314, Generated +1. Total +412 across 10 files. Reproducibility: yes. for the source-level gap: current main's iMessage monitor only reads flat Review metrics: 1 noteworthy metric.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Mantis proof suggestion Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land this after maintainer acceptance of the iMessage flat/nested streaming precedence contract and green required checks, keeping flat Do we have a high-confidence way to reproduce the issue? Yes for the source-level gap: current main's iMessage monitor only reads flat Is this the best way to solve the issue? Yes, with maintainer acceptance of the config contract: using the existing shared resolver is the cleanest owner-boundary fix, and the latest account merge preserves flat account overrides. The only safer alternative is a narrower flat-only fix if maintainers reject adding nested iMessage streaming config now. AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against 57633c42b647. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +97, Tests +314, Generated +1. Total +412 across 10 files. View PR surface stats
Acceptance criteria:
What 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
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ae002d0b74
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| (cfg.channels?.imessage as Record<string, unknown> | undefined)?.streaming, | ||
| (accountConfig as Record<string, unknown> | undefined)?.streaming, | ||
| ); | ||
| return streaming !== undefined ? ({ ...merged, streaming } as IMessageAccountConfig) : merged; |
There was a problem hiding this comment.
Preserve flat account blockStreaming overrides
When a channel opts into the new channels.imessage.streaming.block.enabled=true, this merge always carries that nested streaming object onto each account unless the account also has a nested streaming object. An existing account-level accounts.<id>.blockStreaming=false is then present alongside inherited streaming.block.enabled=true; resolveChannelStreamingBlockEnabled(accountInfo.config) checks the nested value before the flat flag, so dispatch receives disableBlockStreaming=false and block replies are sent for an account that explicitly disabled them. Since blockStreaming remains an accepted iMessage account config key, mixed old/new configs lose per-account opt-outs.
Useful? React with 👍 / 👎.
ae002d0 to
cc32d16
Compare
cc32d16 to
28f7918
Compare
|
updated original post with more detailed logs as proof — I am living on this change with my family's local OpenClaw and it's often giving me at least one intermediary message before final reply. Without this change I only ever see final reply. My family primarily uses OpenClaw via iMessage and the timing difference with this change is easy to feel. |
28f7918 to
7183e7a
Compare
Route iMessage inbound reply dispatch through the shared block-streaming resolver so the channel respects schema-valid channels.imessage.blockStreaming values instead of bypassing them on the monitor path. Also keep the iMessage streaming schema/tests aligned with the shared channel delivery streaming shape.
7183e7a to
78595d9
Compare
|
Merged via squash.
Thanks @jmissig! |
|
@clawsweeper re-review |
|
🦞🧹 Reason: re-review requires an open issue or PR. |
Merged via squash. Prepared head SHA: 6e4e04f Co-authored-by: jmissig <1448107+jmissig@users.noreply.github.com> Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com> Reviewed-by: @omarshahine
…26.6.6) (#1040) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/openclaw/openclaw](https://openclaw.ai) ([source](https://github.com/openclaw/openclaw)) | patch | `2026.6.5` → `2026.6.6` | --- ### Release Notes <details> <summary>openclaw/openclaw (ghcr.io/openclaw/openclaw)</summary> ### [`v2026.6.6`](https://github.com/openclaw/openclaw/blob/HEAD/CHANGELOG.md#202666) [Compare Source](openclaw/openclaw@v2026.6.5...v2026.6.6) ##### Highlights - Security boundaries are substantially tighter across transcripts, sandbox binds, host environment inheritance, MCP stdio, Codex HTTP access, native search policy, elevated sender checks, deleted-agent ACP bypasses, loopback tools, Discord moderation, and Teams group actions; exec approvals now fail closed on timeout. ([#​91529](openclaw/openclaw#91529), [#​91618](openclaw/openclaw#91618), [#​91615](openclaw/openclaw#91615), [#​91619](openclaw/openclaw#91619), [#​91741](openclaw/openclaw#91741), [#​91745](openclaw/openclaw#91745), [#​91746](openclaw/openclaw#91746), [#​91748](openclaw/openclaw#91748), [#​91749](openclaw/openclaw#91749), [#​91750](openclaw/openclaw#91750), [#​91751](openclaw/openclaw#91751), [#​91752](openclaw/openclaw#91752), [#​91763](openclaw/openclaw#91763), [#​89938](openclaw/openclaw#89938)) Thanks [@​joshavant](https://github.com/joshavant), [@​pgondhi987](https://github.com/pgondhi987), [@​mmaps](https://github.com/mmaps), [@​eleqtrizit](https://github.com/eleqtrizit), [@​shakkernerd](https://github.com/shakkernerd), and [@​drobison00](https://github.com/drobison00). - Telegram delivery is safer and more coherent: account-scoped topics route to the right agent, streamed text survives tool calls, `/compact` works on generic ingress, callback handling uses concrete APIs, draft chunking is shared, durable dispatch dedupe moved into the SDK, and unauthorized DM text stays out of cache and prompt context. ([#​91189](openclaw/openclaw#91189), [#​88682](openclaw/openclaw#88682), [#​89588](openclaw/openclaw#89588), [#​90212](openclaw/openclaw#90212), [#​91876](openclaw/openclaw#91876), [#​91874](openclaw/openclaw#91874), [#​91904](openclaw/openclaw#91904), [#​91478](openclaw/openclaw#91478), [#​91915](openclaw/openclaw#91915)) Thanks [@​codysai001](https://github.com/codysai001), [@​alexzhu0](https://github.com/alexzhu0), [@​joelnishanth](https://github.com/joelnishanth), [@​snowzlm](https://github.com/snowzlm), [@​obviyus](https://github.com/obviyus), and [@​sallyom](https://github.com/sallyom). - iMessage recovery and delivery now cover always-on inbound restart, durable echo markers, block streaming, idle approval discovery, hardened outbound transport, and actionable inbound startup diagnostics. ([#​91335](openclaw/openclaw#91335), [#​91449](openclaw/openclaw#91449), [#​88969](openclaw/openclaw#88969), [#​88530](openclaw/openclaw#88530), [#​91783](openclaw/openclaw#91783), [#​91785](openclaw/openclaw#91785)) Thanks [@​omarshahine](https://github.com/omarshahine), [@​jmissig](https://github.com/jmissig), and [@​colmbrogan](https://github.com/colmbrogan). - Browser and MCP connectivity gained existing-session CDP support, discovered WebSocket validation, default-profile `cdpUrl` handling, safer browser-output boundaries, Streamable HTTP loopback transport, corrected OAuth/SSE authorization handling, and broader schema compatibility. ([#​91422](openclaw/openclaw#91422), [#​89851](openclaw/openclaw#89851), [#​91736](openclaw/openclaw#91736), [#​91747](openclaw/openclaw#91747), [#​91451](openclaw/openclaw#91451), [#​80143](openclaw/openclaw#80143)) Thanks [@​pgondhi987](https://github.com/pgondhi987), [@​anagnorisis2peripeteia](https://github.com/anagnorisis2peripeteia), [@​lifuyue](https://github.com/lifuyue), [@​eleqtrizit](https://github.com/eleqtrizit), [@​LiuwqGit](https://github.com/LiuwqGit), and [@​HemantSudarshan](https://github.com/HemantSudarshan). - Control UI startup and first-reply latency are lower through cached model metadata, removal of the startup catalog wait, lazy slash-command loading, and first-event tracing with slow-reply diagnostics. ([#​91531](openclaw/openclaw#91531), [#​91538](openclaw/openclaw#91538), [#​91568](openclaw/openclaw#91568), [#​91583](openclaw/openclaw#91583), [#​91598](openclaw/openclaw#91598)) - Provider support expands with OpenRouter OAuth onboarding and Claude Fable 5 adaptive thinking, while Codex sessions keep correct compaction ownership, local models skip guardian review, dynamic tool progress normalizes cleanly, and Gemma 4 reasoning replay is preserved. ([#​91830](openclaw/openclaw#91830), [#​91882](openclaw/openclaw#91882), [#​91590](openclaw/openclaw#91590), [#​88630](openclaw/openclaw#88630), [#​88768](openclaw/openclaw#88768), [#​91696](openclaw/openclaw#91696)) Thanks [@​Patrick-Erichsen](https://github.com/Patrick-Erichsen), [@​joshavant](https://github.com/joshavant), [@​bdjben](https://github.com/bdjben), and [@​Coder-Wangyankun](https://github.com/Coder-Wangyankun). ##### Changes - CLI progress: emit Claude CLI commentary progress events and bridge inter-tool commentary into channel progress without exposing internal protocol scaffolding. ([#​89834](openclaw/openclaw#89834), [#​90883](openclaw/openclaw#90883)) Thanks [@​anagnorisis2peripeteia](https://github.com/anagnorisis2peripeteia). - Observability: allow trusted diagnostics channels to capture tool input/output content, add first-assistant-event traces, and warn on slow initial replies. ([#​91256](openclaw/openclaw#91256), [#​91568](openclaw/openclaw#91568), [#​91583](openclaw/openclaw#91583)) Thanks [@​amknight](https://github.com/amknight). - Plugins/ClawHub: dogfood reusable package publishing, let dry runs skip publish approval, allow declared installed trusted hooks, report managed plugin version drift, and warn instead of failing on retired Skill Workshop configuration. ([#​91574](openclaw/openclaw#91574), [#​91591](openclaw/openclaw#91591), [#​90004](openclaw/openclaw#90004), [#​90927](openclaw/openclaw#90927), [#​90838](openclaw/openclaw#90838)) Thanks [@​Patrick-Erichsen](https://github.com/Patrick-Erichsen), [@​brokemac79](https://github.com/brokemac79), and [@​lonexreb](https://github.com/lonexreb). - Memory/providers: move the local llama.cpp runtime into its provider plugin, batch embeddings across files, persist the agent model catalog cache, and keep QMD JSON search one-shot while filtering stale REM recall previews. ([#​91324](openclaw/openclaw#91324), [#​89138](openclaw/openclaw#89138), [#​90457](openclaw/openclaw#90457), [#​91837](openclaw/openclaw#91837), [#​91851](openclaw/openclaw#91851)) Thanks [@​osolmaz](https://github.com/osolmaz), [@​mushuiyu886](https://github.com/mushuiyu886), [@​ai-hpc](https://github.com/ai-hpc), and [@​TurboTheTurtle](https://github.com/TurboTheTurtle). - Channels/mobile: add the QQBot group mention toggle, improve iPad and iPhone control surfaces, and expose the active connection host in the TUI footer. ([#​91423](openclaw/openclaw#91423), [#​91557](openclaw/openclaw#91557), [#​89909](openclaw/openclaw#89909)) Thanks [@​cxyhhhhh](https://github.com/cxyhhhhh), [@​Solvely-Colin](https://github.com/Solvely-Colin), and [@​baskduf](https://github.com/baskduf). - Performance: prewarm TUI runtime plugins, deduplicate plugin auto-enable fanout, trim dense text-delta snapshots, and reuse prepared startup model metadata. ([#​90782](openclaw/openclaw#90782), [#​89978](openclaw/openclaw#89978), [#​91580](openclaw/openclaw#91580), [#​91531](openclaw/openclaw#91531)) Thanks [@​RomneyDa](https://github.com/RomneyDa) and [@​ai-hpc](https://github.com/ai-hpc). ##### Fixes - Agent/session recovery: drop stale approval follow-ups after session rebind, remove drained reply-queue items by identity, recover stale main and visible replies, preserve Codex context-engine compaction ownership, lower the default compaction timeout to 180 seconds while respecting explicit configuration, and keep provider-failure terminal lifecycle state correct. ([#​85679](openclaw/openclaw#85679), [#​91450](openclaw/openclaw#91450), [#​91566](openclaw/openclaw#91566), [#​91840](openclaw/openclaw#91840), [#​91590](openclaw/openclaw#91590), [#​91361](openclaw/openclaw#91361), [#​91895](openclaw/openclaw#91895)) Thanks [@​openperf](https://github.com/openperf), [@​yetval](https://github.com/yetval), [@​joshavant](https://github.com/joshavant), [@​wangmiao0668000666](https://github.com/wangmiao0668000666), and [@​TurboTheTurtle](https://github.com/TurboTheTurtle). - User-visible content boundaries: suppress Codex/Harmony protocol artifacts, neutralize browser and LanceDB memory media directives, redact transcript images, and preserve native `/compact` replies through source suppression. ([#​89151](openclaw/openclaw#89151), [#​91422](openclaw/openclaw#91422), [#​91425](openclaw/openclaw#91425), [#​91529](openclaw/openclaw#91529), [#​90212](openclaw/openclaw#90212)) Thanks [@​joelnishanth](https://github.com/joelnishanth), [@​pgondhi987](https://github.com/pgondhi987), [@​joshavant](https://github.com/joshavant), and [@​snowzlm](https://github.com/snowzlm). - Channel delivery: keep WhatsApp captured replies attached to the successor controller after restart, retry Feishu rate limits, preserve Mattermost thread replies, canonicalize LINE webhook paths, restore Discord reply hydration and runtime timeout exports, and show OpenAI Realtime WebRTC assistant transcripts. ([#​85823](openclaw/openclaw#85823), [#​89659](openclaw/openclaw#89659), [#​91684](openclaw/openclaw#91684), [#​91649](openclaw/openclaw#91649), [#​90263](openclaw/openclaw#90263), [#​91686](openclaw/openclaw#91686), [#​90426](openclaw/openclaw#90426)) Thanks [@​itsuzef](https://github.com/itsuzef), [@​ladygege](https://github.com/ladygege), [@​jacobtomlinson](https://github.com/jacobtomlinson), [@​fuller-stack-dev](https://github.com/fuller-stack-dev), and [@​shushushv](https://github.com/shushushv). - Cron: cancel active task runs cleanly, preserve terminal timeout/cancel state, and recover no-deliver tool warnings instead of silently losing the outcome. ([#​90666](openclaw/openclaw#90666), [#​90678](openclaw/openclaw#90678)) Thanks [@​ai-hpc](https://github.com/ai-hpc). - Gateway/config/auth: share the approval runtime socket token, replace arrays explicitly in `config.patch`, skip the deleted-agent guard only for valid ACP harness sessions, surface headless LaunchAgent state, verify SQLite auth migration before cleanup, and arm QMD startup maintenance. ([#​87105](openclaw/openclaw#87105), [#​91551](openclaw/openclaw#91551), [#​91219](openclaw/openclaw#91219), [#​91614](openclaw/openclaw#91614), [#​91740](openclaw/openclaw#91740), [#​91978](openclaw/openclaw#91978)) Thanks [@​fuller-stack-dev](https://github.com/fuller-stack-dev) and [@​scotthuang](https://github.com/scotthuang). - Providers/Codex: clarify quota errors, restore the Codex synthetic usage line, canonicalize Codex protocol assets, require API-key auth for realtime voice, normalize ACP model refs, preserve Gemma 4 `reasoning_content`, and avoid guardian review for local models. ([#​91390](openclaw/openclaw#91390), [#​91709](openclaw/openclaw#91709), [#​91507](openclaw/openclaw#91507), [#​91567](openclaw/openclaw#91567), [#​88630](openclaw/openclaw#88630), [#​91696](openclaw/openclaw#91696)) Thanks [@​hxy91819](https://github.com/hxy91819), [@​brokemac79](https://github.com/brokemac79), [@​RomneyDa](https://github.com/RomneyDa), [@​joshavant](https://github.com/joshavant), and [@​Coder-Wangyankun](https://github.com/Coder-Wangyankun). - Updates/builds: recover package Gateway restarts after refresh failure, expose plugin convergence repair, fall back to Corepack in PATH-less pnpm environments, seed the correct Docker store packages, and keep ClawHub dry-run and publish paths reusable. ([#​91581](openclaw/openclaw#91581), [#​91599](openclaw/openclaw#91599), [#​91547](openclaw/openclaw#91547), [#​91591](openclaw/openclaw#91591)) Thanks [@​fuller-stack-dev](https://github.com/fuller-stack-dev), [@​sallyom](https://github.com/sallyom), and [@​Patrick-Erichsen](https://github.com/Patrick-Erichsen). - UI: require explicit user intent before opening chat sessions and drain restored chat queues after session switches. ([#​91480](openclaw/openclaw#91480)) Thanks [@​TurboTheTurtle](https://github.com/TurboTheTurtle). - Android: avoid the `dataSync` foreground-service type for persistent nodes. ([#​80082](openclaw/openclaw#80082)) Thanks [@​davelutztx](https://github.com/davelutztx). - Native hooks: bound relay lifetimes so abandoned native hook connections cannot linger indefinitely. ([#​91550](openclaw/openclaw#91550)) Thanks [@​joshavant](https://github.com/joshavant). </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEwMS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19--> Reviewed-on: https://git.erwanleboucher.dev/eleboucher/homelab/pulls/1040
Summary
What problem does this PR solve?
channels.imessage.blockStreaming: truedid not make iMessage send interim/progress block replies before the final answer.channels.imessage.streaming.block.enabled, because moving iMessage onto the shared resolver path needs the shared shape to pass schema/config validation and precedence tests.blockStreamingopt-ins/opt-outs when inheriting channel-level nested streaming config.Why does this matter now?
channels.imessage.blockStreaming: truewas enabled and valid, but iMessage still behaved as if block streaming was off: longer turns often produced no visible outbound iMessage until the final answer.What is the intended outcome?
channels.imessage.blockStreaming: trueconfig works for iMessage delivery.blockStreamingsettings continue to work.streaming.block.enabledand mixed channel/account configs behave predictably because the shared resolver path requires those cases to be valid and tested.What is intentionally out of scope?
streaming.block.enabledfor iMessage block streaming.What does success look like?
channels.imessage.blockStreaming: true, iMessage can emit interim/progress replies before final answers.What should reviewers focus on?
Linked context
Which issue does this close?
N/A
Which issues, PRs, or discussions are related?
Related #62387
Was this requested by a maintainer or owner?
No public issue link yet; this came from local real-world iMessage behavior while preparing the fix.
Real behavior proof (required for external PRs)
Behavior addressed: Enabling the existing flat iMessage config
channels.imessage.blockStreaming: truedid not work in real iMessage delivery: iMessage could stay silent until the final answer instead of sending interim/progress block replies.Real environment tested: Local OpenClaw running on Saga with the real iMessage channel and Apple Messages delivery. The local behavior evidence used the installed schema-valid config shape
channels.imessage.blockStreaming: true,channels.imessage.streaming: null,channels.imessage.chunkMode: "newline".Exact steps or command run after this patch:
Evidence after fix: Redacted Apple Messages
chat.dbtimestamp extract from the real iMessage channel, cross-checked with the OpenClaw session/log snippet text:Observed result after fix: In the local real iMessage environment, the existing flat
channels.imessage.blockStreaming: truesetup produced an interim/progress iMessage before the final answer.What was not tested: Full
pnpm build && pnpm check && pnpm testwas not run locally; broad validation is delegated to Testbox/CI. No gateway restart was performed during the local config correction.Proof limitations or environment constraints: Apple Messages
chat.dbproves platform-visible send timing, not the exact in-process object lookup. Current main source has an apparent direct flat lookup, but the real flat-config behavior remained broken. This patch moves iMessage to the shared resolver path, keeps flat config supported, and adds the nested/canonical schema/type support needed for shared validation tests and precedence coverage.Before evidence (optional but encouraged):
Tests and validation
Which commands did you run?
What regression coverage was added or updated?
blockStreamingtrue/false, nested true/false, and unset block-streaming config are passed through to reply dispatch.blockStreamingopt-ins/opt-outs override inherited channel-level nestedstreaming.block.enabledwhen the account lacks its own nested block setting.streaming.block.enabledsurvives partial account-level streaming overrides such aschunkModeorblock.coalesce.What failed before this fix, if known?
channels.imessage.blockStreaming: true, multiple iMessage turns had no visible outbound iMessage until the final answer.blockStreaminglookup, but the real flat-config behavior remained broken; this PR keeps the flat behavior supported and covered while moving iMessage to the shared resolver path.If no test was added, why not?
Not applicable; focused regression tests were added.
Risk checklist
Did user-visible behavior change? (
Yes/No)Yes. iMessage should now honor the existing flat block-streaming config in real delivery and can also honor nested/canonical block streaming config, allowing interim/progress replies before final answers when the effective config enables block streaming.
Did config, environment, or migration behavior change? (
Yes/No)Yes. iMessage now accepts the shared nested
streamingdelivery config shape so shared config validation and precedence coverage can exercise that path. Existing flatblockStreamingconfig remains supported and does not require migration.Did security, auth, secrets, network, or tool execution behavior change? (
Yes/No)No.
What is the highest-risk area?
iMessage reply delivery timing/config resolution. The risk is accidentally disabling block streaming when a user configured it, or enabling it when a user explicitly disabled it.
How is that risk mitigated?
The iMessage monitor now uses the shared resolver and tests cover enabled, disabled, nested, unset, account flat override, and account-inherited nested cases before dispatch.
Current review state
What is the next action?
Wait for CI/Testbox and maintainer review.
What is still waiting on author, maintainer, CI, or external proof?
pnpm build && pnpm check && pnpm test.Which bot or reviewer comments were addressed?
codex review --base origin/mainfirst found one P2 around partial account-level nestedstreamingoverrides dropping inherited channel-levelstreaming.block.enabled. Addressed by deep-merging the iMessage delivery streaming subtree during account config resolution and adding focused account-inheritance monitor tests.blockStreamingopt-outs could be overridden by inherited channel nested config. Addressed by preserving explicit account-level flatblockStreamingwhen inheriting nested channel streaming and adding focused regression coverage.Follow-up
codex review --base origin/mainresult: no actionable regressions found.