fix(code): preserve transcript order during virtualization - #4549
Merged
Mason Daugherty (mdrxy) merged 5 commits intoJul 8, 2026
Conversation
Mason Daugherty (mdrxy)
deleted the
johannes117/code/transcript-virtualization
branch
July 8, 2026 23:39
Mason Daugherty (mdrxy)
added a commit
that referenced
this pull request
Jul 9, 2026
> [!CAUTION] > Merging this PR will automatically publish to **PyPI** and create a **GitHub release**. For the full release process, see [`.github/RELEASING.md`](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md). --- _Everything below this line will be the GitHub release body._ --- ## [0.1.35](deepagents-code==0.1.34...deepagents-code==0.1.35) (2026-07-09) ### Features * Restore interrupted prompt to input on ESC ([#4544](#4544)) ([fccf037](fccf037)) * Add `[startup].mode` default approval mode ([#4573](#4573)) ([7c5bf54](7c5bf54)) * Offer restart after saving Tavily key via `/auth` ([#4560](#4560)) ([12df81a](12df81a)) * Reload env from `/auth` modal via Ctrl+R ([#4566](#4566)) ([f07d638](f07d638)) * Toast on saved `/auth` API key ([#4558](#4558)) ([ee3c264](ee3c264)) ### Bug Fixes * Harden approval content rendering ([#4581](#4581)) ([38446fd](38446fd)) * Preserve transcript order during virtualization ([#4549](#4549)) ([f6ee70c](f6ee70c)) * Run stdio MCP server pre-flight check off the event loop ([#4434](#4434)) ([c9636e2](c9636e2)) * Avoid duplicate "criteria ready" message on `/goal` revisions ([#4559](#4559)) ([1110497](1110497)) * Restore welcome banner tips ([#4528](#4528)) ([3f1e55e](3f1e55e)) * Clarify managed `rg` install failures ([#4578](#4578)) ([434c84a](434c84a)) * Dedupe update/install log path output ([#4553](#4553)) ([1398fee](1398fee)) * Keep notification center open for API-key entry ([#4568](#4568)) ([6e89417](6e89417)) * Queue `/mcp login` sent before the server connects ([#4533](#4533)) ([edac82c](edac82c)) * Serialize MCP OAuth token refreshes to prevent reuse revocation ([#4565](#4565)) ([c37100d](c37100d)) --- _Everything above this line will be the GitHub release body._ --- > [!NOTE] > A **New Contributors** section is appended to the GitHub release notes automatically at publish time (see [Release Pipeline](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md#release-pipeline), step 2). --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Mason Daugherty <github@mdrxy.com>
Mason Daugherty (mdrxy)
added a commit
that referenced
this pull request
Jul 13, 2026
…4646) Follow-up to #4549 (transcript virtualization). Fixed older messages failing to load when scrolling up long conversations in `dcode` with a trackpad, mouse wheel, or keyboard. --- Scrolling up a long `dcode` thread with a trackpad (or wheel/keyboard) never loaded older messages — the viewport parked in the blank top spacer. Transcript virtualization triggered hydration only from app-level `on_scroll_up`/`on_scroll_down` handlers bound to `textual.scrollbar`'s `ScrollUp`/`ScrollDown` messages. Those messages never fire for wheel/trackpad/keyboard scrolling (which scroll via `MouseScroll*` events), and for scrollbar-track clicks they are `bubble=False` and consumed by the `_ChatScroll` container's own handler before they can reach the app — so hydration effectively never ran on scroll. Verified against Textual 8.2.7: a wheel scroll and a scrollbar-track action both move `scroll_y` but invoke the app-level handler zero times. This drives hydration off the actual scroll offset instead: `_ChatScroll` posts a `Scrolled` message from `watch_scroll_y`, and the app checks both hydration directions in `on_chat_scrolled`. That covers every input device (wheel, trackpad, keyboard, scrollbar, programmatic) uniformly. Made by [Open SWE](https://openswe.vercel.app/agents/0f94cbf2-4d61-e04a-9e7b-520902ec436d) --------- Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Marcelo5444
pushed a commit
to Marcelo5444/deepagents
that referenced
this pull request
Jul 30, 2026
…-ai#4549) Fixes long `dcode` conversations so transcript virtualization preserves message order, keeps the scroll position stable when loading older history, and avoids older or newer messages disappearing when scrolling. --- - Make `MessageStore` the canonical source for virtualized transcript geometry with height estimates, protected live rows, and spacer-backed scroll ranges. - Keep rendered transcript rows chronological around spinner/queued widgets by mounting all transcript content above the bottom spacer. - Sync live tool state back into `MessageStore` so hydrated rows preserve status, output, expansion, and rejection details. - Hydrate the hidden tail before appending fresh output, and only advance `_visible_end` on `append` when already at the tail, so new live output never skips messages hidden below the window. ## Correctness & robustness (review pass) - **Fix scroll-anchor double-count on hydrate-above.** The top spacer already shrinks by the hydrated rows' height, so `scroll_y` now stays put instead of jumping the viewport down by ~a screenful when scrolling up through history. - **Keep the mounted window contiguous on partial failure.** Both hydrate directions now mount from the window edge outward and stop at the first failure, so the count-based `mark_hydrated`/`mark_hydrated_below` can't desync `_visible_start`/`_visible_end` from the DOM. - **Fail safe when syncing tool state.** If a tool widget can't be serialized, its row stays protected (we can't prove it's terminal); an unknown/unmapped status no longer unprotects a still-live row. The adapter's tool-sync hook is now total (never raises), so a sync failure can't abort a turn. - **Reason-keyed protection.** `MessageStore` tracks protection reasons (active stream vs. live tool) independently, so releasing one source never revokes another's protection. - **Remove dead/speculative API.** Dropped `MessageWindow`, `get_window_for_viewport`, `prefix_height`, `total_estimated_height`, and `get_protected_messages` (unused by the feature); the live path uses `estimate_height`/`range_height`. - **Single clamped write path for `height_hint`** (`set_height_hint`), plus docstring/comment fixes for the now-populated height hints and protection semantics. --------- Co-authored-by: Mason Daugherty <mason@langchain.dev> Co-authored-by: Mason Daugherty <github@mdrxy.com>
Marcelo5444
pushed a commit
to Marcelo5444/deepagents
that referenced
this pull request
Jul 30, 2026
> [!CAUTION] > Merging this PR will automatically publish to **PyPI** and create a **GitHub release**. For the full release process, see [`.github/RELEASING.md`](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md). --- _Everything below this line will be the GitHub release body._ --- ## [0.1.35](langchain-ai/deepagents@deepagents-code==0.1.34...deepagents-code==0.1.35) (2026-07-09) ### Features * Restore interrupted prompt to input on ESC ([langchain-ai#4544](langchain-ai#4544)) ([fccf037](langchain-ai@fccf037)) * Add `[startup].mode` default approval mode ([langchain-ai#4573](langchain-ai#4573)) ([7c5bf54](langchain-ai@7c5bf54)) * Offer restart after saving Tavily key via `/auth` ([langchain-ai#4560](langchain-ai#4560)) ([12df81a](langchain-ai@12df81a)) * Reload env from `/auth` modal via Ctrl+R ([langchain-ai#4566](langchain-ai#4566)) ([f07d638](langchain-ai@f07d638)) * Toast on saved `/auth` API key ([langchain-ai#4558](langchain-ai#4558)) ([ee3c264](langchain-ai@ee3c264)) ### Bug Fixes * Harden approval content rendering ([langchain-ai#4581](langchain-ai#4581)) ([38446fd](langchain-ai@38446fd)) * Preserve transcript order during virtualization ([langchain-ai#4549](langchain-ai#4549)) ([f6ee70c](langchain-ai@f6ee70c)) * Run stdio MCP server pre-flight check off the event loop ([langchain-ai#4434](langchain-ai#4434)) ([c9636e2](langchain-ai@c9636e2)) * Avoid duplicate "criteria ready" message on `/goal` revisions ([langchain-ai#4559](langchain-ai#4559)) ([1110497](langchain-ai@1110497)) * Restore welcome banner tips ([langchain-ai#4528](langchain-ai#4528)) ([3f1e55e](langchain-ai@3f1e55e)) * Clarify managed `rg` install failures ([langchain-ai#4578](langchain-ai#4578)) ([434c84a](langchain-ai@434c84a)) * Dedupe update/install log path output ([langchain-ai#4553](langchain-ai#4553)) ([1398fee](langchain-ai@1398fee)) * Keep notification center open for API-key entry ([langchain-ai#4568](langchain-ai#4568)) ([6e89417](langchain-ai@6e89417)) * Queue `/mcp login` sent before the server connects ([langchain-ai#4533](langchain-ai#4533)) ([edac82c](langchain-ai@edac82c)) * Serialize MCP OAuth token refreshes to prevent reuse revocation ([langchain-ai#4565](langchain-ai#4565)) ([c37100d](langchain-ai@c37100d)) --- _Everything above this line will be the GitHub release body._ --- > [!NOTE] > A **New Contributors** section is appended to the GitHub release notes automatically at publish time (see [Release Pipeline](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md#release-pipeline), step 2). --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Mason Daugherty <github@mdrxy.com>
Marcelo5444
pushed a commit
to Marcelo5444/deepagents
that referenced
this pull request
Jul 30, 2026
…angchain-ai#4646) Follow-up to langchain-ai#4549 (transcript virtualization). Fixed older messages failing to load when scrolling up long conversations in `dcode` with a trackpad, mouse wheel, or keyboard. --- Scrolling up a long `dcode` thread with a trackpad (or wheel/keyboard) never loaded older messages — the viewport parked in the blank top spacer. Transcript virtualization triggered hydration only from app-level `on_scroll_up`/`on_scroll_down` handlers bound to `textual.scrollbar`'s `ScrollUp`/`ScrollDown` messages. Those messages never fire for wheel/trackpad/keyboard scrolling (which scroll via `MouseScroll*` events), and for scrollbar-track clicks they are `bubble=False` and consumed by the `_ChatScroll` container's own handler before they can reach the app — so hydration effectively never ran on scroll. Verified against Textual 8.2.7: a wheel scroll and a scrollbar-track action both move `scroll_y` but invoke the app-level handler zero times. This drives hydration off the actual scroll offset instead: `_ChatScroll` posts a `Scrolled` message from `watch_scroll_y`, and the app checks both hydration directions in `on_chat_scrolled`. That covers every input device (wheel, trackpad, keyboard, scrollbar, programmatic) uniformly. Made by [Open SWE](https://openswe.vercel.app/agents/0f94cbf2-4d61-e04a-9e7b-520902ec436d) --------- Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes long
dcodeconversations so transcript virtualization preserves message order, keeps the scroll position stable when loading older history, and avoids older or newer messages disappearing when scrolling.MessageStorethe canonical source for virtualized transcript geometry with height estimates, protected live rows, and spacer-backed scroll ranges.MessageStoreso hydrated rows preserve status, output, expansion, and rejection details._visible_endonappendwhen already at the tail, so new live output never skips messages hidden below the window.Correctness & robustness (review pass)
scroll_ynow stays put instead of jumping the viewport down by ~a screenful when scrolling up through history.mark_hydrated/mark_hydrated_belowcan't desync_visible_start/_visible_endfrom the DOM.MessageStoretracks protection reasons (active stream vs. live tool) independently, so releasing one source never revokes another's protection.MessageWindow,get_window_for_viewport,prefix_height,total_estimated_height, andget_protected_messages(unused by the feature); the live path usesestimate_height/range_height.height_hint(set_height_hint), plus docstring/comment fixes for the now-populated height hints and protection semantics.