Commit Graph
100 Commits
Author SHA1 Message Date
Bohdan Triapitsyn 74a065fd10 Merge pull request #3332 from hehuaiyu/fix/windows-bun-shim-resolution
fix(tooling): resolve Bun executable on Windows
2026-09-05 01:24:34 +03:00
Bohdan Triapitsyn d9f7bc199e Merge pull request #3329 from hehuaiyu/fix/preserve-custom-provider-model-metadata
fix(providers): preserve custom model metadata on edit
2026-09-05 01:24:23 +03:00
Bohdan Triapitsyn 05e2903815 release v1.22.1 2026-09-04 23:51:03 +03:00
Bohdan Triapitsyn f42988c9bf chore: bump @opencode-ai/sdk to 1.18.28 2026-09-04 23:43:54 +03:00
Bohdan Triapitsyn d6f0f2f23c feat(settings): retire the third-party plugin integrations
Settings → Integrations offered install cards for the Claude Code and
Cursor provider plugins. They are gone: the section, its plugin catalog,
its own i18n module and tests, the settings search entries, the page
keywords, and the two sprite icons only it used. The page now holds the
built-in GitHub and Linear cards, so it is hidden in VS Code where neither
applies; its title and description live in the settings dictionaries.

Docs follow: the Integrations page in every locale now documents GitHub
(pointing at its own page) and Linear in full, the GitHub page names
Settings → Integrations as the place to connect and covers linking an
issue or PR to a message, and the Providers pages no longer promise Claude
or Cursor subscriptions.

Claude-Session: https://claude.ai/code/session_01HB9wdLQoZX2vfyDjwv6Rso
2026-09-04 23:34:15 +03:00
Bohdan Triapitsyn 34bf631157 feat(queue): queue a message with everything the composer had attached
Queueing captured only the text and files. Context chips (inline comments,
terminal selections, browser annotations, PR comments and checks, quotes,
linked issue/PR/Linear references, pending synthetic parts) stayed in the
composer and only left with the next manual send, so a queued message the
server delivered went out without them and the chips rode an unrelated
message later.

A queued message now carries what the composer would have sent: the text
with its agent mention stripped and file mentions resolved into
attachments, the attached context as structured parts, and the skill
instruction derived from the text. The server delivers those parts in the
composer's order, the VS Code auto-send does the same, and editing a queued
message puts the chips and linked references back. A failed queue restores
the composer completely. Snapshots and broadcasts omit the captured
context like attachment payloads; a take returns it.

Claude-Session: https://claude.ai/code/session_01HB9wdLQoZX2vfyDjwv6Rso
2026-09-04 22:56:27 +03:00
Bohdan Triapitsyn ce5c0c068e feat(mcp): reconnect failed MCP servers in managed OpenCode
OpenCode marks an MCP server failed when it does not come up at startup
or when a live connection drops, and never retries. A new managed plugin
reconnects those servers with a per-server backoff (1s doubling to a 30s
cap), wakes early on mcp.tools.changed, and stops on dispose. Only the
failed state is retried; disabled and auth states stay untouched.

The OPENCODE_CONFIG_CONTENT merge that agent-tool and system-prompt each
carried is now one shared helper so the three managed plugins compose.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-04 22:56:27 +03:00
Bohdan Triapitsyn caac24ac3d Merge pull request #3320 from openchamber/fix/ui-thinking-effort-draft-project-rename
Various session UI fixes: drafts, rename, worktree creation, thinking effort
2026-09-04 20:00:42 +03:00
Bohdan Triapitsyn f81bc26fe5 docs: clarify uncommitted changes warning text 2026-09-04 19:54:16 +03:00
Bohdan Triapitsyn b4a38061bc fix(ui): route answer worktrees from source session 2026-09-04 19:46:21 +03:00
Bohdan Triapitsyn f160f3aac4 Merge remote-tracking branch 'origin/main' into fix/ui-thinking-effort-draft-project-rename 2026-09-04 18:58:08 +03:00
Bohdan Triapitsyn 8a58054551 docs: refresh README wording and product messaging 2026-09-04 14:22:49 +03:00
Bohdan Triapitsyn 07fa83cc72 feat(queue): deliver queued messages from the server
Messages queued while a session is busy used to live in the browser tab and
were sent by that tab once the session went idle, so closing the tab (or
losing the connection) stranded them. The web server now owns the queue:
it persists to <data-dir>/message-queue.json, watches session.status on the
global event hub, re-verifies idleness against OpenCode before sending, and
delivers the head of the queue via prompt_async (or /command for slash
commands) with the model, agent, variant, attachments, and agent mention
captured at queue time. Failed sends stay queued and retry with backoff; a
user abort holds delivery briefly; every change is broadcast so all clients
see one queue.

