fix(code): ignore mouse hits on detached widgets - #5114
Merged
Mason Daugherty (mdrxy) merged 1 commit intoJul 28, 2026
Conversation
Clicking in the transcript while an assistant message streamed could kill the app with `AttributeError: 'NoneType' object has no attribute 'region'`. Textual's compositor keeps reporting a widget as visible for a few event loop iterations after `Markdown.update` prunes it, and `_forward_event` starts a selection from that widget's now-`None` parent. Filter detached hits out of `Screen.get_widget_and_offset_at` so Textual takes its existing "nothing selectable here" branch instead. Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Johannes du Plessis (johannes117)
marked this pull request as ready for review
July 28, 2026 16:08
Mason Daugherty (mdrxy)
deleted the
mdrxy/code/textual-detached-hit-guard
branch
July 28, 2026 16:29
Marcelo5444
pushed a commit
to Marcelo5444/deepagents
that referenced
this pull request
Jul 30, 2026
Related Textualize/textual#6643 Clicking or starting a text selection in the transcript while the agent was streaming a response could take the whole app down with `AttributeError: 'NoneType' object has no attribute 'region'`. Mouse presses on markdown that is being replaced mid-stream are now ignored instead of crashing. --- Textual's compositor keeps reporting a widget as visible for a few event-loop iterations after it leaves the DOM. `Markdown.update` — which `MarkdownStream` runs on every flush of a streaming assistant message — detaches and remounts its blocks constantly, so that stale window is open more or less continuously while output streams. When a mouse press lands in it, `Screen._forward_event` starts a text selection from the hit widget's parent, which is `None` for a detached widget, and dereferences `container.region`. Reproduced against the pinned Textual with upstream's minimal example (no `deepagents` code involved), so this is fixed here only as a stopgap: it joins the other version-scoped shims in the Textual patch module as a fourth independent, separately guarded patch, with Textualize/textual#6643 as its removal criterion. The guard wraps the public `Screen.get_widget_and_offset_at` — the single funnel for all three hit lookups in `_forward_event` (selection start, drag update, and drag-in-progress) — and returns no hit when the widget is detached. Textual then takes its existing "nothing selectable here" branch, so a press on a just-pruned paragraph starts no selection rather than killing the process. This mirrors Textual's own `is_attached` guarding of live selections. Worth a careful look: the patch is on a public Textual method rather than a private one, so it changes hit-testing for every mouse event, not just selection. Live widgets are unaffected, and there is a test pinning that. Made by [Open SWE](https://openswe.vercel.app/agents/a1475bad-bf2c-b5aa-716f-6d5e0cdbc40b) ## References - Plan: https://openswe.vercel.app/agents/a1475bad-bf2c-b5aa-716f-6d5e0cdbc40b/plan Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Mason Daugherty (mdrxy)
pushed a commit
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). --- _Release notes preview: keep this section in sync with the package `CHANGELOG.md`. Publish reads the merged CHANGELOG via `release.yml`, not this PR description — keep them aligned anyway so the PR stays an accurate historical record for reviewers and anyone returning later._ --- ## [0.1.50](deepagents-code==0.1.49...deepagents-code==0.1.50) (2026-07-30) ### Highlights - Added project hooks workspace trust and expanded Hooks v2 support with client and server lifecycle events plus runtime feedback ([#5105](#5105), [#5104](#5104), [#4997](#4997), [#5045](#5045)). - Added an option to mute the “YOLO is active” toast ([#5103](#5103)). - Made the splash screen `thread` ID clickable to copy it ([#5173](#5173)). - Show `ask_user` answers directly on the answered tool row ([#5100](#5100)). - Show a toast when submitting an empty required `ask_user` answer ([#5095](#5095)). - Added thread message counts to the Debug Console ([#5117](#5117)). ### Fixes and improvements - Gated Hooks v2 behind `DEEPAGENTS_CODE_EXPERIMENTAL` and improved hook resume stability across identity and Command tool results ([#5146](#5146), [#5176](#5176)). - Kept server hook state out of task results ([#5164](#5164)). - Stopped duplicate Auto transcript events during interrupt replay ([#5157](#5157)). - Kept `/update` and `/install --package` prompts responsive ([#5127](#5127)). - Refreshed the `/threads` cache after each turn ([#5174](#5174)). - Anchored toasts above the chat input and added a toast when media is dropped into a free-text question ([#5101](#5101), [#5099](#5099)). - Improved thread status message styling and links ([#5118](#5118)). - Made resume hints echo the launched command name ([#5119](#5119)). - Scoped selection copy to the clicked screen ([#5140](#5140)). - Ignored mouse hits on detached widgets ([#5114](#5114)). _End release notes preview._ --- > [!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: langchain-oss-automated-triage[bot] <248757908+langchain-oss-automated-triage[bot]@users.noreply.github.com> Co-authored-by: Johannes du Plessis <johannes@langchain.dev>
Mason Daugherty (mdrxy)
pushed a commit
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). --- _Release notes preview: keep this section in sync with the package `CHANGELOG.md`. Publish reads the merged CHANGELOG via `release.yml`, not this PR description — keep them aligned anyway so the PR stays an accurate historical record for reviewers and anyone returning later._ --- ## [0.1.50](deepagents-code==0.1.49...deepagents-code==0.1.50) (2026-07-30) ### Highlights - Added project hooks workspace trust and expanded Hooks v2 support with client and server lifecycle events plus runtime feedback ([#5105](#5105), [#5104](#5104), [#4997](#4997), [#5045](#5045)). - Added an option to mute the “YOLO is active” toast ([#5103](#5103)). - Made the splash screen `thread` ID clickable to copy it ([#5173](#5173)). - Show `ask_user` answers directly on the answered tool row ([#5100](#5100)). - Show a toast when submitting an empty required `ask_user` answer ([#5095](#5095)). - Added thread message counts to the Debug Console ([#5117](#5117)). ### Fixes and improvements - Gated Hooks v2 behind `DEEPAGENTS_CODE_EXPERIMENTAL` and improved hook resume stability across identity and Command tool results ([#5146](#5146), [#5176](#5176)). - Kept server hook state out of task results ([#5164](#5164)). - Stopped duplicate Auto transcript events during interrupt replay ([#5157](#5157)). - Kept `/update` and `/install --package` prompts responsive ([#5127](#5127)). - Refreshed the `/threads` cache after each turn ([#5174](#5174)). - Anchored toasts above the chat input and added a toast when media is dropped into a free-text question ([#5101](#5101), [#5099](#5099)). - Improved thread status message styling and links ([#5118](#5118)). - Made resume hints echo the launched command name ([#5119](#5119)). - Scoped selection copy to the clicked screen ([#5140](#5140)). - Ignored mouse hits on detached widgets ([#5114](#5114)). _End release notes preview._ --- > [!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: langchain-oss-automated-triage[bot] <248757908+langchain-oss-automated-triage[bot]@users.noreply.github.com> Co-authored-by: Johannes du Plessis <johannes@langchain.dev>
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.
Related Textualize/textual#6643
Clicking or starting a text selection in the transcript while the agent was streaming a response could take the whole app down with
AttributeError: 'NoneType' object has no attribute 'region'. Mouse presses on markdown that is being replaced mid-stream are now ignored instead of crashing.Textual's compositor keeps reporting a widget as visible for a few event-loop iterations after it leaves the DOM.
Markdown.update— whichMarkdownStreamruns on every flush of a streaming assistant message — detaches and remounts its blocks constantly, so that stale window is open more or less continuously while output streams. When a mouse press lands in it,Screen._forward_eventstarts a text selection from the hit widget's parent, which isNonefor a detached widget, and dereferencescontainer.region.Reproduced against the pinned Textual with upstream's minimal example (no
deepagentscode involved), so this is fixed here only as a stopgap: it joins the other version-scoped shims in the Textual patch module as a fourth independent, separately guarded patch, with Textualize/textual#6643 as its removal criterion.The guard wraps the public
Screen.get_widget_and_offset_at— the single funnel for all three hit lookups in_forward_event(selection start, drag update, and drag-in-progress) — and returns no hit when the widget is detached. Textual then takes its existing "nothing selectable here" branch, so a press on a just-pruned paragraph starts no selection rather than killing the process. This mirrors Textual's ownis_attachedguarding of live selections.Worth a careful look: the patch is on a public Textual method rather than a private one, so it changes hit-testing for every mouse event, not just selection. Live widgets are unaffected, and there is a test pinning that.
Made by Open SWE
References