Skip to content

Matrix: keep partial previews aligned with block streaming#59384

Merged
gumadeiras merged 10 commits into
mainfrom
codex/matrix-partial-block-streaming
Apr 2, 2026
Merged

Matrix: keep partial previews aligned with block streaming#59384
gumadeiras merged 10 commits into
mainfrom
codex/matrix-partial-block-streaming

Conversation

@gumadeiras

@gumadeiras gumadeiras commented Apr 2, 2026

Copy link
Copy Markdown
Member

Summary

  • Problem: Matrix streaming: "partial" and blockStreaming: true were not just incompatible in config wiring; async block delivery could also desynchronize draft offsets and assistant-message generations.
  • Why it matters: under slow Matrix sends or fast model output, later partials could be sliced against stale boundaries, leading to duplicated, dropped, rewound, or cross-message draft text.
  • What changed: Matrix now keeps partial previews for the active block, preserves completed block messages when block streaming is enabled, queues logical block boundaries before async delivery, and carries source assistantMessageIndex metadata so delayed block flushes stay attached to the correct message generation.
  • What did NOT change (scope boundary): no config shape change, no other channel behavior change, no transport/protocol redesign, and no change to default streaming: "off" behavior.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #
  • Related #
  • This PR fixes a bug or regression

Root Cause / Regression History (if applicable)

  • Root cause 1: the Matrix handler originally forced disableBlockStreaming=true whenever partial drafts were enabled, so explicit channels.matrix.blockStreaming intent was ignored.
  • Root cause 2: once shared block streaming was re-enabled, Matrix draft bookkeeping still followed transport completion instead of logical block boundaries, so async block sends could leave onPartialReply slicing against stale offsets.
  • Root cause 3: text_end block flushes can be deferred past onAssistantMessageStart, so old block boundaries could be stamped with the next assistant message generation unless the source generation is captured and routed through.
  • Missing detection / guardrail: coverage only checked option wiring, not block/draft/final sequencing, delayed block drain ordering, or late block boundaries crossing assistant-message starts.
  • Prior context (git blame, prior PR, issue, or refactor if known): this extends earlier Matrix draft-streaming and block-streaming behavior rather than introducing a new delivery model.
  • If unknown, what was ruled out: no evidence of a Matrix transport-only bug; the fault was in local reply-state bookkeeping and metadata routing.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target tests/files:
    • extensions/matrix/src/matrix/monitor/handler.test.ts
    • src/auto-reply/reply/dispatch-from-config.test.ts
    • src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.emits-block-replies-text-end-does-not.test.ts
  • Scenarios locked in:
    • partial previews plus explicit Matrix block streaming
    • completed-block preservation plus active-draft finalization
    • delayed block delivery with later partials already received
    • multiple queued block boundaries
    • assistant-message start arriving before an older text_end block flush drains
    • source assistantMessageIndex propagation into block-boundary queueing
  • Why this is the smallest reliable guardrail: the bug spans producer -> shared dispatch -> Matrix consumer, so coverage has to pin each routing seam plus the Matrix state machine.

User-visible / Behavior Changes

  • Matrix can now safely combine streaming: "partial" with blockStreaming: true.
  • The active assistant block stays a live editable draft.
  • Completed blocks can remain preserved as separate Matrix messages.
  • Delayed block sends no longer rewind or corrupt the next draft block or the next assistant message's draft when boundaries arrive late.

Diagram (if applicable)

Before:
[user prompt]
  -> [draft current block]
  -> [async block send lags]
  -> [later partial slices from stale offset]
  -> [duplicate/rewind/drop text possible]

After:
[user prompt]
  -> [draft current block]
  -> [logical block boundary queued immediately]
  -> [completed block preserved when delivery drains]
  -> [next draft starts from queued boundary]
  -> [late old block still routed to original assistant message generation]

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: Node 22+, pnpm
  • Model/provider: N/A
  • Integration/channel (if any): Matrix
  • Relevant config (redacted): channels.matrix.streaming: "partial", channels.matrix.blockStreaming: true

Steps

  1. Enable Matrix partial draft streaming and block streaming.
  2. Trigger an assistant reply with multiple blocks or a delayed text_end block flush.
  3. Let later partials or a new assistant-message start arrive before the older block delivery drains.
  4. Observe draft/block sequencing.

Expected

  • Active block uses a live editable draft.
  • Completed blocks remain preserved as separate messages when block streaming is enabled.
  • Later partials start from the correct logical block boundary.
  • Late block flushes remain associated with the original assistant message generation.

Actual

  • Covered by the updated targeted tests in this PR.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: reviewed producer -> dispatch -> Matrix routing, updated Matrix/docs contracts, ran focused regressions for queued boundaries, late text_end, and message-generation propagation.
  • Edge cases checked: partial previews with block streaming off, partial previews with block streaming on, delayed block delivery, multiple queued boundaries, new assistant message before old block drain.
  • What you did not verify: live Matrix homeserver/manual room repro in this branch.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps:

Risks and Mitigations

  • Risk: the state machine is more explicit now because it has to track queued block boundaries and source generations.
    • Mitigation: keep Matrix-specific policy inside the Matrix plugin, keep the shared seam additive (onBlockReplyQueued + optional metadata), and pin the routing contract with targeted tests.

