* fix(vscode): capture stable request ID before QuestionDock disposal
QuestionDock is mounted through a non-keyed callback-form Solid <Show>
in AssistantMessage. When a question is answered, the <Show> condition
becomes false and Solid disposes the component. The onCleanup handler
re-read props.request.id, which calls the already-disposed <Show>
narrowing accessor, throwing 'Stale read from <Show>'. The uncaught
exception left the webview unresponsive after every question submission.
Capture the request ID at component setup while the accessor is still
valid, and use the stable value in both the effect and the cleanup.
* test(vscode): exercise question submission teardown
* test(cli): stabilize global skill permission test on slow CI
The global skill permission test runs two full agent loops with real
bash subprocess execution but used much tighter timeouts than every
other test in the file:
- Test timeout 15s vs 30s elsewhere
- pollWithTimeout default 5s vs 15s elsewhere
- awaitWithTimeout default 2s for fiber completion vs Fiber.await
with the 30s test-level backstop
On Windows CI (where the file took 64s), these bounds caused
intermittent timeouts. Align all three with the rest of the file
and add a best-effort finalizer to clean up the skill directory
created under the global config path.
* test(cli): focus global skill timeout fix
- Route ProviderListAction.DELETE through the existing disconnect() handler
so the trash-icon action actually removes the custom provider
- Add the missing settings.providers.delete bundle key referenced by
ProviderListRows
- Preset a default id/name/URL when adding a new custom provider without an
existing config to edit
- Style the model picker Close button as the primary/default button and fix
its black background by using a plain JButton with the popup background
- Use the standard action-list icon gap between the picker check and label
- Show provider edit/delete on selection and use a trash icon for delete,
matching the other settings lists
PR #12158 enforced read permissions for file mentions by routing
directory attachments through the permission resolver with
denyDirectory: true. That flag is set for every prompt-mention
attachment, so the read tool denied all directory listings, including
directories inside the current workspace.
Only deny directory attachments whose canonical path changed after
permission approval. A symlink swap during the permission wait moves
the resolved target, so the approved permission no longer applies and
the listing is denied. Unchanged in-workspace directories are listed
as before.
Fixes#12241
* fix(vscode): support filenames with spaces and unicode in @mentions
Two bugs prevented @mentions from working correctly when filenames
contained spaces or non-ASCII characters:
1. Sent-message highlighting broke for paths with spaces.
buildFileAttachments did not set source.text position data on
file attachments, so the renderer fell back to MENTION_RE which
uses [\w./-] and stops at whitespace. Now source.text is computed
via text.indexOf and included in the attachment. The renderer's
resolve() path uses source.value with indexOf, which handles
spaces and any Unicode correctly.
2. Server read failed with 'File not found' for paths with spaces.
VS Code's webview (Chromium) does not percent-encode spaces when
setting url.pathname on a file:// URL. The resulting literal space
in url.href caused Bun's fileURLToPath to truncate the resolved
path at the first space. Spaces are now pre-encoded as %20 before
assignment.
Additionally, MENTION_RE in message-highlight.ts is updated to
match filenames that include space-separated segments (e.g.
'org data.xlsx') as a fallback for messages that pre-date this fix
and therefore lack source.text data.
* chore: add changeset for file mention spaces/unicode fix
* fix(vscode): address review feedback on mention highlighting
Two issues flagged by review:
1. The broadened MENTION_RE fallback regex over-matched ordinary prose.
A pattern permissive enough to span space-separated path segments
also swallows text following any unrelated @mention up to the next
dotted/versioned token (e.g. '@agent check report for v1.2 details'
highlighted the entire span through 'v1.2'). Reverted MENTION_RE to
its original conservative form; the primary fix for space/unicode
filenames does not depend on it; it now relies on source.text data
computed in buildFileAttachments and resolved via exact text search.
2. Repeated mentions of the same path in one message only highlighted
the first occurrence. mentionedPaths is a Set, so buildFileAttachments
produces exactly one ref per unique path regardless of how many times
it appears in the text. Once that ref carries source.text, resolve()
was used instead of the old regex-based detect() fallback, which
used to independently highlight every occurrence via a global regex
scan. resolve() now also searches the remaining text for exact repeats
of each ref's resolved mention value, so every occurrence of a path
stays highlighted, not just the first.
Added tests covering: over-matching prevention, repeated plain mentions,
and repeated mentions containing a space.
* fix(vscode): require boundary match for repeated mention detection
The repeat-mention search added in 44bea9196e used a plain substring
indexOf, which let a shorter mention's value match as a literal prefix
of a longer, distinct mention that starts the same way (e.g. '@a.ts'
matches inside '@a.tsx'). This truncated the longer mention's highlight
to just its prefix and dropped its own ref from being located.
Repeats are now only accepted when flanked by whitespace or a string
edge on both sides, matching the same token-boundary convention already
used elsewhere (syncMentionedPaths' (?:^|\\s)@path(?:\\s|$) pattern).
Added a regression test for the exact a.ts/a.tsx collision case.
* fix(vscode): relax repeat-mention boundary check to allow punctuation
The whitespace-only boundary check added in 55c58791f0 to prevent
'@a.ts' from falsely matching inside '@a.tsx' was stricter than
necessary: it required literal whitespace on both sides, so a repeated
mention directly followed by ordinary punctuation (a trailing comma,
sentence-ending period, or closing paren) silently lost its highlight.
Replaced the whitespace check with a path-continuation check matching
MENTION_RE's own character class (word chars, dot, slash, hyphen).
A repeat is now rejected only when the adjacent character could extend
it into a longer, different path. The dot is handled with one
character of lookahead: it counts as a continuation only when another
word character follows (e.g. '@report.csv' + '.bak'), so a lone
trailing sentence period does not block highlighting, while a genuine
compound-extension collision still correctly does.
Added tests for: repeat followed by a comma, a sentence-ending period,
a closing paren, and a compound-extension collision that must still
be rejected (@report.csv inside @report.csv.bak).
* fix(vscode): make repeat-mention boundary check Unicode-aware
PATH_CONTINUATION and continuesPath used \w, which in JavaScript regex
matches ASCII letters/digits only. A Cyrillic or CJK mention (e.g.
'@файл') was therefore not recognized as continuing into a longer,
distinct mention that starts the same way (e.g. '@файлы'), silently
reintroducing the same collision the check exists to prevent (the
@a.ts/@a.tsx case) specifically for the non-ASCII paths this PR is
meant to support.
Replaced \w with Unicode property escapes (\p{L}, \p{N} with the u
flag), which correctly recognize any Unicode letter or digit as a
continuation character, not just ASCII ones.
Added regression tests for a Cyrillic prefix collision (@файл inside
@файлы) and a CJK one (@文件 inside @文件夹), both verified to fail
against the prior ASCII-only implementation.
* fix(vscode): fix mention truncation when reverting and resending
Reverting to a message with a space-containing @mention, then resending
the same text, reproduced the 'File not found' truncation error even
after the buildFileAttachments/URL-encoding fix, because the revert path
uses a different, unrelated mechanism to reconstruct known mention paths.
Revert restores the original message's text into the input via a
setChatBoxMessage window message, which PromptInput handles by calling
seedFromText(text). seedFromText re-derives candidate mention paths from
raw text with a regex (the same conservative, space-free pattern as
MENTION_RE) — for '@mention-test/my quarterly report.txt' its slash
alternative matches only 'mention-test/my', stopping at the first space.
That truncated candidate is then added to knownPaths and, critically,
passes syncMentionedPaths' own boundary check too: a real space genuinely
follows 'my' in the full filename, so the truncated candidate looks like
a complete, validly-bounded mention from the regex's perspective. The
truncated path then ends up in mentionedPaths alongside the real one, and
buildFileAttachments builds a second, broken attachment for it, producing
the same truncated 'File not found: ...\mention-test\my' error alongside
a correct read of the real file.
Fix: revertSession() now also extracts the reverted message's file parts'
exact source.path values (recorded by the earlier buildFileAttachments
fix) and sends them alongside the restored text. PromptInput's
setChatBoxMessage handler seeds these exact paths directly via a new
seedFromParts() function instead of falling back to seedFromText's regex
re-derivation, when they're available. seedFromParts skips the flawed
candidate-discovery step entirely and just prunes the known-good paths
against the current text, so it can't reintroduce the truncation.
seedFromText itself is left unchanged and still used as a fallback for
callers without exact path data (native undo restoring a draft, or
messages sent before source.path existed) — broadening its regex to
handle spaces was already tried and reverted elsewhere in this PR because
it causes ordinary prose to be over-matched.
Added tests: a regression test locking in seedFromText's known limitation
(so future refactors don't silently 'fix' it in a way that goes
unnoticed), and coverage for seedFromParts handling a space-containing
path correctly, pruning stale paths, and seeding multiple paths.
* fix(vscode): address review feedback on mention repeats and percent-encoding
- Rework message-highlight.ts's resolve()/repeats() to locate each ref
independently and track claimed ranges, instead of threading a single
moving cursor through every ref. Fixes an interleaved-mentions bug where
locating a later repeat of one mention (e.g. the second `@a.ts` in
`@a.ts @b.ts @a.ts`) could advance past and hide a distinct mention
(`@b.ts`) that sits between the repeats.
- Reject a repeat match when it is a literal prefix of another known ref's
exact mention text, not just when the following character looks like a
generic path-continuation character. A trailing space can no longer be
assumed to end a mention now that paths may contain spaces, so
`@a.txt @a.txt backup.txt` no longer truncates the second, longer mention.
- Escape literal percent characters (in addition to spaces) before assigning
to the file:// URL's pathname in buildFileAttachments, so a real filename
like "100%20real.txt" round-trips correctly instead of being decoded as
"100 real.txt" server-side.
* fix(vscode): fix stale-path collision in syncMentionedPaths for space-containing paths
syncMentionedPaths tested each known path independently with a boundary
regex that treated any whitespace after "@path" as proof the mention ends
there. That assumption broke once paths can contain spaces: a stale,
unrelated "a.txt" from an earlier mention would incorrectly survive
pruning whenever the current text also mentions the longer, distinct
"a.txt backup.txt", since a real space genuinely follows "a.txt" as part
of that longer path. The stale path would then get re-attached via
buildFileAttachments, silently reading the wrong file's contents.
Track already-accepted (longest-first) matches and reject a candidate
occurrence when it's a literal prefix of one of them at the same text
position, mirroring the same fix already applied to message-highlight.ts's
repeat-mention detection.
---------
Co-authored-by: Sylwester Liljegren <sylwester.liljegren@softronic.se>