Commit Graph
100 Commits
Author SHA1 Message Date
Bohdan Triapitsyn 6fa2cb66d0 fix: scope instance-served state to the connected instance
Linear and GitHub logins, quotas, MCP status, skills and agent memory are
served by whichever instance is connected, but each was cached globally or
by directory alone — which two instances can share. Switching instances left
the previous instance's answers on screen and its Linear login usable against
a runtime that has no Linear.

Reset them all through runtimeEndpointReset, each store guarding its in-flight
requests with a generation so a response for the previous instance cannot land
in the new one. The Linear team filter is now persisted per instance: a team
belongs to one workspace, so carrying it across filtered the new instance's
issue list down to nothing.

Usage also waits for the instance to report itself initialised before loading.
Providers report themselves as configured only once the instance can read their
credentials, so a fetch fired at mount answered "nothing configured" for every
provider and cached it — which is why Usage stayed missing from the work-status
panel until Settings -> Usage forced a fresh fetch.
2026-09-03 11:49:34 +03:00
Bohdan Triapitsyn e8ba8e996f fix: show full desktop instance label in header 2026-09-03 11:49:34 +03:00
Bohdan Triapitsyn a87f068256 fix: support dev server previews over relay 2026-09-03 11:49:34 +03:00
Bohdan Triapitsyn da6ab52a65 feat: add exe.dev usage tracking 2026-09-03 11:49:34 +03:00
Bohdan Triapitsyn 62a18f07a0 feat: add exe.dev provider logo 2026-09-03 11:49:34 +03:00
Bohdan Triapitsyn 29ca970362 fix: refresh terminal renderer after fonts load 2026-09-03 11:49:34 +03:00
Bohdan Triapitsyn 6c4923b8c8 fix: support Bun-only remote dev deployments 2026-09-03 11:49:34 +03:00
Bohdan Triapitsyn dfb3c614c8 fix: authenticate terminal WebSockets synchronously on Bun 2026-09-03 11:49:34 +03:00
Bohdan Triapitsyn 40e4b6f857 fix: allow external host origin behind HTTP proxy
Accept browser https origins when TLS terminates before an HTTP proxy hop
Honor forwarded external host while rejecting mismatched origins
Add tests for proxy and host matching behavior
2026-09-01 14:38:44 +03:00
Bohdan Triapitsyn bec7a82568 fix: reserve space for project action buttons
Prevents the project label area from shifting when actions appear
Matches spacing behavior with the collapse-toggle branch
Keeps hover and focus states aligned
2026-09-01 10:51:08 +03:00
Bohdan Triapitsyn 715c33b83c fix: preserve chat timeline pinning during width resize
Keeps idle readers from snapping back to the end while rows re-wrap
Releases the pin instead of scrolling if a resize moves an idle view off the end
Re-asserts the live edge after resize settle for active streaming sessions
2026-08-31 00:42:37 +03:00
Bohdan Triapitsyn 8372285718 docs: add vacation notice to README
Announces reduced review activity from 31 Aug to 4 Sep
Sets expectations for issue and PR responses while away
2026-08-30 19:50:49 +03:00
Bohdan Triapitsyn bdda3c36bc release v1.22.0 2026-08-30 19:24:09 +03:00
Bohdan Triapitsyn b97f2d05bb fix(chat): restore a message's attached context on revert and fork
Review comments, quotes, terminal selections and annotations were consumed
at send and never put back, so reverting pulled the message into the
composer without the context it was sent with.