Copilot AI review requested due to automatic review settings April 2, 2026 03:39
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: matrix Channel integration: matrix size: XS maintainer Maintainer-authored PR labels Apr 2, 2026
@greptile-apps

greptile-apps Bot commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a bug where streaming: "partial" unconditionally set disableBlockStreaming: true, making channels.matrix.blockStreaming ineffective when live draft previews were enabled. The fix simplifies the one-line expression to !blockStreamingEnabled, the deliver callback's existing info.kind === "block" path already handles finalizing the current draft and resetting it for the next block, so no additional logic is needed.

Confidence Score: 5/5

  • Safe to merge — minimal one-line fix with correct test coverage and no behavioral change when block streaming is off.
  • The fix is a single-expression simplification with a clear root cause, appropriate unit tests covering both the enabled and disabled cases, updated docs and types, and no change to the default behavior or existing code paths.
  • No files require special attention.

Reviews (1): Last reviewed commit: "Matrix: record partial preview block con..." | Re-trigger Greptile

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes Matrix reply delivery so streaming: "partial" can coexist with channels.matrix.blockStreaming: true, preserving completed assistant block messages while still using a live editable draft for the current block.

Changes:

  • Update Matrix handler reply options so block streaming is only disabled when Matrix block streaming is not enabled (no longer implicitly disabled by partial draft streaming).
  • Extend Matrix handler config tests to assert the correct disableBlockStreaming behavior for partial previews with block streaming on/off.
  • Update Matrix config/type docs and channel docs to describe the combined behavior.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
extensions/matrix/src/types.ts Clarifies streaming/blockStreaming semantics in the Matrix config type docs.
extensions/matrix/src/matrix/monitor/handler.ts Changes disableBlockStreaming wiring to allow block streaming alongside partial draft previews when explicitly enabled.
extensions/matrix/src/matrix/monitor/handler.test.ts Adds/updates unit tests covering the new coexistence contract.
docs/channels/matrix.md Documents how partial previews interact with Matrix block streaming.
CHANGELOG.md Notes the Matrix streaming behavior fix in Unreleased fixes.

@gumadeiras gumadeiras self-assigned this Apr 2, 2026
@Regg819

This comment was marked as spam.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 42a2114c5d

ℹ️ 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".

Comment thread extensions/matrix/src/matrix/monitor/handler.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: beb808281e

ℹ️ 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".

Comment thread extensions/matrix/src/matrix/monitor/handler.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7789ac7d5b

ℹ️ 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".

Comment thread extensions/matrix/src/matrix/monitor/handler.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 11c2158a3a

ℹ️ 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".

Comment thread extensions/matrix/src/matrix/monitor/handler.ts Outdated
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: L and removed size: M labels Apr 2, 2026
@gumadeiras gumadeiras changed the title Matrix: preserve block streaming with partial previews Matrix: keep partial previews aligned with block streaming Apr 2, 2026
@gumadeiras
gumadeiras force-pushed the codex/matrix-partial-block-streaming branch from 7980047 to 5856d97 Compare April 2, 2026 07:31
Track queued Matrix block boundaries in order so the live draft stays scoped
to the current block even when multiple block replies queue before Matrix
delivery drains.

This also adds regression coverage for multi-boundary rotation and keeps
assistant-message resets from reopening stale draft text.
Keep queued Matrix block boundaries tagged to their assistant message so a
new assistant-message start cannot erase the bookkeeping for older in-flight
block deliveries.

This prevents delayed block drains from rewinding or dropping the next draft
preview and adds regression coverage for the cross-message race.
Capture the source assistant-message index before text_end flushes cross the
microtask boundary, then thread that metadata into queued block-boundary
signals for Matrix.

This keeps delayed block replies attached to the correct message generation
and adds regressions for the late-boundary routing path.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5856d97125

ℹ️ 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".

Comment thread extensions/matrix/src/matrix/monitor/handler.ts
@gumadeiras
gumadeiras force-pushed the codex/matrix-partial-block-streaming branch from 5856d97 to 981aa35 Compare April 2, 2026 07:38
@gumadeiras
gumadeiras merged commit 8748b7c into main Apr 2, 2026
9 checks passed
@gumadeiras
gumadeiras deleted the codex/matrix-partial-block-streaming branch April 2, 2026 07:39
@gumadeiras

Copy link
Copy Markdown
Member Author

Merged via squash.

Thanks @gumadeiras!

ngutman pushed a commit that referenced this pull request Apr 3, 2026
Merged via squash.

Prepared head SHA: 981aa35
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras
steipete pushed a commit to duncanita/openclaw that referenced this pull request Apr 4, 2026
…59384)

Merged via squash.

Prepared head SHA: 981aa35
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
…59384)

Merged via squash.

Prepared head SHA: 981aa35
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
…59384)

Merged via squash.

Prepared head SHA: 981aa35
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…59384)

Merged via squash.

Prepared head SHA: 981aa35
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
…59384)

Merged via squash.

Prepared head SHA: 981aa35
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras
Nachx639 pushed a commit to Nachx639/clawdbot that referenced this pull request Jun 17, 2026
…59384)

Merged via squash.

Prepared head SHA: 981aa35
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling channel: matrix Channel integration: matrix docs Improvements or additions to documentation maintainer Maintainer-authored PR size: L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants