fix(vscode): handle multiline bidi prompt input - #12006
Conversation
| if (pos === next) return | ||
|
|
||
| textarea.setSelectionRange(pos, pos) | ||
| }, 0) |
There was a problem hiding this comment.
SUGGESTION: Possible stale-closure race under fast key repeat
cursor and val are captured in the handleArrowKey closure at keydown time, but the callback reads the live textarea.selectionStart (next) when it fires. If ArrowLeft/ArrowRight auto-repeats fast enough that two keydowns queue their setTimeout(0) callbacks before the first one runs, the first callback's next will reflect the caret position after both native moves (not just its own), while its cursor closure only reflects the position before its own move. That mismatch can make next > cursor (and thus the forward/backward branch, and the mention range lookup) resolve against a caret delta larger than one character, potentially snapping to the wrong edge or skipping a mention overlap check it should have made.
This is unlikely to trigger during normal single key-presses (repeat intervals are usually well above the setTimeout(0) delay), but it's worth a comment or a guard (e.g. bail if more than one arrow key is pending) if key-repeat/robustness matters here.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Files Reviewed (2 files)
Previous Review Summaries (2 snapshots, latest commit e717323)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit e717323)Status: No Issues Found | Recommendation: Merge Files Reviewed (2 files)
Previous review (commit 86cdccd)Status: 1 Issue Found | Recommendation: Merge (minor suggestion, non-blocking) Overview
Issue Details (click to expand)SUGGESTION
Files Reviewed (5 files)
Reviewed by claude-sonnet-5-20260630 · Input: 32 · Output: 6.8K · Cached: 722.8K Review guidance: REVIEW.md from base branch |
|
Thanks @mjnaderi
|
|
Let's maybe do that separate to the PR's you contributed to the prompt input. |
Revert the stylistic `const fresh` introduced by Kilo-Org#12009 to the inline ternary at both send sites so session.tsx drops back under the 3000-line max-lines lint cap (3001 -> 2999). The draft-agent seeding contract is preserved: a draftID is minted when there is no session, and the pending agent is seeded before promptAgent(scope) resolves. Update the two prompt-send-contract assertions to the compacted shape.
|
@marius-kilocode Sure, happy to. Thanks for checking this and for the kind note. |
marius-kilocode
left a comment
There was a problem hiding this comment.
The bidi fix is sound: the overlay now uses unicode-bidi: plaintext to match the textarea per-paragraph resolution, and the file-mention arrow handling lets the native bidi-aware caret move run before snapping to mention boundaries via pendingArrowSnap/resolvePendingArrowSnap. The earlier stale-closure race from the bare setTimeout(0) is resolved by resolving pending snaps synchronously at the start of each handleArrowKey and clearing the timer on cleanup.
Pushed a follow-up commit reverting #12009's stylistic const fresh back to the inline ternary so session.tsx drops back under the 3000-line max-lines cap (3001 to 2999); the draft-agent seeding contract is preserved and the contract tests were updated to the compacted shape. The session.tsx regression was on main from #12009, not from this PR, but folding the compaction here keeps the PR's own CI green.
|
@marius-kilocode I created #12015 for agent manager prompt modal. |
* fix(vscode): handle multiline bidi prompt input * fix(vscode): resolve pending prompt arrow snaps * fix(vscode): compact session draft-agent seeding under max-lines Revert the stylistic `const fresh` introduced by Kilo-Org#12009 to the inline ternary at both send sites so session.tsx drops back under the 3000-line max-lines lint cap (3001 -> 2999). The draft-agent seeding contract is preserved: a draftID is minted when there is no session, and the pending agent is seeded before promptAgent(scope) resolves. Update the two prompt-send-contract assertions to the compacted shape. --------- Co-authored-by: Marius <marius@kilocode.ai>

Issue
No linked issue; follow-up to #11918.
Context
Fix follow-up bugs in bidirectional prompt input support for multiline text.
The prompt textarea resolves direction per hard-newline paragraph, but the highlight overlay was still behaving like a normal
div, so mixed multiline prompts could render differently between the textarea and overlay. File mention arrow navigation also assumed one resolved direction for the whole textarea, which breaks when different lines or paragraphs have different base directions.Implementation
The prompt highlight overlay now uses
unicode-bidi: plaintextso it matches textarea plaintext bidi behavior for each hard-newline paragraph.File mention arrow navigation no longer derives a single textarea direction. Instead, it lets the VS Code WebView textarea perform its native bidi-aware caret move, then reads the updated collapsed selection and snaps to the mention boundary only if the caret landed inside a mention. This keeps mention skipping aligned with the actual caret movement for the current line/run.
Screenshots / Video
before.mp4
after.mp4
How to Test
Manual/local verification
bun test tests/unit/use-file-mention.test.ts tests/unit/prompt-input-bidirectional.test.ts.bun eslint webview-ui/src/hooks/useFileMention.ts tests/unit/use-file-mention.test.ts tests/unit/prompt-input-bidirectional.test.ts.bun run check-types:webview.Reviewer test steps
Blocked checks and substitute verification
Checklist