Skip to content

Optimize chat timeline, streaming, Hermes, and native navigation#578

Merged
cogwheel0 merged 17 commits into
mainfrom
streaming-thermal-regression
Jul 18, 2026
Merged

Optimize chat timeline, streaming, Hermes, and native navigation#578
cogwheel0 merged 17 commits into
mainfrom
streaming-thermal-regression

Conversation

@cogwheel0

@cogwheel0 cogwheel0 commented Jul 16, 2026

Copy link
Copy Markdown
Owner

Summary

  • Refactor the chat timeline into one managed SuperSliverList with layout-time bottom anchoring, stable keyed extents, and correct detached scrolling for both long and short conversations.
  • Reduce streaming CPU and allocation pressure with buffered text accumulation, same-frame flush scheduling, append-oriented Markdown updates, geometrically bounded structured-output projection, and depth-, node-, and cycle-bounded traversal of untrusted structured values.
  • Preserve the iOS Liquid Glass composer and native controls while stabilizing native navigation, template avatars, profile settings, and Android toolbar sizing.
  • Align Hermes Runs and Responses with the official session model, replay conversation context, refresh new sessions, and restore persisted tool statuses when chats reopen.
  • Update the pinned super_sliver_list fork and add regression coverage across timeline anchoring, streaming, Hermes sessions, native routing, and avatar rendering.

Verification

  • flutter analyze (no issues)
  • flutter test (4,012 passed; 2 skipped)
  • iOS RunnerTests on iPhone 17 Pro simulator (4 passed)

Note

Optimize chat timeline layout, streaming buffering, Hermes history, and native avatar rendering

  • Replaces per-frame sticky-correction and row-measurement loops in the chat timeline with layout anchoring via ChatBottomScrollSettler and a synthetic composer spacer inside the SuperSliverList, reducing scroll jitter during live streaming
  • Buffers streamed assistant content in a StringBuffer per projection and materializes to an immutable string only when needed, reducing allocations and redundant content rewrites during streaming
  • Adds a StructuredOutputStreamingProjector that appends plain-text suffixes when safe and forces full replacements only on structural/status transitions, bounding render work during structured output streaming
  • Switches Hermes Runs continuity from chaining by previousRunId to sending an explicit conversationHistory payload; Responses API new chains omit the pre-created session and include conversation history instead
  • Maps persisted Hermes tool-role rows into statusHistory entries on their associated assistant messages rather than emitting them as standalone chat messages
  • Replaces scheduleFrame + addPostFrameCallback with a single scheduleFrameCallback in assistant message and streaming markdown widgets, applying updates within the scheduled frame and removing one extra frame per update
  • Adds avatarIsTemplate support to the native profile sheet: Flutter passes the flag through the Pigeon API; iOS renders template avatars with .label tint and aspect-fit content mode
  • Flattens the Profile settings page from categorized sections into a single scrollable list with dedicated entries for Direct Connections and Data & Connection
  • Risk: Hermes Runs no longer chain via previousRunId; regeneration branches from continuityMessages only, which changes session continuity behavior for existing run-based flows

Macroscope summarized e024dbe.

Summary by CodeRabbit

  • New Features

    • Added template-aware avatars (including dark-mode template rendering) with header-scoped image caching.
    • Enabled Direct Connections native-sheet navigation.
    • Hermes runs can now send conversation history; persisted tool activity is reconstructed more accurately.
    • Updated profile settings UI to a simplified flat list with localized subtitles.
  • Bug Fixes

    • Improved chat bottom anchoring and managed timeline/layout stability.
    • Refined streaming refresh timing and structured-output streaming behavior.
    • Tightened navigation and selection behaviors for native routes.
  • Tests

    • Expanded coverage for avatars, caching keys, Direct Connections navigation, Hermes conversation/tool handling, chat layout stability, and streaming/structured-output projections.

Greptile Summary