The shared UI store becomes a projection of the server queue outside VS
Code (hydrate on connect, apply broadcasts, optimistic mutations settled on
the server's copy, one-time upload of locally queued messages from older
builds). Edit / send-now take the full message back from the server. A
UI-driven auto-review run asks the server to hold that session's queue.
VS Code keeps its local queue and foreground auto-send.

Claude-Session: https://claude.ai/code/session_01HB9wdLQoZX2vfyDjwv6Rso
2026-09-04 14:08:08 +03:00
Bohdan Triapitsyn 8afec51480 fix: switch new installs to OpenChamber themes
New installs now default to OpenChamber light and dark themes.
Existing Flexoki theme preferences continue to be preserved during migration.
2026-09-04 12:51:49 +03:00
Bohdan Triapitsyn 40f5ed73c9 Merge pull request #3274 from kydorn/fix/theme-save-echo-clobber
fix(ui): stop settings save echoes from clobbering theme preferences
2026-09-03 13:01:27 +03:00
Bohdan Triapitsyn 2a0672e3a6 fix(ui): preserve VS Code themes during settings broadcasts 2026-09-03 12:41:59 +03:00
Bohdan Triapitsyn 85bf0a99de fix: identify OpenCode Go requests by session 2026-09-03 11:49:35 +03:00
Bohdan Triapitsyn 76128b615f feat: add Fixel font support
Adds Fixel Text as a new UI font option
Allows font sources to load from direct URLs
Keeps existing fontsource-based loading working
2026-09-03 11:49:35 +03:00
Bohdan Triapitsyn 0107abb32d fix: order concurrent instance probes and honour the probe budget
Startup warm-up, opening the switcher and the refresh button can all probe at
once, and a relay host working through tunnel retries takes an order of
magnitude longer than a loopback one — so a slow older run landed last and
replaced a fresh "ok" with its own stale "unreachable". Each host now records
which run owns its status; a status from the switch flow outranks any probe
still running for it.

Each relay attempt is also capped by what is left of the 15s budget rather than
the full per-request timeout, so an attempt started just under the deadline can
no longer run the whole 8s past it.
2026-09-03 11:49:35 +03:00
Bohdan Triapitsyn f0ced9d361 fix: reject instance-served responses that outlive their instance
MCP status and skills were cleared on a switch but their in-flight requests
were not, so a response for the previous instance could still write itself over
the new one's — the same race the quota store already guards. Both now carry a
generation.

Usage also claimed an instance as loaded before it had answered, so a load that
failed on a cold or briefly unreachable instance was never attempted again, and
the previous instance's display mode and provider selection survived a switch —
which decided what the new instance was even asked for.
2026-09-03 11:49:34 +03:00
Bohdan Triapitsyn 17fd46d4e5 fix: keep instance statuses between switcher opens
The switcher held reachability in component state and replaced the whole map at
the end of a probe run. It ran once per open before the config had loaded — with
Local as the only host — so that pass wiped every other instance's status and
each open started on "Checking", including for the instance the app was
connected to and actively talking to.

Statuses move to their own module: startup warms them so the switcher opens on
real values, a re-probe replaces each value in place as it lands rather than
blanking them first, and stale entries are dropped against the loaded config
instead of a partial host list. The connected instance never reads "Checking" —
the live connection already answers what the probe would ask.
2026-09-03 11:49:34 +03:00
Bohdan Triapitsyn 8f1e0c8b5f fix: retry the relay instance probe before reporting it unreachable
The tunnel rejects everything waiting on its channel the moment one connect
attempt fails, even though it has already scheduled the next one with backoff.
That is right for app traffic, which retries for itself, but it made the
one-shot probe report a durable red "Unreachable" for a host that answers when
the user presses refresh a second later — a cold start is exactly when that
first attempt loses.

The probe now spans the tunnel's own reconnects within a 15s budget, and ends
immediately on a terminal tunnel state (auth failed, duplicate client, limit),
which waiting cannot resolve.
2026-09-03 11:49:34 +03:00
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