Claude-Session: https://claude.ai/code/session_01TwLFeTfBnWdvbg9XyezZQx
2026-08-30 18:32:45 +03:00
Bohdan Triapitsyn 356c99ce24 docs: update changelog highlights
Clarify chat session switching is visually stable
Note GitHub account connection moved to Settings → Integrations
Update VS Code changelog wording for session switching
2026-08-30 18:17:48 +03:00
Bohdan Triapitsyn d0a5538bff feat: tune session sidebar tooltip timing
Adds a shared sidebar tooltip provider with delayed open and instant close behavior
Removes per-button tooltip delays so sidebar actions feel more consistent
Aligns session sidebar hover interactions with the opencode-style tooltip experience
2026-08-30 18:03:29 +03:00
Bohdan Triapitsyn 654b3d2441 fix(chat): keep the outgoing conversation still until the next one replaces it
Switching sessions moved the conversation on screen before the swap: the
composer and the status chip followed the live selection and re-shaped a
commit ahead of the timeline, so the pinned outgoing chat jumped; and the
reveal effect re-ran for the outgoing session when its waited flag flipped,
hiding it a few frames before the next one mounted. The chat column now
reads one deferred session, and the reveal runs once per opened session.
2026-08-30 16:54:41 +03:00
Bohdan Triapitsyn 02b1ee637d feat(ui): move project actions from the titlebar overlay into the header before Open in 2026-08-30 14:28:22 +03:00
Bohdan Triapitsyn 65054a5f4a feat(ui): gate the pull-request surface on GitHub, move the account into it, and GitHub sign-in into Integrations
The pull-request rail icon now appears only while GitHub is connected
(OAuth or gh CLI), like Linear; Linear sits after the walkthrough in the
default rail order. The GitHub account avatar and switcher leave the
header for the pull-request panel, where the walkthrough, refresh, and
account controls share one row and one height, and the account stays
visible on the panel's empty state. A manual refresh keeps its spinner on
screen long enough to read as work done.

GitHub sign-in moves from Settings → Git to Settings → Integrations →
Built-in integrations as a card before Linear; search and the connect
buttons follow it.
2026-08-30 14:17:12 +03:00
Bohdan Triapitsyn 9847ef179f chore: changelog for per-instance themes and scheduled-task settings retention 2026-08-30 13:33:36 +03:00
Bohdan Triapitsyn 6eec839fbf refactor(ui): parse the scoped theme entry at the boundary; runtime-switch owns transient keys
The scoped theme entry is now parsed by one boundary parser with a
stated invariant instead of ad hoc typeof narrowing, and the runtime
keys that mean "no instance connected" live next to the code that
produces them so a new sentinel cannot miss the theme-storage guard.
2026-08-30 13:29:52 +03:00
Bohdan Triapitsyn db0bf115ad fix(scheduled-tasks): keep task fields a server build does not know
Every project-config write re-serialized normalized tasks, so a server
that shares the config file but predates a field (goal, auto-accept)
stripped it the first time any task ran. Untouched tasks now go back to
disk verbatim, a state update swaps only `state`, and only a deliberately
replaced task is serialized from the normalized shape.
2026-08-30 13:19:45 +03:00
Bohdan Triapitsyn 5fabeccd2d chore: highlight multi-repository projects in the changelog 2026-08-30 11:34:29 +03:00
Bohdan Triapitsyn 1423fc57b8 fix: use delete icon for context preview remove action
Updates the context preview remove button icon
Makes the control better match its delete behavior
2026-08-30 11:30:07 +03:00
Bohdan Triapitsyn e338a9c561 fix(ui): nested repositories open diffs and report status from the selected repo
Opening a file from the Git panel while a nested repository was selected
created the diff tab under the repository path, a key the context panel
never displays. Tabs are keyed by the project root; the diff surface
resolves the selected nested repository itself.