This PR updates chat scrolling, streaming output, Hermes sessions, and native profile navigation. The main changes are:

  • Refactors the chat timeline into one managed SuperSliverList with layout-time bottom anchoring.
  • Reduces streaming churn with buffered text accumulation and append-oriented structured-output projection.
  • Aligns Hermes Runs and Responses with session history, session refresh, and persisted tool status restoration.
  • Adds template-aware profile avatars through Dart, iOS, Android, and Pigeon bindings.
  • Updates native settings routes and Direct Connections navigation.
  • Adds tests for timeline anchoring, streaming, Hermes sessions, native routing, and avatar rendering.

Confidence Score: 5/5

This PR appears safe to merge.

No blocking correctness or security issues were identified in the reviewed changed paths. The higher-risk chat timeline, streaming, Hermes, and native avatar changes include bounded guards and targeted tests.

No files require special attention.

T-Rex T-Rex Logs

What T-Rex did

  • Ran the tool availability check and confirmed the process exited with code 0, indicating all required tools were available.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
lib/features/chat/views/chat_page.dart Refactors chat timeline rendering into a managed SuperSliverList with layout-time bottom anchoring and extent reconciliation.
lib/features/chat/views/chat_bottom_anchor_controller.dart Introduces bottom-anchor state and a settle helper that cancels corrections after user gestures.
lib/core/services/streaming_helper.dart Refactors streaming accumulation and structured-output projection to reduce cumulative string churn while preserving terminal reconciliation.
lib/core/services/structured_output_renderer.dart Adds bounded structured-output streaming projection and guarded traversal/equality for untrusted structured values.
lib/features/hermes/services/hermes_api_service.dart Aligns Hermes Runs/Responses requests with session history, bounded response handling, and session headers.
lib/features/hermes/services/hermes_run_transport.dart Updates Hermes transport dispatch to send conversation history, reconcile final output, and accumulate bounded tool statuses.
lib/features/hermes/services/hermes_message_mapper.dart Maps persisted Hermes tool-role messages into assistant status history instead of visible chat rows.
ios/Runner/NativeSheetBridge.swift Adds template avatar rendering and header-scoped native image cache keys for profile sheets.
lib/core/services/native_sheet_bridge.dart Extends native sheet route constants and profile user payloads with direct connections and template avatar metadata.
lib/shared/widgets/markdown/streaming_markdown_widget.dart Schedules streaming Markdown refreshes before build via frame callbacks and preserves stale compiled output during async refresh.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant User
participant ChatPage
participant StreamingHelper
participant Projector as StructuredOutputStreamingProjector
participant Hermes as HermesApiService
participant UI as Managed SuperSliverList

User->>ChatPage: Send message / open Hermes turn
ChatPage->>Hermes: create run or stream response with conversationHistory
Hermes-->>StreamingHelper: token, reasoning, tool, output events
StreamingHelper->>Projector: project cumulative structured output
alt plain tail append
    Projector-->>StreamingHelper: append escaped fragment
    StreamingHelper->>ChatPage: append assistant content/status
else structural transition or bounded replacement
    Projector-->>StreamingHelper: replace authoritative snapshot
    StreamingHelper->>ChatPage: replace assistant content/status
end
ChatPage->>UI: update keyed timeline rows and extents
UI-->>ChatPage: layout metrics and bottom distance
ChatPage->>UI: StickTarget.bottom while anchored
Hermes-->>StreamingHelper: terminal output/session id
StreamingHelper->>Projector: finish final authoritative render
StreamingHelper->>ChatPage: complete streaming UI
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant User
participant ChatPage
participant StreamingHelper
participant Projector as StructuredOutputStreamingProjector
participant Hermes as HermesApiService
participant UI as Managed SuperSliverList

User->>ChatPage: Send message / open Hermes turn
ChatPage->>Hermes: create run or stream response with conversationHistory
Hermes-->>StreamingHelper: token, reasoning, tool, output events
StreamingHelper->>Projector: project cumulative structured output
alt plain tail append
    Projector-->>StreamingHelper: append escaped fragment
    StreamingHelper->>ChatPage: append assistant content/status
else structural transition or bounded replacement
    Projector-->>StreamingHelper: replace authoritative snapshot
    StreamingHelper->>ChatPage: replace assistant content/status
