Commit Graph
1592 Commits
Author SHA1 Message Date
Bohdan Triapitsyn 73ab36bc91 fix: send queued messages to the original session
Prevents queued messages from being sent to a newly opened session
Adds explicit session targeting for queued auto-send
Covers the behavior with a unit test
2026-05-25 00:29:52 +03:00
Bohdan Triapitsyn 16d8fcd408 feat: add image attachment citations
Names pasted images predictably when needed
Inserts bracket citations at the cursor
Highlights citations only for pending attachments
2026-05-24 23:47:22 +03:00
Bohdan Triapitsyn f866201b1f feat: preview pending image attachments
Open pasted images before sending
Reuse the existing image preview dialog
Support keyboard preview for attachment thumbnails
2026-05-24 23:18:32 +03:00
Bohdan Triapitsyn 71a2e4c0f1 fix: align user message bubble sizing
Matched Markdown and plain text message spacing
Removed extra Markdown margins in user bubbles
2026-05-24 23:13:21 +03:00
b7440bef39 Fix (mobile) add long-press support to shared tooltips (#1386)
* Add long-press support to shared tooltips

* fix bot comments

* Fix controlled tooltip long-press suppression

---------

Co-authored-by: Konstantin Zolin <zolin_ka@vk.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-24 21:51:58 +03:00
Bohdan Triapitsyn 3f3b835ee9 feat: add native macOS dynamic app icon (#1402)
* feat: add native macOS dynamic app icon

Adds Icon Composer source and compiled Assets.car for macOS
Packages the dynamic icon asset into the Electron app
Adds a script to regenerate macOS icon assets

* fix: harden macOS icon asset scripts
2026-05-24 21:23:46 +03:00
Bohdan Triapitsyn 0c8301d579 fix: recover stuck live session updates
Reconnects and resyncs active sessions when live updates stall
Normalizes synthetic session status events
Uses authoritative status snapshots to clear stale busy states
2026-05-24 19:17:04 +03:00
Bohdan Triapitsyn c4956af565 feat(chat): live markdown source-mode highlighting in composer (#1401)
* feat(chat): live markdown source-mode highlighting in composer

Highlight markdown syntax, fenced code blocks, and mention-style tokens
directly in the chat input via the existing transparent-textarea overlay
(color/decoration/background only, so caret alignment is preserved).

- Markdown source-mode: inline/fenced code, links, headings, blockquotes,
  list markers, with dimmed syntax punctuation
- Per-language syntax highlighting inside fenced blocks, reusing the editor's
  CodeMirror language resolver + Lezer (bash/js/ts/json/html/css/python/md);
  highlighted blocks use a neutral base, plain fences keep the code color
- Token highlighting on match: @file, @agent, /command, /skill, #snippet
- Auto-pairing: wrap selection with markers, triple-backtick expands to a
  fenced block; paste a URL over a selection to form a markdown link
- Add md/markdown to the shared code-block language resolver

* fix(chat): address composer highlight review

- Tilde (~~~) fenced blocks now get per-language syntax highlighting
- Share fence open/close detection between tokenizeMarkdown and
  highlightFencedCode so they agree on boundaries (fence length + format),
  fixing range bleed with 4-backtick fences and ```lang lines inside blocks
- Replace buildHighlightParts O(segments x ranges) scan with a sweep-line
  over an active set (verified equivalent vs the prior algorithm across 30k
  randomized cases, including overlaps and explicit class/priority)
- Cap per-block Lezer parsing at 20k chars; oversized blocks keep the neutral
  code base without per-token coloring
2026-05-24 17:21:11 +03:00
kostazolandKonstantin Zolin af25edd3f7 Fix mobile open file list behavior for deleted and long-named files (#1391)
* Fix mobile open file list cleanup and long names

- Remove deleted files from persisted open file tabs
- Invalidate cached file content when stat/delete/rename affects paths
- Keep mobile open-file close buttons visible for long filenames
- Add marquee scrolling for overflowing file names

* Fix bot comments

---------

Co-authored-by: Konstantin Zolin <zolin_ka@vk.com>
2026-05-24 15:49:22 +03:00
jeremysamuel13andBohdan Triapitsyn c5862cc6ee fix: resolve symlinks in project directory paths (#1316)
* fix: resolve symlinks in project directory paths

OpenCode stores sessions using the canonical (realpath) directory, but
OpenChamber passed the unresolved symlink path in several places. The
string-match directory filter would fail when a project was accessed via
a symlink, making sessions invisible.

Changes:

- Add safeRealpathSync to settings normalization — project paths and
  lastDirectory are canonicalized at persistence time
- Add Express middleware before the API proxy to resolve symlinks in
  ?directory= query params on in-flight requests
- Resolve symlinks in /api/fs/list so the directory browser returns
  canonical paths, allowing the "already added" check to work correctly
- Reconcile the in-memory projects store when the server responds with
  normalized paths, preventing temporary duplicates

Fixes #1315

* fix: avoid sync realpath in opencode proxy

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-24 15:46:11 +03:00
lilyzhaunandlilyzhaun 90b3d4760e fix(ui): keep PWA dialogs visible on Android (#1370)
* fix(ui): keep PWA dialogs visible on Android

The PWA dialog adjustments under
@media (display-mode: standalone) and (max-width: 768px) were originally
written to clear the iOS status bar / notch by adding a top offset and a
translateY override. The rule was not scoped to iOS, so Android PWAs
matched it too:

- The extra top: 50% + (safe-area-top * 0.22) plus
  --tw-translate-y: -50% + (safe-area-top * 0.6) pushed the dialog
  below the visible center on Android, where the parent already centers
  the popup via flex items-center justify-center on Base UI's portal.
- max-height was computed against 100vh. Android Chrome's collapsible
  URL bar makes 100vh larger than the visible viewport, so when the
  bar is shown the dialog's action buttons can be pushed off-screen
  (for example the Install button in the Skills install dialog).

Fix:

- Use 100dvh (with the existing safe-area subtractions) so max-height
  tracks the dynamic visible viewport on Android.
- Move the top / --tw-translate-y override into
  @supports (-webkit-touch-callout: none) so it only applies on iOS,
  where it was always intended.

Verified by rebuilding packages/web and inspecting the emitted CSS:
the common .pwa-dialog-content rule now ships with max-height using
100dvh and no top/translate overrides; the iOS-only block keeps the
original offsets.

Tested manually on Android Chrome PWA against
https://aion.xsim.uk: 'About OpenChamber' and 'Install skill' dialogs
now center vertically and their footer buttons stay on-screen as the
URL bar collapses/expands.

* fix(ui): restore vh fallback for PWA dialog max-height

Address review feedback on #1370: the previous patch dropped the
original `max-height: calc(100vh - ...)` line entirely and only kept
`100dvh`. On browsers that do not understand the `dvh` unit the
declaration is invalid and dropped, which would leave the dialog
without any `max-height` cap inside this media block — potentially
worse than before the fix.

Reinstate the canonical progressive-enhancement pattern: ship the
`100vh` declaration first so older engines have a usable value, then
override with `100dvh` on the next line for browsers that do support
it. New comment makes the two-line pattern explicit so it isn't pruned
again as accidental duplication.

Verified via `packages/web` build: the emitted CSS now contains both
declarations in order on the shared `.pwa-dialog-content` rule:

  max-height: calc(100vh - ...);
  max-height: calc(100dvh - ...);

`type-check` and `lint` in `packages/ui` remain clean.

---------

Co-authored-by: lilyzhaun <lilyzhaun@users.noreply.github.com>
2026-05-24 14:19:19 +03:00
Bohdan Triapitsyn 967704a9b9 docs: add OpenChamber feature docs and translations (#1400)
* docs: add OpenChamber feature docs and translations

Add 30 new docs pages covering OpenChamber-specific workflows and setup:
OpenCode server, providers/models/agents, MCP, skills, commands & snippets,
usage, projects, context, notes/todos/plans, scheduled tasks, project actions,
preview, worktrees, multi-run, git & GitHub, magic prompts, git identities,
mobile/PWA, security, notifications, voice, project icons, remote instances,
desktop browser, updates, and three troubleshooting pages.

Rebuild sidebar into eight task-oriented sections and translate every new
page into all six supported locales (uk, zh-cn, es, pt-br, ko, pl).

* docs: surface new sections on homepage and cross-link tunnels

Add an Explore block to the docs homepage (all seven locales) linking to
the new section anchors, and cross-link the Tunnels page to Security and
PWA & Mobile.
2026-05-24 14:15:55 +03:00
bf6043a472 feat: Show search match count in editor panel (#1369)
* Show search match count in editor panel

* fix: cache CodeMirror search match count

---------

Co-authored-by: liusiyuan.ryanee <liusiyuan.ryanee@bytedance.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-24 14:11:25 +03:00
dffc4078a1 Fix mobile fullscreen panels and header active state (#1366)
* Render mobile side panels fullscreen below the header

* Fix bot comments

---------

Co-authored-by: Konstantin Zolin <zolin_ka@vk.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-24 13:55:01 +03:00
Bohdan Triapitsyn 0776aca9c4 perf(server): cache deterministic git rev-parse reads in fs exec route (#1399)
* perf(server): cache deterministic git rev-parse reads in fs exec route

A fresh client (e.g. immediately after a page reload) has an empty git
store and re-resolves every project's root from scratch, firing identical
`git rev-parse --absolute-git-dir` / `--git-common-dir` lookups against
`/api/fs/exec`. Each spawns a git subprocess server-side, so re-opening a
workspace recomputes everything.

Add a small TTL cache for an allowlist of deterministic, side-effect-free
git plumbing path queries, keyed by `(resolvedCwd, command)`:
- Only `git rev-parse` path lookups (absolute-git-dir, git-common-dir,
  show-toplevel) are cacheable; any other command — including any non-git
  command — always executes and is never stored.
- Only successful results are cached (failures may be transient).
- TTL is configurable via OPENCHAMBER_GIT_READ_CACHE_TTL_MS (default 30s,
  0 disables). The git directory layout is effectively static while the
  app runs, so a short TTL safely absorbs the post-reload burst.
- Expired entries are pruned alongside exec jobs.

Complements the client-side root-resolution cache: that one collapses the
in-session N² cascade, this one absorbs the cold-start burst on reload.

Adds tests covering cache hit, per-cwd keying, non-allowlisted commands,
failed-result bypass and the disable switch.

* fix(server): bound git-read cache with count + byte limits; test TTL expiry

Per the project caching policy (AGENTS.md: cap in-memory caches with both
count and byte limits), the git-read cache was unbounded between prunes.

Add dual-constraint LRU eviction (500 entries / 1MB, oldest-first) with
recency refresh on cache hits. Add tests for TTL expiry (fake timers) and
count-cap eviction.

* fix(server): dedupe in-flight git read cache hits
2026-05-24 13:21:09 +03:00
Bohdan Triapitsyn f94d87b5fd perf(git): cache project-root resolution to stop N² polling cascade (#1398)
* perf(git): cache project-root resolution to stop N² polling cascade

Opening a workspace with many projects/worktrees fired hundreds of
`POST /api/fs/exec` requests (e.g. ~700 for 19 projects) within seconds,
dominated by repeated `git rev-parse --absolute-git-dir` /
`--git-common-dir` for the same directories.

Root cause: in `useProjectRepoStatus`, each project's `ensureStatus`
settles independently and mutates the git store, which re-derives
`projectGitBranchesKey` and re-runs `getRootBranch` for *all* projects on
every change. `getRootBranch` had no caching, so this produced an N×N
burst of uncached git plumbing calls.

Changes:
- worktreeStatus: extract `resolveProjectRoot` to module scope with a
  60s TTL cache + in-flight dedupe (root resolution is static within a
  session). Combine the two `rev-parse` queries into one subprocess.
  Add `getRootBranch(dir, { knownBranch })` fast-path that skips a
  redundant git status when the directory is its own root, while still
  resolving the primary-root branch correctly for linked worktrees.
  Export `invalidateResolvedProjectRootCache`.
- useProjectRepoStatus: replace the cascade effect with a debounced,
  diff-based pass that only resolves projects that are new or whose
  branch actually changed, passing the known branch through.
- worktreeManager: invalidate the root cache on worktree create/remove.
- Add unit tests for caching, dedupe, invalidation, rev-parse
  precedence, non-git fallback, linked-worktree resolution and the
  knownBranch fast-path.

Reduces startup from hundreds of requests to roughly one root
resolution per project.

* fix(git): clear in-flight resolves and guard write-back on cache invalidation

`invalidateResolvedProjectRootCache` cleared `resolvedRootCache` but left
`inFlightRootResolves` intact, so during a worktree topology change a
resolution already in flight could (1) be handed to callers arriving after
invalidation and (2) re-seed the cache with the pre-invalidation root when it
settled, defeating invalidation for up to the full TTL.

Drop the in-flight entry on invalidation and add an epoch guard so a resolve
that was invalidated mid-flight does not write its now-stale result back.
Add a regression test for the concurrent-invalidation scenario.

* fix(git): bound root cache and avoid early sidebar resolves
2026-05-24 13:20:55 +03:00
yangyaofeiandBohdan Triapitsyn 06526767a2 feat(tts/stt): add API key support for OpenAI-compatible custom providers (#1361)
* feat(tts/stt): add API key support for OpenAI-compatible custom providers

## Problem
Custom (OpenAI-compatible) TTS/STT provider in Voice Settings has no way to
pass an API key or bearer token. Many self-hosted or third-party compatible
servers require authentication, making them unreachable from OpenChamber.

The server-side TTS route already accepts an `apiKey` parameter, but the
frontend never sends it. The STT route hardcodes `'not-required'`.

## Implementation
- Add `openaiCompatibleApiKey` to Zustand config store, persisted to localStorage
- Add API Key input field in VoiceSettings.tsx under the custom provider section
- Wire `openaiCompatibleApiKey` through useServerTTS to the TTS backend
- Add `apiKey` field to AudioStreamConfig for STT, forwarded as X-API-Key header
- Update server STT route to accept and forward X-API-Key to transcribeAudio
- Update stt.js to use client-provided apiKey before falling back to env var

## Files changed
- packages/ui/src/stores/useConfigStore.ts
- packages/ui/src/components/sections/openchamber/VoiceSettings.tsx
- packages/ui/src/hooks/useServerTTS.ts
- packages/ui/src/hooks/useBrowserVoice.ts
- packages/ui/src/lib/voice/audioStreamService.ts
- packages/web/server/lib/tts/routes.js
- packages/web/server/lib/tts/stt.js

* feat(tts/stt): add separate API key support for custom TTS and STT providers

## Problem
Custom (OpenAI-compatible) TTS and STT providers in Voice Settings have no way
to pass API keys. Many self-hosted or third-party compatible servers require
authentication, making them unreachable from OpenChamber Desktop (Electron).

## Implementation
- Add `openaiCompatibleApiKey` for TTS (persisted to localStorage, passed in JSON body)
- Add `sttApiKey` for STT (persisted to localStorage, passed via Authorization: Bearer header)
- Two independent keys: TTS and STT are configured separately
- STT authentication follows OpenAI standard (Authorization: Bearer <token>)
- TTS authentication follows existing pattern (apiKey in JSON body)
- Backend STT route extracts bearer token from Authorization header
- Backend STT service prefers client-provided key over OPENAI_API_KEY env var

## Fixes
- Fixed P1: ConfigStore interface now declares setOpenaiCompatibleApiKey setter
- STT API key is only forwarded when sttProvider === 'server' (not leaked to other providers)

## Files changed (7)
- packages/ui/src/stores/useConfigStore.ts
- packages/ui/src/components/sections/openchamber/VoiceSettings.tsx
- packages/ui/src/hooks/useServerTTS.ts
- packages/ui/src/hooks/useBrowserVoice.ts
- packages/ui/src/lib/voice/audioStreamService.ts
- packages/web/server/lib/tts/routes.js
- packages/web/server/lib/tts/stt.js

* fix: refresh server STT callback when API key changes

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-24 00:58:22 +03:00
Paolo InsognaandBohdan Triapitsyn e16097b05d feat: Redesign git changes to split stage/unstaged files. (#1359)
* feat: Redesign git changes to split stage/unstaged files.

Signed-off-by: Paolo Insogna <paolo@cowtech.it>

* fixup

Signed-off-by: Paolo Insogna <paolo@cowtech.it>

* fixup

Signed-off-by: Paolo Insogna <paolo@cowtech.it>

* refactor: streamline git changes panel

* fix: label staged and working diff tabs

* fix: isolate staged and working diff files

* fix: scope staged and working diff updates

* fix: scope git row revert to working changes

---------

Signed-off-by: Paolo Insogna <paolo@cowtech.it>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-24 00:49:38 +03:00
9af0de0056 Add mobile context notes tab (#1355)
* Add mobile context notes tab

* Fix bot comments

---------

Co-authored-by: Konstantin Zolin <zolin_ka@vk.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-23 21:48:56 +03:00
Tom Rochette 0244d7ffcd feat: add quick-add button to directory explorer rows (#1351) 2026-05-23 21:37:51 +03:00
kostazolandKonstantin Zolin 3dfefb8ffc Fix git operations from repository subdirectories (#1344)
* Fix git operations from repository subdirectories

* fix bot comments

---------

Co-authored-by: Konstantin Zolin <zolin_ka@vk.com>
2026-05-23 21:27:43 +03:00
luo jiyin 47f72c2e09 fix: correct typos in CHANGELOG files (#1338) 2026-05-23 21:16:09 +03:00
Roberto BertóandBohdan Triapitsyn 0c60fd6222 feat: rename sessions inline via double-click (#1320)
* feat: rename sessions inline via double-click

Double-clicking a session name in the sidebar or the mobile session
status bar now switches it into an inline editable input. Enter saves,
Esc cancels, and clicking elsewhere blurs the input to save. This
mirrors the VSCode/Finder rename pattern and removes the need to open
the session menu for what is a very common action.

* fix(rename): close sidebar input on empty title; drop duplicate mobile editor

Two issues from PR review:

1. handleSaveEdit (sidebar) only closed the input when editTitle.trim()
   was non-empty. Clearing the title and pressing Enter or blurring left
   the input open with no exit path other than Escape. The save handler
   now always closes the editor; an empty title is treated as a silent
   cancel (no update call).

2. ExpandedView (mobile) renders the current session twice — once in the
   sticky header, once in the session list — so a single editingSessionId
   produced two simultaneous inputs for the current session. The list row
   for the current session now suppresses its rename input; the header
   remains the single editor in that case.

* fix: refine inline session rename editing

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-23 21:15:15 +03:00
Roberto Bertó 49bf1dbff3 feat: widen chat input column with Wide Chat Layout setting (#1318)
The 'Wide Chat Layout' setting toggles a 'wide-chat-layout' class on
the document root that widens '.chat-column' and '.chat-message-column'
from 48rem to 64rem, but '.chat-input-column' (which wraps the
textarea) was missing the matching rule, so the prompt input stayed
narrow while the messages above it widened.

Add the missing '.wide-chat-layout .chat-input-column { width:
min(100%, 64rem) }' selector so the input column tracks the message
column under the same setting.
2026-05-23 20:59:06 +03:00
jkker 1663185a75 fix installed skills discovery and improve editor UX (#1296)
* fix skills discovery from opencode

* Fix stale skill description after frontmatter removal

* fix: align vscode skill discovery parity
2026-05-23 20:58:12 +03:00
Tom Rochette fd01a0ba62 Update CHANGELOG with contributor name corrections (#1382)
Signed-off-by: Tom Rochette <roctom@gmail.com>
2026-05-23 20:52:21 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez b764577943 fix: preserve canonical snippet names (#1380)
* fix: preserve canonical snippet names

* test: cover same-directory snippet alias precedence

---------

Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-23 20:51:45 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 920f987393 fix: handle git identity row keyboard activation (#1379)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-23 20:50:09 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 2b5408406c fix: clean up upstream reader abort listener (#1378)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-23 20:48:16 +03:00
1d36995c47 Fix(mobile) terminal replay, reset artifacts, and preview detection (#1383)
* fix terminal rendering and preview detection

* Fix bot comments

* fix: protect terminal preview URL probe

---------

Co-authored-by: Konstantin Zolin <zolin_ka@vk.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-23 13:15:16 +03:00
Bohdan Triapitsyn ca33c6ae57 docs: add Voice & Style guide and rewrite docs pages to match
Add a Voice & Style section to the docs authoring guide, then bring every
docs page in line with it: lead with the task, add success signals to
procedures, explain jargon on first use, keep bullet casing consistent,
and link out to Troubleshooting where steps can fail.

Applied across English source and all localized versions (uk, zh-cn, es,
pt-br, ko, pl).
2026-05-23 02:43:34 +03:00
Bohdan Triapitsyn 7c0562fa4f Document docs image handling and theme variants 2026-05-23 02:19:44 +03:00
Bohdan Triapitsyn 6f4e0068c1 docs: add localized documentation pages
Adds translated docs for Spanish, Korean, Polish, Portuguese, Ukrainian, and Chinese
Covers install, quickstart, themes, troubleshooting, tunnels, and reverse proxy guides
Updates docs workflow, sidebar, and contributor documentation
2026-05-23 00:33:39 +03:00
Bohdan Triapitsyn 82633d97f5 fix: update color values in Flexoki themes and enhance theme conversion script 2026-05-22 15:21:36 +03:00
Bohdan Triapitsyn 3354d7ec45 ci: preserve macOS app permissions in migration
Transfers Electron app as a tarball between release jobs
Verifies the macOS app executable before packaging
Documents permission risk in Tauri migration flow
2026-05-22 10:43:56 +03:00
Bohdan Triapitsyn 8e11373865 ci: sign Tauri migration payload with Tauri signer 2026-05-22 02:36:06 +03:00
Bohdan Triapitsyn 9faf97acbd ci: handle Electron app artifact shape
Wraps downloaded Contents folder back into OpenChamber.app
Unblocks Tauri-to-Electron migration repackage job
Documents GitHub artifact behavior
2026-05-22 02:22:19 +03:00
Bohdan Triapitsyn 07eb9d50d3 release v1.11.4 2026-05-22 02:07:11 +03:00
Bohdan Triapitsyn a22433ed71 fix: stabilize terminal layout resizing 2026-05-22 01:53:32 +03:00
Bohdan Triapitsyn 2d85cc86be fix: tune sidebar and context panel sizing
Keep the left sidebar open when the context panel opens
Reduce right sidebar and context panel default widths
Collapse only the sync button label at medium widths
2026-05-22 01:33:11 +03:00
Bohdan Triapitsyn 6fd3afd25a feat: replace prompt templates with snippets
Replace the prompt-template workflow with snippet support that is compatible with opencode snippet conventions. Snippets are now stored and loaded from global and project snippet directories, including legacy pluralized paths, with frontmatter metadata for aliases and descriptions. Snippet expansion supports recursive references plus prepend and append sections, while inject sections are treated as unsupported no-ops so OpenChamber remains compatible without requiring an external plugin.

Add the snippets settings experience and remove the old prompt-template settings surface. The new settings page and sidebar support creating, editing, deleting, selecting, and describing snippets, with localized copy across every supported locale. The settings navigation now exposes Snippets with a dedicated icon and metadata.

Wire snippets into all prompt-entry surfaces that need them. Chat, multi-run groups, and scheduled task prompts now offer hash-trigger snippet autocomplete and expand snippets before sending work to OpenCode. Chat also uses an adaptive compact placeholder on mobile or narrow composer widths so helper trigger guidance stays readable in constrained layouts.

Keep multi-run aligned with grouped prompts. Multi-run sessions now use a shared title builder that handles both legacy titles and the newer g1, g2 prompt-group title format. Fusion parsing now recognizes grouped multi-run titles, scopes fusion sources to the same prompt group, and creates fusion sessions under the matching group so outputs from different prompts are not mixed accidentally.

Harden the icon sprite pipeline. The sprite generator now discovers icon names used through typed icon maps, JSX icon props, IconName returns, and generated-value flows without scanning unrelated string literals or the generated sprite itself. The generated sprite is strictly typed so invalid icon names are caught by type checking, and existing invalid or unsafe icon references were cleaned up across settings, provider, Git identity, scheduled task, voice, header, and sidebar surfaces.

Update backend configuration routes and documentation for snippets. The OpenCode config route layer now exposes snippet CRUD and expansion endpoints, accepts JSON bodies for snippet writes, and removes the old prompt-template provider. Scheduled task runtime expansion now uses snippets before dispatching messages.

Add regression coverage for snippet storage and expansion, config-route JSON handling, and multi-run title parsing. Validated with full type checking, full linting, targeted multi-run title tests, and targeted OpenCode snippet/config route tests.
2026-05-21 20:00:35 +03:00
Bohdan Triapitsyn 7d98f388c0 ci: cut over desktop releases to Electron
Repackages Electron app for legacy Tauri updater migration
Stops release and manual DMG workflows from building Tauri
Documents transition flow and cleanup timing
2026-05-21 16:37:06 +03:00
Tom Rochette 6cc1afc963 Multi-run with configurable prompt templates (#1111)
* Multi-run with configurable prompt templates

* Fixes

* Fix handleDuplicate fire-and-forget: await createTemplate and handle failure

* Add Polish translations for prompt template and multirun group keys

* fix: migrate remaining Remix icons to Icon component in MultiRunLauncher

---------

Signed-off-by: Tom Rochette <roctom@gmail.com>
2026-05-21 16:35:42 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 8dac0f73c0 fix(ui): revoke voice preview blob urls (#1342)
* fix(ui): revoke voice preview blob urls

* fix(ui): reset disposed preview audio

---------

Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-21 15:51:49 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 6fbdb22c7e fix(ui): avoid file search cache key collisions (#1343)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-21 15:51:09 +03:00
Bohdan Triapitsyn 51c8d52ab5 perf(ui): improve VS Code chat session switching
Improve chat session switching and history pagination, with most of the aggressive limits scoped to the VS Code webview where the freezes were observed.

Session history loading and pagination:

- Reduce the VS Code message page size to 30 records so switching sessions does not immediately hydrate large histories into the webview.

- Keep manual Load older messages in VS Code fixed at 30 records per request instead of growing the request size over time.

- Add a bounded VS Code initial-tail expansion path from 30 to 50, 80, and 120 records only when the initial page has no user-message turn boundary, preventing large final turns from rendering as an empty chat.

- Lower the normal web message page size from 200 to 150 for a mild shared optimization without adopting the aggressive VS Code limits.

- Make session pagination metadata reactive per session so ChatContainer receives cursor updates from materialization and reconnect paths without requiring a switch away and back.

- Write pagination metadata before publishing newly materialized messages so the first render sees the correct has-more state.

- Store cursor information from direct materialization and reconnect message fetches in the shared session prefetch metadata cache.

VS Code cache and memory pressure reductions:

- Use a shared per-directory session recency map so cache eviction is based on app-level recency instead of whichever useSync instance happened to run.

- Limit VS Code warm session cache retention to 4 sessions and evict heavy inactive message caches after switching away from a large session.

- Disable sidebar session prefetch in VS Code because warming extra sessions was increasing webview memory and GC pressure during navigation.

- Remove dropdown background message prefetch so opening the switcher does not start additional session materialization work.

- Drop cached session-message-record snapshots when evicting session data so stale derived records do not remain after the raw session cache is cleared.

- Add bounded LRU caching for session message record snapshots, with much smaller VS Code limits and a VS Code cap that avoids caching snapshots above 30 messages.

- Bound the turn-window model cache in VS Code and avoid caching turn models for sessions above the VS Code message-page size.

Chat render-path reductions:

- Reuse ChatContainer's already-materialized message records in plan detection instead of adding a second active-session message subscription.

- Add a no-op guard when marking session plan availability so repeated detections do not create new Map references and fan out renders.

- Add no-op guards for session switcher and dropdown open state updates to avoid unnecessary store updates and renders.

- Convert several session-specific hooks to useSyncExternalStore with empty-session no-subscribe behavior so empty IDs do not subscribe to broad store updates.

- Remount the chat viewport when the current session changes, isolating per-session viewport and list state.

- Change the virtualized message-list fallback to render only a tail window when the virtualizer has not produced rows yet, instead of rendering an entire large history.

VS Code layout and header improvements:

- Remove the broad useSessions subscription from the VS Code layout header path and subscribe only to the active session title and initial-session existence.

- Unmount the compact VS Code session sidebar when the user is in chat view instead of keeping the hidden session list mounted and subscribed.

- Compute the latest assistant model and latest context-token usage in a single reverse scan of current-session messages instead of scanning the same list twice.

- Remove switcher git-status warmup work so the switcher reads already-loaded branch labels without starting extra background git status requests.

Markdown and file-reference safeguards:

- Skip expensive syntax highlighting for very large code blocks, with a 200-line cap in VS Code and a softer 1200-line cap in web.

- Add an LRU cap to file-reference stat lookups so the cache cannot grow without bound across many rendered messages.

- Limit the number of file references annotated per render to 40 in VS Code and 200 in web to prevent large assistant outputs from spawning too many stat checks.

- Clear file-link annotations when file-reference mode is disabled so stale attributes and handlers do not remain on previously annotated nodes.

Assistant-message action and preview reductions:

- Skip preview URL scanning on VS Code, mobile, and mini-chat surfaces so assistant text and tool output are not scanned where the preview action is unavailable.

- Skip Save-as-Plan project lookup on VS Code, mini-chat, and mobile surfaces.

- Hide Save-as-Plan and Start MultiRun assistant-message actions on VS Code, mini-chat, and mobile surfaces.

- Resolve the current session directory on demand for assistant actions instead of subscribing each assistant message to the full session list.

Tool and task rendering optimizations:

- Prefer finalized task metadata summaries without fetching child-session messages when the summary is already present.

- Avoid polling or final-fetching task child sessions once a final metadata summary is available.

- Use VS Code-specific task child fetch limits of 30 records for initial, active, and idle fetches.

- Parse diff stats by scanning patch text line-by-line instead of splitting large patches into arrays.

- Count write-tool lines by scanning content instead of allocating a split array for large files.

- Avoid trimming large patch strings just to test whether they contain content.

- Memoize diff and write statistics so unchanged tool parts do not recalculate them on every render.

VS Code bridge improvements:

- Return JSON and text proxy responses through the VS Code bridge as bodyText instead of base64 so the webview avoids synchronous base64 decoding for common API responses.

- Keep binary responses on the base64 path while making bodyBase64 optional in the bridge contract.

- Strip content-length, content-encoding, and transfer-encoding headers from proxied responses because the bridge reconstructs the Response body.

Validation:

- bun run type-check

- bun run lint

- bun run vscode:build
2026-05-21 15:45:44 +03:00
Bohdan Triapitsyn 80cf598d9f fix(ui): preserve reasoning collapse animation 2026-05-21 15:45:44 +03:00
Bohdan Triapitsyn 3f4259379d fix(ui): prevent completed reasoning collapse animation 2026-05-21 15:45:44 +03:00
Bohdan Triapitsyn 40210917c2 fix(ui): keep completed reasoning collapsed 2026-05-21 15:45:44 +03:00
Bohdan Triapitsyn b523dcae91 fix: improve unknown tool names
Format underscores and hyphens as spaces in fallback tool labels
Make third-party tool names easier to read
2026-05-21 15:45:44 +03:00