Commit Graph
2180 Commits
Author SHA1 Message Date
Bohdan Triapitsyn 46284301b8 fix(ui): add in-document search to the Markdown file preview (#2697)
fix(ui): add in-document search to the Markdown file preview
2026-08-28 23:48:56 +03:00
Bohdan Triapitsyn 2e9fd75925 fix(ui): prevent Shiki template-call OOM on backtick JS files (#2618)
fix(ui): prevent Shiki template-call OOM on backtick JS files
2026-08-28 23:48:37 +03:00
Bohdan Triapitsyn e47d87c3d6 feat(ui): add in-document search to the Markdown file preview
Ctrl/Cmd+F (and a toolbar button) opens a compact find bar over the
rendered Markdown preview, with match highlighting, a live count, and
next/previous navigation that scrolls the current match into view.
Escape closes the bar and returns focus where it was.

Merge follow-ups on top of the contribution: mount the bar in the
fullscreen viewer as well as the inline preview, combine it with the
FilePreviewCommentMenu wrapper that landed on main, debounce the
highlight pass so typing does not re-walk the whole document on every
keystroke, use the status-warning theme utilities instead of raw CSS
variables for the highlights, and add the Turkish strings for the
locale added after the branch was cut.

Closes #2401
2026-08-28 23:48:35 +03:00
Bohdan Triapitsyn b6e78fbed5 fix(ui): stop shiki template-call backtracking from OOMing the renderer
Shiki's bundled JS/TS/JSX/TSX grammars carry a `template-call` rule whose
triple-nested lookahead sends the Oniguruma WASM engine into exponential
backtracking on ordinary backtick templates. The WASM heap grows until the
renderer runs out of memory and the window goes black.

Strip `template-call` from those four grammars as they are loaded in the
Shiki worker. Plain backticks and simple tagged templates still highlight;
only the rare `ident<TypeArgs>` tagged-template form loses its specialized
type-argument coloring.

Add a 5s per-request budget on the worker client as a safety net for any
other pathological pattern. Matching is synchronous inside the worker, so
the only way to reclaim its heap is to terminate it from the main thread.
A timed-out request resolves `null` like any other failure, so the caller
keeps plain text and nothing is written to the result cache.

Closes #2587
2026-08-28 23:48:15 +03:00
Bohdan Triapitsyn 08fe004b83 fix(chat): render completed reasoning in full instead of simulating streaming (#2736)
fix(chat): render completed reasoning in full instead of simulating streaming
2026-08-28 23:46:49 +03:00
Bohdan Triapitsyn 49ca62a8a2 fix(sidebar): keep permission badge and hover actions from overlapping (#2738)
fix(sidebar): keep permission badge and hover actions from overlapping
2026-08-28 23:46:43 +03:00
Bohdan Triapitsyn 88812e791a fix(chat): clamp text selection menu Y position to the viewport (#2733)
fix(chat): clamp text selection menu Y position to the viewport
2026-08-28 23:46:33 +03:00
Bohdan Triapitsyn e64fc710fc fix(chat): render completed reasoning in full instead of simulating streaming
Reasoning streaming state now derives only from the live stream phase
(streaming/cooldown), never from missing persisted timing data. A cached
part without time.end is no longer treated as live just because the
timing field is absent, so completed reasoning renders in full on load
instead of replaying a fake stream.

While resolving the merge onto main, also fixed a regression the merge
uncovered: main had added block-level streaming reveal (commitStreamedText)
to ReasoningPart since this fix was authored, which caused the busy
"Thinking…" header to stay hidden for the first moments of a short,
single-paragraph streaming response (no committed line yet). The busy
header now mounts as soon as streaming starts, independent of whether
any text has been committed for display.

Closes #2020
2026-08-28 23:46:14 +03:00
Bohdan Triapitsyn 627add0dd0 fix(chat): clamp text selection menu Y position to the viewport
Selecting text that crosses the top scroll edge could push the
floating selection menu above the viewport because only the X
position was clamped, not Y. Add getDesktopClampedY alongside the
existing X clamp in selectionMenuPosition.ts, measure the menu's
height the same way its width is measured, and re-clamp Y in
showMenu, the layout effect, and the resize handler.

Ported by hand: TextSelectionMenu.tsx changed significantly on main
(comment mode, glass surfaces, header drag-zone push-down) since this
fix was written, so main's file was kept and the fix re-applied on
top of it.

Closes #2257
2026-08-28 23:46:12 +03:00
Bohdan Triapitsyn 8bd4995b8b fix(chat): do not hijack ctrl/cmd+digit while typing in an input (Fixes #2503) (#2689)
fix(chat): do not hijack ctrl/cmd+digit while typing in an input (Fixes #2503)
2026-08-28 23:45:57 +03:00
Bohdan Triapitsyn 507c9cad54 feat(sidebar): show compact timestamp in recent activity rows (#2684)
feat(sidebar): show compact timestamp in recent activity rows
2026-08-28 23:45:49 +03:00
Bohdan Triapitsyn 6a80882d72 fix(chat): ignore Ctrl/Cmd+digit surface switching while typing in an input
The Ctrl/Cmd+digit shortcut for switching context surfaces fired even
while the user was typing in an editable target (input, textarea,
select, or contenteditable element), hijacking the keystroke. Guard the
switchSurfaceDigit branch in useKeyboardShortcuts with the existing
isEditableEventTarget helper, matching how other shortcuts in the same
hook already bail out of editable targets.

Closes #2503
2026-08-28 23:45:41 +03:00
Bohdan Triapitsyn 1b58b54f29 fix(sidebar): show compact timestamp in recent activity rows
The Recent list's metadata slot only opened for activity duration, a
goal glyph, or a branch marker, so plain rows fell back to hover-only
or touch-only timestamps. Extend the slot guard to also open for
renderContext === 'recent' and render the compact timestamp inline,
mirroring the existing touch-only branch.

Closes #2560
2026-08-28 23:45:30 +03:00
Bohdan Triapitsyn 44439c2795 fix(settings): let fixed-width controls scale with font size and density (#2739)
fix(settings): let fixed-width controls scale with font size and density
2026-08-28 23:45:27 +03:00
Bohdan Triapitsyn e0869efeb0 Merge remote-tracking branch 'origin/main' into port-2738
# Conflicts:
#	packages/ui/src/components/session/sidebar/DOCUMENTATION.md
#	packages/ui/src/components/session/sidebar/sessions/SessionNodeItem.tsx
#	packages/ui/src/components/session/sidebar/sessions/sessionNodeItemUtils.test.ts
2026-08-28 23:45:25 +03:00
Bohdan Triapitsyn 5332d124a6 fix(settings): let fixed-width controls scale with font size and density
Merge main and resolve conflicts in RemoteInstancesPage.tsx (re-applied
the width bumps by hand at their current locations) and
KeyboardShortcutsSettings.tsx (dropped the PR's hunk entirely: main
replaced that fixed-width input with ShortcutRecordingDialog, which has
no equivalent clipping at 200% interface font size).

Closes #2320
2026-08-28 23:45:12 +03:00
Bohdan Triapitsyn 69b39db427 fix(sidebar): make file tree rows reliably clickable
On macOS trackpads, a light touch on a file/folder row can start a
native HTML5 drag after ~4px of movement, and Chromium then swallows
the resulting click. Track the drag start position and, on dragend,
treat a micro-drag (dropEffect 'none' and under 8px of travel) as the
click the gesture was meant to be.

Reconciled with main's OS file drag-drop upload handlers on the same
rows: kept onDrop/onDragOver/hasExternalFiles for external file
uploads, and wired the new click-recovery logic alongside it on both
the file tree row and the search-results row. Dropped the row's
cursor-grab/active:cursor-grabbing classes, since these rows are not
meant to read as draggable to the user.

Closes #2368
2026-08-28 23:44:27 +03:00
Bohdan Triapitsyn 52fc1fb25d merge main 2026-08-28 23:44:00 +03:00
Bohdan Triapitsyn 14ca125b5d Merge remote-tracking branch 'origin/main' into port-2736
# Conflicts:
#	packages/ui/src/components/chat/message/parts/ReasoningPart.tsx
2026-08-28 23:43:20 +03:00
Bohdan Triapitsyn 8a82bbaf21 fix(ui): complete VS Code bootstrap detection for directory startup (#2359) (#2462)
fix(ui): complete VS Code bootstrap detection for directory startup (#2359)
2026-08-28 23:41:34 +03:00
Bohdan Triapitsyn 5a0a9af8e3 fix(chat): keep sticky header gradient inside its padding (#2676)
fix(chat): keep sticky header gradient inside its padding
2026-08-28 23:41:25 +03:00
Bohdan Triapitsyn d8737d397d fix(ui): keep the selected model when switching agent modes (#2690)
fix(ui): keep the selected model when switching agent modes
2026-08-28 23:41:16 +03:00
Bohdan Triapitsyn 1f7b7f8a16 fix(settings): flush pending debounced settings writes on page unload (#2734)
fix(settings): flush pending debounced settings writes on page unload
2026-08-28 23:41:07 +03:00
Bohdan Triapitsyn f10fc5ffab fix(git): make post-mutation status refresh authoritative (#2740)
fix(git): make post-mutation status refresh authoritative
2026-08-28 23:40:49 +03:00
Bohdan Triapitsyn 1d1c215230 fix(chat): release live follow on middle-button pan, Shift+Space, and nested wheel
Merge main and reshape the follow opt-out to the gestures the timeline was
missing: a middle-button press starts the platform autoscroll pan (the only
scroll gesture on wheel-less mice and tablets with a pointer), Shift+Space
scrolls up from the keyboard, and an upward wheel over a nested scroller that
still has room above stays with that scroller instead of releasing the chat.

The grace re-pin timer and scroll-direction tracking are dropped: returning to
within the end band already re-arms follow, and the mode machine is built
without timers on purpose. Pause/Break never move the viewport and are not
gestures.

Closes #1640
2026-08-28 23:05:57 +03:00
Bohdan Triapitsyn 7c1902b9e9 fix(settings): drop the class-name assertion test and redundant truncate from the passkey row 2026-08-28 23:03:16 +03:00
Gautam0507andRepro Agent 8fee25c97b fix(ui): let SettingsFieldRow labels truncate on long content (#3196)
* test: reproduce long passkey label overlay (issue #3181)

* fix(ui): let SettingsFieldRow labels truncate on long content

---------

Co-authored-by: Repro Agent <repro-agent@example.com>
2026-08-28 23:02:50 +03:00
Bohdan Triapitsyn 33783999e5 fix(chat): own end-follow during streaming instead of the list's animated maintain
The list's animated maintainScrollAtEnd is single-flight and re-pins only
within a tenth of the viewport, so in a narrow viewport (VS Code sidebar) each
revealed block — several screens tall there — left the reader a second behind
and multiple screens above the live edge. The timeline hook now follows growth
itself: glide when within a viewport of the end, otherwise jump to one screen
above the end and glide the rest. Measured at 420x640: time spent >40px behind
dropped from 45% to 11%, max distance from 1682px to 382px.

Claude-Session: https://claude.ai/code/session_017TK5JAYDfT3Fotc23UEg98
2026-08-28 22:33:01 +03:00
Bohdan Triapitsyn 505f9b9e8c feat(mobile): list managed Chats in the sessions sheet
Chat sessions without a project were dropped from the mobile session tree
because no registered project owned their directory. The sheet now partitions
sessions like the desktop sidebar and shows Chats as a collapsible section above
the project tree, with the same rows, swipe actions and paging; search results
label them "Chats" instead of the raw directory name.

Claude-Session: https://claude.ai/code/session_017TK5JAYDfT3Fotc23UEg98
2026-08-28 20:08:58 +03:00
Bohdan Triapitsyn 010ee59f60 fix(chat): keep the viewport in place on send when auto-follow is off
With "Follow new content while streaming" disabled, sending from mid-history
no longer anchors the new message at the top of the viewport; the reader stays
where they were and the scroll-to-bottom pill leads to the new turn. Sending
from the live edge still parks the message as before. The setting's info text
now describes this in every locale.

Claude-Session: https://claude.ai/code/session_017TK5JAYDfT3Fotc23UEg98
2026-08-28 20:08:58 +03:00
Bohdan Triapitsyn 59fa91309a fix(ui): keep the app root pinned when the caret scrolls it
Chromium scrolls overflow:hidden ancestors when a textarea caret moves out
of view (PageUp/PageDown in the prompt box, long prompts), shifting the whole
app up and hiding the title bar with no way to scroll back. Snap html/body/#root
back to zero on any root scroll event in the web, desktop, VS Code and mini-chat
apps.

Claude-Session: https://claude.ai/code/session_017TK5JAYDfT3Fotc23UEg98
2026-08-28 20:08:58 +03:00
Bohdan Triapitsyn e00ebea262 fix(browser): wait for panel surface before capture 2026-08-28 20:08:58 +03:00
Iuliia Ivashko eca9353382 fix(composer): keep the caret inside the normalized document
CodeMirror collapses a CRLF pair into one line break, so the document is
shorter than the string it was given. The composer derived the caret from
the JS string length, which put it past the end of the document and made
dispatch throw `RangeError: Selection points outside of document`.

Because the exception fires before the transaction applies, the document
never updates, the un-normalized text stays in React state, and the draft
persists as-is: every later visit to the session restores it and crashes
again, with no way out from the UI.

Derive the caret from the change set instead, in the controlled writeback
and in the imperative insert/replace handles.

fixes #3013

# Conflicts:
#	CHANGELOG.md
#	packages/vscode/CHANGELOG.md
2026-08-28 19:14:02 +03:00
Iuliia Ivashko 01b3e3346f fix(git): check out a local tracking branch when a remote branch is picked 2026-08-28 15:45:43 +03:00
Alan Shum 73e21d0050 test(ui): repair current main test baseline (#3191) 2026-08-28 15:44:40 +03:00
Iuliia Ivashko 52d79cb368 fix(desktop): surface failed update installs
"Restart to Update" answered the renderer with null before the install was
attempted, so a rejected install only reached main.log and the button looked
dead. The apply-update path now keeps the IPC call open until the app quits or
autoUpdater reports the failure, rolls the quit/install flags back when the app
stays up, and the update dialog shows the real reason with a translated hint for
a rejected code signature.

Also settle the download promise on downloadUpdate() itself: an already cached
payload emits no 'update-downloaded', which left that promise pending with its
listeners attached on every retry.
2026-08-28 14:47:09 +03:00
Bohdan Triapitsyn 3f3d942aab fix(browser): reveal panel for agent captures
Fixes #3175
2026-08-28 14:06:43 +03:00
Bohdan Triapitsyn 4f53db17e6 fix(worktrees): protect user changes across ambiguous move failures
Post-merge hardening of the session-to-worktree move (#2998), driven by
review findings on the follow-up pass:

- an ambiguous transport failure (relay abort, timeout) on the
  change-carrying move no longer force-deletes the fresh worktree that
  may hold the user's only copy of their changes; both intent kinds
  surface honest guidance and refresh both directories
- assertSdkSuccess re-tags ambiguous transport errors when wrapping SDK
  failures, so ambiguity classification survives the wrapper on every
  path, matching the prompt-send precedent
- session liveness checks scan all child stores plus the global status
  index, and report unknown (not idle) when no store covers the session
  — an evicted background directory can no longer make a busy session
  look movable
- incomplete-rollback errors carry the changes-may-be-in-destination
  guidance instead of swallowing it
- move-message assembly shared across the three call sites; tests now
  exercise the real ambiguity classifier (extracted to
  send-failure-classification.ts) instead of a hand-mirrored mock
- i18n fallout from the merge train: Turkish gains the 21 worktree-move
  keys, all 12 locales get the hedged ambiguous-failure toast; owning
  DOCUMENTATION.md files record the new contracts
2026-08-28 12:03:55 +03:00
Bohdan Triapitsyn 820e3194b5 Merge pull request #2998 from mattv8/feat/move-session-existing-worktree
feat(sessions): move sessions to existing worktrees
2026-08-28 11:37:21 +03:00
Bohdan Triapitsyn 06263a5c2b Merge pull request #3064 from fitzgpt/feat/i18n-turkish
feat(i18n): add Turkish (tr) locale
2026-08-28 11:33:52 +03:00
mattv8 bcaa70216f fix(sessions): restore worktree menu type wiring 2026-08-27 18:43:37 -06:00
mattv8 13ef639479 fix(sessions): keep chat worktree actions hidden 2026-08-27 18:43:37 -06:00
mattv8 a35ff1032c fix(sessions): avoid staged-change rollback conflicts 2026-08-27 18:43:37 -06:00
mattv8 1a9ff65380 docs(sessions): document dirty-source move choice 2026-08-27 18:43:37 -06:00
mattv8 26d6d72551 fix(sessions): preflight every worktree move 2026-08-27 18:43:37 -06:00
mattv8 8fc08853b3 feat(sessions): confirm dirty-source worktree moves 2026-08-27 18:43:37 -06:00
mattv8 0d4b3f036a fix(sessions): require explicit worktree change transfer 2026-08-27 18:43:37 -06:00
mattv8 c75c7809df test(sessions): complete global sessions store mock 2026-08-27 18:43:37 -06:00
mattv8 285bb35224 fix(sessions): recheck idle tree during worktree move 2026-08-27 18:43:37 -06:00
mattv8 52bea6d1f3 fix(sessions): harden worktree move recovery 2026-08-27 18:43:37 -06:00