end
ChatPage->>UI: update keyed timeline rows and extents
UI-->>ChatPage: layout metrics and bottom distance
ChatPage->>UI: StickTarget.bottom while anchored
Hermes-->>StreamingHelper: terminal output/session id
StreamingHelper->>Projector: finish final authoritative render
StreamingHelper->>ChatPage: complete streaming UI
Loading

Comments Outside Diff (1)

  1. ios/Runner/NativeSheetBridge.swift, line 5397-5404 (link)

    Header-scoped avatars collide
    NativeSheetImageLoader caches images by rawUrl only (cacheKey = rawUrl), but this new profile-avatar path passes auth-bearing avatarHeaders. When two accounts or servers reuse the same avatar URL with different headers, the second native sheet receives the first cached image without making an authenticated request, exposing the wrong user's avatar.

    Artifacts

    Repro: standalone cache/header collision harness

    • Contains supporting evidence from the run (text/x-ruby; charset=utf-8).

    Repro: execution log showing second header-scoped load served from first cached value

    • Keeps the command output available without making the summary code-heavy.

    View artifacts

    T-Rex Ran code and verified through T-Rex

Reviews (11): Last reviewed commit: "Address final review feedback" | Re-trigger Greptile

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds avatar template metadata across Flutter and native platforms, refactors profile navigation and settings presentation, reworks chat list anchoring and streaming rendering, updates Hermes session/history handling, and restores persisted tool activity into assistant status history.

Changes

Native profile sheets and settings

Layer / File(s) Summary
Avatar metadata and native-sheet navigation
pigeons/..., lib/core/services/native_sheet_bridge.dart, ios/Runner/..., android/app/..., lib/features/navigation/..., lib/main.dart, test/...
Avatar template state is serialized across platforms, rendered natively, and tested. Direct Connections uses a shared native-sheet route and navigation request.
Settings and auth presentation
lib/features/profile/..., lib/features/auth/..., test/features/profile/..., test/features/workspace/...
Profile settings render as a flat widget list, and Android auth back controls use the minimum toolbar action size.

Chat layout and streaming

Layer / File(s) Summary
Timeline metadata, extents, and anchoring
lib/features/chat/views/..., test/features/chat/views/..., pubspec.yaml
Timeline indices include the live tail and composer spacer; managed extent reconciliation and simplified bottom-anchor transitions replace prior sticky correction paths.
Streaming accumulation and structured projection
lib/core/services/..., lib/features/chat/providers/chat_providers.dart, lib/features/chat/widgets/..., lib/shared/widgets/..., test/core/services/..., test/features/chat/..., test/shared/...
Streaming text uses lazy accumulation, structured output uses bounded append/replace projections, and refreshes are scheduled at frame start with corresponding tests.

Hermes transport and persisted messages

Layer / File(s) Summary
Conversation-history transport
lib/features/hermes/services/..., test/features/hermes/..., test/features/chat/providers/..., test/features/chat/widgets/...
Hermes run creation accepts explicit conversation history and dispatchers pass visible prior messages when required.
Responses session-chain flow
lib/features/chat/providers/chat_providers.dart, test/features/chat/providers/...
Responses chains can adopt server-owned sessions, refresh session listings after new sessions, and update document provenance baselines.
Persisted tool status mapping
lib/features/hermes/services/hermes_message_mapper.dart, test/features/hermes/hermes_sessions_test.dart
Persisted assistant tool calls become status-history entries, and matching tool rows mark those entries complete.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

  • cogwheel0/conduit#543: Both changes modify the Open WebUI structured-output streaming pipeline and related rendering tests.

Poem

