fix(desktop): read live DOM text for Ctrl+Enter steer to avoid stale-state race - #53668
Open
liuhao1024 wants to merge 16 commits into
Open
fix(desktop): read live DOM text for Ctrl+Enter steer to avoid stale-state race#53668liuhao1024 wants to merge 16 commits into
liuhao1024 wants to merge 16 commits into
Conversation
…state race The Ctrl+Enter steer handler gated on `canSteer`, which derives from React state (`trimmedDraft`). React state lags the contentEditable DOM by one render, so typing quickly and pressing Ctrl+Enter immediately could miss the steer because the state hadn't flushed yet. Apply the same live-DOM-read pattern that the plain Enter handler already uses (NousResearch#39630): read `composerPlainText(editorRef.current)` in the Ctrl+Enter branch and check steer conditions against the live text. Also sync `draftRef.current` before calling `steerDraft()` so the function reads the just-typed text (same re-sync pattern as submitDraft). Remove the `canSteer` gate from `steerDraft()` itself — the Ctrl+Enter handler already validates conditions using live DOM, and the Steer button visibility is separately gated on `canSteer` via ComposerControls props. Fixes NousResearch#53659
TypeScript error TS2774: 'This condition will always return true since this function is always defined.' on line 63 where onSteer was typed as required (text: string) => void but checked with if (onSteer && ...). Make onSteer optional to match the actual component type in types.ts (onSteer?: (text: string) => Promise<boolean> | boolean) and add a test case for when onSteer is undefined.
23 tasks
teknium1
reviewed
Jul 15, 2026
teknium1
left a comment
Contributor
There was a problem hiding this comment.
Thanks for isolating the stale DOM/state race; the current main path still has the underlying defect.
Problems
- This branch changes the old inline
steerDraftimplementation, but current main extracted it in773a3703bfc1f8ff2f3aef40d7a565e7f4fe1404. The live shortcut still gates atapps/desktop/src/app/chat/composer/index.tsx:551, and the extracted implementation independently returns on stalecanSteeratapps/desktop/src/app/chat/composer/hooks/use-composer-submit.ts:176-179. GitHub currently marks the PRDIRTY, so the fix needs a targeted port to those current paths. ctrl-enter-steer-dom-race.test.tsx:16tests a copied Harness rather than productionChatBar/useComposerSubmit; it cannot prevent a regression in the live implementation. It also lacks coverage for attachment and slash-command exclusions.
Suggested changes
- Port the live-DOM validation and draft-ref synchronization to the current keydown path, and update the extracted steer guard without weakening the text-only/non-slash contract.
- Add coverage through the current production component or submit hook for stale DOM text plus slash and attachment no-op cases.
Automated hermes-sweeper review.
| // Regression repro for #53659: Ctrl+Enter right after typing (fast typing) | ||
| // did nothing. The `canSteer` guard derives from React state (`trimmedDraft`) | ||
| // which lags the contentEditable DOM by a render, so the keydown handler saw | ||
| // empty state and swallowed the steer. The fix reads the live editor text in |
Contributor
There was a problem hiding this comment.
This Harness duplicates the proposed implementation instead of exercising ChatBar or the extracted useComposerSubmit production path. On current main, the second stale canSteer gate lives in hooks/use-composer-submit.ts:176-179, so this test can pass while the shipped shortcut still fails. Please replace or supplement it with a test through the current component/hook boundary.
This was referenced Jul 28, 2026
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.
What does this PR do?
Fixes a race condition where
Ctrl+Enter/Cmd+Enterin the Desktop chat composer silently missed steer messages when the user typed and immediately pressed the shortcut. The handler gated oncanSteer, which derives from React state (trimmedDraft) that lags the contentEditable DOM by one render.Related Issue
Fixes #53659
Type of Change
Changes Made
apps/desktop/src/app/chat/composer/index.tsx: Read live DOM text viacomposerPlainText(editorRef.current)in theCtrl+Enterhandler instead of relying oncanSteer(React-state-derived). SyncdraftRef.currentbefore callingsteerDraft()so the function reads the just-typed text. Remove thecanSteergate fromsteerDraft()— the Ctrl+Enter handler already validates conditions using live DOM, and the Steer button visibility is separately gated oncanSteervia ComposerControls props.apps/desktop/src/app/chat/composer/ctrl-enter-steer-dom-race.test.tsx: Regression test covering the stale-state race (DOM has text, React state is empty), empty-editor no-op, not-busy no-op, and whitespace-only no-op.How to Test
Ctrl+Enter(Windows/Linux) orCmd+Enter(macOS).npx vitest run --environment jsdom apps/desktop/src/app/chat/composer/ctrl-enter-steer-dom-race.test.tsx— all 5 tests should pass.npx vitest run --environment jsdom apps/desktop/src/app/chat/composer/enter-submit-dom-race.test.tsx— existing plain-Enter race tests should still pass (5/5).Checklist
Code
fix(scope):,feat(scope):, etc.)npx vitest run --environment jsdomon the affected test files and all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/ACode Intelligence
apps/desktop/src/app/chat/composer/index.tsx—handleEditorKeyDownCtrl+Enter branch +steerDraftcallbackcanSteerviaComposerControlsprops