The work-status Project section now reads branch, changes, and PR from the
same resolved repository as the Git tab and names the nested folder under
the branch so the reader knows which repository the readouts describe.
2026-08-30 11:17:38 +03:00
Bohdan Triapitsyn e0f298b957 chore: changelog entry for nested git repositories
Claude-Session: https://claude.ai/code/session_017TK5JAYDfT3Fotc23UEg98
2026-08-30 10:26:04 +03:00
Bohdan Triapitsyn 695957e70e feat(git): support nested git repositories across the git surfaces (#2767)
feat(git): support nested git repositories across the git surfaces
2026-08-30 10:23:37 +03:00
Bohdan Triapitsyn 93fdfa50d5 fix(git): normalize discovered nested repository paths on the client
The server joins discovered repository paths with the platform separator
while every other git directory key in the UI is normalized, so on Windows a
discovered repository never matched its own selection or the root prefix the
picker strips. Parse the route's response at the boundary and normalize each
path. Note in the store docs that worktree bootstrap and session machinery
stay keyed on the project root while a nested repository is selected.
2026-08-30 10:23:26 +03:00
Bohdan Triapitsyn 7fb246d530 chore: changelog for Linear, language-matched voices, failed-turn diagnostics, and session landing
Claude-Session: https://claude.ai/code/session_017TK5JAYDfT3Fotc23UEg98
2026-08-30 02:25:17 +03:00
Bohdan Triapitsyn 391f938334 feat(voice): match local and macOS voices to the language of the text
Text-to-speech picked one voice regardless of what language a reply was in.
A dependency-free language detector (script, marker letters, function words)
now decides the language of the whole message once; with the new
"Match the voice to the language of the text" setting the local provider
switches to a catalog model for that language (Kokoro zh/en and Piper models
for 12 languages, downloaded on first use like the existing model) and macOS
say switches to an installed voice whose locale matches. The local voice
picker lists voices of every installed model, and the settings show which
language models are on disk.

The Ukrainian Piper medium build is a character-level model that sherpa-onnx
turns into noise, so the espeak-based Lada build is used instead.

Claude-Session: https://claude.ai/code/session_017TK5JAYDfT3Fotc23UEg98
2026-08-30 02:24:22 +03:00
Bohdan Triapitsyn b18933f19c feat(chat): surface failed turns and add error diagnostics to the status report
A turn that OpenCode stopped could end with nothing on screen: the
session.error event was only turned into a sidebar badge, its message was
dropped (the notification expected a different shape than OpenCode sends),
and a send that was accepted but never answered looked the same as success.

- The chat shows what OpenCode reported under the last message while that
  turn is the latest one, and names a user message an idle session has left
  unanswered for five seconds.
- The last 20 session errors are kept in memory and listed in the status
  report (Ctrl/Cmd+Shift+L, also `__opencodeDebug.statusReport()`), next to
  rejected sends, the managed OpenCode process's last error and stderr
  tail, and the OpenCode and desktop log file locations.
- The OpenCode health probe hits /global/health instead of a route that
  does not exist, and probe URLs resolve against the page for web runtimes.
2026-08-29 23:22:27 +03:00
Bohdan Triapitsyn d8e223bf49 fix(chat): open a session already at its end, and keep it there
A session opened from the sidebar could land above the bottom, or show a
frame sitting lower and then snap up. The viewport was pinned before the
content was final: the recap note renders once the session record arrives
and grew the footer under the pinned viewport, and on large sessions
subagent task cards grow when their child sessions load, moving everything
above the viewport.

- The recap note holds the timeline reveal until the session record is in
  memory, so it is part of the first finished picture.
- The scroll hook holds the reveal until the viewport is pinned; the reveal
  itself runs once the content height has held still for two frames, with
  one exact pin against the final height (bounded at 300ms).
- Sitting on the end of a session that is not producing output is an
  invariant: content growth re-pins from a MutationObserver in the same
  frame the list writes its layout, so no frame paints with the end out of
  view. Output growth keeps gliding through followEnd, which now glides only
  while the session is working.
2026-08-29 21:17:28 +03:00
Bohdan Triapitsyn c2136ce838 perf(chat): hold the previous timeline while a session loads; fade only when waited
- ChatContainer swaps the timeline on a deferred copy of the selection so the
  active row, URL, and tab commit first. (This part had been overwritten by a
  concurrent edit before the previous commit and is restored here.)
- A session whose messages are not in memory keeps the previous conversation
  on screen for up to 400ms while they load, instead of flashing a skeleton
  between two conversations.
- The reveal fade runs only for a session the user waited for and is 100ms;
  a session that was ready at the click appears in the same frame.
- The sidebar prefetches the two rows on either side of the open session
  150ms after it settles, two at a time, so neighbouring switches are warm.
2026-08-29 17:22:31 +03:00
Bohdan Triapitsyn 115138f5a3 docs: changelog for session switching, chat autocomplete scope, preview find bar 2026-08-29 17:05:35 +03:00
Bohdan Triapitsyn 5f201bb4ba fix(chat): scope command, skill, and file autocomplete to the chat's own directory
Commands and skills for the composer were read from the ambient store, which
follows the project selected in the sidebar; opening a managed chat or a chat
draft never changes that selection, so the previous project's commands,
skills, and (for drafts) files leaked into chats. The autocompletes now load
and read commands and skills for the effective directory, and a chat draft
resolves its effective directory to the prepared chat directory or the Chats
root instead of the last project.

Claude-Session: https://claude.ai/code/session_017TK5JAYDfT3Fotc23UEg98
2026-08-29 17:02:05 +03:00
Bohdan Triapitsyn edfc9779cf perf(chat): make session switching feel instant
Switching sessions ran as one synchronous commit: sidebar highlight, URL,
a full timeline remount with markdown re-parse, and around nine requests,
so nothing changed on screen for 150-250ms after the click.

- ChatContainer swaps the timeline on a deferred copy of the selection, so
  the active row, URL, and tab commit first and the timeline renders behind
  them; selection policy keeps reading the live store value.
- The message fetch starts before the selection is published.
- Sidebar rows stop re-rendering on a project switch: directory-scoped sync
  hooks read the runtime context and a subscribable current-directory source
  instead of the directory-bearing context; the grouping builder reads git
  branches through a ref and section caches key the branches they use;
  descendant ids are keyed by content. Rows per switch went from 73 to 8.
- Markdown skips the async re-render when the settled cached blocks are
  already painted, and mounts synchronously once its lazy module is loaded;
  the module is preloaded at boot.
- A timeline reveal gate holds a freshly opened session at opacity 0 while
  any provisional markdown paint catches up (250ms cap), then fades the whole
  timeline in once, so text, tools, and recap appear together.
- Switch fan-out trimmed: knowledge summary deduped, MCP status refreshed only
  when stale, non-repo directories cached by the git repo check, OpenChamber
  defaults cached briefly, agent memory reused for the same project, goal
  text cached, PWA manifest rebuilt after the switch settles.
- Header tabs snap into the active state and keep the title at the same
  height in both states.
- Prefetch on row press; composer focus moved off the commit.

`bun run profile:switch` records ack/content latency, longest task, and
requests per switch, cold and warm, and compares runs against a baseline.
Measured warm switch: ack 228ms to about 40-60ms, content 228ms to about
100-120ms.
2026-08-29 17:01:15 +03:00
Bohdan Triapitsyn 123c14260a fix(files): let Cmd/Ctrl+F reach the Markdown preview find bar
The find_in_file keybind only opens the preview find bar when the event
target sits inside the preview container, but that container was a plain
div that never held focus, so the shortcut did nothing in read-only preview.
Both preview containers are focusable now and take focus when a Markdown
file opens in preview or is clicked, without stealing focus from a field
the user is typing in.

Claude-Session: https://claude.ai/code/session_017TK5JAYDfT3Fotc23UEg98
2026-08-29 15:06:54 +03:00
Bohdan Triapitsyn 22d8b61912 docs(triage): pr-reviewer takes one or several PRs; batch size is the caller's call 2026-08-29 14:54:32 +03:00
Bohdan Triapitsyn f2bd88a245 docs(triage): pr-reviewer takes a batch of PRs per call 2026-08-29 14:53:16 +03:00
Bohdan Triapitsyn 9963e6e3b7 release v1.21.1 2026-08-29 13:20:21 +03:00
Bohdan Triapitsyn 65c7f27eb4 docs: add Turkish localization 2026-08-29 12:14:19 +03:00
Bohdan Triapitsyn 50159d3747 docs(triage): waiting-on-author bucket, read reviews not only comments, deliberate-behavior premise check 2026-08-29 11:15:02 +03:00
Bohdan Triapitsyn 736586f802 docs(triage-prs): the report carries each ready action verbatim, never paraphrased 2026-08-29 02:31:25 +03:00
Bohdan Triapitsyn d066e888e9 chore(agents): rename the review bot agent to pr-review-bot 2026-08-29 02:24:00 +03:00
Bohdan Triapitsyn dd998ef495 chore(agents): pr-reviewer stays read-only by instruction, not permission rules 2026-08-29 02:21:42 +03:00
Bohdan Triapitsyn 71653d287b feat(agents): add the pr-reviewer subagent; triage fans out through it 2026-08-29 02:18:56 +03:00
Bohdan Triapitsyn eead353326 docs(pr-review): unverifiable is not verified; author-named gaps always land on a list 2026-08-29 02:13:42 +03:00
Bohdan Triapitsyn fb9e13a3a7 fix(chat): list quote-only user messages in the prompt navigator
Context parts are marked synthetic, so a message made only of quoted
fragments was skipped as an injected message and could not be navigated
to. Such turns now appear with the same caption the bubble shows.
2026-08-29 02:02:30 +03:00
Bohdan Triapitsyn e26f647404 fix(chat): re-pin to the measured content end after a resize, not the list's content length
Opening or closing the context panel re-wrapped the timeline; the settle
handler then scrolled to LegendList's total content length, which still
carried pre-wrap sizes for unmounted rows, leaving a viewport-sized blank
tail under the last message.
2026-08-29 01:51:47 +03:00
Bohdan Triapitsyn 8d80224a1e docs(pr-review): decide PUSH-BACK vs MERGE-THEN-FIX by who owns the residue, not its size 2026-08-29 01:25:58 +03:00
Bohdan Triapitsyn 6cd318ddf3 docs(pr-review): a fix earns MERGE only when the symptom's path is shown to be closed 2026-08-29 01:22:38 +03:00
Bohdan Triapitsyn a9172e516e chore: changelog entries for the herjarsa batch
Claude-Session: https://claude.ai/code/session_017TK5JAYDfT3Fotc23UEg98
2026-08-29 01:15:56 +03:00
Bohdan Triapitsyn 8aba30ac43 revert: stop forwarding the Small Model override into the managed OpenCode config
Reverts #2687. In real use the injected small_model behaves poorly with
OpenCode: its internal small-model consumers and OpenChamber's own small
model are different things and must stay configured separately.
2026-08-29 01:14:02 +03:00
Bohdan Triapitsyn 48bcac1758 fix: harden and de-slop the merged sidebar/chat/settings batch
Post-merge follow-ups for #2740 #2735 #2734 #2690 #2676 #2738 #2684
#2689 #2733 #2739 #2462 #2687 #2736 #2618 #2697, plus three regressions
found while reviewing them:

- ctrl/cmd+digit while typing no longer switches session tabs (#2503 was
  still open in practice: the guard only covered the mod+alt surface binding)
- Shiki template-call sanitizer now covers every bundled grammar, including
  the js/ts aliases and embedding grammars; timed-out highlight requests are
  memoized and no longer cancel unrelated in-flight requests
- settings flush on suspend uses keepalive and also fires on Capacitor
  appStateChange; keeps the selected model persisted across mode switches
- remote-only branches fetch before checkout; range helpers fail clearly
- git status invalidation now fires for runtime adapters too
- settings number inputs and select triggers size in ch so they scale with
  the interface font
- recent-activity timestamps tick from one list-level ticker
- Markdown preview find goes through the shared find_in_file keybind with
  containment, no longer counts its own bar, and debounces observer runs
- #2676 reverted; #2524 fixed by fading the sticky header's own background
  instead of overlaying the content below it
- sticky group headers in the model picker and sidebar render again
  (oc-sticky-fade-scroller class restored after 9b9d7069c)
- project switcher names are left-aligned again (wrapper lost in 26dbc2f30)
- tool card quick-open icon is always visible and opens the same line as the
  expanded card's button
- tautological tests replaced or removed; new oxlint findings fixed
2026-08-29 01:06:43 +03:00
Bohdan Triapitsyn a182f4f4ff fix(server): allow reading files through workspace-internal symlinks (#2872)
fix(server): allow reading files through workspace-internal symlinks
2026-08-29 00:53:22 +03:00
Bohdan Triapitsyn 3e0a9622aa refactor(server): own the requested project directory in the runtime
Drop the canonical-containment 403 guard and the extra realpath(base) the
read routes (stat/read/raw/serve) had gained. Every workspace resolution
returns insideWorkspace: true and outside-file grants use
base = dirname(canonicalPath), so the guard could never fire; the flag had
no remaining reader and is gone with it. The read routes are back to the
single realpath(resolved.resolved) they had before.

Move the lexical-base fallback out of the inline header parsing in
routes.js. x-opencode-directory decoding belongs to
project-directory-runtime, so resolveProjectDirectory now also returns
requestedDirectory, the pre-realpath candidate that validated.
resolveWorkspacePathFromContext retries against it when the canonical base
rejects a path, which keeps files under a symlinked project root
addressable without a second copy of the header/query parsing.
2026-08-29 00:53:06 +03:00
Bohdan Triapitsyn 25c2e7b3ff fix(providers): refresh credentials after auth save (#2884)
fix(providers): refresh credentials after auth save
2026-08-29 00:51:02 +03:00
Bohdan Triapitsyn c788cd2237 fix(providers): keep declared env vars as a credential signal
Providers that read credentials from several environment variables
(Bedrock, Azure, Vertex) never get a single resolved Provider.key from
OpenCode, so dropping the env signal made them show "Credentials
missing", auto-open the auth panel, and hide their models even when
fully configured.

providerHasCredentials takes an envDeclared input again, and both
call sites in ProvidersPage pass whether the provider declares any
non-empty env var name.
2026-08-29 00:50:49 +03:00
Bohdan Triapitsyn 8b7ebca187 feat(projects): add multiple projects at once in the directory picker (#2877)
feat(projects): add multiple projects at once in the directory picker
2026-08-29 00:50:32 +03:00
Bohdan Triapitsyn 5c2e3a6955 feat(directory-explorer): show success toast after batch project add 2026-08-29 00:50:22 +03:00
Bohdan Triapitsyn e13f27c1a3 Merge remote-tracking branch 'origin/main' into port-2884
# Conflicts:
#	CHANGELOG.md
2026-08-29 00:49:02 +03:00
Bohdan Triapitsyn 7052d94c2a Merge remote-tracking branch 'origin/main' into port-2877
# Conflicts:
#	CHANGELOG.md
2026-08-29 00:48:50 +03:00
Bohdan Triapitsyn 55ae41bde2 Merge remote-tracking branch 'origin/main' into port-2872 2026-08-29 00:48:36 +03:00
Bohdan Triapitsyn 11d2b69651 fix(ui): complete context tab menu icons 2026-08-29 00:41:57 +03:00
Bohdan Triapitsyn cbe908009b chore: changelog entries for the second contribution batch
Claude-Session: https://claude.ai/code/session_017TK5JAYDfT3Fotc23UEg98
2026-08-29 00:31:49 +03:00
Bohdan Triapitsyn d557c168de feat(ui): attach large text pastes as virtual files (#2619)
feat(ui): attach large text pastes as virtual files
2026-08-29 00:31:04 +03:00
Bohdan Triapitsyn ef0755da8b fix(sync): settle completed turns and finished messages promptly (#2667)
fix(sync): settle completed turns and finished messages promptly
2026-08-29 00:30:01 +03:00
Bohdan Triapitsyn 6b17c0b4e2 chore(ui): finish large text paste merge into main
Adds the Turkish dictionary entries main introduced after this branch was
opened, keeps the composer's four-space style in the new paste modules,
and drops the unused offer-action type plus the widening return
annotation flagged by the anti-slop lint.
2026-08-29 00:30:01 +03:00
Bohdan Triapitsyn 10634c4512 fix(sync): settle completed turns and finished messages promptly
A lost or delayed turn-ending `session.idle` left the busy spinner up until
the watchdog poll caught it (5-10s). An assistant `message.updated` carrying
`time.completed` now schedules one status check for that session, and
`streaming.ts` stops treating a completed trailing message as streaming.

The check is deferred by 750ms and re-reads the session status when the timer
fires, so the overwhelmingly common case — the turn's own `session.idle`
arriving right behind the completed message — settles on its own and costs
zero extra requests; only a session the store still believes busy spends a
fetch. The poll shares the watchdog's in-flight directory guard, so the
deferred check and the periodic poll cannot overlap on one directory.
Status authority is unchanged: the monotonic pass never lowers status, and an
authoritative resync runs only when the snapshot disagrees.
2026-08-29 00:29:42 +03:00
Bohdan Triapitsyn 15ff5c750e fix(chat): show context text before a pending question (#2655)
fix(chat): show context text before a pending question
2026-08-29 00:27:21 +03:00
Bohdan Triapitsyn 5fd86a420d fix(chat): match question tool name exactly
Use an exact-match comparison for the question tool name instead of
toLowerCase(), matching the convention used elsewhere in this file.
2026-08-29 00:27:06 +03:00
Bohdan Triapitsyn 63755a8e45 Merge remote-tracking branch 'origin/main' into port-2619
# Conflicts:
#	packages/ui/src/components/sections/openchamber/OpenChamberVisualSettings.tsx
2026-08-29 00:26:49 +03:00
Bohdan Triapitsyn 5c26c6ae21 Merge remote-tracking branch 'origin/main' into port-2667 2026-08-29 00:26:15 +03:00
Bohdan Triapitsyn 340e20f996 Merge remote-tracking branch 'origin/main' into port-2655 2026-08-29 00:25:56 +03:00
Bohdan Triapitsyn ddc8ab91d9 chore: consolidate the unreleased changelogs by theme
Claude-Session: https://claude.ai/code/session_017TK5JAYDfT3Fotc23UEg98
2026-08-28 23:59:10 +03:00
Bohdan Triapitsyn 635c24e396 chore: changelog entries for the merged contribution batch
Claude-Session: https://claude.ai/code/session_017TK5JAYDfT3Fotc23UEg98
2026-08-28 23:55:32 +03:00
Bohdan Triapitsyn 2a5a25d5a2 fix(small-model): harden configured headers 2026-08-28 23:50:04 +03:00
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 ebb7f07532 fix(server): forward Small Model override to managed OpenCode config (#2687)
fix(server): forward Small Model override to managed OpenCode config
2026-08-28 23:45:21 +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 ac1881fab7 fix(server): forward Small Model override to managed OpenCode config
The Small Model override chosen in Settings never reached the managed
OpenCode process config, so OpenCode's own title/summary generation
kept using its fallback chain instead of the user's explicit choice
and sessions stayed untitled.

Merge main into this branch to pick up the includeWeb/includeMemory
flags added to prepareManagedOpenCodeEnv, and re-apply the Small
Model injection on top of that current env shape in
getManagedOpenCodeEnv (server/index.js).

Closes #2497
2026-08-28 23:45:04 +03:00
Bohdan Triapitsyn ea0a01a046 fix(sidebar): make file tree rows reliably clickable (#2737)
fix(sidebar): make file tree rows reliably clickable
2026-08-28 23:44:45 +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