A rabbit watched the avatars glow,
While chat rows learned where they should go.
Hermes carried history bright,
Tool trails bloomed in status light.
“Hop-hop!” says Bun, “the streams now flow!”

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main themes of the PR: chat timeline, streaming, Hermes, and native navigation updates.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch streaming-thermal-regression

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/features/chat/views/chat_bottom_anchor_controller.dart`:
- Around line 13-20: Update updateAnchor so a false hasScrollableContent does
not automatically set isAnchoredToBottom back to true after detachByUser() has
explicitly detached the anchor. Preserve the existing distanceFromBottom
threshold behavior for scrollable content, while keeping short conversations
detached until an explicit reattach action occurs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6995e78d-79d1-495d-a226-16ac9ed87b67

📥 Commits

Reviewing files that changed from the base of the PR and between 3cfbb9c and 397cbca.

⛔ Files ignored due to path filters (1)
  • pubspec.lock is excluded by !**/*.lock
📒 Files selected for processing (25)
  • android/app/src/main/kotlin/app/cogwheel/conduit/ConduitPlatformApis.g.kt
  • ios/Runner/ConduitPlatformApis.g.swift
  • ios/Runner/NativeSheetBridge.swift
  • ios/RunnerTests/RunnerTests.swift
  • lib/core/platform/conduit_platform_apis.g.dart
  • lib/core/services/native_sheet_bridge.dart
  • lib/core/services/navigation_service.dart
  • lib/features/auth/widgets/adaptive_auth_scaffold.dart
  • lib/features/chat/views/chat_bottom_anchor_controller.dart
  • lib/features/chat/views/chat_page.dart
  • lib/features/chat/views/chat_timeline_render_model.dart
  • lib/features/navigation/widgets/sidebar_user_pill.dart
  • lib/features/profile/models/settings_taxonomy.dart
  • lib/features/profile/views/profile_page.dart
  • lib/main.dart
  • pigeons/conduit_platform_apis.dart
  • pubspec.yaml
  • test/core/router/direct_connections_router_policy_test.dart
  • test/core/services/native_sheet_bridge_test.dart
  • test/features/auth/views/adaptive_auth_flow_test.dart
  • test/features/chat/views/chat_page_layout_metadata_test.dart
  • test/features/chat/views/chat_timeline_render_model_test.dart
  • test/features/profile/models/settings_taxonomy_test.dart
  • test/features/profile/profile_page_hermes_test.dart
  • test/features/workspace/views/workspace_shell_test.dart
💤 Files with no reviewable changes (2)
  • test/features/profile/models/settings_taxonomy_test.dart
  • lib/features/profile/models/settings_taxonomy.dart

Comment thread lib/features/chat/views/chat_bottom_anchor_controller.dart

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/features/chat/providers/chat_providers.dart (1)

1-1: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

responseStartsNewChain should also respect the bound Hermes session
existingMessages alone can mark a continued Responses turn as a new chain, which clears sessionId and invalidates hermesSessionsProvider even when the conversation already has a bound hermesSessionId.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/chat/providers/chat_providers.dart` at line 1, Update
responseStartsNewChain to account for the conversation’s bound hermesSessionId
in addition to existingMessages. A non-null bound Hermes session must prevent
the turn from being classified as a new chain, preserving sessionId and
hermesSessionsProvider state.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/features/chat/providers/chat_providers.dart`:
- Around line 11277-11295: Update responseStartsNewChain in the Hermes response
flow to consider the bound hermesSessionId before treating a missing
responsePreviousResponseId as a new chain. Preserve continuity for resumed chats
with an existing session, and avoid clearing sessionId or invalidating
hermesSessionsProvider in that case.

---

Outside diff comments:
In `@lib/features/chat/providers/chat_providers.dart`:
- Line 1: Update responseStartsNewChain to account for the conversation’s bound
hermesSessionId in addition to existingMessages. A non-null bound Hermes session
must prevent the turn from being classified as a new chain, preserving sessionId
and hermesSessionsProvider state.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 81f0895e-fdae-4633-9870-1c4777c1c251

📥 Commits

Reviewing files that changed from the base of the PR and between 24fa5da and e0cc017.

📒 Files selected for processing (11)
  • lib/features/chat/providers/chat_providers.dart
  • lib/features/hermes/services/hermes_api_service.dart
  • lib/features/hermes/services/hermes_message_mapper.dart
  • lib/features/hermes/services/hermes_run_transport.dart
  • test/features/chat/providers/chat_messages_notifier_streaming_seams_test.dart
  • test/features/chat/providers/hermes_run_remap_test.dart
  • test/features/chat/providers/hermes_session_provenance_test.dart
  • test/features/chat/widgets/hermes_approval_ownership_test.dart
  • test/features/hermes/hermes_api_service_test.dart
  • test/features/hermes/hermes_run_transport_test.dart
  • test/features/hermes/hermes_sessions_test.dart

Comment thread lib/features/chat/providers/chat_providers.dart

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/core/services/structured_output_renderer.dart`:
- Around line 206-224: Bound recursive traversal in _valueLogicalLength and the
nearby _deepEquals helper using the same depth or node-cap approach as
_HermesProjectionSizeEstimator. Ensure nested List/Map values stop or return a
safe result once the bound is reached, while preserving existing comparisons and
length calculations for payloads within the limit.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6a295443-c7ba-4b5d-9594-2ea1f9d9988e

📥 Commits

Reviewing files that changed from the base of the PR and between e0cc017 and 718ce37.

⛔ Files ignored due to path filters (1)
  • ios/Podfile.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • lib/core/services/streaming_helper.dart
  • lib/core/services/structured_output_renderer.dart
  • lib/features/chat/providers/chat_providers.dart
  • lib/features/chat/widgets/assistant_message_widget.dart
  • lib/shared/widgets/markdown/streaming_markdown_widget.dart
  • test/core/services/openwebui_stream_parser_test.dart
  • test/core/services/streaming_helper_transport_test.dart
  • test/features/chat/providers/chat_messages_notifier_dedupe_test.dart
  • test/shared/widgets/markdown/renderer/markdown_performance_test.dart

Comment thread lib/core/services/structured_output_renderer.dart Outdated
@cogwheel0 cogwheel0 changed the title Refactor chat timeline anchoring and polish native navigation Optimize chat timeline, streaming, Hermes, and native navigation Jul 16, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/core/services/structured_output_renderer.dart`:
- Around line 231-237: Enforce node-budget accounting before shortcut returns:
update _measure to increment/check _nodes before the null return, and update the
comparison logic around identical(left, right) || left == right similarly before
either shortcut can return. Add broad flat null and equal-scalar regression
coverage in test/core/services/openwebui_stream_parser_test.dart lines 947-1009,
verifying traversal fails closed at the configured node limit.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8e9c6c3b-df31-4b51-b10f-0f4f8213d3fe

📥 Commits

Reviewing files that changed from the base of the PR and between 718ce37 and a62a2ca.

📒 Files selected for processing (2)
  • lib/core/services/structured_output_renderer.dart
  • test/core/services/openwebui_stream_parser_test.dart

Comment thread lib/core/services/structured_output_renderer.dart
@cogwheel0

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch streaming-thermal-regression

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cogwheel0

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/core/services/openwebui_stream_parser_test.dart`:
- Around line 1056-1059: Refactor the assertions for the
StructuredOutputStreamingReplace revision to use the checks package’s `.has()`
property assertion, replacing the separate type check and manual cast while
preserving the expected content comparison with after.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2f091421-1fce-44f8-825b-9a2ac7450a11

📥 Commits

Reviewing files that changed from the base of the PR and between a62a2ca and 957621d.

📒 Files selected for processing (4)
  • ios/Runner/NativeSheetBridge.swift
  • ios/RunnerTests/RunnerTests.swift
  • lib/core/services/structured_output_renderer.dart
  • test/core/services/openwebui_stream_parser_test.dart

Comment thread test/core/services/openwebui_stream_parser_test.dart Outdated
Buffer owner projection deltas so Hermes no longer copies the accumulated response for every chunk. Re-measure bottom targets after animations and cancel stale settle generations so response or composer growth cannot leave content hidden after navigation or user interaction.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
lib/features/chat/providers/chat_providers.dart (1)

372-391: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Clear contentBuffer on finalization to avoid retaining a duplicate of the content.

finalize materializes the buffer into message but leaves contentBuffer holding the same characters. For finalized projections retained in the recovery cache (bounded by maxRetainedProjections/maxRetainedBytes), each entry then keeps message.content and a StringBuffer copy of it. Since _estimateHermesProjectionBytes only measures message.content, the retention budget undercounts, and the cache can hold roughly 2× the content memory it accounts for.

The buffer is never read after finalization (appendContent no-ops once finalized, and _materializeContent returns early when !contentBufferDirty), so clearing it here is safe and also removes the stale-buffer edge case where _compactResolvingApproval sets content: '' while the buffer still holds prior content.

♻️ Proposed fix
     final current = _materializeContent(projection);
     projection
       ..message = current.copyWith(isStreaming: false)
       ..finalized = true
       ..persistenceRevision += 1
       ..retainedBytes = _estimateHermesProjectionBytes(projection.message);
+    projection.contentBuffer.clear();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/chat/providers/chat_providers.dart` around lines 372 - 391,
Update finalize in _HermesRunProjection to clear contentBuffer immediately after
materializing the final message, while preserving the existing finalized state
and retention accounting. Ensure finalized projections no longer retain a
duplicate buffer, and keep appendContent and subsequent materialization behavior
unchanged.
test/features/chat/providers/chat_messages_notifier_streaming_seams_test.dart (1)

2402-2407: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Assert the exact trusted document key, not only its count.

This passes if an unrelated key is persisted, leaving the document-trust guarantee untested.

Proposed assertion
-      check(
-        HermesLocalDocumentTrustStore.trustedDocumentKeys(
-          connectionIdentity: connectionIdentity,
-          sessionId: 'responses-session',
-        ),
-      ).length.equals(1);
+      check(
+        HermesLocalDocumentTrustStore.trustedDocumentKeys(
+          connectionIdentity: connectionIdentity,
+          sessionId: 'responses-session',
+        ),
+      ).deepEquals(<String>{
+        HermesLocalDocumentTrustStore.documentTrustKey(
+          messageId: 'server-user-1',
+          promptText: prompt,
+          documentEnvelope: envelope,
+          startOffset: prompt.length - envelope.length,
+        ),
+      });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@test/features/chat/providers/chat_messages_notifier_streaming_seams_test.dart`
around lines 2402 - 2407, Update the assertion around
HermesLocalDocumentTrustStore.trustedDocumentKeys to verify the returned
collection contains the expected trusted document key for connectionIdentity and
sessionId 'responses-session', rather than asserting only that its length is
one; preserve the existing lookup and ensure unrelated persisted keys cannot
satisfy the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@lib/features/chat/providers/chat_providers.dart`:
- Around line 372-391: Update finalize in _HermesRunProjection to clear
contentBuffer immediately after materializing the final message, while
preserving the existing finalized state and retention accounting. Ensure
finalized projections no longer retain a duplicate buffer, and keep
appendContent and subsequent materialization behavior unchanged.

In
`@test/features/chat/providers/chat_messages_notifier_streaming_seams_test.dart`:
- Around line 2402-2407: Update the assertion around
HermesLocalDocumentTrustStore.trustedDocumentKeys to verify the returned
collection contains the expected trusted document key for connectionIdentity and
sessionId 'responses-session', rather than asserting only that its length is
one; preserve the existing lookup and ensure unrelated persisted keys cannot
satisfy the test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c4b7054a-515f-4337-a4bb-a4c58cf7e98d

📥 Commits

Reviewing files that changed from the base of the PR and between 957621d and c9a1234.

📒 Files selected for processing (5)
  • lib/features/chat/providers/chat_providers.dart
  • lib/features/chat/views/chat_bottom_anchor_controller.dart
  • lib/features/chat/views/chat_page.dart
  • test/features/chat/providers/chat_messages_notifier_streaming_seams_test.dart
  • test/features/chat/views/chat_page_layout_metadata_test.dart

Release finalized Hermes projection buffers so recovery accounting matches retained memory, and strengthen the affected regression assertions.
@cogwheel0
cogwheel0 merged commit 66308ac into main Jul 18, 2026
3 checks passed
@cogwheel0
cogwheel0 deleted the streaming-thermal-regression branch July 18, 2026 03:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant